From b8577029d1d37b798907f0418ddb1445e13c3c44 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Wed, 10 May 2006 08:02:49 +0000 Subject: --- src/charon/Architecture.txt | 56 + src/charon/Known-bugs.txt | 7 + src/charon/Makefile.charon | 25 + src/charon/Todo-list.txt | 57 + src/charon/charon.kdevelop | 105 -- src/charon/charon/Architecture.txt | 56 - src/charon/charon/Known-bugs.txt | 7 - src/charon/charon/Makefile.charon | 25 - src/charon/charon/Todo-list.txt | 57 - src/charon/charon/config/Makefile.config | 32 - src/charon/charon/config/configuration.c | 112 -- src/charon/charon/config/configuration.h | 89 -- .../charon/config/connections/Makefile.connections | 24 - src/charon/charon/config/connections/connection.c | 367 ------ src/charon/charon/config/connections/connection.h | 283 ----- .../charon/config/connections/connection_store.h | 112 -- .../config/connections/local_connection_store.c | 228 ---- .../config/connections/local_connection_store.h | 63 - .../charon/config/credentials/Makefile.credentials | 20 - .../charon/config/credentials/credential_store.h | 91 -- .../config/credentials/local_credential_store.c | 381 ------ .../config/credentials/local_credential_store.h | 85 -- .../charon/config/policies/Makefile.policies | 24 - .../charon/config/policies/local_policy_store.c | 136 --- .../charon/config/policies/local_policy_store.h | 60 - src/charon/charon/config/policies/policy.c | 397 ------- src/charon/charon/config/policies/policy.h | 249 ---- src/charon/charon/config/policies/policy_store.h | 76 -- src/charon/charon/config/proposal.c | 642 ---------- src/charon/charon/config/proposal.h | 269 ----- src/charon/charon/config/traffic_selector.c | 425 ------- src/charon/charon/config/traffic_selector.h | 258 ---- src/charon/charon/daemon.c | 390 ------ src/charon/charon/daemon.h | 337 ------ src/charon/charon/encoding/Makefile.encoding | 30 - src/charon/charon/encoding/generator.c | 1077 ----------------- src/charon/charon/encoding/generator.h | 101 -- src/charon/charon/encoding/message.c | 1251 -------------------- src/charon/charon/encoding/message.h | 367 ------ src/charon/charon/encoding/parser.c | 1065 ----------------- src/charon/charon/encoding/parser.h | 95 -- .../charon/encoding/payloads/Makefile.payloads | 108 -- src/charon/charon/encoding/payloads/auth_payload.c | 265 ----- src/charon/charon/encoding/payloads/auth_payload.h | 122 -- src/charon/charon/encoding/payloads/cert_payload.c | 279 ----- src/charon/charon/encoding/payloads/cert_payload.h | 155 --- .../charon/encoding/payloads/certreq_payload.c | 259 ---- .../charon/encoding/payloads/certreq_payload.h | 125 -- .../encoding/payloads/configuration_attribute.c | 282 ----- .../encoding/payloads/configuration_attribute.h | 149 --- src/charon/charon/encoding/payloads/cp_payload.c | 305 ----- src/charon/charon/encoding/payloads/cp_payload.h | 138 --- .../charon/encoding/payloads/delete_payload.c | 322 ----- .../charon/encoding/payloads/delete_payload.h | 156 --- src/charon/charon/encoding/payloads/eap_payload.c | 227 ---- src/charon/charon/encoding/payloads/eap_payload.h | 105 -- src/charon/charon/encoding/payloads/encodings.c | 68 -- src/charon/charon/encoding/payloads/encodings.h | 540 --------- .../charon/encoding/payloads/encryption_payload.c | 702 ----------- .../charon/encoding/payloads/encryption_payload.h | 196 --- src/charon/charon/encoding/payloads/id_payload.c | 320 ----- src/charon/charon/encoding/payloads/id_payload.h | 172 --- src/charon/charon/encoding/payloads/ike_header.c | 408 ------- src/charon/charon/encoding/payloads/ike_header.h | 261 ---- src/charon/charon/encoding/payloads/ke_payload.c | 276 ----- src/charon/charon/encoding/payloads/ke_payload.h | 110 -- .../charon/encoding/payloads/nonce_payload.c | 241 ---- .../charon/encoding/payloads/nonce_payload.h | 89 -- .../charon/encoding/payloads/notify_payload.c | 441 ------- .../charon/encoding/payloads/notify_payload.h | 200 ---- src/charon/charon/encoding/payloads/payload.c | 131 -- src/charon/charon/encoding/payloads/payload.h | 279 ----- .../encoding/payloads/proposal_substructure.c | 629 ---------- .../encoding/payloads/proposal_substructure.h | 231 ---- src/charon/charon/encoding/payloads/sa_payload.c | 390 ------ src/charon/charon/encoding/payloads/sa_payload.h | 140 --- .../payloads/traffic_selector_substructure.c | 374 ------ .../payloads/traffic_selector_substructure.h | 171 --- .../charon/encoding/payloads/transform_attribute.c | 333 ------ .../charon/encoding/payloads/transform_attribute.h | 154 --- .../encoding/payloads/transform_substructure.c | 485 -------- .../encoding/payloads/transform_substructure.h | 198 ---- src/charon/charon/encoding/payloads/ts_payload.c | 365 ------ src/charon/charon/encoding/payloads/ts_payload.h | 152 --- .../charon/encoding/payloads/unknown_payload.c | 207 ---- .../charon/encoding/payloads/unknown_payload.h | 95 -- .../charon/encoding/payloads/vendor_id_payload.c | 227 ---- .../charon/encoding/payloads/vendor_id_payload.h | 103 -- src/charon/charon/network/Makefile.network | 24 - src/charon/charon/network/packet.c | 189 --- src/charon/charon/network/packet.h | 135 --- src/charon/charon/network/socket.c | 456 ------- src/charon/charon/network/socket.h | 128 -- src/charon/charon/queues/Makefile.queues | 30 - src/charon/charon/queues/event_queue.c | 349 ------ src/charon/charon/queues/event_queue.h | 117 -- src/charon/charon/queues/job_queue.c | 153 --- src/charon/charon/queues/job_queue.h | 99 -- src/charon/charon/queues/jobs/Makefile.jobs | 40 - .../queues/jobs/delete_established_ike_sa_job.c | 90 -- .../queues/jobs/delete_established_ike_sa_job.h | 78 -- .../queues/jobs/delete_half_open_ike_sa_job.c | 90 -- .../queues/jobs/delete_half_open_ike_sa_job.h | 79 -- .../charon/queues/jobs/incoming_packet_job.c | 102 -- .../charon/queues/jobs/incoming_packet_job.h | 78 -- .../charon/queues/jobs/initiate_ike_sa_job.c | 101 -- .../charon/queues/jobs/initiate_ike_sa_job.h | 75 -- src/charon/charon/queues/jobs/job.c | 34 - src/charon/charon/queues/jobs/job.h | 120 -- .../charon/queues/jobs/retransmit_request_job.c | 132 --- .../charon/queues/jobs/retransmit_request_job.h | 105 -- src/charon/charon/queues/send_queue.c | 153 --- src/charon/charon/queues/send_queue.h | 100 -- src/charon/charon/sa/Makefile.sa | 37 - src/charon/charon/sa/authenticator.c | 405 ------- src/charon/charon/sa/authenticator.h | 138 --- src/charon/charon/sa/child_sa.c | 590 --------- src/charon/charon/sa/child_sa.h | 149 --- src/charon/charon/sa/ike_sa.c | 1199 ------------------- src/charon/charon/sa/ike_sa.h | 462 -------- src/charon/charon/sa/ike_sa_id.c | 185 --- src/charon/charon/sa/ike_sa_id.h | 146 --- src/charon/charon/sa/ike_sa_manager.c | 843 ------------- src/charon/charon/sa/ike_sa_manager.h | 194 --- src/charon/charon/sa/states/Makefile.states | 43 - src/charon/charon/sa/states/ike_auth_requested.c | 671 ----------- src/charon/charon/sa/states/ike_auth_requested.h | 72 -- src/charon/charon/sa/states/ike_sa_established.c | 239 ---- src/charon/charon/sa/states/ike_sa_established.h | 64 - .../charon/sa/states/ike_sa_init_requested.c | 798 ------------- .../charon/sa/states/ike_sa_init_requested.h | 68 -- .../charon/sa/states/ike_sa_init_responded.c | 695 ----------- .../charon/sa/states/ike_sa_init_responded.h | 73 -- src/charon/charon/sa/states/initiator_init.c | 360 ------ src/charon/charon/sa/states/initiator_init.h | 84 -- src/charon/charon/sa/states/responder_init.c | 568 --------- src/charon/charon/sa/states/responder_init.h | 68 -- src/charon/charon/sa/states/state.c | 37 - src/charon/charon/sa/states/state.h | 166 --- src/charon/charon/threads/Makefile.threads | 39 - src/charon/charon/threads/kernel_interface.c | 729 ------------ src/charon/charon/threads/kernel_interface.h | 185 --- src/charon/charon/threads/receiver.c | 128 -- src/charon/charon/threads/receiver.h | 67 -- src/charon/charon/threads/scheduler.c | 124 -- src/charon/charon/threads/scheduler.h | 67 -- src/charon/charon/threads/sender.c | 126 -- src/charon/charon/threads/sender.h | 63 - src/charon/charon/threads/stroke_interface.c | 646 ---------- src/charon/charon/threads/stroke_interface.h | 76 -- src/charon/charon/threads/thread_pool.c | 623 ---------- src/charon/charon/threads/thread_pool.h | 78 -- src/charon/config/Makefile.config | 32 + src/charon/config/configuration.c | 112 ++ src/charon/config/configuration.h | 89 ++ src/charon/config/connections/Makefile.connections | 24 + src/charon/config/connections/connection.c | 367 ++++++ src/charon/config/connections/connection.h | 283 +++++ src/charon/config/connections/connection_store.h | 112 ++ .../config/connections/local_connection_store.c | 228 ++++ .../config/connections/local_connection_store.h | 63 + src/charon/config/credentials/Makefile.credentials | 20 + src/charon/config/credentials/credential_store.h | 91 ++ .../config/credentials/local_credential_store.c | 381 ++++++ .../config/credentials/local_credential_store.h | 85 ++ src/charon/config/policies/Makefile.policies | 24 + src/charon/config/policies/local_policy_store.c | 136 +++ src/charon/config/policies/local_policy_store.h | 60 + src/charon/config/policies/policy.c | 397 +++++++ src/charon/config/policies/policy.h | 249 ++++ src/charon/config/policies/policy_store.h | 76 ++ src/charon/config/proposal.c | 642 ++++++++++ src/charon/config/proposal.h | 269 +++++ src/charon/config/traffic_selector.c | 425 +++++++ src/charon/config/traffic_selector.h | 258 ++++ src/charon/daemon.c | 390 ++++++ src/charon/daemon.h | 337 ++++++ src/charon/encoding/Makefile.encoding | 30 + src/charon/encoding/generator.c | 1077 +++++++++++++++++ src/charon/encoding/generator.h | 101 ++ src/charon/encoding/message.c | 1251 ++++++++++++++++++++ src/charon/encoding/message.h | 367 ++++++ src/charon/encoding/parser.c | 1065 +++++++++++++++++ src/charon/encoding/parser.h | 95 ++ src/charon/encoding/payloads/Makefile.payloads | 108 ++ src/charon/encoding/payloads/auth_payload.c | 265 +++++ src/charon/encoding/payloads/auth_payload.h | 122 ++ src/charon/encoding/payloads/cert_payload.c | 279 +++++ src/charon/encoding/payloads/cert_payload.h | 155 +++ src/charon/encoding/payloads/certreq_payload.c | 259 ++++ src/charon/encoding/payloads/certreq_payload.h | 125 ++ .../encoding/payloads/configuration_attribute.c | 282 +++++ .../encoding/payloads/configuration_attribute.h | 149 +++ src/charon/encoding/payloads/cp_payload.c | 305 +++++ src/charon/encoding/payloads/cp_payload.h | 138 +++ src/charon/encoding/payloads/delete_payload.c | 322 +++++ src/charon/encoding/payloads/delete_payload.h | 156 +++ src/charon/encoding/payloads/eap_payload.c | 227 ++++ src/charon/encoding/payloads/eap_payload.h | 105 ++ src/charon/encoding/payloads/encodings.c | 68 ++ src/charon/encoding/payloads/encodings.h | 540 +++++++++ src/charon/encoding/payloads/encryption_payload.c | 702 +++++++++++ src/charon/encoding/payloads/encryption_payload.h | 196 +++ src/charon/encoding/payloads/id_payload.c | 320 +++++ src/charon/encoding/payloads/id_payload.h | 172 +++ src/charon/encoding/payloads/ike_header.c | 408 +++++++ src/charon/encoding/payloads/ike_header.h | 261 ++++ src/charon/encoding/payloads/ke_payload.c | 276 +++++ src/charon/encoding/payloads/ke_payload.h | 110 ++ src/charon/encoding/payloads/nonce_payload.c | 241 ++++ src/charon/encoding/payloads/nonce_payload.h | 89 ++ src/charon/encoding/payloads/notify_payload.c | 441 +++++++ src/charon/encoding/payloads/notify_payload.h | 200 ++++ src/charon/encoding/payloads/payload.c | 131 ++ src/charon/encoding/payloads/payload.h | 279 +++++ .../encoding/payloads/proposal_substructure.c | 629 ++++++++++ .../encoding/payloads/proposal_substructure.h | 231 ++++ src/charon/encoding/payloads/sa_payload.c | 390 ++++++ src/charon/encoding/payloads/sa_payload.h | 140 +++ .../payloads/traffic_selector_substructure.c | 374 ++++++ .../payloads/traffic_selector_substructure.h | 171 +++ src/charon/encoding/payloads/transform_attribute.c | 333 ++++++ src/charon/encoding/payloads/transform_attribute.h | 154 +++ .../encoding/payloads/transform_substructure.c | 485 ++++++++ .../encoding/payloads/transform_substructure.h | 198 ++++ src/charon/encoding/payloads/ts_payload.c | 365 ++++++ src/charon/encoding/payloads/ts_payload.h | 152 +++ src/charon/encoding/payloads/unknown_payload.c | 207 ++++ src/charon/encoding/payloads/unknown_payload.h | 95 ++ src/charon/encoding/payloads/vendor_id_payload.c | 227 ++++ src/charon/encoding/payloads/vendor_id_payload.h | 103 ++ src/charon/network/Makefile.network | 24 + src/charon/network/packet.c | 189 +++ src/charon/network/packet.h | 135 +++ src/charon/network/socket.c | 456 +++++++ src/charon/network/socket.h | 128 ++ src/charon/queues/Makefile.queues | 30 + src/charon/queues/event_queue.c | 349 ++++++ src/charon/queues/event_queue.h | 117 ++ src/charon/queues/job_queue.c | 153 +++ src/charon/queues/job_queue.h | 99 ++ src/charon/queues/jobs/Makefile.jobs | 40 + .../queues/jobs/delete_established_ike_sa_job.c | 90 ++ .../queues/jobs/delete_established_ike_sa_job.h | 78 ++ .../queues/jobs/delete_half_open_ike_sa_job.c | 90 ++ .../queues/jobs/delete_half_open_ike_sa_job.h | 79 ++ src/charon/queues/jobs/incoming_packet_job.c | 102 ++ src/charon/queues/jobs/incoming_packet_job.h | 78 ++ src/charon/queues/jobs/initiate_ike_sa_job.c | 101 ++ src/charon/queues/jobs/initiate_ike_sa_job.h | 75 ++ src/charon/queues/jobs/job.c | 34 + src/charon/queues/jobs/job.h | 120 ++ src/charon/queues/jobs/retransmit_request_job.c | 132 +++ src/charon/queues/jobs/retransmit_request_job.h | 105 ++ src/charon/queues/send_queue.c | 153 +++ src/charon/queues/send_queue.h | 100 ++ src/charon/sa/Makefile.sa | 37 + src/charon/sa/authenticator.c | 405 +++++++ src/charon/sa/authenticator.h | 138 +++ src/charon/sa/child_sa.c | 590 +++++++++ src/charon/sa/child_sa.h | 149 +++ src/charon/sa/ike_sa.c | 1199 +++++++++++++++++++ src/charon/sa/ike_sa.h | 462 ++++++++ src/charon/sa/ike_sa_id.c | 185 +++ src/charon/sa/ike_sa_id.h | 146 +++ src/charon/sa/ike_sa_manager.c | 843 +++++++++++++ src/charon/sa/ike_sa_manager.h | 194 +++ src/charon/sa/states/Makefile.states | 43 + src/charon/sa/states/ike_auth_requested.c | 671 +++++++++++ src/charon/sa/states/ike_auth_requested.h | 72 ++ src/charon/sa/states/ike_sa_established.c | 239 ++++ src/charon/sa/states/ike_sa_established.h | 64 + src/charon/sa/states/ike_sa_init_requested.c | 798 +++++++++++++ src/charon/sa/states/ike_sa_init_requested.h | 68 ++ src/charon/sa/states/ike_sa_init_responded.c | 695 +++++++++++ src/charon/sa/states/ike_sa_init_responded.h | 73 ++ src/charon/sa/states/initiator_init.c | 360 ++++++ src/charon/sa/states/initiator_init.h | 84 ++ src/charon/sa/states/responder_init.c | 568 +++++++++ src/charon/sa/states/responder_init.h | 68 ++ src/charon/sa/states/state.c | 37 + src/charon/sa/states/state.h | 166 +++ src/charon/threads/Makefile.threads | 39 + src/charon/threads/kernel_interface.c | 729 ++++++++++++ src/charon/threads/kernel_interface.h | 185 +++ src/charon/threads/receiver.c | 128 ++ src/charon/threads/receiver.h | 67 ++ src/charon/threads/scheduler.c | 124 ++ src/charon/threads/scheduler.h | 67 ++ src/charon/threads/sender.c | 126 ++ src/charon/threads/sender.h | 63 + src/charon/threads/stroke_interface.c | 646 ++++++++++ src/charon/threads/stroke_interface.h | 76 ++ src/charon/threads/thread_pool.c | 623 ++++++++++ src/charon/threads/thread_pool.h | 78 ++ 295 files changed, 35328 insertions(+), 35433 deletions(-) create mode 100644 src/charon/Architecture.txt create mode 100644 src/charon/Known-bugs.txt create mode 100644 src/charon/Makefile.charon create mode 100644 src/charon/Todo-list.txt delete mode 100644 src/charon/charon.kdevelop delete mode 100644 src/charon/charon/Architecture.txt delete mode 100644 src/charon/charon/Known-bugs.txt delete mode 100644 src/charon/charon/Makefile.charon delete mode 100644 src/charon/charon/Todo-list.txt delete mode 100644 src/charon/charon/config/Makefile.config delete mode 100755 src/charon/charon/config/configuration.c delete mode 100755 src/charon/charon/config/configuration.h delete mode 100644 src/charon/charon/config/connections/Makefile.connections delete mode 100644 src/charon/charon/config/connections/connection.c delete mode 100644 src/charon/charon/config/connections/connection.h delete mode 100755 src/charon/charon/config/connections/connection_store.h delete mode 100644 src/charon/charon/config/connections/local_connection_store.c delete mode 100644 src/charon/charon/config/connections/local_connection_store.h delete mode 100644 src/charon/charon/config/credentials/Makefile.credentials delete mode 100755 src/charon/charon/config/credentials/credential_store.h delete mode 100644 src/charon/charon/config/credentials/local_credential_store.c delete mode 100644 src/charon/charon/config/credentials/local_credential_store.h delete mode 100644 src/charon/charon/config/policies/Makefile.policies delete mode 100644 src/charon/charon/config/policies/local_policy_store.c delete mode 100644 src/charon/charon/config/policies/local_policy_store.h delete mode 100644 src/charon/charon/config/policies/policy.c delete mode 100644 src/charon/charon/config/policies/policy.h delete mode 100755 src/charon/charon/config/policies/policy_store.h delete mode 100644 src/charon/charon/config/proposal.c delete mode 100644 src/charon/charon/config/proposal.h delete mode 100644 src/charon/charon/config/traffic_selector.c delete mode 100644 src/charon/charon/config/traffic_selector.h delete mode 100644 src/charon/charon/daemon.c delete mode 100644 src/charon/charon/daemon.h delete mode 100644 src/charon/charon/encoding/Makefile.encoding delete mode 100644 src/charon/charon/encoding/generator.c delete mode 100644 src/charon/charon/encoding/generator.h delete mode 100644 src/charon/charon/encoding/message.c delete mode 100644 src/charon/charon/encoding/message.h delete mode 100644 src/charon/charon/encoding/parser.c delete mode 100644 src/charon/charon/encoding/parser.h delete mode 100644 src/charon/charon/encoding/payloads/Makefile.payloads delete mode 100644 src/charon/charon/encoding/payloads/auth_payload.c delete mode 100644 src/charon/charon/encoding/payloads/auth_payload.h delete mode 100644 src/charon/charon/encoding/payloads/cert_payload.c delete mode 100644 src/charon/charon/encoding/payloads/cert_payload.h delete mode 100644 src/charon/charon/encoding/payloads/certreq_payload.c delete mode 100644 src/charon/charon/encoding/payloads/certreq_payload.h delete mode 100644 src/charon/charon/encoding/payloads/configuration_attribute.c delete mode 100644 src/charon/charon/encoding/payloads/configuration_attribute.h delete mode 100644 src/charon/charon/encoding/payloads/cp_payload.c delete mode 100644 src/charon/charon/encoding/payloads/cp_payload.h delete mode 100644 src/charon/charon/encoding/payloads/delete_payload.c delete mode 100644 src/charon/charon/encoding/payloads/delete_payload.h delete mode 100644 src/charon/charon/encoding/payloads/eap_payload.c delete mode 100644 src/charon/charon/encoding/payloads/eap_payload.h delete mode 100644 src/charon/charon/encoding/payloads/encodings.c delete mode 100644 src/charon/charon/encoding/payloads/encodings.h delete mode 100644 src/charon/charon/encoding/payloads/encryption_payload.c delete mode 100644 src/charon/charon/encoding/payloads/encryption_payload.h delete mode 100644 src/charon/charon/encoding/payloads/id_payload.c delete mode 100644 src/charon/charon/encoding/payloads/id_payload.h delete mode 100644 src/charon/charon/encoding/payloads/ike_header.c delete mode 100644 src/charon/charon/encoding/payloads/ike_header.h delete mode 100644 src/charon/charon/encoding/payloads/ke_payload.c delete mode 100644 src/charon/charon/encoding/payloads/ke_payload.h delete mode 100644 src/charon/charon/encoding/payloads/nonce_payload.c delete mode 100644 src/charon/charon/encoding/payloads/nonce_payload.h delete mode 100644 src/charon/charon/encoding/payloads/notify_payload.c delete mode 100644 src/charon/charon/encoding/payloads/notify_payload.h delete mode 100644 src/charon/charon/encoding/payloads/payload.c delete mode 100644 src/charon/charon/encoding/payloads/payload.h delete mode 100644 src/charon/charon/encoding/payloads/proposal_substructure.c delete mode 100644 src/charon/charon/encoding/payloads/proposal_substructure.h delete mode 100644 src/charon/charon/encoding/payloads/sa_payload.c delete mode 100644 src/charon/charon/encoding/payloads/sa_payload.h delete mode 100644 src/charon/charon/encoding/payloads/traffic_selector_substructure.c delete mode 100644 src/charon/charon/encoding/payloads/traffic_selector_substructure.h delete mode 100644 src/charon/charon/encoding/payloads/transform_attribute.c delete mode 100644 src/charon/charon/encoding/payloads/transform_attribute.h delete mode 100644 src/charon/charon/encoding/payloads/transform_substructure.c delete mode 100644 src/charon/charon/encoding/payloads/transform_substructure.h delete mode 100644 src/charon/charon/encoding/payloads/ts_payload.c delete mode 100644 src/charon/charon/encoding/payloads/ts_payload.h delete mode 100644 src/charon/charon/encoding/payloads/unknown_payload.c delete mode 100644 src/charon/charon/encoding/payloads/unknown_payload.h delete mode 100644 src/charon/charon/encoding/payloads/vendor_id_payload.c delete mode 100644 src/charon/charon/encoding/payloads/vendor_id_payload.h delete mode 100644 src/charon/charon/network/Makefile.network delete mode 100644 src/charon/charon/network/packet.c delete mode 100644 src/charon/charon/network/packet.h delete mode 100644 src/charon/charon/network/socket.c delete mode 100644 src/charon/charon/network/socket.h delete mode 100644 src/charon/charon/queues/Makefile.queues delete mode 100644 src/charon/charon/queues/event_queue.c delete mode 100644 src/charon/charon/queues/event_queue.h delete mode 100644 src/charon/charon/queues/job_queue.c delete mode 100644 src/charon/charon/queues/job_queue.h delete mode 100644 src/charon/charon/queues/jobs/Makefile.jobs delete mode 100644 src/charon/charon/queues/jobs/delete_established_ike_sa_job.c delete mode 100644 src/charon/charon/queues/jobs/delete_established_ike_sa_job.h delete mode 100644 src/charon/charon/queues/jobs/delete_half_open_ike_sa_job.c delete mode 100644 src/charon/charon/queues/jobs/delete_half_open_ike_sa_job.h delete mode 100644 src/charon/charon/queues/jobs/incoming_packet_job.c delete mode 100644 src/charon/charon/queues/jobs/incoming_packet_job.h delete mode 100644 src/charon/charon/queues/jobs/initiate_ike_sa_job.c delete mode 100644 src/charon/charon/queues/jobs/initiate_ike_sa_job.h delete mode 100644 src/charon/charon/queues/jobs/job.c delete mode 100644 src/charon/charon/queues/jobs/job.h delete mode 100644 src/charon/charon/queues/jobs/retransmit_request_job.c delete mode 100644 src/charon/charon/queues/jobs/retransmit_request_job.h delete mode 100644 src/charon/charon/queues/send_queue.c delete mode 100644 src/charon/charon/queues/send_queue.h delete mode 100644 src/charon/charon/sa/Makefile.sa delete mode 100644 src/charon/charon/sa/authenticator.c delete mode 100644 src/charon/charon/sa/authenticator.h delete mode 100644 src/charon/charon/sa/child_sa.c delete mode 100644 src/charon/charon/sa/child_sa.h delete mode 100644 src/charon/charon/sa/ike_sa.c delete mode 100644 src/charon/charon/sa/ike_sa.h delete mode 100644 src/charon/charon/sa/ike_sa_id.c delete mode 100644 src/charon/charon/sa/ike_sa_id.h delete mode 100644 src/charon/charon/sa/ike_sa_manager.c delete mode 100644 src/charon/charon/sa/ike_sa_manager.h delete mode 100644 src/charon/charon/sa/states/Makefile.states delete mode 100644 src/charon/charon/sa/states/ike_auth_requested.c delete mode 100644 src/charon/charon/sa/states/ike_auth_requested.h delete mode 100644 src/charon/charon/sa/states/ike_sa_established.c delete mode 100644 src/charon/charon/sa/states/ike_sa_established.h delete mode 100644 src/charon/charon/sa/states/ike_sa_init_requested.c delete mode 100644 src/charon/charon/sa/states/ike_sa_init_requested.h delete mode 100644 src/charon/charon/sa/states/ike_sa_init_responded.c delete mode 100644 src/charon/charon/sa/states/ike_sa_init_responded.h delete mode 100644 src/charon/charon/sa/states/initiator_init.c delete mode 100644 src/charon/charon/sa/states/initiator_init.h delete mode 100644 src/charon/charon/sa/states/responder_init.c delete mode 100644 src/charon/charon/sa/states/responder_init.h delete mode 100644 src/charon/charon/sa/states/state.c delete mode 100644 src/charon/charon/sa/states/state.h delete mode 100644 src/charon/charon/threads/Makefile.threads delete mode 100644 src/charon/charon/threads/kernel_interface.c delete mode 100644 src/charon/charon/threads/kernel_interface.h delete mode 100644 src/charon/charon/threads/receiver.c delete mode 100644 src/charon/charon/threads/receiver.h delete mode 100644 src/charon/charon/threads/scheduler.c delete mode 100644 src/charon/charon/threads/scheduler.h delete mode 100644 src/charon/charon/threads/sender.c delete mode 100644 src/charon/charon/threads/sender.h delete mode 100755 src/charon/charon/threads/stroke_interface.c delete mode 100644 src/charon/charon/threads/stroke_interface.h delete mode 100644 src/charon/charon/threads/thread_pool.c delete mode 100644 src/charon/charon/threads/thread_pool.h create mode 100644 src/charon/config/Makefile.config create mode 100755 src/charon/config/configuration.c create mode 100755 src/charon/config/configuration.h create mode 100644 src/charon/config/connections/Makefile.connections create mode 100644 src/charon/config/connections/connection.c create mode 100644 src/charon/config/connections/connection.h create mode 100755 src/charon/config/connections/connection_store.h create mode 100644 src/charon/config/connections/local_connection_store.c create mode 100644 src/charon/config/connections/local_connection_store.h create mode 100644 src/charon/config/credentials/Makefile.credentials create mode 100755 src/charon/config/credentials/credential_store.h create mode 100644 src/charon/config/credentials/local_credential_store.c create mode 100644 src/charon/config/credentials/local_credential_store.h create mode 100644 src/charon/config/policies/Makefile.policies create mode 100644 src/charon/config/policies/local_policy_store.c create mode 100644 src/charon/config/policies/local_policy_store.h create mode 100644 src/charon/config/policies/policy.c create mode 100644 src/charon/config/policies/policy.h create mode 100755 src/charon/config/policies/policy_store.h create mode 100644 src/charon/config/proposal.c create mode 100644 src/charon/config/proposal.h create mode 100644 src/charon/config/traffic_selector.c create mode 100644 src/charon/config/traffic_selector.h create mode 100644 src/charon/daemon.c create mode 100644 src/charon/daemon.h create mode 100644 src/charon/encoding/Makefile.encoding create mode 100644 src/charon/encoding/generator.c create mode 100644 src/charon/encoding/generator.h create mode 100644 src/charon/encoding/message.c create mode 100644 src/charon/encoding/message.h create mode 100644 src/charon/encoding/parser.c create mode 100644 src/charon/encoding/parser.h create mode 100644 src/charon/encoding/payloads/Makefile.payloads create mode 100644 src/charon/encoding/payloads/auth_payload.c create mode 100644 src/charon/encoding/payloads/auth_payload.h create mode 100644 src/charon/encoding/payloads/cert_payload.c create mode 100644 src/charon/encoding/payloads/cert_payload.h create mode 100644 src/charon/encoding/payloads/certreq_payload.c create mode 100644 src/charon/encoding/payloads/certreq_payload.h create mode 100644 src/charon/encoding/payloads/configuration_attribute.c create mode 100644 src/charon/encoding/payloads/configuration_attribute.h create mode 100644 src/charon/encoding/payloads/cp_payload.c create mode 100644 src/charon/encoding/payloads/cp_payload.h create mode 100644 src/charon/encoding/payloads/delete_payload.c create mode 100644 src/charon/encoding/payloads/delete_payload.h create mode 100644 src/charon/encoding/payloads/eap_payload.c create mode 100644 src/charon/encoding/payloads/eap_payload.h create mode 100644 src/charon/encoding/payloads/encodings.c create mode 100644 src/charon/encoding/payloads/encodings.h create mode 100644 src/charon/encoding/payloads/encryption_payload.c create mode 100644 src/charon/encoding/payloads/encryption_payload.h create mode 100644 src/charon/encoding/payloads/id_payload.c create mode 100644 src/charon/encoding/payloads/id_payload.h create mode 100644 src/charon/encoding/payloads/ike_header.c create mode 100644 src/charon/encoding/payloads/ike_header.h create mode 100644 src/charon/encoding/payloads/ke_payload.c create mode 100644 src/charon/encoding/payloads/ke_payload.h create mode 100644 src/charon/encoding/payloads/nonce_payload.c create mode 100644 src/charon/encoding/payloads/nonce_payload.h create mode 100644 src/charon/encoding/payloads/notify_payload.c create mode 100644 src/charon/encoding/payloads/notify_payload.h create mode 100644 src/charon/encoding/payloads/payload.c create mode 100644 src/charon/encoding/payloads/payload.h create mode 100644 src/charon/encoding/payloads/proposal_substructure.c create mode 100644 src/charon/encoding/payloads/proposal_substructure.h create mode 100644 src/charon/encoding/payloads/sa_payload.c create mode 100644 src/charon/encoding/payloads/sa_payload.h create mode 100644 src/charon/encoding/payloads/traffic_selector_substructure.c create mode 100644 src/charon/encoding/payloads/traffic_selector_substructure.h create mode 100644 src/charon/encoding/payloads/transform_attribute.c create mode 100644 src/charon/encoding/payloads/transform_attribute.h create mode 100644 src/charon/encoding/payloads/transform_substructure.c create mode 100644 src/charon/encoding/payloads/transform_substructure.h create mode 100644 src/charon/encoding/payloads/ts_payload.c create mode 100644 src/charon/encoding/payloads/ts_payload.h create mode 100644 src/charon/encoding/payloads/unknown_payload.c create mode 100644 src/charon/encoding/payloads/unknown_payload.h create mode 100644 src/charon/encoding/payloads/vendor_id_payload.c create mode 100644 src/charon/encoding/payloads/vendor_id_payload.h create mode 100644 src/charon/network/Makefile.network create mode 100644 src/charon/network/packet.c create mode 100644 src/charon/network/packet.h create mode 100644 src/charon/network/socket.c create mode 100644 src/charon/network/socket.h create mode 100644 src/charon/queues/Makefile.queues create mode 100644 src/charon/queues/event_queue.c create mode 100644 src/charon/queues/event_queue.h create mode 100644 src/charon/queues/job_queue.c create mode 100644 src/charon/queues/job_queue.h create mode 100644 src/charon/queues/jobs/Makefile.jobs create mode 100644 src/charon/queues/jobs/delete_established_ike_sa_job.c create mode 100644 src/charon/queues/jobs/delete_established_ike_sa_job.h create mode 100644 src/charon/queues/jobs/delete_half_open_ike_sa_job.c create mode 100644 src/charon/queues/jobs/delete_half_open_ike_sa_job.h create mode 100644 src/charon/queues/jobs/incoming_packet_job.c create mode 100644 src/charon/queues/jobs/incoming_packet_job.h create mode 100644 src/charon/queues/jobs/initiate_ike_sa_job.c create mode 100644 src/charon/queues/jobs/initiate_ike_sa_job.h create mode 100644 src/charon/queues/jobs/job.c create mode 100644 src/charon/queues/jobs/job.h create mode 100644 src/charon/queues/jobs/retransmit_request_job.c create mode 100644 src/charon/queues/jobs/retransmit_request_job.h create mode 100644 src/charon/queues/send_queue.c create mode 100644 src/charon/queues/send_queue.h create mode 100644 src/charon/sa/Makefile.sa create mode 100644 src/charon/sa/authenticator.c create mode 100644 src/charon/sa/authenticator.h create mode 100644 src/charon/sa/child_sa.c create mode 100644 src/charon/sa/child_sa.h create mode 100644 src/charon/sa/ike_sa.c create mode 100644 src/charon/sa/ike_sa.h create mode 100644 src/charon/sa/ike_sa_id.c create mode 100644 src/charon/sa/ike_sa_id.h create mode 100644 src/charon/sa/ike_sa_manager.c create mode 100644 src/charon/sa/ike_sa_manager.h create mode 100644 src/charon/sa/states/Makefile.states create mode 100644 src/charon/sa/states/ike_auth_requested.c create mode 100644 src/charon/sa/states/ike_auth_requested.h create mode 100644 src/charon/sa/states/ike_sa_established.c create mode 100644 src/charon/sa/states/ike_sa_established.h create mode 100644 src/charon/sa/states/ike_sa_init_requested.c create mode 100644 src/charon/sa/states/ike_sa_init_requested.h create mode 100644 src/charon/sa/states/ike_sa_init_responded.c create mode 100644 src/charon/sa/states/ike_sa_init_responded.h create mode 100644 src/charon/sa/states/initiator_init.c create mode 100644 src/charon/sa/states/initiator_init.h create mode 100644 src/charon/sa/states/responder_init.c create mode 100644 src/charon/sa/states/responder_init.h create mode 100644 src/charon/sa/states/state.c create mode 100644 src/charon/sa/states/state.h create mode 100644 src/charon/threads/Makefile.threads create mode 100644 src/charon/threads/kernel_interface.c create mode 100644 src/charon/threads/kernel_interface.h create mode 100644 src/charon/threads/receiver.c create mode 100644 src/charon/threads/receiver.h create mode 100644 src/charon/threads/scheduler.c create mode 100644 src/charon/threads/scheduler.h create mode 100644 src/charon/threads/sender.c create mode 100644 src/charon/threads/sender.h create mode 100755 src/charon/threads/stroke_interface.c create mode 100644 src/charon/threads/stroke_interface.h create mode 100644 src/charon/threads/thread_pool.c create mode 100644 src/charon/threads/thread_pool.h (limited to 'src') diff --git a/src/charon/Architecture.txt b/src/charon/Architecture.txt new file mode 100644 index 000000000..14b99274c --- /dev/null +++ b/src/charon/Architecture.txt @@ -0,0 +1,56 @@ +/** @mainpage + +@section design strongSwans overall design + +IKEv1 and IKEv2 is handled in different keying daemons. The ole IKEv1 stuff is +completely handled in pluto, as it was all the times. IKEv2 is handled in the +new keying daemon, which is called #charon. +Daemon control is done over unix sockets. Pluto uses whack, as it did for years. +Charon uses another socket interface, called stroke. Stroke uses another +format as whack and therefore is not compatible to whack. The starter utility, +wich does fast configuration parsing, speaks both the protocols, whack and +stroke. It also handles daemon startup and termination. +Pluto uses starter for some commands, for other it uses the whack utility. To be +as close to pluto as possible, charon has the same split up of commands to +starter and stroke. All commands are wrapped together in the ipsec script, which +allows transparent control of both daemons. +@verbatim + + +-----------------------------------------+ + | ipsec | + +-----+--------------+---------------+----+ + | | | + | | | + | +-----+-----+ | + +-----+----+ | | +-----+----+ + | | | starter | | | + | stroke | | | | whack | + | | +---+--+----+ | | + +------+---+ | | +--+-------+ + | | | | + +---+------+ | | +------+--+ + | | | | | | + | charon +----+ +----+ pluto | + | | | | + +-----+----+ +----+----+ + | | + +-----+----+ | + | LSF | | + +-----+----+ | + | | + +-----+----+ +----+----+ + | RAW Sock | | UDP/500 | + +----------+ +---------+ + +@endverbatim +Since IKEv2 uses the same port as IKEv1, both daemons must listen to UDP port +500. Under Linux, there is no clean way to set up two sockets at the same port. +To reslove this problem, charon uses a RAW socket, as they are used in network +sniffers. An installed Linux Socket Filter (LSF) filters out all none-IKEv2 +traffic. Pluto receives any IKE message, independant of charons behavior. +Therefore plutos behavior is changed to discard any IKEv2 traffic silently. + +To gain some reusability of the code, generic crypto and utility functions are +separeted in a shared library, libstrongswan. + +*/ \ No newline at end of file diff --git a/src/charon/Known-bugs.txt b/src/charon/Known-bugs.txt new file mode 100644 index 000000000..7fdf258e3 --- /dev/null +++ b/src/charon/Known-bugs.txt @@ -0,0 +1,7 @@ + Known bugs in charon +====================== + +- intiating the same connection twice makes trouble +- leak_detective gets confused from libpthread (invalid frees) +- installing to many SAs in the kernel at the same time causes troubles. Threading issue? + diff --git a/src/charon/Makefile.charon b/src/charon/Makefile.charon new file mode 100644 index 000000000..336495db9 --- /dev/null +++ b/src/charon/Makefile.charon @@ -0,0 +1,25 @@ +# Copyright (C) 2006 Martin Willi +# Hochschule fuer Technik Rapperswil +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. See . +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +CHARON_DIR= $(MAIN_DIR)charon/ + +$(BUILD_DIR)daemon.o : $(CHARON_DIR)daemon.c $(CHARON_DIR)daemon.h + $(CC) $(CFLAGS) -c -o $@ $< + + +include $(CHARON_DIR)network/Makefile.network +include $(CHARON_DIR)config/Makefile.config +include $(CHARON_DIR)encoding/Makefile.encoding +include $(CHARON_DIR)queues/Makefile.queues +include $(CHARON_DIR)sa/Makefile.sa +include $(CHARON_DIR)threads/Makefile.threads \ No newline at end of file diff --git a/src/charon/Todo-list.txt b/src/charon/Todo-list.txt new file mode 100644 index 000000000..7bff26d84 --- /dev/null +++ b/src/charon/Todo-list.txt @@ -0,0 +1,57 @@ + Todo-List for charon +====================== + ++ = done, / = partial, - = todo, ordered by priority + + ++ private key loading: der, without passphrase ++ load all private keys from ipsec.d/private/ in stroke.c ++ handle leftcert and rightcert in starterstroke.c/stroke.c ++ load specified certs in stroke.c ++ extract public keys from certs ++ public key authentication ++ release for Andreas + ++ stroke loglevels ++ stroke up ++ ike_sa_manager checkout_by_hosts ++ stroke down ++ stroke output redirection ++ stroke status + ++ libx509 + + new charon build - libstrong? + + transforms + + utils (plus host) + + logger_manager instance in lib + + leak detective usable for charon and pluto and anything else + + integrate asn1 parser/oid (asn1/oid) + + integrate basic PEM loading + + port x509 stuff + ++ doxygen cleanup (charon/lib) + +/ useable certificate support + + more id types (use atodn from pluto) + + rewrite certificate storage the clean way + - further subjectAltName support + - certificate validation/chaining + - certificate exchange + ++ Apply -W's from Makefile.program to charon +- do ipsec status via starter +- add more output to to up/down, somehow... + +- stroke status should show configured connections +- stroke loglevel update +- stroke argument parsing via getopts/gperf? + +- implement 3DES to load encrypted pem files +- ipsec.secrets parsing + +- trapping +- delete notify, when to send? +- notifys on connection setup failure +- create child sa message/rekeying + +- new build environment (autotools?) diff --git a/src/charon/charon.kdevelop b/src/charon/charon.kdevelop deleted file mode 100644 index 270e815c4..000000000 --- a/src/charon/charon.kdevelop +++ /dev/null @@ -1,105 +0,0 @@ - - - - Martin Willi - martin@strongswan.org - $VERSION$ - KDevCustomProject - C - - - - - Source - executable - - - - - - - - - - - - - ada - ada_bugs_gcc - bash - bash_bugs - clanlib - fortran_bugs_gcc - gnome1 - gnustep - gtk - gtk_bugs - haskell - haskell_bugs_ghc - java_bugs_gcc - java_bugs_sun - kde2book - libstdc++ - opengl - pascal_bugs_fp - php - php_bugs - perl - perl_bugs - python - python_bugs - qt-kdev3 - ruby - ruby_bugs - sdl - stl - sw - w3c-dom-level2-html - w3c-svg - w3c-uaag10 - wxwidgets_bugs - - - Guide to the Qt Translation Tools - Qt Assistant Manual - Qt Designer Manual - Qt Reference Documentation - qmake User Guide - - - KDE Libraries (Doxygen) - - - - - - - - - - - - - true - true - true - false - true - true - true - 250 - 400 - 250 - - - - - false - false - - - *.o,*.lo,CVS - false - - - diff --git a/src/charon/charon/Architecture.txt b/src/charon/charon/Architecture.txt deleted file mode 100644 index 14b99274c..000000000 --- a/src/charon/charon/Architecture.txt +++ /dev/null @@ -1,56 +0,0 @@ -/** @mainpage - -@section design strongSwans overall design - -IKEv1 and IKEv2 is handled in different keying daemons. The ole IKEv1 stuff is -completely handled in pluto, as it was all the times. IKEv2 is handled in the -new keying daemon, which is called #charon. -Daemon control is done over unix sockets. Pluto uses whack, as it did for years. -Charon uses another socket interface, called stroke. Stroke uses another -format as whack and therefore is not compatible to whack. The starter utility, -wich does fast configuration parsing, speaks both the protocols, whack and -stroke. It also handles daemon startup and termination. -Pluto uses starter for some commands, for other it uses the whack utility. To be -as close to pluto as possible, charon has the same split up of commands to -starter and stroke. All commands are wrapped together in the ipsec script, which -allows transparent control of both daemons. -@verbatim - - +-----------------------------------------+ - | ipsec | - +-----+--------------+---------------+----+ - | | | - | | | - | +-----+-----+ | - +-----+----+ | | +-----+----+ - | | | starter | | | - | stroke | | | | whack | - | | +---+--+----+ | | - +------+---+ | | +--+-------+ - | | | | - +---+------+ | | +------+--+ - | | | | | | - | charon +----+ +----+ pluto | - | | | | - +-----+----+ +----+----+ - | | - +-----+----+ | - | LSF | | - +-----+----+ | - | | - +-----+----+ +----+----+ - | RAW Sock | | UDP/500 | - +----------+ +---------+ - -@endverbatim -Since IKEv2 uses the same port as IKEv1, both daemons must listen to UDP port -500. Under Linux, there is no clean way to set up two sockets at the same port. -To reslove this problem, charon uses a RAW socket, as they are used in network -sniffers. An installed Linux Socket Filter (LSF) filters out all none-IKEv2 -traffic. Pluto receives any IKE message, independant of charons behavior. -Therefore plutos behavior is changed to discard any IKEv2 traffic silently. - -To gain some reusability of the code, generic crypto and utility functions are -separeted in a shared library, libstrongswan. - -*/ \ No newline at end of file diff --git a/src/charon/charon/Known-bugs.txt b/src/charon/charon/Known-bugs.txt deleted file mode 100644 index 7fdf258e3..000000000 --- a/src/charon/charon/Known-bugs.txt +++ /dev/null @@ -1,7 +0,0 @@ - Known bugs in charon -====================== - -- intiating the same connection twice makes trouble -- leak_detective gets confused from libpthread (invalid frees) -- installing to many SAs in the kernel at the same time causes troubles. Threading issue? - diff --git a/src/charon/charon/Makefile.charon b/src/charon/charon/Makefile.charon deleted file mode 100644 index 336495db9..000000000 --- a/src/charon/charon/Makefile.charon +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (C) 2006 Martin Willi -# Hochschule fuer Technik Rapperswil -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. See . -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# for more details. -# -CHARON_DIR= $(MAIN_DIR)charon/ - -$(BUILD_DIR)daemon.o : $(CHARON_DIR)daemon.c $(CHARON_DIR)daemon.h - $(CC) $(CFLAGS) -c -o $@ $< - - -include $(CHARON_DIR)network/Makefile.network -include $(CHARON_DIR)config/Makefile.config -include $(CHARON_DIR)encoding/Makefile.encoding -include $(CHARON_DIR)queues/Makefile.queues -include $(CHARON_DIR)sa/Makefile.sa -include $(CHARON_DIR)threads/Makefile.threads \ No newline at end of file diff --git a/src/charon/charon/Todo-list.txt b/src/charon/charon/Todo-list.txt deleted file mode 100644 index 7bff26d84..000000000 --- a/src/charon/charon/Todo-list.txt +++ /dev/null @@ -1,57 +0,0 @@ - Todo-List for charon -====================== - -+ = done, / = partial, - = todo, ordered by priority - - -+ private key loading: der, without passphrase -+ load all private keys from ipsec.d/private/ in stroke.c -+ handle leftcert and rightcert in starterstroke.c/stroke.c -+ load specified certs in stroke.c -+ extract public keys from certs -+ public key authentication -+ release for Andreas - -+ stroke loglevels -+ stroke up -+ ike_sa_manager checkout_by_hosts -+ stroke down -+ stroke output redirection -+ stroke status - -+ libx509 - + new charon build - libstrong? - + transforms - + utils (plus host) - + logger_manager instance in lib - + leak detective usable for charon and pluto and anything else - + integrate asn1 parser/oid (asn1/oid) - + integrate basic PEM loading - + port x509 stuff - -+ doxygen cleanup (charon/lib) - -/ useable certificate support - + more id types (use atodn from pluto) - + rewrite certificate storage the clean way - - further subjectAltName support - - certificate validation/chaining - - certificate exchange - -+ Apply -W's from Makefile.program to charon -- do ipsec status via starter -- add more output to to up/down, somehow... - -- stroke status should show configured connections -- stroke loglevel update -- stroke argument parsing via getopts/gperf? - -- implement 3DES to load encrypted pem files -- ipsec.secrets parsing - -- trapping -- delete notify, when to send? -- notifys on connection setup failure -- create child sa message/rekeying - -- new build environment (autotools?) diff --git a/src/charon/charon/config/Makefile.config b/src/charon/charon/config/Makefile.config deleted file mode 100644 index d4638b318..000000000 --- a/src/charon/charon/config/Makefile.config +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright (C) 2005 Jan Hutter, 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 . -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# for more details. -# - -CONFIG_DIR= $(CHARON_DIR)config/ - - -CHARON_OBJS+= $(BUILD_DIR)traffic_selector.o -$(BUILD_DIR)traffic_selector.o : $(CONFIG_DIR)traffic_selector.c $(CONFIG_DIR)traffic_selector.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)proposal.o -$(BUILD_DIR)proposal.o : $(CONFIG_DIR)proposal.c $(CONFIG_DIR)proposal.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)configuration.o -$(BUILD_DIR)configuration.o : $(CONFIG_DIR)configuration.c $(CONFIG_DIR)configuration.h - $(CC) $(CFLAGS) -c -o $@ $< - -include $(CONFIG_DIR)connections/Makefile.connections -include $(CONFIG_DIR)credentials/Makefile.credentials -include $(CONFIG_DIR)policies/Makefile.policies \ No newline at end of file diff --git a/src/charon/charon/config/configuration.c b/src/charon/charon/config/configuration.c deleted file mode 100755 index eac1bd43a..000000000 --- a/src/charon/charon/config/configuration.c +++ /dev/null @@ -1,112 +0,0 @@ -/** - * @file configuration.c - * - * @brief Implementation of configuration_t. - * - */ - -/* - * Copyright (C) 2006 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 - -#include "configuration.h" - -#include - -/** - * First retransmit timeout in milliseconds. - * Timeout value is increasing in each retransmit round. - */ -#define RETRANSMIT_TIMEOUT 3000 - -/** - * Timeout in milliseconds after that a half open IKE_SA gets deleted. - */ -#define HALF_OPEN_IKE_SA_TIMEOUT 30000 - -/** - * Max retransmit count. - * 0 for infinite. The max time a half open IKE_SA is alive is set by - * RETRANSMIT_TIMEOUT. - */ -#define MAX_RETRANSMIT_COUNT 0 - - -typedef struct private_configuration_t private_configuration_t; - -/** - * Private data of an configuration_t object. - */ -struct private_configuration_t { - - /** - * Public part of configuration_t object. - */ - configuration_t public; - -}; - -/** - * Implementation of configuration_t.get_retransmit_timeout. - */ -static status_t get_retransmit_timeout (private_configuration_t *this, u_int32_t retransmit_count, u_int32_t *timeout) -{ - int new_timeout = RETRANSMIT_TIMEOUT, i; - if (retransmit_count > MAX_RETRANSMIT_COUNT && MAX_RETRANSMIT_COUNT != 0) - { - return FAILED; - } - - for (i = 0; i < retransmit_count; i++) - { - new_timeout *= 2; - } - - *timeout = new_timeout; - - return SUCCESS; -} - -/** - * Implementation of configuration_t.get_half_open_ike_sa_timeout. - */ -static u_int32_t get_half_open_ike_sa_timeout (private_configuration_t *this) -{ - return HALF_OPEN_IKE_SA_TIMEOUT; -} - -/** - * Implementation of configuration_t.destroy. - */ -static void destroy(private_configuration_t *this) -{ - free(this); -} - -/* - * Described in header-file - */ -configuration_t *configuration_create() -{ - private_configuration_t *this = malloc_thing(private_configuration_t); - - /* public functions */ - this->public.destroy = (void(*)(configuration_t*))destroy; - this->public.get_retransmit_timeout = (status_t (*) (configuration_t *, u_int32_t retransmit_count, u_int32_t *timeout))get_retransmit_timeout; - this->public.get_half_open_ike_sa_timeout = (u_int32_t (*) (configuration_t *)) get_half_open_ike_sa_timeout; - - return (&this->public); -} diff --git a/src/charon/charon/config/configuration.h b/src/charon/charon/config/configuration.h deleted file mode 100755 index 3696215f0..000000000 --- a/src/charon/charon/config/configuration.h +++ /dev/null @@ -1,89 +0,0 @@ -/** - * @file configuration.h - * - * @brief Interface configuration_t. - * - */ - -/* - * Copyright (C) 2006 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef CONFIGURATION_H_ -#define CONFIGURATION_H_ - -#include - - -typedef struct configuration_t configuration_t; - -/** - * @brief The interface for various daemon related configs. - * - * @b Constructors: - * - configuration_create() - * - * @ingroup config - */ -struct configuration_t { - - /** - * @brief Returns the retransmit timeout. - * - * The timeout values are managed by the configuration, so - * another backoff algorithm may be implemented here. - * - * @param this calling object - * @param retransmit_count number of times a message was retransmitted so far - * @param[out] timeout the new retransmit timeout in milliseconds - * - * @return - * - FAILED, if the message should not be retransmitted - * - SUCCESS - */ - status_t (*get_retransmit_timeout) (configuration_t *this, u_int32_t retransmit_count, u_int32_t *timeout); - - /** - * @brief Returns the timeout for an half open IKE_SA in ms. - * - * Half open means that the IKE_SA is still in one of the following states: - * - INITIATOR_INIT - * - RESPONDER_INIT - * - IKE_SA_INIT_REQUESTED - * - IKE_SA_INIT_RESPONDED - * - IKE_AUTH_REQUESTED - * - * @param this calling object - * @return timeout in milliseconds (ms) - */ - u_int32_t (*get_half_open_ike_sa_timeout) (configuration_t *this); - - /** - * @brief Destroys a configuration_t object. - * - * @param this calling object - */ - void (*destroy) (configuration_t *this); -}; - -/** - * @brief Creates a configuration backend. - * - * @return static_configuration_t object - * - * @ingroup config - */ -configuration_t *configuration_create(void); - -#endif /*CONFIGURATION_H_*/ diff --git a/src/charon/charon/config/connections/Makefile.connections b/src/charon/charon/config/connections/Makefile.connections deleted file mode 100644 index 8fbc983f6..000000000 --- a/src/charon/charon/config/connections/Makefile.connections +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (C) 2006 Martin Willi -# Hochschule fuer Technik Rapperswil -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. See . -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# for more details. -# - -CONNECTIONS_DIR= $(CONFIG_DIR)connections/ - - -CHARON_OBJS+= $(BUILD_DIR)connection.o -$(BUILD_DIR)connection.o : $(CONNECTIONS_DIR)connection.c $(CONNECTIONS_DIR)connection.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)local_connection_store.o -$(BUILD_DIR)local_connection_store.o : $(CONNECTIONS_DIR)local_connection_store.c $(CONNECTIONS_DIR)local_connection_store.h - $(CC) $(CFLAGS) -c -o $@ $< \ No newline at end of file diff --git a/src/charon/charon/config/connections/connection.c b/src/charon/charon/config/connections/connection.c deleted file mode 100644 index 74e6762b4..000000000 --- a/src/charon/charon/config/connections/connection.c +++ /dev/null @@ -1,367 +0,0 @@ -/** - * @file connection.c - * - * @brief Implementation of connection_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 - -#include "connection.h" - -#include -#include - -/** - * String mappings for auth_method_t. - */ -mapping_t auth_method_m[] = { - {RSA_DIGITAL_SIGNATURE, "RSA"}, - {SHARED_KEY_MESSAGE_INTEGRITY_CODE, "SHARED_KEY"}, - {DSS_DIGITAL_SIGNATURE, "DSS"}, - {MAPPING_END, NULL} -}; - - -typedef struct private_connection_t private_connection_t; - -/** - * Private data of an connection_t object - */ -struct private_connection_t { - - /** - * Public part - */ - connection_t public; - - /** - * Name of the connection - */ - char *name; - - /** - * ID of us - */ - identification_t *my_id; - - /** - * ID of remote peer - */ - identification_t *other_id; - - /** - * Host information of my host. - */ - host_t *my_host; - - /** - * Host information of other host. - */ - host_t *other_host; - - /** - * Method to use for own authentication data - */ - auth_method_t auth_method; - - /** - * Supported proposals - */ - linked_list_t *proposals; -}; - -/** - * Implementation of connection_t.get_name. - */ -static char *get_name (private_connection_t *this) -{ - return this->name; -} - -/** - * Implementation of connection_t.get_my_id. - */ -static identification_t *get_my_id (private_connection_t *this) -{ - return this->my_id; -} - -/** - * Implementation of connection_t.get_other_id. - */ -static identification_t *get_other_id(private_connection_t *this) -{ - return this->other_id; -} - -/** - * Implementation of connection_t.update_my_id - */ -static void update_my_id(private_connection_t *this, identification_t *my_id) -{ - this->my_id->destroy(this->my_id); - this->my_id = my_id; -} - -/** - * Implementation of connection_t.update_other_id - */ -static void update_other_id(private_connection_t *this, identification_t *other_id) -{ - this->other_id->destroy(this->other_id); - this->other_id = other_id; -} - -/** - * Implementation of connection_t.get_my_host. - */ -static host_t * get_my_host (private_connection_t *this) -{ - return this->my_host; -} - -/** - * Implementation of connection_t.update_my_host. - */ -static void update_my_host(private_connection_t *this, host_t *my_host) -{ - this->my_host->destroy(this->my_host); - this->my_host = my_host; -} - -/** - * Implementation of connection_t.update_other_host. - */ -static void update_other_host(private_connection_t *this, host_t *other_host) -{ - this->other_host->destroy(this->other_host); - this->other_host = other_host; -} - -/** - * Implementation of connection_t.get_other_host. - */ -static host_t * get_other_host (private_connection_t *this) -{ - return this->other_host; -} - -/** - * Implementation of connection_t.get_proposals. - */ -static linked_list_t* get_proposals (private_connection_t *this) -{ - return this->proposals; -} - -/** - * Implementation of connection_t.select_proposal. - */ -static proposal_t *select_proposal(private_connection_t *this, linked_list_t *proposals) -{ - iterator_t *stored_iter, *supplied_iter; - proposal_t *stored, *supplied, *selected; - - stored_iter = this->proposals->create_iterator(this->proposals, TRUE); - supplied_iter = proposals->create_iterator(proposals, TRUE); - - /* compare all stored proposals with all supplied. Stored ones are preferred. */ - while (stored_iter->has_next(stored_iter)) - { - supplied_iter->reset(supplied_iter); - stored_iter->current(stored_iter, (void**)&stored); - - while (supplied_iter->has_next(supplied_iter)) - { - supplied_iter->current(supplied_iter, (void**)&supplied); - selected = stored->select(stored, supplied); - if (selected) - { - /* they match, return */ - stored_iter->destroy(stored_iter); - supplied_iter->destroy(supplied_iter); - return selected; - } - } - } - - /* no proposal match :-(, will result in a NO_PROPOSAL_CHOSEN... */ - stored_iter->destroy(stored_iter); - supplied_iter->destroy(supplied_iter); - - return NULL; -} - -/** - * Implementation of connection_t.add_proposal. - */ -static void add_proposal (private_connection_t *this, proposal_t *proposal) -{ - this->proposals->insert_last(this->proposals, proposal); -} - -/** - * Implementation of connection_t.auth_method_t. - */ -static auth_method_t get_auth_method(private_connection_t *this) -{ - return this->auth_method; -} - -/** - * Implementation of connection_t.get_dh_group. - */ -static diffie_hellman_group_t get_dh_group(private_connection_t *this) -{ - iterator_t *iterator; - proposal_t *proposal; - algorithm_t *algo; - - iterator = this->proposals->create_iterator(this->proposals, TRUE); - while (iterator->has_next(iterator)) - { - iterator->current(iterator, (void**)&proposal); - proposal->get_algorithm(proposal, PROTO_IKE, DIFFIE_HELLMAN_GROUP, &algo); - if (algo) - { - iterator->destroy(iterator); - return algo->algorithm; - } - } - iterator->destroy(iterator); - return MODP_UNDEFINED; -} - -/** - * Implementation of connection_t.check_dh_group. - */ -static bool check_dh_group(private_connection_t *this, diffie_hellman_group_t dh_group) -{ - iterator_t *prop_iter, *alg_iter; - proposal_t *proposal; - algorithm_t *algo; - - prop_iter = this->proposals->create_iterator(this->proposals, TRUE); - while (prop_iter->has_next(prop_iter)) - { - prop_iter->current(prop_iter, (void**)&proposal); - alg_iter = proposal->create_algorithm_iterator(proposal, PROTO_IKE, DIFFIE_HELLMAN_GROUP); - while (alg_iter->has_next(alg_iter)) - { - alg_iter->current(alg_iter, (void**)&algo); - if (algo->algorithm == dh_group) - { - prop_iter->destroy(prop_iter); - alg_iter->destroy(alg_iter); - return TRUE; - } - } - } - prop_iter->destroy(prop_iter); - alg_iter->destroy(alg_iter); - return FALSE; -} - -/** - * Implementation of connection_t.clone. - */ -static connection_t *clone(private_connection_t *this) -{ - iterator_t *iterator; - proposal_t *proposal; - private_connection_t *clone = (private_connection_t*)connection_create( - this->name, - this->my_host->clone(this->my_host), - this->other_host->clone(this->other_host), - this->my_id->clone(this->my_id), - this->other_id->clone(this->other_id), - this->auth_method); - - /* clone all proposals */ - iterator = this->proposals->create_iterator(this->proposals, TRUE); - while (iterator->has_next(iterator)) - { - iterator->current(iterator, (void**)&proposal); - proposal = proposal->clone(proposal); - clone->proposals->insert_last(clone->proposals, (void*)proposal); - } - iterator->destroy(iterator); - - return &clone->public; -} - -/** - * Implementation of connection_t.destroy. - */ -static void destroy (private_connection_t *this) -{ - proposal_t *proposal; - - while (this->proposals->remove_last(this->proposals, (void**)&proposal) == SUCCESS) - { - proposal->destroy(proposal); - } - this->proposals->destroy(this->proposals); - - this->my_host->destroy(this->my_host); - this->other_host->destroy(this->other_host); - this->my_id->destroy(this->my_id); - this->other_id->destroy(this->other_id); - free(this->name); - free(this); -} - -/** - * Described in header. - */ -connection_t * connection_create(char *name, host_t *my_host, host_t *other_host, identification_t *my_id, identification_t *other_id, auth_method_t auth_method) -{ - private_connection_t *this = malloc_thing(private_connection_t); - - /* public functions */ - this->public.get_name = (char*(*)(connection_t*))get_name; - this->public.get_my_id = (identification_t*(*)(connection_t*))get_my_id; - this->public.get_other_id = (identification_t*(*)(connection_t*))get_other_id; - this->public.get_my_host = (host_t*(*)(connection_t*))get_my_host; - this->public.update_my_host = (void(*)(connection_t*,host_t*))update_my_host; - this->public.update_other_host = (void(*)(connection_t*,host_t*))update_other_host; - this->public.update_my_id = (void(*)(connection_t*,identification_t*))update_my_id; - this->public.update_other_id = (void(*)(connection_t*,identification_t*))update_other_id; - this->public.get_other_host = (host_t*(*)(connection_t*))get_other_host; - this->public.get_proposals = (linked_list_t*(*)(connection_t*))get_proposals; - this->public.select_proposal = (proposal_t*(*)(connection_t*,linked_list_t*))select_proposal; - this->public.add_proposal = (void(*)(connection_t*, proposal_t*)) add_proposal; - this->public.get_auth_method = (auth_method_t(*)(connection_t*)) get_auth_method; - this->public.get_dh_group = (diffie_hellman_group_t(*)(connection_t*)) get_dh_group; - this->public.check_dh_group = (bool(*)(connection_t*,diffie_hellman_group_t)) check_dh_group; - this->public.clone = (connection_t*(*)(connection_t*))clone; - this->public.destroy = (void(*)(connection_t*))destroy; - - /* private variables */ - this->name = strdup(name); - this->my_host = my_host; - this->other_host = other_host; - this->my_id = my_id; - this->other_id = other_id; - this->auth_method = auth_method; - - this->proposals = linked_list_create(); - - return (&this->public); -} diff --git a/src/charon/charon/config/connections/connection.h b/src/charon/charon/config/connections/connection.h deleted file mode 100644 index 2cb3c20b8..000000000 --- a/src/charon/charon/config/connections/connection.h +++ /dev/null @@ -1,283 +0,0 @@ -/** - * @file connection.h - * - * @brief Interface of connection_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef CONNECTION_H_ -#define CONNECTION_H_ - -#include -#include -#include -#include -#include -#include - - -typedef enum auth_method_t auth_method_t; - -/** - * AUTH Method to use. - * - * @ingroup config - */ -enum auth_method_t { - /** - * Computed as specified in section 2.15 of RFC using - * an RSA private key over a PKCS#1 padded hash. - */ - RSA_DIGITAL_SIGNATURE = 1, - - /** - * Computed as specified in section 2.15 of RFC using the - * shared key associated with the identity in the ID payload - * and the negotiated prf function - */ - SHARED_KEY_MESSAGE_INTEGRITY_CODE = 2, - - /** - * Computed as specified in section 2.15 of RFC using a - * DSS private key over a SHA-1 hash. - */ - DSS_DIGITAL_SIGNATURE = 3, -}; - -/** - * string mappings for auth method. - * - * @ingroup config - */ -extern mapping_t auth_method_m[]; - - -typedef struct connection_t connection_t; - -/** - * @brief A connection_t defines the rules to set up an IKE_SA. - * - * - * @b Constructors: - * - connection_create() - * - * @ingroup config - */ -struct connection_t { - - /** - * @brief Get my ID for this connection. - * - * Object is NOT getting cloned. - * - * @param this calling object - * @return host information as identification_t object - */ - identification_t *(*get_my_id) (connection_t *this); - - /** - * @brief Get others ID for this connection. - * - * Object is NOT getting cloned. - * - * @param this calling object - * @return host information as identification_t object - */ - identification_t *(*get_other_id) (connection_t *this); - - /** - * @brief Get my address as host_t object. - * - * Object is NOT getting cloned. - * - * @param this calling object - * @return host information as host_t object - */ - host_t *(*get_my_host) (connection_t *this); - - /** - * @brief Get others address as host_t object. - * - * Object is NOT getting cloned. - * - * @param this calling object - * @return host information as host_t object - */ - host_t *(*get_other_host) (connection_t *this); - - /** - * @brief Update address of my host. - * - * It may be necessary to uptdate own address, as it - * is set to the default route (0.0.0.0) in some cases. - * Old host is destroyed, new one NOT cloned. - * - * @param this calling object - * @param my_host new host to set as my_host - */ - void (*update_my_host) (connection_t *this, host_t *my_host); - - /** - * @brief Update address of remote host. - * - * It may be necessary to uptdate remote address, as a - * connection may define %any (0.0.0.0) or a subnet. - * Old host is destroyed, new one NOT cloned. - * - * @param this calling object - * @param my_host new host to set as other_host - */ - void (*update_other_host) (connection_t *this, host_t *other_host); - - /** - * @brief Update own ID. - * - * It may be necessary to uptdate own ID, as it - * is set to %any or to e.g. *@strongswan.org in - * some cases. - * Old ID is destroyed, new one NOT cloned. - * - * @param this calling object - * @param my_id new ID to set as my_id - */ - void (*update_my_id) (connection_t *this, identification_t *my_id); - - /** - * @brief Update others ID. - * - * It may be necessary to uptdate others ID, as it - * is set to %any or to e.g. *@strongswan.org in - * some cases. - * Old ID is destroyed, new one NOT cloned. - * - * @param this calling object - * @param other_id new ID to set as other_id - */ - void (*update_other_id) (connection_t *this, identification_t *other_id); - - /** - * @brief Returns a list of all supported proposals. - * - * Returned list is still owned by connection and MUST NOT - * modified or destroyed. - * - * @param this calling object - * @return list containing all the proposals - */ - linked_list_t *(*get_proposals) (connection_t *this); - - /** - * @brief Adds a proposal to the list. - * - * The first added proposal has the highest priority, the last - * added the lowest. - * - * @param this calling object - * @param proposal proposal to add - */ - void (*add_proposal) (connection_t *this, proposal_t *proposal); - - /** - * @brief Select a proposed from suggested proposals. - * - * Returned proposal must be destroyed after usage. - * - * @param this calling object - * @param proposals list of proposals to select from - * @return selected proposal, or NULL if none matches. - */ - proposal_t *(*select_proposal) (connection_t *this, linked_list_t *proposals); - - /** - * @brief Get the authentication method to use - * - * @param this calling object - * @return authentication method - */ - auth_method_t (*get_auth_method) (connection_t *this); - - /** - * @brief Get the connection name. - * - * Name must not be freed, since it points to - * internal data. - * - * @param this calling object - * @return name of the connection - */ - char* (*get_name) (connection_t *this); - - /** - * @brief Get the DH group to use for connection initialization. - * - * @param this calling object - * @return dh group to use for initialization - */ - diffie_hellman_group_t (*get_dh_group) (connection_t *this); - - /** - * @brief Check if a suggested dh group is acceptable. - * - * If we guess a wrong DH group for IKE_SA_INIT, the other - * peer will send us a offer. But is this acceptable for us? - * - * @param this calling object - * @return TRUE if group acceptable - */ - bool (*check_dh_group) (connection_t *this, diffie_hellman_group_t dh_group); - - /** - * @brief Clone a connection_t object. - * - * @param this connection to clone - * @return clone of it - */ - connection_t *(*clone) (connection_t *this); - - /** - * @brief Destroys a connection_t object. - * - * @param this calling object - */ - void (*destroy) (connection_t *this); -}; - -/** - * @brief Creates a connection_t object. - * - * Supplied hosts/IDs become owned by connection, so - * do not modify or destroy them after a call to - * connection_create(). Name gets cloned internally. - * - * @param name connection identifier - * @param my_host host_t representing local address - * @param other_host host_t representing remote address - * @param my_id identification_t for me - * @param other_id identification_t for other - * @param auth_method Authentication method to use for our(!) auth data - * @return connection_t object. - * - * @ingroup config - */ -connection_t * connection_create(char *name, - host_t *my_host, host_t *other_host, - identification_t *my_id, - identification_t *other_id, - auth_method_t auth_method); - -#endif /* CONNECTION_H_ */ diff --git a/src/charon/charon/config/connections/connection_store.h b/src/charon/charon/config/connections/connection_store.h deleted file mode 100755 index 41fd58e42..000000000 --- a/src/charon/charon/config/connections/connection_store.h +++ /dev/null @@ -1,112 +0,0 @@ -/** - * @file connection_store.h - * - * @brief Interface connection_store_t. - * - */ - -/* - * Copyright (C) 2006 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef CONNECTION_STORE_H_ -#define CONNECTION_STORE_H_ - -#include -#include - - -typedef struct connection_store_t connection_store_t; - -/** - * @brief The interface for a store of connection_t's. - * - * @b Constructors: - * - stroke_create() - * - * @ingroup config - */ -struct connection_store_t { - - /** - * @brief Returns a connection definition identified by two IDs. - * - * This call is useful to get a connection which is identified by IDs - * rather than addresses, e.g. for connection setup on user request. - * The returned connection gets created/cloned and therefore must - * be destroyed after usage. - * - * @param this calling object - * @param my_id own ID of connection - * @param other_id others ID of connection - * @return - * - connection_t, if found - * - NULL otherwise - */ - connection_t *(*get_connection_by_ids) (connection_store_t *this, identification_t *my_id, identification_t *other_id); - - /** - * @brief Returns a connection definition identified by two hosts. - * - * This call is usefull to get a connection identified by addresses. - * It may be used after kernel request for traffic protection. - * The returned connection gets created/cloned and therefore must - * be destroyed after usage. - * - * @param this calling object - * @param my_id own address of connection - * @param other_id others address of connection - * @return - * - connection_t, if found - * - NULL otherwise - */ - connection_t *(*get_connection_by_hosts) (connection_store_t *this, host_t *my_host, host_t *other_host); - - /** - * @brief Returns a connection identified by its name. - * - * This call is usefull to get a connection identified its - * name, as on an connection setup. - * - * @param this calling object - * @param name name of the connection to get - * @return - * - connection_t, if found - * - NULL otherwise - */ - connection_t *(*get_connection_by_name) (connection_store_t *this, char *name); - - /** - * @brief Add a connection to the store. - * - * After a successful call, the connection is owned by the store and may - * not be manipulated nor destroyed. - * - * @param this calling object - * @param connection connection to add - * @return - * - SUCCESS, or - * - FAILED - */ - status_t (*add_connection) (connection_store_t *this, connection_t *connection); - - /** - * @brief Destroys a connection_store_t object. - * - * @param this calling object - */ - void (*destroy) (connection_store_t *this); -}; - -#endif /* CONNECTION_STORE_H_ */ diff --git a/src/charon/charon/config/connections/local_connection_store.c b/src/charon/charon/config/connections/local_connection_store.c deleted file mode 100644 index 0ae18e0a7..000000000 --- a/src/charon/charon/config/connections/local_connection_store.c +++ /dev/null @@ -1,228 +0,0 @@ -/** - * @file local_connection_store.c - * - * @brief Implementation of local_connection_store_t. - * - */ - -/* - * Copyright (C) 2006 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 - -#include "local_connection_store.h" - -#include -#include - - -typedef struct private_local_connection_store_t private_local_connection_store_t; - -/** - * Private data of an local_connection_store_t object - */ -struct private_local_connection_store_t { - - /** - * Public part - */ - local_connection_store_t public; - - /** - * stored connection - */ - linked_list_t *connections; - - /** - * Assigned logger - */ - logger_t *logger; -}; - - -/** - * Implementation of connection_store_t.get_connection_by_hosts. - */ -static connection_t *get_connection_by_hosts(private_local_connection_store_t *this, host_t *my_host, host_t *other_host) -{ - iterator_t *iterator; - connection_t *current, *found = NULL; - - this->logger->log(this->logger, CONTROL|LEVEL1, "getting config for hosts %s - %s", - my_host->get_address(my_host), other_host->get_address(other_host)); - - iterator = this->connections->create_iterator(this->connections, TRUE); - while (iterator->has_next(iterator)) - { - host_t *config_my_host, *config_other_host; - - iterator->current(iterator, (void**)¤t); - - config_my_host = current->get_my_host(current); - config_other_host = current->get_other_host(current); - - /* first check if ip is equal */ - if(config_other_host->ip_equals(config_other_host, other_host)) - { - this->logger->log(this->logger, CONTROL|LEVEL2, "config entry with remote host %s", - config_other_host->get_address(config_other_host)); - /* could be right one, check my_host for default route*/ - if (config_my_host->is_default_route(config_my_host)) - { - found = current->clone(current); - break; - } - /* check now if host informations are the same */ - else if (config_my_host->ip_equals(config_my_host,my_host)) - { - found = current->clone(current); - break; - } - - } - /* Then check for wildcard hosts! - * TODO - * actually its only checked if other host with default route can be found! */ - else if (config_other_host->is_default_route(config_other_host)) - { - /* could be right one, check my_host for default route*/ - if (config_my_host->is_default_route(config_my_host)) - { - found = current->clone(current); - break; - } - /* check now if host informations are the same */ - else if (config_my_host->ip_equals(config_my_host,my_host)) - { - found = current->clone(current); - break; - } - } - } - iterator->destroy(iterator); - - /* apply hosts as they are supplied since my_host may be %defaultroute, and other_host may be %any. */ - if (found) - { - found->update_my_host(found, my_host->clone(my_host)); - found->update_other_host(found, other_host->clone(other_host)); - } - - return found; -} - -/** - * Implementation of connection_store_t.get_connection_by_ids. - */ -static connection_t *get_connection_by_ids(private_local_connection_store_t *this, identification_t *my_id, identification_t *other_id) -{ - iterator_t *iterator; - connection_t *current, *found = NULL; - - this->logger->log(this->logger, CONTROL|LEVEL1, "getting config for ids %s - %s", - my_id->get_string(my_id), other_id->get_string(other_id)); - - iterator = this->connections->create_iterator(this->connections, TRUE); - while (iterator->has_next(iterator)) - { - identification_t *config_my_id, *config_other_id; - - iterator->current(iterator, (void**)¤t); - - config_my_id = current->get_my_id(current); - config_other_id = current->get_other_id(current); - - /* first check if ids are equal - * TODO: Add wildcard checks */ - if (config_other_id->equals(config_other_id, other_id) && - config_my_id->equals(config_my_id, my_id)) - { - this->logger->log(this->logger, CONTROL|LEVEL2, "config entry with remote id %s", - config_other_id->get_string(config_other_id)); - found = current->clone(current); - break; - } - } - iterator->destroy(iterator); - - return found; -} - -/** - * Implementation of connection_store_t.get_connection_by_name. - */ -static connection_t *get_connection_by_name(private_local_connection_store_t *this, char *name) -{ - iterator_t *iterator; - connection_t *current, *found = NULL; - - iterator = this->connections->create_iterator(this->connections, TRUE); - while (iterator->has_next(iterator)) - { - iterator->current(iterator, (void**)¤t); - if (strcmp(name, current->get_name(current)) == 0) - { - found = current->clone(current); - break; - } - } - iterator->destroy(iterator); - - return found; -} - -/** - * Implementation of connection_store_t.add_connection. - */ -static status_t add_connection(private_local_connection_store_t *this, connection_t *connection) -{ - this->connections->insert_last(this->connections, connection); - return SUCCESS; -} - -/** - * Implementation of connection_store_t.destroy. - */ -static void destroy (private_local_connection_store_t *this) -{ - connection_t *connection; - - while (this->connections->remove_last(this->connections, (void**)&connection) == SUCCESS) - { - connection->destroy(connection); - } - this->connections->destroy(this->connections); - free(this); -} - -/** - * Described in header. - */ -local_connection_store_t * local_connection_store_create(void) -{ - private_local_connection_store_t *this = malloc_thing(private_local_connection_store_t); - - this->public.connection_store.get_connection_by_hosts = (connection_t*(*)(connection_store_t*,host_t*,host_t*))get_connection_by_hosts; - this->public.connection_store.get_connection_by_ids = (connection_t*(*)(connection_store_t*,identification_t*,identification_t*))get_connection_by_ids; - this->public.connection_store.get_connection_by_name = (connection_t*(*)(connection_store_t*,char*))get_connection_by_name; - this->public.connection_store.add_connection = (status_t(*)(connection_store_t*,connection_t*))add_connection; - this->public.connection_store.destroy = (void(*)(connection_store_t*))destroy; - - /* private variables */ - this->connections = linked_list_create(); - this->logger = logger_manager->get_logger(logger_manager, CONFIG); - - return (&this->public); -} diff --git a/src/charon/charon/config/connections/local_connection_store.h b/src/charon/charon/config/connections/local_connection_store.h deleted file mode 100644 index 6e73ef945..000000000 --- a/src/charon/charon/config/connections/local_connection_store.h +++ /dev/null @@ -1,63 +0,0 @@ -/** - * @file local_connection_store.h - * - * @brief Interface of local_connection_store_t. - * - */ - -/* - * Copyright (C) 2006 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef LOCAL_CONNECTION_H_ -#define LOCAL_CONNECTION_H_ - -#include -#include - - -typedef struct local_connection_store_t local_connection_store_t; - -/** - * @brief A connection_store_t implementation using a simple connection list. - * - * The local_connection_store_t class implements the connection_store_t interface - * as simple as possible. connection_t's are stored in an in-memory list. - * - * @b Constructors: - * - local_connection_store_create() - * - * @todo Make thread-save first - * @todo Add remove_connection method - * - * @ingroup config - */ -struct local_connection_store_t { - - /** - * Implements connection_store_t interface - */ - connection_store_t connection_store; -}; - -/** - * @brief Creates a local_connection_store_t instance. - * - * @return connection store instance. - * - * @ingroup config - */ -local_connection_store_t * local_connection_store_create(void); - -#endif /* LOCAL_CONNECTION_H_ */ diff --git a/src/charon/charon/config/credentials/Makefile.credentials b/src/charon/charon/config/credentials/Makefile.credentials deleted file mode 100644 index 720d56656..000000000 --- a/src/charon/charon/config/credentials/Makefile.credentials +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright (C) 2006 Martin Willi -# Hochschule fuer Technik Rapperswil -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. See . -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# for more details. -# - -CREDENTIALS_DIR= $(CONFIG_DIR)credentials/ - - -CHARON_OBJS+= $(BUILD_DIR)local_credential_store.o -$(BUILD_DIR)local_credential_store.o : $(CREDENTIALS_DIR)local_credential_store.c $(CREDENTIALS_DIR)local_credential_store.h - $(CC) $(CFLAGS) -c -o $@ $< diff --git a/src/charon/charon/config/credentials/credential_store.h b/src/charon/charon/config/credentials/credential_store.h deleted file mode 100755 index 2339469c0..000000000 --- a/src/charon/charon/config/credentials/credential_store.h +++ /dev/null @@ -1,91 +0,0 @@ -/** - * @file credential_store.h - * - * @brief Interface credential_store_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef CREDENTIAL_STORE_H_ -#define CREDENTIAL_STORE_H_ - -#include -#include -#include -#include - - -typedef struct credential_store_t credential_store_t; - -/** - * @brief The interface for a credential_store backend. - * - * @b Constructors: - * - stroke_create() - * - * @ingroup config - */ -struct credential_store_t { - - /** - * @brief Returns the preshared secret of a specific ID. - * - * The returned chunk must be destroyed by the caller after usage. - * - * @param this calling object - * @param identification identification_t object identifiying the secret. - * @param[out] preshared_secret the preshared secret will be written there. - * @return - * - NOT_FOUND if no preshared secrets for specific ID could be found - * - SUCCESS - * - * @todo We should use two IDs to query shared secrets, since we want to use different - * keys for different peers... - */ - status_t (*get_shared_secret) (credential_store_t *this, identification_t *identification, chunk_t *preshared_secret); - - /** - * @brief Returns the RSA public key of a specific ID. - * - * The returned rsa_public_key_t must be destroyed by the caller after usage. - * - * @param this calling object - * @param identification identification_t object identifiying the key. - * @return public key, or NULL if not found - */ - rsa_public_key_t * (*get_rsa_public_key) (credential_store_t *this, identification_t *identification); - - /** - * @brief Returns the RSA private key of a specific ID. - * - * The returned rsa_private_key_t must be destroyed by the caller after usage. - * - * @param this calling object - * @param identification identification_t object identifiying the key - * @return private key, or NULL if not found - */ - rsa_private_key_t *(*get_rsa_private_key) (credential_store_t *this, identification_t *identification); - - /** - * @brief Destroys a credential_store_t object. - * - * @param this calling object - */ - void (*destroy) (credential_store_t *this); -}; - -#endif /*CREDENTIAL_STORE_H_*/ diff --git a/src/charon/charon/config/credentials/local_credential_store.c b/src/charon/charon/config/credentials/local_credential_store.c deleted file mode 100644 index 2554eec4a..000000000 --- a/src/charon/charon/config/credentials/local_credential_store.c +++ /dev/null @@ -1,381 +0,0 @@ -/** - * @file local_credential_store.c - * - * @brief Implementation of local_credential_store_t. - * - */ - -/* - * Copyright (C) 2006 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 -#include -#include - -#include "local_credential_store.h" - -#include -#include -#include -#include - -#define PATH_BUF 256 - -typedef struct key_entry_t key_entry_t; - -/** - * Private key with an associated ID to find it - */ -struct key_entry_t { - - /** - * ID, as added - */ - identification_t *id; - - /** - * Associated rsa private key - */ - rsa_private_key_t *key; -}; - - -typedef struct private_local_credential_store_t private_local_credential_store_t; - -/** - * Private data of an local_credential_store_t object - */ -struct private_local_credential_store_t { - - /** - * Public part - */ - local_credential_store_t public; - - /** - * list of key_entry_t's with private keys - */ - linked_list_t *private_keys; - - /** - * list of x509 certificates with public keys - */ - linked_list_t *certificates; - - /** - * Assigned logger - */ - logger_t *logger; -}; - - -/** - * Implementation of credential_store_t.get_shared_secret. - */ -static status_t get_shared_secret(private_local_credential_store_t *this, identification_t *identification, chunk_t *preshared_secret) -{ - return FAILED; -} - -/** - * Implementation of credential_store_t.get_rsa_public_key. - */ -static rsa_public_key_t * get_rsa_public_key(private_local_credential_store_t *this, identification_t *identification) -{ - x509_t *current; - rsa_public_key_t *found = NULL; - iterator_t *iterator; - - this->logger->log(this->logger, CONTROL|LEVEL2, "Looking for public key for %s", - identification->get_string(identification)); - iterator = this->certificates->create_iterator(this->certificates, TRUE); - while (iterator->has_next(iterator)) - { - iterator->current(iterator, (void**)¤t); - identification_t *stored = current->get_subject(current); - this->logger->log(this->logger, CONTROL|LEVEL2, "there is one for %s", - stored->get_string(stored)); - if (identification->equals(identification, stored)) - { - found = current->get_public_key(current); - break; - } - } - iterator->destroy(iterator); - return found; -} - -/** - * Implementation of credential_store_t.get_rsa_private_key. - */ -static rsa_private_key_t *get_rsa_private_key(private_local_credential_store_t *this, identification_t *identification) -{ - rsa_private_key_t *found = NULL; - key_entry_t *current; - iterator_t *iterator; - - iterator = this->private_keys->create_iterator(this->private_keys, TRUE); - while (iterator->has_next(iterator)) - { - iterator->current(iterator, (void**)¤t); - if (identification->equals(identification, current->id)) - { - found = current->key->clone(current->key); - break; - } - } - iterator->destroy(iterator); - return found; -} - -/** - * Implements local_credential_store_t.load_certificates - */ -static void load_certificates(private_local_credential_store_t *this, const char *path) -{ - struct dirent* entry; - struct stat stb; - DIR* dir; - x509_t *cert; - - dir = opendir(path); - if (dir == NULL) { - this->logger->log(this->logger, ERROR, "error opening certificate directory \"%s\"", path); - return; - } - while ((entry = readdir(dir)) != NULL) - { - char file[PATH_BUF]; - - snprintf(file, sizeof(file), "%s/%s", path, entry->d_name); - - if (stat(file, &stb) == -1) - { - continue; - } - /* try to parse all regular files */ - if (stb.st_mode & S_IFREG) - { - cert = x509_create_from_file(file); - if (cert) - { - this->certificates->insert_last(this->certificates, (void*)cert); - } - else - { - this->logger->log(this->logger, ERROR, "certificate \"%s\" invalid, skipped", file); - } - } - } - closedir(dir); -} - -/** - * Query the ID for a private key, by doing a lookup in the certificates - */ -static identification_t *get_id_for_private_key(private_local_credential_store_t *this, rsa_private_key_t *private_key) -{ - iterator_t *iterator; - x509_t *cert; - identification_t *found = NULL; - rsa_public_key_t *public_key; - - this->logger->log(this->logger, CONTROL|LEVEL2, "Getting ID for a private key..."); - - iterator = this->certificates->create_iterator(this->certificates, TRUE); - while (!found && iterator->has_next(iterator)) - { - iterator->current(iterator, (void**)&cert); - public_key = cert->get_public_key(cert); - if (public_key) - { - if (private_key->belongs_to(private_key, public_key)) - { - this->logger->log(this->logger, CONTROL|LEVEL2, "found a match"); - found = cert->get_subject(cert); - found = found->clone(found); - } - else - { - this->logger->log(this->logger, CONTROL|LEVEL3, "this one did not match"); - } - public_key->destroy(public_key); - } - } - iterator->destroy(iterator); - return found; -} - -/** - * Implements local_credential_store_t.load_private_keys - */ -static void load_private_keys(private_local_credential_store_t *this, const char *secretsfile, const char *defaultpath) -{ - FILE *fd = fopen(secretsfile, "r"); - - if (fd) - { - int bytes; - int line_nr = 0; - chunk_t chunk, src, line; - - this->logger->log(this->logger, CONTROL, "loading secrets from \"%s\"", secretsfile); - - fseek(fd, 0, SEEK_END); - chunk.len = ftell(fd); - rewind(fd); - chunk.ptr = malloc(chunk.len); - bytes = fread(chunk.ptr, 1, chunk.len, fd); - fclose(fd); - - src = chunk; - - while (fetchline(&src, &line)) - { - chunk_t ids, token; - - line_nr++; - - if (!eat_whitespace(&line)) - { - continue; - } - if (!extract_token(&ids, ':', &line)) - { - this->logger->log(this->logger, ERROR, "line %d: missing ':' separator", line_nr); - goto error; - } - if (!eat_whitespace(&line) || !extract_token(&token, ' ', &line)) - { - this->logger->log(this->logger, ERROR, "line %d: missing token", line_nr); - goto error; - } - if (match("RSA", &token)) - { - char path[PATH_BUF]; - chunk_t filename; - - err_t ugh = extract_value(&filename, &line); - - if (ugh != NULL) - { - this->logger->log(this->logger, ERROR, "line %d: %s", line_nr, ugh); - goto error; - } - if (filename.len == 0) - { - this->logger->log(this->logger, ERROR, - "line %d: empty filename", line_nr); - goto error; - } - if (*filename.ptr == '/') - { - /* absolute path name */ - snprintf(path, sizeof(path), "%.*s", filename.len, filename.ptr); - } - else - { - /* relative path name */ - snprintf(path, sizeof(path), "%s/%.*s", defaultpath, filename.len, filename.ptr); - } - - rsa_private_key_t *key = rsa_private_key_create_from_file(path, NULL); - if (key) - { - key_entry_t *entry; - identification_t *id = get_id_for_private_key(this, key); - - if (!id) - { - this->logger->log(this->logger, ERROR, - "no certificate found for private key \"%s\", skipped", path); - key->destroy(key); - continue; - } - entry = malloc_thing(key_entry_t); - entry->key = key; - entry->id = id; - this->private_keys->insert_last(this->private_keys, (void*)entry); - } - } - else if (match("PSK", &token)) - { - - } - else if (match("PIN", &token)) - { - - } - else - { - this->logger->log(this->logger, ERROR, - "line %d: token must be either RSA, PSK, or PIN", - line_nr, token.len); - goto error; - } - } -error: - free(chunk.ptr); - } - else - { - this->logger->log(this->logger, ERROR, "could not open file '%s'", secretsfile); - } -} - -/** - * Implementation of credential_store_t.destroy. - */ -static void destroy(private_local_credential_store_t *this) -{ - x509_t *certificate; - key_entry_t *key_entry; - - while (this->certificates->remove_last(this->certificates, (void**)&certificate) == SUCCESS) - { - certificate->destroy(certificate); - } - this->certificates->destroy(this->certificates); - while (this->private_keys->remove_last(this->private_keys, (void**)&key_entry) == SUCCESS) - { - key_entry->id->destroy(key_entry->id); - key_entry->key->destroy(key_entry->key); - free(key_entry); - } - this->private_keys->destroy(this->private_keys); - free(this); -} - -/** - * Described in header. - */ -local_credential_store_t * local_credential_store_create(void) -{ - private_local_credential_store_t *this = malloc_thing(private_local_credential_store_t); - - this->public.credential_store.get_shared_secret = (status_t(*)(credential_store_t*,identification_t*,chunk_t*))get_shared_secret; - this->public.credential_store.get_rsa_private_key = (rsa_private_key_t*(*)(credential_store_t*,identification_t*))get_rsa_private_key; - this->public.credential_store.get_rsa_public_key = (rsa_public_key_t*(*)(credential_store_t*,identification_t*))get_rsa_public_key; - this->public.load_certificates = (void(*)(local_credential_store_t*,const char*))load_certificates; - this->public.load_private_keys = (void(*)(local_credential_store_t*,const char*, const char*))load_private_keys; - this->public.credential_store.destroy = (void(*)(credential_store_t*))destroy; - - /* private variables */ - this->private_keys = linked_list_create(); - this->certificates = linked_list_create(); - this->logger = logger_manager->get_logger(logger_manager, CONFIG); - - return (&this->public); -} diff --git a/src/charon/charon/config/credentials/local_credential_store.h b/src/charon/charon/config/credentials/local_credential_store.h deleted file mode 100644 index 81b7568d7..000000000 --- a/src/charon/charon/config/credentials/local_credential_store.h +++ /dev/null @@ -1,85 +0,0 @@ -/** - * @file local_credential_store.h - * - * @brief Interface of local_credential_store_t. - * - */ - -/* - * Copyright (C) 2006 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef LOCAL_CREDENTIAL_H_ -#define LOCAL_CREDENTIAL_H_ - -#include -#include - - -typedef struct local_credential_store_t local_credential_store_t; - -/** - * @brief A credential_store_t implementation using simple credentail lists. - * - * The local_credential_store_t class implements the credential_store_t interface - * as simple as possible. The credentials are stored in lists, and can be loaded - * from folders. - * Shared secret are not handled yet, so get_shared_secret always returns NOT_FOUND. - * - * @b Constructors: - * - local_credential_store_create() - * - * @ingroup config - */ -struct local_credential_store_t { - - /** - * Implements credential_store_t interface - */ - credential_store_t credential_store; - - /** - * @brief Loads trusted certificates from a folder. - * - * Currently, all keys must be in binary DER format. - * - * @param this calling object - * @param path directory to load certificates from - */ - void (*load_certificates) (local_credential_store_t *this, const char *path); - - /** - * @brief Loads RSA private keys from a folder. - * - * Currently, all keys must be unencrypted in binary DER format. Anything - * other gets ignored. Further, a certificate for the specific private - * key must already be loaded to get the ID from. - * - * @param this calling object - * @param secretsfile file where secrets are stored - * @param defaultpath default directory for private keys - */ - void (*load_private_keys) (local_credential_store_t *this, const char *secretsfile, const char *defaultpath); -}; - -/** - * @brief Creates a local_credential_store_t instance. - * - * @return credential store instance. - * - * @ingroup config - */ -local_credential_store_t *local_credential_store_create(void); - -#endif /* LOCAL_CREDENTIAL_H_ */ diff --git a/src/charon/charon/config/policies/Makefile.policies b/src/charon/charon/config/policies/Makefile.policies deleted file mode 100644 index e7ed8ab13..000000000 --- a/src/charon/charon/config/policies/Makefile.policies +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (C) 2006 Martin Willi -# Hochschule fuer Technik Rapperswil -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. See . -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# for more details. -# - -POLICIES_DIR= $(CONFIG_DIR)policies/ - - -CHARON_OBJS+= $(BUILD_DIR)policy.o -$(BUILD_DIR)policy.o : $(POLICIES_DIR)policy.c $(POLICIES_DIR)policy.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)local_policy_store.o -$(BUILD_DIR)local_policy_store.o : $(POLICIES_DIR)local_policy_store.c $(POLICIES_DIR)local_policy_store.h - $(CC) $(CFLAGS) -c -o $@ $< \ No newline at end of file diff --git a/src/charon/charon/config/policies/local_policy_store.c b/src/charon/charon/config/policies/local_policy_store.c deleted file mode 100644 index 24d22f485..000000000 --- a/src/charon/charon/config/policies/local_policy_store.c +++ /dev/null @@ -1,136 +0,0 @@ -/** - * @file local_policy_store.c - * - * @brief Implementation of local_policy_store_t. - * - */ - -/* - * Copyright (C) 2006 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 "local_policy_store.h" - -#include -#include - - -typedef struct private_local_policy_store_t private_local_policy_store_t; - -/** - * Private data of an local_policy_store_t object - */ -struct private_local_policy_store_t { - - /** - * Public part - */ - local_policy_store_t public; - - /** - * list of policy_t's - */ - linked_list_t *policies; - - /** - * Assigned logger - */ - logger_t *logger; -}; - -/** - * Implementation of policy_store_t.add_policy. - */ -static void add_policy(private_local_policy_store_t *this, policy_t *policy) -{ - this->policies->insert_last(this->policies, (void*)policy); -} - - -/** - * Implementation of policy_store_t.get_policy. - */ -static policy_t *get_policy(private_local_policy_store_t *this, identification_t *my_id, identification_t *other_id) -{ - iterator_t *iterator; - policy_t *current, *found = NULL; - - this->logger->log(this->logger, CONTROL|LEVEL1, "Looking for policy for IDs %s - %s", - my_id ? my_id->get_string(my_id) : "%any", - other_id->get_string(other_id)); - iterator = this->policies->create_iterator(this->policies, TRUE); - while (iterator->has_next(iterator)) - { - iterator->current(iterator, (void **)¤t); - identification_t *config_my_id = current->get_my_id(current); - identification_t *config_other_id = current->get_other_id(current); - - this->logger->log(this->logger, CONTROL|LEVEL2, "Found one for %s - %s", - config_my_id->get_string(config_my_id), - config_other_id->get_string(config_other_id)); - - /* check other host first */ - if (other_id->belongs_to(other_id, config_other_id)) - { - /* get it if my_id not specified */ - if (my_id->belongs_to(my_id, config_my_id)) - { - found = current->clone(current); - break; - } - } - } - iterator->destroy(iterator); - - /* apply IDs as they are requsted, since they may be configured as %any or such */ - if (found) - { - found->update_my_id(found, my_id->clone(my_id)); - found->update_other_id(found, other_id->clone(other_id)); - } - return found; -} - -/** - * Implementation of policy_store_t.destroy. - */ -static void destroy(private_local_policy_store_t *this) -{ - policy_t *policy; - - while (this->policies->remove_last(this->policies, (void**)&policy) == SUCCESS) - { - policy->destroy(policy); - } - this->policies->destroy(this->policies); - free(this); -} - -/** - * Described in header. - */ -local_policy_store_t *local_policy_store_create(void) -{ - private_local_policy_store_t *this = malloc_thing(private_local_policy_store_t); - - this->public.policy_store.add_policy = (void(*)(policy_store_t*,policy_t*))add_policy; - this->public.policy_store.get_policy = (policy_t*(*)(policy_store_t*,identification_t*,identification_t*))get_policy; - this->public.policy_store.destroy = (void(*)(policy_store_t*))destroy; - - /* private variables */ - this->policies = linked_list_create(); - this->logger = logger_manager->get_logger(logger_manager, CONFIG); - - return (&this->public); -} diff --git a/src/charon/charon/config/policies/local_policy_store.h b/src/charon/charon/config/policies/local_policy_store.h deleted file mode 100644 index ce9b33d71..000000000 --- a/src/charon/charon/config/policies/local_policy_store.h +++ /dev/null @@ -1,60 +0,0 @@ -/** - * @file local_policy_store.h - * - * @brief Interface of local_policy_store_t. - * - */ - -/* - * Copyright (C) 2006 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef LOCAL_POLICY_STORE_H_ -#define LOCAL_POLICY_STORE_H_ - -#include -#include - - -typedef struct local_policy_store_t local_policy_store_t; - -/** - * @brief A policy_store_t implementation using a simple policy lists. - * - * The local_policy_store_t class implements the policy_store_t interface - * as simple as possible. The policies are stored in a in-memory list. - * - * @b Constructors: - * - local_policy_store_create() - * - * @ingroup config - */ -struct local_policy_store_t { - - /** - * Implements policy_store_t interface - */ - policy_store_t policy_store; -}; - -/** - * @brief Creates a local_policy_store_t instance. - * - * @return policy store instance. - * - * @ingroup config - */ -local_policy_store_t *local_policy_store_create(void); - -#endif /* LOCAL_POLICY_STORE_H_ */ diff --git a/src/charon/charon/config/policies/policy.c b/src/charon/charon/config/policies/policy.c deleted file mode 100644 index cff87fc6b..000000000 --- a/src/charon/charon/config/policies/policy.c +++ /dev/null @@ -1,397 +0,0 @@ -/** - * @file policy.c - * - * @brief Implementation of policy_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 "policy.h" - -#include -#include -#include - -typedef struct private_policy_t private_policy_t; - -/** - * Private data of an policy_t object - */ -struct private_policy_t { - - /** - * Public part - */ - policy_t public; - - /** - * id to use to identify us - */ - identification_t *my_id; - - /** - * allowed id for other - */ - identification_t *other_id; - - /** - * list for all proposals - */ - linked_list_t *proposals; - - /** - * list for traffic selectors for my site - */ - linked_list_t *my_ts; - - /** - * list for traffic selectors for others site - */ - linked_list_t *other_ts; - - /** - * select_traffic_selectors for both - */ - linked_list_t *(*select_traffic_selectors) (private_policy_t *,linked_list_t*,linked_list_t*); -}; - -/** - * Implementation of policy_t.get_my_id - */ -static identification_t *get_my_id(private_policy_t *this) -{ - return this->my_id; -} - -/** - * Implementation of policy_t.get_other_id - */ -static identification_t *get_other_id(private_policy_t *this) -{ - return this->other_id; -} - -/** - * Implementation of policy_t.update_my_id - */ -static void update_my_id(private_policy_t *this, identification_t *my_id) -{ - this->my_id->destroy(this->my_id); - this->my_id = my_id; -} - -/** - * Implementation of policy_t.update_other_id - */ -static void update_other_id(private_policy_t *this, identification_t *other_id) -{ - this->other_id->destroy(this->other_id); - this->other_id = other_id; -} - -/** - * Helper function which does the work for policy_t.update_my_ts and update_other_ts - */ -static void update_ts(linked_list_t* list, host_t *new_host) -{ - traffic_selector_t *ts; - iterator_t *iterator; - - iterator = list->create_iterator(list, TRUE); - while (iterator->has_next(iterator)) - { - iterator->current(iterator, (void**)&ts); - ts->update_address_range(ts, new_host); - } - iterator->destroy(iterator); -} - -/** - * Implementation of policy_t.update_my_id - */ -static void update_my_ts(private_policy_t *this, host_t *my_host) -{ - update_ts(this->my_ts, my_host); -} - -/** - * Implementation of policy_t.update_other_ts - */ -static void update_other_ts(private_policy_t *this, host_t *my_host) -{ - update_ts(this->other_ts, my_host); -} - -/** - * Implementation of policy_t.get_my_traffic_selectors - */ -static linked_list_t *get_my_traffic_selectors(private_policy_t *this) -{ - return this->my_ts; -} - -/** - * Implementation of policy_t.get_other_traffic_selectors - */ -static linked_list_t *get_other_traffic_selectors(private_policy_t *this, traffic_selector_t **traffic_selectors[]) -{ - return this->other_ts; -} - -/** - * Implementation of private_policy_t.select_my_traffic_selectors - */ -static linked_list_t *select_my_traffic_selectors(private_policy_t *this, linked_list_t *supplied) -{ - return this->select_traffic_selectors(this, this->my_ts, supplied); -} - -/** - * Implementation of private_policy_t.select_other_traffic_selectors - */ -static linked_list_t *select_other_traffic_selectors(private_policy_t *this, linked_list_t *supplied) -{ - return this->select_traffic_selectors(this, this->other_ts, supplied); -} -/** - * Implementation of private_policy_t.select_traffic_selectors - */ -static linked_list_t *select_traffic_selectors(private_policy_t *this, linked_list_t *stored, linked_list_t *supplied) -{ - iterator_t *supplied_iter, *stored_iter; - traffic_selector_t *supplied_ts, *stored_ts, *selected_ts; - linked_list_t *selected = linked_list_create(); - - - stored_iter = stored->create_iterator(stored, TRUE); - supplied_iter = supplied->create_iterator(supplied, TRUE); - - /* iterate over all stored selectors */ - while (stored_iter->has_next(stored_iter)) - { - stored_iter->current(stored_iter, (void**)&stored_ts); - - supplied_iter->reset(supplied_iter); - /* iterate over all supplied traffic selectors */ - while (supplied_iter->has_next(supplied_iter)) - { - supplied_iter->current(supplied_iter, (void**)&supplied_ts); - - selected_ts = stored_ts->get_subset(stored_ts, supplied_ts); - if (selected_ts) - { - /* got a match, add to list */ - selected->insert_last(selected, (void*)selected_ts); - } - } - } - stored_iter->destroy(stored_iter); - supplied_iter->destroy(supplied_iter); - - return selected; -} - -/** - * Implementation of policy_t.get_proposal_iterator - */ -static linked_list_t *get_proposals(private_policy_t *this) -{ - return this->proposals; -} - -/** - * Implementation of policy_t.select_proposal - */ -static proposal_t *select_proposal(private_policy_t *this, linked_list_t *proposals) -{ - iterator_t *stored_iter, *supplied_iter; - proposal_t *stored, *supplied, *selected; - - stored_iter = this->proposals->create_iterator(this->proposals, TRUE); - supplied_iter = proposals->create_iterator(proposals, TRUE); - - /* compare all stored proposals with all supplied. Stored ones are preferred. */ - while (stored_iter->has_next(stored_iter)) - { - supplied_iter->reset(supplied_iter); - stored_iter->current(stored_iter, (void**)&stored); - - while (supplied_iter->has_next(supplied_iter)) - { - supplied_iter->current(supplied_iter, (void**)&supplied); - selected = stored->select(stored, supplied); - if (selected) - { - /* they match, return */ - stored_iter->destroy(stored_iter); - supplied_iter->destroy(supplied_iter); - return selected; - } - } - } - - /* no proposal match :-(, will result in a NO_PROPOSAL_CHOSEN... */ - stored_iter->destroy(stored_iter); - supplied_iter->destroy(supplied_iter); - - return NULL; -} - -/** - * Implementation of policy_t.add_my_traffic_selector - */ -static void add_my_traffic_selector(private_policy_t *this, traffic_selector_t *traffic_selector) -{ - this->my_ts->insert_last(this->my_ts, (void*)traffic_selector); -} - -/** - * Implementation of policy_t.add_other_traffic_selector - */ -static void add_other_traffic_selector(private_policy_t *this, traffic_selector_t *traffic_selector) -{ - this->other_ts->insert_last(this->other_ts, (void*)traffic_selector); -} - -/** - * Implementation of policy_t.add_proposal - */ -static void add_proposal(private_policy_t *this, proposal_t *proposal) -{ - this->proposals->insert_last(this->proposals, (void*)proposal); -} - -/** - * Implements policy_t.destroy. - */ -static status_t destroy(private_policy_t *this) -{ - proposal_t *proposal; - traffic_selector_t *traffic_selector; - - - /* delete proposals */ - while(this->proposals->remove_last(this->proposals, (void**)&proposal) == SUCCESS) - { - proposal->destroy(proposal); - } - this->proposals->destroy(this->proposals); - - /* delete traffic selectors */ - while(this->my_ts->remove_last(this->my_ts, (void**)&traffic_selector) == SUCCESS) - { - traffic_selector->destroy(traffic_selector); - } - this->my_ts->destroy(this->my_ts); - - /* delete traffic selectors */ - while(this->other_ts->remove_last(this->other_ts, (void**)&traffic_selector) == SUCCESS) - { - traffic_selector->destroy(traffic_selector); - } - this->other_ts->destroy(this->other_ts); - - /* delete ids */ - this->my_id->destroy(this->my_id); - this->other_id->destroy(this->other_id); - - free(this); - return SUCCESS; -} - -/** - * Implements policy_t.clone. - */ -static policy_t *clone(private_policy_t *this) -{ - private_policy_t *clone = (private_policy_t*)policy_create(this->my_id->clone(this->my_id), - this->other_id->clone(this->other_id)); - iterator_t *iterator; - proposal_t *proposal; - traffic_selector_t *ts; - - /* clone all proposals */ - iterator = this->proposals->create_iterator(this->proposals, TRUE); - while (iterator->has_next(iterator)) - { - iterator->current(iterator, (void**)&proposal); - proposal = proposal->clone(proposal); - clone->proposals->insert_last(clone->proposals, (void*)proposal); - } - iterator->destroy(iterator); - - /* clone all local traffic selectors */ - iterator = this->my_ts->create_iterator(this->my_ts, TRUE); - while (iterator->has_next(iterator)) - { - iterator->current(iterator, (void**)&ts); - ts = ts->clone(ts); - clone->my_ts->insert_last(clone->my_ts, (void*)ts); - } - iterator->destroy(iterator); - - /* clone all remote traffic selectors */ - iterator = this->other_ts->create_iterator(this->other_ts, TRUE); - while (iterator->has_next(iterator)) - { - iterator->current(iterator, (void**)&ts); - ts = ts->clone(ts); - clone->other_ts->insert_last(clone->other_ts, (void*)ts); - } - iterator->destroy(iterator); - - return &clone->public; -} - -/* - * Described in header-file - */ -policy_t *policy_create(identification_t *my_id, identification_t *other_id) -{ - private_policy_t *this = malloc_thing(private_policy_t); - - /* public functions */ - this->public.get_my_id = (identification_t*(*)(policy_t*))get_my_id; - this->public.get_other_id = (identification_t*(*)(policy_t*))get_other_id; - this->public.update_my_id = (void(*)(policy_t*,identification_t*))update_my_id; - this->public.update_other_id = (void(*)(policy_t*,identification_t*))update_other_id; - this->public.update_my_ts = (void(*)(policy_t*,host_t*))update_my_ts; - this->public.update_other_ts = (void(*)(policy_t*,host_t*))update_other_ts; - this->public.get_my_traffic_selectors = (linked_list_t*(*)(policy_t*))get_my_traffic_selectors; - this->public.select_my_traffic_selectors = (linked_list_t*(*)(policy_t*,linked_list_t*))select_my_traffic_selectors; - this->public.get_other_traffic_selectors = (linked_list_t*(*)(policy_t*))get_other_traffic_selectors; - this->public.select_other_traffic_selectors = (linked_list_t*(*)(policy_t*,linked_list_t*))select_other_traffic_selectors; - this->public.get_proposals = (linked_list_t*(*)(policy_t*))get_proposals; - this->public.select_proposal = (proposal_t*(*)(policy_t*,linked_list_t*))select_proposal; - this->public.add_my_traffic_selector = (void(*)(policy_t*,traffic_selector_t*))add_my_traffic_selector; - this->public.add_other_traffic_selector = (void(*)(policy_t*,traffic_selector_t*))add_other_traffic_selector; - this->public.add_proposal = (void(*)(policy_t*,proposal_t*))add_proposal; - this->public.clone = (policy_t*(*)(policy_t*))clone; - this->public.destroy = (void(*)(policy_t*))destroy; - - /* apply init values */ - this->my_id = my_id; - this->other_id = other_id; - - /* init private members*/ - this->select_traffic_selectors = select_traffic_selectors; - this->proposals = linked_list_create(); - this->my_ts = linked_list_create(); - this->other_ts = linked_list_create(); - - return (&this->public); -} diff --git a/src/charon/charon/config/policies/policy.h b/src/charon/charon/config/policies/policy.h deleted file mode 100644 index 78cda1e8b..000000000 --- a/src/charon/charon/config/policies/policy.h +++ /dev/null @@ -1,249 +0,0 @@ -/** - * @file policy.h - * - * @brief Interface of policy_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef POLICY_H_ -#define POLICY_H_ - -#include -#include -#include -#include -#include - - -typedef struct policy_t policy_t; - -/** - * @brief A policy_t defines the policies to apply to CHILD_SAs. - * - * The given two IDs identify a policy. These rules define how - * child SAs may be set up and which traffic may be IPsec'ed. - * - * @b Constructors: - * - policy_create() - * - * @ingroup config - */ -struct policy_t { - - /** - * @brief Get own id to use for identification. - * - * Returned object is not getting cloned. - * - * @param this calling object - * @return own id - */ - identification_t *(*get_my_id) (policy_t *this); - - /** - * @brief Get id of communication partner. - * - * Returned object is not getting cloned. - * - * @param this calling object - * @return other id - */ - identification_t *(*get_other_id) (policy_t *this); - - /** - * @brief Update own ID. - * - * It may be necessary to uptdate own ID, as it - * is set to %any or to e.g. *@strongswan.org in - * some cases. - * Old ID is destroyed, new one NOT cloned. - * - * @param this calling object - * @param my_id new ID to set as my_id - */ - void (*update_my_id) (policy_t *this, identification_t *my_id); - - /** - * @brief Update others ID. - * - * It may be necessary to uptdate others ID, as it - * is set to %any or to e.g. *@strongswan.org in - * some cases. - * Old ID is destroyed, new one NOT cloned. - * - * @param this calling object - * @param other_id new ID to set as other_id - */ - void (*update_other_id) (policy_t *this, identification_t *other_id); - - /** - * @brief Update own address in traffic selectors. - * - * Update own 0.0.0.0 address in traffic selectors - * with supplied one. The size of the subnet will be - * set to /32. - * - * @param this calling object - * @param my_host new address to set in traffic selectors - */ - void (*update_my_ts) (policy_t *this, host_t *my_host); - - /** - * @brief Update others address in traffic selectors. - * - * Update remote 0.0.0.0 address in traffic selectors - * with supplied one. The size of the subnet will be - * set to /32. - * - * @param this calling object - * @param other_host new address to set in traffic selectors - */ - void (*update_other_ts) (policy_t *this, host_t *other_host); - - /** - * @brief Get configured traffic selectors for our site. - * - * Returns a list with all traffic selectors for the local - * site. List and items MUST NOT be freed nor modified. - * - * @param this calling object - * @return list with traffic selectors - */ - linked_list_t *(*get_my_traffic_selectors) (policy_t *this); - - /** - * @brief Get configured traffic selectors for others site. - * - * Returns a list with all traffic selectors for the remote - * site. List and items MUST NOT be freed nor modified. - * - * @param this calling object - * @return list with traffic selectors - */ - linked_list_t *(*get_other_traffic_selectors) (policy_t *this); - - /** - * @brief Select traffic selectors from a supplied list for local site. - * - * Resulted list and traffic selectors must be destroyed after usage. - * - * @param this calling object - * @param supplied linked list with traffic selectors - * @return list containing the selected traffic selectors - */ - linked_list_t *(*select_my_traffic_selectors) (policy_t *this, linked_list_t *supplied); - - /** - * @brief Select traffic selectors from a supplied list for remote site. - * - * Resulted list and traffic selectors must be destroyed after usage. - * - * @param this calling object - * @param supplied linked list with traffic selectors - * @return list containing the selected traffic selectors - */ - linked_list_t *(*select_other_traffic_selectors) (policy_t *this, linked_list_t *supplied); - - /** - * @brief Get the list of internally stored proposals. - * - * Rembember: policy_t does store proposals for AH/ESP, - * IKE proposals are in the connection_t - * - * @warning List and Items are still owned by policy and MUST NOT - * be manipulated or freed! - * - * @param this calling object - * @return lists with proposals - */ - linked_list_t *(*get_proposals) (policy_t *this); - - /** - * @brief Select a proposal from a supplied list. - * - * @param this calling object - * @param proposals list from from wich proposals are selected - * @return selected proposal, or NULL if nothing matches - */ - proposal_t *(*select_proposal) (policy_t *this, linked_list_t *proposals); - - /** - * @brief Add a traffic selector to the list for local site. - * - * After add, proposal is owned by policy. - * - * @warning Do not add while other threads are reading. - * - * @param this calling object - * @param traffic_selector traffic_selector to add - */ - void (*add_my_traffic_selector) (policy_t *this, traffic_selector_t *traffic_selector); - - /** - * @brief Add a traffic selector to the list for remote site. - * - * After add, proposal is owned by policy. - * - * @warning Do not add while other threads are reading. - * - * @param this calling object - * @param traffic_selector traffic_selector to add - */ - void (*add_other_traffic_selector) (policy_t *this, traffic_selector_t *traffic_selector); - - /** - * @brief Add a proposal to the list. - * - * The proposals are stored by priority, first added - * is the most prefered. - * - * @warning Do not add while other threads are reading. - * - * @param this calling object - * @param proposal proposal to add - */ - void (*add_proposal) (policy_t *this, proposal_t *proposal); - - /** - * @brief Clone a policy. - * - * @param this policy to clone - * @return clone of it - */ - policy_t *(*clone) (policy_t *this); - - /** - * @brief Destroys the policy object - * - * @param this calling object - */ - void (*destroy) (policy_t *this); -}; - -/** - * @brief Create a configuration object for IKE_AUTH and later. - * - * @param my_id identification_t for ourselves - * @param other_id identification_t for the remote guy - * @return policy_t object - * - * @ingroup config - */ -policy_t *policy_create(identification_t *my_id, identification_t *other_id); - -#endif /* POLICY_H_ */ diff --git a/src/charon/charon/config/policies/policy_store.h b/src/charon/charon/config/policies/policy_store.h deleted file mode 100755 index 651dea634..000000000 --- a/src/charon/charon/config/policies/policy_store.h +++ /dev/null @@ -1,76 +0,0 @@ -/** - * @file policy_store.h - * - * @brief Interface policy_store_t. - * - */ - -/* - * Copyright (C) 2006 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef POLICY_STORE_H_ -#define POLICY_STORE_H_ - -#include -#include - - -typedef struct policy_store_t policy_store_t; - -/** - * @brief The interface for a store of policy_t's. - * - * @b Constructors: - * - stroke_create() - * - * @ingroup config - */ -struct policy_store_t { - - /** - * @brief Returns a policy identified by two IDs. - * - * The returned policy gets created/cloned and therefore must be - * destroyed by the caller. - * - * @param this calling object - * @param my_id own ID of the policy - * @param other_id others ID of the policy - * @return - * - matching policy_t, if found - * - NULL otherwise - */ - policy_t *(*get_policy) (policy_store_t *this, identification_t *my_id, identification_t *other_id); - - /** - * @brief Add a policy to the list. - * - * The policy is owned by the store after the call. Do - * not modify nor free. - * - * @param this calling object - * @param policy policy to add - */ - void (*add_policy) (policy_store_t *this, policy_t *policy); - - /** - * @brief Destroys a policy_store_t object. - * - * @param this calling object - */ - void (*destroy) (policy_store_t *this); -}; - -#endif /*POLICY_STORE_H_*/ diff --git a/src/charon/charon/config/proposal.c b/src/charon/charon/config/proposal.c deleted file mode 100644 index cb71a756a..000000000 --- a/src/charon/charon/config/proposal.c +++ /dev/null @@ -1,642 +0,0 @@ -/** - * @file proposal.c - * - * @brief Implementation of proposal_t. - * - */ - -/* - * Copyright (C) 2006 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 - -#include "proposal.h" - -#include -#include -#include - - -/** - * String mappings for protocol_id_t. - */ -mapping_t protocol_id_m[] = { - {PROTO_NONE, "PROTO_NONE"}, - {PROTO_IKE, "PROTO_IKE"}, - {PROTO_AH, "PROTO_AH"}, - {PROTO_ESP, "PROTO_ESP"}, - {MAPPING_END, NULL} -}; - -/** - * String mappings for transform_type_t. - */ -mapping_t transform_type_m[] = { - {UNDEFINED_TRANSFORM_TYPE, "UNDEFINED_TRANSFORM_TYPE"}, - {ENCRYPTION_ALGORITHM, "ENCRYPTION_ALGORITHM"}, - {PSEUDO_RANDOM_FUNCTION, "PSEUDO_RANDOM_FUNCTION"}, - {INTEGRITY_ALGORITHM, "INTEGRITY_ALGORITHM"}, - {DIFFIE_HELLMAN_GROUP, "DIFFIE_HELLMAN_GROUP"}, - {EXTENDED_SEQUENCE_NUMBERS, "EXTENDED_SEQUENCE_NUMBERS"}, - {MAPPING_END, NULL} -}; - -/** - * String mappings for extended_sequence_numbers_t. - */ -mapping_t extended_sequence_numbers_m[] = { - {NO_EXT_SEQ_NUMBERS, "NO_EXT_SEQ_NUMBERS"}, - {EXT_SEQ_NUMBERS, "EXT_SEQ_NUMBERS"}, - {MAPPING_END, NULL} -}; - - -typedef struct protocol_proposal_t protocol_proposal_t; - -/** - * substructure which holds all data algos for a specific protocol - */ -struct protocol_proposal_t { - /** - * protocol (ESP or AH) - */ - protocol_id_t protocol; - - /** - * priority ordered list of encryption algorithms - */ - linked_list_t *encryption_algos; - - /** - * priority ordered list of integrity algorithms - */ - linked_list_t *integrity_algos; - - /** - * priority ordered list of pseudo random functions - */ - linked_list_t *prf_algos; - - /** - * priority ordered list of dh groups - */ - linked_list_t *dh_groups; - - /** - * priority ordered list of extended sequence number flags - */ - linked_list_t *esns; - - /** - * senders SPI - */ - chunk_t spi; -}; - - -typedef struct private_proposal_t private_proposal_t; - -/** - * Private data of an proposal_t object - */ -struct private_proposal_t { - - /** - * Public part - */ - proposal_t public; - - /** - * number of this proposal, as used in the payload - */ - u_int8_t number; - - /** - * list of protocol_proposal_t's - */ - linked_list_t *protocol_proposals; -}; - -/** - * Look up a protocol_proposal, or create one if necessary... - */ -static protocol_proposal_t *get_protocol_proposal(private_proposal_t *this, protocol_id_t proto, bool create) -{ - protocol_proposal_t *proto_proposal = NULL, *current_proto_proposal;; - iterator_t *iterator; - - /* find our protocol in the proposals */ - iterator = this->protocol_proposals->create_iterator(this->protocol_proposals, TRUE); - while (iterator->has_next(iterator)) - { - iterator->current(iterator, (void**)¤t_proto_proposal); - if (current_proto_proposal->protocol == proto) - { - proto_proposal = current_proto_proposal; - break; - } - } - iterator->destroy(iterator); - - if (!proto_proposal && create) - { - /* nope, create a new one */ - proto_proposal = malloc_thing(protocol_proposal_t); - proto_proposal->protocol = proto; - proto_proposal->encryption_algos = linked_list_create(); - proto_proposal->integrity_algos = linked_list_create(); - proto_proposal->prf_algos = linked_list_create(); - proto_proposal->dh_groups = linked_list_create(); - proto_proposal->esns = linked_list_create(); - if (proto == PROTO_IKE) - { - proto_proposal->spi.len = 8; - } - else - { - proto_proposal->spi.len = 4; - } - proto_proposal->spi.ptr = malloc(proto_proposal->spi.len); - /* add to the list */ - this->protocol_proposals->insert_last(this->protocol_proposals, (void*)proto_proposal); - } - return proto_proposal; -} - -/** - * Add algorithm/keysize to a algorithm list - */ -static void add_algo(linked_list_t *list, u_int8_t algo, size_t key_size) -{ - algorithm_t *algo_key = malloc_thing(algorithm_t); - - algo_key->algorithm = algo; - algo_key->key_size = key_size; - list->insert_last(list, (void*)algo_key); -} - -/** - * Implements proposal_t.add_algorithm - */ -static void add_algorithm(private_proposal_t *this, protocol_id_t proto, transform_type_t type, u_int16_t algo, size_t key_size) -{ - protocol_proposal_t *proto_proposal = get_protocol_proposal(this, proto, TRUE); - - switch (type) - { - case ENCRYPTION_ALGORITHM: - add_algo(proto_proposal->encryption_algos, algo, key_size); - break; - case INTEGRITY_ALGORITHM: - add_algo(proto_proposal->integrity_algos, algo, key_size); - break; - case PSEUDO_RANDOM_FUNCTION: - add_algo(proto_proposal->prf_algos, algo, key_size); - break; - case DIFFIE_HELLMAN_GROUP: - add_algo(proto_proposal->dh_groups, algo, 0); - break; - case EXTENDED_SEQUENCE_NUMBERS: - add_algo(proto_proposal->esns, algo, 0); - break; - default: - break; - } -} - -/** - * Implements proposal_t.get_algorithm. - */ -static bool get_algorithm(private_proposal_t *this, protocol_id_t proto, transform_type_t type, algorithm_t** algo) -{ - linked_list_t * list; - protocol_proposal_t *proto_proposal = get_protocol_proposal(this, proto, FALSE); - - if (proto_proposal == NULL) - { - return FALSE; - } - switch (type) - { - case ENCRYPTION_ALGORITHM: - list = proto_proposal->encryption_algos; - break; - case INTEGRITY_ALGORITHM: - list = proto_proposal->integrity_algos; - break; - case PSEUDO_RANDOM_FUNCTION: - list = proto_proposal->prf_algos; - break; - case DIFFIE_HELLMAN_GROUP: - list = proto_proposal->dh_groups; - break; - case EXTENDED_SEQUENCE_NUMBERS: - list = proto_proposal->esns; - break; - default: - return FALSE; - } - if (list->get_first(list, (void**)algo) != SUCCESS) - { - return FALSE; - } - return TRUE; -} - -/** - * Implements proposal_t.create_algorithm_iterator. - */ -static iterator_t *create_algorithm_iterator(private_proposal_t *this, protocol_id_t proto, transform_type_t type) -{ - protocol_proposal_t *proto_proposal = get_protocol_proposal(this, proto, FALSE); - if (proto_proposal == NULL) - { - return NULL; - } - - switch (type) - { - case ENCRYPTION_ALGORITHM: - return proto_proposal->encryption_algos->create_iterator(proto_proposal->encryption_algos, TRUE); - case INTEGRITY_ALGORITHM: - return proto_proposal->integrity_algos->create_iterator(proto_proposal->integrity_algos, TRUE); - case PSEUDO_RANDOM_FUNCTION: - return proto_proposal->prf_algos->create_iterator(proto_proposal->prf_algos, TRUE); - case DIFFIE_HELLMAN_GROUP: - return proto_proposal->dh_groups->create_iterator(proto_proposal->dh_groups, TRUE); - case EXTENDED_SEQUENCE_NUMBERS: - return proto_proposal->esns->create_iterator(proto_proposal->esns, TRUE); - default: - break; - } - return NULL; -} - -/** - * Find a matching alg/keysize in two linked lists - */ -static bool select_algo(linked_list_t *first, linked_list_t *second, bool *add, u_int16_t *alg, size_t *key_size) -{ - iterator_t *first_iter, *second_iter; - algorithm_t *first_alg, *second_alg; - - /* if in both are zero algorithms specified, we HAVE a match */ - if (first->get_count(first) == 0 && second->get_count(second) == 0) - { - *add = FALSE; - return TRUE; - } - - first_iter = first->create_iterator(first, TRUE); - second_iter = second->create_iterator(second, TRUE); - /* compare algs, order of algs in "first" is preferred */ - while (first_iter->has_next(first_iter)) - { - first_iter->current(first_iter, (void**)&first_alg); - second_iter->reset(second_iter); - while (second_iter->has_next(second_iter)) - { - second_iter->current(second_iter, (void**)&second_alg); - if (first_alg->algorithm == second_alg->algorithm && - first_alg->key_size == second_alg->key_size) - { - /* ok, we have an algorithm */ - *alg = first_alg->algorithm; - *key_size = first_alg->key_size; - *add = TRUE; - first_iter->destroy(first_iter); - second_iter->destroy(second_iter); - return TRUE; - } - } - } - /* no match in all comparisons */ - first_iter->destroy(first_iter); - second_iter->destroy(second_iter); - return FALSE; -} - -/** - * Implements proposal_t.select. - */ -static proposal_t *select_proposal(private_proposal_t *this, private_proposal_t *other) -{ - proposal_t *selected; - u_int16_t algo; - size_t key_size; - iterator_t *iterator; - protocol_proposal_t *this_prop, *other_prop; - protocol_id_t proto; - bool add; - u_int64_t spi; - - /* empty proposal? no match */ - if (this->protocol_proposals->get_count(this->protocol_proposals) == 0 || - other->protocol_proposals->get_count(other->protocol_proposals) == 0) - { - return NULL; - } - /* they MUST have the same amount of protocols */ - if (this->protocol_proposals->get_count(this->protocol_proposals) != - other->protocol_proposals->get_count(other->protocol_proposals)) - { - return NULL; - } - - selected = proposal_create(this->number); - - /* iterate over supplied proposals */ - iterator = other->protocol_proposals->create_iterator(other->protocol_proposals, TRUE); - while (iterator->has_next(iterator)) - { - iterator->current(iterator, (void**)&other_prop); - /* get the proposal with the same protocol */ - proto = other_prop->protocol; - this_prop = get_protocol_proposal(this, proto, FALSE); - - if (this_prop == NULL) - { - iterator->destroy(iterator); - selected->destroy(selected); - return NULL; - } - - /* select encryption algorithm */ - if (select_algo(this_prop->encryption_algos, other_prop->encryption_algos, &add, &algo, &key_size)) - { - if (add) - { - selected->add_algorithm(selected, proto, ENCRYPTION_ALGORITHM, algo, key_size); - } - } - else - { - iterator->destroy(iterator); - selected->destroy(selected); - return NULL; - } - /* select integrity algorithm */ - if (select_algo(this_prop->integrity_algos, other_prop->integrity_algos, &add, &algo, &key_size)) - { - if (add) - { - selected->add_algorithm(selected, proto, INTEGRITY_ALGORITHM, algo, key_size); - } - } - else - { - iterator->destroy(iterator); - selected->destroy(selected); - return NULL; - } - /* select prf algorithm */ - if (select_algo(this_prop->prf_algos, other_prop->prf_algos, &add, &algo, &key_size)) - { - if (add) - { - selected->add_algorithm(selected, proto, PSEUDO_RANDOM_FUNCTION, algo, key_size); - } - } - else - { - iterator->destroy(iterator); - selected->destroy(selected); - return NULL; - } - /* select a DH-group */ - if (select_algo(this_prop->dh_groups, other_prop->dh_groups, &add, &algo, &key_size)) - { - if (add) - { - selected->add_algorithm(selected, proto, DIFFIE_HELLMAN_GROUP, algo, 0); - } - } - else - { - iterator->destroy(iterator); - selected->destroy(selected); - return NULL; - } - /* select if we use ESNs */ - if (select_algo(this_prop->esns, other_prop->esns, &add, &algo, &key_size)) - { - if (add) - { - selected->add_algorithm(selected, proto, EXTENDED_SEQUENCE_NUMBERS, algo, 0); - } - } - else - { - iterator->destroy(iterator); - selected->destroy(selected); - return NULL; - } - } - iterator->destroy(iterator); - - /* apply spis from "other" */ - spi = other->public.get_spi(&(other->public), PROTO_AH); - if (spi) - { - selected->set_spi(selected, PROTO_AH, spi); - } - spi = other->public.get_spi(&(other->public), PROTO_ESP); - if (spi) - { - selected->set_spi(selected, PROTO_ESP, spi); - } - - /* everything matched, return new proposal */ - return selected; -} - -/** - * Implements proposal_t.get_number. - */ -static u_int8_t get_number(private_proposal_t *this) -{ - return this->number; -} - -/** - * Implements proposal_t.get_protocols. - */ -static void get_protocols(private_proposal_t *this, protocol_id_t ids[2]) -{ - iterator_t *iterator = this->protocol_proposals->create_iterator(this->protocol_proposals, TRUE); - u_int i = 0; - - ids[0] = PROTO_NONE; - ids[1] = PROTO_NONE; - while (iterator->has_next(iterator)) - { - protocol_proposal_t *proto_prop; - iterator->current(iterator, (void**)&proto_prop); - ids[i++] = proto_prop->protocol; - if (i>1) - { - /* should not happen, but who knows */ - break; - } - } - iterator->destroy(iterator); -} - -/** - * Implements proposal_t.set_spi. - */ -static void set_spi(private_proposal_t *this, protocol_id_t proto, u_int64_t spi) -{ - protocol_proposal_t *proto_proposal = get_protocol_proposal(this, proto, FALSE); - if (proto_proposal) - { - if (proto == PROTO_AH || proto == PROTO_ESP) - { - *((u_int32_t*)proto_proposal->spi.ptr) = (u_int32_t)spi; - } - else - { - *((u_int64_t*)proto_proposal->spi.ptr) = spi; - } - } -} - -/** - * Implements proposal_t.get_spi. - */ -static u_int64_t get_spi(private_proposal_t *this, protocol_id_t proto) -{ - protocol_proposal_t *proto_proposal = get_protocol_proposal(this, proto, FALSE); - if (proto_proposal) - { - if (proto == PROTO_AH || proto == PROTO_ESP) - { - return (u_int64_t)*((u_int32_t*)proto_proposal->spi.ptr); - } - else - { - return *((u_int64_t*)proto_proposal->spi.ptr); - } - } - return 0; -} - -/** - * Clone a algorithm list - */ -static void clone_algo_list(linked_list_t *list, linked_list_t *clone_list) -{ - algorithm_t *algo, *clone_algo; - iterator_t *iterator = list->create_iterator(list, TRUE); - while (iterator->has_next(iterator)) - { - iterator->current(iterator, (void**)&algo); - clone_algo = malloc_thing(algorithm_t); - memcpy(clone_algo, algo, sizeof(algorithm_t)); - clone_list->insert_last(clone_list, (void*)clone_algo); - } - iterator->destroy(iterator); -} - -/** - * Implements proposal_t.clone - */ -static proposal_t *clone(private_proposal_t *this) -{ - private_proposal_t *clone = (private_proposal_t*)proposal_create(this->number); - - iterator_t *iterator = this->protocol_proposals->create_iterator(this->protocol_proposals, TRUE); - while (iterator->has_next(iterator)) - { - protocol_proposal_t *proto_prop, *clone_proto_prop; - iterator->current(iterator, (void**)&proto_prop); - - clone_proto_prop = get_protocol_proposal(clone, proto_prop->protocol, TRUE); - memcpy(clone_proto_prop->spi.ptr, proto_prop->spi.ptr, clone_proto_prop->spi.len); - - clone_algo_list(proto_prop->encryption_algos, clone_proto_prop->encryption_algos); - clone_algo_list(proto_prop->integrity_algos, clone_proto_prop->integrity_algos); - clone_algo_list(proto_prop->prf_algos, clone_proto_prop->prf_algos); - clone_algo_list(proto_prop->dh_groups, clone_proto_prop->dh_groups); - clone_algo_list(proto_prop->esns, clone_proto_prop->esns); - } - iterator->destroy(iterator); - - return &clone->public; -} - -/** - * Frees all list items and destroys the list - */ -static void free_algo_list(linked_list_t *list) -{ - algorithm_t *algo; - - while(list->get_count(list) > 0) - { - list->remove_last(list, (void**)&algo); - free(algo); - } - list->destroy(list); -} - -/** - * Implements proposal_t.destroy. - */ -static void destroy(private_proposal_t *this) -{ - while(this->protocol_proposals->get_count(this->protocol_proposals) > 0) - { - protocol_proposal_t *proto_prop; - this->protocol_proposals->remove_last(this->protocol_proposals, (void**)&proto_prop); - - free_algo_list(proto_prop->encryption_algos); - free_algo_list(proto_prop->integrity_algos); - free_algo_list(proto_prop->prf_algos); - free_algo_list(proto_prop->dh_groups); - free_algo_list(proto_prop->esns); - - free(proto_prop->spi.ptr); - free(proto_prop); - } - this->protocol_proposals->destroy(this->protocol_proposals); - - free(this); -} - -/* - * Describtion in header-file - */ -proposal_t *proposal_create(u_int8_t number) -{ - private_proposal_t *this = malloc_thing(private_proposal_t); - - this->public.add_algorithm = (void (*)(proposal_t*,protocol_id_t,transform_type_t,u_int16_t,size_t))add_algorithm; - this->public.create_algorithm_iterator = (iterator_t* (*)(proposal_t*,protocol_id_t,transform_type_t))create_algorithm_iterator; - this->public.get_algorithm = (bool (*)(proposal_t*,protocol_id_t,transform_type_t,algorithm_t**))get_algorithm; - this->public.select = (proposal_t* (*)(proposal_t*,proposal_t*))select_proposal; - this->public.get_number = (u_int8_t (*)(proposal_t*))get_number; - this->public.get_protocols = (void(*)(proposal_t *this, protocol_id_t ids[2]))get_protocols; - this->public.set_spi = (void(*)(proposal_t*,protocol_id_t,u_int64_t spi))set_spi; - this->public.get_spi = (u_int64_t(*)(proposal_t*,protocol_id_t))get_spi; - this->public.clone = (proposal_t*(*)(proposal_t*))clone; - this->public.destroy = (void(*)(proposal_t*))destroy; - - /* init private members*/ - this->number = number; - this->protocol_proposals = linked_list_create(); - - return (&this->public); -} diff --git a/src/charon/charon/config/proposal.h b/src/charon/charon/config/proposal.h deleted file mode 100644 index 48e3ad8d5..000000000 --- a/src/charon/charon/config/proposal.h +++ /dev/null @@ -1,269 +0,0 @@ -/** - * @file proposal.h - * - * @brief Interface of proposal_t. - * - */ - -/* - * Copyright (C) 2006 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef PROPOSAL_H_ -#define PROPOSAL_H_ - -#include -#include -#include -#include -#include -#include -#include -#include - - -typedef enum protocol_id_t protocol_id_t; - -/** - * Protocol ID of a proposal. - * - * @ingroup config - */ -enum protocol_id_t { - PROTO_NONE = 0, - PROTO_IKE = 1, - PROTO_AH = 2, - PROTO_ESP = 3, -}; - -/** - * String mappings for protocol_id_t. - * - * @ingroup config - */ -extern mapping_t protocol_id_m[]; - - -typedef enum transform_type_t transform_type_t; - -/** - * Type of a transform, as in IKEv2 RFC 3.3.2. - * - * @ingroup payloads - */ -enum transform_type_t { - UNDEFINED_TRANSFORM_TYPE = 241, - ENCRYPTION_ALGORITHM = 1, - PSEUDO_RANDOM_FUNCTION = 2, - INTEGRITY_ALGORITHM = 3, - DIFFIE_HELLMAN_GROUP = 4, - EXTENDED_SEQUENCE_NUMBERS = 5 -}; - -/** - * String mappings for transform_type_t. - * - * @ingroup payloads - */ -extern mapping_t transform_type_m[]; - - -typedef enum extended_sequence_numbers_t extended_sequence_numbers_t; - -/** - * Extended sequence numbers, as in IKEv2 RFC 3.3.2. - * - * @ingroup payloads - */ -enum extended_sequence_numbers_t { - NO_EXT_SEQ_NUMBERS = 0, - EXT_SEQ_NUMBERS = 1 -}; - -/** - * String mappings for extended_sequence_numbers_t. - * - * @ingroup payloads - */ -extern mapping_t extended_sequence_numbers_m[]; - - -typedef struct algorithm_t algorithm_t; - -/** - * Struct used to store different kinds of algorithms. The internal - * lists of algorithms contain such structures. - */ -struct algorithm_t { - /** - * Value from an encryption_algorithm_t/integrity_algorithm_t/... - */ - u_int16_t algorithm; - - /** - * the associated key size, or zero if not needed - */ - u_int16_t key_size; -}; - -typedef struct proposal_t proposal_t; - -/** - * @brief Stores a set of algorithms used for an SA. - * - * A proposal stores algorithms for a specific - * protocol. It can store algorithms for more than - * one protocol (e.g. AH and ESP). Then the proposal - * means both protocols must be used. - * A proposal may contain more than one algorithm - * of the same kind. ONE of them can be selected. - * - * @warning This class is NOT thread-save! - * - * @b Constructors: - * - proposal_create() - * - * @ingroup config - */ -struct proposal_t { - - /** - * @brief Add an algorithm to the proposal. - * - * The algorithms are stored by priority, first added - * is the most preferred. - * Key size is only needed for encryption algorithms - * with variable key size (such as AES). Must be set - * to zero if key size is not specified. - * The alg parameter accepts encryption_algorithm_t, - * integrity_algorithm_t, dh_group_number_t and - * extended_sequence_numbers_t. - * - * @warning Do not add while other threads are reading. - * - * @param this calling object - * @param proto desired protocol - * @param type kind of algorithm - * @param alg identifier for algorithm - * @param key_size key size to use - */ - void (*add_algorithm) (proposal_t *this, protocol_id_t proto, transform_type_t type, u_int16_t alg, size_t key_size); - - /** - * @brief Get an iterator over algorithms for a specifc protocol/algo type. - * - * @param this calling object - * @param proto desired protocol - * @param type kind of algorithm - * @return iterator over algorithms - */ - iterator_t *(*create_algorithm_iterator) (proposal_t *this, protocol_id_t proto, transform_type_t type); - - /** - * @brief Get the algorithm for a type to use. - * - * If there are multiple algorithms, only the first is returned. - * Result is still owned by proposal, do not modify! - * - * @param this calling object - * @param proto desired protocol - * @param type kind of algorithm - * @param[out] algo pointer which receives algorithm and key size - * @return TRUE if algorithm of this kind available - */ - bool (*get_algorithm) (proposal_t *this, protocol_id_t proto, transform_type_t type, algorithm_t** algo); - - /** - * @brief Compare two proposal, and select a matching subset. - * - * If the proposals are for the same protocols (AH/ESP), they are - * compared. If they have at least one algorithm of each type - * in common, a resulting proposal of this kind is created. - * - * @param this calling object - * @param other proposal to compair agains - * @return - * - selected proposal, if possible - * - NULL, if proposals don't match - */ - proposal_t *(*select) (proposal_t *this, proposal_t *other); - - /** - * @brief Get the number set on construction. - * - * @param this calling object - * @return number - */ - u_int8_t (*get_number) (proposal_t *this); - - /** - * @brief Get the protocol ids in the proposals. - * - * With AH and ESP, there could be two protocols in one - * proposal. - * - * @param this calling object - * @param ids array of protocol ids, - */ - void (*get_protocols) (proposal_t *this, protocol_id_t ids[2]); - - /** - * @brief Get the spi for a specific protocol. - * - * @param this calling object - * @param proto AH/ESP - * @return spi for proto - */ - u_int64_t (*get_spi) (proposal_t *this, protocol_id_t proto); - - /** - * @brief Set the spi for a specific protocol. - * - * @param this calling object - * @param proto AH/ESP - * @param spi spi to set for proto - */ - void (*set_spi) (proposal_t *this, protocol_id_t proto, u_int64_t spi); - - /** - * @brief Clone a proposal. - * - * @param this proposal to clone - * @return clone of it - */ - proposal_t *(*clone) (proposal_t *this); - - /** - * @brief Destroys the proposal object. - * - * @param this calling object - */ - void (*destroy) (proposal_t *this); -}; - -/** - * @brief Create a child proposal for AH and/or ESP. - * - * Since the order of multiple proposals is important for - * key derivation, we must assign them numbers as they - * appear in the raw payload. Numbering starts at 1. - * - * @param number number of the proposal, as in the payload - * @return proposal_t object - * - * @ingroup config - */ -proposal_t *proposal_create(u_int8_t number); - -#endif /* PROPOSAL_H_ */ diff --git a/src/charon/charon/config/traffic_selector.c b/src/charon/charon/config/traffic_selector.c deleted file mode 100644 index 81272659a..000000000 --- a/src/charon/charon/config/traffic_selector.c +++ /dev/null @@ -1,425 +0,0 @@ -/** - * @file traffic_selector.c - * - * @brief Implementation of traffic_selector_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 "traffic_selector.h" - -#include -#include -#include -#include - -typedef struct private_traffic_selector_t private_traffic_selector_t; - -/** - * Private data of an traffic_selector_t object - */ -struct private_traffic_selector_t { - - /** - * Public part - */ - traffic_selector_t public; - - /** - * Type of address - */ - ts_type_t type; - - /** - * IP protocol (UDP, TCP, ICMP, ...) - */ - u_int8_t protocol; - - /** - * begin of address range, host order - */ - union { - u_int32_t from_addr_ipv4; - }; - - /** - * end of address range, host order - */ - union { - u_int32_t to_addr_ipv4; - }; - - /** - * begin of port range - */ - u_int16_t from_port; - - /** - * end of port range - */ - u_int16_t to_port; -}; - -/** - * internal generic constructor - */ -static private_traffic_selector_t *traffic_selector_create(u_int8_t protocol, ts_type_t type, u_int16_t from_port, u_int16_t to_port); - -/** - * implements traffic_selector_t.get_subset - */ -static traffic_selector_t *get_subset(private_traffic_selector_t *this, private_traffic_selector_t *other) -{ - if ((this->type == TS_IPV4_ADDR_RANGE) && - (other->type == TS_IPV4_ADDR_RANGE) && - (this->protocol == other->protocol)) - { - u_int32_t from_addr, to_addr; - u_int16_t from_port, to_port; - private_traffic_selector_t *new_ts; - - /* calculate the maximum address range allowed for both */ - from_addr = max(this->from_addr_ipv4, other->from_addr_ipv4); - to_addr = min(this->to_addr_ipv4, other->to_addr_ipv4); - if (from_addr > to_addr) - { - /* no match */ - return NULL; - } - - /* calculate the maximum port range allowed for both */ - from_port = max(this->from_port, other->from_port); - to_port = min(this->to_port, other->to_port); - if (from_port > to_port) - { - /* no match */ - return NULL; - } - - /* got a match, return it */ - new_ts = traffic_selector_create(this->protocol, this->type, from_port, to_port); - new_ts->from_addr_ipv4 = from_addr; - new_ts->to_addr_ipv4 = to_addr; - new_ts->type = TS_IPV4_ADDR_RANGE; - return &(new_ts->public); - } - return NULL; -} - -/** - * Implements traffic_selector_t.get_from_address. - */ -static chunk_t get_from_address(private_traffic_selector_t *this) -{ - chunk_t from_addr = CHUNK_INITIALIZER; - - switch (this->type) - { - case TS_IPV4_ADDR_RANGE: - { - u_int32_t network; - from_addr.len = sizeof(network); - from_addr.ptr = malloc(from_addr.len); - /* chunk must contain network order, convert! */ - network = htonl(this->from_addr_ipv4); - memcpy(from_addr.ptr, &network, from_addr.len); - break; - } - case TS_IPV6_ADDR_RANGE: - { - break; - } - } - return from_addr; -} - -/** - * Implements traffic_selector_t.get_to_address. - */ -static chunk_t get_to_address(private_traffic_selector_t *this) -{ - chunk_t to_addr = CHUNK_INITIALIZER; - - switch (this->type) - { - case TS_IPV4_ADDR_RANGE: - { - u_int32_t network; - to_addr.len = sizeof(network); - to_addr.ptr = malloc(to_addr.len); - /* chunk must contain network order, convert! */ - network = htonl(this->to_addr_ipv4); - memcpy(to_addr.ptr, &network, to_addr.len); - break; - } - case TS_IPV6_ADDR_RANGE: - { - break; - } - } - return to_addr; -} - -/** - * Implements traffic_selector_t.get_from_port. - */ -static u_int16_t get_from_port(private_traffic_selector_t *this) -{ - return this->from_port; -} - -/** - * Implements traffic_selector_t.get_to_port. - */ -static u_int16_t get_to_port(private_traffic_selector_t *this) -{ - return this->to_port; -} - -/** - * Implements traffic_selector_t.get_type. - */ -static ts_type_t get_type(private_traffic_selector_t *this) -{ - return this->type; -} - -/** - * Implements traffic_selector_t.get_protocol. - */ -static u_int8_t get_protocol(private_traffic_selector_t *this) -{ - return this->protocol; -} - -/** - * Implements traffic_selector_t.get_netmask. - */ -static u_int8_t get_netmask(private_traffic_selector_t *this) -{ - switch (this->type) - { - case TS_IPV4_ADDR_RANGE: - { - u_int32_t from, to, bit; - from = htonl(this->from_addr_ipv4); - to = htonl(this->to_addr_ipv4); - for (bit = 0; bit < 32; bit++) - { - if ((1<get_family(host) == AF_INET && - this->type == TS_IPV4_ADDR_RANGE) - { - if (this->from_addr_ipv4 == 0) - { - chunk_t from = host->get_address_as_chunk(host); - this->from_addr_ipv4 = ntohl(*((u_int32_t*)from.ptr)); - this->to_addr_ipv4 = this->from_addr_ipv4; - chunk_free(&from); - } - } -} - -/** - * Implements traffic_selector_t.clone. - */ -static traffic_selector_t *clone(private_traffic_selector_t *this) -{ - private_traffic_selector_t *clone = traffic_selector_create(this->protocol, this->type, this->from_port, this->to_port); - clone->type = this->type; - switch (clone->type) - { - case TS_IPV4_ADDR_RANGE: - { - clone->from_addr_ipv4 = this->from_addr_ipv4; - clone->to_addr_ipv4 = this->to_addr_ipv4; - return &(clone->public); - } - case TS_IPV6_ADDR_RANGE: - default: - { - free(this); - return NULL; - } - } -} - -/** - * Implements traffic_selector_t.destroy. - */ -static void destroy(private_traffic_selector_t *this) -{ - free(this); -} - -/* - * see header - */ -traffic_selector_t *traffic_selector_create_from_bytes(u_int8_t protocol, ts_type_t type, chunk_t from_addr, int16_t from_port, chunk_t to_addr, u_int16_t to_port) -{ - private_traffic_selector_t *this = traffic_selector_create(protocol, type, from_port, to_port); - - this->type = type; - switch (type) - { - case TS_IPV4_ADDR_RANGE: - { - if (from_addr.len != 4 || to_addr.len != 4) - { - free(this); - return NULL; - } - /* chunk contains network order, convert! */ - this->from_addr_ipv4 = ntohl(*((u_int32_t*)from_addr.ptr)); - this->to_addr_ipv4 = ntohl(*((u_int32_t*)to_addr.ptr)); - break; - } - case TS_IPV6_ADDR_RANGE: - default: - { - free(this); - return NULL; - } - } - return (&this->public); -} - -/* - * see header - */ -traffic_selector_t *traffic_selector_create_from_subnet(host_t *net, u_int8_t netbits) -{ - private_traffic_selector_t *this = traffic_selector_create(0, 0, 0, 65535); - - switch (net->get_family(net)) - { - case AF_INET: - { - chunk_t from; - - this->type = TS_IPV4_ADDR_RANGE; - from = net->get_address_as_chunk(net); - this->from_addr_ipv4 = ntohl(*((u_int32_t*)from.ptr)); - if (this->from_addr_ipv4 == 0) - { - /* use /32 for 0.0.0.0 */ - this->to_addr_ipv4 = 0xFFFFFF; - } - else - { - this->to_addr_ipv4 = this->from_addr_ipv4 | ((1 << (32 - netbits)) - 1); - } - chunk_free(&from); - break; - } - case AF_INET6: - default: - { - free(this); - return NULL; - } - } - return (&this->public); -} - -/* - * see header - */ -traffic_selector_t *traffic_selector_create_from_string(u_int8_t protocol, ts_type_t type, char *from_addr, u_int16_t from_port, char *to_addr, u_int16_t to_port) -{ - private_traffic_selector_t *this = traffic_selector_create(protocol, type, from_port, to_port); - - /* public functions */ - this->public.get_subset = (traffic_selector_t*(*)(traffic_selector_t*,traffic_selector_t*))get_subset; - this->public.destroy = (void(*)(traffic_selector_t*))destroy; - - this->type = type; - switch (type) - { - case TS_IPV4_ADDR_RANGE: - { - if (inet_aton(from_addr, (struct in_addr*)&(this->from_addr_ipv4)) == 0) - { - free(this); - return NULL; - } - if (inet_aton(to_addr, (struct in_addr*)&(this->to_addr_ipv4)) == 0) - { - free(this); - return NULL; - } - /* convert to host order, inet_aton has network order */ - this->from_addr_ipv4 = ntohl(this->from_addr_ipv4); - this->to_addr_ipv4 = ntohl(this->to_addr_ipv4); - break; - } - case TS_IPV6_ADDR_RANGE: - { - free(this); - return NULL; - } - } - - return (&this->public); -} - -/* - * see declaration - */ -static private_traffic_selector_t *traffic_selector_create(u_int8_t protocol, ts_type_t type, u_int16_t from_port, u_int16_t to_port) -{ - private_traffic_selector_t *this = malloc_thing(private_traffic_selector_t); - - /* public functions */ - this->public.get_subset = (traffic_selector_t*(*)(traffic_selector_t*,traffic_selector_t*))get_subset; - this->public.get_from_address = (chunk_t(*)(traffic_selector_t*))get_from_address; - this->public.get_to_address = (chunk_t(*)(traffic_selector_t*))get_to_address; - this->public.get_from_port = (u_int16_t(*)(traffic_selector_t*))get_from_port; - this->public.get_to_port = (u_int16_t(*)(traffic_selector_t*))get_to_port; - this->public.get_type = (ts_type_t(*)(traffic_selector_t*))get_type; - this->public.get_protocol = (u_int8_t(*)(traffic_selector_t*))get_protocol; - this->public.get_netmask = (u_int8_t(*)(traffic_selector_t*))get_netmask; - this->public.update_address_range = (void(*)(traffic_selector_t*,host_t*))update_address_range; - this->public.clone = (traffic_selector_t*(*)(traffic_selector_t*))clone; - this->public.destroy = (void(*)(traffic_selector_t*))destroy; - - this->from_port = from_port; - this->to_port = to_port; - this->protocol = protocol; - this->type = type; - - return this; -} diff --git a/src/charon/charon/config/traffic_selector.h b/src/charon/charon/config/traffic_selector.h deleted file mode 100644 index 5ac5bdeb1..000000000 --- a/src/charon/charon/config/traffic_selector.h +++ /dev/null @@ -1,258 +0,0 @@ -/** - * @file traffic_selector.h - * - * @brief Interface of traffic_selector_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef TRAFFIC_SELECTOR_H_ -#define TRAFFIC_SELECTOR_H_ - -#include -#include - -typedef enum ts_type_t ts_type_t; - -/** - * Traffic selector types. - * - * @ingroup config - */ -enum ts_type_t { - - /** - * A range of IPv4 addresses, represented by two four (4) octet - * values. The first value is the beginning IPv4 address - * (inclusive) and the second value is the ending IPv4 address - * (inclusive). All addresses falling between the two specified - * addresses are considered to be within the list. - */ - TS_IPV4_ADDR_RANGE = 7, - - /** - * A range of IPv6 addresses, represented by two sixteen (16) - * octet values. The first value is the beginning IPv6 address - * (inclusive) and the second value is the ending IPv6 address - * (inclusive). All addresses falling between the two specified - * addresses are considered to be within the list. - */ - TS_IPV6_ADDR_RANGE = 8 -}; - -/** - * string mappings for ts_type_t - */ -extern mapping_t ts_type_m[]; - - -typedef struct traffic_selector_t traffic_selector_t; - -/** - * @brief Object representing a traffic selector entry. - * - * A traffic selector defines an range of addresses - * and a range of ports. IPv6 is not fully supported yet. - * - * @b Constructors: - * - traffic_selector_create_from_bytes() - * - traffic_selector_create_from_string() - * - * @todo Add IPv6 support - * - * @ingroup config - */ -struct traffic_selector_t { - - /** - * @brief Compare two traffic selectors, and create a new one - * which is the largest subset of both (subnet & port). - * - * Resulting traffic_selector is newly created and must be destroyed. - * - * @param this first to compare - * @param other second to compare - * @return - * - created subset of them - * - or NULL if no match between this and other - */ - traffic_selector_t *(*get_subset) (traffic_selector_t *this, traffic_selector_t *other); - - /** - * @brief Clone a traffic selector. - * - * @param this traffic selector to clone - * @return clone of it - */ - traffic_selector_t *(*clone) (traffic_selector_t *this); - - /** - * @brief Get starting address of this ts as a chunk. - * - * Data is in network order and represents the address. - * Size depends on protocol. - * - * Resulting chunk data is allocated and must be freed! - * - * @param this calling object - * @return chunk containing the address - */ - chunk_t (*get_from_address) (traffic_selector_t *this); - - /** - * @brief Get ending address of this ts as a chunk. - * - * Data is in network order and represents the address. - * Size depends on protocol. - * - * Resulting chunk data is allocated and must be freed! - * - * @param this calling object - * @return chunk containing the address - */ - chunk_t (*get_to_address) (traffic_selector_t *this); - - /** - * @brief Get starting port of this ts. - * - * Port is in host order, since the parser converts it. - * Size depends on protocol. - * - * @param this calling object - * @return port - */ - u_int16_t (*get_from_port) (traffic_selector_t *this); - - /** - * @brief Get ending port of this ts. - * - * Port is in host order, since the parser converts it. - * Size depends on protocol. - * - * @param this calling object - * @return port - */ - u_int16_t (*get_to_port) (traffic_selector_t *this); - - /** - * @brief Get the type of the traffic selector. - * - * @param this calling obect - * @return ts_type_t specifying the type - */ - ts_type_t (*get_type) (traffic_selector_t *this); - - /** - * @brief Get the protocol id of this ts. - * - * @param this calling obect - * @return protocol id - */ - u_int8_t (*get_protocol) (traffic_selector_t *this); - - /** - * @brief Get the netmask of the address range. - * - * Returns the number of bits associated to the subnet. - * (As the "24" in "192.168.0.0/24"). This is approximated - * if the address range is not a complete subnet! Since Linux - * does not support full IP address ranges (yet), we can't do this - * (much) better. - * - * @param this calling obect - * @return netmask as "bits for subnet" - */ - u_int8_t (*get_netmask) (traffic_selector_t *this); - - /** - * @brief Update the address of a traffic selector. - * - * Update the address range of a traffic selector, - * if the current address is 0.0.0.0. The new address range - * starts from the supplied address and also ends there - * (which means it is a one-host-address-range ;-). - * - * @param this calling obect - * @param host host_t specifying the address range - */ - void (*update_address_range) (traffic_selector_t *this, host_t* host); - - /** - * @brief Destroys the ts object - * - * @param this calling object - */ - void (*destroy) (traffic_selector_t *this); -}; - -/** - * @brief Create a new traffic selector using human readable params. - * - * @param protocol protocol for this ts, such as TCP or UDP - * @param type type of following addresses, such as TS_IPV4_ADDR_RANGE - * @param from_addr start of address range as string - * @param from_port port number in host order - * @param to_addr end of address range as string - * @param to_port port number in host order - * @return - * - traffic_selector_t object - * - NULL if invalid address strings/protocol - * - * @ingroup config - */ -traffic_selector_t *traffic_selector_create_from_string(u_int8_t protocol, ts_type_t type, char *from_addr, u_int16_t from_port, char *to_addr, u_int16_t to_port); - -/** - * @brief Create a new traffic selector using data read from the net. - * - * There exists a mix of network and host order in the params. - * But the parser gives us this data in this format, so we - * don't have to convert twice. - * - * @param protocol protocol for this ts, such as TCP or UDP - * @param type type of following addresses, such as TS_IPV4_ADDR_RANGE - * @param from_address start of address range, network order - * @param from_port port number, host order - * @param to_address end of address range as string, network - * @param to_port port number, host order - * @return - * - traffic_selector_t object - * - NULL if invalid address input/protocol - * - * @ingroup config - */ -traffic_selector_t *traffic_selector_create_from_bytes(u_int8_t protocol, ts_type_t type, chunk_t from_address, int16_t from_port, chunk_t to_address, u_int16_t to_port); - -/** - * @brief Create a new traffic selector defining a whole subnet. - * - * In most cases, definition of a traffic selector for full subnets - * is sufficient. This constructor creates a traffic selector for - * all protocols, all ports and the address range specified by the - * subnet. - * - * @param net subnet to use - * @param netbits size of the subnet, as used in e.g. 192.168.0.0/24 notation - * @return - * - traffic_selector_t object - * - NULL if address family of net not supported - * - * @ingroup config - */ -traffic_selector_t *traffic_selector_create_from_subnet(host_t *net, u_int8_t netbits); - -#endif /* TRAFFIC_SELECTOR_H_ */ diff --git a/src/charon/charon/daemon.c b/src/charon/charon/daemon.c deleted file mode 100644 index c3d7ed766..000000000 --- a/src/charon/charon/daemon.c +++ /dev/null @@ -1,390 +0,0 @@ -/** - * @file daemon.c - * - * @brief Implementation of daemon_t and main of IKEv2-Daemon. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 -#include -#include -#include -#include -#include -#include -#include - -#include "daemon.h" - -#include -#include -#include -#include - - -typedef struct private_daemon_t private_daemon_t; - -/** - * Private additions to daemon_t, contains threads and internal functions. - */ -struct private_daemon_t { - /** - * Public members of daemon_t. - */ - daemon_t public; - - /** - * A logger_t object assigned for daemon things. - */ - logger_t *logger; - - /** - * Signal set used for signal handling. - */ - sigset_t signal_set; - - /** - * The thread_id of main-thread. - */ - pthread_t main_thread_id; - - /** - * Main loop function. - * - * @param this calling object - */ - void (*run) (private_daemon_t *this); - - /** - * Initialize the daemon. - * - * @param this calling object - */ - void (*initialize) (private_daemon_t *this); - - /** - * Destroy the daemon. - * - * @param this calling object - */ - void (*destroy) (private_daemon_t *this); -}; - -/** - * One and only instance of the daemon. - */ -daemon_t *charon; - -/** - * Implementation of private_daemon_t.run. - */ -static void run(private_daemon_t *this) -{ - /* reselect signals for this thread */ - sigemptyset(&(this->signal_set)); - sigaddset(&(this->signal_set), SIGINT); - sigaddset(&(this->signal_set), SIGHUP); - sigaddset(&(this->signal_set), SIGTERM); - pthread_sigmask(SIG_BLOCK, &(this->signal_set), 0); - - while(TRUE) - { - int signal_number; - int error; - - error = sigwait(&(this->signal_set), &signal_number); - if(error) - { - this->logger->log(this->logger, ERROR, "Error %d when waiting for signal", error); - return; - } - switch (signal_number) - { - case SIGHUP: - { - this->logger->log(this->logger, CONTROL, "Signal of type SIGHUP received. Do nothing"); - break; - } - case SIGINT: - { - this->logger->log(this->logger, CONTROL, "Signal of type SIGINT received. Exit main loop"); - return; - } - case SIGTERM: - this->logger->log(this->logger, CONTROL, "Signal of type SIGTERM received. Exit main loop"); - return; - default: - { - this->logger->log(this->logger, CONTROL, "Unknown signal %d received. Do nothing", signal_number); - break; - } - } - } -} - -/** - * Implementation of daemon_t.kill. - */ -static void kill_daemon(private_daemon_t *this, char *reason) -{ - /* we send SIGTERM, so the daemon can cleanly shut down */ - this->logger->log(this->logger, CONTROL, "Killing daemon: %s", reason); - if (this->main_thread_id == pthread_self()) - { - /* initialization failed, terminate daemon */ - this->destroy(this); - unlink(PID_FILE); - exit(-1); - } - else - { - this->logger->log(this->logger, CONTROL, "sending SIGTERM to ourself", reason); - kill(0, SIGTERM); - /* thread must die, since he produced a ciritcal failure and can't continue */ - pthread_exit(NULL); - } -} - -/** - * Implementation of private_daemon_t.initialize. - */ -static void initialize(private_daemon_t *this) -{ - local_credential_store_t* cred_store; - - this->public.configuration = configuration_create(); - this->public.socket = socket_create(IKEV2_UDP_PORT); - this->public.ike_sa_manager = ike_sa_manager_create(); - this->public.job_queue = job_queue_create(); - this->public.event_queue = event_queue_create(); - this->public.send_queue = send_queue_create(); - this->public.connections = (connection_store_t*)local_connection_store_create(); - this->public.policies = (policy_store_t*)local_policy_store_create(); - this->public.credentials = (credential_store_t*)(cred_store = local_credential_store_create()); - - /* load keys & certs */ - cred_store->load_certificates(cred_store, CERTIFICATE_DIR); - cred_store->load_private_keys(cred_store, SECRETS_FILE, PRIVATE_KEY_DIR); - - - /* start building threads, we are multi-threaded NOW */ - this->public.stroke = stroke_create(); - this->public.sender = sender_create(); - this->public.receiver = receiver_create(); - this->public.scheduler = scheduler_create(); - this->public.kernel_interface = kernel_interface_create(); - this->public.thread_pool = thread_pool_create(NUMBER_OF_WORKING_THREADS); -} - -/** - * Destory all initiated objects - */ -static void destroy(private_daemon_t *this) -{ - if (this->public.ike_sa_manager != NULL) - { - this->public.ike_sa_manager->destroy(this->public.ike_sa_manager); - } - if (this->public.kernel_interface != NULL) - { - this->public.kernel_interface->destroy(this->public.kernel_interface); - } - if (this->public.receiver != NULL) - { - this->public.receiver->destroy(this->public.receiver); - } - if (this->public.scheduler != NULL) - { - this->public.scheduler->destroy(this->public.scheduler); - } - if (this->public.sender != NULL) - { - this->public.sender->destroy(this->public.sender); - } - if (this->public.thread_pool != NULL) - { - this->public.thread_pool->destroy(this->public.thread_pool); - } - if (this->public.job_queue != NULL) - { - this->public.job_queue->destroy(this->public.job_queue); - } - if (this->public.event_queue != NULL) - { - this->public.event_queue->destroy(this->public.event_queue); - } - if (this->public.send_queue != NULL) - { - this->public.send_queue->destroy(this->public.send_queue); - } - if (this->public.socket != NULL) - { - this->public.socket->destroy(this->public.socket); - } - if (this->public.configuration != NULL) - { - this->public.configuration->destroy(this->public.configuration); - } - if (this->public.credentials != NULL) - { - this->public.credentials->destroy(this->public.credentials); - } - if (this->public.connections != NULL) - { - this->public.connections->destroy(this->public.connections); - } - if (this->public.policies != NULL) - { - this->public.policies->destroy(this->public.policies); - } - if (this->public.stroke != NULL) - { - this->public.stroke->destroy(this->public.stroke); - } - free(this); -} - -void signal_handler(int signal) -{ - void *array[20]; - size_t size; - char **strings; - size_t i; - logger_t *logger; - - size = backtrace(array, 20); - strings = backtrace_symbols(array, size); - logger = logger_manager->get_logger(logger_manager, DAEMON); - - logger->log(logger, ERROR, "Thread %u received SIGSEGV. Dumping %d frames from stack:", pthread_self(), size); - - for (i = 0; i < size; i++) - { - logger->log(logger, ERROR, " %s", strings[i]); - } - free (strings); - logger->log(logger, ERROR, "Killing ourself hard after SIGSEGV"); - kill(getpid(), SIGKILL); -} - -/** - * @brief Create the daemon. - * - * @return created daemon_t - */ -private_daemon_t *daemon_create(void) -{ - private_daemon_t *this = malloc_thing(private_daemon_t); - struct sigaction action; - - /* assign methods */ - this->run = run; - this->destroy = destroy; - this->initialize = initialize; - this->public.kill = (void (*) (daemon_t*,char*))kill_daemon; - - /* NULL members for clean destruction */ - this->public.socket = NULL; - this->public.ike_sa_manager = NULL; - this->public.job_queue = NULL; - this->public.event_queue = NULL; - this->public.send_queue = NULL; - this->public.configuration = NULL; - this->public.credentials = NULL; - this->public.connections = NULL; - this->public.policies = NULL; - this->public.sender= NULL; - this->public.receiver = NULL; - this->public.scheduler = NULL; - this->public.kernel_interface = NULL; - this->public.thread_pool = NULL; - this->public.stroke = NULL; - - this->main_thread_id = pthread_self(); - - /* setup signal handling for all threads */ - sigemptyset(&(this->signal_set)); - sigaddset(&(this->signal_set), SIGSEGV); - sigaddset(&(this->signal_set), SIGINT); - sigaddset(&(this->signal_set), SIGHUP); - sigaddset(&(this->signal_set), SIGTERM); - pthread_sigmask(SIG_BLOCK, &(this->signal_set), 0); - - /* setup SIGSEGV handler for all threads */ - action.sa_handler = signal_handler; - action.sa_mask = this->signal_set; - action.sa_flags = 0; - if (sigaction(SIGSEGV, &action, NULL) == -1) - { - this->logger->log(this->logger, ERROR, "signal handler setup for SIGSEGV failed"); - } - return this; -} - -/** - * Main function, manages the daemon. - */ -int main(int argc, char *argv[]) -{ - private_daemon_t *private_charon; - FILE *pid_file; - struct stat stb; - int i; - - /* trivial argument parsing */ - for (i = 1; i < argc; i++) - { - if (strcmp(argv[i], "--use-syslog") == 0) - { - logger_manager->set_output(logger_manager, ALL_LOGGERS, NULL); - } - } - private_charon = daemon_create(); - charon = (daemon_t*)private_charon; - - private_charon->logger = logger_manager->get_logger(logger_manager, DAEMON); - - /* initialize daemon */ - private_charon->initialize(private_charon); - - /* check/setup PID file */ - if (stat(PID_FILE, &stb) == 0) - { - private_charon->logger->log(private_charon->logger, ERROR, - "charon already running (\""PID_FILE"\" exists)"); - private_charon->destroy(private_charon); - exit(-1); - } - pid_file = fopen(PID_FILE, "w"); - if (pid_file) - { - fprintf(pid_file, "%d\n", getpid()); - fclose(pid_file); - } - - /* run daemon */ - private_charon->run(private_charon); - - /* normal termination, cleanup and exit */ - private_charon->destroy(private_charon); - unlink(PID_FILE); - - return 0; -} - - diff --git a/src/charon/charon/daemon.h b/src/charon/charon/daemon.h deleted file mode 100644 index 5cad1339b..000000000 --- a/src/charon/charon/daemon.h +++ /dev/null @@ -1,337 +0,0 @@ -/** - * @file daemon.h - * - * @brief Interface of daemon_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef DAEMON_H_ -#define DAEMON_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/** - * @defgroup charon charon - * - * @brief IKEv2 keying daemon. - * - * @section Architecture - * - * All IKEv2 stuff is handled in charon. It uses a newer and more flexible - * architecture than pluto. Charon uses a thread-pool, which allows parallel - * execution SA-management. Beside the thread-pool, there are some special purpose - * threads which do their job for the common health of the daemon. - @verbatim - +------+ - | E Q | - | v u |---+ +------+ +------+ - | e e | | | | | IKE- | - | n u | +-----------+ | |--| SA | - | t e | | | | I M | +------+ - +------------+ | - | | Scheduler | | K a | - | receiver | +------+ | | | E n | +------+ - +----+-------+ +-----------+ | - a | | IKE- | - | | +------+ | | S g |--| SA | - +-------+--+ +-----| J Q |---+ +------------+ | A e | +------+ - -| socket | | o u | | | | - r | - +-------+--+ | b e | | Thread- | | | - | | - u | | Pool | | | - +----+-------+ | e |------| |---| | - | sender | +------+ +------------+ +------+ - +----+-------+ - | +------+ - | | S Q | - | | e u | - | | n e | - +------------| d u | - | - e | - +--+---+ - @endverbatim - * The thread-pool is the heart of the architecture. It processes jobs from a - * (fully synchronized) job-queue. Mostly, a job is associated with a specific - * IKE SA. These IKE SAs are synchronized, only one thread can work one an IKE SA. - * This makes it unnecesary to use further synchronisation methods once a IKE SA - * is checked out. The (rather complex) synchronization of IKE SAs is completely - * done in the IKE SA manager. - * The sceduler is responsible for event firing. It waits until a event in the - * (fully synchronized) event-queue is ready for processing and pushes the event - * down to the job-queue. A thread form the pool will pick it up as quick as - * possible. Every thread can queue events or jobs. Furter, an event can place a - * packet in the send-queue. The sender thread waits for those packets and sends - * them over the wire, via the socket. The receiver does exactly the opposite of - * the sender. It waits on the socket, reads in packets an places them on the - * job-queue for further processing by a thread from the pool. - * There are even more threads, not drawn in the upper scheme. The stroke thread - * is responsible for reading and processessing commands from another process. The - * kernel interface thread handles communication from and to the kernel via a - * netlink socket. It waits for kernel events and processes them appropriately. - */ - -/** - * @defgroup config config - * - * Classes implementing configuration related things. - * - * @ingroup charon - */ - -/** - * @defgroup encoding encoding - * - * Classes used to encode and decode IKEv2 messages. - * - * @ingroup charon - */ - - /** - * @defgroup payloads payloads - * - * Classes representing specific IKEv2 payloads. - * - * @ingroup encoding - */ - -/** - * @defgroup network network - * - * Classes for network relevant stuff. - * - * @ingroup charon - */ - -/** - * @defgroup queues queues - * - * Different kind of queues - * (thread save lists). - * - * @ingroup charon - */ - -/** - * @defgroup jobs jobs - * - * Jobs used in job queue and event queue. - * - * @ingroup queues - */ - -/** - * @defgroup sa sa - * - * Security associations for IKE and IPSec, - * and some helper classes. - * - * @ingroup charon - */ - -/** - * @defgroup states states - * - * Varius states in which an IKE SA can be. - * - * @ingroup sa - */ - -/** - * @defgroup threads threads - * - * Threaded classes, which will do their job alone. - * - * @ingroup charon - */ - -/** - * Name of the daemon. - * - * @ingroup charon - */ -#define DAEMON_NAME "charon" - -/** - * @brief Number of threads in the thread pool. - * - * There are several other threads, this defines - * only the number of threads in thread_pool_t. - * - * @ingroup charon - */ -#define NUMBER_OF_WORKING_THREADS 4 - -/** - * UDP Port on which the daemon will listen for incoming traffic. - * - * @ingroup charon - */ -#define IKEV2_UDP_PORT 500 - -/** - * PID file, in which charon stores its process id - * - * @ingroup charon - */ -#define PID_FILE "/var/run/charon.pid" - -/** - * Configuration directory - * - * @ingroup charon - */ -#define CONFIG_DIR "/etc" - -/** - * Directory of IPsec relevant files - * - * @ingroup charon - */ -#define IPSEC_DIR CONFIG_DIR "/ipsec.d" - -/** - * Directory for private keys - * - * @ingroup charon - */ -#define PRIVATE_KEY_DIR IPSEC_DIR "/private" - -/** - * Directory for trusted certificates - * - * @ingroup charon - */ -#define CERTIFICATE_DIR IPSEC_DIR "/certs" - -/** - * Secrets files - * - * @ingroup charon - */ -#define SECRETS_FILE CONFIG_DIR "/ipsec.secrets" - -typedef struct daemon_t daemon_t; - -/** - * @brief Main class of daemon, contains some globals. - * - * @ingroup charon - */ -struct daemon_t { - /** - * A socket_t instance. - */ - socket_t *socket; - - /** - * A send_queue_t instance. - */ - send_queue_t *send_queue; - - /** - * A job_queue_t instance. - */ - job_queue_t *job_queue; - - /** - * A event_queue_t instance. - */ - event_queue_t *event_queue; - - /** - * A ike_sa_manager_t instance. - */ - ike_sa_manager_t *ike_sa_manager; - - /** - * A configuration_t instance. - */ - configuration_t *configuration; - - /** - * A connection_store_t instance. - */ - connection_store_t *connections; - - /** - * A policy_store_t instance. - */ - policy_store_t *policies; - - /** - * A credential_store_t instance. - */ - credential_store_t *credentials; - - /** - * The Sender-Thread. - */ - sender_t *sender; - - /** - * The Receiver-Thread. - */ - receiver_t *receiver; - - /** - * The Scheduler-Thread. - */ - scheduler_t *scheduler; - - /** - * The Thread pool managing the worker threads. - */ - thread_pool_t *thread_pool; - - /** - * Kernel Interface to communicate with kernel - */ - kernel_interface_t *kernel_interface; - - /** - * IPC interface, as whack in pluto - */ - stroke_t *stroke; - - /** - * @brief Shut down the daemon. - * - * @param this the daemon to kill - * @param reason describtion why it will be killed - */ - void (*kill) (daemon_t *this, char *reason); -}; - -/** - * The one and only instance of the daemon. - */ -extern daemon_t *charon; - -#endif /*DAEMON_H_*/ diff --git a/src/charon/charon/encoding/Makefile.encoding b/src/charon/charon/encoding/Makefile.encoding deleted file mode 100644 index ccdb42f79..000000000 --- a/src/charon/charon/encoding/Makefile.encoding +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (C) 2005 Jan Hutter, 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 . -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# for more details. -# - -ENCODING_DIR= $(CHARON_DIR)encoding/ - -CHARON_OBJS+= $(BUILD_DIR)generator.o -$(BUILD_DIR)generator.o : $(ENCODING_DIR)generator.c $(ENCODING_DIR)generator.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)parser.o -$(BUILD_DIR)parser.o : $(ENCODING_DIR)parser.c $(ENCODING_DIR)parser.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)message.o -$(BUILD_DIR)message.o : $(ENCODING_DIR)message.c $(ENCODING_DIR)message.h - $(CC) $(CFLAGS) -c -o $@ $< - - -include $(ENCODING_DIR)payloads/Makefile.payloads \ No newline at end of file diff --git a/src/charon/charon/encoding/generator.c b/src/charon/charon/encoding/generator.c deleted file mode 100644 index ba12190dd..000000000 --- a/src/charon/charon/encoding/generator.c +++ /dev/null @@ -1,1077 +0,0 @@ -/** - * @file generator.c - * - * @brief Implementation of generator_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 -#include -#include -#include - - -#include "generator.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -typedef struct private_generator_t private_generator_t; - -/** - * Private part of a generator_t object. - */ -struct private_generator_t { - /** - * Public part of a generator_t object. - */ - generator_t public; - - /** - * Generates a U_INT-Field type and writes it to buffer. - * - * @param this private_generator_t object - * @param int_type type of U_INT field (U_INT_4, U_INT_8, etc.) - * ATTRIBUTE_TYPE is also generated in this function - * @param offset offset of value in data struct - * @param generator_contexts generator_contexts_t object where the context is written or read from - * @return - * - SUCCESS - * - FAILED if allignment is wrong - */ - void (*generate_u_int_type) (private_generator_t *this,encoding_type_t int_type,u_int32_t offset); - - /** - * Get size of current buffer in bytes. - * - * @param this private_generator_t object - * @return Size of buffer in bytes - */ - size_t (*get_current_buffer_size) (private_generator_t *this); - - /** - * Get free space of current buffer in bytes. - * - * @param this private_generator_t object - * @return space in buffer in bytes - */ - size_t (*get_current_buffer_space) (private_generator_t *this); - - /** - * Get length of data in buffer (in bytes). - * - * @param this private_generator_t object - * @return length of data in bytes - */ - size_t (*get_current_data_length) (private_generator_t *this); - - /** - * Get current offset in buffer (in bytes). - * - * @param this private_generator_t object - * @return offset in bytes - */ - u_int32_t (*get_current_buffer_offset) (private_generator_t *this); - - /** - * Generates a RESERVED BIT field or a RESERVED BYTE field and writes - * it to the buffer. - * - * @param this private_generator_t object - * @param generator_contexts generator_contexts_t object where the context is written or read from - * @param bits number of bits to generate - */ - void (*generate_reserved_field) (private_generator_t *this,int bits); - - /** - * Generates a FLAG field. - * - * @param this private_generator_t object - * @param generator_contexts generator_contexts_t object where the context is written or read from - * @param offset offset of flag value in data struct - */ - void (*generate_flag) (private_generator_t *this,u_int32_t offset); - - /** - * Writes the current buffer content into a chunk_t. - * - * Memory of specific chunk_t gets allocated. - * - * @param this calling private_generator_t object - * @param data pointer of chunk_t to write to - */ - void (*write_chunk) (private_generator_t *this,chunk_t *data); - - /** - * Generates a bytestream from a chunk_t. - * - * @param this private_generator_t object - * @param offset offset of chunk_t value in data struct - */ - void (*generate_from_chunk) (private_generator_t *this,u_int32_t offset); - - /** - * Makes sure enough space is available in buffer to store amount of bits. - * - * If buffer is to small to hold the specific amount of bits it - * is increased using reallocation function of allocator. - * - * @param this calling private_generator_t object - * @param bits number of bits to make available in buffer - */ - void (*make_space_available) (private_generator_t *this,size_t bits); - - /** - * Writes a specific amount of byte into the buffer. - * - * If buffer is to small to hold the specific amount of bytes it - * is increased. - * - * @param this calling private_generator_t object - * @param bytes pointer to bytes to write - * @param number_of_bytes number of bytes to write into buffer - */ - void (*write_bytes_to_buffer) (private_generator_t *this,void * bytes,size_t number_of_bytes); - - - /** - * Writes a specific amount of byte into the buffer at a specific offset. - * - * @warning buffer size is not check to hold the data if offset is to large. - * - * @param this calling private_generator_t object - * @param bytes pointer to bytes to write - * @param number_of_bytes number of bytes to write into buffer - * @param offset offset to write the data into - */ - void (*write_bytes_to_buffer_at_offset) (private_generator_t *this,void * bytes,size_t number_of_bytes,u_int32_t offset); - - /** - * Buffer used to generate the data into. - */ - u_int8_t *buffer; - - /** - * Current write position in buffer (one byte aligned). - */ - u_int8_t *out_position; - - /** - * Position of last byte in buffer. - */ - u_int8_t *roof_position; - - /** - * Current bit writing to in current byte (between 0 and 7). - */ - size_t current_bit; - - /** - * Associated data struct to read informations from. - */ - 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; - - /* - * Attribute format of the last generated transform attribute. - * - * Used to check if a variable value field is used or not for - * the transform attribute value. - */ - bool attribute_format; - - /* - * Depending on the value of attribute_format this field is used - * to hold the length of the transform attribute in bytes. - */ - u_int16_t attribute_length; - - /** - * Associated Logger. - */ - logger_t *logger; -}; - -/** - * Implementation of private_generator_t.get_current_buffer_size. - */ -static size_t get_current_buffer_size (private_generator_t *this) -{ - return ((this->roof_position) - (this->buffer)); -} - -/** - * Implementation of private_generator_t.get_current_buffer_space. - */ -static size_t get_current_buffer_space (private_generator_t *this) -{ - /* we know, one byte more */ - size_t space = (this->roof_position) - (this->out_position); - return (space); -} - -/** - * Implementation of private_generator_t.get_current_data_length. - */ -static size_t get_current_data_length (private_generator_t *this) -{ - return (this->out_position - this->buffer); -} - -/** - * Implementation of private_generator_t.get_current_buffer_offset. - */ -static u_int32_t get_current_buffer_offset (private_generator_t *this) -{ - return (this->out_position - this->buffer); -} - -/** - * Implementation of private_generator_t.generate_u_int_type. - */ -static void generate_u_int_type (private_generator_t *this,encoding_type_t int_type,u_int32_t offset) -{ - size_t number_of_bits = 0; - - /* find out number of bits of each U_INT type to check for enough space - in buffer */ - switch (int_type) - { - case U_INT_4: - number_of_bits = 4; - break; - case TS_TYPE: - case U_INT_8: - number_of_bits = 8; - break; - case U_INT_16: - case CONFIGURATION_ATTRIBUTE_LENGTH: - number_of_bits = 16; - break; - case U_INT_32: - number_of_bits = 32; - break; - case U_INT_64: - number_of_bits = 64; - break; - case ATTRIBUTE_TYPE: - number_of_bits = 15; - break; - case IKE_SPI: - number_of_bits = 64; - break; - - default: - this->logger->log(this->logger, ERROR, "U_INT Type %s is not supported", - mapping_find(encoding_type_m,int_type)); - - return; - } - /* U_INT Types of multiple then 8 bits must be aligned */ - if (((number_of_bits % 8) == 0) && (this->current_bit != 0)) - { - this->logger->log(this->logger, ERROR, "U_INT Type %s is not 8 Bit aligned", - mapping_find(encoding_type_m,int_type)); - /* current bit has to be zero for values multiple of 8 bits */ - return; - } - - /* make sure enough space is available in buffer */ - this->make_space_available(this,number_of_bits); - /* now handle each u int type differently */ - switch (int_type) - { - case U_INT_4: - { - if (this->current_bit == 0) - { - /* highval of current byte in buffer has to be set to the new value*/ - u_int8_t high_val = *((u_int8_t *)(this->data_struct + offset)) << 4; - /* lowval in buffer is not changed */ - u_int8_t low_val = *(this->out_position) & 0x0F; - /* highval is set, low_val is not changed */ - *(this->out_position) = high_val | low_val; - this->logger->log(this->logger, RAW|LEVEL2, " => %d", *(this->out_position)); - /* write position is not changed, just bit position is moved */ - this->current_bit = 4; - } - else if (this->current_bit == 4) - { - /* highval in buffer is not changed */ - u_int high_val = *(this->out_position) & 0xF0; - /* lowval of current byte in buffer has to be set to the new value*/ - u_int low_val = *((u_int8_t *)(this->data_struct + offset)) & 0x0F; - *(this->out_position) = high_val | low_val; - this->logger->log(this->logger, RAW|LEVEL2, " => %d", *(this->out_position)); - this->out_position++; - this->current_bit = 0; - - } - else - { - this->logger->log(this->logger, ERROR, "U_INT_4 Type is not 4 Bit aligned"); - /* 4 Bit integers must have a 4 bit alignment */ - return; - }; - break; - } - case TS_TYPE: - case U_INT_8: - { - /* 8 bit values are written as they are */ - *this->out_position = *((u_int8_t *)(this->data_struct + offset)); - this->logger->log(this->logger, RAW|LEVEL2, " => %d", *(this->out_position)); - this->out_position++; - break; - - } - case ATTRIBUTE_TYPE: - { - /* attribute type must not change first bit uf current byte ! */ - if (this->current_bit != 1) - { - this->logger->log(this->logger, ERROR, "ATTRIBUTE FORMAT flag is not set"); - /* first bit has to be set! */ - return; - } - /* get value of attribute format flag */ - u_int8_t attribute_format_flag = *(this->out_position) & 0x80; - /* get attribute type value as 16 bit integer*/ - u_int16_t int16_val = htons(*((u_int16_t*)(this->data_struct + offset))); - /* last bit must be unset */ - int16_val = int16_val & 0xFF7F; - - int16_val = int16_val | attribute_format_flag; - this->logger->log(this->logger, RAW|LEVEL2, " => %d", int16_val); - /* write bytes to buffer (set bit is overwritten)*/ - this->write_bytes_to_buffer(this,&int16_val,sizeof(u_int16_t)); - this->current_bit = 0; - break; - - } - case U_INT_16: - case CONFIGURATION_ATTRIBUTE_LENGTH: - { - u_int16_t int16_val = htons(*((u_int16_t*)(this->data_struct + offset))); - this->logger->log_bytes(this->logger, RAW|LEVEL2, " =>", (void*)&int16_val, sizeof(int16_val)); - this->write_bytes_to_buffer(this,&int16_val,sizeof(u_int16_t)); - break; - } - case U_INT_32: - { - u_int32_t int32_val = htonl(*((u_int32_t*)(this->data_struct + offset))); - this->logger->log_bytes(this->logger, RAW|LEVEL2, " =>", (void*)&int32_val, sizeof(int32_val)); - this->write_bytes_to_buffer(this,&int32_val,sizeof(u_int32_t)); - break; - } - case U_INT_64: - { - /* 64 bit integers are written as two 32 bit integers */ - u_int32_t int32_val_low = htonl(*((u_int32_t*)(this->data_struct + offset))); - u_int32_t int32_val_high = htonl(*((u_int32_t*)(this->data_struct + offset) + 1)); - this->logger->log_bytes(this->logger, RAW|LEVEL2, " => (low)", (void*)&int32_val_low, sizeof(int32_val_low)); - this->logger->log_bytes(this->logger, RAW|LEVEL2, " => (high)", (void*)&int32_val_high, sizeof(int32_val_high)); - /* TODO add support for big endian machines */ - this->write_bytes_to_buffer(this,&int32_val_high,sizeof(u_int32_t)); - this->write_bytes_to_buffer(this,&int32_val_low,sizeof(u_int32_t)); - break; - } - - case IKE_SPI: - { - /* 64 bit are written as they come :-) */ - this->write_bytes_to_buffer(this,(this->data_struct + offset),sizeof(u_int64_t)); - this->logger->log_bytes(this->logger, RAW|LEVEL2, " =>", (void*)(this->data_struct + offset), sizeof(u_int64_t)); - break; - } - default: - { - this->logger->log(this->logger, ERROR, "U_INT Type %s is not supported", mapping_find(encoding_type_m,int_type)); - return; - } - } -} - -/** - * Implementation of private_generator_t.generate_reserved_field. - */ -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)) - { - this->logger->log(this->logger, ERROR, "Reserved field of %d bits cannot be generated", bits); - return ; - } - /* make sure enough space is available in buffer */ - this->make_space_available(this,bits); - - if (bits == 1) - { - /* one bit processing */ - 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 - { - /* one byte processing*/ - if (this->current_bit > 0) - { - this->logger->log(this->logger, ERROR, - "Reserved field cannot be written cause allignement of current bit is %d", - this->current_bit); - return; - } - *(this->out_position) = 0x00; - this->out_position++; - } -} - -/** - * Implementation of private_generator_t.generate_flag. - */ -static void generate_flag (private_generator_t *this,u_int32_t offset) -{ - /* value of current flag */ - u_int8_t flag_value; - /* position of flag in current byte */ - u_int8_t flag; - - /* if the value in the data_struct is TRUE, flag_value is set to 1, 0 otherwise */ - flag_value = (*((bool *) (this->data_struct + offset))) ? 1 : 0; - /* get flag position */ - flag = (flag_value << (7 - this->current_bit)); - - /* make sure one bit is available in buffer */ - this->make_space_available(this,1); - if (this->current_bit == 0) - { - /* memory must be zero */ - *(this->out_position) = 0x00; - } - - *(this->out_position) = *(this->out_position) | flag; - - - this->logger->log(this->logger, RAW|LEVEL2, " => %d", *(this->out_position)); - - this->current_bit++; - if (this->current_bit >= 8) - { - this->current_bit = this->current_bit % 8; - this->out_position++; - } -} - -/** - * Implementation of private_generator_t.generate_from_chunk. - */ -static void generate_from_chunk (private_generator_t *this,u_int32_t offset) -{ - if (this->current_bit != 0) - { - this->logger->log(this->logger, ERROR, "can not generate a chunk at Bitpos %d", this->current_bit); - return ; - } - - /* position in buffer */ - chunk_t *attribute_value = (chunk_t *)(this->data_struct + offset); - - this->logger->log_chunk(this->logger, RAW|LEVEL2, " =>", *attribute_value); - - /* use write_bytes_to_buffer function to do the job */ - this->write_bytes_to_buffer(this,attribute_value->ptr,attribute_value->len); -} - -/** - * Implementation of private_generator_t.make_space_available. - */ -static void make_space_available (private_generator_t *this, size_t bits) -{ - while (((this->get_current_buffer_space(this) * 8) - this->current_bit) < bits) - { - /* must increase buffer */ - size_t old_buffer_size = this->get_current_buffer_size(this); - size_t new_buffer_size = old_buffer_size + GENERATOR_DATA_BUFFER_INCREASE_VALUE; - size_t out_position_offset = ((this->out_position) - (this->buffer)); - - this->logger->log(this->logger, CONTROL|LEVEL3, "increased gen buffer from %d to %d byte", - old_buffer_size, new_buffer_size); - - /* Reallocate space for new buffer */ - this->buffer = realloc(this->buffer,new_buffer_size); - - this->out_position = (this->buffer + out_position_offset); - this->roof_position = (this->buffer + new_buffer_size); - } -} - -/** - * Implementation of private_generator_t.write_bytes_to_buffer. - */ -static void write_bytes_to_buffer (private_generator_t *this,void * bytes, size_t number_of_bytes) -{ - int i; - u_int8_t *read_position = (u_int8_t *) bytes; - - this->make_space_available(this,number_of_bytes * 8); - - for (i = 0; i < number_of_bytes; i++) - { - *(this->out_position) = *(read_position); - read_position++; - this->out_position++; - } -} - -/** - * Implementation of private_generator_t.write_bytes_to_buffer_at_offset. - */ -static void write_bytes_to_buffer_at_offset (private_generator_t *this,void * bytes,size_t 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 = (this->get_current_buffer_size(this) - offset); - - /* check first if enough space for new data is available */ - if (number_of_bytes > free_space_after_offset) - { - this->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++; - } -} - -/** - * Implementation of private_generator_t.write_to_chunk. - */ -static void write_to_chunk (private_generator_t *this,chunk_t *data) -{ - size_t data_length = this->get_current_data_length(this); - u_int32_t header_length_field = data_length; - - /* write length into header length field */ - if (this->header_length_position_offset > 0) - { - u_int32_t int32_val = htonl(header_length_field); - this->write_bytes_to_buffer_at_offset(this,&int32_val,sizeof(u_int32_t),this->header_length_position_offset); - } - - if (this->current_bit > 0) - data_length++; - data->ptr = malloc(data_length); - memcpy(data->ptr,this->buffer,data_length); - data->len = data_length; - - this->logger->log_chunk(this->logger, RAW|LEVEL3, "generated data of this generator", *data); -} - -/** - * Implementation of private_generator_t.generate_payload. - */ -static void generate_payload (private_generator_t *this,payload_t *payload) -{ - int i; - this->data_struct = payload; - size_t rule_count; - encoding_rule_t *rules; - payload_type_t payload_type; - u_int8_t *payload_start; - - /* get payload type */ - payload_type = payload->get_type(payload); - /* spi size has to get reseted */ - this->last_spi_size = 0; - - payload_start = this->out_position; - - this->logger->log(this->logger, CONTROL|LEVEL1, "generating payload of type %s", - mapping_find(payload_type_m,payload_type)); - - /* each payload has its own encoding rules */ - payload->get_encoding_rules(payload,&rules,&rule_count); - - for (i = 0; i < rule_count;i++) - { - this->logger->log(this->logger, CONTROL|LEVEL2, " generating rule %d %s", - i, mapping_find(encoding_type_m,rules[i].type)); - switch (rules[i].type) - { - /* all u int values, IKE_SPI,TS_TYPE and ATTRIBUTE_TYPE are generated in generate_u_int_type */ - case U_INT_4: - case U_INT_8: - case U_INT_16: - case U_INT_32: - case U_INT_64: - case IKE_SPI: - case TS_TYPE: - case ATTRIBUTE_TYPE: - case CONFIGURATION_ATTRIBUTE_LENGTH: - { - this->generate_u_int_type(this,rules[i].type,rules[i].offset); - break; - } - case RESERVED_BIT: - { - this->generate_reserved_field(this,1); - break; - } - case RESERVED_BYTE: - { - this->generate_reserved_field(this,8); - break; - } - case FLAG: - { - this->generate_flag(this,rules[i].offset); - break; - } - case PAYLOAD_LENGTH: - { - /* position of payload lenght field is temporary stored */ - this->last_payload_length_position_offset = this->get_current_buffer_offset(this); - /* payload length is generated like an U_INT_16 */ - this->generate_u_int_type(this,U_INT_16,rules[i].offset); - break; - } - case HEADER_LENGTH: - { - /* position of header length field is temporary stored */ - this->header_length_position_offset = this->get_current_buffer_offset(this); - /* header length is generated like an U_INT_32 */ - this->generate_u_int_type(this,U_INT_32,rules[i].offset); - break; - } - case SPI_SIZE: - /* spi size is handled as 8 bit unsigned integer */ - this->generate_u_int_type(this,U_INT_8,rules[i].offset); - /* last spi size is temporary stored */ - this->last_spi_size = *((u_int8_t *)(this->data_struct + rules[i].offset)); - break; - case ADDRESS: - { - /* the Address value is generated from chunk */ - this->generate_from_chunk(this,rules[i].offset); - break; - } - case SPI: - { - /* the SPI value is generated from chunk */ - this->generate_from_chunk(this,rules[i].offset); - break; - } - case KEY_EXCHANGE_DATA: - case NOTIFICATION_DATA: - case NONCE_DATA: - case ID_DATA: - case AUTH_DATA: - case CERT_DATA: - case CERTREQ_DATA: - case SPIS: - case CONFIGURATION_ATTRIBUTE_VALUE: - case VID_DATA: - case EAP_MESSAGE: - { - 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_MESSAGE: - header_length = EAP_PAYLOAD_HEADER_LENGTH; - break; - default: - break; - } - - /* the data value is generated from chunk */ - this->generate_from_chunk(this,rules[i].offset); - - payload_length_position_offset = this->last_payload_length_position_offset; - - - /* Length of payload is calculated */ - length_of_payload = header_length + ((chunk_t *)(this->data_struct + rules[i].offset))->len; - - length_in_network_order = htons(length_of_payload); - this->write_bytes_to_buffer_at_offset(this,&length_in_network_order,sizeof(u_int16_t),payload_length_position_offset); - break; - } - case PROPOSALS: - { - /* before iterative generate the transforms, store the current payload length position */ - 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; - /* proposals are stored in a linked list and so accessed */ - linked_list_t *proposals = *((linked_list_t **)(this->data_struct + rules[i].offset)); - - iterator_t *iterator; - /* create forward iterator */ - iterator = proposals->create_iterator(proposals,TRUE); - /* every proposal is processed (iterative call )*/ - while (iterator->has_next(iterator)) - { - payload_t *current_proposal; - u_int32_t before_generate_position_offset; - u_int32_t after_generate_position_offset; - - iterator->current(iterator,(void **)¤t_proposal); - - before_generate_position_offset = this->get_current_buffer_offset(this); - this->public.generate_payload(&(this->public),current_proposal); - after_generate_position_offset = this->get_current_buffer_offset(this); - - /* increase size of transform */ - length_of_sa_payload += (after_generate_position_offset - before_generate_position_offset); - } - iterator->destroy(iterator); - - int16_val = htons(length_of_sa_payload); - this->write_bytes_to_buffer_at_offset(this,&int16_val,sizeof(u_int16_t),payload_length_position_offset); - break; - } - case TRANSFORMS: - { - /* before iterative generate the transforms, store the current length position */ - 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; - - /* create forward iterator */ - iterator = transforms->create_iterator(transforms,TRUE); - while (iterator->has_next(iterator)) - { - payload_t *current_transform; - u_int32_t before_generate_position_offset; - u_int32_t after_generate_position_offset; - - iterator->current(iterator,(void **)¤t_transform); - - before_generate_position_offset = this->get_current_buffer_offset(this); - this->public.generate_payload(&(this->public),current_transform); - after_generate_position_offset = this->get_current_buffer_offset(this); - - /* increase size of transform */ - length_of_proposal += (after_generate_position_offset - before_generate_position_offset); - } - - iterator->destroy(iterator); - - int16_val = htons(length_of_proposal); - this->write_bytes_to_buffer_at_offset(this,&int16_val,sizeof(u_int16_t),payload_length_position_offset); - - break; - } - case TRANSFORM_ATTRIBUTES: - { - /* before iterative generate the transform attributes, store the current length position */ - 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; - /* create forward iterator */ - iterator = transform_attributes->create_iterator(transform_attributes,TRUE); - while (iterator->has_next(iterator)) - { - payload_t *current_attribute; - u_int32_t before_generate_position_offset; - u_int32_t after_generate_position_offset; - - iterator->current(iterator,(void **)¤t_attribute); - - before_generate_position_offset = this->get_current_buffer_offset(this); - this->public.generate_payload(&(this->public),current_attribute); - after_generate_position_offset = this->get_current_buffer_offset(this); - - /* increase size of transform */ - length_of_transform += (after_generate_position_offset - before_generate_position_offset); - } - - iterator->destroy(iterator); - - int16_val = htons(length_of_transform); - this->write_bytes_to_buffer_at_offset(this,&int16_val,sizeof(u_int16_t),transform_length_position_offset); - - break; - } - case CONFIGURATION_ATTRIBUTES: - { - /* before iterative generate the configuration attributes, store the current length position */ - 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; - /* create forward iterator */ - iterator = configuration_attributes->create_iterator(configuration_attributes,TRUE); - while (iterator->has_next(iterator)) - { - payload_t *current_attribute; - u_int32_t before_generate_position_offset; - u_int32_t after_generate_position_offset; - - iterator->current(iterator,(void **)¤t_attribute); - - before_generate_position_offset = this->get_current_buffer_offset(this); - this->public.generate_payload(&(this->public),current_attribute); - after_generate_position_offset = this->get_current_buffer_offset(this); - - /* increase size of transform */ - length_of_configurations += (after_generate_position_offset - before_generate_position_offset); - } - - iterator->destroy(iterator); - - int16_val = htons(length_of_configurations); - this->write_bytes_to_buffer_at_offset(this,&int16_val,sizeof(u_int16_t),configurations_length_position_offset); - - break; - } - case ATTRIBUTE_FORMAT: - { - this->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) - { - this->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 - { - this->generate_u_int_type(this,U_INT_16,rules[i].offset); - } - break; - } - case ATTRIBUTE_VALUE: - { - if (this->attribute_format == FALSE) - { - this->logger->log(this->logger, CONTROL|LEVEL3, "attribute value has not fixed size"); - /* the attribute value is generated */ - this->generate_from_chunk(this,rules[i].offset); - } - break; - } - case TRAFFIC_SELECTORS: - { - /* before iterative generate the traffic_selectors, store the current payload length position */ - u_int32_t payload_length_position_offset = this->last_payload_length_position_offset; - /* Length of SA_PAYLOAD is calculated */ - u_int16_t length_of_ts_payload = TS_PAYLOAD_HEADER_LENGTH; - u_int16_t int16_val; - /* traffic selectors are stored in a linked list and so accessed */ - linked_list_t *traffic_selectors = *((linked_list_t **)(this->data_struct + rules[i].offset)); - - iterator_t *iterator; - /* create forward iterator */ - iterator = traffic_selectors->create_iterator(traffic_selectors,TRUE); - /* every proposal is processed (iterative call )*/ - while (iterator->has_next(iterator)) - { - payload_t *current_traffic_selector_substructure; - u_int32_t before_generate_position_offset; - u_int32_t after_generate_position_offset; - - iterator->current(iterator,(void **)¤t_traffic_selector_substructure); - - before_generate_position_offset = this->get_current_buffer_offset(this); - this->public.generate_payload(&(this->public),current_traffic_selector_substructure); - after_generate_position_offset = this->get_current_buffer_offset(this); - - /* increase size of transform */ - length_of_ts_payload += (after_generate_position_offset - before_generate_position_offset); - } - iterator->destroy(iterator); - - int16_val = htons(length_of_ts_payload); - this->write_bytes_to_buffer_at_offset(this,&int16_val,sizeof(u_int16_t),payload_length_position_offset); - break; - } - - case ENCRYPTED_DATA: - { - this->generate_from_chunk(this, rules[i].offset); - break; - } - default: - this->logger->log(this->logger, ERROR, "field type %s is not supported", - mapping_find(encoding_type_m,rules[i].type)); - return; - } - } - this->logger->log(this->logger, CONTROL|LEVEL2, "generating %s payload finished.", - mapping_find(payload_type_m, payload_type)); - this->logger->log_bytes(this->logger, RAW|LEVEL3, "generated data for this payload", - payload_start, this->out_position-payload_start); -} - -/** - * Implementation of generator_t.destroy. - */ -static status_t destroy(private_generator_t *this) -{ - free(this->buffer); - free(this); - return SUCCESS; -} - -/* - * Described in header - */ -generator_t *generator_create() -{ - private_generator_t *this; - - this = malloc_thing(private_generator_t); - - /* initiate public functions */ - this->public.generate_payload = (void(*)(generator_t*, payload_t *)) generate_payload; - this->public.destroy = (void(*)(generator_t*)) destroy; - this->public.write_to_chunk = (void (*) (generator_t *,chunk_t *)) write_to_chunk; - - - /* initiate private functions */ - this->get_current_buffer_size = get_current_buffer_size; - this->get_current_buffer_space = get_current_buffer_space; - this->get_current_data_length = get_current_data_length; - this->get_current_buffer_offset = get_current_buffer_offset; - this->generate_u_int_type = generate_u_int_type; - this->generate_reserved_field = generate_reserved_field; - this->generate_flag = generate_flag; - this->generate_from_chunk = generate_from_chunk; - this->make_space_available = make_space_available; - this->write_bytes_to_buffer = write_bytes_to_buffer; - this->write_bytes_to_buffer_at_offset = write_bytes_to_buffer_at_offset; - - - /* allocate memory for buffer */ - this->buffer = malloc(GENERATOR_DATA_BUFFER_SIZE); - - /* initiate private variables */ - this->out_position = this->buffer; - this->roof_position = this->buffer + GENERATOR_DATA_BUFFER_SIZE; - this->data_struct = NULL; - this->current_bit = 0; - this->last_payload_length_position_offset = 0; - this->header_length_position_offset = 0; - this->logger = logger_manager->get_logger(logger_manager, GENERATOR); - - return &(this->public); -} diff --git a/src/charon/charon/encoding/generator.h b/src/charon/charon/encoding/generator.h deleted file mode 100644 index 4bbca162a..000000000 --- a/src/charon/charon/encoding/generator.h +++ /dev/null @@ -1,101 +0,0 @@ -/** - * @file generator.h - * - * @brief Interface of generator_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef GENERATOR_H_ -#define GENERATOR_H_ - -#include -#include -#include - -/** - * Generating is done in a data buffer. - * This is thehe start size of this buffer in bytes. - * - * @ingroup enconding - */ -#define GENERATOR_DATA_BUFFER_SIZE 500 - -/** - * Number of bytes to increase the buffer, if it is to small. - * - * @ingroup enconding - */ -#define GENERATOR_DATA_BUFFER_INCREASE_VALUE 500 - - -typedef struct generator_t generator_t; - -/** - * @brief A generator_t class used to generate IKEv2 payloads. - * - * After creation, multiple payloads can be generated with the generate_payload - * method. The generated bytes are appended. After all payloads are added, - * the write_to_chunk method writes out all generated data since - * the creation of the generator. After that, the generator must be destroyed. - * The generater uses a set of encoding rules, which it can get from - * the supplied payload. With this rules, the generater can generate - * the payload and all substructures automatically. - * - * @b Constructor: - * - generator_create() - * - * @ingroup encoding - */ -struct generator_t { - - /** - * @brief Generates a specific payload from given payload object. - * - * Remember: Header and substructures are also handled as payloads. - * - * @param this generator_t object - * @param[in] payload interface payload_t implementing object - */ - void (*generate_payload) (generator_t *this,payload_t *payload); - - /** - * @brief Writes all generated data of the generator to a chunk. - * - * @param this generator_t object - * @param[out] data chunk to write the data to - */ - void (*write_to_chunk) (generator_t *this,chunk_t *data); - - /** - * @brief Destroys a generator_t object. - * - * @param this generator_t object - */ - void (*destroy) (generator_t *this); -}; - -/** - * @brief Constructor to create a generator. - * - * @return generator_t object. - * - * @ingroup encoding - */ -generator_t *generator_create(void); - -#endif /*GENERATOR_H_*/ diff --git a/src/charon/charon/encoding/message.c b/src/charon/charon/encoding/message.c deleted file mode 100644 index a57315272..000000000 --- a/src/charon/charon/encoding/message.c +++ /dev/null @@ -1,1251 +0,0 @@ -/** - * @file message.c - * - * @brief Implementation of message_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 - -#include "message.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/** - * Max number of notify payloads per IKEv2 Message - */ -#define MAX_NOTIFY_PAYLOADS 10 - - -typedef struct payload_rule_t payload_rule_t; - -/** - * A payload rule defines the rules for a payload - * in a specific message rule. It defines if and how - * many times a payload must/can occur in a message - * and if it must be encrypted. - */ -struct payload_rule_t { - /** - * Payload type. - */ - payload_type_t payload_type; - - /** - * Minimal occurence of this payload. - */ - size_t min_occurence; - - /** - * Max occurence of this payload. - */ - size_t max_occurence; - - /** - * TRUE if payload must be encrypted - */ - bool encrypted; - - /** - * If this payload occurs, the message rule is - * fullfilled in any case. This applies e.g. to - * notify_payloads. - */ - bool sufficient; -}; - -typedef struct message_rule_t message_rule_t; - -/** - * A message rule defines the kind of a message, - * if it has encrypted contents and a list - * of payload rules. - * - */ -struct message_rule_t { - /** - * Type of message. - */ - exchange_type_t exchange_type; - - /** - * Is message a request or response. - */ - bool is_request; - - /** - * Message contains encrypted content. - */ - bool encrypted_content; - - /** - * Number of payload rules which will follow - */ - size_t payload_rule_count; - - /** - * Pointer to first payload rule - */ - payload_rule_t *payload_rules; -}; - -/** - * Message rule for IKE_SA_INIT from initiator. - */ -static payload_rule_t ike_sa_init_i_payload_rules[] = { - {NOTIFY,0,MAX_NOTIFY_PAYLOADS,FALSE,FALSE}, - {SECURITY_ASSOCIATION,1,1,FALSE,FALSE}, - {KEY_EXCHANGE,1,1,FALSE,FALSE}, - {NONCE,1,1,FALSE,FALSE}, -}; - -/** - * Message rule for IKE_SA_INIT from responder. - */ -static payload_rule_t ike_sa_init_r_payload_rules[] = { - {NOTIFY,0,MAX_NOTIFY_PAYLOADS,FALSE,TRUE}, - {SECURITY_ASSOCIATION,1,1,FALSE,FALSE}, - {KEY_EXCHANGE,1,1,FALSE,FALSE}, - {NONCE,1,1,FALSE,FALSE}, -}; - -/** - * Message rule for IKE_AUTH from initiator. - */ -static payload_rule_t ike_auth_i_payload_rules[] = { - {NOTIFY,0,MAX_NOTIFY_PAYLOADS,TRUE,FALSE}, - {ID_INITIATOR,1,1,TRUE,FALSE}, - {CERTIFICATE,0,1,TRUE,FALSE}, - {CERTIFICATE_REQUEST,0,1,TRUE,FALSE}, - {ID_RESPONDER,0,1,TRUE,FALSE}, - {AUTHENTICATION,1,1,TRUE,FALSE}, - {SECURITY_ASSOCIATION,1,1,TRUE,FALSE}, - {TRAFFIC_SELECTOR_INITIATOR,1,1,TRUE,FALSE}, - {TRAFFIC_SELECTOR_RESPONDER,1,1,TRUE,FALSE}, - {CONFIGURATION,0,1,TRUE,FALSE}, -}; - -/** - * Message rule for IKE_AUTH from responder. - */ -static payload_rule_t ike_auth_r_payload_rules[] = { - {NOTIFY,0,MAX_NOTIFY_PAYLOADS,TRUE,TRUE}, - {CERTIFICATE,0,1,TRUE,FALSE}, - {ID_RESPONDER,1,1,TRUE,FALSE}, - {AUTHENTICATION,1,1,TRUE,FALSE}, - {SECURITY_ASSOCIATION,1,1,TRUE,FALSE}, - {TRAFFIC_SELECTOR_INITIATOR,1,1,TRUE,FALSE}, - {TRAFFIC_SELECTOR_RESPONDER,1,1,TRUE,FALSE}, - {CONFIGURATION,0,1,TRUE,FALSE}, -}; - - -/** - * Message rule for INFORMATIONAL from initiator. - */ -static payload_rule_t informational_i_payload_rules[] = { - {NOTIFY,0,MAX_NOTIFY_PAYLOADS,TRUE,FALSE}, - {CONFIGURATION,0,1,TRUE,FALSE}, - {DELETE,0,1,TRUE,FALSE}, - -}; - -/** - * Message rule for INFORMATIONAL from responder. - */ -static payload_rule_t informational_r_payload_rules[] = { - {NOTIFY,0,MAX_NOTIFY_PAYLOADS,TRUE,FALSE}, - {CONFIGURATION,0,1,TRUE,FALSE}, - {DELETE,0,1,TRUE,FALSE}, -}; - - -/** - * Message rules, defines allowed payloads. - */ -static message_rule_t message_rules[] = { - {IKE_SA_INIT,TRUE,FALSE,(sizeof(ike_sa_init_i_payload_rules)/sizeof(payload_rule_t)),ike_sa_init_i_payload_rules}, - {IKE_SA_INIT,FALSE,FALSE,(sizeof(ike_sa_init_r_payload_rules)/sizeof(payload_rule_t)),ike_sa_init_r_payload_rules}, - {IKE_AUTH,TRUE,TRUE,(sizeof(ike_auth_i_payload_rules)/sizeof(payload_rule_t)),ike_auth_i_payload_rules}, - {IKE_AUTH,FALSE,TRUE,(sizeof(ike_auth_r_payload_rules)/sizeof(payload_rule_t)),ike_auth_r_payload_rules}, - {INFORMATIONAL,TRUE,TRUE,(sizeof(informational_i_payload_rules)/sizeof(payload_rule_t)),informational_i_payload_rules}, - {INFORMATIONAL,FALSE,TRUE,(sizeof(informational_r_payload_rules)/sizeof(payload_rule_t)),informational_r_payload_rules} -}; - - -typedef struct private_message_t private_message_t; - -/** - * Private data of an message_t object. - */ -struct private_message_t { - - /** - * Public part of a message_t object. - */ - message_t public; - - /** - * Minor version of message. - */ - u_int8_t major_version; - - /** - * Major version of message. - */ - u_int8_t minor_version; - - /** - * First Payload in message. - */ - payload_type_t first_payload; - - /** - * Assigned exchange type. - */ - exchange_type_t exchange_type; - - /** - * TRUE if message is a request, FALSE if a reply. - */ - bool is_request; - - /** - * Message ID of this message. - */ - u_int32_t message_id; - - /** - * ID of assigned IKE_SA. - */ - ike_sa_id_t *ike_sa_id; - - /** - * Assigned UDP packet, stores incoming packet or last generated one. - */ - packet_t *packet; - - /** - * Linked List where payload data are stored in. - */ - linked_list_t *payloads; - - /** - * Assigned parser to parse Header and Body of this message. - */ - parser_t *parser; - - /** - * The message rule for this message instance - */ - message_rule_t *message_rule; - - /** - * Assigned logger. - */ - logger_t *logger; - - /** - * Sets the private message_rule member to the rule which - * applies to this message. Must be called before get_payload_rule(). - * - * @param this calling object - * @return - * - SUCCESS - * - NOT_FOUND if no message rule applies to this message. - */ - status_t (*set_message_rule) (private_message_t *this); - - /** - * Gets the payload_rule_t for a specific message_rule_t and payload type. - * - * @param this calling object - * @param payload_type payload type - * @param[out] payload_rule returned payload_rule_t - * @return - * - SUCCESS - * - NOT_FOUND if payload not defined in current message rule - * - INVALID_STATE if message rule is not set via set_message_rule() - */ - status_t (*get_payload_rule) (private_message_t *this, payload_type_t payload_type, payload_rule_t **payload_rule); - - /** - * Encrypts all payloads which has to get encrypted. - * - * Can also be called with messages not containing encrypted content. - * - * @param this calling object - * @param crypter crypter_t object - * @param signer signer_t object - * @return - * - SUCCESS - * - INVALID_STATE if no crypter/signer supplied but needed - */ - status_t (*encrypt_payloads) (private_message_t *this,crypter_t *crypter, signer_t* signer); - - /** - * Decrypts encrypted contents, and checks if a payload is encrypted if it has to be. - * - * @param this calling object - * @param crypter crypter_t object - * @param signer signer_t object - * @return - * - SUCCESS - * - FAILED if decryption not successfull - * - INVALID_STATE if no crypter/signer supplied but needed - */ - status_t (*decrypt_payloads) (private_message_t *this,crypter_t *crypter, signer_t* signer); - - /** - * Verifies the message. Checks for payloads count. - * - * @param calling object - * @return - * - SUCCESS if message valid, or - * - FAILED if message does not align with message rules. - */ - status_t (*verify) (private_message_t *this); -}; - -/** - * Implementation of private_message_t.set_message_rule. - */ -static status_t set_message_rule(private_message_t *this) -{ - int i; - - for (i = 0; i < (sizeof(message_rules) / sizeof(message_rule_t)); i++) - { - if ((this->exchange_type == message_rules[i].exchange_type) && - (this->is_request == message_rules[i].is_request)) - { - /* found rule for given exchange_type*/ - this->message_rule = &(message_rules[i]); - return SUCCESS; - } - } - this->message_rule = NULL; - return NOT_FOUND; -} - -/** - * Implementation of private_message_t.get_payload_rule. - */ -static status_t get_payload_rule(private_message_t *this, payload_type_t payload_type, payload_rule_t **payload_rule) -{ - int i; - - for (i = 0; i < this->message_rule->payload_rule_count;i++) - { - if (this->message_rule->payload_rules[i].payload_type == payload_type) - { - *payload_rule = &(this->message_rule->payload_rules[i]); - return SUCCESS; - } - } - - *payload_rule = NULL; - return NOT_FOUND; -} - -/** - * Implementation of message_t.set_ike_sa_id. - */ -static void set_ike_sa_id (private_message_t *this,ike_sa_id_t *ike_sa_id) -{ - this->ike_sa_id = ike_sa_id->clone(ike_sa_id); -} - -/** - * Implementation of message_t.get_ike_sa_id. - */ -static status_t get_ike_sa_id (private_message_t *this,ike_sa_id_t **ike_sa_id) -{ - if (this->ike_sa_id == NULL) - { - return FAILED; - } - *ike_sa_id = this->ike_sa_id->clone(this->ike_sa_id); - return SUCCESS; -} - -/** - * Implementation of message_t.set_message_id. - */ -static void set_message_id (private_message_t *this,u_int32_t message_id) -{ - this->message_id = message_id; -} - -/** - * Implementation of message_t.get_message_id. - */ -static u_int32_t get_message_id (private_message_t *this) -{ - return this->message_id; -} - -/** - * Implementation of message_t.get_responder_spi. - */ -static u_int64_t get_responder_spi (private_message_t *this) -{ - return (this->ike_sa_id->get_responder_spi(this->ike_sa_id)); -} - -/** - * Implementation of message_t.set_major_version. - */ -static void set_major_version (private_message_t *this,u_int8_t major_version) -{ - this->major_version = major_version; -} - - -/** - * Implementation of message_t.set_major_version. - */ -static u_int8_t get_major_version (private_message_t *this) -{ - return this->major_version; -} - -/** - * Implementation of message_t.set_minor_version. - */ -static void set_minor_version (private_message_t *this,u_int8_t minor_version) -{ - this->minor_version = minor_version; -} - -/** - * Implementation of message_t.get_minor_version. - */ -static u_int8_t get_minor_version (private_message_t *this) -{ - return this->minor_version; -} - -/** - * Implementation of message_t.set_exchange_type. - */ -static void set_exchange_type (private_message_t *this,exchange_type_t exchange_type) -{ - this->exchange_type = exchange_type; -} - -/** - * Implementation of message_t.get_exchange_type. - */ -static exchange_type_t get_exchange_type (private_message_t *this) -{ - return this->exchange_type; -} - -/** - * Implementation of message_t.set_request. - */ -static void set_request (private_message_t *this,bool request) -{ - this->is_request = request; -} - -/** - * Implementation of message_t.get_request. - */ -static exchange_type_t get_request (private_message_t *this) -{ - return this->is_request; -} - -/** - * Implementation of message_t.add_payload. - */ -static void add_payload(private_message_t *this, payload_t *payload) -{ - payload_t *last_payload; - if (this->payloads->get_count(this->payloads) > 0) - { - this->payloads->get_last(this->payloads,(void **) &last_payload); - last_payload->set_next_type(last_payload, payload->get_type(payload)); - } - else - { - this->first_payload = payload->get_type(payload); - } - payload->set_next_type(payload, NO_PAYLOAD); - this->payloads->insert_last(this->payloads, (void*)payload); - - this->logger->log(this->logger, CONTROL|LEVEL1, "Added payload of type %s to message", - mapping_find(payload_type_m, payload->get_type(payload))); -} - -/** - * Implementation of message_t.set_source. - */ -static void set_source(private_message_t *this, host_t *host) -{ - this->packet->set_source(this->packet, host); -} - -/** - * Implementation of message_t.set_destination. - */ -static void set_destination(private_message_t *this, host_t *host) -{ - - this->packet->set_destination(this->packet, host); -} - -/** - * Implementation of message_t.get_source. - */ -static host_t* get_source(private_message_t *this) -{ - return this->packet->get_source(this->packet); -} - -/** - * Implementation of message_t.get_destination. - */ -static host_t * get_destination(private_message_t *this) -{ - return this->packet->get_destination(this->packet); -} - -/** - * Implementation of message_t.get_destination. - */ -static iterator_t *get_payload_iterator(private_message_t *this) -{ - return this->payloads->create_iterator(this->payloads, TRUE); -} - - -/** - * Implementation of message_t.generate. - */ -static status_t generate(private_message_t *this, crypter_t *crypter, signer_t* signer, packet_t **packet) -{ - generator_t *generator; - ike_header_t *ike_header; - payload_t *payload, *next_payload; - iterator_t *iterator; - status_t status; - chunk_t packet_data; - - this->logger->log(this->logger, CONTROL, "Generating message of type %s, contains %d payloads", - mapping_find(exchange_type_m,this->exchange_type), - this->payloads->get_count(this->payloads)); - - if (this->exchange_type == EXCHANGE_TYPE_UNDEFINED) - { - this->logger->log(this->logger, ERROR | LEVEL1, "Exchange type %s is not defined", - mapping_find(exchange_type_m,this->exchange_type)); - return INVALID_STATE; - } - - if (this->packet->get_source(this->packet) == NULL || - this->packet->get_destination(this->packet) == NULL) - { - this->logger->log(this->logger, ERROR|LEVEL1, "%s not defined", - !this->packet->get_source(this->packet) ? "source" : "destination"); - return INVALID_STATE; - } - - /* set the rules for this messge */ - status = this->set_message_rule(this); - if (status != SUCCESS) - { - this->logger->log(this->logger, ERROR, "No message rules specified for a %s %s", - mapping_find(exchange_type_m,this->exchange_type), - this->is_request ? "request" : "response"); - return NOT_SUPPORTED; - } - - - /* going to encrypt all content which have to be encrypted */ - status = this->encrypt_payloads(this, crypter, signer); - if (status != SUCCESS) - { - this->logger->log(this->logger, ERROR | LEVEL1, "Could not encrypt payloads"); - return status; - } - - /* build ike header */ - ike_header = ike_header_create(); - - 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_initiator_flag(ike_header, this->ike_sa_id->is_initiator(this->ike_sa_id)); - ike_header->set_initiator_spi(ike_header, this->ike_sa_id->get_initiator_spi(this->ike_sa_id)); - ike_header->set_responder_spi(ike_header, this->ike_sa_id->get_responder_spi(this->ike_sa_id)); - - generator = generator_create(); - - payload = (payload_t*)ike_header; - - - /* generate every payload expect last one, this is doen later*/ - iterator = this->payloads->create_iterator(this->payloads, TRUE); - while(iterator->has_next(iterator)) - { - iterator->current(iterator, (void**)&next_payload); - payload->set_next_type(payload, next_payload->get_type(next_payload)); - generator->generate_payload(generator, payload); - payload = next_payload; - } - iterator->destroy(iterator); - - /* last payload has no next payload*/ - payload->set_next_type(payload, NO_PAYLOAD); - - generator->generate_payload(generator, payload); - - ike_header->destroy(ike_header); - - /* build packet */ - generator->write_to_chunk(generator, &packet_data); - generator->destroy(generator); - - /* if last payload is of type encrypted, integrity checksum if necessary */ - if (payload->get_type(payload) == ENCRYPTED) - { - this->logger->log(this->logger, CONTROL | LEVEL1, "Build signature on whole message"); - encryption_payload_t *encryption_payload = (encryption_payload_t*)payload; - status = encryption_payload->build_signature(encryption_payload, packet_data); - if (status != SUCCESS) - { - return status; - } - } - - this->packet->set_data(this->packet, packet_data); - - /* clone packet for caller */ - *packet = this->packet->clone(this->packet); - - this->logger->log(this->logger, CONTROL|LEVEL1, "Message of type %s generated successfully", - mapping_find(exchange_type_m,this->exchange_type)); - return SUCCESS; -} - -/** - * Implementation of message_t.get_packet. - */ -static packet_t *get_packet (private_message_t *this) -{ - return this->packet->clone(this->packet); -} - -/** - * Implementation of message_t.get_packet_data. - */ -static chunk_t get_packet_data (private_message_t *this) -{ - return chunk_clone(this->packet->get_data(this->packet)); -} - -/** - * Implementation of message_t.parse_header. - */ -static status_t parse_header(private_message_t *this) -{ - ike_header_t *ike_header; - status_t status; - - - this->logger->log(this->logger, CONTROL|LEVEL1, "parsing Header of message"); - - this->parser->reset_context(this->parser); - status = this->parser->parse_payload(this->parser,HEADER,(payload_t **) &ike_header); - if (status != SUCCESS) - { - this->logger->log(this->logger, ERROR | LEVEL1, "Header could not be parsed"); - return status; - - } - - /* verify payload */ - status = ike_header->payload_interface.verify(&(ike_header->payload_interface)); - if (status != SUCCESS) - { - this->logger->log(this->logger, ERROR | LEVEL1, "Header verification failed"); - ike_header->destroy(ike_header); - return status; - } - - if (this->ike_sa_id != NULL) - { - this->ike_sa_id->destroy(this->ike_sa_id); - } - - this->ike_sa_id = ike_sa_id_create(ike_header->get_initiator_spi(ike_header), - ike_header->get_responder_spi(ike_header), - ike_header->get_initiator_flag(ike_header)); - - this->exchange_type = ike_header->get_exchange_type(ike_header); - this->message_id = ike_header->get_message_id(ike_header); - this->is_request = (!(ike_header->get_response_flag(ike_header))); - this->major_version = ike_header->get_maj_version(ike_header); - this->minor_version = ike_header->get_min_version(ike_header); - this->first_payload = ike_header->payload_interface.get_next_type(&(ike_header->payload_interface)); - - this->logger->log(this->logger, CONTROL, "Parsed a %s %s", - mapping_find(exchange_type_m, this->exchange_type), - this->is_request ? "request" : "response"); - - ike_header->destroy(ike_header); - - /* get the rules for this messge */ - status = this->set_message_rule(this); - if (status != SUCCESS) - { - this->logger->log(this->logger, ERROR, "No message rules specified for a %s %s", - mapping_find(exchange_type_m,this->exchange_type), - this->is_request ? "request" : "response"); - } - - return status; -} - -/** - * Implementation of message_t.parse_body. - */ -static status_t parse_body(private_message_t *this, crypter_t *crypter, signer_t *signer) -{ - status_t status = SUCCESS; - payload_type_t current_payload_type; - - current_payload_type = this->first_payload; - - this->logger->log(this->logger, CONTROL|LEVEL1, "Parsing body of message, first payload is %s", - mapping_find(payload_type_m, current_payload_type)); - - /* parse payload for payload, while there are more available */ - while ((current_payload_type != NO_PAYLOAD)) - { - payload_t *current_payload; - - this->logger->log(this->logger, CONTROL|LEVEL2, "Start parsing a %s payload", - mapping_find(payload_type_m, current_payload_type)); - - /* parse current payload */ - status = this->parser->parse_payload(this->parser,current_payload_type,(payload_t **) ¤t_payload); - - if (status != SUCCESS) - { - this->logger->log(this->logger, ERROR, "Payload type %s could not be parsed", - mapping_find(payload_type_m,current_payload_type)); - return status; - } - - this->logger->log(this->logger, CONTROL|LEVEL2, "Verify payload of type %s", - mapping_find(payload_type_m, current_payload_type)); - - /* verify it, stop parsig if its invalid */ - status = current_payload->verify(current_payload); - if (status != SUCCESS) - { - this->logger->log(this->logger, ERROR, "%s payload verification failed", - mapping_find(payload_type_m,current_payload_type)); - current_payload->destroy(current_payload); - status = VERIFY_ERROR; - return status; - } - - this->logger->log(this->logger, CONTROL|LEVEL2, "%s payload verified. Adding to payload list", - mapping_find(payload_type_m, current_payload_type)); - this->payloads->insert_last(this->payloads,current_payload); - - /* an encryption payload is the last one, so STOP here. decryption is done later */ - if (current_payload_type == ENCRYPTED) - { - this->logger->log(this->logger, CONTROL|LEVEL2, "%s payload found. Stop parsing", - mapping_find(payload_type_m, current_payload_type)); - break; - } - - /* get next payload type */ - current_payload_type = current_payload->get_next_type(current_payload); - } - - if (current_payload_type == ENCRYPTED) - status = this->decrypt_payloads(this,crypter,signer); - if (status != SUCCESS) - { - this->logger->log(this->logger, ERROR, "Could not decrypt payloads"); - return status; - } - - status = this->verify(this); - if (status != SUCCESS) - { - this->logger->log(this->logger, ERROR, "Verification of message failed"); - } - - this->logger->log(this->logger, CONTROL, "Message %s %s contains %d payloads", - mapping_find(exchange_type_m, this->exchange_type), - this->is_request ? "request" : "response", - this->payloads->get_count(this->payloads)); - - return status; -} - -/** - * Implementation of private_message_t.verify. - */ -static status_t verify(private_message_t *this) -{ - int i; - iterator_t *iterator; - size_t total_found_payloads = 0; - - this->logger->log(this->logger, CONTROL|LEVEL1, "Verifying message structure"); - - iterator = this->payloads->create_iterator(this->payloads,TRUE); - /* check for payloads with wrong count*/ - for (i = 0; i < this->message_rule->payload_rule_count;i++) - { - size_t found_payloads = 0; - - /* check all payloads for specific rule */ - iterator->reset(iterator); - - while(iterator->has_next(iterator)) - { - payload_t *current_payload; - payload_type_t current_payload_type; - - iterator->current(iterator,(void **)¤t_payload); - current_payload_type = current_payload->get_type(current_payload); - - if (current_payload_type == UNKNOWN_PAYLOAD) - { - /* unknown payloads are ignored, IF they are not critical */ - unknown_payload_t *unknown_payload = (unknown_payload_t*)current_payload; - if (unknown_payload->is_critical(unknown_payload)) - { - this->logger->log(this->logger, ERROR|LEVEL1, "%s (%d) is not supported, but its critical!", - mapping_find(payload_type_m, current_payload_type), current_payload_type); - iterator->destroy(iterator); - return NOT_SUPPORTED; - } - } - else if (current_payload_type == this->message_rule->payload_rules[i].payload_type) - { - found_payloads++; - total_found_payloads++; - this->logger->log(this->logger, CONTROL|LEVEL2, "Found payload of type %s", - mapping_find(payload_type_m, this->message_rule->payload_rules[i].payload_type)); - - /* as soon as ohe payload occures more then specified, the verification fails */ - if (found_payloads > this->message_rule->payload_rules[i].max_occurence) - { - this->logger->log(this->logger, ERROR|LEVEL1, "Payload of type %s more than %d times (%d) occured in current message", - mapping_find(payload_type_m, current_payload_type), - this->message_rule->payload_rules[i].max_occurence, found_payloads); - iterator->destroy(iterator); - return FAILED; - } - } - } - - if (found_payloads < this->message_rule->payload_rules[i].min_occurence) - { - this->logger->log(this->logger, ERROR|LEVEL1, "Payload of type %s not occured %d times (%d)", - mapping_find(payload_type_m, this->message_rule->payload_rules[i].payload_type), - this->message_rule->payload_rules[i].min_occurence, found_payloads); - iterator->destroy(iterator); - return FAILED; - } - if ((this->message_rule->payload_rules[i].sufficient) && (this->payloads->get_count(this->payloads) == total_found_payloads)) - { - iterator->destroy(iterator); - return SUCCESS; - } - } - iterator->destroy(iterator); - return SUCCESS; -} - - -/** - * Implementation of private_message_t.decrypt_and_verify_payloads. - */ -static status_t decrypt_payloads(private_message_t *this,crypter_t *crypter, signer_t* signer) -{ - bool current_payload_was_encrypted = FALSE; - payload_t *previous_payload = NULL; - int payload_number = 1; - iterator_t *iterator; - status_t status; - - iterator = this->payloads->create_iterator(this->payloads,TRUE); - - /* process each payload and decrypt a encryption payload */ - while(iterator->has_next(iterator)) - { - payload_rule_t *payload_rule; - payload_type_t current_payload_type; - payload_t *current_payload; - - /* get current payload */ - iterator->current(iterator,(void **)¤t_payload); - - /* needed to check */ - current_payload_type = current_payload->get_type(current_payload); - - this->logger->log(this->logger, CONTROL|LEVEL2, "Process payload of type %s", - mapping_find(payload_type_m,current_payload_type)); - - if (current_payload_type == ENCRYPTED) - { - encryption_payload_t *encryption_payload; - payload_t *current_encrypted_payload; - - encryption_payload = (encryption_payload_t*)current_payload; - - this->logger->log(this->logger, CONTROL | LEVEL2, "Found an encryption payload"); - - if (payload_number != this->payloads->get_count(this->payloads)) - { - /* encrypted payload is not last one */ - this->logger->log(this->logger, ERROR | LEVEL1, "Encrypted payload is not last payload"); - iterator->destroy(iterator); - return FAILED; - } - /* decrypt */ - encryption_payload->set_transforms(encryption_payload, crypter, signer); - this->logger->log(this->logger, CONTROL | LEVEL1, "Verify signature of encryption payload"); - status = encryption_payload->verify_signature(encryption_payload, this->packet->get_data(this->packet)); - if (status != SUCCESS) - { - this->logger->log(this->logger, ERROR | LEVEL1, "encryption payload signature invalid"); - iterator->destroy(iterator); - return status; - } - this->logger->log(this->logger, CONTROL | LEVEL2, "Decrypt content of encryption payload"); - status = encryption_payload->decrypt(encryption_payload); - if (status != SUCCESS) - { - this->logger->log(this->logger, ERROR | LEVEL1, "Encrypted payload could not be decrypted and parsed: %s", - mapping_find(status_m, status)); - iterator->destroy(iterator); - return status; - } - - /* needed later to find out if a payload was encrypted */ - current_payload_was_encrypted = TRUE; - - /* check if there are payloads contained in the encryption payload */ - if (encryption_payload->get_payload_count(encryption_payload) == 0) - { - this->logger->log(this->logger, CONTROL|LEVEL2, "Encrypted payload is empty"); - /* remove the encryption payload, is not needed anymore */ - iterator->remove(iterator); - /* encrypted payload contains no other payload */ - current_payload_type = NO_PAYLOAD; - } - else - { - /* encryption_payload is replaced with first payload contained in encryption_payload */ - encryption_payload->remove_first_payload(encryption_payload, ¤t_encrypted_payload); - iterator->replace(iterator,NULL,(void *) current_encrypted_payload); - current_payload_type = current_encrypted_payload->get_type(current_encrypted_payload); - } - - /* is the current paylad the first in the message? */ - if (previous_payload == NULL) - { - /* yes, set the first payload type of the message to the current type */ - this->first_payload = current_payload_type; - } - else - { - /* no, set the next_type of the previous payload to the current type */ - previous_payload->set_next_type(previous_payload, current_payload_type); - } - - /* all encrypted payloads are added to the payload list */ - while (encryption_payload->get_payload_count(encryption_payload) > 0) - { - encryption_payload->remove_first_payload(encryption_payload, ¤t_encrypted_payload); - this->logger->log(this->logger, CONTROL | LEVEL1, "Insert unencrypted payload of type %s at end of list.", - mapping_find(payload_type_m,current_encrypted_payload->get_type(current_encrypted_payload))); - this->payloads->insert_last(this->payloads,current_encrypted_payload); - } - - /* encryption payload is processed, payloads are moved. Destroy it. */ - encryption_payload->destroy(encryption_payload); - } - - /* we allow unknown payloads of any type and don't bother if it was encrypted. Not our problem. */ - if (current_payload_type != UNKNOWN_PAYLOAD) - { - /* get the ruleset for found payload */ - status = this->get_payload_rule(this, current_payload_type, &payload_rule); - if (status != SUCCESS) - { - /* payload is not allowed */ - this->logger->log(this->logger, ERROR | LEVEL1, "Payload type %s not allowed",mapping_find(payload_type_m,current_payload_type)); - iterator->destroy(iterator); - return status; - } - - /* check if the payload was encrypted, and if it should been have encrypted */ - if (payload_rule->encrypted != current_payload_was_encrypted) - { - /* payload was not encrypted, but should have been. or vice-versa */ - this->logger->log(this->logger, ERROR | LEVEL1, "Payload type %s should be %s!", - mapping_find(payload_type_m,current_payload_type), - (payload_rule->encrypted) ? "encrypted" : "not encrypted"); - iterator->destroy(iterator); - return FAILED; - } - } - /* advance to the next payload */ - payload_number++; - /* is stored to set next payload in case of found encryption payload */ - previous_payload = current_payload; - } - iterator->destroy(iterator); - return SUCCESS; -} - -/** - * Implementation of private_message_t.encrypt_payloads. - */ -static status_t encrypt_payloads (private_message_t *this,crypter_t *crypter, signer_t* signer) -{ - encryption_payload_t *encryption_payload = NULL; - status_t status; - linked_list_t *all_payloads; - - if (!this->message_rule->encrypted_content) - { - this->logger->log(this->logger, CONTROL | LEVEL1, "Message doesn't have to be encrypted"); - /* message contains no content to encrypt */ - return SUCCESS; - } - - this->logger->log(this->logger, CONTROL | LEVEL2, "Copy all payloads to a temporary list"); - all_payloads = linked_list_create(); - - /* first copy all payloads in a temporary list */ - while (this->payloads->get_count(this->payloads) > 0) - { - void *current_payload; - this->payloads->remove_first(this->payloads,¤t_payload); - all_payloads->insert_last(all_payloads,current_payload); - } - - encryption_payload = encryption_payload_create(); - - this->logger->log(this->logger, CONTROL | LEVEL2, "Check each payloads if they have to get encrypted"); - while (all_payloads->get_count(all_payloads) > 0) - { - payload_rule_t *payload_rule; - payload_t *current_payload; - bool to_encrypt = FALSE; - - all_payloads->remove_first(all_payloads,(void **)¤t_payload); - this->logger->log(this->logger, CONTROL | LEVEL3, "Get rule for payload %s", - mapping_find(payload_type_m,current_payload->get_type(current_payload))); - - status = this->get_payload_rule(this,current_payload->get_type(current_payload),&payload_rule); - /* for payload types which are not found in supported payload list, it is presumed - * that they don't have to be encrypted */ - if ((status == SUCCESS) && (payload_rule->encrypted)) - { - this->logger->log(this->logger, CONTROL | LEVEL2, "Payload %s has to get encrypted", - mapping_find(payload_type_m,current_payload->get_type(current_payload))); - to_encrypt = TRUE; - } - else if (status != SUCCESS) - { - this->logger->log(this->logger, CONTROL | LEVEL2, "Payload %s not defined for exchange type %s. Handle it anyway", - mapping_find(payload_type_m,current_payload->get_type(current_payload)), - mapping_find(exchange_type_m,this->exchange_type)); - } - - if (to_encrypt) - { - this->logger->log(this->logger, CONTROL | LEVEL2, "Insert payload %s to encryption payload", - mapping_find(payload_type_m,current_payload->get_type(current_payload))); - - encryption_payload->add_payload(encryption_payload,current_payload); - } - else - { - this->logger->log(this->logger, CONTROL | LEVEL2, "Insert payload %s as payload wich does not have to be encrypted", - mapping_find(payload_type_m,current_payload->get_type(current_payload))); - this->public.add_payload(&(this->public), (payload_t*)encryption_payload); - } - } - - status = SUCCESS; - this->logger->log(this->logger, CONTROL | LEVEL2, "Set transforms for encryption payload "); - encryption_payload->set_transforms(encryption_payload,crypter,signer); - this->logger->log(this->logger, CONTROL | LEVEL1, "Encrypt all payloads of encrypted payload"); - status = encryption_payload->encrypt(encryption_payload); - this->logger->log(this->logger, CONTROL | LEVEL2, "Add encrypted payload to payload list"); - this->public.add_payload(&(this->public), (payload_t*)encryption_payload); - - all_payloads->destroy(all_payloads); - - return status; -} - - -/** - * Implementation of message_t.destroy. - */ -static void destroy (private_message_t *this) -{ - iterator_t *iterator; - - this->logger->log(this->logger, CONTROL|LEVEL3, "Going to destroy message_t object"); - - this->packet->destroy(this->packet); - - if (this->ike_sa_id != NULL) - { - this->ike_sa_id->destroy(this->ike_sa_id); - } - - iterator = this->payloads->create_iterator(this->payloads, TRUE); - while (iterator->has_next(iterator)) - { - payload_t *payload; - iterator->current(iterator, (void**)&payload); - this->logger->log(this->logger, CONTROL|LEVEL3, "Destroying payload of type %s", - mapping_find(payload_type_m, payload->get_type(payload))); - payload->destroy(payload); - } - iterator->destroy(iterator); - this->payloads->destroy(this->payloads); - this->parser->destroy(this->parser); - - free(this); -} - -/* - * Described in Header-File - */ -message_t *message_create_from_packet(packet_t *packet) -{ - private_message_t *this = malloc_thing(private_message_t); - - /* public functions */ - this->public.set_major_version = (void(*)(message_t*, u_int8_t))set_major_version; - this->public.get_major_version = (u_int8_t(*)(message_t*))get_major_version; - this->public.set_minor_version = (void(*)(message_t*, u_int8_t))set_minor_version; - this->public.get_minor_version = (u_int8_t(*)(message_t*))get_minor_version; - this->public.set_message_id = (void(*)(message_t*, u_int32_t))set_message_id; - this->public.get_message_id = (u_int32_t(*)(message_t*))get_message_id; - this->public.get_responder_spi = (u_int64_t(*)(message_t*))get_responder_spi; - this->public.set_ike_sa_id = (void(*)(message_t*, ike_sa_id_t *))set_ike_sa_id; - this->public.get_ike_sa_id = (status_t(*)(message_t*, ike_sa_id_t **))get_ike_sa_id; - this->public.set_exchange_type = (void(*)(message_t*, exchange_type_t))set_exchange_type; - this->public.get_exchange_type = (exchange_type_t(*)(message_t*))get_exchange_type; - this->public.set_request = (void(*)(message_t*, bool))set_request; - this->public.get_request = (bool(*)(message_t*))get_request; - this->public.add_payload = (void(*)(message_t*,payload_t*))add_payload; - this->public.generate = (status_t (*) (message_t *,crypter_t*,signer_t*,packet_t**)) generate; - this->public.set_source = (void (*) (message_t*,host_t*)) set_source; - this->public.get_source = (host_t * (*) (message_t*)) get_source; - this->public.set_destination = (void (*) (message_t*,host_t*)) set_destination; - this->public.get_destination = (host_t * (*) (message_t*)) get_destination; - this->public.get_payload_iterator = (iterator_t * (*) (message_t *)) get_payload_iterator; - this->public.parse_header = (status_t (*) (message_t *)) parse_header; - this->public.parse_body = (status_t (*) (message_t *,crypter_t*,signer_t*)) parse_body; - this->public.get_packet = (packet_t * (*) (message_t*)) get_packet; - this->public.get_packet_data = (chunk_t (*) (message_t *this)) get_packet_data; - this->public.destroy = (void(*)(message_t*))destroy; - - /* private values */ - this->exchange_type = EXCHANGE_TYPE_UNDEFINED; - this->is_request = TRUE; - this->ike_sa_id = NULL; - this->first_payload = NO_PAYLOAD; - this->message_id = 0; - - /* private functions */ - this->set_message_rule = set_message_rule; - this->get_payload_rule = get_payload_rule; - this->encrypt_payloads = encrypt_payloads; - this->decrypt_payloads = decrypt_payloads; - this->verify = verify; - - /* private values */ - if (packet == NULL) - { - packet = packet_create(); - } - this->message_rule = NULL; - this->packet = packet; - this->payloads = linked_list_create(); - - /* parser is created from data of packet */ - this->parser = parser_create(this->packet->get_data(this->packet)); - - this->logger = logger_manager->get_logger(logger_manager, MESSAGE); - - return (&this->public); -} - -/* - * Described in Header. - */ -message_t *message_create() -{ - return message_create_from_packet(NULL); -} - -/* - * Described in Header. - */ -message_t *message_create_notify_reply(host_t *source, host_t *destination, exchange_type_t exchange_type, bool original_initiator,ike_sa_id_t *ike_sa_id,notify_message_type_t notify_type) -{ - message_t *message = message_create_from_packet(NULL); - notify_payload_t *payload; - - message->set_source(message, source->clone(source)); - message->set_destination(message, destination->clone(destination)); - message->set_exchange_type(message, exchange_type); - message->set_request(message, FALSE); - message->set_message_id(message,0); - message->set_ike_sa_id(message, ike_sa_id); - - payload = notify_payload_create_from_protocol_and_type(PROTO_IKE, notify_type); - message->add_payload(message,(payload_t *) payload); - - return message; -} diff --git a/src/charon/charon/encoding/message.h b/src/charon/charon/encoding/message.h deleted file mode 100644 index 4b3f8e997..000000000 --- a/src/charon/charon/encoding/message.h +++ /dev/null @@ -1,367 +0,0 @@ -/** - * @file message.h - * - * @brief Interface of message_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef MESSAGE_H_ -#define MESSAGE_H_ - -#include -#include -#include -#include -#include -#include -#include -#include - - -typedef struct message_t message_t; - -/** - * @brief This class is used to represent an IKEv2-Message. - * - * The message handles parsing and generation of payloads - * via parser_t/generator_t. Encryption is done transparently - * via the encryption_payload_t. A set of rules for messages - * and payloads does check parsed messages. - * - * @b Constructors: - * - message_create() - * - message_create_from_packet() - * - message_create_notify_reply() - * - * @ingroup encoding - */ -struct message_t { - - /** - * @brief Sets the IKE major version of the message. - * - * @param this message_t object - * @param major_version major version to set - */ - void (*set_major_version) (message_t *this,u_int8_t major_version); - - /** - * @brief Gets the IKE major version of the message. - * - * @param this message_t object - * @return major version of the message - */ - u_int8_t (*get_major_version) (message_t *this); - - /** - * @brief Sets the IKE minor version of the message. - * - * @param this message_t object - * @param minor_version minor version to set - */ - void (*set_minor_version) (message_t *this,u_int8_t minor_version); - - /** - * @brief Gets the IKE minor version of the message. - * - * @param this message_t object - * @return minor version of the message - */ - u_int8_t (*get_minor_version) (message_t *this); - - /** - * @brief Sets the Message ID of the message. - * - * @param this message_t object - * @param message_id message_id to set - */ - void (*set_message_id) (message_t *this,u_int32_t message_id); - - /** - * @brief Gets the Message ID of the message. - * - * @param this message_t object - * @return message_id type of the message - */ - u_int32_t (*get_message_id) (message_t *this); - - /** - * @brief Gets the responder SPI of the message. - * - * @param this message_t object - * @return responder spi of the message - */ - u_int64_t (*get_responder_spi) (message_t *this); - - /** - * @brief Sets the IKE_SA ID of the message. - * - * @warning ike_sa_id gets cloned internaly and - * so can be destroyed afterwards. - * - * @param this message_t object - * @param ike_sa_id ike_sa_id to set - */ - void (*set_ike_sa_id) (message_t *this,ike_sa_id_t * ike_sa_id); - - /** - * @brief Gets the IKE_SA ID of the message. - * - * @warning The returned ike_sa_id is a clone of the internal one. - * So it has to be destroyed by the caller. - * - * @param this message_t object - * @param ike_sa_id pointer to ike_sa_id pointer which will be set - * @return - * - SUCCESS - * - FAILED if no ike_sa_id is set - */ - status_t (*get_ike_sa_id) (message_t *this,ike_sa_id_t **ike_sa_id); - - /** - * @brief Sets the exchange type of the message. - * - * @param this message_t object - * @param exchange_type exchange_type to set - */ - void (*set_exchange_type) (message_t *this,exchange_type_t exchange_type); - - /** - * @brief Gets the exchange type of the message. - * - * @param this message_t object - * @return exchange type of the message - */ - exchange_type_t (*get_exchange_type) (message_t *this); - - /** - * @brief Sets the request flag. - * - * @param this message_t object - * @param original_initiator TRUE if message is a request, FALSE if it is a reply - */ - void (*set_request) (message_t *this,bool request); - - /** - * @brief Gets request flag. - * - * @param this message_t object - * @return TRUE if message is a request, FALSE if it is a reply - */ - bool (*get_request) (message_t *this); - - /** - * @brief Append a payload to the message. - * - * If the payload must be encrypted is not specified here. Encryption - * of payloads is evaluated via internal rules for the messages and - * is done before generation. The order of payloads may change, since - * all payloads to encrypt are added to the encryption payload, which is - * always the last one. - * - * @param this message_t object - * @param payload payload to append - */ - void (*add_payload) (message_t *this, payload_t *payload); - - /** - * @brief Parses header of message. - * - * Begins parisng of a message created via message_create_from_packet(). - * The parsing context is stored, so a subsequent call to parse_body() - * will continue the parsing process. - * - * @param this message_t object - * @return - * - SUCCESS if header could be parsed - * - PARSE_ERROR if corrupted/invalid data found - * - FAILED if consistence check of header failed - */ - status_t (*parse_header) (message_t *this); - - /** - * @brief Parses body of message. - * - * The body gets not only parsed, but rather it gets verified. - * All payloads are verified if they are allowed to exist in the message - * of this type and if their own structure is ok. - * If there are encrypted payloads, they get decrypted via the supplied - * crypter. Also the message integrity gets verified with the supplied - * signer. - * Crypter/signer can be omitted (by passing NULL) when no encryption - * payload is expected. - * - * @param this message_t object - * @param crypter crypter to decrypt encryption payloads - * @param signer signer to verifiy a message with an encryption payload - * @return - * - SUCCESS if header could be parsed - * - NOT_SUPPORTED if ciritcal unknown payloads found - * - FAILED if message type is not suppported! - * - PARSE_ERROR if corrupted/invalid data found - * - VERIFY_ERROR if verification of some payload failed - * - INVALID_STATE if crypter/signer not supplied, but needed - */ - status_t (*parse_body) (message_t *this, crypter_t *crypter, signer_t *signer); - - /** - * @brief Generates the UDP packet of specific message. - * - * Payloads which must be encrypted are generated first and added to - * an encryption payload. This encryption payload will get encrypted via - * the supplied crypter. Then all other payloads and the header get generated. - * After that, the checksum is added to the encryption payload over the full - * message. - * Crypter/signer can be omitted (by passing NULL) when no encryption - * payload is expected. - * - * @param this message_t object - * @param crypter crypter to use when a payload must be encrypted - * @param signer signer to build a mac - * @return - * - SUCCESS if packet could be generated - * - INVALID_STATE if exchange type is currently not set - * - NOT_FOUND if no rules found for message generation - * - INVALID_STATE if crypter/signer not supplied but needed. - */ - status_t (*generate) (message_t *this, crypter_t *crypter, signer_t *signer, packet_t **packet); - - /** - * @brief Gets the source host informations. - * - * @warning Returned host_t object is not getting cloned, - * do not destroy nor modify. - * - * @param this message_t object - * @return host_t object representing source host - */ - host_t * (*get_source) (message_t *this); - - /** - * @brief Sets the source host informations. - * - * @warning host_t object is not getting cloned and gets destroyed by - * message_t.destroy or next call of message_t.set_source. - * - * @param this message_t object - * @param host host_t object representing source host - */ - void (*set_source) (message_t *this, host_t *host); - - /** - * @brief Gets the destination host informations. - * - * @warning Returned host_t object is not getting cloned, - * do not destroy nor modify. - * - * @param this message_t object - * @return host_t object representing destination host - */ - host_t * (*get_destination) (message_t *this); - - /** - * @brief Sets the destination host informations. - * - * @warning host_t object is not getting cloned and gets destroyed by - * message_t.destroy or next call of message_t.set_destination. - * - * @param this message_t object - * @param host host_t object representing destination host - */ - void (*set_destination) (message_t *this, host_t *host); - - /** - * @brief Returns an iterator on all stored payloads. - * - * @warning Don't insert payloads over this iterator. - * Use add_payload() instead. - * - * @param this message_t object - * @return iterator_t object which has to get destroyd by the caller - */ - iterator_t * (*get_payload_iterator) (message_t *this); - - /** - * Returns a clone of the internal stored packet_t object. - * - * @param this message_t object - * @return packet_t object as clone of internal one - */ - packet_t * (*get_packet) (message_t *this); - - /** - * Returns a clone of the internal stored packet_t data. - * - * @param this message_t object - * @return clone of the internal stored packet_t data. - */ - chunk_t (*get_packet_data) (message_t *this); - - - /** - * @brief Destroys a message and all including objects. - * - * @param this message_t object - */ - void (*destroy) (message_t *this); -}; - -/** - * @brief Creates an message_t object from a incoming UDP Packet. - * - * @warning the given packet_t object is not copied and gets - * destroyed in message_t's destroy call. - * - * @warning Packet is not parsed in here! - * - * - exchange_type is set to NOT_SET - * - original_initiator is set to TRUE - * - is_request is set to TRUE - * Call message_t.parse_header afterwards. - * - * @param packet packet_t object which is assigned to message - * @return message_t object - * - * @ingroup encoding - */ -message_t * message_create_from_packet(packet_t *packet); - - -/** - * @brief Creates an empty message_t object. - * - * - exchange_type is set to NOT_SET - * - original_initiator is set to TRUE - * - is_request is set to TRUE - * - * @return message_t object - * - * @ingroup encoding - */ -message_t * message_create(void); - -/** - * @brief Creates an message_t object of type reply containing a notify payload. - * - * @return message_t object - * - * @ingroup encoding - */ -message_t *message_create_notify_reply(host_t *source, host_t *destination, exchange_type_t exchange_type, bool original_initiator,ike_sa_id_t *ike_sa_id,notify_message_type_t notify_type); - -#endif /*MESSAGE_H_*/ diff --git a/src/charon/charon/encoding/parser.c b/src/charon/charon/encoding/parser.c deleted file mode 100644 index a589e9bde..000000000 --- a/src/charon/charon/encoding/parser.c +++ /dev/null @@ -1,1065 +0,0 @@ -/** - * @file parser.c - * - * @brief Implementation of parser_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 -#include -#include - -#include "parser.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -typedef struct private_parser_t private_parser_t; - -/** - * Private data stored in a context. - * - * Contains pointers and counters to store current state. - */ -struct private_parser_t { - /** - * Public members, see parser_t. - */ - parser_t public; - - /** - * @brief Parse a 4-Bit unsigned integer from the current parsing position. - * - * @param this parser_t object - * @param rule_number number of current rule - * @param[out] output_pos pointer where to write the parsed result - * @return - * - SUCCESS or - * - PARSE_ERROR when not successful - */ - status_t (*parse_uint4) (private_parser_t *this, int rule_number, u_int8_t *output_pos); - - /** - * @brief Parse a 8-Bit unsigned integer from the current parsing position. - * - * @param this parser_t object - * @param rule_number number of current rule - * @param[out] output_pos pointer where to write the parsed result - * @return - * - SUCCESS or - * - PARSE_ERROR when not successful - */ - status_t (*parse_uint8) (private_parser_t *this, int rule_number, u_int8_t *output_pos); - - /** - * @brief Parse a 15-Bit unsigned integer from the current parsing position. - * - * This is a special case used for ATTRIBUTE_TYPE. - * Big-/Little-endian conversion is done here. - * - * @param this parser_t object - * @param rule_number number of current rule - * @param[out] output_pos pointer where to write the parsed result - * @return - * - SUCCESS or - * - PARSE_ERROR when not successful - */ - status_t (*parse_uint15) (private_parser_t *this, int rule_number, u_int16_t *output_pos); - - /** - * @brief Parse a 16-Bit unsigned integer from the current parsing position. - * - * Big-/Little-endian conversion is done here. - * - * @param this parser_t object - * @param rule_number number of current rule - * @param[out] output_pos pointer where to write the parsed result - * @return - * - SUCCESS or - * - PARSE_ERROR when not successful - */ - status_t (*parse_uint16) (private_parser_t *this, int rule_number, u_int16_t *output_pos); - - /** - * @brief Parse a 32-Bit unsigned integer from the current parsing position. - * - * Big-/Little-endian conversion is done here. - * - * @param this parser_t object - * @param rule_number number of current rule - * @param[out] output_pos pointer where to write the parsed result - * @return - * - SUCCESS or - * - PARSE_ERROR when not successful - */ - status_t (*parse_uint32) (private_parser_t *this, int rule_number, u_int32_t *output_pos); - - /** - * @brief Parse a 64-Bit unsigned integer from the current parsing position. - * - * @todo add support for big-endian machines. - * - * @param this parser_t object - * @param rule_number number of current rule - * @param[out] output_pos pointer where to write the parsed result - * @return - * - SUCCESS or - * - PARSE_ERROR when not successful - */ - status_t (*parse_uint64) (private_parser_t *this, int rule_number, u_int64_t *output_pos); - - /** - * @brief Parse a given amount of bytes and writes them to a specific location - * - * @param this parser_t object - * @param rule_number number of current rule - * @param[out] output_pos pointer where to write the parsed result - * @param bytes number of bytes to parse - * @return - * - SUCCESS or - * - PARSE_ERROR when not successful - */ - status_t (*parse_bytes) (private_parser_t *this, int rule_number, u_int8_t *output_pos,size_t bytes); - - /** - * @brief Parse a single Bit from the current parsing position - * - * @param this parser_t object - * @param rule_number number of current rule - * @param[out] output_pos pointer where to write the parsed result - * @return - * - SUCCESS or - * - PARSE_ERROR when not successful - */ - status_t (*parse_bit) (private_parser_t *this, int rule_number, bool *output_pos); - - /** - * @brief Parse substructures in a list - * - * This function calls the parser recursivly to parse contained substructures - * in a linked_list_t. The list must already be created. Payload defines - * the type of the substructures. parsing is continued until the specified length - * is completely parsed. - * - * @param this parser_t object - * @param rule_number number of current rule - * @param[out] output_pos pointer of a linked_list where substructures are added - * @param payload_type type of the contained substructures to parse - * @param length number of bytes to parse in this list - * @return - * - SUCCESS or - * - PARSE_ERROR when not successful - */ - status_t (*parse_list) (private_parser_t *this, int rule_number, linked_list_t **output_pos, payload_type_t payload_ype, size_t length); - - /** - * @brief Parse data from current parsing position in a chunk. - * - * This function clones length number of bytes to output_pos, without - * modifiyng them. Space will be allocated and must be freed by caller. - * - * @param this parser_t object - * @param rule_number number of current rule - * @param[out] output_pos pointer of a chunk which will point to the allocated data - * @param length number of bytes to clone - * @return - * - SUCCESS or - * - PARSE_ERROR when not successful - */ - status_t (*parse_chunk) (private_parser_t *this, int rule_number, chunk_t *output_pos, size_t length); - - /** - * Current bit for reading in input data. - */ - u_int8_t bit_pos; - - /** - * Current byte for reading in input data. - */ - u_int8_t *byte_pos; - - /** - * Input data to parse. - */ - u_int8_t *input; - - /** - * Roof of input, used for length-checking. - */ - u_int8_t *input_roof; - - /** - * Set of encoding rules for this parsing session. - */ - encoding_rule_t *rules; - - /** - * Assigned logger_t object. - */ - logger_t *logger; -}; - -/** - * Implementation of private_parser_t.parse_uint4. - */ -static status_t parse_uint4(private_parser_t *this, int rule_number, u_int8_t *output_pos) -{ - if (this->byte_pos + sizeof(u_int8_t) > this->input_roof) - { - this->logger->log(this->logger, ERROR|LEVEL1, " not enough input to parse rule %d %s", - rule_number, mapping_find(encoding_type_m, - this->rules[rule_number].type)); - return PARSE_ERROR; - } - switch (this->bit_pos) - { - case 0: - /* caller interested in result ? */ - if (output_pos != NULL) - { - *output_pos = *(this->byte_pos) >> 4; - } - this->bit_pos = 4; - break; - case 4: - /* caller interested in result ? */ - if (output_pos != NULL) - { - *output_pos = *(this->byte_pos) & 0x0F; - } - this->bit_pos = 0; - this->byte_pos++; - break; - default: - this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d", - rule_number, mapping_find(encoding_type_m, - this->rules[rule_number].type), this->bit_pos); - return PARSE_ERROR; - } - - if (output_pos != NULL) - { - this->logger->log(this->logger, RAW|LEVEL2, " => %d", *output_pos); - } - - return SUCCESS; -} - -/** - * Implementation of private_parser_t.parse_uint8. - */ -static status_t parse_uint8(private_parser_t *this, int rule_number, u_int8_t *output_pos) -{ - if (this->byte_pos + sizeof(u_int8_t) > this->input_roof) - { - this->logger->log(this->logger, ERROR|LEVEL1, " not enough input to parse rule %d %s", - rule_number, mapping_find(encoding_type_m, - this->rules[rule_number].type)); - return PARSE_ERROR; - } - if (this->bit_pos) - { - this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d", - rule_number, mapping_find(encoding_type_m, - this->rules[rule_number].type), this->bit_pos); - return PARSE_ERROR; - } - - /* caller interested in result ? */ - if (output_pos != NULL) - { - *output_pos = *(this->byte_pos); - this->logger->log(this->logger, RAW|LEVEL2, " => %d", *output_pos); - } - this->byte_pos++; - - return SUCCESS; -} - -/** - * Implementation of private_parser_t.parse_uint15. - */ -static status_t parse_uint15(private_parser_t *this, int rule_number, u_int16_t *output_pos) -{ - if (this->byte_pos + sizeof(u_int16_t) > this->input_roof) - { - this->logger->log(this->logger, ERROR|LEVEL1, " not enough input to parse rule %d %s", - rule_number, mapping_find(encoding_type_m, - this->rules[rule_number].type)); - return PARSE_ERROR; - } - if (this->bit_pos != 1) - { - this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d", - rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type), - this->bit_pos); - return PARSE_ERROR; - } - /* caller interested in result ? */ - if (output_pos != NULL) - { - *output_pos = ntohs(*((u_int16_t*)this->byte_pos)) & ~0x8000; - this->logger->log(this->logger, RAW|LEVEL2, " => %d", *output_pos); - } - this->byte_pos += 2; - this->bit_pos = 0; - - return SUCCESS; -} - -/** - * Implementation of private_parser_t.parse_uint16. - */ -static status_t parse_uint16(private_parser_t *this, int rule_number, u_int16_t *output_pos) -{ - if (this->byte_pos + sizeof(u_int16_t) > this->input_roof) - { - this->logger->log(this->logger, ERROR|LEVEL1, " not enough input to parse rule %d %s", - rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type)); - return PARSE_ERROR; - } - if (this->bit_pos) - { - this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d", - rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type), - this->bit_pos); - return PARSE_ERROR; - } - /* caller interested in result ? */ - if (output_pos != NULL) - { - *output_pos = ntohs(*((u_int16_t*)this->byte_pos)); - - this->logger->log(this->logger, RAW|LEVEL2, " => %d", *output_pos); - } - this->byte_pos += 2; - - return SUCCESS; -} -/** - * Implementation of private_parser_t.parse_uint32. - */ -static status_t parse_uint32(private_parser_t *this, int rule_number, u_int32_t *output_pos) -{ - if (this->byte_pos + sizeof(u_int32_t) > this->input_roof) - { - this->logger->log(this->logger, ERROR|LEVEL1, " not enough input to parse rule %d %s", - rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type)); - return PARSE_ERROR; - } - if (this->bit_pos) - { - this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d", - rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type), - this->bit_pos); - return PARSE_ERROR; - } - /* caller interested in result ? */ - if (output_pos != NULL) - { - *output_pos = ntohl(*((u_int32_t*)this->byte_pos)); - - this->logger->log(this->logger, RAW|LEVEL2, " => %d", *output_pos); - } - this->byte_pos += 4; - - return SUCCESS; -} - -/** - * Implementation of private_parser_t.parse_uint64. - */ -static status_t parse_uint64(private_parser_t *this, int rule_number, u_int64_t *output_pos) -{ - if (this->byte_pos + sizeof(u_int64_t) > this->input_roof) - { - this->logger->log(this->logger, ERROR|LEVEL1, " not enough input to parse rule %d %s", - rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type)); - return PARSE_ERROR; - } - if (this->bit_pos) - { - this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d", - rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type), - this->bit_pos); - return PARSE_ERROR; - } - /* caller interested in result ? */ - if (output_pos != NULL) - { - /* assuming little endian host order */ - *(output_pos + 1) = ntohl(*((u_int32_t*)this->byte_pos)); - *output_pos = ntohl(*(((u_int32_t*)this->byte_pos) + 1)); - - this->logger->log_bytes(this->logger, RAW|LEVEL2, " =>", (void*)output_pos, 8); - } - this->byte_pos += 8; - - return SUCCESS; -} - -/** - * Implementation of private_parser_t.parse_bytes. - */ -static status_t parse_bytes (private_parser_t *this, int rule_number, u_int8_t *output_pos,size_t bytes) -{ - if (this->byte_pos + bytes > this->input_roof) - { - this->logger->log(this->logger, ERROR|LEVEL1, " not enough input to parse rule %d %s", - rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type)); - return PARSE_ERROR; - } - if (this->bit_pos) - { - this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d", - rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type), - this->bit_pos); - return PARSE_ERROR; - } - - /* caller interested in result ? */ - if (output_pos != NULL) - { - memcpy(output_pos,this->byte_pos,bytes); - - this->logger->log_bytes(this->logger, RAW|LEVEL2, " =>", (void*)output_pos, bytes); - } - this->byte_pos += bytes; - - return SUCCESS; -} - -/** - * Implementation of private_parser_t.parse_bit. - */ -static status_t parse_bit(private_parser_t *this, int rule_number, bool *output_pos) -{ - if (this->byte_pos + sizeof(u_int8_t) > this->input_roof) - { - this->logger->log(this->logger, ERROR|LEVEL1, " not enough input to parse rule %d %s", - rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type)); - return PARSE_ERROR; - } - /* caller interested in result ? */ - if (output_pos != NULL) - { - u_int8_t mask; - mask = 0x01 << (7 - this->bit_pos); - *output_pos = *this->byte_pos & mask; - - if (*output_pos) - { - /* set to a "clean", comparable true */ - *output_pos = TRUE; - } - - this->logger->log(this->logger, RAW|LEVEL2, " => %d", *output_pos); - } - this->bit_pos = (this->bit_pos + 1) % 8; - if (this->bit_pos == 0) - { - this->byte_pos++; - } - - return SUCCESS; -} - -/** - * Implementation of private_parser_t.parse_list. - */ -static status_t parse_list(private_parser_t *this, int rule_number, linked_list_t **output_pos, payload_type_t payload_type, size_t length) -{ - linked_list_t * list = *output_pos; - - if (length < 0) - { - this->logger->log(this->logger, ERROR|LEVEL1, " invalid length for rule %d %s", - rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type)); - return PARSE_ERROR; - } - - if (this->bit_pos) - { - this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d", - rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type), this->bit_pos); - return PARSE_ERROR; - } - - while (length > 0) - { - u_int8_t *pos_before = this->byte_pos; - payload_t *payload; - status_t status; - this->logger->log(this->logger, CONTROL|LEVEL1, " %d bytes left, parsing recursivly %s", - length, mapping_find(payload_type_m, payload_type)); - status = this->public.parse_payload((parser_t*)this, payload_type, &payload); - if (status != SUCCESS) - { - this->logger->log(this->logger, ERROR, " parsing of a %s substructure failed", - mapping_find(payload_type_m, payload_type)); - return status; - } - list->insert_last(list, payload); - length -= this->byte_pos - pos_before; - } - *output_pos = list; - return SUCCESS; -} - -/** - * Implementation of private_parser_t.parse_chunk. - */ -static status_t parse_chunk(private_parser_t *this, int rule_number, chunk_t *output_pos, size_t length) -{ - if (this->byte_pos + length > this->input_roof) - { - this->logger->log(this->logger, ERROR, " not enough input (%d bytes) to parse rule %d %s", - length, rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type)); - return PARSE_ERROR; - } - if (this->bit_pos) - { - this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d", - rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type), this->bit_pos); - return PARSE_ERROR; - } - if (output_pos != NULL) - { - output_pos->len = length; - output_pos->ptr = malloc(length); - memcpy(output_pos->ptr, this->byte_pos, length); - } - this->byte_pos += length; - this->logger->log_bytes(this->logger, RAW|LEVEL2, " =>", (void*)output_pos->ptr, length); - - return SUCCESS; -} - -/** - * Implementation of parser_t.parse_payload. - */ -static status_t parse_payload(private_parser_t *this, payload_type_t payload_type, payload_t **payload) -{ - payload_t *pld; - void *output; - size_t rule_count, payload_length, spi_size, attribute_length; - u_int16_t ts_type; - bool attribute_format; - int rule_number; - encoding_rule_t *rule; - - /* create instance of the payload to parse */ - pld = payload_create(payload_type); - - this->logger->log(this->logger, CONTROL|LEVEL1, "parsing %s payload, %d bytes left", - mapping_find(payload_type_m, payload_type), - this->input_roof-this->byte_pos); - - this->logger->log_bytes(this->logger, RAW|LEVEL3, "parsing payload from", this->byte_pos, - this->input_roof-this->byte_pos); - - if (pld->get_type(pld) == UNKNOWN_PAYLOAD) - { - this->logger->log(this->logger, ERROR|LEVEL1, " payload type %d is unknown, handling as %s", - payload_type, mapping_find(payload_type_m, UNKNOWN_PAYLOAD)); - } - - /* base pointer for output, avoids casting in every rule */ - output = pld; - - /* parse the payload with its own rulse */ - pld->get_encoding_rules(pld, &(this->rules), &rule_count); - for (rule_number = 0; rule_number < rule_count; rule_number++) - { - rule = &(this->rules[rule_number]); - this->logger->log(this->logger, CONTROL|LEVEL2, " parsing rule %d %s", - rule_number, mapping_find(encoding_type_m, rule->type)); - switch (rule->type) - { - case U_INT_4: - { - if (this->parse_uint4(this, rule_number, output + rule->offset) != SUCCESS) - { - pld->destroy(pld); - return PARSE_ERROR; - } - break; - } - case U_INT_8: - { - if (this->parse_uint8(this, rule_number, output + rule->offset) != SUCCESS) - { - pld->destroy(pld); - return PARSE_ERROR; - } - break; - } - case U_INT_16: - { - if (this->parse_uint16(this, rule_number, output + rule->offset) != SUCCESS) - { - pld->destroy(pld); - return PARSE_ERROR; - } - break; - } - case U_INT_32: - { - if (this->parse_uint32(this, rule_number, output + rule->offset) != SUCCESS) - { - pld->destroy(pld); - return PARSE_ERROR; - } - break; - } - case U_INT_64: - { - if (this->parse_uint64(this, rule_number, output + rule->offset) != SUCCESS) - { - pld->destroy(pld); - return PARSE_ERROR; - } - break; - } - case IKE_SPI: - { - if (this->parse_bytes(this, rule_number, output + rule->offset,8) != SUCCESS) - { - pld->destroy(pld); - return PARSE_ERROR; - } - break; - } - case RESERVED_BIT: - { - if (this->parse_bit(this, rule_number, NULL) != SUCCESS) - { - pld->destroy(pld); - return PARSE_ERROR; - } - break; - } - case RESERVED_BYTE: - { - if (this->parse_uint8(this, rule_number, NULL) != SUCCESS) - { - pld->destroy(pld); - return PARSE_ERROR; - } - break; - } - case FLAG: - { - if (this->parse_bit(this, rule_number, output + rule->offset) != SUCCESS) - { - pld->destroy(pld); - return PARSE_ERROR; - } - break; - } - case PAYLOAD_LENGTH: - { - if (this->parse_uint16(this, rule_number, output + rule->offset) != SUCCESS) - { - pld->destroy(pld); - return PARSE_ERROR; - } - payload_length = *(u_int16_t*)(output + rule->offset); - break; - } - case HEADER_LENGTH: - { - if (this->parse_uint32(this, rule_number, output + rule->offset) != SUCCESS) - { - pld->destroy(pld); - return PARSE_ERROR; - } - break; - } - case SPI_SIZE: - { - if (this->parse_uint8(this, rule_number, output + rule->offset) != SUCCESS) - { - pld->destroy(pld); - return PARSE_ERROR; - } - spi_size = *(u_int8_t*)(output + rule->offset); - break; - } - case SPI: - { - if (this->parse_chunk(this, rule_number, output + rule->offset, spi_size) != SUCCESS) - { - pld->destroy(pld); - return PARSE_ERROR; - } - break; - } - case PROPOSALS: - { - size_t proposals_length = payload_length - SA_PAYLOAD_HEADER_LENGTH; - if (this->parse_list(this, rule_number, output + rule->offset, PROPOSAL_SUBSTRUCTURE, proposals_length) != SUCCESS) - { - pld->destroy(pld); - return PARSE_ERROR; - } - break; - } - case TRANSFORMS: - { - size_t transforms_length = payload_length - spi_size - PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH; - if (this->parse_list(this, rule_number, output + rule->offset, TRANSFORM_SUBSTRUCTURE, transforms_length) != SUCCESS) - { - pld->destroy(pld); - return PARSE_ERROR; - } - break; - } - case TRANSFORM_ATTRIBUTES: - { - size_t transform_a_length = payload_length - TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH; - if (this->parse_list(this, rule_number, output + rule->offset, TRANSFORM_ATTRIBUTE, transform_a_length) != SUCCESS) - { - pld->destroy(pld); - return PARSE_ERROR; - } - break; - } - case CONFIGURATION_ATTRIBUTES: - { - size_t configuration_attributes_length = payload_length - CP_PAYLOAD_HEADER_LENGTH; - if (this->parse_list(this, rule_number, output + rule->offset, CONFIGURATION_ATTRIBUTE, configuration_attributes_length) != SUCCESS) - { - pld->destroy(pld); - return PARSE_ERROR; - } - break; - } - case ATTRIBUTE_FORMAT: - { - if (this->parse_bit(this, rule_number, output + rule->offset) != SUCCESS) - { - pld->destroy(pld); - return PARSE_ERROR; - } - attribute_format = *(bool*)(output + rule->offset); - break; - } - case ATTRIBUTE_TYPE: - { - if (this->parse_uint15(this, rule_number, output + rule->offset) != SUCCESS) - { - pld->destroy(pld); - return PARSE_ERROR; - } - attribute_format = *(bool*)(output + rule->offset); - break; - } - case CONFIGURATION_ATTRIBUTE_LENGTH: - { - if (this->parse_uint16(this, rule_number, output + rule->offset) != SUCCESS) - { - pld->destroy(pld); - return PARSE_ERROR; - } - attribute_length = *(u_int16_t*)(output + rule->offset); - break; - } - case ATTRIBUTE_LENGTH_OR_VALUE: - { - if (this->parse_uint16(this, rule_number, output + rule->offset) != SUCCESS) - { - pld->destroy(pld); - return PARSE_ERROR; - } - attribute_length = *(u_int16_t*)(output + rule->offset); - break; - } - case ATTRIBUTE_VALUE: - { - if (attribute_format == FALSE) - { - if (this->parse_chunk(this, rule_number, output + rule->offset, attribute_length) != SUCCESS) - { - pld->destroy(pld); - return PARSE_ERROR; - } - } - break; - } - case NONCE_DATA: - { - size_t nonce_length = payload_length - NONCE_PAYLOAD_HEADER_LENGTH; - if (this->parse_chunk(this, rule_number, output + rule->offset, nonce_length) != SUCCESS) - { - pld->destroy(pld); - return PARSE_ERROR; - } - break; - } - case ID_DATA: - { - size_t data_length = payload_length - ID_PAYLOAD_HEADER_LENGTH; - if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS) - { - pld->destroy(pld); - return PARSE_ERROR; - } - break; - } - case AUTH_DATA: - { - size_t data_length = payload_length - AUTH_PAYLOAD_HEADER_LENGTH; - if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS) - { - pld->destroy(pld); - return PARSE_ERROR; - } - break; - } - case CERT_DATA: - { - size_t data_length = payload_length - CERT_PAYLOAD_HEADER_LENGTH; - if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS) - { - pld->destroy(pld); - return PARSE_ERROR; - } - break; - } - case CERTREQ_DATA: - { - size_t data_length = payload_length - CERTREQ_PAYLOAD_HEADER_LENGTH; - if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS) - { - pld->destroy(pld); - return PARSE_ERROR; - } - break; - } - case EAP_MESSAGE: - { - size_t data_length = payload_length - EAP_PAYLOAD_HEADER_LENGTH; - if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS) - { - pld->destroy(pld); - return PARSE_ERROR; - } - break; - } - case SPIS: - { - size_t data_length = payload_length - DELETE_PAYLOAD_HEADER_LENGTH; - if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS) - { - pld->destroy(pld); - return PARSE_ERROR; - } - break; - } - case VID_DATA: - { - size_t data_length = payload_length - VENDOR_ID_PAYLOAD_HEADER_LENGTH; - if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS) - { - pld->destroy(pld); - return PARSE_ERROR; - } - break; - } - case CONFIGURATION_ATTRIBUTE_VALUE: - { - size_t data_length = attribute_length; - if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS) - { - pld->destroy(pld); - return PARSE_ERROR; - } - break; - } - case KEY_EXCHANGE_DATA: - { - size_t keydata_length = payload_length - KE_PAYLOAD_HEADER_LENGTH; - if (this->parse_chunk(this, rule_number, output + rule->offset, keydata_length) != SUCCESS) - { - pld->destroy(pld); - return PARSE_ERROR; - } - break; - } - case NOTIFICATION_DATA: - { - size_t notify_length = payload_length - NOTIFY_PAYLOAD_HEADER_LENGTH - spi_size; - if (this->parse_chunk(this, rule_number, output + rule->offset, notify_length) != SUCCESS) - { - pld->destroy(pld); - return PARSE_ERROR; - } - break; - } - case ENCRYPTED_DATA: - { - size_t data_length = payload_length - ENCRYPTION_PAYLOAD_HEADER_LENGTH; - if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS) - { - pld->destroy(pld); - return PARSE_ERROR; - } - break; - } - case TS_TYPE: - { - if (this->parse_uint8(this, rule_number, output + rule->offset) != SUCCESS) - { - pld->destroy(pld); - return PARSE_ERROR; - } - ts_type = *(u_int8_t*)(output + rule->offset); - break; - } - case ADDRESS: - { - size_t address_length = (ts_type == TS_IPV4_ADDR_RANGE) ? 4 : 16; - if (this->parse_chunk(this, rule_number, output + rule->offset,address_length) != SUCCESS) - { - pld->destroy(pld); - return PARSE_ERROR; - } - break; - } - case TRAFFIC_SELECTORS: - { - size_t traffic_selectors_length = payload_length - TS_PAYLOAD_HEADER_LENGTH; - if (this->parse_list(this, rule_number, output + rule->offset, TRAFFIC_SELECTOR_SUBSTRUCTURE, traffic_selectors_length) != SUCCESS) - { - pld->destroy(pld); - return PARSE_ERROR; - } - break; - } - case UNKNOWN_PAYLOAD: - { - size_t unknown_payload_data_length = payload_length - UNKNOWN_PAYLOAD_HEADER_LENGTH; - if (this->parse_chunk(this, rule_number, output + rule->offset, unknown_payload_data_length) != SUCCESS) - { - pld->destroy(pld); - return PARSE_ERROR; - } - break; - } - default: - { - this->logger->log(this->logger, ERROR, " no rule to parse rule %d %s (%d)", rule_number, mapping_find(encoding_type_m, rule->type), rule->type); - pld->destroy(pld); - return PARSE_ERROR; - } - } - /* process next rulue */ - rule++; - } - - *payload = pld; - this->logger->log(this->logger, CONTROL|LEVEL2, "parsing %s payload finished.", - mapping_find(payload_type_m, payload_type)); - return SUCCESS; -} - -/** - * Implementation of parser_t.get_remaining_byte_count. - */ -static int get_remaining_byte_count (private_parser_t *this) -{ - int count = (this->input_roof - this->byte_pos); - return count; -} - -/** - * Implementation of parser_t.reset_context. - */ -static void reset_context (private_parser_t *this) -{ - this->byte_pos = this->input; - this->bit_pos = 0; -} - -/** - * Implementation of parser_t.destroy. - */ -static void destroy(private_parser_t *this) -{ - free(this); -} - -/* - * Described in header. - */ -parser_t *parser_create(chunk_t data) -{ - private_parser_t *this = malloc_thing(private_parser_t); - - this->logger = logger_manager->get_logger(logger_manager, PARSER); - - this->public.parse_payload = (status_t(*)(parser_t*,payload_type_t,payload_t**)) parse_payload; - this->public.reset_context = (void(*)(parser_t*)) reset_context; - this->public.get_remaining_byte_count = (int (*) (parser_t *))get_remaining_byte_count; - this->public.destroy = (void(*)(parser_t*)) destroy; - - this->parse_uint4 = parse_uint4; - this->parse_uint8 = parse_uint8; - this->parse_uint15 = parse_uint15; - this->parse_uint16 = parse_uint16; - this->parse_uint32 = parse_uint32; - this->parse_uint64 = parse_uint64; - this->parse_bytes = parse_bytes; - this->parse_bit = parse_bit; - this->parse_list = parse_list; - this->parse_chunk = parse_chunk; - - this->input = data.ptr; - this->byte_pos = data.ptr; - this->bit_pos = 0; - this->input_roof = data.ptr + data.len; - - return (parser_t*)this; -} - diff --git a/src/charon/charon/encoding/parser.h b/src/charon/charon/encoding/parser.h deleted file mode 100644 index 216fac9b7..000000000 --- a/src/charon/charon/encoding/parser.h +++ /dev/null @@ -1,95 +0,0 @@ -/** - * @file parser.h - * - * @brief Interface of parser_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef PARSER_H_ -#define PARSER_H_ - -#include -#include -#include - - -typedef struct parser_t parser_t; - -/** - * @brief A parser_t class to parse IKEv2 payloads. - * - * A parser is used for parsing one chunk of data. Multiple - * payloads can be parsed out of the chunk using parse_payload. - * The parser remains the state until destroyed. - * - * @b Constructors: - * - parser_create() - * - * @ingroup encoding - */ -struct parser_t { - - /** - * @brief Parses the next payload. - * - * @warning Caller is responsible for freeing allocated payload. - * - * Rules for parsing are described in the payload definition. - * - * @param this parser_t bject - * @param payload_type payload type to parse - * @param[out] payload pointer where parsed payload was allocated - * @return - * - SUCCESSFUL if succeeded, - * - PARSE_ERROR if corrupted/invalid data found - */ - status_t (*parse_payload) (parser_t *this, payload_type_t payload_type, payload_t **payload); - - /** - * Gets the remaining byte count which is not currently parsed. - * - * @param parser parser_t object - */ - int (*get_remaining_byte_count) (parser_t *this); - - /** - * @brief Resets the current parser context. - * - * @param parser parser_t object - */ - void (*reset_context) (parser_t *this); - - /** - * @brief Destroys a parser_t object. - * - * @param parser parser_t object - */ - void (*destroy) (parser_t *this); -}; - -/** - * @brief Constructor to create a parser_t object. - * - * @param data chunk of data to parse with this parser_t object - * @return parser_t object - * - * @ingroup encoding - */ -parser_t *parser_create(chunk_t data); - -#endif /*PARSER_H_*/ diff --git a/src/charon/charon/encoding/payloads/Makefile.payloads b/src/charon/charon/encoding/payloads/Makefile.payloads deleted file mode 100644 index 61d920907..000000000 --- a/src/charon/charon/encoding/payloads/Makefile.payloads +++ /dev/null @@ -1,108 +0,0 @@ -# Copyright (C) 2005 Jan Hutter, 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 . -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# for more details. -# - -PAYLOADS_DIR= $(ENCODING_DIR)payloads/ - -CHARON_OBJS+= $(BUILD_DIR)encodings.o -$(BUILD_DIR)encodings.o : $(PAYLOADS_DIR)encodings.c $(PAYLOADS_DIR)encodings.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)ike_header.o -$(BUILD_DIR)ike_header.o : $(PAYLOADS_DIR)ike_header.c $(PAYLOADS_DIR)ike_header.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)ke_payload.o -$(BUILD_DIR)ke_payload.o : $(PAYLOADS_DIR)ke_payload.c $(PAYLOADS_DIR)ke_payload.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)nonce_payload.o -$(BUILD_DIR)nonce_payload.o : $(PAYLOADS_DIR)nonce_payload.c $(PAYLOADS_DIR)nonce_payload.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)notify_payload.o -$(BUILD_DIR)notify_payload.o : $(PAYLOADS_DIR)notify_payload.c $(PAYLOADS_DIR)notify_payload.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)id_payload.o -$(BUILD_DIR)id_payload.o : $(PAYLOADS_DIR)id_payload.c $(PAYLOADS_DIR)id_payload.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)auth_payload.o -$(BUILD_DIR)auth_payload.o : $(PAYLOADS_DIR)auth_payload.c $(PAYLOADS_DIR)auth_payload.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)cert_payload.o -$(BUILD_DIR)cert_payload.o : $(PAYLOADS_DIR)cert_payload.c $(PAYLOADS_DIR)cert_payload.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)certreq_payload.o -$(BUILD_DIR)certreq_payload.o : $(PAYLOADS_DIR)certreq_payload.c $(PAYLOADS_DIR)certreq_payload.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)delete_payload.o -$(BUILD_DIR)delete_payload.o : $(PAYLOADS_DIR)delete_payload.c $(PAYLOADS_DIR)delete_payload.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)vendor_id_payload.o -$(BUILD_DIR)vendor_id_payload.o : $(PAYLOADS_DIR)vendor_id_payload.c $(PAYLOADS_DIR)vendor_id_payload.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)cp_payload.o -$(BUILD_DIR)cp_payload.o : $(PAYLOADS_DIR)cp_payload.c $(PAYLOADS_DIR)cp_payload.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)configuration_attribute.o -$(BUILD_DIR)configuration_attribute.o : $(PAYLOADS_DIR)configuration_attribute.c $(PAYLOADS_DIR)configuration_attribute.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)eap_payload.o -$(BUILD_DIR)eap_payload.o : $(PAYLOADS_DIR)eap_payload.c $(PAYLOADS_DIR)eap_payload.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)unknown_payload.o -$(BUILD_DIR)unknown_payload.o : $(PAYLOADS_DIR)unknown_payload.c $(PAYLOADS_DIR)unknown_payload.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)ts_payload.o -$(BUILD_DIR)ts_payload.o : $(PAYLOADS_DIR)ts_payload.c $(PAYLOADS_DIR)ts_payload.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)traffic_selector_substructure.o -$(BUILD_DIR)traffic_selector_substructure.o : $(PAYLOADS_DIR)traffic_selector_substructure.c $(PAYLOADS_DIR)traffic_selector_substructure.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)payload.o -$(BUILD_DIR)payload.o : $(PAYLOADS_DIR)payload.c $(PAYLOADS_DIR)payload.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)proposal_substructure.o -$(BUILD_DIR)proposal_substructure.o : $(PAYLOADS_DIR)proposal_substructure.c $(PAYLOADS_DIR)proposal_substructure.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)sa_payload.o -$(BUILD_DIR)sa_payload.o : $(PAYLOADS_DIR)sa_payload.c $(PAYLOADS_DIR)sa_payload.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)transform_attribute.o -$(BUILD_DIR)transform_attribute.o : $(PAYLOADS_DIR)transform_attribute.c $(PAYLOADS_DIR)transform_attribute.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)transform_substructure.o -$(BUILD_DIR)transform_substructure.o : $(PAYLOADS_DIR)transform_substructure.c $(PAYLOADS_DIR)transform_substructure.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)encryption_payload.o -$(BUILD_DIR)encryption_payload.o : $(PAYLOADS_DIR)encryption_payload.c $(PAYLOADS_DIR)encryption_payload.h - $(CC) $(CFLAGS) -c -o $@ $< - diff --git a/src/charon/charon/encoding/payloads/auth_payload.c b/src/charon/charon/encoding/payloads/auth_payload.c deleted file mode 100644 index cc7c4bfb1..000000000 --- a/src/charon/charon/encoding/payloads/auth_payload.c +++ /dev/null @@ -1,265 +0,0 @@ -/** - * @file auth_payload.h - * - * @brief Implementation of auth_payload_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 "auth_payload.h" - -#include - - -typedef struct private_auth_payload_t private_auth_payload_t; - -/** - * Private data of an auth_payload_t object. - * - */ -struct private_auth_payload_t { - - /** - * Public auth_payload_t interface. - */ - auth_payload_t public; - - /** - * Next payload type. - */ - u_int8_t next_payload; - - /** - * Critical flag. - */ - bool critical; - - /** - * Length of this payload. - */ - u_int16_t payload_length; - - /** - * Method of the AUTH Data. - */ - u_int8_t auth_method; - - /** - * The contained auth data value. - */ - chunk_t auth_data; -}; - -/** - * Encoding rules to parse or generate a AUTH payload - * - * The defined offsets are the positions in a object of type - * 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) }, - /* 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 }, - /* Length of the whole payload*/ - { PAYLOAD_LENGTH, offsetof(private_auth_payload_t, payload_length)}, - /* 1 Byte AUTH type*/ - { U_INT_8, offsetof(private_auth_payload_t, auth_method) }, - /* 3 reserved bytes */ - { RESERVED_BYTE, 0 }, - { RESERVED_BYTE, 0 }, - { RESERVED_BYTE, 0 }, - /* some auth data bytes, length is defined in PAYLOAD_LENGTH */ - { AUTH_DATA, offsetof(private_auth_payload_t, auth_data) } -}; - -/* - 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! Next Payload !C! RESERVED ! Payload Length ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! Auth Method ! RESERVED ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! ! - ~ Authentication Data ~ - ! ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -*/ - -/** - * Implementation of payload_t.verify. - */ -static status_t verify(private_auth_payload_t *this) -{ - if ((this->auth_method == 0) || - ((this->auth_method >= 4) && (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) -{ - *rules = auth_payload_encodings; - *rule_count = sizeof(auth_payload_encodings) / sizeof(encoding_rule_t); -} - -/** - * Implementation of payload_t.get_type. - */ -static payload_type_t get_payload_type(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) -{ - 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) -{ - this->next_payload = type; -} - -/** - * Implementation of payload_t.get_length. - */ -static size_t get_length(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) -{ - this->auth_method = method; -} - -/** - * Implementation of auth_payload_t.get_auth_method. - */ -static auth_method_t get_auth_method (private_auth_payload_t *this) -{ - return (this->auth_method); -} - -/** - * Implementation of auth_payload_t.set_data. - */ -static void set_data (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; - 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) -{ - return (this->auth_data); -} - -/** - * Implementation of auth_payload_t.get_data_clone. - */ -static chunk_t get_data_clone (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); -} - -/* - * Described in header - */ -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_INITIALIZER; - - return (&(this->public)); -} diff --git a/src/charon/charon/encoding/payloads/auth_payload.h b/src/charon/charon/encoding/payloads/auth_payload.h deleted file mode 100644 index 30db4f254..000000000 --- a/src/charon/charon/encoding/payloads/auth_payload.h +++ /dev/null @@ -1,122 +0,0 @@ -/** - * @file auth_payload.h - * - * @brief Interface of auth_payload_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - - -#ifndef AUTH_PAYLOAD_H_ -#define AUTH_PAYLOAD_H_ - -#include -#include -#include - -/** - * Length of a auth payload without the auth data in bytes. - * - * @ingroup payloads - */ -#define AUTH_PAYLOAD_HEADER_LENGTH 8 - - -typedef struct auth_payload_t auth_payload_t; - -/** - * @brief Class representing an IKEv2 AUTH payload. - * - * The AUTH payload format is described in RFC section 3.8. - * - * @b Constructors: - * - auth_payload_create() - * - * @ingroup payloads - */ -struct auth_payload_t { - - /** - * The payload_t interface. - */ - payload_t payload_interface; - - /** - * @brief Set the AUTH method. - * - * @param this calling auth_payload_t object - * @param method auth_method_t to use - */ - void (*set_auth_method) (auth_payload_t *this, auth_method_t method); - - /** - * @brief Get the AUTH method. - * - * @param this calling auth_payload_t object - * @return auth_method_t used - */ - auth_method_t (*get_auth_method) (auth_payload_t *this); - - /** - * @brief Set the AUTH data. - * - * Data are getting cloned. - * - * @param this calling auth_payload_t object - * @param data AUTH data as chunk_t - */ - void (*set_data) (auth_payload_t *this, chunk_t data); - - /** - * @brief Get the AUTH data. - * - * Returned data are a copy of the internal one. - * - * @param this calling auth_payload_t object - * @return AUTH data as chunk_t - */ - chunk_t (*get_data_clone) (auth_payload_t *this); - - /** - * @brief Get the AUTH data. - * - * Returned data are NOT copied - * - * @param this calling auth_payload_t object - * @return AUTH data as chunk_t - */ - chunk_t (*get_data) (auth_payload_t *this); - - /** - * @brief Destroys an auth_payload_t object. - * - * @param this auth_payload_t object to destroy - */ - void (*destroy) (auth_payload_t *this); -}; - -/** - * @brief Creates an empty auth_payload_t object. - * - * @return auth_payload_t object - * - * @ingroup payloads - */ -auth_payload_t *auth_payload_create(void); - - -#endif /* AUTH_PAYLOAD_H_ */ diff --git a/src/charon/charon/encoding/payloads/cert_payload.c b/src/charon/charon/encoding/payloads/cert_payload.c deleted file mode 100644 index 146d42eda..000000000 --- a/src/charon/charon/encoding/payloads/cert_payload.c +++ /dev/null @@ -1,279 +0,0 @@ -/** - * @file cert_payload.c - * - * @brief Implementation of cert_payload_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 - -#include "cert_payload.h" - - -/** - * String mappings for cert_encoding_t. - */ -mapping_t cert_encoding_m[] = { - {PKCS7_WRAPPED_X509_CERTIFICATE, "PKCS7_WRAPPED_X509_CERTIFICATE"}, - {PGP_CERTIFICATE, "PGP_CERTIFICATE"}, - {DNS_SIGNED_KEY, "DNS_SIGNED_KEY"}, - {X509_CERTIFICATE_SIGNATURE, "X509_CERTIFICATE_SIGNATURE"}, - {KERBEROS_TOKEN, "KERBEROS_TOKEN"}, - {CERTIFICATE_REVOCATION_LIST, "CERTIFICATE_REVOCATION_LIST"}, - {AUTHORITY_REVOCATION_LIST, "AUTHORITY_REVOCATION_LIST"}, - {SPKI_CERTIFICATE, "SPKI_CERTIFICATE"}, - {X509_CERTIFICATE_ATTRIBUTE, "X509_CERTIFICATE_ATTRIBUTE"}, - {RAW_SA_KEY, "RAW_SA_KEY"}, - {HASH_AND_URL_X509_CERTIFICATE, "HASH_AND_URL_X509_CERTIFICATE"}, - {HASH_AND_URL_X509_BUNDLE, "HASH_AND_URL_X509_BUNDLE"}, - {MAPPING_END, NULL} -}; - - -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. - */ - cert_payload_t public; - - /** - * Next payload type. - */ - u_int8_t next_payload; - - /** - * Critical flag. - */ - bool critical; - - /** - * Length of this payload. - */ - u_int16_t payload_length; - - /** - * Encoding of the CERT Data. - */ - u_int8_t cert_encoding; - - /** - * The contained cert data value. - */ - chunk_t cert_data; -}; - -/** - * Encoding rules to parse or generate a CERT payload - * - * The defined offsets are the positions in a object of type - * 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) }, - /* the critical bit */ - { 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 }, - /* 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, cert_encoding) }, - /* some cert data bytes, length is defined in PAYLOAD_LENGTH */ - { CERT_DATA, offsetof(private_cert_payload_t, cert_data) } -}; - -/* - 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! Next Payload !C! RESERVED ! Payload Length ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! Cert Encoding ! ! - +-+-+-+-+-+-+-+-+ ! - ~ Certificate Data ~ - ! ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -*/ - -/** - * Implementation of payload_t.verify. - */ -static status_t verify(private_cert_payload_t *this) -{ - if ((this->cert_encoding == 0) || - ((this->cert_encoding >= 14) && (this->cert_encoding <= 200))) - { - /* reserved IDs */ - return FAILED; - } - 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) -{ - *rules = cert_payload_encodings; - *rule_count = sizeof(cert_payload_encodings) / sizeof(encoding_rule_t); -} - -/** - * Implementation of payload_t.get_type. - */ -static payload_type_t get_payload_type(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) -{ - 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) -{ - this->next_payload = type; -} - -/** - * Implementation of payload_t.get_length. - */ -static size_t get_length(private_cert_payload_t *this) -{ - return this->payload_length; -} - -/** - * Implementation of cert_payload_t.set_cert_encoding. - */ -static void set_cert_encoding (private_cert_payload_t *this, cert_encoding_t encoding) -{ - this->cert_encoding = encoding; -} - -/** - * Implementation of cert_payload_t.get_cert_encoding. - */ -static cert_encoding_t get_cert_encoding (private_cert_payload_t *this) -{ - return (this->cert_encoding); -} - -/** - * Implementation of cert_payload_t.set_data. - */ -static void set_data (private_cert_payload_t *this, chunk_t data) -{ - if (this->cert_data.ptr != NULL) - { - chunk_free(&(this->cert_data)); - } - this->cert_data.ptr = clalloc(data.ptr,data.len); - this->cert_data.len = data.len; - this->payload_length = CERT_PAYLOAD_HEADER_LENGTH + this->cert_data.len; -} - -/** - * Implementation of cert_payload_t.get_data. - */ -static chunk_t get_data (private_cert_payload_t *this) -{ - return (this->cert_data); -} - -/** - * Implementation of cert_payload_t.get_data_clone. - */ -static chunk_t get_data_clone (private_cert_payload_t *this) -{ - chunk_t cloned_data; - if (this->cert_data.ptr == NULL) - { - return (this->cert_data); - } - cloned_data.ptr = clalloc(this->cert_data.ptr,this->cert_data.len); - cloned_data.len = this->cert_data.len; - return cloned_data; -} - -/** - * Implementation of payload_t.destroy and cert_payload_t.destroy. - */ -static void destroy(private_cert_payload_t *this) -{ - if (this->cert_data.ptr != NULL) - { - chunk_free(&(this->cert_data)); - } - - free(this); -} - -/* - * Described in header - */ -cert_payload_t *cert_payload_create() -{ - private_cert_payload_t *this = malloc_thing(private_cert_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 (*) (cert_payload_t *)) destroy; - this->public.set_cert_encoding = (void (*) (cert_payload_t *,cert_encoding_t)) set_cert_encoding; - this->public.get_cert_encoding = (cert_encoding_t (*) (cert_payload_t *)) get_cert_encoding; - this->public.set_data = (void (*) (cert_payload_t *,chunk_t)) set_data; - this->public.get_data_clone = (chunk_t (*) (cert_payload_t *)) get_data_clone; - this->public.get_data = (chunk_t (*) (cert_payload_t *)) get_data; - - /* private variables */ - this->critical = FALSE; - this->next_payload = NO_PAYLOAD; - this->payload_length =CERT_PAYLOAD_HEADER_LENGTH; - this->cert_data = CHUNK_INITIALIZER; - - return (&(this->public)); -} diff --git a/src/charon/charon/encoding/payloads/cert_payload.h b/src/charon/charon/encoding/payloads/cert_payload.h deleted file mode 100644 index 51620d699..000000000 --- a/src/charon/charon/encoding/payloads/cert_payload.h +++ /dev/null @@ -1,155 +0,0 @@ -/** - * @file cert_payload.h - * - * @brief Interface of cert_payload_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef CERT_PAYLOAD_H_ -#define CERT_PAYLOAD_H_ - -#include -#include - -/** - * Length of a cert payload without the cert data in bytes. - * - * @ingroup payloads - */ -#define CERT_PAYLOAD_HEADER_LENGTH 5 - - -typedef enum cert_encoding_t cert_encoding_t; - -/** - * @brief Certificate encoding, as described in IKEv2 RFC section 3.6 - * - * @ingroup payloads - */ -enum cert_encoding_t { - PKCS7_WRAPPED_X509_CERTIFICATE = 1, - PGP_CERTIFICATE = 2, - DNS_SIGNED_KEY = 3, - X509_CERTIFICATE_SIGNATURE = 4, - KERBEROS_TOKEN = 6, - CERTIFICATE_REVOCATION_LIST = 7, - AUTHORITY_REVOCATION_LIST = 8, - SPKI_CERTIFICATE = 9, - X509_CERTIFICATE_ATTRIBUTE = 10, - RAW_SA_KEY = 11, - HASH_AND_URL_X509_CERTIFICATE = 12, - HASH_AND_URL_X509_BUNDLE = 13 -}; - -/** - * string mappings for cert_encoding_t. - * - * @ingroup payloads - */ -extern mapping_t cert_encoding_m[]; - - -typedef struct cert_payload_t cert_payload_t; - -/** - * @brief Class representing an IKEv2 CERT payload. - * - * The CERT payload format is described in RFC section 3.6. - * This is just a dummy implementation to fullfill the standards - * requirements. A full implementation would offer setters/getters - * for the different encoding types. - * - * @b Constructors: - * - cert_payload_create() - * - * @todo Implement setters/getters for the different certificate encodings. - * - * @ingroup payloads - */ -struct cert_payload_t { - - /** - * The payload_t interface. - */ - payload_t payload_interface; - - /** - * @brief Set the CERT encoding. - * - * @param this calling cert_payload_t object - * @param encoding CERT encoding - */ - void (*set_cert_encoding) (cert_payload_t *this, cert_encoding_t encoding); - - /** - * @brief Get the CERT encoding. - * - * @param this calling cert_payload_t object - * @return Encoding of the CERT - */ - cert_encoding_t (*get_cert_encoding) (cert_payload_t *this); - - /** - * @brief Set the CERT data. - * - * Data are getting cloned. - * - * @param this calling cert_payload_t object - * @param data CERT data as chunk_t - */ - void (*set_data) (cert_payload_t *this, chunk_t data); - - /** - * @brief Get the CERT data. - * - * Returned data are a copy of the internal one. - * - * @param this calling cert_payload_t object - * @return CERT data as chunk_t - */ - chunk_t (*get_data_clone) (cert_payload_t *this); - - /** - * @brief Get the CERT data. - * - * Returned data are NOT copied. - * - * @param this calling cert_payload_t object - * @return CERT data as chunk_t - */ - chunk_t (*get_data) (cert_payload_t *this); - - /** - * @brief Destroys an cert_payload_t object. - * - * @param this cert_payload_t object to destroy - */ - void (*destroy) (cert_payload_t *this); -}; - -/** - * @brief Creates an empty cert_payload_t object. - * - * @return cert_payload_t object - * - * @ingroup payloads - */ -cert_payload_t *cert_payload_create(void); - - -#endif /* CERT_PAYLOAD_H_ */ diff --git a/src/charon/charon/encoding/payloads/certreq_payload.c b/src/charon/charon/encoding/payloads/certreq_payload.c deleted file mode 100644 index cdab82be4..000000000 --- a/src/charon/charon/encoding/payloads/certreq_payload.c +++ /dev/null @@ -1,259 +0,0 @@ -/** - * @file certreq_payload.c - * - * @brief Implementation of certreq_payload_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 - -#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. - */ - certreq_payload_t public; - - /** - * Next payload type. - */ - u_int8_t next_payload; - - /** - * Critical flag. - */ - bool critical; - - /** - * Length of this payload. - */ - u_int16_t payload_length; - - /** - * Encoding of the CERT Data. - */ - u_int8_t cert_encoding; - - /** - * The contained certreq data value. - */ - chunk_t certreq_data; -}; - -/** - * Encoding rules to parse or generate a CERTREQ payload - * - * The defined offsets are the positions in a object of type - * private_certreq_payload_t. - * - */ -encoding_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) }, - /* 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 }, - /* Length of the whole payload*/ - { PAYLOAD_LENGTH, offsetof(private_certreq_payload_t, payload_length)}, - /* 1 Byte CERTREQ type*/ - { U_INT_8, offsetof(private_certreq_payload_t, cert_encoding)}, - /* some certreq data bytes, length is defined in PAYLOAD_LENGTH */ - { CERTREQ_DATA, offsetof(private_certreq_payload_t, certreq_data)} -}; - -/* - 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! Next Payload !C! RESERVED ! Payload Length ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! Cert Encoding ! ! - +-+-+-+-+-+-+-+-+ ! - ~ Certification Authority ~ - ! ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -*/ - -/** - * Implementation of payload_t.verify. - */ -static status_t verify(private_certreq_payload_t *this) -{ - if ((this->cert_encoding == 0) || - ((this->cert_encoding >= 14) && (this->cert_encoding <= 200))) - { - /* reserved IDs */ - return FAILED; - } - 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) -{ - *rules = certreq_payload_encodings; - *rule_count = sizeof(certreq_payload_encodings) / sizeof(encoding_rule_t); -} - -/** - * Implementation of payload_t.get_type. - */ -static payload_type_t get_payload_type(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) -{ - 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) -{ - this->next_payload = type; -} - -/** - * Implementation of payload_t.get_length. - */ -static size_t get_length(private_certreq_payload_t *this) -{ - return this->payload_length; -} - -/** - * Implementation of certreq_payload_t.set_cert_encoding. - */ -static void set_cert_encoding (private_certreq_payload_t *this, cert_encoding_t encoding) -{ - this->cert_encoding = encoding; -} - -/** - * Implementation of certreq_payload_t.get_cert_encoding. - */ -static cert_encoding_t get_cert_encoding (private_certreq_payload_t *this) -{ - return (this->cert_encoding); -} - -/** - * Implementation of certreq_payload_t.set_data. - */ -static void set_data (private_certreq_payload_t *this, chunk_t data) -{ - if (this->certreq_data.ptr != NULL) - { - chunk_free(&(this->certreq_data)); - } - this->certreq_data.ptr = clalloc(data.ptr,data.len); - this->certreq_data.len = data.len; - this->payload_length = CERTREQ_PAYLOAD_HEADER_LENGTH + this->certreq_data.len; -} - -/** - * Implementation of certreq_payload_t.get_data. - */ -static chunk_t get_data (private_certreq_payload_t *this) -{ - return (this->certreq_data); -} - -/** - * Implementation of certreq_payload_t.get_data_clone. - */ -static chunk_t get_data_clone (private_certreq_payload_t *this) -{ - chunk_t cloned_data; - if (this->certreq_data.ptr == NULL) - { - return (this->certreq_data); - } - cloned_data.ptr = clalloc(this->certreq_data.ptr,this->certreq_data.len); - cloned_data.len = this->certreq_data.len; - return cloned_data; -} - -/** - * Implementation of payload_t.destroy and certreq_payload_t.destroy. - */ -static void destroy(private_certreq_payload_t *this) -{ - if (this->certreq_data.ptr != NULL) - { - chunk_free(&(this->certreq_data)); - } - - free(this); -} - -/* - * Described in header - */ -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.set_cert_encoding = (void (*) (certreq_payload_t *,cert_encoding_t)) set_cert_encoding; - this->public.get_cert_encoding = (cert_encoding_t (*) (certreq_payload_t *)) get_cert_encoding; - this->public.set_data = (void (*) (certreq_payload_t *,chunk_t)) set_data; - this->public.get_data_clone = (chunk_t (*) (certreq_payload_t *)) get_data_clone; - this->public.get_data = (chunk_t (*) (certreq_payload_t *)) get_data; - - /* private variables */ - this->critical = FALSE; - this->next_payload = NO_PAYLOAD; - this->payload_length =CERTREQ_PAYLOAD_HEADER_LENGTH; - this->certreq_data = CHUNK_INITIALIZER; - - return (&(this->public)); -} diff --git a/src/charon/charon/encoding/payloads/certreq_payload.h b/src/charon/charon/encoding/payloads/certreq_payload.h deleted file mode 100644 index a4b0f1f50..000000000 --- a/src/charon/charon/encoding/payloads/certreq_payload.h +++ /dev/null @@ -1,125 +0,0 @@ -/** - * @file certreq_payload.h - * - * @brief Interface of certreq_payload_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef CERTREQ_PAYLOAD_H_ -#define CERTREQ_PAYLOAD_H_ - -#include -#include -#include - -/** - * Length of a CERTREQ payload without the CERTREQ data in bytes. - * - * @ingroup payloads - */ -#define CERTREQ_PAYLOAD_HEADER_LENGTH 5 - - -typedef struct certreq_payload_t certreq_payload_t; - -/** - * @brief Class representing an IKEv2 CERTREQ payload. - * - * The CERTREQ payload format is described in RFC section 3.7. - * This is just a dummy implementation to fullfill the standards - * requirements. A full implementation would offer setters/getters - * for the different encoding types. - * - * @b Constructors: - * - certreq_payload_create() - * - * @todo Implement payload functionality. - * - * @ingroup payloads - */ -struct certreq_payload_t { - /** - * The payload_t interface. - */ - payload_t payload_interface; - - /** - * @brief Set the CERT encoding. - * - * @param this calling certreq_payload_t object - * @param encoding CERT encoding - */ - void (*set_cert_encoding) (certreq_payload_t *this, cert_encoding_t encoding); - - /** - * @brief Get the CERT encoding. - * - * @param this calling certreq_payload_t object - * @return Encoding of the CERT - */ - cert_encoding_t (*get_cert_encoding) (certreq_payload_t *this); - - /** - * @brief Set the CERTREQ data. - * - * Data are getting cloned. - * - * @param this calling certreq_payload_t object - * @param data CERTREQ data as chunk_t - */ - void (*set_data) (certreq_payload_t *this, chunk_t data); - - /** - * @brief Get the CERTREQ data. - * - * Returned data are a copy of the internal one. - * - * @param this calling certreq_payload_t object - * @return CERTREQ data as chunk_t - */ - chunk_t (*get_data_clone) (certreq_payload_t *this); - - /** - * @brief Get the CERTREQ data. - * - * Returned data are NOT copied. - * - * @param this calling certreq_payload_t object - * @return CERTREQ data as chunk_t - */ - chunk_t (*get_data) (certreq_payload_t *this); - - /** - * @brief Destroys an certreq_payload_t object. - * - * @param this certreq_payload_t object to destroy - */ - void (*destroy) (certreq_payload_t *this); -}; - -/** - * @brief Creates an empty certreq_payload_t object. - * - * @return certreq_payload_t object - * - * @ingroup payloads - */ -certreq_payload_t *certreq_payload_create(void); - - -#endif /* CERTREQ_PAYLOAD_H_ */ diff --git a/src/charon/charon/encoding/payloads/configuration_attribute.c b/src/charon/charon/encoding/payloads/configuration_attribute.c deleted file mode 100644 index 489d7f372..000000000 --- a/src/charon/charon/encoding/payloads/configuration_attribute.c +++ /dev/null @@ -1,282 +0,0 @@ -/** - * @file configuration_attribute.c - * - * @brief Implementation of configuration_attribute_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 - -#include "configuration_attribute.h" - -#include -#include - - -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; - - /** - * Type of the attribute. - */ - u_int16_t attribute_type; - - /** - * Length of the attribute. - */ - u_int16_t attribute_length; - - - /** - * Attribute value as chunk. - */ - chunk_t attribute_value; -}; - -/** - * String mappings for configuration_attribute_type_t. - */ -mapping_t configuration_attribute_type_m[] = { - {INTERNAL_IP4_ADDRESS, "INTERNAL_IP4_ADDRESS"}, - {INTERNAL_IP4_NETMASK, "INTERNAL_IP4_NETMASK"}, - {INTERNAL_IP4_DNS, "INTERNAL_IP4_DNS"}, - {INTERNAL_IP4_NBNS, "INTERNAL_IP4_NBNS"}, - {INTERNAL_ADDRESS_EXPIRY, "INTERNAL_ADDRESS_EXPIRY"}, - {INTERNAL_IP4_DHCP, "INTERNAL_IP4_DHCP"}, - {APPLICATION_VERSION, "APPLICATION_VERSION"}, - {INTERNAL_IP6_ADDRESS, "INTERNAL_IP6_ADDRESS"}, - {INTERNAL_IP6_DNS, "INTERNAL_IP6_DNS"}, - {INTERNAL_IP6_NBNS, "INTERNAL_IP6_NBNS"}, - {INTERNAL_IP6_DHCP, "INTERNAL_IP6_DHCP"}, - {INTERNAL_IP4_SUBNET, "INTERNAL_IP4_SUBNET"}, - {SUPPORTED_ATTRIBUTES, "SUPPORTED_ATTRIBUTES"}, - {INTERNAL_IP6_SUBNET, "INTERNAL_IP6_SUBNET"}, - {MAPPING_END, NULL} -}; - - -/** - * Encoding rules to parse or generate a configuration attribute. - * - * The defined offsets are the positions in a object of type - * private_configuration_attribute_t. - * - */ -encoding_rule_t configuration_attribute_encodings[] = { - - { RESERVED_BIT, 0 }, - /* type of the attribute as 15 bit unsigned integer */ - { ATTRIBUTE_TYPE, offsetof(private_configuration_attribute_t, attribute_type) }, - /* Length of attribute value */ - { CONFIGURATION_ATTRIBUTE_LENGTH, offsetof(private_configuration_attribute_t, attribute_length)}, - /* Value of attribute if attribute format flag is zero */ - { CONFIGURATION_ATTRIBUTE_VALUE, offsetof(private_configuration_attribute_t, attribute_value)} -}; - -/* - 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - !R| Attribute Type ! Length | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | | - ~ Value ~ - | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -*/ - -/** - * Implementation of payload_t.verify. - */ -static status_t verify(private_configuration_attribute_t *this) -{ - switch (this->attribute_type) - { - case INTERNAL_IP4_ADDRESS: - case INTERNAL_IP4_NETMASK: - case INTERNAL_IP4_DNS: - case INTERNAL_IP4_NBNS: - case INTERNAL_ADDRESS_EXPIRY: - case INTERNAL_IP4_DHCP: - case APPLICATION_VERSION: - case INTERNAL_IP6_ADDRESS: - case INTERNAL_IP6_DNS: - case INTERNAL_IP6_NBNS: - case INTERNAL_IP6_DHCP: - case INTERNAL_IP4_SUBNET: - case SUPPORTED_ATTRIBUTES: - case INTERNAL_IP6_SUBNET: - { - /* Attribute types are not checked in here */ - break; - } - default: - return FAILED; - } - - if (this->attribute_length != this->attribute_value.len) - { - return FAILED; - } - - 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) -{ - *rules = configuration_attribute_encodings; - *rule_count = sizeof(configuration_attribute_encodings) / sizeof(encoding_rule_t); -} - -/** - * Implementation of payload_t.get_type. - */ -static payload_type_t get_type(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) -{ - return (NO_PAYLOAD); -} - -/** - * Implementation of payload_t.set_next_type. - */ -static void set_next_type(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) -{ - return (this->attribute_value.len + CONFIGURATION_ATTRIBUTE_HEADER_LENGTH); -} - -/** - * Implementation of configuration_attribute_t.set_value. - */ -static void set_value(private_configuration_attribute_t *this, chunk_t value) -{ - if (this->attribute_value.ptr != NULL) - { - /* free existing value */ - chunk_free(&(this->attribute_value)); - } - - this->attribute_value.ptr = clalloc(value.ptr,value.len); - this->attribute_value.len = value.len; - - this->attribute_length = this->attribute_value.len; -} - -/** - * Implementation of configuration_attribute_t.get_value. - */ -static chunk_t get_value (private_configuration_attribute_t *this) -{ - return this->attribute_value; -} - - -/** - * Implementation of configuration_attribute_t.set_attribute_type. - */ -static void set_attribute_type (private_configuration_attribute_t *this, u_int16_t type) -{ - this->attribute_type = type & 0x7FFF; -} - -/** - * Implementation of configuration_attribute_t.get_attribute_type. - */ -static u_int16_t get_attribute_type (private_configuration_attribute_t *this) -{ - return this->attribute_type; -} - -/** - * Implementation of configuration_attribute_t.get_attribute_length. - */ -static u_int16_t get_attribute_length (private_configuration_attribute_t *this) -{ - return this->attribute_length; -} - - -/** - * Implementation of configuration_attribute_t.destroy and payload_t.destroy. - */ -static void destroy(private_configuration_attribute_t *this) -{ - if (this->attribute_value.ptr != NULL) - { - free(this->attribute_value.ptr); - } - free(this); -} - -/* - * Described in header. - */ -configuration_attribute_t *configuration_attribute_create() -{ - private_configuration_attribute_t *this = malloc_thing(private_configuration_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 = (void (*) (configuration_attribute_t *,chunk_t)) set_value; - this->public.get_value = (chunk_t (*) (configuration_attribute_t *)) get_value; - this->public.set_attribute_type = (void (*) (configuration_attribute_t *,u_int16_t type)) set_attribute_type; - this->public.get_attribute_type = (u_int16_t (*) (configuration_attribute_t *)) get_attribute_type; - this->public.get_attribute_length = (u_int16_t (*) (configuration_attribute_t *)) get_attribute_length; - this->public.destroy = (void (*) (configuration_attribute_t *)) destroy; - - /* set default values of the fields */ - this->attribute_type = 0; - this->attribute_value = CHUNK_INITIALIZER; - this->attribute_length = 0; - - return (&(this->public)); -} diff --git a/src/charon/charon/encoding/payloads/configuration_attribute.h b/src/charon/charon/encoding/payloads/configuration_attribute.h deleted file mode 100644 index b8d95a190..000000000 --- a/src/charon/charon/encoding/payloads/configuration_attribute.h +++ /dev/null @@ -1,149 +0,0 @@ -/** - * @file configuration_attribute.h - * - * @brief Interface of configuration_attribute_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef CONFIGURATION_ATTRIBUTE_H_ -#define CONFIGURATION_ATTRIBUTE_H_ - -#include -#include - - - -/** - * Configuration attribute header length in bytes. - * - * @ingroup payloads - */ -#define CONFIGURATION_ATTRIBUTE_HEADER_LENGTH 4 - - -typedef enum configuration_attribute_type_t configuration_attribute_type_t; - -/** - * Type of the attribute, as in IKEv2 RFC 3.15.1. - * - * @ingroup payloads - */ -enum configuration_attribute_type_t { - INTERNAL_IP4_ADDRESS = 1, - INTERNAL_IP4_NETMASK = 2, - INTERNAL_IP4_DNS = 3, - INTERNAL_IP4_NBNS = 4, - INTERNAL_ADDRESS_EXPIRY = 5, - INTERNAL_IP4_DHCP = 6, - APPLICATION_VERSION = 7, - INTERNAL_IP6_ADDRESS = 8, - INTERNAL_IP6_DNS = 10, - INTERNAL_IP6_NBNS = 11, - INTERNAL_IP6_DHCP = 12, - INTERNAL_IP4_SUBNET = 13, - SUPPORTED_ATTRIBUTES = 14, - INTERNAL_IP6_SUBNET = 15 -}; - -/** - * String mappings for configuration_attribute_type_t. - * - * @ingroup payloads - */ -extern mapping_t configuration_attribute_type_m[]; - -typedef struct configuration_attribute_t configuration_attribute_t; - -/** - * @brief Class representing an IKEv2-CONFIGURATION Attribute. - * - * The CONFIGURATION ATTRIBUTE format is described in RFC section 3.15.1. - * - * @b Constructors: - * - configuration_attribute_create() - * - * @ingroup payloads - */ -struct configuration_attribute_t { - /** - * The payload_t interface. - */ - payload_t payload_interface; - - /** - * @brief Returns the currently set value of the attribute. - * - * @warning Returned data are not copied. - * - * @param this calling configuration_attribute_t object - * @return chunk_t pointing to the value - */ - chunk_t (*get_value) (configuration_attribute_t *this); - - /** - * @brief Sets the value of the attribute. - * - * @warning Value is getting copied. - * - * @param this calling configuration_attribute_t object - * @param value chunk_t pointing to the value to set - */ - void (*set_value) (configuration_attribute_t *this, chunk_t value); - - /** - * @brief Sets the type of the attribute. - * - * @param this calling configuration_attribute_t object - * @param type type to set (most significant bit is set to zero) - */ - void (*set_attribute_type) (configuration_attribute_t *this, u_int16_t type); - - /** - * @brief get the type of the attribute. - * - * @param this calling configuration_attribute_t object - * @return type of the value - */ - u_int16_t (*get_attribute_type) (configuration_attribute_t *this); - - /** - * @brief get the length of an attribute. - * - * @param this calling configuration_attribute_t object - * @return type of the value - */ - u_int16_t (*get_attribute_length) (configuration_attribute_t *this); - - /** - * @brief Destroys an configuration_attribute_t object. - * - * @param this configuration_attribute_t object to destroy - */ - void (*destroy) (configuration_attribute_t *this); -}; - -/** - * @brief Creates an empty configuration_attribute_t object. - * - * @return created configuration_attribute_t object - * - * @ingroup payloads - */ -configuration_attribute_t *configuration_attribute_create(void); - -#endif /* CONFIGURATION_ATTRIBUTE_H_*/ diff --git a/src/charon/charon/encoding/payloads/cp_payload.c b/src/charon/charon/encoding/payloads/cp_payload.c deleted file mode 100644 index 583488382..000000000 --- a/src/charon/charon/encoding/payloads/cp_payload.c +++ /dev/null @@ -1,305 +0,0 @@ -/** - * @file cp_payload.c - * - * @brief Implementation of cp_payload_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 - -#include "cp_payload.h" - -#include -#include - - -/** - * String mappings for config_type_t. - */ -mapping_t config_type_m[] = { - {CFG_REQUEST, "CFG_REQUEST"}, - {CFG_REPLY, "CFG_REPLY"}, - {CFG_SET, "CFG_SET"}, - {CFG_ACK, "CFG_ACK"}, - {MAPPING_END, NULL} -}; - - -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. - */ - cp_payload_t public; - - /** - * Next payload type. - */ - u_int8_t next_payload; - - /** - * Critical flag. - */ - bool critical; - - /** - * Length of this payload. - */ - u_int16_t payload_length; - - /** - * Configuration Attributes in this payload are stored in a linked_list_t. - */ - linked_list_t * attributes; - - /** - * Config Type. - */ - u_int8_t config_type; - - /** - * @brief Computes the length of this payload. - * - * @param this calling private_cp_payload_t object - */ - void (*compute_length) (private_cp_payload_t *this); -}; - -/** - * Encoding rules to parse or generate a IKEv2-CP Payload - * - * The defined offsets are the positions in a object of type - * private_cp_payload_t. - * - */ -encoding_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) }, - /* 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 }, - /* Length of the whole CP payload*/ - { PAYLOAD_LENGTH, offsetof(private_cp_payload_t, payload_length) }, - /* Proposals are stored in a proposal substructure, - offset points to a linked_list_t pointer */ - { U_INT_8, offsetof(private_cp_payload_t, config_type) }, - { RESERVED_BYTE,0 }, - { RESERVED_BYTE,0 }, - { RESERVED_BYTE,0 }, - { CONFIGURATION_ATTRIBUTES, offsetof(private_cp_payload_t, attributes) } -}; - -/* - 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! Next Payload !C! RESERVED ! Payload Length ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! CFG Type ! RESERVED ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! ! - ~ Configuration Attributes ~ - ! ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -*/ - -/** - * Implementation of payload_t.verify. - */ -static status_t verify(private_cp_payload_t *this) -{ - status_t status = SUCCESS; - iterator_t *iterator; - - iterator = this->attributes->create_iterator(this->attributes,TRUE); - - while(iterator->has_next(iterator)) - { - configuration_attribute_t *attribute; - iterator->current(iterator,(void **)&attribute); - status = attribute->payload_interface.verify(&(attribute->payload_interface)); - if (status != SUCCESS) - { - break; - } - } - - iterator->destroy(iterator); - 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) -{ - *rules = cp_payload_encodings; - *rule_count = sizeof(cp_payload_encodings) / sizeof(encoding_rule_t); -} - -/** - * Implementation of payload_t.get_type. - */ -static payload_type_t get_type(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) -{ - 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) -{ - this->next_payload = type; -} - -/** - * Implementation of payload_t.get_length. - */ -static size_t get_length(private_cp_payload_t *this) -{ - this->compute_length(this); - return this->payload_length; -} - -/** - * Implementation of cp_payload_t.create_configuration_attribute_iterator. - */ -static iterator_t *create_configuration_attribute_iterator (private_cp_payload_t *this,bool forward) -{ - return this->attributes->create_iterator(this->attributes,forward); -} - -/** - * Implementation of cp_payload_t.add_proposal_substructure. - */ -static void add_configuration_attribute (private_cp_payload_t *this,configuration_attribute_t *attribute) -{ - this->attributes->insert_last(this->attributes,(void *) attribute); - this->compute_length(this); -} - -/** - * Implementation of cp_payload_t.set_config_type. - */ -static void set_config_type (private_cp_payload_t *this,config_type_t config_type) -{ - this->config_type = config_type; -} - -/** - * Implementation of cp_payload_t.get_config_type. - */ -static config_type_t get_config_type (private_cp_payload_t *this) -{ - return this->config_type; -} - -/** - * Implementation of private_cp_payload_t.compute_length. - */ -static void compute_length (private_cp_payload_t *this) -{ - iterator_t *iterator; - size_t length = CP_PAYLOAD_HEADER_LENGTH; - iterator = this->attributes->create_iterator(this->attributes,TRUE); - while (iterator->has_next(iterator)) - { - payload_t *current_attribute; - iterator->current(iterator,(void **) ¤t_attribute); - length += current_attribute->get_length(current_attribute); - } - iterator->destroy(iterator); - - this->payload_length = length; -} - -/** - * Implementation of payload_t.destroy and cp_payload_t.destroy. - */ -static status_t destroy(private_cp_payload_t *this) -{ - /* all attributes are getting destroyed */ - while (this->attributes->get_count(this->attributes) > 0) - { - configuration_attribute_t *current_attribute; - this->attributes->remove_last(this->attributes,(void **)¤t_attribute); - current_attribute->destroy(current_attribute); - } - this->attributes->destroy(this->attributes); - - free(this); - - return SUCCESS; -} - -/* - * Described in header. - */ -cp_payload_t *cp_payload_create() -{ - private_cp_payload_t *this = malloc_thing(private_cp_payload_t); - - /* public 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_configuration_attribute_iterator = (iterator_t* (*) (cp_payload_t *,bool)) create_configuration_attribute_iterator; - this->public.add_configuration_attribute = (void (*) (cp_payload_t *,configuration_attribute_t *)) add_configuration_attribute; - this->public.set_config_type = (void (*) (cp_payload_t *, config_type_t)) set_config_type; - this->public.get_config_type = (config_type_t (*) (cp_payload_t *)) get_config_type; - this->public.destroy = (void (*) (cp_payload_t *)) destroy; - - - /* private functions */ - this->compute_length = compute_length; - - /* 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(); - return (&(this->public)); -} diff --git a/src/charon/charon/encoding/payloads/cp_payload.h b/src/charon/charon/encoding/payloads/cp_payload.h deleted file mode 100644 index 235d36f43..000000000 --- a/src/charon/charon/encoding/payloads/cp_payload.h +++ /dev/null @@ -1,138 +0,0 @@ -/** - * @file cp_payload.h - * - * @brief Interface of cp_payload_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef CP_PAYLOAD_H_ -#define CP_PAYLOAD_H_ - -#include -#include -#include -#include - -/** - * CP_PAYLOAD length in bytes without any proposal substructure. - * - * @ingroup payloads - */ -#define CP_PAYLOAD_HEADER_LENGTH 8 - - -typedef enum config_type_t config_type_t; - -/** - * Config Type of an Configuration Payload. - * - * @ingroup payloads - */ -enum config_type_t { - CFG_REQUEST = 1, - CFG_REPLY = 2, - CFG_SET = 3, - CFG_ACK = 4, -}; - -/** - * string mappings for config_type_t. - * - * @ingroup payloads - */ -extern mapping_t config_type_m[]; - - -typedef struct cp_payload_t cp_payload_t; - -/** - * @brief Class representing an IKEv2-CP Payload. - * - * The CP Payload format is described in RFC section 3.15. - * - * @b Constructors: - * - cp_payload_create() - * - * @ingroup payloads - */ -struct cp_payload_t { - /** - * The payload_t interface. - */ - payload_t payload_interface; - - /** - * @brief Creates an iterator of stored configuration_attribute_t objects. - * - * @warning The created iterator has to get destroyed by the caller! - * - * @warning When deleting an attribute using this iterator, - * the length of this configuration_attribute_t has to be refreshed - * by calling get_length()! - * - * @param this calling cp_payload_t object - * @param[in] forward iterator direction (TRUE: front to end) - * @return created iterator_t object - */ - iterator_t *(*create_configuration_attribute_iterator) (cp_payload_t *this, bool forward); - - /** - * @brief Adds a configuration_attribute_t object to this object. - * - * @warning The added configuration_attribute_t object is - * getting destroyed in destroy function of cp_payload_t. - * - * @param this calling cp_payload_t object - * @param attribute configuration_attribute_t object to add - */ - void (*add_configuration_attribute) (cp_payload_t *this, configuration_attribute_t *attribute); - - /** - * @brief Set the config type. - * - * @param this calling cp_payload_t object - * @param config_type config_type_t to set - */ - void (*set_config_type) (cp_payload_t *this,config_type_t config_type); - - /** - * @brief Get the config type. - * - * @param this calling cp_payload_t object - * @return config_type_t - */ - config_type_t (*get_config_type) (cp_payload_t *this); - - /** - * @brief Destroys an cp_payload_t object. - * - * @param this cp_payload_t object to destroy - */ - void (*destroy) (cp_payload_t *this); -}; - -/** - * @brief Creates an empty cp_payload_t object - * - * @return cp_payload_t object - * - * @ingroup payloads - */ -cp_payload_t *cp_payload_create(void); - -#endif /*CP_PAYLOAD_H_*/ diff --git a/src/charon/charon/encoding/payloads/delete_payload.c b/src/charon/charon/encoding/payloads/delete_payload.c deleted file mode 100644 index 28e78800f..000000000 --- a/src/charon/charon/encoding/payloads/delete_payload.c +++ /dev/null @@ -1,322 +0,0 @@ -/** - * @file delete_payload.c - * - * @brief Implementation of delete_payload_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 - -#include "delete_payload.h" - - -typedef struct private_delete_payload_t private_delete_payload_t; - -/** - * Private data of an delete_payload_t object. - * - */ -struct private_delete_payload_t { - /** - * Public delete_payload_t interface. - */ - delete_payload_t public; - - /** - * Next payload type. - */ - u_int8_t next_payload; - - /** - * Critical flag. - */ - bool critical; - - /** - * Length of this payload. - */ - u_int16_t payload_length; - - /** - * Protocol ID. - */ - u_int8_t protocol_id; - - /** - * SPI Size. - */ - u_int8_t spi_size; - - /** - * Number of SPI's. - */ - u_int16_t spi_count; - - /** - * The contained SPI's. - */ - chunk_t spis; -}; - -/** - * Encoding rules to parse or generate a DELETE payload - * - * The defined offsets are the positions in a object of type - * private_delete_payload_t. - * - */ -encoding_rule_t delete_payload_encodings[] = { - /* 1 Byte next payload type, stored in the field next_payload */ - { 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 }, - /* Length of the whole payload*/ - { PAYLOAD_LENGTH, offsetof(private_delete_payload_t, payload_length)}, - { U_INT_8, offsetof(private_delete_payload_t, protocol_id) }, - { U_INT_8, offsetof(private_delete_payload_t, spi_size) }, - { U_INT_16, offsetof(private_delete_payload_t, spi_count) }, - /* some delete data bytes, length is defined in PAYLOAD_LENGTH */ - { SPIS, offsetof(private_delete_payload_t, spis) } -}; - -/* - 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! Next Payload !C! RESERVED ! Payload Length ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! Protocol ID ! SPI Size ! # of SPIs ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! ! - ~ Security Parameter Index(es) (SPI) ~ - ! ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -*/ - -/** - * Implementation of payload_t.verify. - */ -static status_t verify(private_delete_payload_t *this) -{ - if ((this->protocol_id == 0) || - (this->protocol_id > 3)) - { - /* reserved IDs */ - return FAILED; - } - if (this->spis.len != (this->spi_count * this->spi_size)) - { - return FAILED; - } - if ((this->protocol_id == PROTO_IKE) && (this->spis.len != 0)) - { - /* IKE deletion has no spi assigned! */ - return FAILED; - } - - - return SUCCESS; -} - -/** - * Implementation of delete_payload_t.get_encoding_rules. - */ -static void get_encoding_rules(private_delete_payload_t *this, encoding_rule_t **rules, size_t *rule_count) -{ - *rules = delete_payload_encodings; - *rule_count = sizeof(delete_payload_encodings) / sizeof(encoding_rule_t); -} - -/** - * Implementation of payload_t.get_type. - */ -static payload_type_t get_payload_type(private_delete_payload_t *this) -{ - return DELETE; -} - -/** - * Implementation of payload_t.get_next_type. - */ -static payload_type_t get_next_type(private_delete_payload_t *this) -{ - return (this->next_payload); -} - -/** - * Implementation of payload_t.set_next_type. - */ -static void set_next_type(private_delete_payload_t *this,payload_type_t type) -{ - this->next_payload = type; -} - -/** - * Implementation of payload_t.get_length. - */ -static size_t get_length(private_delete_payload_t *this) -{ - return this->payload_length; -} - -/** - * Implementation of delete_payload_t.set_protocol_id. - */ -static void set_protocol_id (private_delete_payload_t *this, protocol_id_t protocol_id) -{ - this->protocol_id = protocol_id; -} - -/** - * Implementation of delete_payload_t.get_protocol_id. - */ -static protocol_id_t get_protocol_id (private_delete_payload_t *this) -{ - return (this->protocol_id); -} - -/** - * Implementation of delete_payload_t.set_spi_size. - */ -static void set_spi_size (private_delete_payload_t *this, u_int8_t spi_size) -{ - this->spi_size = spi_size; -} - -/** - * Implementation of delete_payload_t.get_spi_size. - */ -static u_int8_t get_spi_size (private_delete_payload_t *this) -{ - return (this->spi_size); -} - -/** - * Implementation of delete_payload_t.set_spi_count. - */ -static void set_spi_count (private_delete_payload_t *this, u_int16_t spi_count) -{ - this->spi_count = spi_count; -} - -/** - * Implementation of delete_payload_t.get_spi_count. - */ -static u_int16_t get_spi_count (private_delete_payload_t *this) -{ - return (this->spi_count); -} - - -/** - * Implementation of delete_payload_t.set_spis. - */ -static void set_spis (private_delete_payload_t *this, chunk_t spis) -{ - if (this->spis.ptr != NULL) - { - chunk_free(&(this->spis)); - } - this->spis.ptr = clalloc(spis.ptr,spis.len); - this->spis.len = spis.len; - this->payload_length = DELETE_PAYLOAD_HEADER_LENGTH + this->spis.len; -} - -/** - * Implementation of delete_payload_t.get_spis. - */ -static chunk_t get_spis (private_delete_payload_t *this) -{ - return (this->spis); -} - -/** - * Implementation of delete_payload_t.get_spis_clone. - */ -static chunk_t get_spis_clone (private_delete_payload_t *this) -{ - chunk_t cloned_spis; - if (this->spis.ptr == NULL) - { - return (this->spis); - } - cloned_spis.ptr = clalloc(this->spis.ptr,this->spis.len); - cloned_spis.len = this->spis.len; - return cloned_spis; -} - -/** - * Implementation of payload_t.destroy and delete_payload_t.destroy. - */ -static void destroy(private_delete_payload_t *this) -{ - if (this->spis.ptr != NULL) - { - chunk_free(&(this->spis)); - } - - free(this); -} - -/* - * Described in header - */ -delete_payload_t *delete_payload_create() -{ - private_delete_payload_t *this = malloc_thing(private_delete_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 (*) (delete_payload_t *)) destroy; - this->public.set_protocol_id = (void (*) (delete_payload_t *,protocol_id_t)) set_protocol_id; - this->public.get_protocol_id = (protocol_id_t (*) (delete_payload_t *)) get_protocol_id; - this->public.set_spi_size = (void (*) (delete_payload_t *,u_int8_t)) set_spi_size; - this->public.get_spi_size = (u_int8_t (*) (delete_payload_t *)) get_spi_size; - this->public.set_spi_count = (void (*) (delete_payload_t *,u_int16_t)) set_spi_count; - this->public.get_spi_count = (u_int16_t (*) (delete_payload_t *)) get_spi_count; - this->public.set_spis = (void (*) (delete_payload_t *,chunk_t)) set_spis; - this->public.get_spis_clone = (chunk_t (*) (delete_payload_t *)) get_spis_clone; - this->public.get_spis = (chunk_t (*) (delete_payload_t *)) get_spis; - - /* private variables */ - this->critical = FALSE; - this->next_payload = NO_PAYLOAD; - this->payload_length =DELETE_PAYLOAD_HEADER_LENGTH; - this->protocol_id = PROTO_NONE; - this->spi_size = 0; - this->spi_count = 0; - this->spis = CHUNK_INITIALIZER; - - return (&(this->public)); -} diff --git a/src/charon/charon/encoding/payloads/delete_payload.h b/src/charon/charon/encoding/payloads/delete_payload.h deleted file mode 100644 index a25d0f116..000000000 --- a/src/charon/charon/encoding/payloads/delete_payload.h +++ /dev/null @@ -1,156 +0,0 @@ -/** - * @file delete_payload.h - * - * @brief Interface of delete_payload_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef DELETE_PAYLOAD_H_ -#define DELETE_PAYLOAD_H_ - -#include -#include -#include - -/** - * Length of a delete payload without the SPI in bytes. - * - * @ingroup payloads - */ -#define DELETE_PAYLOAD_HEADER_LENGTH 8 - - - -typedef struct delete_payload_t delete_payload_t; - -/** - * @brief Class representing an IKEv2 DELETE payload. - * - * The DELETE payload format is described in RFC section 3.11. - * - * @b Constructors: - * - delete_payload_create() - * - * @todo Implement better setter/getters - * - * @ingroup payloads - */ -struct delete_payload_t { - /** - * The payload_t interface. - */ - payload_t payload_interface; - - /** - * @brief Set the protocol ID. - * - * @param this calling delete_payload_t object - * @param protocol_id protocol ID - */ - void (*set_protocol_id) (delete_payload_t *this, protocol_id_t protocol_id); - - /** - * @brief Get the protocol ID. - * - * @param this calling delete_payload_t object - * @return protocol ID - */ - protocol_id_t (*get_protocol_id) (delete_payload_t *this); - - /** - * @brief Set the SPI size. - * - * - * @param this calling delete_payload_t object - * @param spi_size SPI size - */ - void (*set_spi_size) (delete_payload_t *this, u_int8_t spi_size); - - /** - * @brief Get the SPI size. - * - * @param this calling delete_payload_t object - * @return SPI size - */ - u_int8_t (*get_spi_size) (delete_payload_t *this); - - /** - * @brief Set the SPI count. - * - * @param this calling delete_payload_t object - * @param spi_count SPI count - */ - void (*set_spi_count) (delete_payload_t *this, u_int16_t spi_count); - - /** - * @brief Get the SPI count. - * - * @param this calling delete_payload_t object - * @return Number of SPI's - */ - u_int16_t (*get_spi_count) (delete_payload_t *this); - - /** - * @brief Set the SPI's. - * - * Data are getting cloned. - * - * @param this calling delete_payload_t object - * @param data SPI's as chunk_t - */ - void (*set_spis) (delete_payload_t *this, chunk_t spis); - - /** - * @brief Get the SPI's. - * - * Returned data are a copy of the internal one. - * - * @param this calling delete_payload_t object - * @return SPI's chunk_t - */ - chunk_t (*get_spis_clone) (delete_payload_t *this); - - /** - * @brief Get the SPI's. - * - * Returned data are NOT copied. - * - * @param this calling delete_payload_t object - * @return SPI's as chunk_t - */ - chunk_t (*get_spis) (delete_payload_t *this); - - /** - * @brief Destroys an delete_payload_t object. - * - * @param this delete_payload_t object to destroy - */ - void (*destroy) (delete_payload_t *this); -}; - -/** - * @brief Creates an empty delete_payload_t object. - * - * @return delete_payload_t object - * - * @ingroup payloads - */ -delete_payload_t *delete_payload_create(void); - - -#endif /* DELETE_PAYLOAD_H_ */ diff --git a/src/charon/charon/encoding/payloads/eap_payload.c b/src/charon/charon/encoding/payloads/eap_payload.c deleted file mode 100644 index 2a0e17679..000000000 --- a/src/charon/charon/encoding/payloads/eap_payload.c +++ /dev/null @@ -1,227 +0,0 @@ -/** - * @file eap_payload.c - * - * @brief Implementation of eap_payload_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 - -#include "eap_payload.h" - - -typedef struct private_eap_payload_t private_eap_payload_t; - -/** - * Private data of an eap_payload_t object. - * - */ -struct private_eap_payload_t { - /** - * Public eap_payload_t interface. - */ - eap_payload_t public; - - /** - * Next payload type. - */ - u_int8_t next_payload; - - /** - * Critical flag. - */ - bool critical; - - /** - * Length of this payload. - */ - u_int16_t payload_length; - - /** - * The contained message. - */ - chunk_t message; -}; - -/** - * Encoding rules to parse or generate a EAP payload. - * - * The defined offsets are the positions in a object of type - * private_eap_payload_t. - * - */ -encoding_rule_t eap_payload_encodings[] = { - /* 1 Byte next payload type, stored in the field next_payload */ - { U_INT_8, offsetof(private_eap_payload_t, next_payload) }, - /* the critical bit */ - { 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 }, - /* Length of the whole payload*/ - { PAYLOAD_LENGTH, offsetof(private_eap_payload_t, payload_length)}, - /* some eap data bytes, length is defined in PAYLOAD_LENGTH */ - { EAP_MESSAGE, offsetof(private_eap_payload_t, message) } -}; - -/* - 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! Next Payload !C! RESERVED ! Payload Length ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! ! - ~ EAP Message ~ - ! ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -*/ - -/** - * Implementation of payload_t.verify. - */ -static status_t verify(private_eap_payload_t *this) -{ - return SUCCESS; -} - -/** - * Implementation of eap_payload_t.get_encoding_rules. - */ -static void get_encoding_rules(private_eap_payload_t *this, encoding_rule_t **rules, size_t *rule_count) -{ - *rules = eap_payload_encodings; - *rule_count = sizeof(eap_payload_encodings) / sizeof(encoding_rule_t); -} - -/** - * Implementation of payload_t.get_type. - */ -static payload_type_t get_payload_type(private_eap_payload_t *this) -{ - return EXTENSIBLE_AUTHENTICATION; -} - -/** - * Implementation of payload_t.get_next_type. - */ -static payload_type_t get_next_type(private_eap_payload_t *this) -{ - return (this->next_payload); -} - -/** - * Implementation of payload_t.set_next_type. - */ -static void set_next_type(private_eap_payload_t *this,payload_type_t type) -{ - this->next_payload = type; -} - -/** - * Implementation of payload_t.get_length. - */ -static size_t get_length(private_eap_payload_t *this) -{ - return this->payload_length; -} - -/** - * Implementation of eap_payload_t.set_message. - */ -static void set_message (private_eap_payload_t *this, chunk_t message) -{ - if (this->message.ptr != NULL) - { - chunk_free(&(this->message)); - } - this->message.ptr = clalloc(message.ptr,message.len); - this->message.len = message.len; - this->payload_length = EAP_PAYLOAD_HEADER_LENGTH + this->message.len; -} - -/** - * Implementation of eap_payload_t.get_message. - */ -static chunk_t get_message (private_eap_payload_t *this) -{ - return (this->message); -} - -/** - * Implementation of eap_payload_t.get_data_clone. - */ -static chunk_t get_message_clone (private_eap_payload_t *this) -{ - chunk_t cloned_message; - if (this->message.ptr == NULL) - { - return (this->message); - } - cloned_message.ptr = clalloc(this->message.ptr,this->message.len); - cloned_message.len = this->message.len; - return cloned_message; -} - -/** - * Implementation of payload_t.destroy and eap_payload_t.destroy. - */ -static void destroy(private_eap_payload_t *this) -{ - if (this->message.ptr != NULL) - { - chunk_free(&(this->message)); - } - - free(this); -} - -/* - * Described in header - */ -eap_payload_t *eap_payload_create() -{ - private_eap_payload_t *this = malloc_thing(private_eap_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 (*) (eap_payload_t *)) destroy; - this->public.set_message = (void (*) (eap_payload_t *,chunk_t)) set_message; - this->public.get_message_clone = (chunk_t (*) (eap_payload_t *)) get_message_clone; - this->public.get_message = (chunk_t (*) (eap_payload_t *)) get_message; - - /* private variables */ - this->critical = FALSE; - this->next_payload = NO_PAYLOAD; - this->payload_length = EAP_PAYLOAD_HEADER_LENGTH; - this->message = CHUNK_INITIALIZER; - - return (&(this->public)); -} diff --git a/src/charon/charon/encoding/payloads/eap_payload.h b/src/charon/charon/encoding/payloads/eap_payload.h deleted file mode 100644 index 044d89cf8..000000000 --- a/src/charon/charon/encoding/payloads/eap_payload.h +++ /dev/null @@ -1,105 +0,0 @@ -/** - * @file eap_payload.h - * - * @brief Interface of eap_payload_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef EAP_PAYLOAD_H_ -#define EAP_PAYLOAD_H_ - -#include -#include - -/** - * Length of a EAP payload without the EAP Message in bytes. - * - * @ingroup payloads - */ -#define EAP_PAYLOAD_HEADER_LENGTH 4 - - -typedef struct eap_payload_t eap_payload_t; - -/** - * @brief Class representing an IKEv2 EAP payload. - * - * The EAP payload format is described in RFC section 3.16. - * - * @b Constructors: - * - eap_payload_create() - * - * @todo Implement functionality for this payload - * - * @ingroup payloads - */ -struct eap_payload_t { - /** - * The payload_t interface. - */ - payload_t payload_interface; - - /** - * @brief Set the EAP Message. - * - * Data are getting cloned. - * - * @param this calling eap_payload_t object - * @param message EAP message as chunk_t - */ - void (*set_message) (eap_payload_t *this, chunk_t message); - - /** - * @brief Get the EAP message. - * - * Returned data are a copy of the internal one. - * - * @param this calling eap_payload_t object - * @return EAP message as chunk_t - */ - chunk_t (*get_message_clone) (eap_payload_t *this); - - /** - * @brief Get the EAP message. - * - * Returned data are NOT copied. - * - * @param this calling eap_payload_t object - * @return EAP message as chunk_t - */ - chunk_t (*get_message) (eap_payload_t *this); - - /** - * @brief Destroys an eap_payload_t object. - * - * @param this eap_payload_t object to destroy - */ - void (*destroy) (eap_payload_t *this); -}; - -/** - * @brief Creates an empty eap_payload_t object. - * - * @return eap_payload_t object - * - * @ingroup payloads - */ -eap_payload_t *eap_payload_create(void); - - -#endif /* EAP_PAYLOAD_H_ */ diff --git a/src/charon/charon/encoding/payloads/encodings.c b/src/charon/charon/encoding/payloads/encodings.c deleted file mode 100644 index da39467a9..000000000 --- a/src/charon/charon/encoding/payloads/encodings.c +++ /dev/null @@ -1,68 +0,0 @@ -/** - * @file encodings.c - * - * @brief String mappings of encoding_type_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 "encodings.h" - - -mapping_t encoding_type_m[] = { - {U_INT_4, "U_INT_4"}, - {U_INT_8, "U_INT_8"}, - {U_INT_16, "U_INT_16"}, - {U_INT_32, "U_INT_32"}, - {U_INT_64, "U_INT_64"}, - {IKE_SPI, "IKE_SPI"}, - {RESERVED_BIT, "RESERVED_BIT"}, - {RESERVED_BYTE, "RESERVED_BYTE"}, - {FLAG, "FLAG"}, - {PAYLOAD_LENGTH, "PAYLOAD_LENGTH"}, - {HEADER_LENGTH, "HEADER_LENGTH"}, - {SPI_SIZE, "SPI_SIZE"}, - {SPI, "SPI"}, - {KEY_EXCHANGE_DATA, "KEY_EXCHANGE_DATA"}, - {NOTIFICATION_DATA, "NOTIFICATION_DATA"}, - {PROPOSALS, "PROPOSALS"}, - {TRANSFORMS, "TRANSFORMS"}, - {TRANSFORM_ATTRIBUTES, "TRANSFORM_ATTRIBUTES"}, - {ATTRIBUTE_FORMAT, "ATTRIBUTE_FORMAT"}, - {ATTRIBUTE_TYPE, "ATTRIBUTE_TYPE"}, - {ATTRIBUTE_LENGTH_OR_VALUE, "ATTRIBUTE_LENGTH_OR_VALUE"}, - {ATTRIBUTE_VALUE, "ATTRIBUTE_VALUE"}, - {NONCE_DATA, "NONCE_DATA"}, - {ID_DATA, "ID_DATA"}, - {AUTH_DATA, "AUTH_DATA"}, - {ENCRYPTED_DATA, "ENCRYPTED_DATA"}, - {TS_TYPE, "TS_TYPE"}, - {ADDRESS, "ADDRESS"}, - {TRAFFIC_SELECTORS, "TRAFFIC_SELECTORS"}, - {CERT_DATA, "CERT_DATA"}, - {CERTREQ_DATA, "CERTREQ_DATA"}, - {SPIS, "SPIS"}, - {VID_DATA, "VID_DATA"}, - {VID_DATA, "VID_DATA"}, - {CONFIGURATION_ATTRIBUTES, "CONFIGURATION_ATTRIBUTES"}, - {CONFIGURATION_ATTRIBUTE_LENGTH, "CONFIGURATION_ATTRIBUTE_LENGTH"}, - {CONFIGURATION_ATTRIBUTE_VALUE, "CONFIGURATION_ATTRIBUTE_VALUE"}, - {EAP_MESSAGE, "EAP_MESSAGE"}, - {UNKNOWN_DATA,"UNKNOWN_DATA"}, - {MAPPING_END, NULL} -}; diff --git a/src/charon/charon/encoding/payloads/encodings.h b/src/charon/charon/encoding/payloads/encodings.h deleted file mode 100644 index e30e1c215..000000000 --- a/src/charon/charon/encoding/payloads/encodings.h +++ /dev/null @@ -1,540 +0,0 @@ -/** - * @file encodings.h - * - * @brief Definition of encoding_type_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef ENCODINGS_H_ -#define ENCODINGS_H_ - -#include -#include - - -typedef enum encoding_type_t encoding_type_t; - -/** - * @brief All different kinds of encoding types. - * - * Each field of an IKEv2-Message (in header or payload) - * which has to be parsed or generated differently has its own - * type defined here. - * - * Header is parsed like a payload and gets its one payload_id - * from PRIVATE USE space. Also the substructures - * of specific payload types get their own payload_id - * from PRIVATE_USE space. See IKEv2-Draft for more informations. - * - * @ingroup payloads - */ -enum encoding_type_t { - - /** - * Representing a 4 Bit unsigned int value. - * - * - * When generating it must be changed from host to network order. - * The value is read from the associated data struct. - * The current write position is moved 4 bit forward afterwards. - * - * When parsing it must be changed from network to host order. - * The value is written to the associated data struct. - * The current read pointer is moved 4 bit forward afterwards. - */ - U_INT_4, - - /** - * Representing a 8 Bit unsigned int value. - * - * - * When generating it must be changed from host to network order. - * The value is read from the associated data struct. - * The current write position is moved 8 bit forward afterwards. - * - * When parsing it must be changed from network to host order. - * The value is written to the associated data struct. - * The current read pointer is moved 8 bit forward afterwards. - */ - U_INT_8, - - /** - * Representing a 16 Bit unsigned int value. - * - * - * When generating it must be changed from host to network order. - * The value is read from the associated data struct. - * The current write position is moved 16 bit forward afterwards. - * - * When parsing it must be changed from network to host order. - * The value is written to the associated data struct. - * The current read pointer is moved 16 bit forward afterwards. - */ - U_INT_16, - - /** - * Representing a 32 Bit unsigned int value. - * - * When generating it must be changed from host to network order. - * The value is read from the associated data struct. - * The current write position is moved 32 bit forward afterwards. - * - * When parsing it must be changed from network to host order. - * The value is written to the associated data struct. - * The current read pointer is moved 32 bit forward afterwards. - */ - U_INT_32, - - /** - * Representing a 64 Bit unsigned int value. - * - * When generating it must be changed from host to network order. - * The value is read from the associated data struct. - * The current write position is moved 64 bit forward afterwards. - * - * When parsing it must be changed from network to host order. - * The value is written to the associated data struct. - * The current read pointer is moved 64 bit forward afterwards. - */ - U_INT_64, - - /** - * @brief represents a RESERVED_BIT used in FLAG-Bytes. - * - * When generating, the next bit is set to zero and the current write - * position is moved one bit forward. - * No value is read from the associated data struct. - * The current write position is moved 1 bit forward afterwards. - * - * When parsing, the current read pointer is moved one bit forward. - * No value is written to the associated data struct. - * The current read pointer is moved 1 bit forward afterwards. - */ - RESERVED_BIT, - - /** - * @brief represents a RESERVED_BYTE. - * - * When generating, the next byte is set to zero and the current write - * position is moved one byte forward. - * No value is read from the associated data struct. - * The current write position is moved 1 byte forward afterwards. - * - * When parsing, the current read pointer is moved one byte forward. - * No value is written to the associated data struct. - * The current read pointer is moved 1 byte forward afterwards. - */ - RESERVED_BYTE, - - /** - * Representing a 1 Bit flag. - * - * When generation, the next bit is set to 1 if the associated value - * in the data struct is TRUE, 0 otherwise. The current write position - * is moved 1 bit forward afterwards. - * - * When parsing, the next bit is read and stored in the associated data - * struct. 0 means FALSE, 1 means TRUE, The current read pointer - * is moved 1 bit forward afterwards - */ - FLAG, - - /** - * Representating a length field of a payload. - * - * When generating it must be changed from host to network order. - * The value is read from the associated data struct. - * The current write position is moved 16 bit forward afterwards. - * - * When parsing it must be changed from network to host order. - * The value is written to the associated data struct. - * The current read pointer is moved 16 bit forward afterwards. - */ - PAYLOAD_LENGTH, - - /** - * Representating a length field of a header. - * - * When generating it must be changed from host to network order. - * The value is read from the associated data struct. - * The current write position is moved 32 bit forward afterwards. - * - * When parsing it must be changed from network to host order. - * The value is written to the associated data struct. - * The current read pointer is moved 32 bit forward afterwards. - */ - HEADER_LENGTH, - - /** - * Representating a spi size field. - * - * When generating it must be changed from host to network order. - * The value is read from the associated data struct. - * The current write position is moved 8 bit forward afterwards. - * - * When parsing it must be changed from network to host order. - * The value is written to the associated data struct. - * The current read pointer is moved 8 bit forward afterwards. - */ - SPI_SIZE, - - /** - * Representating a spi field. - * - * When generating the content of the chunkt pointing to - * is written. - * - * When parsing SPI_SIZE bytes are read and written into the chunk pointing to. - */ - SPI, - - /** - * Representating a Key Exchange Data field. - * - * When generating the content of the chunkt pointing to - * is written. - * - * When parsing (Payload Length - 8) bytes are read and written into the chunk pointing to. - */ - KEY_EXCHANGE_DATA, - - /** - * Representating a Notification field. - * - * When generating the content of the chunkt pointing to - * is written. - * - * When parsing (Payload Length - spi size - 8) bytes are read and written into the chunk pointing to. - */ - NOTIFICATION_DATA, - - /** - * Representating one or more proposal substructures. - * - * The offset points to a linked_list_t pointer. - * - * When generating the proposal_substructure_t objects are stored - * in the pointed linked_list. - * - * When parsing the parsed proposal_substructure_t objects have - * to be stored in the pointed linked_list. - */ - PROPOSALS, - - /** - * Representating one or more transform substructures. - * - * The offset points to a linked_list_t pointer. - * - * When generating the transform_substructure_t objects are stored - * in the pointed linked_list. - * - * When parsing the parsed transform_substructure_t objects have - * to be stored in the pointed linked_list. - */ - TRANSFORMS, - - /** - * Representating one or more Attributes of a transform substructure. - * - * The offset points to a linked_list_t pointer. - * - * When generating the transform_attribute_t objects are stored - * in the pointed linked_list. - * - * When parsing the parsed transform_attribute_t objects have - * to be stored in the pointed linked_list. - */ - TRANSFORM_ATTRIBUTES, - - /** - * Representating one or more Attributes of a configuration payload. - * - * The offset points to a linked_list_t pointer. - * - * When generating the configuration_attribute_t objects are stored - * in the pointed linked_list. - * - * When parsing the parsed configuration_attribute_t objects have - * to be stored in the pointed linked_list. - */ - CONFIGURATION_ATTRIBUTES, - - /** - * - * When generating the content of the chunkt pointing to - * is written. - * - * When parsing (Payload Length - 4) bytes are read and written into the chunk pointing to. - */ - CONFIGURATION_ATTRIBUTE_VALUE, - - /** - * Representing a 1 Bit flag specifying the format of a transform attribute. - * - * When generation, the next bit is set to 1 if the associated value - * in the data struct is TRUE, 0 otherwise. The current write position - * is moved 1 bit forward afterwards. - * - * When parsing, the next bit is read and stored in the associated data - * struct. 0 means FALSE, 1 means TRUE, The current read pointer - * is moved 1 bit forward afterwards. - */ - ATTRIBUTE_FORMAT, - /** - * Representing a 15 Bit unsigned int value used as attribute type - * in an attribute transform. - * - * - * When generating it must be changed from host to network order. - * The value is read from the associated data struct. - * The current write position is moved 15 bit forward afterwards. - * - * When parsing it must be changed from network to host order. - * The value is written to the associated data struct. - * The current read pointer is moved 15 bit forward afterwards. - */ - ATTRIBUTE_TYPE, - - /** - * Depending on the field of type ATTRIBUTE_FORMAT - * this field contains the length or the value of an transform attribute. - * Its stored in a 16 unsigned integer field. - * - * When generating it must be changed from host to network order. - * The value is read from the associated data struct. - * The current write position is moved 16 bit forward afterwards. - * - * When parsing it must be changed from network to host order. - * The value is written to the associated data struct. - * The current read pointer is moved 16 bit forward afterwards. - */ - ATTRIBUTE_LENGTH_OR_VALUE, - - /** - * This field contains the length or the value of an configuration attribute. - * Its stored in a 16 unsigned integer field. - * - * When generating it must be changed from host to network order. - * The value is read from the associated data struct. - * The current write position is moved 16 bit forward afterwards. - * - * When parsing it must be changed from network to host order. - * The value is written to the associated data struct. - * The current read pointer is moved 16 bit forward afterwards. - */ - CONFIGURATION_ATTRIBUTE_LENGTH, - - /** - * Depending on the field of type ATTRIBUTE_FORMAT - * this field is available or missing and so parsed/generated - * or not parsed/not generated. - * - * When generating the content of the chunkt pointing to - * is written. - * - * When parsing SPI_SIZE bytes are read and written into the chunk pointing to. - */ - ATTRIBUTE_VALUE, - - /** - * Representating one or more Traffic selectors of a TS payload. - * - * The offset points to a linked_list_t pointer. - * - * When generating the traffic_selector_substructure_t objects are stored - * in the pointed linked_list. - * - * When parsing the parsed traffic_selector_substructure_t objects have - * to be stored in the pointed linked_list. - */ - TRAFFIC_SELECTORS, - - /** - * Representating a Traffic selector type field. - * - * When generating it must be changed from host to network order. - * The value is read from the associated data struct. - * The current write position is moved 16 bit forward afterwards. - * - * When parsing it must be changed from network to host order. - * The value is written to the associated data struct. - * The current read pointer is moved 16 bit forward afterwards. - */ - TS_TYPE, - - /** - * Representating an address field in a traffic selector. - * - * Depending on the last field of type TS_TYPE - * this field is either 4 or 16 byte long. - * - * When generating the content of the chunkt pointing to - * is written. - * - * When parsing 4 or 16 bytes are read and written into the chunk pointing to. - */ - ADDRESS, - - /** - * Representating a Nonce Data field. - * - * When generating the content of the chunkt pointing to - * is written. - * - * When parsing (Payload Length - 4) bytes are read and written into the chunk pointing to. - */ - NONCE_DATA, - - /** - * Representating a ID Data field. - * - * When generating the content of the chunkt pointing to - * is written. - * - * When parsing (Payload Length - 8) bytes are read and written into the chunk pointing to. - */ - ID_DATA, - - /** - * Representating a AUTH Data field. - * - * When generating the content of the chunkt pointing to - * is written. - * - * When parsing (Payload Length - 8) bytes are read and written into the chunk pointing to. - */ - AUTH_DATA, - - /** - * Representating a CERT Data field. - * - * When generating the content of the chunkt pointing to - * is written. - * - * When parsing (Payload Length - 5) bytes are read and written into the chunk pointing to. - */ - CERT_DATA, - - /** - * Representating a CERTREQ Data field. - * - * When generating the content of the chunkt pointing to - * is written. - * - * When parsing (Payload Length - 5) bytes are read and written into the chunk pointing to. - */ - CERTREQ_DATA, - - /** - * Representating an EAP message field. - * - * When generating the content of the chunkt pointing to - * is written. - * - * When parsing (Payload Length - 4) bytes are read and written into the chunk pointing to. - */ - EAP_MESSAGE, - - /** - * Representating the SPIS field in a DELETE payload. - * - * When generating the content of the chunkt pointing to - * is written. - * - * When parsing (Payload Length - 8) bytes are read and written into the chunk pointing to. - */ - SPIS, - - /** - * Representating the VID DATA field in a VENDOR ID payload. - * - * When generating the content of the chunkt pointing to - * is written. - * - * When parsing (Payload Length - 4) bytes are read and written into the chunk pointing to. - */ - VID_DATA, - - /** - * Representating the DATA of an unknown payload. - * - * When generating the content of the chunkt pointing to - * is written. - * - * When parsing (Payload Length - 4) bytes are read and written into the chunk pointing to. - */ - UNKNOWN_DATA, - - /** - * Representating an IKE_SPI field in an IKEv2 Header. - * - * When generating the value of the u_int64_t pointing to - * is written (host and networ order is not changed). - * - * When parsing 8 bytes are read and written into the u_int64_t pointing to. - */ - IKE_SPI, - - /** - * Representing the encrypted data body of a encryption payload. - */ - ENCRYPTED_DATA, -}; - -/** - * mappings to map encoding_type_t's to strings - * - * @ingroup payloads - */ -extern mapping_t encoding_type_m[]; - - -typedef struct encoding_rule_t encoding_rule_t; - -/** - * An encoding rule is a mapping of a specific encoding type to - * a location in the data struct where the current field is stored to - * or read from. - * - * For examples see files in this directory. - * - * This rules are used by parser and generator. - * - * @ingroup payloads - */ -struct encoding_rule_t { - - /** - * Encoding type. - */ - encoding_type_t type; - - /** - * Offset in the data struct. - * - * When parsing, data are written to this offset of the - * data struct. - * - * When generating, data are read from this offset in the - * data struct. - */ - u_int32_t offset; -}; - -#endif /*ENCODINGS_H_*/ diff --git a/src/charon/charon/encoding/payloads/encryption_payload.c b/src/charon/charon/encoding/payloads/encryption_payload.c deleted file mode 100644 index e0ca74ff4..000000000 --- a/src/charon/charon/encoding/payloads/encryption_payload.c +++ /dev/null @@ -1,702 +0,0 @@ -/** - * @file encryption_payload.c - * - * @brief Implementation of encryption_payload_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 -#include - -#include "encryption_payload.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - - - -typedef struct private_encryption_payload_t private_encryption_payload_t; - -/** - * Private data of an encryption_payload_t' Object. - * - */ -struct private_encryption_payload_t { - - /** - * Public encryption_payload_t interface. - */ - encryption_payload_t public; - - /** - * There is no next payload for an encryption payload, - * since encryption payload MUST be the last one. - * next_payload means here the first payload of the - * contained, encrypted payload. - */ - u_int8_t next_payload; - - /** - * Critical flag. - */ - bool critical; - - /** - * Length of this payload - */ - u_int16_t payload_length; - - /** - * Chunk containing the iv, data, padding, - * and (an eventually not calculated) signature. - */ - chunk_t encrypted; - - /** - * Chunk containing the data in decrypted (unpadded) form. - */ - chunk_t decrypted; - - /** - * Signer set by set_signer. - */ - signer_t *signer; - - /** - * Crypter, supplied by encrypt/decrypt - */ - crypter_t *crypter; - - /** - * Contained payloads of this encrpytion_payload. - */ - linked_list_t *payloads; - - /** - * logger for this payload, uses MESSAGE context - */ - logger_t *logger; - - /** - * @brief Computes the length of this payload. - * - * @param this calling private_encryption_payload_t object - */ - void (*compute_length) (private_encryption_payload_t *this); - - /** - * @brief Generate payloads (unencrypted) in chunk decrypted. - * - * @param this calling private_encryption_payload_t object - */ - void (*generate) (private_encryption_payload_t *this); - - /** - * @brief Parse payloads from a (unencrypted) chunk. - * - * @param this calling private_encryption_payload_t object - */ - status_t (*parse) (private_encryption_payload_t *this); -}; - -/** - * Encoding rules to parse or generate a IKEv2-Encryption Payload. - * - * The defined offsets are the positions in a object of type - * private_encryption_payload_t. - * - */ -encoding_rule_t encryption_payload_encodings[] = { - /* 1 Byte next payload type, stored in the field next_payload */ - { U_INT_8, offsetof(private_encryption_payload_t, next_payload) }, - /* the critical bit */ - { FLAG, offsetof(private_encryption_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 }, - /* Length of the whole encryption payload*/ - { PAYLOAD_LENGTH, offsetof(private_encryption_payload_t, payload_length) }, - /* encrypted data, stored in a chunk. contains iv, data, padding */ - { ENCRYPTED_DATA, offsetof(private_encryption_payload_t, encrypted) }, -}; - -/* - 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! Next Payload !C! RESERVED ! Payload Length ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! Initialization Vector ! - ! (length is block size for encryption algorithm) ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! Encrypted IKE Payloads ! - + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! ! Padding (0-255 octets) ! - +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ - ! ! Pad Length ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ~ Integrity Checksum Data ~ - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -*/ - -/** - * Implementation of payload_t.verify. - */ -static status_t verify(private_encryption_payload_t *this) -{ - return SUCCESS; -} - -/** - * Implementation of payload_t.get_encoding_rules. - */ -static void get_encoding_rules(private_encryption_payload_t *this, encoding_rule_t **rules, size_t *rule_count) -{ - *rules = encryption_payload_encodings; - *rule_count = sizeof(encryption_payload_encodings) / sizeof(encoding_rule_t); -} - -/** - * Implementation of payload_t.get_type. - */ -static payload_type_t get_type(private_encryption_payload_t *this) -{ - return ENCRYPTED; -} - -/** - * Implementation of payload_t.get_next_type. - */ -static payload_type_t get_next_type(private_encryption_payload_t *this) -{ - /* returns first contained payload here */ - return (this->next_payload); -} - -/** - * Implementation of payload_t.set_next_type. - */ -static void set_next_type(private_encryption_payload_t *this, payload_type_t type) -{ - /* set next type is not allowed, since this payload MUST be the last one - * and so nothing is done in here*/ -} - -/** - * Implementation of payload_t.get_length. - */ -static size_t get_length(private_encryption_payload_t *this) -{ - this->compute_length(this); - return this->payload_length; -} - -/** - * Implementation of payload_t.create_payload_iterator. - */ -static iterator_t *create_payload_iterator (private_encryption_payload_t *this, bool forward) -{ - return (this->payloads->create_iterator(this->payloads, forward)); -} - -/** - * Implementation of payload_t.add_payload. - */ -static void add_payload(private_encryption_payload_t *this, payload_t *payload) -{ - payload_t *last_payload; - if (this->payloads->get_count(this->payloads) > 0) - { - this->payloads->get_last(this->payloads,(void **) &last_payload); - last_payload->set_next_type(last_payload, payload->get_type(payload)); - } - else - { - this->next_payload = payload->get_type(payload); - } - payload->set_next_type(payload, NO_PAYLOAD); - this->payloads->insert_last(this->payloads, (void*)payload); - this->compute_length(this); -} - -/** - * Implementation of encryption_payload_t.remove_first_payload. - */ -static status_t remove_first_payload(private_encryption_payload_t *this, payload_t **payload) -{ - return this->payloads->remove_first(this->payloads, (void**)payload); -} - -/** - * Implementation of encryption_payload_t.get_payload_count. - */ -static size_t get_payload_count(private_encryption_payload_t *this) -{ - return this->payloads->get_count(this->payloads); -} - - -/** - * Implementation of encryption_payload_t.encrypt. - */ -static status_t encrypt(private_encryption_payload_t *this) -{ - chunk_t iv, padding, to_crypt, result; - randomizer_t *randomizer; - status_t status; - size_t block_size; - - if (this->signer == NULL || this->crypter == NULL) - { - this->logger->log(this->logger, ERROR, "could not encrypt, signer/crypter not set"); - return INVALID_STATE; - } - - /* for random data in iv and padding */ - randomizer = randomizer_create(); - - - /* build payload chunk */ - this->generate(this); - - this->logger->log(this->logger, CONTROL|LEVEL2, "encrypting payloads"); - this->logger->log_chunk(this->logger, RAW|LEVEL2, "data to encrypt", this->decrypted); - - /* build padding */ - block_size = this->crypter->get_block_size(this->crypter); - padding.len = block_size - ((this->decrypted.len + 1) % block_size); - status = randomizer->allocate_pseudo_random_bytes(randomizer, padding.len, &padding); - if (status != SUCCESS) - { - randomizer->destroy(randomizer); - return status; - } - - /* concatenate payload data, padding, padding len */ - to_crypt.len = this->decrypted.len + padding.len + 1; - to_crypt.ptr = malloc(to_crypt.len); - - memcpy(to_crypt.ptr, this->decrypted.ptr, this->decrypted.len); - memcpy(to_crypt.ptr + this->decrypted.len, padding.ptr, padding.len); - *(to_crypt.ptr + to_crypt.len - 1) = padding.len; - - /* build iv */ - iv.len = block_size; - status = randomizer->allocate_pseudo_random_bytes(randomizer, iv.len, &iv); - randomizer->destroy(randomizer); - if (status != SUCCESS) - { - chunk_free(&to_crypt); - chunk_free(&padding); - return status; - } - - this->logger->log_chunk(this->logger, RAW|LEVEL2, "data before encryption with padding", to_crypt); - - /* encrypt to_crypt chunk */ - free(this->encrypted.ptr); - status = this->crypter->encrypt(this->crypter, to_crypt, iv, &result); - free(padding.ptr); - free(to_crypt.ptr); - if (status != SUCCESS) - { - this->logger->log(this->logger, ERROR|LEVEL1, "encryption failed"); - free(iv.ptr); - return status; - } - this->logger->log_chunk(this->logger, RAW|LEVEL2, "data after encryption", result); - - - /* build encrypted result with iv and signature */ - this->encrypted.len = iv.len + result.len + this->signer->get_block_size(this->signer); - free(this->encrypted.ptr); - this->encrypted.ptr = malloc(this->encrypted.len); - - /* fill in result, signature is left out */ - memcpy(this->encrypted.ptr, iv.ptr, iv.len); - memcpy(this->encrypted.ptr + iv.len, result.ptr, result.len); - - free(result.ptr); - free(iv.ptr); - this->logger->log_chunk(this->logger, RAW|LEVEL2, "data after encryption with IV and (invalid) signature", this->encrypted); - - return SUCCESS; -} - -/** - * Implementation of encryption_payload_t.encrypt. - */ -static status_t decrypt(private_encryption_payload_t *this) -{ - chunk_t iv, concatenated; - u_int8_t padding_length; - status_t status; - - - this->logger->log(this->logger, CONTROL|LEVEL2, "decrypting encryption payload"); - this->logger->log_chunk(this->logger, RAW|LEVEL2, "data before decryption with IV and (invalid) signature", this->encrypted); - - - if (this->signer == NULL || this->crypter == NULL) - { - this->logger->log(this->logger, ERROR, "could not decrypt, no crypter/signer set"); - return INVALID_STATE; - } - - /* get IV */ - iv.len = this->crypter->get_block_size(this->crypter); - - iv.ptr = this->encrypted.ptr; - - /* point concatenated to data + padding + padding_length*/ - concatenated.ptr = this->encrypted.ptr + iv.len; - concatenated.len = this->encrypted.len - iv.len - this->signer->get_block_size(this->signer); - - /* check the size of input: - * concatenated must be at least on block_size of crypter - */ - if (concatenated.len < iv.len) - { - this->logger->log(this->logger, ERROR|LEVEL1, "could not decrypt, invalid input"); - return FAILED; - } - - /* free previus data, if any */ - free(this->decrypted.ptr); - - this->logger->log_chunk(this->logger, RAW|LEVEL2, "data before decryption", concatenated); - - status = this->crypter->decrypt(this->crypter, concatenated, iv, &(this->decrypted)); - if (status != SUCCESS) - { - this->logger->log(this->logger, ERROR|LEVEL1, "could not decrypt, decryption failed"); - return FAILED; - } - this->logger->log_chunk(this->logger, RAW|LEVEL2, "data after decryption with padding", this->decrypted); - - - /* get padding length, sits just bevore signature */ - padding_length = *(this->decrypted.ptr + this->decrypted.len - 1); - /* add one byte to the padding length, since the padding_length field is not included */ - padding_length++; - this->decrypted.len -= padding_length; - - /* check size again */ - if (padding_length > concatenated.len || this->decrypted.len < 0) - { - this->logger->log(this->logger, ERROR|LEVEL1, "decryption failed, invalid padding length found. Invalid key?"); - /* decryption failed :-/ */ - return FAILED; - } - - /* free padding */ - this->decrypted.ptr = realloc(this->decrypted.ptr, this->decrypted.len); - this->logger->log_chunk(this->logger, RAW|LEVEL2, "data after decryption without padding", this->decrypted); - this->logger->log(this->logger, CONTROL|LEVEL2, "decryption successful, trying to parse content"); - return (this->parse(this)); -} - -/** - * Implementation of encryption_payload_t.set_transforms. - */ -static void set_transforms(private_encryption_payload_t *this, crypter_t* crypter, signer_t* signer) -{ - this->signer = signer; - this->crypter = crypter; -} - -/** - * Implementation of encryption_payload_t.build_signature. - */ -static status_t build_signature(private_encryption_payload_t *this, chunk_t data) -{ - chunk_t data_without_sig = data; - chunk_t sig; - - if (this->signer == NULL) - { - this->logger->log(this->logger, ERROR, "unable to build signature, no signer set"); - return INVALID_STATE; - } - - sig.len = this->signer->get_block_size(this->signer); - data_without_sig.len -= sig.len; - sig.ptr = data.ptr + data_without_sig.len; - this->logger->log(this->logger, CONTROL|LEVEL2, "building signature"); - this->signer->get_signature(this->signer, data_without_sig, sig.ptr); - return SUCCESS; -} - -/** - * Implementation of encryption_payload_t.verify_signature. - */ -static status_t verify_signature(private_encryption_payload_t *this, chunk_t data) -{ - chunk_t sig, data_without_sig; - bool valid; - - if (this->signer == NULL) - { - this->logger->log(this->logger, ERROR, "unable to verify signature, no signer set"); - return INVALID_STATE; - } - /* find signature in data chunk */ - sig.len = this->signer->get_block_size(this->signer); - if (data.len <= sig.len) - { - this->logger->log(this->logger, ERROR|LEVEL1, "unable to verify signature, invalid input"); - return FAILED; - } - sig.ptr = data.ptr + data.len - sig.len; - - /* verify it */ - data_without_sig.len = data.len - sig.len; - data_without_sig.ptr = data.ptr; - valid = this->signer->verify_signature(this->signer, data_without_sig, sig); - - if (!valid) - { - this->logger->log(this->logger, ERROR|LEVEL1, "signature verification failed"); - return FAILED; - } - - this->logger->log(this->logger, CONTROL|LEVEL2, "signature verification successful"); - return SUCCESS; -} - -/** - * Implementation of private_encryption_payload_t.generate. - */ -static void generate(private_encryption_payload_t *this) -{ - payload_t *current_payload, *next_payload; - generator_t *generator; - iterator_t *iterator; - - /* recalculate length before generating */ - this->compute_length(this); - - /* create iterator */ - iterator = this->payloads->create_iterator(this->payloads, TRUE); - - /* get first payload */ - if (iterator->has_next(iterator)) - { - iterator->current(iterator, (void**)¤t_payload); - this->next_payload = current_payload->get_type(current_payload); - } - else - { - /* no paylads? */ - this->logger->log(this->logger, CONTROL|LEVEL1, "generating contained payloads, but no available"); - free(this->decrypted.ptr); - this->decrypted = CHUNK_INITIALIZER; - iterator->destroy(iterator); - return; - } - - generator = generator_create(); - - /* build all payload, except last */ - while(iterator->has_next(iterator)) - { - iterator->current(iterator, (void**)&next_payload); - current_payload->set_next_type(current_payload, next_payload->get_type(next_payload)); - generator->generate_payload(generator, current_payload); - current_payload = next_payload; - } - iterator->destroy(iterator); - - /* build last payload */ - current_payload->set_next_type(current_payload, NO_PAYLOAD); - generator->generate_payload(generator, current_payload); - - /* free already generated data */ - free(this->decrypted.ptr); - - generator->write_to_chunk(generator, &(this->decrypted)); - generator->destroy(generator); - this->logger->log(this->logger, CONTROL|LEVEL1, "successfully generated content in encrpytion payload"); -} - -/** - * Implementation of private_encryption_payload_t.parse. - */ -static status_t parse(private_encryption_payload_t *this) -{ - parser_t *parser; - status_t status; - payload_type_t current_payload_type; - - /* check if there is decrypted data */ - if (this->decrypted.ptr == NULL) - { - this->logger->log(this->logger, ERROR, "unable to parse, no input!"); - return INVALID_STATE; - } - - /* build a parser on the decrypted data */ - parser = parser_create(this->decrypted); - - current_payload_type = this->next_payload; - /* parse all payloads */ - while (current_payload_type != NO_PAYLOAD) - { - payload_t *current_payload; - - status = parser->parse_payload(parser, current_payload_type, (payload_t**)¤t_payload); - if (status != SUCCESS) - { - parser->destroy(parser); - return PARSE_ERROR; - } - - status = current_payload->verify(current_payload); - if (status != SUCCESS) - { - this->logger->log(this->logger, ERROR|LEVEL1, "%s verification failed: %s", - mapping_find(payload_type_m,current_payload->get_type(current_payload)), - mapping_find(status_m, status)); - current_payload->destroy(current_payload); - parser->destroy(parser); - return VERIFY_ERROR; - } - - /* get next payload type */ - current_payload_type = current_payload->get_next_type(current_payload); - - this->payloads->insert_last(this->payloads,current_payload); - } - parser->destroy(parser); - this->logger->log(this->logger, CONTROL|LEVEL1, "succesfully parsed content of encryption payload"); - return SUCCESS; -} - -/** - * Implementation of private_encryption_payload_t.compute_length. - */ -static void compute_length(private_encryption_payload_t *this) -{ - iterator_t *iterator; - size_t block_size, length = 0; - iterator = this->payloads->create_iterator(this->payloads, TRUE); - - /* count payload length */ - while (iterator->has_next(iterator)) - { - payload_t *current_payload; - iterator->current(iterator, (void **) ¤t_payload); - length += current_payload->get_length(current_payload); - } - iterator->destroy(iterator); - - if (this->crypter && this->signer) - { - /* append one byte for padding length */ - length++; - /* append padding */ - block_size = this->crypter->get_block_size(this->crypter); - length += block_size - length % block_size; - /* add iv */ - length += block_size; - /* add signature */ - length += this->signer->get_block_size(this->signer); - } - length += ENCRYPTION_PAYLOAD_HEADER_LENGTH; - this->payload_length = length; -} - - -/** - * Implementation of payload_t.destroy. - */ -static void destroy(private_encryption_payload_t *this) -{ - /* all proposals are getting destroyed */ - while (this->payloads->get_count(this->payloads) > 0) - { - payload_t *current_payload; - this->payloads->remove_last(this->payloads,(void **)¤t_payload); - current_payload->destroy(current_payload); - } - this->payloads->destroy(this->payloads); - free(this->encrypted.ptr); - free(this->decrypted.ptr); - free(this); -} - -/* - * Described in header - */ -encryption_payload_t *encryption_payload_create() -{ - private_encryption_payload_t *this = malloc_thing(private_encryption_payload_t); - - /* 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.create_payload_iterator = (iterator_t * (*) (encryption_payload_t *,bool)) create_payload_iterator; - this->public.add_payload = (void (*) (encryption_payload_t *,payload_t *)) add_payload; - this->public.remove_first_payload = (status_t (*)(encryption_payload_t*, payload_t **)) remove_first_payload; - this->public.get_payload_count = (size_t (*)(encryption_payload_t*)) get_payload_count; - - this->public.encrypt = (status_t (*) (encryption_payload_t *)) encrypt; - this->public.decrypt = (status_t (*) (encryption_payload_t *)) decrypt; - this->public.set_transforms = (void (*) (encryption_payload_t*,crypter_t*,signer_t*)) set_transforms; - this->public.build_signature = (status_t (*) (encryption_payload_t*, chunk_t)) build_signature; - this->public.verify_signature = (status_t (*) (encryption_payload_t*, chunk_t)) verify_signature; - this->public.destroy = (void (*) (encryption_payload_t *)) destroy; - - /* private functions */ - this->compute_length = compute_length; - this->generate = generate; - this->parse = parse; - this->logger = logger_manager->get_logger(logger_manager, ENCRYPTION_PAYLOAD); - - /* set default values of the fields */ - this->critical = FALSE; - this->next_payload = NO_PAYLOAD; - this->payload_length = ENCRYPTION_PAYLOAD_HEADER_LENGTH; - this->encrypted = CHUNK_INITIALIZER; - this->decrypted = CHUNK_INITIALIZER; - this->signer = NULL; - this->crypter = NULL; - this->payloads = linked_list_create(); - - return (&(this->public)); -} diff --git a/src/charon/charon/encoding/payloads/encryption_payload.h b/src/charon/charon/encoding/payloads/encryption_payload.h deleted file mode 100644 index 006df969c..000000000 --- a/src/charon/charon/encoding/payloads/encryption_payload.h +++ /dev/null @@ -1,196 +0,0 @@ -/** - * @file encryption_payload.h - * - * @brief Interface of encryption_payload_t. - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef ENCRYPTION_PAYLOAD_H_ -#define ENCRYPTION_PAYLOAD_H_ - -#include -#include -#include -#include -#include - -/** - * Encrpytion payload length in bytes without IV and following data. - * - * @ingroup payloads - */ -#define ENCRYPTION_PAYLOAD_HEADER_LENGTH 4 - - -typedef struct encryption_payload_t encryption_payload_t; - -/** - * @brief The encryption payload as described in RFC section 3.14. - * - * Before any crypt/decrypt/sign/verify operation can occur, - * the transforms must be set. After that, a parsed encryption payload - * can be decrypted, which also will parse the contained payloads. - * Encryption is done the same way, added payloads will get generated - * and then encrypted. - * For signature building, there is the FULL packet needed. Meaning it - * must be builded after generation of all payloads and the encryption - * of the encryption payload. - * Signature verificatin is done before decryption. - * - * @b Constructors: - * - encryption_payload_create() - * - * @ingroup payloads - */ -struct encryption_payload_t { - /** - * Implements payload_t interface. - */ - payload_t payload_interface; - - /** - * @brief Creates an iterator for all contained payloads. - * - * @warning iterator_t object has to get destroyed by the caller. - * - * @param this calling encryption_payload_t object - * @param[in] forward iterator direction (TRUE: front to end) - * return created iterator_t object - */ - iterator_t *(*create_payload_iterator) (encryption_payload_t *this, bool forward); - - /** - * @brief Adds a payload to this encryption payload. - * - * @param this calling encryption_payload_t object - * @param payload payload_t object to add - */ - void (*add_payload) (encryption_payload_t *this, payload_t *payload); - - /** - * @brief Reove the last payload in the contained payload list. - * - * @param this calling encryption_payload_t object - * @param[out] payload removed payload - * @return - * - SUCCESS, or - * - NOT_FOUND if list empty - */ - status_t (*remove_first_payload) (encryption_payload_t *this, payload_t **payload); - - /** - * @brief Get the number of payloads. - * - * @param this calling encryption_payload_t object - * @return number of contained payloads - */ - size_t (*get_payload_count) (encryption_payload_t *this); - - /** - * @brief Set transforms to use. - * - * To decryption, encryption, signature building and verifying, - * the payload needs a crypter and a signer object. - * - * @warning Do NOT call this function again after encryption, since - * the signer must be the same while encrypting and signature building! - * - * @param this calling encryption_payload_t - * @param crypter crypter_t to use for data de-/encryption - * @param signer signer_t to use for data signing/verifying - */ - void (*set_transforms) (encryption_payload_t *this, crypter_t *crypter, signer_t *signer); - - /** - * @brief Generate and encrypt contained payloads. - * - * This function generates the content for added payloads - * and encrypts them. Signature is not built, since we need - * additional data (the full message). - * - * @param this calling encryption_payload_t - * @return - * - SUCCESS, or - * - INVALID_STATE if transforms not set - */ - status_t (*encrypt) (encryption_payload_t *this); - - /** - * @brief Decrypt and parse contained payloads. - * - * This function decrypts the contained data. After, - * the payloads are parsed internally and are accessible - * via the iterator. - * - * @param this calling encryption_payload_t - * @return - * - SUCCESS, or - * - INVALID_STATE if transforms not set, or - * - FAILED if data is invalid - */ - status_t (*decrypt) (encryption_payload_t *this); - - /** - * @brief Build the signature. - * - * The signature is built over the FULL message, so the header - * and every payload (inclusive this one) must already be generated. - * The generated message is supplied via the data paramater. - * - * @param this calling encryption_payload_t - * @param data chunk contains the already generated message - * @return - * - SUCCESS, or - * - INVALID_STATE if transforms not set - */ - status_t (*build_signature) (encryption_payload_t *this, chunk_t data); - - /** - * @brief Verify the signature. - * - * Since the signature is built over the full message, we need - * this data to do the verification. The message data - * is supplied via the data argument. - * - * @param this calling encryption_payload_t - * @param data chunk contains the message - * @return - * - SUCCESS, or - * - FAILED if signature invalid, or - * - INVALID_STATE if transforms not set - */ - status_t (*verify_signature) (encryption_payload_t *this, chunk_t data); - - /** - * @brief Destroys an encryption_payload_t object. - * - * @param this encryption_payload_t object to destroy - */ - void (*destroy) (encryption_payload_t *this); -}; - -/** - * @brief Creates an empty encryption_payload_t object. - * - * @return encryption_payload_t object - * - * @ingroup payloads - */ -encryption_payload_t *encryption_payload_create(void); - - -#endif /*ENCRYPTION_PAYLOAD_H_*/ diff --git a/src/charon/charon/encoding/payloads/id_payload.c b/src/charon/charon/encoding/payloads/id_payload.c deleted file mode 100644 index 6a8d7738d..000000000 --- a/src/charon/charon/encoding/payloads/id_payload.c +++ /dev/null @@ -1,320 +0,0 @@ -/** - * @file id_payload.h - * - * @brief Interface of id_payload_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 - -#include "id_payload.h" - -#include - -typedef struct private_id_payload_t private_id_payload_t; - -/** - * Private data of an id_payload_t object. - * - */ -struct private_id_payload_t { - /** - * Public id_payload_t interface. - */ - id_payload_t public; - - /** - * TRUE if this ID payload is of type IDi, FALSE for IDr. - */ - bool is_initiator; - - /** - * Next payload type. - */ - u_int8_t next_payload; - - /** - * Critical flag. - */ - bool critical; - - /** - * Length of this payload. - */ - u_int16_t payload_length; - - /** - * Type of the ID Data. - */ - u_int8_t id_type; - - /** - * The contained id data value. - */ - chunk_t id_data; -}; - -/** - * Encoding rules to parse or generate a ID payload - * - * The defined offsets are the positions in a object of type - * private_id_payload_t. - * - */ -encoding_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 }, - /* 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 }, - /* some id data bytes, length is defined in PAYLOAD_LENGTH */ - { ID_DATA, offsetof(private_id_payload_t, id_data) } -}; - -/* - 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! Next Payload !C! RESERVED ! Payload Length ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! ID Type ! RESERVED | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! ! - ~ Identification Data ~ - ! ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -*/ - -/** - * Implementation of payload_t.verify. - */ -static status_t verify(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))) - { - /* reserved IDs */ - 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) -{ - *rules = id_payload_encodings; - *rule_count = sizeof(id_payload_encodings) / sizeof(encoding_rule_t); -} - -/** - * Implementation of payload_t.get_type. - */ -static payload_type_t get_payload_type(private_id_payload_t *this) -{ - if (this->is_initiator) - { - return ID_INITIATOR; - } - else - { - return ID_RESPONDER; - } -} - -/** - * Implementation of payload_t.get_next_type. - */ -static payload_type_t get_next_type(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) -{ - this->next_payload = type; -} - -/** - * Implementation of payload_t.get_length. - */ -static size_t get_length(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) -{ - return (this->id_type); -} - -/** - * Implementation of id_payload_t.set_data. - */ -static void set_data (private_id_payload_t *this, chunk_t data) -{ - 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_initiator. - */ -static bool get_initiator (private_id_payload_t *this) -{ - return (this->is_initiator); -} - -/** - * Implementation of id_payload_t.set_initiator. - */ -static void set_initiator (private_id_payload_t *this,bool is_initiator) -{ - this->is_initiator = is_initiator; -} - -/** - * 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); -} - -/* - * Described in header. - */ -id_payload_t *id_payload_create(bool is_initiator) -{ - 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_initiator = (bool (*) (id_payload_t *)) get_initiator; - this->public.set_initiator = (void (*) (id_payload_t *,bool)) set_initiator; - 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_INITIALIZER; - this->is_initiator = is_initiator; - - return (&(this->public)); -} - -/* - * Described in header. - */ -id_payload_t *id_payload_create_from_identification(bool is_initiator,identification_t *identification) -{ - id_payload_t *this= id_payload_create(is_initiator); - this->set_data(this,identification->get_encoding(identification)); - this->set_id_type(this,identification->get_type(identification)); - return this; -} diff --git a/src/charon/charon/encoding/payloads/id_payload.h b/src/charon/charon/encoding/payloads/id_payload.h deleted file mode 100644 index c35b44d59..000000000 --- a/src/charon/charon/encoding/payloads/id_payload.h +++ /dev/null @@ -1,172 +0,0 @@ -/** - * @file id_payload.h - * - * @brief Interface of id_payload_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - - -#ifndef ID_PAYLOAD_H_ -#define ID_PAYLOAD_H_ - -#include -#include -#include - -/** - * Length of a id payload without the data in bytes. - * - * @ingroup payloads - */ -#define ID_PAYLOAD_HEADER_LENGTH 8 - - -typedef struct id_payload_t id_payload_t; - -/** - * Object representing an IKEv2 ID payload. - * - * The ID payload format is described in RFC section 3.5. - * - * @b Constructors: - * - id_payload_create_from_identification() - * - id_payload_create() - * - * @ingroup payloads - */ -struct id_payload_t { - /** - * The payload_t interface. - */ - payload_t payload_interface; - - /** - * @brief Set the ID type. - * - * @param this calling id_payload_t object - * @param type Type of ID - */ - void (*set_id_type) (id_payload_t *this, id_type_t type); - - /** - * @brief Get the ID type. - * - * @param this calling id_payload_t object - * @return type of the ID - */ - id_type_t (*get_id_type) (id_payload_t *this); - - /** - * @brief Set the ID data. - * - * Data are getting cloned. - * - * @param this calling id_payload_t object - * @param data ID data as chunk_t - */ - void (*set_data) (id_payload_t *this, chunk_t data); - - /** - * @brief Get the ID data. - * - * Returned data are a copy of the internal one - * - * @param this calling id_payload_t object - * @return ID data as chunk_t - */ - chunk_t (*get_data_clone) (id_payload_t *this); - - /** - * @brief Get the ID data. - * - * Returned data are NOT copied. - * - * @param this calling id_payload_t object - * @return ID data as chunk_t - */ - chunk_t (*get_data) (id_payload_t *this); - - /** - * @brief Creates an identification object of this id payload. - * - * Returned object has to get destroyed by the caller. - * - * @param this calling id_payload_t object - * @return identification_t object - */ - identification_t *(*get_identification) (id_payload_t *this); - - /** - * @brief Get the type of ID payload (IDi or IDr). - * - * @param this calling id_payload_t object - * @return - * - TRUE if this payload is of type IDi - * - FALSE if this payload is of type IDr - * - */ - bool (*get_initiator) (id_payload_t *this); - - /** - * @brief Set the type of ID payload (IDi or IDr). - * - * @param this calling id_payload_t object - * @param is_initiator - * - TRUE if this payload is of type IDi - * - FALSE if this payload is of type IDr - * - */ - void (*set_initiator) (id_payload_t *this,bool is_initiator); - - /** - * @brief Destroys an id_payload_t object. - * - * @param this id_payload_t object to destroy - */ - void (*destroy) (id_payload_t *this); -}; - -/** - * @brief Creates an empty id_payload_t object. - * - * @param is_initiator - * - TRUE if this payload is of type IDi - * - FALSE if this payload is of type IDr - * - * @return id_payload_t object - * - * @ingroup payloads - */ -id_payload_t *id_payload_create(bool is_initiator); - -/** - * @brief Creates an id_payload_t from an existing identification_t object. - * - * @param is_initiator - * - TRUE if this payload is of type IDi - * - FALSE if this payload is of type IDr - * @param identification identification_t object - * @return id_payload_t object - * - * @ingroup payloads - */ -id_payload_t *id_payload_create_from_identification(bool is_initiator,identification_t *identification); - - - -#endif /* ID_PAYLOAD_H_ */ diff --git a/src/charon/charon/encoding/payloads/ike_header.c b/src/charon/charon/encoding/payloads/ike_header.c deleted file mode 100644 index ad46d3d29..000000000 --- a/src/charon/charon/encoding/payloads/ike_header.c +++ /dev/null @@ -1,408 +0,0 @@ -/** - * @file ike_header.c - * - * @brief Implementation of ike_header_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -/* offsetof macro */ -#include - -#include "ike_header.h" - -#include - - -typedef struct private_ike_header_t private_ike_header_t; - -/** - * Private data of an ike_header_t object. - * - */ -struct private_ike_header_t { - /** - * Public interface. - */ - ike_header_t public; - - /** - * SPI of the initiator. - */ - u_int64_t initiator_spi; - - /** - * SPI of the responder. - */ - u_int64_t responder_spi; - - /** - * Next payload type. - */ - u_int8_t next_payload; - /** - * IKE major version. - */ - u_int8_t maj_version; - - /** - * IKE minor version. - */ - u_int8_t min_version; - - /** - * Exchange type . - */ - u_int8_t exchange_type; - - /** - * Flags of the Message. - * - */ - struct { - /** - * Sender is initiator of the associated IKE_SA_INIT-Exchange. - */ - bool initiator; - - /** - * Is protocol supporting higher version? - */ - bool version; - - /** - * TRUE, if this is a response, FALSE if its a Request. - */ - bool response; - } flags; - - /** - * Associated Message-ID. - */ - u_int32_t message_id; - - /** - * Length of the whole IKEv2-Message (header and all payloads). - */ - u_int32_t length; -}; - -/** - * Mappings used to get strings for exchange_type_t. - */ -mapping_t exchange_type_m[] = { - {EXCHANGE_TYPE_UNDEFINED, "EXCHANGE_TYPE_UNDEFINED"}, - {IKE_SA_INIT, "IKE_SA_INIT"}, - {IKE_AUTH, "IKE_AUTH"}, - {CREATE_CHILD_SA, "CREATE_CHILD_SA"}, - {INFORMATIONAL, "INFORMATIONAL"} -}; - - -/** - * Encoding rules to parse or generate a IKEv2-Header. - * - * The defined offsets are the positions in a object of type - * ike_header_t. - * - */ -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) }, - /* 1 Byte next payload type, stored in the field 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) }, - /* 4 Bit minor version, stored in the field 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 }, - /* 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 }, - /* 4 Byte message id, stored in the field message_id */ - { U_INT_32, offsetof(private_ike_header_t, message_id) }, - /* 4 Byte length fied, stored in the field length */ - { HEADER_LENGTH, offsetof(private_ike_header_t, length) } -}; - - -/* 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! IKE_SA Initiator's SPI ! - ! ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! IKE_SA Responder's SPI ! - ! ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! Next Payload ! MjVer ! MnVer ! Exchange Type ! Flags ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! Message ID ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! Length ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -*/ - - -/** - * Implementation of payload_t.verify. - */ -static status_t verify(private_ike_header_t *this) -{ - if ((this->exchange_type < IKE_SA_INIT) || (this->exchange_type > INFORMATIONAL)) - { - /* unsupported exchange type */ - return FAILED; - } - if (this->initiator_spi == 0) - { - /* initiator spi not set */ - return FAILED; - } - - /* verification of version is not done in here */ - - return SUCCESS; -} - -/** - * Implementation of payload_t.set_next_type. - */ -static void set_next_type(payload_t *this,payload_type_t type) -{ - ((private_ike_header_t *)this)->next_payload = type; -} -/** - * Implementation of ike_header_t.get_initiator_spi. - */ -static u_int64_t get_initiator_spi(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) -{ - 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) -{ - 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) -{ - 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) -{ - return this->maj_version; -} - -/** - * Implementation of ike_header_t.get_min_version. - */ -static u_int8_t get_min_version(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) -{ - return this->flags.response; -} - -/** - * Implementation of ike_header_t.set_response_flag. - */ -static void set_response_flag(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) -{ - return this->flags.version; -} - -/** - * Implementation of ike_header_t.get_initiator_flag. - */ -static bool get_initiator_flag(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) -{ - this->flags.initiator = initiator; -} - -/** - * Implementation of ike_header_t.get_exchange_type. - */ -static u_int8_t get_exchange_type(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) -{ - 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) -{ - 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) -{ - this->message_id = message_id; -} - -/** - * Implementation of ike_header_t.destroy and payload_t.destroy. - */ -static void destroy(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; -} diff --git a/src/charon/charon/encoding/payloads/ike_header.h b/src/charon/charon/encoding/payloads/ike_header.h deleted file mode 100644 index bc4c40a5b..000000000 --- a/src/charon/charon/encoding/payloads/ike_header.h +++ /dev/null @@ -1,261 +0,0 @@ -/** - * @file ike_header.h - * - * @brief Interface of ike_header_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef IKE_HEADER_H_ -#define IKE_HEADER_H_ - -#include -#include - -/** - * Major Version of IKEv2. - * - * @ingroup payloads - */ -#define IKE_MAJOR_VERSION 2 - -/** - * Minor Version of IKEv2. - * - * @ingroup payloads - */ -#define IKE_MINOR_VERSION 0 - -/** - * Flag in IKEv2-Header. Always 0. - * - * @ingroup payloads - */ -#define HIGHER_VERSION_SUPPORTED_FLAG 0 - -/** - * Length of IKE Header in Bytes. - * - * @ingroup payloads - */ -#define IKE_HEADER_LENGTH 28 - -typedef enum exchange_type_t exchange_type_t; - -/** - * @brief Different types of IKE-Exchanges. - * - * See Draft for different types. - * - * @ingroup payloads - */ -enum exchange_type_t{ - - /** - * EXCHANGE_TYPE_UNDEFINED. In private space, since not a official message type. - */ - EXCHANGE_TYPE_UNDEFINED = 240, - - /** - * IKE_SA_INIT. - */ - IKE_SA_INIT = 34, - - /** - * IKE_AUTH. - */ - IKE_AUTH = 35, - - /** - * CREATE_CHILD_SA. - */ - CREATE_CHILD_SA = 36, - - /** - * INFORMATIONAL. - */ - INFORMATIONAL = 37 -}; - -/** - * string mappings for exchange_type_t - * - * @ingroup payloads - */ -extern mapping_t exchange_type_m[]; - - -typedef struct ike_header_t ike_header_t; - -/** - * @brief An object of this type represents an IKEv2 header and is used to - * generate and parse IKEv2 headers. - * - * The header format of an IKEv2-Message is compatible to the - * ISAKMP-Header format to allow implementations supporting - * both versions of the IKE-protocol. - * - * @b Constructors: - * - ike_header_create() - * - * @ingroup payloads - */ -struct ike_header_t { - /** - * The payload_t interface. - */ - payload_t payload_interface; - - /** - * @brief Get the initiator spi. - * - * @param this ike_header_t object - * @return initiator_spi - */ - u_int64_t (*get_initiator_spi) (ike_header_t *this); - - /** - * @brief Set the initiator spi. - * - * @param this ike_header_t object - * @param initiator_spi initiator_spi - */ - void (*set_initiator_spi) (ike_header_t *this, u_int64_t initiator_spi); - - /** - * @brief Get the responder spi. - * - * @param this ike_header_t object - * @return responder_spi - */ - u_int64_t (*get_responder_spi) (ike_header_t *this); - - /** - * @brief Set the responder spi. - * - * @param this ike_header_t object - * @param responder_spi responder_spi - */ - void (*set_responder_spi) (ike_header_t *this, u_int64_t responder_spi); - - /** - * @brief Get the major version. - * - * @param this ike_header_t object - * @return major version - */ - u_int8_t (*get_maj_version) (ike_header_t *this); - - /** - * @brief Get the minor version. - * - * @param this ike_header_t object - * @return minor version - */ - u_int8_t (*get_min_version) (ike_header_t *this); - - /** - * @brief Get the response flag. - * - * @param this ike_header_t object - * @return response flag - */ - bool (*get_response_flag) (ike_header_t *this); - - /** - * @brief Set the response flag- - * - * @param this ike_header_t object - * @param response response flag - * - */ - void (*set_response_flag) (ike_header_t *this, bool response); - /** - * @brief Get "higher version supported"-flag. - * - * @param this ike_header_t object - * @return version flag - */ - bool (*get_version_flag) (ike_header_t *this); - - /** - * @brief Get the initiator flag. - * - * @param this ike_header_t object - * @return initiator flag - */ - bool (*get_initiator_flag) (ike_header_t *this); - - /** - * @brief Set the initiator flag. - * - * @param this ike_header_t object - * @param initiator initiator flag - * - */ - void (*set_initiator_flag) (ike_header_t *this, bool initiator); - - /** - * @brief Get the exchange type. - * - * @param this ike_header_t object - * @return exchange type - */ - u_int8_t (*get_exchange_type) (ike_header_t *this); - - /** - * @brief Set the exchange type. - * - * @param this ike_header_t object - * @param exchange_type exchange type - */ - void (*set_exchange_type) (ike_header_t *this, u_int8_t exchange_type); - - /** - * @brief Get the message id. - * - * @param this ike_header_t object - * @return message id - */ - u_int32_t (*get_message_id) (ike_header_t *this); - - /** - * @brief Set the message id. - * - * @param this ike_header_t object - * @param initiator_spi message id - */ - void (*set_message_id) (ike_header_t *this, u_int32_t message_id); - - /** - * @brief Destroys a ike_header_t object. - * - * @param this ike_header_t object to destroy - */ - void (*destroy) (ike_header_t *this); -}; - -/** - * @brief Create an ike_header_t object - * - * @return ike_header_t object - * - * @ingroup payloads - */ -ike_header_t *ike_header_create(void); - -#endif /*IKE_HEADER_H_*/ diff --git a/src/charon/charon/encoding/payloads/ke_payload.c b/src/charon/charon/encoding/payloads/ke_payload.c deleted file mode 100644 index 0c92e033d..000000000 --- a/src/charon/charon/encoding/payloads/ke_payload.c +++ /dev/null @@ -1,276 +0,0 @@ -/** - * @file ke_payload.c - * - * @brief Implementation of ke_payload_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 - -#include "ke_payload.h" - -#include - - -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. - */ - ke_payload_t public; - - /** - * Next payload type. - */ - u_int8_t next_payload; - - /** - * Critical flag. - */ - bool critical; - - /** - * Length of this payload. - */ - u_int16_t payload_length; - - /** - * DH Group Number. - */ - diffie_hellman_group_t dh_group_number; - - /** - * Key Exchange Data of this KE payload. - */ - chunk_t key_exchange_data; - - /** - * @brief Computes the length of this payload. - * - * @param this calling private_ke_payload_t object - */ - void (*compute_length) (private_ke_payload_t *this); -}; - -/** - * Encoding rules to parse or generate a IKEv2-KE Payload. - * - * The defined offsets are the positions in a object of type - * private_ke_payload_t. - * - */ -encoding_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) }, - /* 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 }, - /* Length of the whole payload*/ - { 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 }, - /* Key Exchange Data is from variable size */ - { KEY_EXCHANGE_DATA, offsetof(private_ke_payload_t, key_exchange_data)} -}; - -/* - 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! Next Payload !C! RESERVED ! Payload Length ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! DH Group # ! RESERVED ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! ! - ~ Key Exchange Data ~ - ! ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -*/ - -/** - * Implementation of payload_t.verify. - */ -static status_t verify(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) -{ - *rules = ke_payload_encodings; - *rule_count = sizeof(ke_payload_encodings) / sizeof(encoding_rule_t); -} - -/** - * Implementation of payload_t.get_type. - */ -static payload_type_t get_type(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) -{ - 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) -{ - this->next_payload = type; -} - -/** - * Implementation of payload_t.get_length. - */ -static size_t get_length(private_ke_payload_t *this) -{ - this->compute_length(this); - return this->payload_length; -} - -/** - * Implementation of private_ke_payload_t.compute_length. - */ -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 ke_payload_t.get_key_exchange_data. - */ -static chunk_t get_key_exchange_data(private_ke_payload_t *this) -{ - 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.ptr = clalloc(key_exchange_data.ptr,key_exchange_data.len); - - this->key_exchange_data.len = key_exchange_data.len; - this->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) -{ - 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) -{ - this->dh_group_number = dh_group_number; -} - -/* - * Described in header - */ -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; - - /* private functions */ - this->compute_length = compute_length; - - /* 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.ptr = NULL; - this->key_exchange_data.len = 0; - this->dh_group_number = 0; - - return (&(this->public)); -} diff --git a/src/charon/charon/encoding/payloads/ke_payload.h b/src/charon/charon/encoding/payloads/ke_payload.h deleted file mode 100644 index 9490bef89..000000000 --- a/src/charon/charon/encoding/payloads/ke_payload.h +++ /dev/null @@ -1,110 +0,0 @@ -/** - * @file ke_payload.h - * - * @brief Interface of ke_payload_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef KE_PAYLOAD_H_ -#define KE_PAYLOAD_H_ - -#include -#include -#include -#include -/** - * KE payload length in bytes without any key exchange data. - * - * @ingroup payloads - */ -#define KE_PAYLOAD_HEADER_LENGTH 8 - - -typedef struct ke_payload_t ke_payload_t; - -/** - * @brief Class representing an IKEv2-KE Payload. - * - * The KE Payload format is described in RFC section 3.4. - * - * @b Constructors: - * - ke_payload_create() - * - * @ingroup payloads - */ -struct ke_payload_t { - /** - * The payload_t interface. - */ - payload_t payload_interface; - - /** - * @brief Returns the currently set key exchange data of this KE payload. - * - * @warning Returned data are not copied. - * - * @param this calling ke_payload_t object - * @return chunk_t pointing to the value - */ - chunk_t (*get_key_exchange_data) (ke_payload_t *this); - - /** - * @brief Sets the key exchange data of this KE payload. - * - * @warning Value is getting copied. - * - * @param this calling ke_payload_t object - * @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); - - /** - * @brief Gets the Diffie-Hellman Group Number of this KE payload. - * - * @param this calling ke_payload_t object - * @return DH Group Number of this payload - */ - diffie_hellman_group_t (*get_dh_group_number) (ke_payload_t *this); - - /** - * @brief Sets the Diffie-Hellman Group Number of this KE payload. - * - * @param this calling ke_payload_t object - * @param dh_group_number DH Group to set - */ - void (*set_dh_group_number) (ke_payload_t *this, diffie_hellman_group_t dh_group_number); - - /** - * @brief Destroys an ke_payload_t object. - * - * @param this ke_payload_t object to destroy - */ - void (*destroy) (ke_payload_t *this); -}; - -/** - * @brief Creates an empty ke_payload_t object - * - * @return ke_payload_t object - * - * @ingroup payloads - */ -ke_payload_t *ke_payload_create(void); - - -#endif /*KE_PAYLOAD_H_*/ diff --git a/src/charon/charon/encoding/payloads/nonce_payload.c b/src/charon/charon/encoding/payloads/nonce_payload.c deleted file mode 100644 index a7528fbfb..000000000 --- a/src/charon/charon/encoding/payloads/nonce_payload.c +++ /dev/null @@ -1,241 +0,0 @@ -/** - * @file nonce_payload.h - * - * @brief Implementation of nonce_payload_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -/* offsetof macro */ -#include - -#include "nonce_payload.h" - -#include - - -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. - */ - nonce_payload_t public; - - /** - * Next payload type. - */ - u_int8_t next_payload; - - /** - * Critical flag. - */ - bool critical; - - /** - * Length of this payload. - */ - u_int16_t payload_length; - - /** - * The contained nonce value. - */ - chunk_t nonce; - - /** - * @brief Computes the length of this payload. - * - * @param this calling private_nonce_payload_t object - */ - void (*compute_length) (private_nonce_payload_t *this); -}; - -/** - * Encoding rules to parse or generate a nonce payload - * - * 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) }, - /* 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 }, - /* Length of the whole nonce payload*/ - { PAYLOAD_LENGTH, offsetof(private_nonce_payload_t, payload_length) }, - /* some nonce bytes, lenth is defined in PAYLOAD_LENGTH */ - { NONCE_DATA, offsetof(private_nonce_payload_t, nonce) } -}; - -/* 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! Next Payload !C! RESERVED ! Payload Length ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! ! - ~ Nonce Data ~ - ! ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -*/ - -/** - * Implementation of payload_t.verify. - */ -static status_t verify(private_nonce_payload_t *this) -{ - 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) -{ - *rules = nonce_payload_encodings; - *rule_count = sizeof(nonce_payload_encodings) / sizeof(encoding_rule_t); -} - -/** - * Implementation of payload_t.get_type. - */ -static payload_type_t get_type(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) -{ - 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) -{ - this->next_payload = type; -} - -/** - * Implementation of payload_t.get_length. - */ -static size_t get_length(private_nonce_payload_t *this) -{ - this->compute_length(this); - return this->payload_length; -} - -/** - * Implementation of private_id_payload_t.compute_length. - */ -static void compute_length(private_nonce_payload_t *this) -{ - this->payload_length = NONCE_PAYLOAD_HEADER_LENGTH + this->nonce.len; -} - -/** - * Implementation of payload_t.destroy and nonce_payload_t.destroy. - */ -static void destroy(private_nonce_payload_t *this) -{ - if (this->nonce.ptr != NULL) - { - free(this->nonce.ptr); - } - - free(this); -} - -/* - * Described in header - */ -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 functions */ - this->compute_length = compute_length; - - /* 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)); -} - - diff --git a/src/charon/charon/encoding/payloads/nonce_payload.h b/src/charon/charon/encoding/payloads/nonce_payload.h deleted file mode 100644 index e875fb263..000000000 --- a/src/charon/charon/encoding/payloads/nonce_payload.h +++ /dev/null @@ -1,89 +0,0 @@ -/** - * @file nonce_payload.h - * - * @brief Interface of nonce_payload_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef NONCE_PAYLOAD_H_ -#define NONCE_PAYLOAD_H_ - -#include -#include - -/** - * Length of a nonce payload without a nonce in bytes. - * - * @ingroup payloads - */ -#define NONCE_PAYLOAD_HEADER_LENGTH 4 - -typedef struct nonce_payload_t nonce_payload_t; - -/** - * Object representing an IKEv2 Nonce payload. - * - * The Nonce payload format is described in RFC section 3.3. - * - * @b Constructors: - * - nonce_payload_create() - * - * @ingroup payloads - */ -struct nonce_payload_t { - /** - * The payload_t interface. - */ - payload_t payload_interface; - - /** - * @brief Set the nonce value. - * - * @param this calling nonce_payload_t object - * @param nonce chunk containing the nonce, will be cloned - */ - void (*set_nonce) (nonce_payload_t *this, chunk_t nonce); - - /** - * @brief Get the nonce value. - * - * @param this calling nonce_payload_t object - * @return a chunk containing the cloned nonce - */ - chunk_t (*get_nonce) (nonce_payload_t *this); - - /** - * @brief Destroys an nonce_payload_t object. - * - * @param this nonce_payload_t object to destroy - */ - void (*destroy) (nonce_payload_t *this); -}; - -/** - * @brief Creates an empty nonce_payload_t object - * - * @return nonce_payload_t object - * - * @ingroup payloads - */ - -nonce_payload_t *nonce_payload_create(void); - - -#endif /*NONCE_PAYLOAD_H_*/ diff --git a/src/charon/charon/encoding/payloads/notify_payload.c b/src/charon/charon/encoding/payloads/notify_payload.c deleted file mode 100644 index 43d0c5322..000000000 --- a/src/charon/charon/encoding/payloads/notify_payload.c +++ /dev/null @@ -1,441 +0,0 @@ -/** - * @file notify_payload.c - * - * @brief Implementation of notify_payload_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 - -#include "notify_payload.h" - -#include -#include - -/** - * String mappings for notify_message_type_t. - */ -mapping_t notify_message_type_m[] = { - {UNSUPPORTED_CRITICAL_PAYLOAD, "UNSUPPORTED_CRITICAL_PAYLOAD"}, - {INVALID_IKE_SPI, "INVALID_IKE_SPI"}, - {INVALID_MAJOR_VERSION, "INVALID_MAJOR_VERSION"}, - {INVALID_SYNTAX, "INVALID_SYNTAX"}, - {INVALID_MESSAGE_ID, "INVALID_MESSAGE_ID"}, - {INVALID_SPI, "INVALID_SPI"}, - {NO_PROPOSAL_CHOSEN, "NO_PROPOSAL_CHOSEN"}, - {INVALID_KE_PAYLOAD, "INVALID_KE_PAYLOAD"}, - {AUTHENTICATION_FAILED, "AUTHENTICATION_FAILED"}, - {SINGLE_PAIR_REQUIRED, "SINGLE_PAIR_REQUIRED"}, - {NO_ADDITIONAL_SAS, "NO_ADDITIONAL_SAS"}, - {INTERNAL_ADDRESS_FAILURE, "INTERNAL_ADDRESS_FAILURE"}, - {FAILED_CP_REQUIRED, "FAILED_CP_REQUIRED"}, - {TS_UACCEPTABLE, "TS_UACCEPTABLE"}, - {INVALID_SELECTORS, "INVALID_SELECTORS"}, - {INITIAL_CONTACT, "INITIAL_CONTACT"}, - {SET_WINDOW_SIZE, "SET_WINDOW_SIZE"}, - {MAPPING_END, NULL} -}; - -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. - */ - notify_payload_t public; - - /** - * Next payload type. - */ - u_int8_t next_payload; - - /** - * Critical flag. - */ - bool critical; - - /** - * Length of this payload. - */ - u_int16_t payload_length; - - /** - * Protocol id. - */ - u_int8_t protocol_id; - - /** - * Spi size. - */ - u_int8_t spi_size; - - /** - * Notify message type. - */ - u_int16_t notify_message_type; - - /** - * Security parameter index (spi). - */ - chunk_t spi; - - /** - * Notification data. - */ - chunk_t notification_data; - - /** - * Assigned logger - */ - logger_t *logger; - - /** - * @brief Computes the length of this payload. - * - * @param this calling private_ke_payload_t object - */ - void (*compute_length) (private_notify_payload_t *this); -}; - -/** - * Encoding rules to parse or generate a IKEv2-Notify Payload. - * - * The defined offsets are the positions in a object of type - * private_notify_payload_t. - * - */ -encoding_rule_t notify_payload_encodings[] = { - /* 1 Byte next payload type, stored in the field next_payload */ - { U_INT_8, offsetof(private_notify_payload_t, next_payload) }, - /* 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 }, - /* Length of the whole payload*/ - { PAYLOAD_LENGTH, offsetof(private_notify_payload_t, payload_length) }, - /* Protocol ID as 8 bit field*/ - { U_INT_8, offsetof(private_notify_payload_t, protocol_id) }, - /* 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_message_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) } -}; - -/* - 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! Next Payload !C! RESERVED ! Payload Length ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! Protocol ID ! SPI Size ! Notify Message Type ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! ! - ~ Security Parameter Index (SPI) ~ - ! ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! ! - ~ Notification Data ~ - ! ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -*/ - -/** - * Implementation of payload_t.verify. - */ -static status_t verify(private_notify_payload_t *this) -{ - if (this->protocol_id > 3) - { - /* reserved for future use */ - return FAILED; - } - - /* TODO: Check all kinds of notify */ - - if (this->notify_message_type == INVALID_KE_PAYLOAD) - { - /* check notification data */ - diffie_hellman_group_t dh_group; - if (this->notification_data.len != 2) - { - return FAILED; - } - dh_group = ntohs(*((u_int16_t*)this->notification_data.ptr)); - switch (dh_group) - { - case MODP_768_BIT: - case MODP_1024_BIT: - case MODP_1536_BIT: - case MODP_2048_BIT: - case MODP_3072_BIT: - case MODP_4096_BIT: - case MODP_6144_BIT: - case MODP_8192_BIT: - break; - default: - this->logger->log(this->logger, ERROR, "Bad DH group (%d)", dh_group); - return FAILED; - } - } - 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) -{ - *rules = notify_payload_encodings; - *rule_count = sizeof(notify_payload_encodings) / sizeof(encoding_rule_t); -} - -/** - * Implementation of payload_t.get_type. - */ -static payload_type_t get_type(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) -{ - 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) -{ - this->next_payload = type; -} - -/** - * Implementation of payload_t.get_length. - */ -static size_t get_length(private_notify_payload_t *this) -{ - this->compute_length(this); - return this->payload_length; -} - -/** - * Implementation of private_notify_payload_t.compute_length. - */ -static void compute_length (private_notify_payload_t *this) -{ - size_t length = NOTIFY_PAYLOAD_HEADER_LENGTH; - if (this->notification_data.ptr != NULL) - { - length += this->notification_data.len; - } - if (this->spi.ptr != NULL) - { - length += this->spi.len; - } - - this->payload_length = length; - -} - -/** - * Implementation of notify_payload_t.get_protocol_id. - */ -static u_int8_t get_protocol_id(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) -{ - this->protocol_id = protocol_id; -} - -/** - * Implementation of notify_payload_t.get_notify_message_type. - */ -static u_int16_t get_notify_message_type(private_notify_payload_t *this) -{ - return this->notify_message_type; -} - -/** - * Implementation of notify_payload_t.set_notify_message_type. - */ -static void set_notify_message_type(private_notify_payload_t *this, u_int16_t notify_message_type) -{ - this->notify_message_type = notify_message_type; -} - -/** - * Implementation of notify_payload_t.get_spi. - */ -static chunk_t get_spi(private_notify_payload_t *this) -{ - return (this->spi); -} - -/** - * Implementation of notify_payload_t.set_spi. - */ -static void set_spi(private_notify_payload_t *this, chunk_t spi) -{ - /* destroy existing data first */ - if (this->spi.ptr != NULL) - { - /* free existing value */ - free(this->spi.ptr); - this->spi.ptr = NULL; - this->spi.len = 0; - - } - - this->spi.ptr = clalloc(spi.ptr,spi.len); - - this->spi.len = spi.len; - this->spi_size = spi.len; - this->compute_length(this); - -} - -/** - * Implementation of notify_payload_t.get_notification_data. - */ -static chunk_t get_notification_data(private_notify_payload_t *this) -{ - 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) -{ - /* destroy existing data first */ - if (this->notification_data.ptr != NULL) - { - /* free existing value */ - free(this->notification_data.ptr); - this->notification_data.ptr = NULL; - this->notification_data.len = 0; - - } - - this->notification_data.ptr = clalloc(notification_data.ptr,notification_data.len); - this->notification_data.len = notification_data.len; - this->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) -{ - if (this->notification_data.ptr != NULL) - { - free(this->notification_data.ptr); - } - if (this->spi.ptr != NULL) - { - free(this->spi.ptr); - } - - free(this); - return SUCCESS; -} - -/* - * Described in header - */ -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_message_type = (u_int16_t (*) (notify_payload_t *)) get_notify_message_type; - this->public.set_notify_message_type = (void (*) (notify_payload_t *,u_int16_t)) set_notify_message_type; - this->public.get_spi = (chunk_t (*) (notify_payload_t *)) get_spi; - this->public.set_spi = (void (*) (notify_payload_t *,chunk_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; - - /* private functions */ - this->compute_length = compute_length; - - /* 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_message_type = 0; - this->spi.ptr = NULL; - this->spi.len = 0; - this->spi_size = 0; - this->notification_data.ptr = NULL; - this->notification_data.len = 0; - this->logger = logger_manager->get_logger(logger_manager, PAYLOAD); - - return (&(this->public)); -} - -/* - * Described in header. - */ -notify_payload_t *notify_payload_create_from_protocol_and_type(protocol_id_t protocol_id, notify_message_type_t notify_message_type) -{ - notify_payload_t *notify = notify_payload_create(); - - notify->set_notify_message_type(notify,notify_message_type); - notify->set_protocol_id(notify,protocol_id); - - return notify; -} diff --git a/src/charon/charon/encoding/payloads/notify_payload.h b/src/charon/charon/encoding/payloads/notify_payload.h deleted file mode 100644 index 4c9383e49..000000000 --- a/src/charon/charon/encoding/payloads/notify_payload.h +++ /dev/null @@ -1,200 +0,0 @@ -/** - * @file notify_payload.h - * - * @brief Interface of notify_payload_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - - -#ifndef NOTIFY_PAYLOAD_H_ -#define NOTIFY_PAYLOAD_H_ - -#include -#include -#include -#include - -/** - * Notify payload length in bytes without any spi and notification data. - * - * @ingroup payloads - */ -#define NOTIFY_PAYLOAD_HEADER_LENGTH 8 - -typedef enum notify_message_type_t notify_message_type_t; - - -/** - * @brief Notify message types. - * - * See IKEv2 RFC 3.10.1. - * - * @ingroup payloads - */ -enum notify_message_type_t { - UNSUPPORTED_CRITICAL_PAYLOAD = 1, - INVALID_IKE_SPI = 4, - INVALID_MAJOR_VERSION = 5, - INVALID_SYNTAX = 7, - INVALID_MESSAGE_ID = 9, - INVALID_SPI = 11, - NO_PROPOSAL_CHOSEN = 14, - INVALID_KE_PAYLOAD = 17, - AUTHENTICATION_FAILED = 24, - SINGLE_PAIR_REQUIRED = 34, - NO_ADDITIONAL_SAS = 35, - INTERNAL_ADDRESS_FAILURE = 36, - FAILED_CP_REQUIRED = 37, - TS_UACCEPTABLE = 38, - INVALID_SELECTORS = 39, - - INITIAL_CONTACT = 16384, - SET_WINDOW_SIZE = 16385 -}; - -/** - * String mappings for notify_message_type_t. - * - * @ingroup payloads - */ -extern mapping_t notify_message_type_m[]; - - -typedef struct notify_payload_t notify_payload_t; - -/** - * @brief Class representing an IKEv2-Notify Payload. - * - * The Notify Payload format is described in Draft section 3.10. - * - * @b Constructors: - * - notify_payload_create() - * - notify_payload_create_from_protocol_and_type() - * - * @todo Build specified constructor/getter for notify's - * - * @ingroup payloads - */ -struct notify_payload_t { - /** - * The payload_t interface. - */ - payload_t payload_interface; - - /** - * @brief Gets the protocol id of this payload. - * - * @param this calling notify_payload_t object - * @return protocol id of this payload - */ - u_int8_t (*get_protocol_id) (notify_payload_t *this); - - /** - * @brief Sets the protocol id of this payload. - * - * @param this calling notify_payload_t object - * @param protocol_id protocol id to set - */ - void (*set_protocol_id) (notify_payload_t *this, u_int8_t protocol_id); - - /** - * @brief Gets the notify message type of this payload. - * - * @param this calling notify_payload_t object - * @return notify message type of this payload - */ - u_int16_t (*get_notify_message_type) (notify_payload_t *this); - - /** - * @brief Sets notify message type of this payload. - * - * @param this calling notify_payload_t object - * @param notify_message_type notify message type to set - */ - void (*set_notify_message_type) (notify_payload_t *this, u_int16_t notify_message_type); - - /** - * @brief Returns the currently set spi of this payload. - * - * @warning Returned data are not copied. - * - * @param this calling notify_payload_t object - * @return chunk_t pointing to the value - */ - chunk_t (*get_spi) (notify_payload_t *this); - - /** - * @brief Sets the spi of this payload. - * - * @warning Value is getting copied. - * - * @param this calling notify_payload_t object - * @param spi chunk_t pointing to the value to set - */ - void (*set_spi) (notify_payload_t *this, chunk_t spi); - - /** - * @brief Returns the currently set notification data of payload. - * - * @warning Returned data are not copied. - * - * @param this calling notify_payload_t object - * @return chunk_t pointing to the value - */ - chunk_t (*get_notification_data) (notify_payload_t *this); - - /** - * @brief Sets the notification data of this payload. - * - * @warning Value is getting copied. - * - * @param this calling notify_payload_t object - * @param notification_data chunk_t pointing to the value to set - */ - void (*set_notification_data) (notify_payload_t *this, chunk_t notification_data); - - /** - * @brief Destroys an notify_payload_t object. - * - * @param this notify_payload_t object to destroy - */ - void (*destroy) (notify_payload_t *this); -}; - -/** - * @brief Creates an empty notify_payload_t object - * - * @return created notify_payload_t object - * - * @ingroup payloads - */ -notify_payload_t *notify_payload_create(void); - -/** - * @brief Creates an notify_payload_t object of specific type for specific protocol id. - * - * @param protocol_id protocol id (IKE, AH or ESP) - * @param notify_message_type notify type (see notify_message_type_t) - * @return notify_payload_t object - * - * @ingroup payloads - */ -notify_payload_t *notify_payload_create_from_protocol_and_type(protocol_id_t protocol_id, notify_message_type_t notify_message_type); - - -#endif /*NOTIFY_PAYLOAD_H_*/ diff --git a/src/charon/charon/encoding/payloads/payload.c b/src/charon/charon/encoding/payloads/payload.c deleted file mode 100644 index b89e80a53..000000000 --- a/src/charon/charon/encoding/payloads/payload.c +++ /dev/null @@ -1,131 +0,0 @@ -/** - * @file payload.c - * - * @brief Generic constructor to the payload_t interface. - * - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 "payload.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * build the mappings for payload_type_t - */ -mapping_t payload_type_m[] = { - {NO_PAYLOAD, "NO_PAYLOAD"}, - {SECURITY_ASSOCIATION, "SECURITY_ASSOCIATION"}, - {KEY_EXCHANGE, "KEY_EXCHANGE"}, - {ID_INITIATOR, "ID_INITIATOR"}, - {ID_RESPONDER, "ID_RESPONDER"}, - {CERTIFICATE, "CERTIFICATE"}, - {CERTIFICATE_REQUEST, "CERTIFICATE_REQUEST"}, - {AUTHENTICATION, "AUTHENTICATION"}, - {NONCE, "NONCE"}, - {NOTIFY, "NOTIFY"}, - {DELETE, "DELETE"}, - {VENDOR_ID, "VENDOR_ID"}, - {TRAFFIC_SELECTOR_INITIATOR, "TRAFFIC_SELECTOR_INITIATOR"}, - {TRAFFIC_SELECTOR_RESPONDER, "TRAFFIC_SELECTOR_RESPONDER"}, - {ENCRYPTED, "ENCRYPTED"}, - {CONFIGURATION, "CONFIGURATION"}, - {EXTENSIBLE_AUTHENTICATION, "EXTENSIBLE_AUTHENTICATION"}, - {HEADER, "HEADER"}, - {PROPOSAL_SUBSTRUCTURE, "PROPOSAL_SUBSTRUCTURE"}, - {TRANSFORM_SUBSTRUCTURE, "TRANSFORM_SUBSTRUCTURE"}, - {TRANSFORM_ATTRIBUTE, "TRANSFORM_ATTRIBUTE"}, - {TRAFFIC_SELECTOR_SUBSTRUCTURE, "TRAFFIC_SELECTOR_SUBSTRUCTURE"}, - {CONFIGURATION_ATTRIBUTE,"CONFIGURATION_ATTRIBUTE"}, - {UNKNOWN_PAYLOAD,"UNKNOWN_PAYLOAD"}, - {MAPPING_END, NULL} -}; - -/* - * see header - */ -payload_t *payload_create(payload_type_t type) -{ - switch (type) - { - case HEADER: - return (payload_t*)ike_header_create(); - case SECURITY_ASSOCIATION: - return (payload_t*)sa_payload_create(); - case PROPOSAL_SUBSTRUCTURE: - return (payload_t*)proposal_substructure_create(); - case TRANSFORM_SUBSTRUCTURE: - return (payload_t*)transform_substructure_create(); - case TRANSFORM_ATTRIBUTE: - return (payload_t*)transform_attribute_create(); - case NONCE: - return (payload_t*)nonce_payload_create(); - case ID_INITIATOR: - return (payload_t*)id_payload_create(TRUE); - case ID_RESPONDER: - return (payload_t*)id_payload_create(FALSE); - case AUTHENTICATION: - return (payload_t*)auth_payload_create(); - case CERTIFICATE: - return (payload_t*)cert_payload_create(); - case CERTIFICATE_REQUEST: - return (payload_t*)certreq_payload_create(); - case TRAFFIC_SELECTOR_SUBSTRUCTURE: - return (payload_t*)traffic_selector_substructure_create(); - case TRAFFIC_SELECTOR_INITIATOR: - return (payload_t*)ts_payload_create(TRUE); - case TRAFFIC_SELECTOR_RESPONDER: - return (payload_t*)ts_payload_create(FALSE); - case KEY_EXCHANGE: - return (payload_t*)ke_payload_create(); - case NOTIFY: - return (payload_t*)notify_payload_create(); - case DELETE: - return (payload_t*)delete_payload_create(); - case VENDOR_ID: - return (payload_t*)vendor_id_payload_create(); - case CONFIGURATION: - return (payload_t*)cp_payload_create(); - case CONFIGURATION_ATTRIBUTE: - return (payload_t*)configuration_attribute_create(); - case EXTENSIBLE_AUTHENTICATION: - return (payload_t*)eap_payload_create(); - case ENCRYPTED: - return (payload_t*)encryption_payload_create(); - default: - return (payload_t*)unknown_payload_create(); - } -} - diff --git a/src/charon/charon/encoding/payloads/payload.h b/src/charon/charon/encoding/payloads/payload.h deleted file mode 100644 index fc3457832..000000000 --- a/src/charon/charon/encoding/payloads/payload.h +++ /dev/null @@ -1,279 +0,0 @@ -/** - * @file payload.h - * - * @brief Interface payload_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef PAYLOAD_H_ -#define PAYLOAD_H_ - -#include -#include -#include - - -typedef enum payload_type_t payload_type_t; - -/** - * @brief Payload-Types of a IKEv2-Message. - * - * Header and substructures are also defined as - * payload types with values from PRIVATE USE space. - * - * @ingroup payloads - */ -enum payload_type_t{ - - /** - * End of payload list in next_payload - */ - NO_PAYLOAD = 0, - - /** - * The security association (SA) payload containing proposals. - */ - SECURITY_ASSOCIATION = 33, - - /** - * The key exchange (KE) payload containing diffie-hellman values. - */ - KEY_EXCHANGE = 34, - - /** - * Identification for the original initiator (IDi). - */ - ID_INITIATOR = 35, - - /** - * Identification for the original responder (IDr). - */ - ID_RESPONDER = 36, - - /** - * Certificate payload with certificates (CERT). - */ - CERTIFICATE = 37, - - /** - * Certificate request payload (CERTREQ). - */ - CERTIFICATE_REQUEST = 38, - - /** - * Authentication payload contains auth data (AUTH). - */ - AUTHENTICATION = 39, - - /** - * Nonces, for initator and responder (Ni, Nr, N) - */ - NONCE = 40, - - /** - * Notif paylaod (N). - */ - NOTIFY = 41, - - /** - * Delete payload (D) - */ - DELETE = 42, - - /** - * Vendor id paylpoad (V). - */ - VENDOR_ID = 43, - - /** - * Traffic selector for the original initiator (TSi). - */ - TRAFFIC_SELECTOR_INITIATOR = 44, - - /** - * Traffic selector for the original responser (TSr). - */ - TRAFFIC_SELECTOR_RESPONDER = 45, - - /** - * Encryption payload, contains other payloads (E). - */ - ENCRYPTED = 46, - - /** - * Configuration payload (CP). - */ - CONFIGURATION = 47, - - /** - * Extensible authentication payload (EAP). - */ - EXTENSIBLE_AUTHENTICATION = 48, - - /** - * Header has a value of PRIVATE USE space. - * - * This payload type is not send over wire and just - * used internally to handle IKEv2-Header like a payload. - */ - HEADER = 140, - - /** - * PROPOSAL_SUBSTRUCTURE has a value of PRIVATE USE space. - * - * This payload type is not send over wire and just - * used internally to handle a proposal substructure like a payload. - */ - PROPOSAL_SUBSTRUCTURE = 141, - - /** - * TRANSFORM_SUBSTRUCTURE has a value of PRIVATE USE space. - * - * This payload type is not send over wire and just - * used internally to handle a transform substructure like a payload. - */ - TRANSFORM_SUBSTRUCTURE = 142, - - /** - * TRANSFORM_ATTRIBUTE has a value of PRIVATE USE space. - * - * This payload type is not send over wire and just - * used internally to handle a transform attribute like a payload. - */ - TRANSFORM_ATTRIBUTE = 143, - - /** - * TRAFFIC_SELECTOR_SUBSTRUCTURE has a value of PRIVATE USE space. - * - * This payload type is not send over wire and just - * used internally to handle a transform selector like a payload. - */ - TRAFFIC_SELECTOR_SUBSTRUCTURE = 144, - - /** - * CONFIGURATION_ATTRIBUTE has a value of PRIVATE USE space. - * - * This payload type is not send 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 send over wire and just - * used internally to handle a unknown payload. - */ - UNKNOWN_PAYLOAD = 146, -}; - - -/** - * String mappings for payload_type_t. - */ -extern mapping_t payload_type_m[]; - - -typedef struct payload_t payload_t; - -/** - * @brief Generic interface for all payload types (incl.header and substructures). - * - * To handle all kinds of payloads on a generic way, this interface must - * be implemented by every payload. This allows parser_t/generator_t a simple - * handling of all payloads. - * - * @b Constructors: - * - payload_create() with the payload to instanciate. - * - * @ingroup payloads - */ -struct payload_t { - - /** - * @brief Get encoding rules for this payload. - * - * @param this calling object - * @param[out] rules location to store pointer of first rule - * @param[out] rule_count location to store number of rules - */ - void (*get_encoding_rules) (payload_t *this, encoding_rule_t **rules, size_t *rule_count); - - /** - * @brief Get type of payload. - * - * @param this calling object - * @return type of this payload - */ - payload_type_t (*get_type) (payload_t *this); - - /** - * @brief Get type of next payload or NO_PAYLOAD (0) if this is the last one. - * - * @param this calling object - * @return type of next payload - */ - payload_type_t (*get_next_type) (payload_t *this); - - /** - * @brief Set type of next payload. - * - * @param this calling object - * @param type type of next payload - */ - void (*set_next_type) (payload_t *this,payload_type_t type); - - /** - * @brief Get length of payload. - * - * @param this calling object - * @return length of this payload - */ - size_t (*get_length) (payload_t *this); - - /** - * @brief Verifies payload structure and makes consistence check. - * - * @param this calling object - * @return - * - SUCCESS - * - FAILED if consistence not given - */ - status_t (*verify) (payload_t *this); - - /** - * @brief Destroys a payload and all included substructures. - * - * @param this payload to destroy - */ - void (*destroy) (payload_t *this); -}; - -/** - * @brief Create an empty payload. - * - * Useful for the parser, who wants a generic constructor for all payloads. - * It supports all payload_t methods. If a payload type is not known, - * an unknwon_paylod is created with the chunk of data in it. - * - * @param type type of the payload to create - * @return payload_t object - */ -payload_t *payload_create(payload_type_t type); - -#endif /*PAYLOAD_H_*/ diff --git a/src/charon/charon/encoding/payloads/proposal_substructure.c b/src/charon/charon/encoding/payloads/proposal_substructure.c deleted file mode 100644 index cb3c695b2..000000000 --- a/src/charon/charon/encoding/payloads/proposal_substructure.c +++ /dev/null @@ -1,629 +0,0 @@ -/** - * @file proposal_substructure.h - * - * @brief Implementation of proposal_substructure_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 - -#include "proposal_substructure.h" - -#include -#include -#include -#include - - -/** - * IKEv1 Value for a proposal payload. - */ -#define PROPOSAL_TYPE_VALUE 2 - - -typedef struct private_proposal_substructure_t private_proposal_substructure_t; - -/** - * Private data of an proposal_substructure_t object. - * - */ -struct private_proposal_substructure_t { - /** - * Public proposal_substructure_t interface. - */ - proposal_substructure_t public; - - /** - * Next payload type. - */ - u_int8_t next_payload; - - /** - * Length of this payload. - */ - u_int16_t proposal_length; - - /** - * Proposal number. - */ - u_int8_t proposal_number; - - /** - * Protocol ID. - */ - u_int8_t protocol_id; - - /** - * SPI size of the following SPI. - */ - u_int8_t spi_size; - - /** - * Number of transforms. - */ - u_int8_t transforms_count; - - /** - * SPI is stored as chunk. - */ - chunk_t spi; - - /** - * Transforms are stored in a linked_list_t. - */ - linked_list_t * transforms; - - /** - * @brief Computes the length of this substructure. - * - * @param this calling private_proposal_substructure_t object - */ - void (*compute_length) (private_proposal_substructure_t *this); -}; - -/** - * Encoding rules to parse or generate a Proposal substructure. - * - * The defined offsets are the positions in a object of type - * private_proposal_substructure_t. - * - */ -encoding_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 }, - /* Length of the whole proposal substructure payload*/ - { PAYLOAD_LENGTH, offsetof(private_proposal_substructure_t, proposal_length) }, - /* proposal number is a number of 8 bit */ - { U_INT_8, offsetof(private_proposal_substructure_t, proposal_number) }, - /* protocol ID is a number of 8 bit */ - { U_INT_8, offsetof(private_proposal_substructure_t, protocol_id) }, - /* SPI Size has its own type */ - { SPI_SIZE, offsetof(private_proposal_substructure_t, spi_size) }, - /* Number of transforms is a number of 8 bit */ - { U_INT_8, offsetof(private_proposal_substructure_t, transforms_count) }, - /* SPI is a chunk of variable size*/ - { SPI, offsetof(private_proposal_substructure_t, spi) }, - /* Transforms are stored in a transform substructure, - offset points to a linked_list_t pointer */ - { TRANSFORMS, offsetof(private_proposal_substructure_t, transforms) } -}; - -/* - 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 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! 0 (last) or 2 ! RESERVED ! Proposal Length ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! Proposal # ! Protocol ID ! SPI Size !# of Transforms! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ~ SPI (variable) ~ - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! ! - ~ ~ - ! ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -*/ - -/** - * Implementation of payload_t.verify. - */ -static status_t verify(private_proposal_substructure_t *this) -{ - status_t status = SUCCESS; - iterator_t *iterator; - - if ((this->next_payload != NO_PAYLOAD) && (this->next_payload != 2)) - { - /* must be 0 or 2 */ - return FAILED; - } - if (this->transforms_count != this->transforms->get_count(this->transforms)) - { - /* must be the same! */ - return FAILED; - } - - if ((this->protocol_id == 0) || (this->protocol_id >= 4)) - { - /* reserved are not supported */ - return FAILED; - } - - iterator = this->transforms->create_iterator(this->transforms,TRUE); - - while(iterator->has_next(iterator)) - { - payload_t *current_transform; - iterator->current(iterator,(void **)¤t_transform); - - status = current_transform->verify(current_transform); - if (status != SUCCESS) - { - break; - } - } - - iterator->destroy(iterator); - - - /* proposal number is checked in SA payload */ - return status; -} - -/** - * Implementation of payload_t.get_encoding_rules. - */ -static void get_encoding_rules(private_proposal_substructure_t *this, encoding_rule_t **rules, size_t *rule_count) -{ - *rules = proposal_substructure_encodings; - *rule_count = sizeof(proposal_substructure_encodings) / sizeof(encoding_rule_t); -} - -/** - * Implementation of payload_t.get_type. - */ -static payload_type_t get_type(private_proposal_substructure_t *this) -{ - return PROPOSAL_SUBSTRUCTURE; -} - -/** - * Implementation of payload_t.get_next_type. - */ -static payload_type_t get_next_type(private_proposal_substructure_t *this) -{ - return (this->next_payload); -} - -/** - * Implementation of payload_t.set_next_type. - */ -static void set_next_type(private_proposal_substructure_t *this,payload_type_t type) -{ -} - -/** - * Implementation of payload_t.get_length. - */ -static size_t get_length(private_proposal_substructure_t *this) -{ - this->compute_length(this); - return this->proposal_length; -} - -/** - * Implementation of proposal_substructure_t.create_transform_substructure_iterator. - */ -static iterator_t *create_transform_substructure_iterator (private_proposal_substructure_t *this,bool forward) -{ - return (this->transforms->create_iterator(this->transforms,forward)); -} - -/** - * Implementation of proposal_substructure_t.add_transform_substructure. - */ -static void add_transform_substructure (private_proposal_substructure_t *this,transform_substructure_t *transform) -{ - status_t status; - if (this->transforms->get_count(this->transforms) > 0) - { - transform_substructure_t *last_transform; - status = this->transforms->get_last(this->transforms,(void **) &last_transform); - /* last transform is now not anymore last one */ - last_transform->set_is_last_transform(last_transform,FALSE); - - } - transform->set_is_last_transform(transform,TRUE); - - this->transforms->insert_last(this->transforms,(void *) transform); - this->compute_length(this); -} - -/** - * Implementation of proposal_substructure_t.proposal_substructure_t. - */ -static void set_is_last_proposal (private_proposal_substructure_t *this, bool is_last) -{ - this->next_payload = (is_last) ? 0: PROPOSAL_TYPE_VALUE; -} - - -/** - * Implementation of proposal_substructure_t.set_proposal_number. - */ -static void set_proposal_number(private_proposal_substructure_t *this,u_int8_t proposal_number) -{ - this->proposal_number = proposal_number; -} - -/** - * Implementation of proposal_substructure_t.get_proposal_number. - */ -static u_int8_t get_proposal_number (private_proposal_substructure_t *this) -{ - return (this->proposal_number); -} - -/** - * Implementation of proposal_substructure_t.set_protocol_id. - */ -static void set_protocol_id(private_proposal_substructure_t *this,u_int8_t protocol_id) -{ - this->protocol_id = protocol_id; -} - -/** - * Implementation of proposal_substructure_t.get_protocol_id. - */ -static u_int8_t get_protocol_id (private_proposal_substructure_t *this) -{ - return (this->protocol_id); -} - -/** - * Implementation of proposal_substructure_t.set_spi. - */ -static void set_spi (private_proposal_substructure_t *this, chunk_t spi) -{ - /* first delete already set spi value */ - if (this->spi.ptr != NULL) - { - free(this->spi.ptr); - this->spi.ptr = NULL; - this->spi.len = 0; - this->compute_length(this); - } - - this->spi.ptr = clalloc(spi.ptr,spi.len); - this->spi.len = spi.len; - this->spi_size = spi.len; - this->compute_length(this); -} - -/** - * Implementation of proposal_substructure_t.get_spi. - */ -static chunk_t get_spi (private_proposal_substructure_t *this) -{ - chunk_t spi; - spi.ptr = this->spi.ptr; - spi.len = this->spi.len; - - return spi; -} - -/** - * Implementation of proposal_substructure_t.get_info_for_transform_type. - */ -static status_t get_info_for_transform_type (private_proposal_substructure_t *this,transform_type_t type, u_int16_t *transform_id, u_int16_t *key_length) -{ - iterator_t *iterator; - status_t status; - u_int16_t found_transform_id; - u_int16_t found_key_length; - - iterator = this->transforms->create_iterator(this->transforms,TRUE); - - while (iterator->has_next(iterator)) - { - transform_substructure_t *current_transform; - status = iterator->current(iterator,(void **) ¤t_transform); - if (status != SUCCESS) - { - break; - } - if (current_transform->get_transform_type(current_transform) == type) - { - /* now get data for specific type */ - found_transform_id = current_transform->get_transform_id(current_transform); - status = current_transform->get_key_length(current_transform,&found_key_length); - *transform_id = found_transform_id; - *key_length = found_key_length; - iterator->destroy(iterator); - return status; - } - } - iterator->destroy(iterator); - return NOT_FOUND; -} - -/** - * Implementation of private_proposal_substructure_t.compute_length. - */ -static void compute_length (private_proposal_substructure_t *this) -{ - iterator_t *iterator; - size_t transforms_count = 0; - size_t length = PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH; - iterator = this->transforms->create_iterator(this->transforms,TRUE); - while (iterator->has_next(iterator)) - { - payload_t * current_transform; - iterator->current(iterator,(void **) ¤t_transform); - length += current_transform->get_length(current_transform); - transforms_count++; - } - iterator->destroy(iterator); - - length += this->spi.len; - this->transforms_count = transforms_count; - this->proposal_length = length; -} - -/** - * Implementation of proposal_substructure_t.get_transform_count. - */ -static size_t get_transform_count (private_proposal_substructure_t *this) -{ - return this->transforms->get_count(this->transforms); -} - -/** - * Implementation of proposal_substructure_t.get_spi_size. - */ -static size_t get_spi_size (private_proposal_substructure_t *this) -{ - return this->spi.len; -} - -/** - * Implementation of proposal_substructure_t.add_to_proposal. - */ -void add_to_proposal(private_proposal_substructure_t *this, proposal_t *proposal) -{ - iterator_t *iterator = this->transforms->create_iterator(this->transforms, TRUE); - u_int32_t spi; - - - while (iterator->has_next(iterator)) - { - transform_substructure_t *transform; - transform_type_t transform_type; - u_int16_t transform_id; - u_int16_t key_length = 0; - - iterator->current(iterator, (void**)&transform); - - transform_type = transform->get_transform_type(transform); - transform_id = transform->get_transform_id(transform); - transform->get_key_length(transform, &key_length); - - proposal->add_algorithm(proposal, this->protocol_id, transform_type, transform_id, key_length); - } - iterator->destroy(iterator); - - spi = *((u_int32_t*)this->spi.ptr); - - proposal->set_spi(proposal, this->protocol_id, spi); -} - -/** - * Implementation of proposal_substructure_t.clone. - */ -static private_proposal_substructure_t* clone(private_proposal_substructure_t *this) -{ - private_proposal_substructure_t * new_clone; - iterator_t *transforms; - - new_clone = (private_proposal_substructure_t *) proposal_substructure_create(); - - new_clone->next_payload = this->next_payload; - new_clone->proposal_number = this->proposal_number; - new_clone->protocol_id = this->protocol_id; - new_clone->spi_size = this->spi_size; - if (this->spi.ptr != NULL) - { - new_clone->spi.ptr = clalloc(this->spi.ptr,this->spi.len); - new_clone->spi.len = this->spi.len; - } - - transforms = this->transforms->create_iterator(this->transforms,FALSE); - - while (transforms->has_next(transforms)) - { - transform_substructure_t *current_transform; - transform_substructure_t *current_transform_clone; - - transforms->current(transforms,(void **) ¤t_transform); - - current_transform_clone = current_transform->clone(current_transform); - - new_clone->public.add_transform_substructure(&(new_clone->public),current_transform_clone); - } - - transforms->destroy(transforms); - - return new_clone; -} - -/** - * Implements payload_t's and proposal_substructure_t's destroy function. - * See #payload_s.destroy or proposal_substructure_s.destroy for description. - */ -static status_t destroy(private_proposal_substructure_t *this) -{ - /* all proposals are getting destroyed */ - while (this->transforms->get_count(this->transforms) > 0) - { - transform_substructure_t *current_transform; - if (this->transforms->remove_last(this->transforms,(void **)¤t_transform) != SUCCESS) - { - break; - } - current_transform->destroy(current_transform); - } - this->transforms->destroy(this->transforms); - - if (this->spi.ptr != NULL) - { - free(this->spi.ptr); - } - - free(this); - - return SUCCESS; -} - -/* - * Described in header. - */ -proposal_substructure_t *proposal_substructure_create() -{ - private_proposal_substructure_t *this = malloc_thing(private_proposal_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_type; - this->public.payload_interface.destroy = (void (*) (payload_t *))destroy; - - - /* public functions */ - this->public.create_transform_substructure_iterator = (iterator_t* (*) (proposal_substructure_t *,bool)) create_transform_substructure_iterator; - this->public.add_transform_substructure = (void (*) (proposal_substructure_t *,transform_substructure_t *)) add_transform_substructure; - this->public.set_proposal_number = (void (*) (proposal_substructure_t *,u_int8_t))set_proposal_number; - this->public.get_proposal_number = (u_int8_t (*) (proposal_substructure_t *)) get_proposal_number; - this->public.set_protocol_id = (void (*) (proposal_substructure_t *,u_int8_t))set_protocol_id; - this->public.get_protocol_id = (u_int8_t (*) (proposal_substructure_t *)) get_protocol_id; - this->public.get_info_for_transform_type = (status_t (*) (proposal_substructure_t *,transform_type_t,u_int16_t *, u_int16_t *))get_info_for_transform_type; - this->public.set_is_last_proposal = (void (*) (proposal_substructure_t *,bool)) set_is_last_proposal; - this->public.add_to_proposal = (void (*) (proposal_substructure_t*,proposal_t*))add_to_proposal; - this->public.set_spi = (void (*) (proposal_substructure_t *,chunk_t))set_spi; - this->public.get_spi = (chunk_t (*) (proposal_substructure_t *)) get_spi; - this->public.get_transform_count = (size_t (*) (proposal_substructure_t *)) get_transform_count; - this->public.get_spi_size = (size_t (*) (proposal_substructure_t *)) get_spi_size; - this->public.clone = (proposal_substructure_t * (*) (proposal_substructure_t *)) clone; - this->public.destroy = (void (*) (proposal_substructure_t *)) destroy; - - /* private functions */ - this->compute_length = compute_length; - - /* set default values of the fields */ - this->next_payload = NO_PAYLOAD; - this->proposal_length = 0; - this->proposal_number = 0; - this->protocol_id = 0; - this->transforms_count = 0; - this->spi_size = 0; - this->spi.ptr = NULL; - this->spi.len = 0; - - this->transforms = linked_list_create(); - - return (&(this->public)); -} - -/* - * Described in header. - */ -proposal_substructure_t *proposal_substructure_create_from_proposal(proposal_t *proposal, protocol_id_t proto) -{ - private_proposal_substructure_t *this = (private_proposal_substructure_t*)proposal_substructure_create(); - iterator_t *iterator; - algorithm_t *algo; - transform_substructure_t *transform; - - /* encryption algorithm is only availble in ESP */ - iterator = proposal->create_algorithm_iterator(proposal, proto, ENCRYPTION_ALGORITHM); - while (iterator->has_next(iterator)) - { - iterator->current(iterator, (void**)&algo); - transform = transform_substructure_create_type(ENCRYPTION_ALGORITHM, algo->algorithm, algo->key_size); - this->public.add_transform_substructure(&(this->public), transform); - } - iterator->destroy(iterator); - - /* integrity algorithms */ - iterator = proposal->create_algorithm_iterator(proposal, proto, INTEGRITY_ALGORITHM); - while (iterator->has_next(iterator)) - { - algorithm_t *algo; - iterator->current(iterator, (void**)&algo); - transform = transform_substructure_create_type(INTEGRITY_ALGORITHM, algo->algorithm, algo->key_size); - this->public.add_transform_substructure(&(this->public), transform); - } - iterator->destroy(iterator); - - /* prf algorithms */ - iterator = proposal->create_algorithm_iterator(proposal, proto, PSEUDO_RANDOM_FUNCTION); - while (iterator->has_next(iterator)) - { - algorithm_t *algo; - iterator->current(iterator, (void**)&algo); - transform = transform_substructure_create_type(PSEUDO_RANDOM_FUNCTION, algo->algorithm, algo->key_size); - this->public.add_transform_substructure(&(this->public), transform); - } - iterator->destroy(iterator); - - /* dh groups */ - iterator = proposal->create_algorithm_iterator(proposal, proto, DIFFIE_HELLMAN_GROUP); - while (iterator->has_next(iterator)) - { - algorithm_t *algo; - iterator->current(iterator, (void**)&algo); - transform = transform_substructure_create_type(DIFFIE_HELLMAN_GROUP, algo->algorithm, 0); - this->public.add_transform_substructure(&(this->public), transform); - } - iterator->destroy(iterator); - - /* extended sequence numbers */ - iterator = proposal->create_algorithm_iterator(proposal, proto, EXTENDED_SEQUENCE_NUMBERS); - while (iterator->has_next(iterator)) - { - algorithm_t *algo; - iterator->current(iterator, (void**)&algo); - transform = transform_substructure_create_type(EXTENDED_SEQUENCE_NUMBERS, algo->algorithm, 0); - this->public.add_transform_substructure(&(this->public), transform); - } - iterator->destroy(iterator); - - /* take over general infos */ - this->spi_size = proto == PROTO_IKE ? 8 : 4; - this->spi.len = this->spi_size; - this->spi.ptr = malloc(this->spi_size); - *((u_int32_t*)this->spi.ptr) = proposal->get_spi(proposal, proto); - this->proposal_number = proposal->get_number(proposal); - this->protocol_id = proto; - - return &(this->public); -} diff --git a/src/charon/charon/encoding/payloads/proposal_substructure.h b/src/charon/charon/encoding/payloads/proposal_substructure.h deleted file mode 100644 index a59f9532f..000000000 --- a/src/charon/charon/encoding/payloads/proposal_substructure.h +++ /dev/null @@ -1,231 +0,0 @@ -/** - * @file proposal_substructure.h - * - * @brief Interface of proposal_substructure_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef PROPOSAL_SUBSTRUCTURE_H_ -#define PROPOSAL_SUBSTRUCTURE_H_ - -#include -#include -#include -#include -#include - - -/** - * Length of the proposal substructure header (without spi). - * - * @ingroup payloads - */ -#define PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH 8 - - -typedef struct proposal_substructure_t proposal_substructure_t; - -/** - * @brief Class representing an IKEv2-PROPOSAL SUBSTRUCTURE. - * - * The PROPOSAL SUBSTRUCTURE format is described in RFC section 3.3.1. - * - * @b Constructors: - * - proposal_substructure_create() - * - * @ingroup payloads - */ -struct proposal_substructure_t { - /** - * The payload_t interface. - */ - payload_t payload_interface; - - /** - * @brief Creates an iterator of stored transform_substructure_t objects. - * - * @warning The created iterator has to get destroyed by the caller! - * When deleting any transform over this iterator, call - * get_size to make sure the length and number values are ok. - * - * @param this calling proposal_substructure_t object - * @param forward iterator direction (TRUE: front to end) - * @return created iterator_t object - */ - iterator_t * (*create_transform_substructure_iterator) (proposal_substructure_t *this, bool forward); - - /** - * @brief Adds a transform_substructure_t object to this object. - * - * @warning The added transform_substructure_t object is - * getting destroyed in destroy function of proposal_substructure_t. - * - * @param this calling proposal_substructure_t object - * @param transform transform_substructure_t object to add - */ - void (*add_transform_substructure) (proposal_substructure_t *this,transform_substructure_t *transform); - - /** - * @brief Sets the proposal number of current proposal. - * - * @param this calling proposal_substructure_t object - * @param id proposal number to set - */ - void (*set_proposal_number) (proposal_substructure_t *this,u_int8_t proposal_number); - - /** - * @brief get proposal number of current proposal. - * - * @param this calling proposal_substructure_t object - * @return proposal number of current proposal substructure. - */ - u_int8_t (*get_proposal_number) (proposal_substructure_t *this); - - /** - * @brief get the number of transforms in current proposal. - * - * @param this calling proposal_substructure_t object - * @return transform count in current proposal - */ - size_t (*get_transform_count) (proposal_substructure_t *this); - - /** - * @brief get size of the set spi in bytes. - * - * @param this calling proposal_substructure_t object - * @return size of the spi in bytes - */ - size_t (*get_spi_size) (proposal_substructure_t *this); - - /** - * @brief Sets the protocol id of current proposal. - * - * @param this calling proposal_substructure_t object - * @param id protocol id to set - */ - void (*set_protocol_id) (proposal_substructure_t *this,u_int8_t protocol_id); - - /** - * @brief get protocol id of current proposal. - * - * @param this calling proposal_substructure_t object - * @return protocol id of current proposal substructure. - */ - u_int8_t (*get_protocol_id) (proposal_substructure_t *this); - - /** - * @brief Get informations for a specific transform type. - * - * @param this calling proposal_substructure_t object - * @param type type to get informations for - * @param transform_id transform id of the specific type - * @param key_length key length of the specific key length transform attribute - * @return - * - SUCCESS if transform type is part of this proposal and - * all data (incl. key length) could be fetched - * - NOT_FOUND if transform type is not part of this proposal - */ - status_t (*get_info_for_transform_type) (proposal_substructure_t *this,transform_type_t type, u_int16_t *transform_id, u_int16_t *key_length); - - /** - * @brief Sets the next_payload field of this substructure - * - * If this is the last proposal, next payload field is set to 0, - * otherwise to 2 - * - * @param this calling proposal_substructure_t object - * @param is_last When TRUE, next payload field is set to 0, otherwise to 2 - */ - void (*set_is_last_proposal) (proposal_substructure_t *this, bool is_last); - - /** - * @brief Returns the currently set SPI of this proposal. - * - * @warning Returned data are not copied - * - * @param this calling proposal_substructure_t object - * @return chunk_t pointing to the value - */ - chunk_t (*get_spi) (proposal_substructure_t *this); - - /** - * @brief Sets the SPI of the current proposal. - * - * @warning SPI is getting copied - * - * @param this calling proposal_substructure_t object - * @param spi chunk_t pointing to the value to set - */ - void (*set_spi) (proposal_substructure_t *this, chunk_t spi); - - /** - * @brief Add this proposal_substructure to a proposal. - * - * Since a proposal_t may contain the data of multiple - * proposal_sbustructure_t's, it may be necessary to call - * the function multiple times with the same proposal. - * - * @param this calling proposal_substructure_t object - * @param proposal proposal where the data should be added - */ - void (*add_to_proposal) (proposal_substructure_t *this, proposal_t *proposal); - - /** - * @brief Clones an proposal_substructure_t object. - * - * @param this proposal_substructure_t object to clone - * @return cloned object - */ - proposal_substructure_t* (*clone) (proposal_substructure_t *this); - - /** - * @brief Destroys an proposal_substructure_t object. - * - * @param this proposal_substructure_t object to destroy - */ - void (*destroy) (proposal_substructure_t *this); -}; - -/** - * @brief Creates an empty proposal_substructure_t object - * - * @return proposal_substructure_t object - * - * @ingroup payloads - */ -proposal_substructure_t *proposal_substructure_create(void); - -/** - * @brief Creates a proposal substructure from a proposal. - * - * Since a child proposal may contain data for both AH and ESP, - * the protocol must be specified. If the proposal does not contain - * data for proto, NULL is returned. Call twice, once with AH, once - * with ESP, with the same proposal to build the two substructures - * for it. - * - * @param proposal proposal to build a substruct out of it - * @param proto for which protocol the substructure should be built - * @return proposal_substructure_t object, or NULL - * - * @ingroup payloads - */ -proposal_substructure_t *proposal_substructure_create_from_proposal(proposal_t *proposal, protocol_id_t proto); - - -#endif /*PROPOSAL_SUBSTRUCTURE_H_*/ diff --git a/src/charon/charon/encoding/payloads/sa_payload.c b/src/charon/charon/encoding/payloads/sa_payload.c deleted file mode 100644 index 81b4e6709..000000000 --- a/src/charon/charon/encoding/payloads/sa_payload.c +++ /dev/null @@ -1,390 +0,0 @@ -/** - * @file sa_payload.c - * - * @brief Implementation of sa_payload_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 - -#include "sa_payload.h" - -#include -#include - - -typedef struct private_sa_payload_t private_sa_payload_t; - -/** - * Private data of an sa_payload_t object. - * - */ -struct private_sa_payload_t { - /** - * Public sa_payload_t interface. - */ - sa_payload_t public; - - /** - * Next payload type. - */ - u_int8_t next_payload; - - /** - * Critical flag. - */ - bool critical; - - /** - * Length of this payload. - */ - u_int16_t payload_length; - - /** - * Proposals in this payload are stored in a linked_list_t. - */ - linked_list_t * proposals; - - /** - * @brief Computes the length of this payload. - * - * @param this calling private_sa_payload_t object - */ - void (*compute_length) (private_sa_payload_t *this); -}; - -/** - * Encoding rules to parse or generate a IKEv2-SA Payload - * - * The defined offsets are the positions in a object of type - * private_sa_payload_t. - * - */ -encoding_rule_t sa_payload_encodings[] = { - /* 1 Byte next payload type, stored in the field next_payload */ - { U_INT_8, offsetof(private_sa_payload_t, next_payload) }, - /* the critical bit */ - { FLAG, offsetof(private_sa_payload_t, critical) }, - /* 7 Bit reserved bits, nowhere stored */ - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - /* Length of the whole SA payload*/ - { PAYLOAD_LENGTH, offsetof(private_sa_payload_t, payload_length) }, - /* Proposals are stored in a proposal substructure, - offset points to a linked_list_t pointer */ - { PROPOSALS, offsetof(private_sa_payload_t, proposals) } -}; - -/* - 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! Next Payload !C! RESERVED ! Payload Length ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! ! - ~ ~ - ! ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -*/ - -/** - * Implementation of payload_t.verify. - */ -static status_t verify(private_sa_payload_t *this) -{ - int proposal_number = 1; - status_t status = SUCCESS; - iterator_t *iterator; - bool first = TRUE; - - /* check proposal numbering */ - iterator = this->proposals->create_iterator(this->proposals,TRUE); - - while(iterator->has_next(iterator)) - { - proposal_substructure_t *current_proposal; - iterator->current(iterator,(void **)¤t_proposal); - if (current_proposal->get_proposal_number(current_proposal) > proposal_number) - { - if (first) - { - /* first number must be 1 */ - status = FAILED; - break; - } - - if (current_proposal->get_proposal_number(current_proposal) != (proposal_number + 1)) - { - /* must be only one more then previous proposal */ - status = FAILED; - break; - } - } - else if (current_proposal->get_proposal_number(current_proposal) < proposal_number) - { - /* must not be smaller then proceeding one */ - status = FAILED; - break; - } - - status = current_proposal->payload_interface.verify(&(current_proposal->payload_interface)); - if (status != SUCCESS) - { - break; - } - first = FALSE; - } - - iterator->destroy(iterator); - return status; -} - - -/** - * Implementation of payload_t.destroy and sa_payload_t.destroy. - */ -static status_t destroy(private_sa_payload_t *this) -{ - /* all proposals are getting destroyed */ - while (this->proposals->get_count(this->proposals) > 0) - { - proposal_substructure_t *current_proposal; - this->proposals->remove_last(this->proposals,(void **)¤t_proposal); - current_proposal->destroy(current_proposal); - } - this->proposals->destroy(this->proposals); - - free(this); - - return SUCCESS; -} - -/** - * Implementation of payload_t.get_encoding_rules. - */ -static void get_encoding_rules(private_sa_payload_t *this, encoding_rule_t **rules, size_t *rule_count) -{ - *rules = sa_payload_encodings; - *rule_count = sizeof(sa_payload_encodings) / sizeof(encoding_rule_t); -} - -/** - * Implementation of payload_t.get_type. - */ -static payload_type_t get_type(private_sa_payload_t *this) -{ - return SECURITY_ASSOCIATION; -} - -/** - * Implementation of payload_t.get_next_type. - */ -static payload_type_t get_next_type(private_sa_payload_t *this) -{ - return (this->next_payload); -} - -/** - * Implementation of payload_t.set_next_type. - */ -static void set_next_type(private_sa_payload_t *this,payload_type_t type) -{ - this->next_payload = type; -} - -/** - * Implementation of payload_t.get_length. - */ -static size_t get_length(private_sa_payload_t *this) -{ - this->compute_length(this); - return this->payload_length; -} - -/** - * Implementation of sa_payload_t.create_proposal_substructure_iterator. - */ -static iterator_t *create_proposal_substructure_iterator (private_sa_payload_t *this,bool forward) -{ - return this->proposals->create_iterator(this->proposals,forward); -} - -/** - * Implementation of sa_payload_t.add_proposal_substructure. - */ -static void add_proposal_substructure (private_sa_payload_t *this,proposal_substructure_t *proposal) -{ - status_t status; - if (this->proposals->get_count(this->proposals) > 0) - { - proposal_substructure_t *last_proposal; - status = this->proposals->get_last(this->proposals,(void **) &last_proposal); - /* last transform is now not anymore last one */ - last_proposal->set_is_last_proposal(last_proposal,FALSE); - } - proposal->set_is_last_proposal(proposal,TRUE); - - this->proposals->insert_last(this->proposals,(void *) proposal); - this->compute_length(this); -} - -/** - * Implementation of sa_payload_t.add_proposal. - */ -static void add_proposal(private_sa_payload_t *this, proposal_t *proposal) -{ - proposal_substructure_t *substructure; - protocol_id_t proto[2]; - u_int i; - - /* build the substructures for every protocol */ - proposal->get_protocols(proposal, proto); - for (i = 0; i<2; i++) - { - if (proto[i] != PROTO_NONE) - { - substructure = proposal_substructure_create_from_proposal(proposal, proto[i]); - add_proposal_substructure(this, substructure); - } - } -} - -/** - * Implementation of sa_payload_t.get_proposals. - */ -static linked_list_t *get_proposals(private_sa_payload_t *this) -{ - int proposal_struct_number = 0; - iterator_t *iterator; - proposal_t *proposal; - linked_list_t *proposal_list; - - /* this list will hold our proposals */ - proposal_list = linked_list_create(); - - /* iterate over structures, one OR MORE structures will result in a proposal */ - iterator = this->proposals->create_iterator(this->proposals,TRUE); - while (iterator->has_next(iterator)) - { - proposal_substructure_t *proposal_struct; - iterator->current(iterator,(void **)&(proposal_struct)); - - if (proposal_struct->get_proposal_number(proposal_struct) > proposal_struct_number) - { - /* here starts a new proposal, create a new one and add it to the list */ - proposal_struct_number = proposal_struct->get_proposal_number(proposal_struct); - proposal = proposal_create(proposal_struct_number); - proposal_list->insert_last(proposal_list, proposal); - } - /* proposal_substructure_t does the dirty work and builds up the proposal */ - proposal_struct->add_to_proposal(proposal_struct, proposal); - } - iterator->destroy(iterator); - return proposal_list; -} - -/** - * Implementation of private_sa_payload_t.compute_length. - */ -static void compute_length (private_sa_payload_t *this) -{ - iterator_t *iterator; - size_t length = SA_PAYLOAD_HEADER_LENGTH; - iterator = this->proposals->create_iterator(this->proposals,TRUE); - while (iterator->has_next(iterator)) - { - payload_t *current_proposal; - iterator->current(iterator,(void **) ¤t_proposal); - length += current_proposal->get_length(current_proposal); - } - iterator->destroy(iterator); - - this->payload_length = length; -} - -/* - * Described in header. - */ -sa_payload_t *sa_payload_create() -{ - private_sa_payload_t *this = malloc_thing(private_sa_payload_t); - - /* public 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_proposal_substructure_iterator = (iterator_t* (*) (sa_payload_t *,bool)) create_proposal_substructure_iterator; - this->public.add_proposal_substructure = (void (*) (sa_payload_t *,proposal_substructure_t *)) add_proposal_substructure; - this->public.get_proposals = (linked_list_t* (*) (sa_payload_t *)) get_proposals; - this->public.destroy = (void (*) (sa_payload_t *)) destroy; - - /* private functions */ - this->compute_length = compute_length; - - /* set default values of the fields */ - this->critical = FALSE; - this->next_payload = NO_PAYLOAD; - this->payload_length = SA_PAYLOAD_HEADER_LENGTH; - - this->proposals = linked_list_create(); - return (&(this->public)); -} - -/* - * Described in header. - */ -sa_payload_t *sa_payload_create_from_proposal_list(linked_list_t *proposals) -{ - iterator_t *iterator; - proposal_t *proposal; - sa_payload_t *sa_payload = sa_payload_create(); - - /* add every payload from the list */ - iterator = proposals->create_iterator(proposals, TRUE); - while (iterator->has_next(iterator)) - { - iterator->current(iterator, (void**)&proposal); - add_proposal((private_sa_payload_t*)sa_payload, proposal); - } - iterator->destroy(iterator); - - return sa_payload; -} - -/* - * Described in header. - */ -sa_payload_t *sa_payload_create_from_proposal(proposal_t *proposal) -{ - sa_payload_t *sa_payload = sa_payload_create(); - - add_proposal((private_sa_payload_t*)sa_payload, proposal); - - return sa_payload; -} diff --git a/src/charon/charon/encoding/payloads/sa_payload.h b/src/charon/charon/encoding/payloads/sa_payload.h deleted file mode 100644 index 3cf6f5065..000000000 --- a/src/charon/charon/encoding/payloads/sa_payload.h +++ /dev/null @@ -1,140 +0,0 @@ -/** - * @file sa_payload.h - * - * @brief Interface of sa_payload_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef SA_PAYLOAD_H_ -#define SA_PAYLOAD_H_ - -#include -#include -#include -#include - -/** - * SA_PAYLOAD length in bytes without any proposal substructure. - * - * @ingroup payloads - */ -#define SA_PAYLOAD_HEADER_LENGTH 4 - -typedef struct sa_payload_t sa_payload_t; - -/** - * @brief Class representing an IKEv2-SA Payload. - * - * The SA Payload format is described in RFC section 3.3. - * - * @b Constructors: - * - sa_payload_create() - * - sa_payload_create_from_ike_proposals() - * - sa_payload_create_from_proposal() - * - * @todo Add support of algorithms without specified keylength in get_proposals and get_ike_proposals. - * - * @ingroup payloads - */ -struct sa_payload_t { - /** - * The payload_t interface. - */ - payload_t payload_interface; - - /** - * @brief Creates an iterator of stored proposal_substructure_t objects. - * - * @warning The created iterator has to get destroyed by the caller! - * - * @warning When deleting an proposal using this iterator, - * the length of this transform substructure has to be refreshed - * by calling get_length()! - * - * @param this calling sa_payload_t object - * @param[in] forward iterator direction (TRUE: front to end) - * @return created iterator_t object - */ - iterator_t *(*create_proposal_substructure_iterator) (sa_payload_t *this, bool forward); - - /** - * @brief Adds a proposal_substructure_t object to this object. - * - * @warning The added proposal_substructure_t object is - * getting destroyed in destroy function of sa_payload_t. - * - * @param this calling sa_payload_t object - * @param proposal proposal_substructure_t object to add - */ - void (*add_proposal_substructure) (sa_payload_t *this,proposal_substructure_t *proposal); - - /** - * @brief Gets the proposals in this payload as a list. - * - * @return a list containing proposal_t s - */ - linked_list_t *(*get_proposals) (sa_payload_t *this); - - /** - * @brief Add a child proposal (AH/ESP) to the payload. - * - * @param proposal child proposal to add to the payload - */ - void (*add_proposal) (sa_payload_t *this, proposal_t *proposal); - - /** - * @brief Destroys an sa_payload_t object. - * - * @param this sa_payload_t object to destroy - */ - void (*destroy) (sa_payload_t *this); -}; - -/** - * @brief Creates an empty sa_payload_t object - * - * @return created sa_payload_t object - * - * @ingroup payloads - */ -sa_payload_t *sa_payload_create(void); - -/** - * @brief Creates a sa_payload_t object from a list of proposals. - * - * @param proposals list of proposals to build the payload from - * @return sa_payload_t object - * - * @ingroup payloads - */ -sa_payload_t *sa_payload_create_from_proposal_list(linked_list_t *proposals); - -/** - * @brief Creates a sa_payload_t object from a single proposal. - * - * This is only for convenience. Use sa_payload_create_from_proposal_list - * if you want to add more than one proposal. - * - * @param proposal proposal from which the payload should be built. - * @return sa_payload_t object - * - * @ingroup payloads - */ -sa_payload_t *sa_payload_create_from_proposal(proposal_t *proposal); - -#endif /*SA_PAYLOAD_H_*/ diff --git a/src/charon/charon/encoding/payloads/traffic_selector_substructure.c b/src/charon/charon/encoding/payloads/traffic_selector_substructure.c deleted file mode 100644 index c1a461e8a..000000000 --- a/src/charon/charon/encoding/payloads/traffic_selector_substructure.c +++ /dev/null @@ -1,374 +0,0 @@ -/** - * @file traffic_selector_substructure.c - * - * @brief Interface of traffic_selector_substructure_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 "traffic_selector_substructure.h" - -#include -#include - -/** - * String mappings for ts_type_t. - */ -mapping_t ts_type_m[] = { - {TS_IPV4_ADDR_RANGE, "TS_IPV4_ADDR_RANGE"}, - {TS_IPV6_ADDR_RANGE, "TS_IPV6_ADDR_RANGE"}, - {MAPPING_END, NULL} -}; - - -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. - */ - traffic_selector_substructure_t public; - - /** - * Type of traffic selector. - */ - u_int8_t ts_type; - - /** - * IP Protocol ID. - */ - u_int8_t ip_protocol_id; - - /** - * Length of this payload. - */ - u_int16_t payload_length; - - /** - * Start port number. - */ - u_int16_t start_port; - - /** - * End port number. - */ - u_int16_t end_port; - - /** - * Starting address. - */ - chunk_t starting_address; - - /** - * Ending address. - */ - chunk_t ending_address; - - /** - * update length - */ - void (*compute_length) (private_traffic_selector_substructure_t *this); -}; - -/** - * Encoding rules to parse or generate a TS payload - * - * 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) }, - /* 1 Byte 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) }, - /* 2 Byte 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) }, - /* ending address is either 4 or 16 byte */ - { ADDRESS, offsetof(private_traffic_selector_substructure_t, ending_address) } - -}; - -/* - 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 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! TS Type !IP Protocol ID*| Selector Length | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Start Port* | End Port* | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! ! - ~ Starting Address* ~ - ! ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! ! - ~ Ending Address* ~ - ! ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -*/ - -/** - * Implementation of payload_t.verify. - */ -static status_t verify(private_traffic_selector_substructure_t *this) -{ - - if (this->start_port > this->end_port) - { - return FAILED; - } - switch (this->ts_type) - { - case TS_IPV4_ADDR_RANGE: - { - if ((this->starting_address.len != 4) || - (this->ending_address.len != 4)) - { - /* ipv4 address must be 4 bytes long */ - return FAILED; - } - break; - } - case TS_IPV6_ADDR_RANGE: - default: - { - /* not supported ts type */ - return FAILED; - } - } - - - 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) -{ - *rules = traffic_selector_substructure_encodings; - *rule_count = sizeof(traffic_selector_substructure_encodings) / sizeof(encoding_rule_t); -} - -/** - * Implementation of payload_t.get_type. - */ -static payload_type_t get_payload_type(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) -{ - return 0; -} - -/** - * Implementation of payload_t.set_next_type. - */ -static void set_next_type(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) -{ - return this->payload_length; -} - -/** - * Implementation of traffic_selector_substructure_t.get_ts_type. - */ -static ts_type_t get_ts_type (private_traffic_selector_substructure_t *this) -{ - return this->ts_type; -} - -/** - * Implementation of traffic_selector_substructure_t.set_ts_type. - */ -static void set_ts_type (private_traffic_selector_substructure_t *this,ts_type_t ts_type) -{ - this->ts_type = ts_type; -} - -/** - * Implementation of traffic_selector_substructure_t.get_protocol_id. - */ -static u_int8_t get_protocol_id (private_traffic_selector_substructure_t *this) -{ - return this->ip_protocol_id; -} - -/** - * Implementation of traffic_selector_substructure_t.set_protocol_id. - */ -static void set_protocol_id (private_traffic_selector_substructure_t *this,u_int8_t protocol_id) -{ - this->ip_protocol_id = protocol_id; -} - -/** - * Implementation of traffic_selector_substructure_t.get_start_host. - */ -static host_t * get_start_host (private_traffic_selector_substructure_t *this) -{ - return (host_create_from_chunk(AF_INET,this->starting_address, this->start_port)); -} - -/** - * Implementation of traffic_selector_substructure_t.set_start_host. - */ -static void set_start_host (private_traffic_selector_substructure_t *this,host_t *start_host) -{ - this->start_port = start_host->get_port(start_host); - if (this->starting_address.ptr != NULL) - { - chunk_free(&(this->starting_address)); - } - this->starting_address = start_host->get_address_as_chunk(start_host); - this->compute_length(this); -} - -/** - * Implementation of traffic_selector_substructure_t.get_end_host. - */ -static host_t *get_end_host (private_traffic_selector_substructure_t *this) -{ - return (host_create_from_chunk(AF_INET,this->ending_address, this->end_port)); -} - -/** - * Implementation of traffic_selector_substructure_t.set_end_host. - */ -static void set_end_host (private_traffic_selector_substructure_t *this,host_t *end_host) -{ - this->end_port = end_host->get_port(end_host); - if (this->ending_address.ptr != NULL) - { - chunk_free(&(this->ending_address)); - } - this->ending_address = end_host->get_address_as_chunk(end_host); - this->compute_length(this); -} - -/** - * Implementation of traffic_selector_substructure_t.get_traffic_selector. - */ -static traffic_selector_t *get_traffic_selector(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; -} - -/** - * Implementation of private_ts_payload_t.compute_length - */ -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) -{ - free(this->starting_address.ptr); - free(this->ending_address.ptr); - free(this); -} - -/* - * Described in header - */ -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.destroy = (void (*) (traffic_selector_substructure_t *)) destroy; - this->public.get_ts_type = (ts_type_t (*) (traffic_selector_substructure_t *)) get_ts_type; - this->public.set_ts_type = (void (*) (traffic_selector_substructure_t *,ts_type_t)) set_ts_type; - this->public.get_protocol_id = (u_int8_t (*) (traffic_selector_substructure_t *)) get_protocol_id; - this->public.set_protocol_id = (void (*) (traffic_selector_substructure_t *,u_int8_t)) set_protocol_id; - this->public.get_start_host = (host_t * (*) (traffic_selector_substructure_t *))get_start_host; - this->public.set_start_host = (void (*) (traffic_selector_substructure_t *, host_t *))set_start_host; - this->public.get_end_host = (host_t * (*) (traffic_selector_substructure_t *))get_end_host; - this->public.set_end_host = (void (*) (traffic_selector_substructure_t *, host_t *))set_end_host; - this->public.get_traffic_selector = (traffic_selector_t* (*)(traffic_selector_substructure_t*))get_traffic_selector; - - /* private functions */ - this->compute_length = compute_length; - - /* private variables */ - this->payload_length = TRAFFIC_SELECTOR_HEADER_LENGTH; - this->start_port = 0; - this->end_port = 0; - this->starting_address = CHUNK_INITIALIZER; - this->ending_address = CHUNK_INITIALIZER; - this->ip_protocol_id = 0; - /* must be set to be valid */ - this->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) -{ - 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 = traffic_selector->get_from_address(traffic_selector); - this->ending_address = traffic_selector->get_to_address(traffic_selector); - - this->compute_length(this); - - return &(this->public); -} diff --git a/src/charon/charon/encoding/payloads/traffic_selector_substructure.h b/src/charon/charon/encoding/payloads/traffic_selector_substructure.h deleted file mode 100644 index 65b61dccf..000000000 --- a/src/charon/charon/encoding/payloads/traffic_selector_substructure.h +++ /dev/null @@ -1,171 +0,0 @@ -/** - * @file traffic_selector_substructure.h - * - * @brief Interface of traffic_selector_substructure_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - - -#ifndef TRAFFIC_SELECTOR_SUBSTRUCTURE_H_ -#define TRAFFIC_SELECTOR_SUBSTRUCTURE_H_ - -#include -#include -#include -#include - -/** - * Length of a TRAFFIC SELECTOR SUBSTRUCTURE without start and end address. - * - * @ingroup payloads - */ -#define TRAFFIC_SELECTOR_HEADER_LENGTH 8 - -typedef struct traffic_selector_substructure_t traffic_selector_substructure_t; - -/** - * @brief Class representing an IKEv2 TRAFFIC SELECTOR. - * - * The TRAFFIC SELECTOR format is described in RFC section 3.13.1. - * - * @b Constructors: - * - traffic_selector_substructure_create() - * - traffic_selector_substructure_create_from_traffic_selector() - * - * @ingroup payloads - */ -struct traffic_selector_substructure_t { - /** - * The payload_t interface. - */ - payload_t payload_interface; - - /** - * @brief Get the type of Traffic selector. - * - * @param this calling traffic_selector_substructure_t object - * @return type of traffic selector - * - */ - ts_type_t (*get_ts_type) (traffic_selector_substructure_t *this); - - /** - * @brief Set the type of Traffic selector. - * - * @param this calling traffic_selector_substructure_t object - * @param ts_type type of traffic selector - */ - void (*set_ts_type) (traffic_selector_substructure_t *this,ts_type_t ts_type); - - /** - * @brief Get the IP protocol ID of Traffic selector. - * - * @param this calling traffic_selector_substructure_t object - * @return type of traffic selector - * - */ - u_int8_t (*get_protocol_id) (traffic_selector_substructure_t *this); - - /** - * @brief Set the IP protocol ID of Traffic selector - * - * @param this calling traffic_selector_substructure_t object - * @param protocol_id protocol ID of traffic selector - */ - void (*set_protocol_id) (traffic_selector_substructure_t *this,u_int8_t protocol_id); - - /** - * @brief Get the start port and address as host_t object. - * - * Returned host_t object has to get destroyed by the caller. - * - * @param this calling traffic_selector_substructure_t object - * @return start host as host_t object - * - */ - host_t *(*get_start_host) (traffic_selector_substructure_t *this); - - /** - * @brief Set the start port and address as host_t object. - * - * @param this calling traffic_selector_substructure_t object - * @param start_host start host as host_t object - */ - void (*set_start_host) (traffic_selector_substructure_t *this,host_t *start_host); - - /** - * @brief Get the end port and address as host_t object. - * - * Returned host_t object has to get destroyed by the caller. - * - * @param this calling traffic_selector_substructure_t object - * @return end host as host_t object - * - */ - host_t *(*get_end_host) (traffic_selector_substructure_t *this); - - /** - * @brief Set the end port and address as host_t object. - * - * @param this calling traffic_selector_substructure_t object - * @param end_host end host as host_t object - */ - void (*set_end_host) (traffic_selector_substructure_t *this,host_t *end_host); - - /** - * @brief Get a traffic_selector_t from this substructure. - * - * @warning traffic_selector_t must be destroyed after usage. - * - * @param this calling traffic_selector_substructure_t object - * @return contained traffic_selector_t - */ - traffic_selector_t *(*get_traffic_selector) (traffic_selector_substructure_t *this); - - /** - * @brief Destroys an traffic_selector_substructure_t object. - * - * @param this traffic_selector_substructure_t object to destroy - */ - void (*destroy) (traffic_selector_substructure_t *this); -}; - -/** - * @brief Creates an empty traffic_selector_substructure_t object. - * - * TS type is set to default TS_IPV4_ADDR_RANGE! - * - * @return traffic_selector_substructure_t object - * - * @ingroup payloads - */ -traffic_selector_substructure_t *traffic_selector_substructure_create(void); - -/** - * @brief Creates an initialized traffif selector substructure using - * the values from a traffic_selector_t. - * - * @param traffic_selector traffic_selector_t to use for initialization - * @return traffic_selector_substructure_t object - * - * @ingroup payloads - */ -traffic_selector_substructure_t *traffic_selector_substructure_create_from_traffic_selector(traffic_selector_t *traffic_selector); - - -#endif /* /TRAFFIC_SELECTOR_SUBSTRUCTURE_H_ */ diff --git a/src/charon/charon/encoding/payloads/transform_attribute.c b/src/charon/charon/encoding/payloads/transform_attribute.c deleted file mode 100644 index 71cdd59e2..000000000 --- a/src/charon/charon/encoding/payloads/transform_attribute.c +++ /dev/null @@ -1,333 +0,0 @@ -/** - * @file transform_attribute.c - * - * @brief Implementation of transform_attribute_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 -#include - -#include "transform_attribute.h" - -#include -#include - -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. - */ - transform_attribute_t public; - - /** - * Attribute Format Flag. - * - * - TRUE means value is stored in attribute_length_or_value - * - FALSE means value is stored in attribute_value - */ - bool attribute_format; - - /** - * Type of the attribute. - */ - u_int16_t attribute_type; - - /** - * Attribute Length if attribute_format is 0, attribute Value otherwise. - */ - u_int16_t attribute_length_or_value; - - /** - * Attribute value as chunk if attribute_format is 0 (FALSE). - */ - chunk_t attribute_value; -}; - -/** - * String mappings for transform_attribute_type_t. - */ -mapping_t transform_attribute_type_m[] = { - {ATTRIBUTE_UNDEFINED, "ATTRIBUTE_UNDEFINED"}, - {KEY_LENGTH, "KEY_LENGTH"}, - {MAPPING_END, NULL} -}; - -/** - * Encoding rules to parse or generate a Transform attribute. - * - * The defined offsets are the positions in a object of type - * private_transform_attribute_t. - * - */ -encoding_rule_t transform_attribute_encodings[] = { - /* Flag defining the format of this payload */ - { ATTRIBUTE_FORMAT, offsetof(private_transform_attribute_t, attribute_format) }, - /* type of the attribute as 15 bit unsigned integer */ - { ATTRIBUTE_TYPE, offsetof(private_transform_attribute_t, attribute_type) }, - /* Length or value, depending on the attribute format flag */ - { ATTRIBUTE_LENGTH_OR_VALUE, offsetof(private_transform_attribute_t, attribute_length_or_value) }, - /* Value of attribute if attribute format flag is zero */ - { ATTRIBUTE_VALUE, offsetof(private_transform_attribute_t, attribute_value) } -}; - -/* - 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - !A! Attribute Type ! AF=0 Attribute Length ! - !F! ! AF=1 Attribute Value ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! AF=0 Attribute Value ! - ! AF=1 Not Transmitted ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -*/ - -/** - * Implementation of payload_t.verify. - */ -static status_t verify(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) -{ - *rules = transform_attribute_encodings; - *rule_count = sizeof(transform_attribute_encodings) / sizeof(encoding_rule_t); -} - -/** - * Implementation of payload_t.get_type. - */ -static payload_type_t get_type(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) -{ - return (NO_PAYLOAD); -} - -/** - * Implementation of payload_t.set_next_type. - */ -static void set_next_type(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) -{ - if (this->attribute_format == TRUE) - { - /*Attribute size is only 4 byte */ - return 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) -{ - if (this->attribute_value.ptr != NULL) - { - /* free existing value */ - free(this->attribute_value.ptr); - this->attribute_value.ptr = NULL; - this->attribute_value.len = 0; - - } - - if (value.len > 2) - { - this->attribute_value.ptr = clalloc(value.ptr,value.len); - this->attribute_value.len = value.len; - 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); - } -} - -/** - * Implementation of transform_attribute_t.set_value. - */ -static void set_value(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; - - } - this->attribute_length_or_value = value; -} - -/** - * Implementation of transform_attribute_t.get_value_chunk. - */ -static chunk_t get_value_chunk (private_transform_attribute_t *this) -{ - chunk_t value; - - if (this->attribute_format == FALSE) - { - value.ptr = this->attribute_value.ptr; - value.len = this->attribute_value.len; - } - else - { - value.ptr = (void *) &(this->attribute_length_or_value); - value.len = 2; - } - - return value; -} - -/** - * Implementation of transform_attribute_t.get_value. - */ -static u_int16_t get_value (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) -{ - 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) -{ - return this->attribute_type; -} - -/** - * Implementation of transform_attribute_t.clone. - */ -static transform_attribute_t * clone(private_transform_attribute_t *this) -{ - private_transform_attribute_t *new_clone; - - new_clone = (private_transform_attribute_t *) transform_attribute_create(); - - new_clone->attribute_format = this->attribute_format; - new_clone->attribute_type = this->attribute_type; - new_clone->attribute_length_or_value = this->attribute_length_or_value; - - if (!new_clone->attribute_format) - { - new_clone->attribute_value.ptr = clalloc(this->attribute_value.ptr,this->attribute_value.len); - new_clone->attribute_value.len = this->attribute_value.len; - } - - return (transform_attribute_t *) new_clone; -} - -/** - * Implementation of transform_attribute_t.destroy and payload_t.destroy. - */ -static void destroy(private_transform_attribute_t *this) -{ - if (this->attribute_value.ptr != NULL) - { - free(this->attribute_value.ptr); - } - free(this); -} - -/* - * Described in header. - */ -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)); -} - -/* - * Described in header. - */ -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); - return attribute; -} diff --git a/src/charon/charon/encoding/payloads/transform_attribute.h b/src/charon/charon/encoding/payloads/transform_attribute.h deleted file mode 100644 index e2ac946f6..000000000 --- a/src/charon/charon/encoding/payloads/transform_attribute.h +++ /dev/null @@ -1,154 +0,0 @@ -/** - * @file transform_attribute.h - * - * @brief Interface of transform_attribute_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef TRANSFORM_ATTRIBUTE_H_ -#define TRANSFORM_ATTRIBUTE_H_ - -#include -#include - - -typedef enum transform_attribute_type_t transform_attribute_type_t; - -/** - * Type of the attribute, as in IKEv2 RFC 3.3.5. - * - * @ingroup payloads - */ -enum transform_attribute_type_t { - ATTRIBUTE_UNDEFINED = 16384, - KEY_LENGTH = 14 -}; - -/** - * String mappings for transform_attribute_type_t. - * - * @ingroup payloads - */ -extern mapping_t transform_attribute_type_m[]; - -typedef struct transform_attribute_t transform_attribute_t; - -/** - * @brief Class representing an IKEv2- TRANSFORM Attribute. - * - * The TRANSFORM ATTRIBUTE format is described in RFC section 3.3.5. - * - * @ingroup payloads - */ -struct transform_attribute_t { - /** - * The payload_t interface. - */ - payload_t payload_interface; - - /** - * @brief Returns the currently set value of the attribute. - * - * @warning Returned data are not copied. - * - * @param this calling transform_attribute_t object - * @return chunk_t pointing to the value - */ - chunk_t (*get_value_chunk) (transform_attribute_t *this); - - /** - * @brief Returns the currently set value of the attribute. - * - * @warning Returned data are not copied. - * - * @param this calling transform_attribute_t object - * @return value - */ - u_int16_t (*get_value) (transform_attribute_t *this); - - /** - * @brief Sets the value of the attribute. - * - * @warning Value is getting copied. - * - * @param this calling transform_attribute_t object - * @param value chunk_t pointing to the value to set - */ - void (*set_value_chunk) (transform_attribute_t *this, chunk_t value); - - /** - * @brief Sets the value of the attribute. - * - * @param this calling transform_attribute_t object - * @param value value to set - */ - void (*set_value) (transform_attribute_t *this, u_int16_t value); - - /** - * @brief Sets the type of the attribute. - * - * @param this calling transform_attribute_t object - * @param type type to set (most significant bit is set to zero) - */ - void (*set_attribute_type) (transform_attribute_t *this, u_int16_t type); - - /** - * @brief get the type of the attribute. - * - * @param this calling transform_attribute_t object - * @return type of the value - */ - u_int16_t (*get_attribute_type) (transform_attribute_t *this); - - /** - * @brief Clones an transform_attribute_t object. - * - * @param this transform_attribute_t object to clone - * @return cloned transform_attribute_t object - */ - transform_attribute_t * (*clone) (transform_attribute_t *this); - - /** - * @brief Destroys an transform_attribute_t object. - * - * @param this transform_attribute_t object to destroy - */ - void (*destroy) (transform_attribute_t *this); -}; - -/** - * @brief Creates an empty transform_attribute_t object. - * - * @return transform_attribute_t object - * - * @ingroup payloads - */ -transform_attribute_t *transform_attribute_create(void); - -/** - * @brief Creates an transform_attribute_t of type KEY_LENGTH. - * - * @param key_length key length in bytes - * @return transform_attribute_t object - * - * @ingroup payloads - */ -transform_attribute_t *transform_attribute_create_key_length(u_int16_t key_length); - - -#endif /*TRANSFORM_ATTRIBUTE_H_*/ diff --git a/src/charon/charon/encoding/payloads/transform_substructure.c b/src/charon/charon/encoding/payloads/transform_substructure.c deleted file mode 100644 index 350ad63e4..000000000 --- a/src/charon/charon/encoding/payloads/transform_substructure.c +++ /dev/null @@ -1,485 +0,0 @@ -/** - * @file transform_substructure.h - * - * @brief Implementation of transform_substructure_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 - -#include "transform_substructure.h" - -#include -#include -#include -#include - - -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. - */ - transform_substructure_t public; - - /** - * Next payload type. - */ - u_int8_t next_payload; - - - /** - * Length of this payload. - */ - u_int16_t transform_length; - - - /** - * Type of the transform. - */ - u_int8_t transform_type; - - /** - * Transform ID. - */ - u_int16_t transform_id; - - /** - * Transforms Attributes are stored in a linked_list_t. - */ - linked_list_t *attributes; - - /** - * @brief Computes the length of this substructure. - * - * @param this calling private_transform_substructure_t object - */ - void (*compute_length) (private_transform_substructure_t *this); -}; - - -/** - * 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 }, - /* Length of the whole transform substructure*/ - { PAYLOAD_LENGTH, offsetof(private_transform_substructure_t, transform_length) }, - /* transform type is a number of 8 bit */ - { U_INT_8, offsetof(private_transform_substructure_t, transform_type) }, - /* Reserved Byte is skipped */ - { RESERVED_BYTE, 0 }, - /* tranform ID is a number of 8 bit */ - { U_INT_16, offsetof(private_transform_substructure_t, transform_id) }, - /* Attributes are stored in a transform attribute, - offset points to a linked_list_t pointer */ - { TRANSFORM_ATTRIBUTES, offsetof(private_transform_substructure_t, attributes) } -}; - -/* - 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 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! 0 (last) or 3 ! RESERVED ! Transform Length ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - !Transform Type ! RESERVED ! Transform ID ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! ! - ~ Transform Attributes ~ - ! ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -*/ - - -/** - * Implementation of payload_t.verify. - */ -static status_t verify(private_transform_substructure_t *this) -{ - status_t status = SUCCESS; - iterator_t *iterator; - - if ((this->next_payload != NO_PAYLOAD) && (this->next_payload != 3)) - { - /* must be 0 or 3 */ - return FAILED; - } - - switch (this->transform_type) - { - case ENCRYPTION_ALGORITHM: - { - if ((this->transform_id < ENCR_DES_IV64) || (this->transform_id > ENCR_AES_CTR)) - { - return FAILED; - } - break; - } - case PSEUDO_RANDOM_FUNCTION: - { - if ((this->transform_id < PRF_HMAC_MD5) || (this->transform_id > PRF_AES128_CBC)) - { - return FAILED; - } - break; - } - case INTEGRITY_ALGORITHM: - { - if ((this->transform_id < AUTH_HMAC_MD5_96) || (this->transform_id > AUTH_AES_XCBC_96)) - { - return FAILED; - } - break; - } - case DIFFIE_HELLMAN_GROUP: - { - switch (this->transform_id) - { - case MODP_768_BIT: - case MODP_1024_BIT: - case MODP_1536_BIT: - case MODP_2048_BIT: - case MODP_3072_BIT: - case MODP_4096_BIT: - case MODP_6144_BIT: - case MODP_8192_BIT: - { - break; - } - default: - { - return FAILED; - } - } - - - break; - } - case EXTENDED_SEQUENCE_NUMBERS: - { - if ((this->transform_id != NO_EXT_SEQ_NUMBERS) && (this->transform_id != EXT_SEQ_NUMBERS)) - { - return FAILED; - } - break; - } - default: - { - /* not a supported transform type! */ - return FAILED; - } - } - iterator = this->attributes->create_iterator(this->attributes,TRUE); - - while(iterator->has_next(iterator)) - { - payload_t *current_attributes; - iterator->current(iterator,(void **)¤t_attributes); - - status = current_attributes->verify(current_attributes); - if (status != SUCCESS) - { - break; - } - } - - iterator->destroy(iterator); - - - /* 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) -{ - *rules = transform_substructure_encodings; - *rule_count = sizeof(transform_substructure_encodings) / sizeof(encoding_rule_t); -} - -/** - * Implementation of payload_t.get_type. - */ -static payload_type_t get_type(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) -{ - return (this->next_payload); -} - -/** - * Implementation of payload_t.get_length. - */ -static size_t get_length(private_transform_substructure_t *this) -{ - 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); - this->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) -{ -} - -/** - * Implementation of transform_substructure_t.set_transform_type. - */ -static void set_transform_type (private_transform_substructure_t *this,u_int8_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) -{ - 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) -{ - return this->transform_id; -} - -/** - * Implementation of private_transform_substructure_t.compute_length. - */ -static void compute_length (private_transform_substructure_t *this) -{ - iterator_t *iterator; - size_t length = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH; - iterator = this->attributes->create_iterator(this->attributes,TRUE); - while (iterator->has_next(iterator)) - { - payload_t * current_attribute; - iterator->current(iterator,(void **) ¤t_attribute); - length += current_attribute->get_length(current_attribute); - } - iterator->destroy(iterator); - - this->transform_length = length; -} - -/** - * Implementation of transform_substructure_t.clone. - */ -static transform_substructure_t *clone(private_transform_substructure_t *this) -{ - private_transform_substructure_t *new_clone; - iterator_t *attributes; - - new_clone = (private_transform_substructure_t *) transform_substructure_create(); - - new_clone->next_payload = this->next_payload; - new_clone->transform_type = this->transform_type; - new_clone->transform_id = this->transform_id; - - attributes = this->attributes->create_iterator(this->attributes,FALSE); - - while (attributes->has_next(attributes)) - { - transform_attribute_t *current_attribute; - transform_attribute_t *current_attribute_clone; - attributes->current(attributes,(void **) ¤t_attribute); - - current_attribute_clone = current_attribute->clone(current_attribute); - - new_clone->public.add_transform_attribute(&(new_clone->public),current_attribute_clone); - } - - attributes->destroy(attributes); - - return &(new_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) -{ - iterator_t *attributes; - - attributes = this->attributes->create_iterator(this->attributes,TRUE); - - while (attributes->has_next(attributes)) - { - transform_attribute_t *current_attribute; - attributes->current(attributes,(void **) ¤t_attribute); - - if (current_attribute->get_attribute_type(current_attribute) == KEY_LENGTH) - { - *key_length = current_attribute->get_value(current_attribute); - attributes->destroy(attributes); - return SUCCESS; - } - - } - attributes->destroy(attributes); - - return FAILED; -} - - -/** - * Implementation of transform_substructure_t.destroy and payload_t.destroy. - */ -static void destroy(private_transform_substructure_t *this) -{ - /* all proposals are getting destroyed */ - while (this->attributes->get_count(this->attributes) > 0) - { - transform_attribute_t *current_attribute; - this->attributes->remove_last(this->attributes,(void **)¤t_attribute); - current_attribute->destroy(current_attribute); - } - this->attributes->destroy(this->attributes); - - free(this); -} - -/* - * Described in header. - */ -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; - - /* private functions */ - this->compute_length = compute_length; - - /* 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)); -} - -/* - * 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_substructure_t *transform = transform_substructure_create(); - - transform->set_transform_type(transform,transform_type); - transform->set_transform_id(transform,transform_id); - - /* a keylength attribute is only created for AES encryption */ - if (transform_type == ENCRYPTION_ALGORITHM && - transform_id == ENCR_AES_CBC) - { - transform_attribute_t *attribute = transform_attribute_create_key_length(key_length); - transform->add_transform_attribute(transform,attribute); - } - - return transform; -} diff --git a/src/charon/charon/encoding/payloads/transform_substructure.h b/src/charon/charon/encoding/payloads/transform_substructure.h deleted file mode 100644 index 8aac55400..000000000 --- a/src/charon/charon/encoding/payloads/transform_substructure.h +++ /dev/null @@ -1,198 +0,0 @@ -/** - * @file transform_substructure.h - * - * @brief Interface of transform_substructure_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef TRANSFORM_SUBSTRUCTURE_H_ -#define TRANSFORM_SUBSTRUCTURE_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -/** - * IKEv1 Value for a transform payload. - * - * @ingroup payloads - */ -#define TRANSFORM_TYPE_VALUE 3 - -/** - * Length of the transform substructure header in bytes. - * - * @ingroup payloads - */ -#define TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH 8 - - -typedef struct transform_substructure_t transform_substructure_t; - -/** - * @brief Class representing an IKEv2- TRANSFORM SUBSTRUCTURE. - * - * The TRANSFORM SUBSTRUCTURE format is described in RFC section 3.3.2. - * - * @ingroup payloads - */ -struct transform_substructure_t { - /** - * The payload_t interface. - */ - payload_t payload_interface; - - /** - * @brief Creates an iterator of stored transform_attribute_t objects. - * - * @warning The created iterator has to get destroyed by the caller! - * - * @warning When deleting an transform attribute using this iterator, - * the length of this transform substructure has to be refreshed - * by calling get_length()! - * - * @param this calling transform_substructure_t object - * @param[in] forward iterator direction (TRUE: front to end) - * @return created iterator_t object. - */ - iterator_t * (*create_transform_attribute_iterator) (transform_substructure_t *this, bool forward); - - /** - * @brief Adds a transform_attribute_t object to this object. - * - * @warning The added proposal_substructure_t object is - * getting destroyed in destroy function of transform_substructure_t. - * - * @param this calling transform_substructure_t object - * @param proposal transform_attribute_t object to add - */ - void (*add_transform_attribute) (transform_substructure_t *this,transform_attribute_t *attribute); - - /** - * @brief Sets the next_payload field of this substructure - * - * If this is the last transform, next payload field is set to 0, - * otherwise to 3 - * - * @param this calling transform_substructure_t object - * @param is_last When TRUE, next payload field is set to 0, otherwise to 3 - */ - void (*set_is_last_transform) (transform_substructure_t *this, bool is_last); - - /** - * @brief Checks if this is the last transform. - * - * @param this calling transform_substructure_t object - * @return TRUE if this is the last Transform, FALSE otherwise - */ - bool (*get_is_last_transform) (transform_substructure_t *this); - - /** - * @brief Sets transform type of the current transform substructure. - * - * @param this calling transform_substructure_t object - * @param type type value to set - */ - void (*set_transform_type) (transform_substructure_t *this,u_int8_t type); - - /** - * @brief get transform type of the current transform. - * - * @param this calling transform_substructure_t object - * @return Transform type of current transform substructure. - */ - u_int8_t (*get_transform_type) (transform_substructure_t *this); - - /** - * @brief Sets transform id of the current transform substructure. - * - * @param this calling transform_substructure_t object - * @param id transform id to set - */ - void (*set_transform_id) (transform_substructure_t *this,u_int16_t id); - - /** - * @brief get transform id of the current transform. - * - * @param this calling transform_substructure_t object - * @return Transform id of current transform substructure. - */ - u_int16_t (*get_transform_id) (transform_substructure_t *this); - - /** - * @brief get transform id of the current transform. - * - * @param this calling transform_substructure_t object - * @param key_length The key length is written to this location - * @return - * - SUCCESS if a key length attribute is contained - * - FAILED if no key length attribute is part of this - * transform or key length uses more then 16 bit! - */ - status_t (*get_key_length) (transform_substructure_t *this,u_int16_t *key_length); - - /** - * @brief Clones an transform_substructure_t object. - * - * @param this transform_substructure_t object to clone - * @return cloned transform_substructure_t object - */ - transform_substructure_t* (*clone) (transform_substructure_t *this); - - /** - * @brief Destroys an transform_substructure_t object. - * - * @param this transform_substructure_t object to destroy - */ - void (*destroy) (transform_substructure_t *this); -}; - -/** - * @brief Creates an empty transform_substructure_t object. - * - * @return created transform_substructure_t object - * - * @ingroup payloads - */ -transform_substructure_t *transform_substructure_create(void); - -/** - * @brief 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 - * - * @ingroup payloads - */ -transform_substructure_t *transform_substructure_create_type(transform_type_t transform_type, u_int16_t transform_id, u_int16_t key_length); - -#endif /*TRANSFORM_SUBSTRUCTURE_H_*/ diff --git a/src/charon/charon/encoding/payloads/ts_payload.c b/src/charon/charon/encoding/payloads/ts_payload.c deleted file mode 100644 index 58772e666..000000000 --- a/src/charon/charon/encoding/payloads/ts_payload.c +++ /dev/null @@ -1,365 +0,0 @@ -/** - * @file ts_payload.c - * - * @brief Implementation of ts_payload_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 - -#include "ts_payload.h" - -#include -#include - -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. - */ - ts_payload_t public; - - /** - * TRUE if this TS payload is of type TSi, FALSE for TSr. - */ - bool is_initiator; - - /** - * Next payload type. - */ - u_int8_t next_payload; - - /** - * Critical flag. - */ - bool critical; - - /** - * Length of this payload. - */ - u_int16_t payload_length; - - /** - * Number of traffic selectors - */ - u_int8_t number_of_traffic_selectors; - - /** - * Contains the traffic selectors of type traffic_selector_substructure_t. - */ - linked_list_t *traffic_selectors; - - /** - * @brief Computes the length of this payload. - * - * @param this calling private_ts_payload_t object - */ - void (*compute_length) (private_ts_payload_t *this); -}; - -/** - * Encoding rules to parse or generate a TS payload - * - * 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) }, - /* 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 }, - /* Length of the whole payload*/ - { 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) }, - /* 3 reserved bytes */ - { RESERVED_BYTE, 0 }, - { RESERVED_BYTE, 0 }, - { RESERVED_BYTE, 0 }, - /* some ts data bytes, length is defined in PAYLOAD_LENGTH */ - { TRAFFIC_SELECTORS, offsetof(private_ts_payload_t, traffic_selectors) } -}; - -/* - 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! Next Payload !C! RESERVED ! Payload Length ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! Number of TSs ! RESERVED ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! ! - ~ ~ - ! ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -*/ - -/** - * Implementation of payload_t.verify. - */ -static status_t verify(private_ts_payload_t *this) -{ - iterator_t *iterator; - status_t status = SUCCESS; - - if (this->number_of_traffic_selectors != (this->traffic_selectors->get_count(this->traffic_selectors))) - { - /* must be the same */ - return FAILED; - } - - iterator = this->traffic_selectors->create_iterator(this->traffic_selectors,TRUE); - while(iterator->has_next(iterator)) - { - payload_t *current_traffic_selector; - iterator->current(iterator,(void **)¤t_traffic_selector); - - status = current_traffic_selector->verify(current_traffic_selector); - if (status != SUCCESS) - { - break; - } - } - iterator->destroy(iterator); - - 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) -{ - *rules = ts_payload_encodings; - *rule_count = sizeof(ts_payload_encodings) / sizeof(encoding_rule_t); -} - -/** - * Implementation of payload_t.get_type. - */ -static payload_type_t get_payload_type(private_ts_payload_t *this) -{ - if (this->is_initiator) - { - return TRAFFIC_SELECTOR_INITIATOR; - } - else - { - return TRAFFIC_SELECTOR_RESPONDER; - } -} - -/** - * Implementation of payload_t.get_next_type. - */ -static payload_type_t get_next_type(private_ts_payload_t *this) -{ - 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) -{ - this->next_payload = type; -} - -/** - * Implementation of payload_t.get_length. - */ -static size_t get_length(private_ts_payload_t *this) -{ - this->compute_length(this); - return this->payload_length; -} - -/** - * Implementation of ts_payload_t.get_initiator. - */ -static bool get_initiator (private_ts_payload_t *this) -{ - return (this->is_initiator); -} - -/** - * Implementation of ts_payload_t.set_initiator. - */ -static void set_initiator (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) -{ - traffic_selector_t *ts; - iterator_t *iterator; - linked_list_t *ts_list = linked_list_create(); - - iterator = this->traffic_selectors->create_iterator(this->traffic_selectors, TRUE); - while (iterator->has_next(iterator)) - { - traffic_selector_substructure_t *ts_substructure; - iterator->current(iterator, (void**)&ts_substructure); - ts = ts_substructure->get_traffic_selector(ts_substructure); - ts_list->insert_last(ts_list, (void*)ts); - } - iterator->destroy(iterator); - - return ts_list; -} - -/** - * Implementation of private_ts_payload_t.compute_length. - */ -static void compute_length (private_ts_payload_t *this) -{ - iterator_t *iterator; - size_t ts_count = 0; - size_t length = TS_PAYLOAD_HEADER_LENGTH; - iterator = this->traffic_selectors->create_iterator(this->traffic_selectors,TRUE); - while (iterator->has_next(iterator)) - { - payload_t * current_traffic_selector; - iterator->current(iterator,(void **) ¤t_traffic_selector); - length += current_traffic_selector->get_length(current_traffic_selector); - ts_count++; - } - iterator->destroy(iterator); - - this->number_of_traffic_selectors= ts_count; - this->payload_length = length; - -} - - -/** - * Implementation of payload_t.destroy and ts_payload_t.destroy. - */ -static void destroy(private_ts_payload_t *this) -{ - while (this->traffic_selectors->get_count(this->traffic_selectors) > 0) - { - payload_t *current_traffic_selector; - - this->traffic_selectors->remove_last(this->traffic_selectors,(void **) ¤t_traffic_selector); - - current_traffic_selector->destroy(current_traffic_selector); - } - - this->traffic_selectors->destroy(this->traffic_selectors); - - free(this); -} - -/* - * Described in header - */ -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 functions */ - this->compute_length = compute_length; - - /* 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(); - - return &(this->public); -} - -/* - * Described in header - */ -ts_payload_t *ts_payload_create_from_traffic_selectors(bool is_initiator, linked_list_t *traffic_selectors) -{ - iterator_t *iterator; - traffic_selector_t *ts; - traffic_selector_substructure_t *ts_substructure; - 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->has_next(iterator)) - { - iterator->current(iterator, (void**)&ts); - ts_substructure = traffic_selector_substructure_create_from_traffic_selector(ts); - this->public.add_traffic_selector_substructure(&(this->public), ts_substructure); - } - iterator->destroy(iterator); - - return &(this->public); -} - diff --git a/src/charon/charon/encoding/payloads/ts_payload.h b/src/charon/charon/encoding/payloads/ts_payload.h deleted file mode 100644 index 775ff6134..000000000 --- a/src/charon/charon/encoding/payloads/ts_payload.h +++ /dev/null @@ -1,152 +0,0 @@ -/** - * @file ts_payload.h - * - * @brief Interface of ts_payload_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - - -#ifndef TS_PAYLOAD_H_ -#define TS_PAYLOAD_H_ - -#include -#include -#include -#include -#include - -/** - * Length of a TS payload without the Traffic selectors. - * - * @ingroup payloads - */ -#define TS_PAYLOAD_HEADER_LENGTH 8 - - -typedef struct ts_payload_t ts_payload_t; - -/** - * @brief Class representing an IKEv2 TS payload. - * - * The TS payload format is described in RFC section 3.13. - * - * @b Constructors: - * - ts_payload_create() - * - ts_payload_create_from_traffic_selectors() - * - * @ingroup payloads - */ -struct ts_payload_t { - /** - * The payload_t interface. - */ - payload_t payload_interface; - - /** - * @brief Get the type of TSpayload (TSi or TSr). - * - * @param this calling id_payload_t object - * @return - * - TRUE if this payload is of type TSi - * - FALSE if this payload is of type TSr - */ - bool (*get_initiator) (ts_payload_t *this); - - /** - * @brief Set the type of TS payload (TSi or TSr). - * - * @param this calling id_payload_t object - * @param is_initiator - * - TRUE if this payload is of type TSi - * - FALSE if this payload is of type TSr - */ - void (*set_initiator) (ts_payload_t *this,bool is_initiator); - - /** - * @brief Adds a traffic_selector_substructure_t object to this object. - * - * @warning The added traffic_selector_substructure_t object is - * getting destroyed in destroy function of ts_payload_t. - * - * @param this calling ts_payload_t 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); - - /** - * @brief Creates an iterator of stored traffic_selector_substructure_t objects. - * - * @warning The created iterator has to get destroyed by the caller! - * - * @warning 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 this calling ts_payload_t object - * @param[in] 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); - - /** - * @brief Get a list of nested traffic selectors as traffic_selector_t. - * - * Resulting list and its traffic selectors must be destroyed after usage - * - * @param this calling ts_payload_t object - * @return list of traffic selectors - */ - linked_list_t *(*get_traffic_selectors) (ts_payload_t *this); - - /** - * @brief Destroys an ts_payload_t object. - * - * @param this ts_payload_t object to destroy - */ - void (*destroy) (ts_payload_t *this); -}; - -/** - * @brief 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 - * - * @ingroup payloads - */ -ts_payload_t *ts_payload_create(bool is_initiator); - -/** - * @brief 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 traffic_selectors list of traffic selectors to include - * @return ts_payload_t object - * - * @ingroup payloads - */ -ts_payload_t *ts_payload_create_from_traffic_selectors(bool is_initiator, linked_list_t *traffic_selectors); - - -#endif /* TS_PAYLOAD_H_ */ diff --git a/src/charon/charon/encoding/payloads/unknown_payload.c b/src/charon/charon/encoding/payloads/unknown_payload.c deleted file mode 100644 index 25bb37d59..000000000 --- a/src/charon/charon/encoding/payloads/unknown_payload.c +++ /dev/null @@ -1,207 +0,0 @@ -/** - * @file unknown_payload.c - * - * @brief Implementation of unknown_payload_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 - -#include "unknown_payload.h" - - - -typedef struct private_unknown_payload_t private_unknown_payload_t; - -/** - * Private data of an unknown_payload_t object. - */ -struct private_unknown_payload_t { - - /** - * Public unknown_payload_t interface. - */ - unknown_payload_t public; - - /** - * Next payload type. - */ - u_int8_t next_payload; - - /** - * Critical flag. - */ - bool critical; - - /** - * Length of this payload. - */ - u_int16_t payload_length; - - /** - * The contained data. - */ - chunk_t data; -}; - -/** - * Encoding rules to parse an payload which is not further specified. - * - * The defined offsets are the positions in a object of type - * 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)}, - /* 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 }, - /* Length of the whole payload*/ - { PAYLOAD_LENGTH, offsetof(private_unknown_payload_t, payload_length)}, - /* some unknown data bytes, length is defined in PAYLOAD_LENGTH */ - { UNKNOWN_DATA, offsetof(private_unknown_payload_t, data) } -}; - -/* - 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! Next Payload !C! RESERVED ! Payload Length ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! ! - ~ Data of any type ~ - ! ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -*/ - -/** - * Implementation of payload_t.verify. - */ -static status_t verify(private_unknown_payload_t *this) -{ - /* can't do any checks, so we assume its good */ - 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) -{ - *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) -{ - return UNKNOWN_PAYLOAD; -} - -/** - * Implementation of payload_t.get_next_type. - */ -static payload_type_t get_next_type(private_unknown_payload_t *this) -{ - 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) -{ - this->next_payload = type; -} - -/** - * Implementation of payload_t.get_length. - */ -static size_t get_length(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) -{ - return this->critical; -} - -/** - * Implementation of unknown_payload_t.get_data. - */ -static chunk_t get_data (private_unknown_payload_t *this) -{ - return (this->data); -} - -/** - * Implementation of payload_t.destroy and unknown_payload_t.destroy. - */ -static void destroy(private_unknown_payload_t *this) -{ - if (this->data.ptr != NULL) - { - chunk_free(&(this->data)); - } - - free(this); -} - -/* - * Described in header - */ -unknown_payload_t *unknown_payload_create() -{ - 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_INITIALIZER; - - return (&(this->public)); -} diff --git a/src/charon/charon/encoding/payloads/unknown_payload.h b/src/charon/charon/encoding/payloads/unknown_payload.h deleted file mode 100644 index 56cdd5677..000000000 --- a/src/charon/charon/encoding/payloads/unknown_payload.h +++ /dev/null @@ -1,95 +0,0 @@ -/** - * @file unknown_payload.h - * - * @brief Interface of unknown_payload_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef UNKNOWN_PAYLOAD_H_ -#define UNKNOWN_PAYLOAD_H_ - -#include -#include - -/** - * Header length of the unknown payload. - * - * @ingroup payloads - */ -#define UNKNOWN_PAYLOAD_HEADER_LENGTH 4 - - -typedef struct unknown_payload_t unknown_payload_t; - -/** - * @brief Payload which can't be processed further. - * - * When the parser finds an unknown payload, he builds an instance of - * this class. This allows further processing of this payload, such as - * a check for the critical bit in the header. - * - * @b Constructors: - * - unknown_payload_create() - * - * @ingroup payloads - */ -struct unknown_payload_t { - - /** - * The payload_t interface. - */ - payload_t payload_interface; - - /** - * @brief Get the raw data of this payload, without - * the generic payload header. - * - * Returned data are NOT copied and must not be freed. - * - * @param this calling unknown_payload_t object - * @return data as chunk_t - */ - chunk_t (*get_data) (unknown_payload_t *this); - - /** - * @brief Get the critical flag. - * - * @param this calling unknown_payload_t object - * @return TRUE if payload is critical, FALSE if not - */ - bool (*is_critical) (unknown_payload_t *this); - - /** - * @brief Destroys an unknown_payload_t object. - * - * @param this unknown_payload_t object to destroy - */ - void (*destroy) (unknown_payload_t *this); -}; - -/** - * @brief Creates an empty unknown_payload_t object. - * - * @return unknown_payload_t object - * - * @ingroup payloads - */ -unknown_payload_t *unknown_payload_create(void); - - -#endif /* UNKNOWN_PAYLOAD_H_ */ diff --git a/src/charon/charon/encoding/payloads/vendor_id_payload.c b/src/charon/charon/encoding/payloads/vendor_id_payload.c deleted file mode 100644 index 436b82d79..000000000 --- a/src/charon/charon/encoding/payloads/vendor_id_payload.c +++ /dev/null @@ -1,227 +0,0 @@ -/** - * @file vendor_id_payload.c - * - * @brief Implementation of vendor_id_payload_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 - -#include "vendor_id_payload.h" - - -typedef struct private_vendor_id_payload_t private_vendor_id_payload_t; - -/** - * Private data of an vendor_id_payload_t object. - * - */ -struct private_vendor_id_payload_t { - /** - * Public vendor_id_payload_t interface. - */ - vendor_id_payload_t public; - - /** - * Next payload type. - */ - u_int8_t next_payload; - - /** - * Critical flag. - */ - bool critical; - - /** - * Length of this payload. - */ - u_int16_t payload_length; - - /** - * The contained vendor_id data value. - */ - chunk_t vendor_id_data; -}; - -/** - * Encoding rules to parse or generate a VENDOR ID payload - * - * The defined offsets are the positions in a object of type - * 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) }, - /* 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 }, - /* 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, vendor_id_data) } -}; - -/* - 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! Next Payload !C! RESERVED ! Payload Length ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! Cert Encoding ! ! - +-+-+-+-+-+-+-+-+ ! - ~ Certificate Data ~ - ! ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -*/ - -/** - * Implementation of payload_t.verify. - */ -static status_t verify(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) -{ - *rules = vendor_id_payload_encodings; - *rule_count = sizeof(vendor_id_payload_encodings) / sizeof(encoding_rule_t); -} - -/** - * Implementation of payload_t.get_type. - */ -static payload_type_t get_payload_type(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) -{ - 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) -{ - this->next_payload = type; -} - -/** - * Implementation of payload_t.get_length. - */ -static size_t get_length(private_vendor_id_payload_t *this) -{ - return this->payload_length; -} - -/** - * Implementation of vendor_id_payload_t.set_data. - */ -static void set_data (private_vendor_id_payload_t *this, chunk_t data) -{ - if (this->vendor_id_data.ptr != NULL) - { - chunk_free(&(this->vendor_id_data)); - } - this->vendor_id_data.ptr = clalloc(data.ptr,data.len); - this->vendor_id_data.len = data.len; - this->payload_length = VENDOR_ID_PAYLOAD_HEADER_LENGTH + this->vendor_id_data.len; -} - -/** - * Implementation of vendor_id_payload_t.get_data. - */ -static chunk_t get_data (private_vendor_id_payload_t *this) -{ - return (this->vendor_id_data); -} - -/** - * Implementation of vendor_id_payload_t.get_data_clone. - */ -static chunk_t get_data_clone (private_vendor_id_payload_t *this) -{ - chunk_t cloned_data; - if (this->vendor_id_data.ptr == NULL) - { - return (this->vendor_id_data); - } - cloned_data.ptr = clalloc(this->vendor_id_data.ptr,this->vendor_id_data.len); - cloned_data.len = this->vendor_id_data.len; - return cloned_data; -} - -/** - * Implementation of payload_t.destroy and vendor_id_payload_t.destroy. - */ -static void destroy(private_vendor_id_payload_t *this) -{ - if (this->vendor_id_data.ptr != NULL) - { - chunk_free(&(this->vendor_id_data)); - } - free(this); -} - -/* - * Described in header - */ -vendor_id_payload_t *vendor_id_payload_create() -{ - private_vendor_id_payload_t *this = malloc_thing(private_vendor_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 (*) (vendor_id_payload_t *)) destroy; - this->public.set_data = (void (*) (vendor_id_payload_t *,chunk_t)) set_data; - this->public.get_data_clone = (chunk_t (*) (vendor_id_payload_t *)) get_data_clone; - this->public.get_data = (chunk_t (*) (vendor_id_payload_t *)) get_data; - - /* private variables */ - this->critical = FALSE; - this->next_payload = NO_PAYLOAD; - this->payload_length = VENDOR_ID_PAYLOAD_HEADER_LENGTH; - this->vendor_id_data = CHUNK_INITIALIZER; - - return (&(this->public)); -} diff --git a/src/charon/charon/encoding/payloads/vendor_id_payload.h b/src/charon/charon/encoding/payloads/vendor_id_payload.h deleted file mode 100644 index 1e4fdb510..000000000 --- a/src/charon/charon/encoding/payloads/vendor_id_payload.h +++ /dev/null @@ -1,103 +0,0 @@ -/** - * @file vendor_id_payload.h - * - * @brief Interface of vendor_id_payload_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef VENDOR_ID_PAYLOAD_H_ -#define VENDOR_ID_PAYLOAD_H_ - -#include -#include - -/** - * Length of a VENDOR ID payload without the VID data in bytes. - * - * @ingroup payloads - */ -#define VENDOR_ID_PAYLOAD_HEADER_LENGTH 4 - - -typedef struct vendor_id_payload_t vendor_id_payload_t; - -/** - * @brief Class representing an IKEv2 VENDOR ID payload. - * - * The VENDOR ID payload format is described in RFC section 3.12. - * - * @b Constructors: - * - vendor_id_payload_create() - * - * @ingroup payloads - */ -struct vendor_id_payload_t { - /** - * The payload_t interface. - */ - payload_t payload_interface; - - /** - * @brief Set the VID data. - * - * Data are getting cloned. - * - * @param this calling vendor_id_payload_t object - * @param data VID data as chunk_t - */ - void (*set_data) (vendor_id_payload_t *this, chunk_t data); - - /** - * @brief Get the VID data. - * - * Returned data are a copy of the internal one. - * - * @param this calling vendor_id_payload_t object - * @return VID data as chunk_t - */ - chunk_t (*get_data_clone) (vendor_id_payload_t *this); - - /** - * @brief Get the VID data. - * - * Returned data are NOT copied. - * - * @param this calling vendor_id_payload_t object - * @return VID data as chunk_t - */ - chunk_t (*get_data) (vendor_id_payload_t *this); - - /** - * @brief Destroys an vendor_id_payload_t object. - * - * @param this vendor_id_payload_t object to destroy - */ - void (*destroy) (vendor_id_payload_t *this); -}; - -/** - * @brief Creates an empty vendor_id_payload_t object. - * - * @return vendor_id_payload_t object - * - * @ingroup payloads - */ -vendor_id_payload_t *vendor_id_payload_create(void); - - -#endif /* VENDOR_ID_PAYLOAD_H_ */ diff --git a/src/charon/charon/network/Makefile.network b/src/charon/charon/network/Makefile.network deleted file mode 100644 index fd99bd085..000000000 --- a/src/charon/charon/network/Makefile.network +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (C) 2005 Jan Hutter, 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 . -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# for more details. -# - -NETWORK_DIR= $(CHARON_DIR)network/ - - -CHARON_OBJS+= $(BUILD_DIR)packet.o -$(BUILD_DIR)packet.o : $(NETWORK_DIR)packet.c $(NETWORK_DIR)packet.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)socket.o -$(BUILD_DIR)socket.o : $(NETWORK_DIR)socket.c $(NETWORK_DIR)socket.h - $(CC) $(CFLAGS) -c -o $@ $< \ No newline at end of file diff --git a/src/charon/charon/network/packet.c b/src/charon/charon/network/packet.c deleted file mode 100644 index 6aaeca190..000000000 --- a/src/charon/charon/network/packet.c +++ /dev/null @@ -1,189 +0,0 @@ -/** - * @file packet.c - * - * @brief Implementation of packet_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - - -#include "packet.h" - - -typedef struct private_packet_t private_packet_t; - -/** - * Private data of an packet_t object. - */ -struct private_packet_t { - - /** - * Public part of a packet_t object. - */ - packet_t public; - - /** - * source address - */ - host_t *source; - - /** - * destination address - */ - host_t *destination; - - /** - * message data - */ - chunk_t data; -}; - -/** - * Implements packet_t.get_source - */ -static void set_source(private_packet_t *this, host_t *source) -{ - if (this->source) - { - this->source->destroy(this->source); - } - this->source = source; -} - -/** - * Implements packet_t.set_destination - */ -static void set_destination(private_packet_t *this, host_t *destination) -{ - if (this->destination) - { - this->destination->destroy(this->destination); - } - this->destination = destination; -} - -/** - * Implements packet_t.get_source - */ -static host_t *get_source(private_packet_t *this) -{ - return this->source; -} - -/** - * Implements packet_t.get_destination - */ -static host_t *get_destination(private_packet_t *this) -{ - return this->destination; -} - -/** - * Implements packet_t.get_data - */ -static chunk_t get_data(private_packet_t *this) -{ - return this->data; -} - -/** - * Implements packet_t.set_data - */ -static void set_data(private_packet_t *this, chunk_t data) -{ - free(this->data.ptr); - this->data = data; -} - -/** - * Implements packet_t.destroy. - */ -static void destroy(private_packet_t *this) -{ - if (this->source != NULL) - { - this->source->destroy(this->source); - } - if (this->destination != NULL) - { - this->destination->destroy(this->destination); - } - free(this->data.ptr); - free(this); -} - -/** - * Implements packet_t.clone. - */ -static packet_t *clone(private_packet_t *this) -{ - private_packet_t *other = (private_packet_t*)packet_create(); - - if (this->destination != NULL) - { - other->destination = this->destination->clone(this->destination); - } - else - { - other->destination = NULL; - } - - if (this->source != NULL) - { - other->source = this->source->clone(this->source); - } - else - { - other->source = NULL; - } - - /* only clone existing chunks :-) */ - if (this->data.ptr != NULL) - { - other->data.ptr = clalloc(this->data.ptr,this->data.len); - other->data.len = this->data.len; - } - else - { - other->data = CHUNK_INITIALIZER; - } - return &(other->public); -} - - -/* - * Documented in header - */ -packet_t *packet_create(void) -{ - private_packet_t *this = malloc_thing(private_packet_t); - - this->public.set_data = (void(*) (packet_t *,chunk_t)) set_data; - this->public.get_data = (chunk_t(*) (packet_t *)) get_data; - this->public.set_source = (void(*) (packet_t *,host_t*)) set_source; - this->public.get_source = (host_t*(*) (packet_t *)) get_source; - this->public.set_destination = (void(*) (packet_t *,host_t*)) set_destination; - this->public.get_destination = (host_t*(*) (packet_t *)) get_destination; - this->public.clone = (packet_t*(*) (packet_t *))clone; - this->public.destroy = (void(*) (packet_t *)) destroy; - - this->destination = NULL; - this->source = NULL; - this->data = CHUNK_INITIALIZER; - - return &(this->public); -} diff --git a/src/charon/charon/network/packet.h b/src/charon/charon/network/packet.h deleted file mode 100644 index 9510ecd87..000000000 --- a/src/charon/charon/network/packet.h +++ /dev/null @@ -1,135 +0,0 @@ -/** - * @file packet.h - * - * @brief Interface of packet_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef PACKET_H_ -#define PACKET_H_ - - -#include -#include - - -typedef struct packet_t packet_t; - -/** - * @brief Abstraction of an UDP-Packet, contains data, sender and receiver. - * - * @b Constructors: - * - packet_create() - * - * @ingroup network - */ -struct packet_t { - - /** - * @brief Set the source address. - * - * Set host_t is now owned by packet_t, it will destroy - * it if necessary. - * - * @param this calling object - * @param source address to set as source - */ - void (*set_source) (packet_t *packet, host_t *source); - - /** - * @brief Set the destination address. - * - * Set host_t is now owned by packet_t, it will destroy - * it if necessary. - * - * @param this calling object - * @param source address to set as destination - */ - void (*set_destination) (packet_t *packet, host_t *destination); - - /** - * @brief Get the source address. - * - * Set host_t is still owned by packet_t, clone it - * if needed. - * - * @param this calling object - * @return source address - */ - host_t *(*get_source) (packet_t *packet); - - /** - * @brief Get the destination address. - * - * Set host_t is still owned by packet_t, clone it - * if needed. - * - * @param this calling object - * @return destination address - */ - host_t *(*get_destination) (packet_t *packet); - - /** - * @brief Get the data from the packet. - * - * The data pointed by the chunk is still owned - * by the packet. Clone it if needed. - * - * @param this calling object - * @return chunk containing the data - */ - chunk_t (*get_data) (packet_t *packet); - - /** - * @brief Set the data in the packet. - * - * Supplied chunk data is now owned by the - * packet. It will free it. - * - * @param this calling object - * @param data chunk with data to set - */ - void (*set_data) (packet_t *packet, chunk_t data); - - /** - * @brief Clones a packet_t object. - * - * @param packet calling object - * @param clone pointer to a packet_t object pointer where the new object is stored - */ - packet_t* (*clone) (packet_t *packet); - - /** - * @brief Destroy the packet, freeing contained data. - * - * @param packet packet to destroy - */ - void (*destroy) (packet_t *packet); -}; - -/** - * @brief create an empty packet - * - * @return packet_t object - * - * @ingroup network - */ -packet_t *packet_create(void); - - -#endif /*PACKET_H_*/ diff --git a/src/charon/charon/network/socket.c b/src/charon/charon/network/socket.c deleted file mode 100644 index 4193e6fd8..000000000 --- a/src/charon/charon/network/socket.c +++ /dev/null @@ -1,456 +0,0 @@ -/** - * @file socket.c - * - * @brief Implementation of socket_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, Martin Willi - * Hochschule fuer Technik Rapperswil - * Copyright (C) 1998-2002 D. Hugh Redelmeier. - * Copyright (C) 1997 Angelos D. Keromytis. - * - * Some parts of interface lookup code from pluto. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "socket.h" - -#include -#include - - -#define IP_HEADER_LENGTH 20 -#define UDP_HEADER_LENGTH 8 - - -/** - * This filter code filters out all non-IKEv2 traffic on - * a SOCK_RAW IP_PROTP_UDP socket. Handling of other - * IKE versions is done in pluto. - */ -struct sock_filter ikev2_filter_code[] = -{ - /* Protocol must be UDP */ - BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 9), - BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, IPPROTO_UDP, 0, 7), - /* Destination Port must be 500 */ - BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 22), - BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 500, 0, 5), - /* IKE version must be 2.0 */ - BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 45), - BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0x20, 0, 3), - /* packet length is length in IKEv2 header + ip header + udp header */ - BPF_STMT(BPF_LD+BPF_W+BPF_ABS, 52), - BPF_STMT(BPF_ALU+BPF_ADD+BPF_K, IP_HEADER_LENGTH + UDP_HEADER_LENGTH), - BPF_STMT(BPF_RET+BPF_A, 0), - /* packet doesn't match IKEv2, ignore */ - BPF_STMT(BPF_RET+BPF_K, 0), -}; - -/** - * Filter struct to use with setsockopt - */ -struct sock_fprog ikev2_filter = { - sizeof(ikev2_filter_code) / sizeof(struct sock_filter), - ikev2_filter_code -}; - - -typedef struct interface_t interface_t; - -/** - * An interface on which we listen. - */ -struct interface_t { - - /** - * Name of the interface - */ - char name[IFNAMSIZ]; - - /** - * Associated socket - */ - int socket_fd; - - /** - * Host with listening address - */ - host_t *address; -}; - -typedef struct private_socket_t private_socket_t; - -/** - * Private data of an socket_t object - */ -struct private_socket_t{ - /** - * public functions - */ - socket_t public; - - /** - * Master socket - */ - int master_fd; - - /** - * List of all socket to listen - */ - linked_list_t* interfaces; - - /** - * logger for this socket - */ - logger_t *logger; -}; - -/** - * implementation of socket_t.receive - */ -static status_t receiver(private_socket_t *this, packet_t **packet) -{ - char buffer[MAX_PACKET]; - chunk_t data; - packet_t *pkt = packet_create(); - host_t *source, *dest; - int bytes_read = 0; - - - while (bytes_read >= 0) - { - int max_fd = 1; - fd_set readfds; - iterator_t *iterator; - int oldstate; - interface_t *interface; - - /* build fd_set */ - FD_ZERO(&readfds); - iterator = this->interfaces->create_iterator(this->interfaces, TRUE); - while (iterator->has_next(iterator)) - { - iterator->current(iterator, (void**)&interface); - FD_SET(interface->socket_fd, &readfds); - if (interface->socket_fd > max_fd) - { - max_fd = interface->socket_fd + 1; - } - } - iterator->destroy(iterator); - - /* add packet destroy handler for cancellation, enable cancellation */ - pthread_cleanup_push((void(*)(void*))pkt->destroy, (void*)pkt); - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); - - this->logger->log(this->logger, CONTROL|LEVEL1, "waiting on sockets"); - bytes_read = select(max_fd, &readfds, NULL, NULL, NULL); - - /* reset cancellation, remove packet destroy handler (without executing) */ - pthread_setcancelstate(oldstate, NULL); - pthread_cleanup_pop(0); - - /* read on the first nonblocking socket */ - bytes_read = 0; - iterator = this->interfaces->create_iterator(this->interfaces, TRUE); - while (iterator->has_next(iterator)) - { - iterator->current(iterator, (void**)&interface); - if (FD_ISSET(interface->socket_fd, &readfds)) - { - /* do the read */ - bytes_read = recv(interface->socket_fd, buffer, MAX_PACKET, 0); - break; - } - } - iterator->destroy(iterator); - - if (bytes_read < 0) - { - this->logger->log(this->logger, ERROR, "error reading from socket: %s", strerror(errno)); - continue; - } - if (bytes_read > IP_HEADER_LENGTH + UDP_HEADER_LENGTH) - { - /* read source/dest from raw IP/UDP header */ - chunk_t source_chunk = {buffer + 12, 4}; - chunk_t dest_chunk = {buffer + 16, 4}; - u_int16_t source_port = ntohs(*(u_int16_t*)(buffer + 20)); - u_int16_t dest_port = ntohs(*(u_int16_t*)(buffer + 22)); - source = host_create_from_chunk(AF_INET, source_chunk, source_port); - dest = host_create_from_chunk(AF_INET, dest_chunk, dest_port); - pkt->set_source(pkt, source); - pkt->set_destination(pkt, dest); - break; - } - this->logger->log(this->logger, ERROR|LEVEL1, "too short packet received"); - } - - this->logger->log(this->logger, CONTROL, "received packet: from %s:%d to %s:%d", - source->get_address(source), source->get_port(source), - dest->get_address(dest), dest->get_port(dest)); - - /* fill in packet */ - data.len = bytes_read - IP_HEADER_LENGTH - UDP_HEADER_LENGTH; - data.ptr = malloc(data.len); - memcpy(data.ptr, buffer + IP_HEADER_LENGTH + UDP_HEADER_LENGTH, data.len); - pkt->set_data(pkt, data); - - /* return packet */ - *packet = pkt; - - return SUCCESS; -} - -/** - * implementation of socket_t.send - */ -status_t sender(private_socket_t *this, packet_t *packet) -{ - ssize_t bytes_sent; - chunk_t data; - host_t *src, *dst; - - src = packet->get_source(packet); - dst = packet->get_destination(packet); - data = packet->get_data(packet); - - this->logger->log(this->logger, CONTROL, "sending packet: from %s:%d to %s:%d", - src->get_address(src), src->get_port(src), - dst->get_address(dst), dst->get_port(dst)); - - /* send data */ - /* TODO: should we send via the interface we received the packet? */ - bytes_sent = sendto(this->master_fd, data.ptr, data.len, 0, - dst->get_sockaddr(dst), *(dst->get_sockaddr_len(dst))); - - if (bytes_sent != data.len) - { - this->logger->log(this->logger, ERROR, "error writing to socket: %s", strerror(errno)); - return FAILED; - } - return SUCCESS; -} - -/** - * Find all suitable interfaces, bind them and add them to the list - */ -static status_t build_interface_list(private_socket_t *this, u_int16_t port) -{ - int on = TRUE; - int i; - struct sockaddr_in addr; - struct ifconf ifconf; - struct ifreq buf[300]; - - /* master socket for querying socket for a specific interfaces */ - this->master_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (this->master_fd == -1) - { - this->logger->log(this->logger, ERROR, "could not open IPv4 master socket!"); - return FAILED; - } - - /* allow binding of multiplo sockets */ - if (setsockopt(this->master_fd, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on)) < 0) - { - this->logger->log(this->logger, ERROR, "unable to set SO_REUSEADDR on master socket!"); - return FAILED; - } - - /* bind the master socket */ - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = INADDR_ANY; - addr.sin_port = htons(port); - if (bind(this->master_fd,(struct sockaddr*)&addr, sizeof(addr)) < 0) - { - this->logger->log(this->logger, ERROR, "unable to bind master socket: %s!", strerror(errno)); - return FAILED; - } - - /* get all interfaces */ - ifconf.ifc_len = sizeof(buf); - ifconf.ifc_buf = (void*) buf; - memset(buf, 0, sizeof(buf)); - if (ioctl(this->master_fd, SIOCGIFCONF, &ifconf) == -1) - { - this->logger->log(this->logger, ERROR, "unable to get interfaces!"); - return FAILED; - } - - /* add every interesting interfaces to our interface list */ - for (i = 0; (i+1) * sizeof(*buf) <= (size_t)ifconf.ifc_len; i++) - { - struct sockaddr_in *current = (struct sockaddr_in*) &buf[i].ifr_addr; - struct ifreq auxinfo; - int skt; - interface_t *interface; - - if (current->sin_family != AF_INET) - { - /* ignore all but AF_INET interfaces */ - continue; - } - - /* get auxilary info about socket */ - memset(&auxinfo, 0, sizeof(auxinfo)); - memcpy(auxinfo.ifr_name, buf[i].ifr_name, IFNAMSIZ); - if (ioctl(this->master_fd, SIOCGIFFLAGS, &auxinfo) == -1) - { - this->logger->log(this->logger, ERROR, "unable to SIOCGIFFLAGS master socket!"); - continue; - } - if (!(auxinfo.ifr_flags & IFF_UP)) - { - /* ignore an interface that isn't up */ - continue; - } - if (current->sin_addr.s_addr == 0) - { - /* ignore unconfigured interfaces */ - continue; - } - - /* set up interface socket */ - skt = socket(AF_INET, SOCK_RAW, IPPROTO_UDP); - if (socket < 0) - { - this->logger->log(this->logger, ERROR, "unable to open interface socket!"); - continue; - } - if (setsockopt(skt, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on)) < 0) - { - this->logger->log(this->logger, ERROR, "unable to set SO_REUSEADDR on interface socket!"); - close(skt); - continue; - } - current->sin_port = htons(port); - current->sin_family = AF_INET; - if (bind(skt, (struct sockaddr*)current, sizeof(struct sockaddr_in)) < 0) - { - this->logger->log(this->logger, ERROR, "unable to bind interface socket!"); - close(skt); - continue; - } - - if (setsockopt(skt, SOL_SOCKET, SO_ATTACH_FILTER, &ikev2_filter, sizeof(ikev2_filter)) < 0) - { - this->logger->log(this->logger, ERROR, "unable to attack IKEv2 filter to interface socket!"); - close(skt); - continue; - } - - /* add socket with interface name to list */ - interface = malloc_thing(interface_t); - strncpy(interface->name, buf[i].ifr_name, IFNAMSIZ); - interface->socket_fd = skt; - interface->address = host_create_from_sockaddr((struct sockaddr*)current); - this->logger->log(this->logger, CONTROL, "listening on %s (%s)", - interface->name, interface->address->get_address(interface->address)); - this->interfaces->insert_last(this->interfaces, (void*)interface); - } - - if (this->interfaces->get_count(this->interfaces) == 0) - { - this->logger->log(this->logger, ERROR, "unable to find any usable interface!"); - return FAILED; - } - return SUCCESS; -} - -/** - * implementation of socket_t.is_listening_on - */ -static bool is_listening_on(private_socket_t *this, host_t *host) -{ - iterator_t *iterator; - - /* listening on 0.0.0.0 is always TRUE */ - if (host->is_default_route(host)) - { - return TRUE; - } - - /* compare host with all interfaces */ - iterator = this->interfaces->create_iterator(this->interfaces, TRUE); - while (iterator->has_next(iterator)) - { - interface_t *interface; - iterator->current(iterator, (void**)&interface); - if (host->equals(host, interface->address)) - { - iterator->destroy(iterator); - return TRUE; - } - } - iterator->destroy(iterator); - return FALSE; -} - -/** - * implementation of socket_t.destroy - */ -static void destroy(private_socket_t *this) -{ - interface_t *interface; - while (this->interfaces->remove_last(this->interfaces, (void**)&interface) == SUCCESS) - { - interface->address->destroy(interface->address); - close(interface->socket_fd); - free(interface); - } - this->interfaces->destroy(this->interfaces); - close(this->master_fd); - free(this); -} - -/* - * See header for description - */ -socket_t *socket_create(u_int16_t port) -{ - private_socket_t *this = malloc_thing(private_socket_t); - - /* public functions */ - this->public.send = (status_t(*)(socket_t*, packet_t*))sender; - this->public.receive = (status_t(*)(socket_t*, packet_t**))receiver; - this->public.is_listening_on = (bool (*)(socket_t*,host_t*))is_listening_on; - this->public.destroy = (void(*)(socket_t*)) destroy; - - this->logger = logger_manager->get_logger(logger_manager, SOCKET); - this->interfaces = linked_list_create(); - - if (build_interface_list(this, port) != SUCCESS) - { - this->interfaces->destroy(this->interfaces); - free(this); - charon->kill(charon, "could not bind any interface!"); - } - - return (socket_t*)this; -} diff --git a/src/charon/charon/network/socket.h b/src/charon/charon/network/socket.h deleted file mode 100644 index 498e7700a..000000000 --- a/src/charon/charon/network/socket.h +++ /dev/null @@ -1,128 +0,0 @@ -/** - * @file socket.h - * - * @brief Interface for socket_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef SOCKET_H_ -#define SOCKET_H_ - - -#include -#include - - -/** - * @brief Maximum size of a packet. - * - * 3000 Bytes should be sufficient, see IKEv2 RFC. - * - * @ingroup network - */ -#define MAX_PACKET 3000 - - -typedef struct socket_t socket_t; - -/** - * @brief Abstraction all sockets (currently IPv4 only). - * - * All available IPv4 sockets are bound and the receive function - * reads from them. To allow binding of other daemons (pluto) to - * UDP/500, this implementation uses RAW sockets. An installed - * "Linux socket filter" filters out all non-IKEv2 traffic and handles - * just IKEv2 messages. An other daemon (pluto) must handle all traffic - * seperatly, e.g. ignore IKEv2 traffic, since charon handles that. - * - * @b Constructors: - * - socket_create() - * - * @todo add IPv6 support - * - * @todo We currently use multiple sockets for historic reasons. With the - * new RAW socket mechanism, we could use just one socket and filter - * addresses in userspace (or via linux socket filter). This would allow - * realtime interface/address management in a easy way... - * - * @ingroup network - */ -struct socket_t { - /** - * @brief Receive a packet. - * - * Reads a packet from the socket and sets source/dest - * appropriately. - * - * @param sock socket_t object to work on - * @param packet pinter gets address from allocated packet_t - * @return - * - SUCCESS when packet successfully received - * - FAILED when unable to receive - */ - status_t (*receive) (socket_t *sock, packet_t **packet); - - /** - * @brief Send a packet. - * - * Sends a packet to the net using destination from the packet. - * Packet is sent using default routing mechanisms, thus the - * source address in packet is ignored. - * - * @param sock socket_t object to work on - * @param packet[out] packet_t to send - * @return - * - SUCCESS when packet successfully sent - * - FAILED when unable to send - */ - status_t (*send) (socket_t *sock, packet_t *packet); - - /** - * @brief Check if socket listens on an address. - * - * @param sock socket_t object to work on - * @param host address to check - * @return TRUE if listening on host, FALSE otherwise - */ - bool (*is_listening_on) (socket_t *sock, host_t *host); - - /** - * @brief Destroy sockets. - * - * close sockets and destroy socket_t object - * - * @param sock socket_t to destroy - */ - void (*destroy) (socket_t *sock); -}; - -/** - * @brief Create a socket_t, wich binds multiple sockets. - * - * currently creates one socket, listening on all addresses - * on "port". - * - * @param port port to bind socket to - * @return socket_t object - * - * @ingroup network - */ -socket_t *socket_create(u_int16_t port); - - -#endif /*SOCKET_H_*/ diff --git a/src/charon/charon/queues/Makefile.queues b/src/charon/charon/queues/Makefile.queues deleted file mode 100644 index eeb012d2b..000000000 --- a/src/charon/charon/queues/Makefile.queues +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (C) 2005 Jan Hutter, 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 . -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# for more details. -# - -QUEUES_DIR= $(CHARON_DIR)queues/ - -CHARON_OBJS+= $(BUILD_DIR)event_queue.o -$(BUILD_DIR)event_queue.o : $(QUEUES_DIR)event_queue.c $(QUEUES_DIR)event_queue.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)job_queue.o -$(BUILD_DIR)job_queue.o : $(QUEUES_DIR)job_queue.c $(QUEUES_DIR)job_queue.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)send_queue.o -$(BUILD_DIR)send_queue.o : $(QUEUES_DIR)send_queue.c $(QUEUES_DIR)send_queue.h - $(CC) $(CFLAGS) -c -o $@ $< - - -include $(QUEUES_DIR)jobs/Makefile.jobs \ No newline at end of file diff --git a/src/charon/charon/queues/event_queue.c b/src/charon/charon/queues/event_queue.c deleted file mode 100644 index ece9d1513..000000000 --- a/src/charon/charon/queues/event_queue.c +++ /dev/null @@ -1,349 +0,0 @@ -/** - * @file event_queue.c - * - * @brief Implementation of event_queue_t - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 -#include - -#include "event_queue.h" - -#include -#include - - - -typedef struct event_t event_t; - -/** - * @brief Represents an event as it is stored in the event queue. - * - * A event consists of a event time and an assigned job object. - * - */ -struct event_t{ - /** - * Time to fire the event. - */ - timeval_t time; - - /** - * Every event has its assigned job. - */ - job_t * job; - - /** - * @brief Destroys a event_t object. - * - * @param event_t calling object - */ - void (*destroy) (event_t *event); -}; - - -/** - * implements event_t.destroy - */ -static void event_destroy(event_t *event) -{ - free(event); -} - -/** - * @brief Creates a event for a specific time - * - * @param time absolute time to fire the event - * @param job job to add to job-queue at specific time - * - * @returns created event_t object - */ -static event_t *event_create(timeval_t time, job_t *job) -{ - event_t *this = malloc_thing(event_t); - - this->destroy = event_destroy; - this->time = time; - this->job = job; - - return this; -} - - -typedef struct private_event_queue_t private_event_queue_t; - -/** - * Private Variables and Functions of event_queue_t class. - * - */ -struct private_event_queue_t { - /** - * Public part. - */ - event_queue_t public; - - /** - * The events are stored in a linked list of type linked_list_t. - */ - linked_list_t *list; - - /** - * Access to linked_list is locked through this mutex. - */ - pthread_mutex_t mutex; - - /** - * If the queue is empty or an event has not to be fired - * a thread has to wait. - * - * This condvar is used to wake up such a thread. - */ - pthread_cond_t condvar; -}; - -/** - * Returns the difference of to timeval structs in microseconds - * - * @param end_time end time - * @param start_time start time - * - * @warning this function is also defined in the tester class - * In later improvements, this function can be added to a general - * class type! - * - * @return difference in microseconds (end time - start time) - */ -static long time_difference(struct timeval *end_time, struct timeval *start_time) -{ - long seconds, microseconds; - - seconds = (end_time->tv_sec - start_time->tv_sec); - microseconds = (end_time->tv_usec - start_time->tv_usec); - return ((seconds * 1000000) + microseconds); -} - - -/** - * Implements event_queue_t.get_count - */ -static int get_count (private_event_queue_t *this) -{ - int count; - pthread_mutex_lock(&(this->mutex)); - count = this->list->get_count(this->list); - pthread_mutex_unlock(&(this->mutex)); - return count; -} - -/** - * Implements event_queue_t.get - */ -static job_t *get(private_event_queue_t *this) -{ - timespec_t timeout; - timeval_t current_time; - event_t * next_event; - job_t *job; - int oldstate; - - pthread_mutex_lock(&(this->mutex)); - - while (1) - { - while(this->list->get_count(this->list) == 0) - { - /* add mutex unlock handler for cancellation, enable cancellation */ - pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock, (void*)&(this->mutex)); - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); - - pthread_cond_wait( &(this->condvar), &(this->mutex)); - - /* reset cancellation, remove mutex-unlock handler (without executing) */ - pthread_setcancelstate(oldstate, NULL); - pthread_cleanup_pop(0); - } - - this->list->get_first(this->list,(void **) &next_event); - - gettimeofday(¤t_time,NULL); - long difference = time_difference(¤t_time,&(next_event->time)); - if (difference <= 0) - { - timeout.tv_sec = next_event->time.tv_sec; - timeout.tv_nsec = next_event->time.tv_usec * 1000; - - /* add mutex unlock handler for cancellation, enable cancellation */ - pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock, (void*)&(this->mutex)); - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); - - pthread_cond_timedwait( &(this->condvar), &(this->mutex),&timeout); - - /* reset cancellation, remove mutex-unlock handler (without executing) */ - pthread_setcancelstate(oldstate, NULL); - pthread_cleanup_pop(0); - } - else - { - /* event available */ - this->list->remove_first(this->list,(void **) &next_event); - - job = next_event->job; - - next_event->destroy(next_event); - break; - } - - } - pthread_cond_signal( &(this->condvar)); - - pthread_mutex_unlock(&(this->mutex)); - - return job; -} - -/** - * Implements function add_absolute of event_queue_t. - * See #event_queue_s.add_absolute for description. - */ -static void add_absolute(private_event_queue_t *this, job_t *job, timeval_t time) -{ - event_t *event = event_create(time,job); - event_t *current_event; - status_t status; - - pthread_mutex_lock(&(this->mutex)); - - /* while just used to break out */ - while(1) - { - if (this->list->get_count(this->list) == 0) - { - this->list->insert_first(this->list,event); - break; - } - - /* check last entry */ - this->list->get_last(this->list,(void **) ¤t_event); - - if (time_difference(&(event->time), &(current_event->time)) >= 0) - { - /* my event has to be fired after the last event in list */ - this->list->insert_last(this->list,event); - break; - } - - /* check first entry */ - this->list->get_first(this->list,(void **) ¤t_event); - - if (time_difference(&(event->time), &(current_event->time)) < 0) - { - /* my event has to be fired before the first event in list */ - this->list->insert_first(this->list,event); - break; - } - - iterator_t * iterator; - - iterator = this->list->create_iterator(this->list,TRUE); - - iterator->has_next(iterator); - /* first element has not to be checked (already done) */ - - while(iterator->has_next(iterator)) - { - status = iterator->current(iterator,(void **) ¤t_event); - - if (time_difference(&(event->time), &(current_event->time)) <= 0) - { - /* my event has to be fired before the current event in list */ - iterator->insert_before(iterator,event); - break; - } - } - iterator->destroy(iterator); - break; - } - - pthread_cond_signal( &(this->condvar)); - pthread_mutex_unlock(&(this->mutex)); -} - -/** - * Implements event_queue_t.add_relative. - */ -static void add_relative(event_queue_t *this, job_t *job, u_int32_t ms) -{ - timeval_t current_time; - timeval_t time; - int micros = ms * 1000; - - gettimeofday(¤t_time, NULL); - - time.tv_usec = ((current_time.tv_usec + micros) % 1000000); - time.tv_sec = current_time.tv_sec + ((current_time.tv_usec + micros)/ 1000000); - - this->add_absolute(this, job, time); -} - - -/** - * Implements event_queue_t.destroy. - */ -static void event_queue_destroy(private_event_queue_t *this) -{ - while (this->list->get_count(this->list) > 0) - { - event_t *event; - - if (this->list->remove_first(this->list,(void *) &event) != SUCCESS) - { - this->list->destroy(this->list); - break; - } - event->job->destroy_all(event->job); - event->destroy(event); - } - this->list->destroy(this->list); - - pthread_mutex_destroy(&(this->mutex)); - - pthread_cond_destroy(&(this->condvar)); - - free(this); -} - -/* - * Documented in header - */ -event_queue_t *event_queue_create() -{ - private_event_queue_t *this = malloc_thing(private_event_queue_t); - - this->public.get_count = (int (*) (event_queue_t *event_queue)) get_count; - this->public.get = (job_t *(*) (event_queue_t *event_queue)) get; - this->public.add_absolute = (void (*) (event_queue_t *event_queue, job_t *job, timeval_t time)) add_absolute; - this->public.add_relative = (void (*) (event_queue_t *event_queue, job_t *job, u_int32_t ms)) add_relative; - this->public.destroy = (void (*) (event_queue_t *event_queue)) event_queue_destroy; - - this->list = linked_list_create(); - pthread_mutex_init(&(this->mutex), NULL); - pthread_cond_init(&(this->condvar), NULL); - - return (&this->public); -} diff --git a/src/charon/charon/queues/event_queue.h b/src/charon/charon/queues/event_queue.h deleted file mode 100644 index 638887dac..000000000 --- a/src/charon/charon/queues/event_queue.h +++ /dev/null @@ -1,117 +0,0 @@ -/** - * @file event_queue.h - * - * @brief Interface of job_queue_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef EVENT_QUEUE_H_ -#define EVENT_QUEUE_H_ - -#include - -#include -#include - -typedef struct event_queue_t event_queue_t; - -/** - * @brief Event-Queue used to store timed events. - * - * Added events are sorted. The get method blocks until - * the time is elapsed to process the next event. The get - * method is called from the scheduler_t thread, which - * will add the jobs to to job_queue_t for further processing. - * - * Although the event-queue is based on a linked_list_t - * all access functions are thread-save implemented. - * - * @b Constructors: - * - event_queue_create() - * - * @ingroup queues - */ -struct event_queue_t { - - /** - * @brief Returns number of events in queue. - * - * @param event_queue calling object - * @return number of events in queue - */ - int (*get_count) (event_queue_t *event_queue); - - /** - * @brief Get the next job from the event-queue. - * - * If no event is pending, this function blocks until a job can be returned. - * - * @param event_queue calling object - * @param[out] job pointer to a job pointer where to job is returned to - * @return next job - */ - job_t *(*get) (event_queue_t *event_queue); - - /** - * @brief Adds a event to the queue, using a relative time. - * - * This function is non blocking and adds a job_t at a specific time to the list. - * The specific job object has to get destroyed by the thread which - * removes the job. - * - * @param event_queue calling object - * @param[in] job job to add to the queue (job is not copied) - * @param[in] time relative time, when the event has to get fired - */ - void (*add_relative) (event_queue_t *event_queue, job_t *job, u_int32_t ms); - - /** - * @brief Adds a event to the queue, using an absolute time. - * - * This function is non blocking and adds a job_t at a specific time to the list. - * The specific job object has to get destroyed by the thread which - * removes the job. - * - * @param event_queue calling object - * @param[in] job job to add to the queue (job is not copied) - * @param[in] absolute time time, when the event has to get fired - */ - void (*add_absolute) (event_queue_t *event_queue, job_t *job, timeval_t time); - - /** - * @brief Destroys a event_queue object. - * - * @warning The caller of this function has to make sure - * that no thread is going to add or get an event from the event_queue - * after calling this function. - * - * @param event_queue calling object - */ - void (*destroy) (event_queue_t *event_queue); -}; - -/** - * @brief Creates an empty event_queue. - * - * @returns event_queue_t object - * - * @ingroup queues - */ -event_queue_t *event_queue_create(void); - -#endif /*EVENT_QUEUE_H_*/ diff --git a/src/charon/charon/queues/job_queue.c b/src/charon/charon/queues/job_queue.c deleted file mode 100644 index 12a781c67..000000000 --- a/src/charon/charon/queues/job_queue.c +++ /dev/null @@ -1,153 +0,0 @@ -/** - * @file job_queue.c - * - * @brief Implementation of job_queue_t - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 -#include - -#include "job_queue.h" - -#include - - -typedef struct private_job_queue_t private_job_queue_t; - -/** - * @brief Private Variables and Functions of job_queue class - * - */ -struct private_job_queue_t { - - /** - * public members - */ - job_queue_t public; - - /** - * The jobs are stored in a linked list - */ - linked_list_t *list; - - /** - * access to linked_list is locked through this mutex - */ - pthread_mutex_t mutex; - - /** - * If the queue is empty a thread has to wait - * This condvar is used to wake up such a thread - */ - pthread_cond_t condvar; -}; - - -/** - * implements job_queue_t.get_count - */ -static int get_count(private_job_queue_t *this) -{ - int count; - pthread_mutex_lock(&(this->mutex)); - count = this->list->get_count(this->list); - pthread_mutex_unlock(&(this->mutex)); - return count; -} - -/** - * implements job_queue_t.get - */ -static job_t *get(private_job_queue_t *this) -{ - int oldstate; - job_t *job; - pthread_mutex_lock(&(this->mutex)); - /* go to wait while no jobs available */ - while(this->list->get_count(this->list) == 0) - { - /* add mutex unlock handler for cancellation, enable cancellation */ - pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock, (void*)&(this->mutex)); - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); - - pthread_cond_wait( &(this->condvar), &(this->mutex)); - - /* reset cancellation, remove mutex-unlock handler (without executing) */ - pthread_setcancelstate(oldstate, NULL); - pthread_cleanup_pop(0); - } - this->list->remove_first(this->list,(void **) &job); - pthread_mutex_unlock(&(this->mutex)); - return job; -} - -/** - * implements function job_queue_t.add - */ -static void add(private_job_queue_t *this, job_t *job) -{ - pthread_mutex_lock(&(this->mutex)); - this->list->insert_last(this->list,job); - pthread_cond_signal( &(this->condvar)); - pthread_mutex_unlock(&(this->mutex)); -} - -/** - * implements job_queue_t.destroy - */ -static void job_queue_destroy (private_job_queue_t *this) -{ - while (this->list->get_count(this->list) > 0) - { - job_t *job; - if (this->list->remove_first(this->list,(void *) &job) != SUCCESS) - { - this->list->destroy(this->list); - break; - } - job->destroy_all(job); - } - this->list->destroy(this->list); - - pthread_mutex_destroy(&(this->mutex)); - - pthread_cond_destroy(&(this->condvar)); - - free(this); -} - -/* - * - * Documented in header - */ -job_queue_t *job_queue_create(void) -{ - private_job_queue_t *this = malloc_thing(private_job_queue_t); - - this->public.get_count = (int(*)(job_queue_t*))get_count; - this->public.get = (job_t*(*)(job_queue_t*))get; - this->public.add = (void(*)(job_queue_t*, job_t*))add; - this->public.destroy = (void(*)(job_queue_t*))job_queue_destroy; - - this->list = linked_list_create(); - pthread_mutex_init(&(this->mutex), NULL); - pthread_cond_init(&(this->condvar), NULL); - - return (&this->public); -} diff --git a/src/charon/charon/queues/job_queue.h b/src/charon/charon/queues/job_queue.h deleted file mode 100644 index 71cc5891e..000000000 --- a/src/charon/charon/queues/job_queue.h +++ /dev/null @@ -1,99 +0,0 @@ -/** - * @file job_queue.h - * - * @brief Interface of job_queue_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef JOB_QUEUE_H_ -#define JOB_QUEUE_H_ - -#include -#include - -typedef struct job_queue_t job_queue_t; - -/** - * @brief The job queue stores jobs, which will be processed by the thread_pool_t. - * - * Jobs are added from various sources, from the threads and - * from the event_queue_t. - * Although the job-queue is based on a linked_list_t - * all access functions are thread-save implemented. - * - * @b Constructors: - * - job_queue_create() - * - * @ingroup queues - */ -struct job_queue_t { - - /** - * @brief Returns number of jobs in queue. - * - * @param job_queue_t calling object - * @returns number of items in queue - */ - int (*get_count) (job_queue_t *job_queue); - - /** - * @brief Get the next job from the queue. - * - * If the queue is empty, this function blocks until a job can be returned. - * After using, the returned job has to get destroyed by the caller. - * - * @param job_queue_t calling object - * @param[out] job pointer to a job pointer where to job is returned to - * @return next job - */ - job_t *(*get) (job_queue_t *job_queue); - - /** - * @brief Adds a job to the queue. - * - * This function is non blocking and adds a job_t to the list. - * The specific job object has to get destroyed by the thread which - * removes the job. - * - * @param job_queue_t calling object - * @param job job to add to the queue (job is not copied) - */ - void (*add) (job_queue_t *job_queue, job_t *job); - - /** - * @brief Destroys a job_queue object. - * - * @warning The caller of this function has to make sure - * that no thread is going to add or get a job from the job_queue - * after calling this function. - * - * @param job_queue_t calling object - */ - void (*destroy) (job_queue_t *job_queue); -}; - -/** - * @brief Creates an empty job_queue. - * - * @return job_queue_t object - * - * @ingroup queues - */ -job_queue_t *job_queue_create(void); - -#endif /*JOB_QUEUE_H_*/ diff --git a/src/charon/charon/queues/jobs/Makefile.jobs b/src/charon/charon/queues/jobs/Makefile.jobs deleted file mode 100644 index db89987bc..000000000 --- a/src/charon/charon/queues/jobs/Makefile.jobs +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright (C) 2005 Jan Hutter, 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 . -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# for more details. -# - -JOBS_DIR= $(QUEUES_DIR)jobs/ - -CHARON_OBJS+= $(BUILD_DIR)delete_half_open_ike_sa_job.o -$(BUILD_DIR)delete_half_open_ike_sa_job.o : $(JOBS_DIR)delete_half_open_ike_sa_job.c $(JOBS_DIR)delete_half_open_ike_sa_job.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)delete_established_ike_sa_job.o -$(BUILD_DIR)delete_established_ike_sa_job.o : $(JOBS_DIR)delete_established_ike_sa_job.c $(JOBS_DIR)delete_established_ike_sa_job.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)incoming_packet_job.o -$(BUILD_DIR)incoming_packet_job.o : $(JOBS_DIR)incoming_packet_job.c $(JOBS_DIR)incoming_packet_job.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)initiate_ike_sa_job.o -$(BUILD_DIR)initiate_ike_sa_job.o : $(JOBS_DIR)initiate_ike_sa_job.c $(JOBS_DIR)initiate_ike_sa_job.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)retransmit_request_job.o -$(BUILD_DIR)retransmit_request_job.o : $(JOBS_DIR)retransmit_request_job.c $(JOBS_DIR)retransmit_request_job.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)job.o -$(BUILD_DIR)job.o : $(JOBS_DIR)job.c $(JOBS_DIR)job.h - $(CC) $(CFLAGS) -c -o $@ $< - \ No newline at end of file diff --git a/src/charon/charon/queues/jobs/delete_established_ike_sa_job.c b/src/charon/charon/queues/jobs/delete_established_ike_sa_job.c deleted file mode 100644 index 7251e2ca4..000000000 --- a/src/charon/charon/queues/jobs/delete_established_ike_sa_job.c +++ /dev/null @@ -1,90 +0,0 @@ -/** - * @file delete_established_ike_sa_job.c - * - * @brief Implementation of delete_established_ike_sa_job_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 "delete_established_ike_sa_job.h" - - - -typedef struct private_delete_established_ike_sa_job_t private_delete_established_ike_sa_job_t; - -/** - * Private data of an delete_established_ike_sa_job_t object. - */ -struct private_delete_established_ike_sa_job_t { - /** - * Public delete_established_ike_sa_job_t interface. - */ - delete_established_ike_sa_job_t public; - - /** - * ID of the ike_sa to delete. - */ - ike_sa_id_t *ike_sa_id; -}; - -/** - * Implementation of job_t.get_type. - */ -static job_type_t get_type(private_delete_established_ike_sa_job_t *this) -{ - return DELETE_ESTABLISHED_IKE_SA; -} - -/** - * Implementation of delete_established_ike_sa_job_t.get_ike_sa_id - */ -static ike_sa_id_t *get_ike_sa_id(private_delete_established_ike_sa_job_t *this) -{ - return this->ike_sa_id; -} - -/** - * Implementation of job_t.destroy. - */ -static void destroy(private_delete_established_ike_sa_job_t *this) -{ - this->ike_sa_id->destroy(this->ike_sa_id); - free(this); -} - -/* - * Described in header - */ -delete_established_ike_sa_job_t *delete_established_ike_sa_job_create(ike_sa_id_t *ike_sa_id) -{ - private_delete_established_ike_sa_job_t *this = malloc_thing(private_delete_established_ike_sa_job_t); - - /* interface functions */ - this->public.job_interface.get_type = (job_type_t (*) (job_t *)) get_type; - /* same as destroy */ - this->public.job_interface.destroy_all = (void (*) (job_t *)) destroy; - this->public.job_interface.destroy = (void (*)(job_t*)) destroy; - - /* public functions */ - this->public.get_ike_sa_id = (ike_sa_id_t * (*)(delete_established_ike_sa_job_t *)) get_ike_sa_id; - this->public.destroy = (void (*)(delete_established_ike_sa_job_t *)) destroy; - - /* private variables */ - this->ike_sa_id = ike_sa_id->clone(ike_sa_id); - - return &(this->public); -} diff --git a/src/charon/charon/queues/jobs/delete_established_ike_sa_job.h b/src/charon/charon/queues/jobs/delete_established_ike_sa_job.h deleted file mode 100644 index 762dceae6..000000000 --- a/src/charon/charon/queues/jobs/delete_established_ike_sa_job.h +++ /dev/null @@ -1,78 +0,0 @@ -/** - * @file delete_established_ike_sa_job.h - * - * @brief Interface of delete_established_ike_sa_job_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef DELETE_ESTABLISHED_IKE_SA_JOB_H_ -#define DELETE_ESTABLISHED_IKE_SA_JOB_H_ - -#include -#include -#include - - -typedef struct delete_established_ike_sa_job_t delete_established_ike_sa_job_t; - -/** - * @brief Class representing an DELETE_ESTABLISHED_IKE_SA Job. - * - * This job initiates the deletion of an IKE_SA. The SA - * to delete is specified via an ike_sa_id_t. - * - * @b Constructors: - * - delete_established_ike_sa_job_create() - * - * @ingroup jobs - */ -struct delete_established_ike_sa_job_t { - /** - * The job_t interface. - */ - job_t job_interface; - - /** - * @brief Returns the currently set ike_sa_id. - * - * @warning Returned object is not copied. - * - * @param this calling delete_established_ike_sa_job_t object - * @return ike_sa_id_t object - */ - ike_sa_id_t * (*get_ike_sa_id) (delete_established_ike_sa_job_t *this); - - /** - * @brief Destroys an delete_established_ike_sa_job_t object (including assigned data). - * - * @param this delete_established_ike_sa_job_t object to destroy - */ - void (*destroy) (delete_established_ike_sa_job_t *this); -}; - -/** - * @brief Creates a job of type DELETE_ESTABLISHED_IKE_SA. - * - * @param ike_sa_id id of the IKE_SA to delete - * @return delete_established_ike_sa_job_t object - * - * @ingroup jobs - */ -delete_established_ike_sa_job_t *delete_established_ike_sa_job_create(ike_sa_id_t *ike_sa_id); - -#endif /*DELETE_ESTABLISHED_IKE_SA_JOB_H_*/ diff --git a/src/charon/charon/queues/jobs/delete_half_open_ike_sa_job.c b/src/charon/charon/queues/jobs/delete_half_open_ike_sa_job.c deleted file mode 100644 index 610285e20..000000000 --- a/src/charon/charon/queues/jobs/delete_half_open_ike_sa_job.c +++ /dev/null @@ -1,90 +0,0 @@ -/** - * @file delete_half_open_ike_sa_job.c - * - * @brief Implementation of delete_half_open_ike_sa_job_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 "delete_half_open_ike_sa_job.h" - - - -typedef struct private_delete_half_open_ike_sa_job_t private_delete_half_open_ike_sa_job_t; - -/** - * Private data of an delete_half_open_ike_sa_job_t Object - */ -struct private_delete_half_open_ike_sa_job_t { - /** - * public delete_half_open_ike_sa_job_t interface - */ - delete_half_open_ike_sa_job_t public; - - /** - * ID of the ike_sa to delete - */ - ike_sa_id_t *ike_sa_id; -}; - -/** - * Implements job_t.get_type. - */ -static job_type_t get_type(private_delete_half_open_ike_sa_job_t *this) -{ - return DELETE_HALF_OPEN_IKE_SA; -} - -/** - * Implements elete_ike_sa_job_t.get_ike_sa_id - */ -static ike_sa_id_t *get_ike_sa_id(private_delete_half_open_ike_sa_job_t *this) -{ - return this->ike_sa_id; -} - -/** - * Implements job_t.destroy. - */ -static void destroy(private_delete_half_open_ike_sa_job_t *this) -{ - this->ike_sa_id->destroy(this->ike_sa_id); - free(this); -} - -/* - * Described in header - */ -delete_half_open_ike_sa_job_t *delete_half_open_ike_sa_job_create(ike_sa_id_t *ike_sa_id) -{ - private_delete_half_open_ike_sa_job_t *this = malloc_thing(private_delete_half_open_ike_sa_job_t); - - /* interface functions */ - this->public.job_interface.get_type = (job_type_t (*) (job_t *)) get_type; - /* same as destroy */ - this->public.job_interface.destroy_all = (void (*) (job_t *)) destroy; - this->public.job_interface.destroy = (void (*)(job_t *)) destroy;; - - /* public functions */ - this->public.get_ike_sa_id = (ike_sa_id_t * (*)(delete_half_open_ike_sa_job_t *)) get_ike_sa_id; - this->public.destroy = (void (*)(delete_half_open_ike_sa_job_t *)) destroy; - - /* private variables */ - this->ike_sa_id = ike_sa_id->clone(ike_sa_id); - - return &(this->public); -} diff --git a/src/charon/charon/queues/jobs/delete_half_open_ike_sa_job.h b/src/charon/charon/queues/jobs/delete_half_open_ike_sa_job.h deleted file mode 100644 index ea42be8f2..000000000 --- a/src/charon/charon/queues/jobs/delete_half_open_ike_sa_job.h +++ /dev/null @@ -1,79 +0,0 @@ -/** - * @file delete_half_open_ike_sa_job.h - * - * @brief Interface of delete_half_open_ike_sa_job_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef DELETE_HALF_OPEN_IKE_SA_JOB_H_ -#define DELETE_HALF_OPEN_IKE_SA_JOB_H_ - -#include -#include -#include - - -typedef struct delete_half_open_ike_sa_job_t delete_half_open_ike_sa_job_t; - -/** - * @brief Class representing an DELETE_HALF_OPEN_IKE_SA Job. - * - * This job is responsible for deleting of half open IKE_SAs. A half - * open IKE_SA is every IKE_SA which hasn't reache the ike_sa_established - * state. - * - * @b Constructors: - * - delete_half_open_ike_sa_job_create() - * - * @ingroup jobs - */ -struct delete_half_open_ike_sa_job_t { - /** - * The job_t interface. - */ - job_t job_interface; - - /** - * @brief Returns the currently set ike_sa_id. - * - * @warning Returned object is not copied. - * - * @param this calling delete_half_open_ike_sa_job_t object - * @return ike_sa_id_t object - */ - ike_sa_id_t * (*get_ike_sa_id) (delete_half_open_ike_sa_job_t *this); - - /** - * @brief Destroys an delete_half_open_ike_sa_job_t object (including assigned data). - * - * @param this delete_half_open_ike_sa_job_t object to destroy - */ - void (*destroy) (delete_half_open_ike_sa_job_t *this); -}; - -/** - * @brief Creates a job of type DELETE_HALF_OPEN_IKE_SA. - * - * @param ike_sa_id id of the IKE_SA to delete - * @return created delete_half_open_ike_sa_job_t object - * - * @ingroup jobs - */ -delete_half_open_ike_sa_job_t *delete_half_open_ike_sa_job_create(ike_sa_id_t *ike_sa_id); - -#endif /*DELETE_HALF_OPEN_IKE_SA_JOB_H_*/ diff --git a/src/charon/charon/queues/jobs/incoming_packet_job.c b/src/charon/charon/queues/jobs/incoming_packet_job.c deleted file mode 100644 index fc71f63ea..000000000 --- a/src/charon/charon/queues/jobs/incoming_packet_job.c +++ /dev/null @@ -1,102 +0,0 @@ -/** - * @file incoming_packet_job.h - * - * @brief Implementation of incoming_packet_job_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 "incoming_packet_job.h" - - - -typedef struct private_incoming_packet_job_t private_incoming_packet_job_t; - -/** - * Private data of an incoming_packet_job_t Object - */ -struct private_incoming_packet_job_t { - /** - * public incoming_packet_job_t interface - */ - incoming_packet_job_t public; - - /** - * Assigned packet - */ - packet_t *packet; -}; - -/** - * Implements job_t.get_type. - */ -static job_type_t get_type(private_incoming_packet_job_t *this) -{ - return INCOMING_PACKET; -} - -/** - * Implements incoming_packet_job_t.get_packet. - */ -static packet_t *get_packet(private_incoming_packet_job_t *this) -{ - return this->packet; -} - -/** - * Implements job_t.destroy_all. - */ -static void destroy_all(private_incoming_packet_job_t *this) -{ - if (this->packet != NULL) - { - this->packet->destroy(this->packet); - } - free(this); -} - -/** - * Implements job_t.destroy. - */ -static void destroy(job_t *job) -{ - private_incoming_packet_job_t *this = (private_incoming_packet_job_t *) job; - free(this); -} - -/* - * Described in header - */ -incoming_packet_job_t *incoming_packet_job_create(packet_t *packet) -{ - private_incoming_packet_job_t *this = malloc_thing(private_incoming_packet_job_t); - - /* interface functions */ - this->public.job_interface.get_type = (job_type_t (*) (job_t *)) get_type; - this->public.job_interface.destroy_all = (void (*) (job_t *)) destroy_all; - this->public.job_interface.destroy = destroy; - - /* public functions */ - this->public.get_packet = (packet_t * (*)(incoming_packet_job_t *)) get_packet; - this->public.destroy = (void (*)(incoming_packet_job_t *)) destroy; - - /* private variables */ - this->packet = packet; - - return &(this->public); -} diff --git a/src/charon/charon/queues/jobs/incoming_packet_job.h b/src/charon/charon/queues/jobs/incoming_packet_job.h deleted file mode 100644 index e3fb5797e..000000000 --- a/src/charon/charon/queues/jobs/incoming_packet_job.h +++ /dev/null @@ -1,78 +0,0 @@ -/** - * @file incoming_packet_job.h - * - * @brief Interface of incoming_packet_job_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef INCOMING_PACKET_JOB_H_ -#define INCOMING_PACKET_JOB_H_ - -#include -#include -#include - - -typedef struct incoming_packet_job_t incoming_packet_job_t; - -/** - * @brief Class representing an INCOMING_PACKET Job. - * - * An incoming pack job is created from the receiver, which has - * read a packet to process from the socket. - * - * @b Constructors: - * - incoming_packet_job_create() - * - * @ingroup jobs - */ -struct incoming_packet_job_t { - /** - * implements job_t interface - */ - job_t job_interface; - - /** - * @brief Returns the assigned packet_t object - * - * @warning Returned packet is not cloned and has to get destroyed by the caller. - * - * @param this calling incoming_packet_job_t object - * @return assigned packet - */ - packet_t *(*get_packet) (incoming_packet_job_t *this); - - /** - * @brief Destroys an incoming_packet_job_t object. - * - * @param this incoming_packet_job_t object to destroy - */ - void (*destroy) (incoming_packet_job_t *this); -}; - -/** - * @brief Creates a job of type INCOMING_PACKET - * - * @param[in] packet packet to assign with this job - * @return created incoming_packet_job_t object - * - * @ingroup jobs - */ -incoming_packet_job_t *incoming_packet_job_create(packet_t *packet); - -#endif /*INCOMING_PACKET_JOB_H_*/ diff --git a/src/charon/charon/queues/jobs/initiate_ike_sa_job.c b/src/charon/charon/queues/jobs/initiate_ike_sa_job.c deleted file mode 100644 index ac9ace36c..000000000 --- a/src/charon/charon/queues/jobs/initiate_ike_sa_job.c +++ /dev/null @@ -1,101 +0,0 @@ -/** - * @file initiate_ike_sa_job.c - * - * @brief Implementation of initiate_ike_sa_job_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 - -#include "initiate_ike_sa_job.h" - - - -typedef struct private_initiate_ike_sa_job_t private_initiate_ike_sa_job_t; - -/** - * Private data of an initiate_ike_sa_job_t Object - */ -struct private_initiate_ike_sa_job_t { - /** - * public initiate_ike_sa_job_t interface - */ - initiate_ike_sa_job_t public; - - /** - * associated connection object to initiate - */ - connection_t *connection; -}; - - -/** - * Implements initiate_ike_sa_job_t.get_type. - */ -static job_type_t get_type(private_initiate_ike_sa_job_t *this) -{ - return INITIATE_IKE_SA; -} - -/** - * Implements initiate_ike_sa_job_t.get_configuration_name. - */ -static connection_t *get_connection(private_initiate_ike_sa_job_t *this) -{ - return this->connection; -} - -/** - * Implements job_t.destroy. - */ -static void destroy_all(private_initiate_ike_sa_job_t *this) -{ - this->connection->destroy(this->connection); - free(this); -} - -/** - * Implements job_t.destroy. - */ -static void destroy(private_initiate_ike_sa_job_t *this) -{ - free(this); -} - -/* - * Described in header - */ -initiate_ike_sa_job_t *initiate_ike_sa_job_create(connection_t *connection) -{ - private_initiate_ike_sa_job_t *this = malloc_thing(private_initiate_ike_sa_job_t); - - /* interface functions */ - this->public.job_interface.get_type = (job_type_t (*) (job_t *)) get_type; - this->public.job_interface.destroy_all = (void (*) (job_t *)) destroy_all; - this->public.job_interface.destroy = (void (*) (job_t *)) destroy; - - /* public functions */ - this->public.get_connection = (connection_t* (*)(initiate_ike_sa_job_t *)) get_connection; - this->public.destroy = (void (*)(initiate_ike_sa_job_t *)) destroy; - - /* private variables */ - this->connection = connection; - - return &(this->public); -} diff --git a/src/charon/charon/queues/jobs/initiate_ike_sa_job.h b/src/charon/charon/queues/jobs/initiate_ike_sa_job.h deleted file mode 100644 index cee31f07b..000000000 --- a/src/charon/charon/queues/jobs/initiate_ike_sa_job.h +++ /dev/null @@ -1,75 +0,0 @@ -/** - * @file initiate_ike_sa_job.h - * - * @brief Interface of initiate_ike_sa_job_t. - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef INITIATE_IKE_SA_JOB_H_ -#define INITIATE_IKE_SA_JOB_H_ - -#include -#include -#include - - -typedef struct initiate_ike_sa_job_t initiate_ike_sa_job_t; - -/** - * @brief Class representing an INITIATE_IKE_SA Job. - * - * This job is created if an IKE_SA should be iniated. This - * happens via a user request, or via the kernel interface. - * - * @b Constructors: - * - initiate_ike_sa_job_create() - * - * @ingroup jobs - */ -struct initiate_ike_sa_job_t { - /** - * implements job_t interface - */ - job_t job_interface; - - /** - * @brief Returns the connection_t to initialize - * - * @param this calling initiate_ike_sa_job_t object - * @return connection_t - */ - connection_t *(*get_connection) (initiate_ike_sa_job_t *this); - - /** - * @brief Destroys an initiate_ike_sa_job_t object. - * - * @param this initiate_ike_sa_job_t object to destroy - */ - void (*destroy) (initiate_ike_sa_job_t *this); -}; - -/** - * @brief Creates a job of type INITIATE_IKE_SA. - * - * @param connection connection_t to initializes - * @return initiate_ike_sa_job_t object - * - * @ingroup jobs - */ -initiate_ike_sa_job_t *initiate_ike_sa_job_create(connection_t *connection); - -#endif /*INITIATE_IKE_SA_JOB_H_*/ diff --git a/src/charon/charon/queues/jobs/job.c b/src/charon/charon/queues/jobs/job.c deleted file mode 100644 index df739f9e5..000000000 --- a/src/charon/charon/queues/jobs/job.c +++ /dev/null @@ -1,34 +0,0 @@ -/** - * @file job.c - * - * @brief Interface additions to job_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 "job.h" - - -mapping_t job_type_m[] = { - {INCOMING_PACKET, "INCOMING_PACKET"}, - {RETRANSMIT_REQUEST, "RETRANSMIT_REQUEST"}, - {INITIATE_IKE_SA, "INITIATE_IKE_SA"}, - {DELETE_HALF_OPEN_IKE_SA, "DELETE_HALF_OPEN_IKE_SA"}, - {DELETE_ESTABLISHED_IKE_SA, "DELETE_ESTABLISHED_IKE_SA"}, - {MAPPING_END, NULL} -}; diff --git a/src/charon/charon/queues/jobs/job.h b/src/charon/charon/queues/jobs/job.h deleted file mode 100644 index eea4da09e..000000000 --- a/src/charon/charon/queues/jobs/job.h +++ /dev/null @@ -1,120 +0,0 @@ -/** - * @file job.h - * - * @brief Interface job_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef JOB_H_ -#define JOB_H_ - -#include -#include - - -typedef enum job_type_t job_type_t; - -/** - * @brief Definition of the various job types. - * - * @todo add more jobs, such as rekeying. - * - * @ingroup jobs - */ -enum job_type_t { - /** - * Process an incoming IKEv2-Message. - * - * Job is implemented in class type incoming_packet_job_t - */ - INCOMING_PACKET, - - /** - * Retransmit an IKEv2-Message. - */ - RETRANSMIT_REQUEST, - - /** - * Establish an ike sa as initiator. - * - * Job is implemented in class type initiate_ike_sa_job_t - */ - INITIATE_IKE_SA, - - /** - * Delete an ike sa which is still not established. - * - * Job is implemented in class type delete_half_open_ike_sa_job_t - */ - DELETE_HALF_OPEN_IKE_SA, - - /** - * Delete an ike sa which is established. - * - * Job is implemented in class type delete_established_ike_sa_job_t - */ - DELETE_ESTABLISHED_IKE_SA -}; - -/** - * string mappings for job_type_t - * - * @ingroup jobs - */ -extern mapping_t job_type_m[]; - - -typedef struct job_t job_t; - -/** - * @brief Job-Interface as it is stored in the job queue. - * - * A job consists of a job-type and one or more assigned values. - * - * @b Constructors: - * - None, use specific implementation of the interface. - * - * @ingroup jobs - */ -struct job_t { - - /** - * @brief get type of job. - * - * @param this calling object - * @return type of this job - */ - job_type_t (*get_type) (job_t *this); - - /** - * @brief Destroys a job_t object and all assigned data! - * - * @param job_t calling object - */ - void (*destroy_all) (job_t *job); - - /** - * @brief Destroys a job_t object - * - * @param job_t calling object - */ - void (*destroy) (job_t *job); -}; - - -#endif /*JOB_H_*/ diff --git a/src/charon/charon/queues/jobs/retransmit_request_job.c b/src/charon/charon/queues/jobs/retransmit_request_job.c deleted file mode 100644 index e171df5bd..000000000 --- a/src/charon/charon/queues/jobs/retransmit_request_job.c +++ /dev/null @@ -1,132 +0,0 @@ -/** - * @file retransmit_request_job.c - * - * @brief Implementation of retransmit_request_job_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 "retransmit_request_job.h" - - - - -typedef struct private_retransmit_request_job_t private_retransmit_request_job_t; - -/** - * Private data of an retransmit_request_job_t Object. - */ -struct private_retransmit_request_job_t { - /** - * Public retransmit_request_job_t interface. - */ - retransmit_request_job_t public; - - /** - * Message ID of the request to resend. - */ - u_int32_t message_id; - - /** - * ID of the IKE_SA which the message belongs to. - */ - ike_sa_id_t *ike_sa_id; - - /** - * Number of times a request was retransmitted - */ - u_int32_t retransmit_count; -}; - - -/** - * Implements job_t.get_type. - */ -static job_type_t get_type(private_retransmit_request_job_t *this) -{ - return RETRANSMIT_REQUEST; -} - -/** - * Implements retransmit_request_job_t.get_ike_sa_id. - */ -static ike_sa_id_t *get_ike_sa_id(private_retransmit_request_job_t *this) -{ - return this->ike_sa_id; -} - -/** - * Implements retransmit_request_job_t.get_retransmit_count. - */ -static u_int32_t get_retransmit_count(private_retransmit_request_job_t *this) -{ - return this->retransmit_count; -} - -/** - * Implements retransmit_request_job_t.increase_retransmit_count. - */ -static void increase_retransmit_count(private_retransmit_request_job_t *this) -{ - this->retransmit_count++; -} - -/** - * Implements retransmit_request_job_t.get_message_id. - */ -static u_int32_t get_message_id(private_retransmit_request_job_t *this) -{ - return this->message_id; -} - - -/** - * Implements job_t.destroy. - */ -static void destroy(private_retransmit_request_job_t *this) -{ - this->ike_sa_id->destroy(this->ike_sa_id); - free(this); -} - -/* - * Described in header. - */ -retransmit_request_job_t *retransmit_request_job_create(u_int32_t message_id,ike_sa_id_t *ike_sa_id) -{ - private_retransmit_request_job_t *this = malloc_thing(private_retransmit_request_job_t); - - /* interface functions */ - this->public.job_interface.get_type = (job_type_t (*) (job_t *)) get_type; - /* same as destroy */ - this->public.job_interface.destroy_all = (void (*) (job_t *)) destroy; - this->public.job_interface.destroy = (void (*) (job_t *)) destroy; - - /* public functions */ - this->public.get_ike_sa_id = (ike_sa_id_t * (*)(retransmit_request_job_t *)) get_ike_sa_id; - this->public.get_message_id = (u_int32_t (*)(retransmit_request_job_t *)) get_message_id; - this->public.destroy = (void (*)(retransmit_request_job_t *)) destroy; - this->public.get_retransmit_count = (u_int32_t (*)(retransmit_request_job_t *)) get_retransmit_count; - this->public.increase_retransmit_count = (void (*)(retransmit_request_job_t *)) increase_retransmit_count; - - /* private variables */ - this->message_id = message_id; - this->retransmit_count = 0; - this->ike_sa_id = ike_sa_id->clone(ike_sa_id); - - return &(this->public); -} diff --git a/src/charon/charon/queues/jobs/retransmit_request_job.h b/src/charon/charon/queues/jobs/retransmit_request_job.h deleted file mode 100644 index 2349d3f5e..000000000 --- a/src/charon/charon/queues/jobs/retransmit_request_job.h +++ /dev/null @@ -1,105 +0,0 @@ -/** - * @file retransmit_request_job.h - * - * @brief Interface of retransmit_request_job_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef RESEND_MESSAGE_JOB_H_ -#define RESEND_MESSAGE_JOB_H_ - -#include -#include -#include - - -typedef struct retransmit_request_job_t retransmit_request_job_t; - -/** - * @brief Class representing an RETRANSMIT_REQUEST Job. - * - * This job is scheduled every time a request is sent over the - * wire. If the response to the request is not received at schedule - * time, the retransmission will be initiated. - * - * @b Constructors: - * - retransmit_request_job_create() - * - * @ingroup jobs - */ -struct retransmit_request_job_t { - /** - * The job_t interface. - */ - job_t job_interface; - - /** - * @brief Returns the retransmit count for a specific request. - * - * @param this calling retransmit_request_job_t object - * @return retransmit count of request - */ - u_int32_t (*get_retransmit_count) (retransmit_request_job_t *this); - - /** - * @brief Increases number of retransmitt attemps. - * - * @param this calling retransmit_request_job_t object - */ - void (*increase_retransmit_count) (retransmit_request_job_t *this); - - /** - * @brief Returns the message_id of the request to be resent - * - * @param this calling retransmit_request_job_t object - * @return message id of the request to resend - */ - u_int32_t (*get_message_id) (retransmit_request_job_t *this); - - /** - * @brief Returns the ike_sa_id_t object of the IKE_SA - * which the request belongs to - * - * @warning returned ike_sa_id_t object is getting destroyed in - * retransmit_request_job_t.destroy. - * - * @param this calling retransmit_request_job_t object - * @return ike_sa_id_t object to identify IKE_SA (gets NOT cloned) - */ - ike_sa_id_t *(*get_ike_sa_id) (retransmit_request_job_t *this); - - /** - * @brief Destroys an retransmit_request_job_t object. - * - * @param this retransmit_request_job_t object to destroy - */ - void (*destroy) (retransmit_request_job_t *this); -}; - -/** - * @brief Creates a job of type RETRANSMIT_REQUEST. - * - * @param message_id message_id of the request to resend - * @param ike_sa_id identification of the ike_sa as ike_sa_id_t object (gets cloned) - * @return retransmit_request_job_t object - * - * @ingroup jobs - */ -retransmit_request_job_t *retransmit_request_job_create(u_int32_t message_id,ike_sa_id_t *ike_sa_id); - -#endif /* RESEND_MESSAGE_JOB_H_ */ diff --git a/src/charon/charon/queues/send_queue.c b/src/charon/charon/queues/send_queue.c deleted file mode 100644 index 6a55d96ab..000000000 --- a/src/charon/charon/queues/send_queue.c +++ /dev/null @@ -1,153 +0,0 @@ -/** - * @file send_queue.c - * - * @brief Implementation of send_queue_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 - -#include "send_queue.h" - -#include - - -typedef struct private_send_queue_t private_send_queue_t; - -/** - * @brief Private Variables and Functions of send_queue class - * - */ -struct private_send_queue_t { - /** - * Public part of the send_queue_t object - */ - send_queue_t public; - - /** - * The packets are stored in a linked list - */ - linked_list_t *list; - - /** - * access to linked_list is locked through this mutex - */ - pthread_mutex_t mutex; - - /** - * If the queue is empty a thread has to wait - * This condvar is used to wake up such a thread - */ - pthread_cond_t condvar; -}; - - -/** - * implements send_queue_t.get_count - */ -static int get_count(private_send_queue_t *this) -{ - int count; - pthread_mutex_lock(&(this->mutex)); - count = this->list->get_count(this->list); - pthread_mutex_unlock(&(this->mutex)); - return count; -} - -/** - * implements send_queue_t.get - */ -static packet_t *get(private_send_queue_t *this) -{ - int oldstate; - packet_t *packet; - pthread_mutex_lock(&(this->mutex)); - /* go to wait while no packets available */ - - while(this->list->get_count(this->list) == 0) - { - /* add mutex unlock handler for cancellation, enable cancellation */ - pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock, (void*)&(this->mutex)); - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); - pthread_cond_wait( &(this->condvar), &(this->mutex)); - - /* reset cancellation, remove mutex-unlock handler (without executing) */ - pthread_setcancelstate(oldstate, NULL); - pthread_cleanup_pop(0); - } - this->list->remove_first(this->list,(void **)&packet); - pthread_mutex_unlock(&(this->mutex)); - return packet; -} - -/** - * implements send_queue_t.add - */ -static void add(private_send_queue_t *this, packet_t *packet) -{ - pthread_mutex_lock(&(this->mutex)); - this->list->insert_last(this->list,packet); - pthread_cond_signal( &(this->condvar)); - pthread_mutex_unlock(&(this->mutex)); -} - -/** - * implements send_queue_t.destroy - */ -static void destroy (private_send_queue_t *this) -{ - - /* destroy all packets in list before destroying list */ - while (this->list->get_count(this->list) > 0) - { - packet_t *packet; - if (this->list->remove_first(this->list,(void *) &packet) != SUCCESS) - { - this->list->destroy(this->list); - break; - } - packet->destroy(packet); - } - this->list->destroy(this->list); - - pthread_mutex_destroy(&(this->mutex)); - - pthread_cond_destroy(&(this->condvar)); - - free(this); -} - -/* - * - * Documented in header - */ -send_queue_t *send_queue_create(void) -{ - private_send_queue_t *this = malloc_thing(private_send_queue_t); - - this->public.get_count = (int(*)(send_queue_t*)) get_count; - this->public.get = (packet_t*(*)(send_queue_t*)) get; - this->public.add = (void(*)(send_queue_t*, packet_t*)) add; - this->public.destroy = (void(*)(send_queue_t*)) destroy; - - this->list = linked_list_create(); - pthread_mutex_init(&(this->mutex), NULL); - pthread_cond_init(&(this->condvar), NULL); - - return (&this->public); -} diff --git a/src/charon/charon/queues/send_queue.h b/src/charon/charon/queues/send_queue.h deleted file mode 100644 index 022a831fe..000000000 --- a/src/charon/charon/queues/send_queue.h +++ /dev/null @@ -1,100 +0,0 @@ -/** - * @file send_queue.h - * - * @brief Interface of send_queue_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef SEND_QUEUE_H_ -#define SEND_QUEUE_H_ - -#include -#include - - -typedef struct send_queue_t send_queue_t; - -/** - * @brief The send queue stores packet for the sender_t instance. - * - * The sender_t will send them consequently over the wire. - * Although the send-queue is based on a linked_list_t - * all access functions are thread-save implemented. - * - * @b Constructors: - * - send_queue_create() - * - * @ingroup queues - */ -struct send_queue_t { - - /** - * @brief returns number of packets in queue - * - * @param send_queue_t calling object - * @param[out] count integer pointer to store the count in - * @returns number of items in queue - */ - int (*get_count) (send_queue_t *send_queue); - - /** - * @brief get the next packet from the queue. - * - * If the queue is empty, this function blocks until a packet can be returned. - * - * After using, the returned packet has to get destroyed by the caller. - * - * @param send_queue_t calling object - * @return next packet from the queue - */ - packet_t *(*get) (send_queue_t *send_queue); - - /** - * @brief adds a packet to the queue. - * - * This function is non blocking and adds a packet_t to the list. - * The specific packet object has to get destroyed by the thread which - * removes the packet. - * - * @param send_queue_t calling object - * @param packet packet_t to add to the queue (packet is not copied) - */ - void (*add) (send_queue_t *send_queue, packet_t *packet); - - /** - * @brief destroys a send_queue object. - * - * @warning The caller of this function has to make sure - * that no thread is going to add or get a packet from the send_queue - * after calling this function. - * - * @param send_queue_t calling object - */ - void (*destroy) (send_queue_t *send_queue); -}; - -/** - * @brief Creates an empty send_queue_t. - * - * @return send_queue_t object - * - * @ingroup queues - */ -send_queue_t *send_queue_create(void); - -#endif /*SEND_QUEUE_H_*/ diff --git a/src/charon/charon/sa/Makefile.sa b/src/charon/charon/sa/Makefile.sa deleted file mode 100644 index 825c19959..000000000 --- a/src/charon/charon/sa/Makefile.sa +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright (C) 2005 Jan Hutter, 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 . -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# for more details. -# - -SA_DIR= $(CHARON_DIR)sa/ - -CHARON_OBJS+= $(BUILD_DIR)ike_sa_id.o -$(BUILD_DIR)ike_sa_id.o : $(SA_DIR)ike_sa_id.c $(SA_DIR)ike_sa_id.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)ike_sa_manager.o -$(BUILD_DIR)ike_sa_manager.o : $(SA_DIR)ike_sa_manager.c $(SA_DIR)ike_sa_manager.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)ike_sa.o -$(BUILD_DIR)ike_sa.o : $(SA_DIR)ike_sa.c $(SA_DIR)ike_sa.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)authenticator.o -$(BUILD_DIR)authenticator.o : $(SA_DIR)authenticator.c $(SA_DIR)authenticator.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)child_sa.o -$(BUILD_DIR)child_sa.o : $(SA_DIR)child_sa.c $(SA_DIR)child_sa.h - $(CC) $(CFLAGS) -c -o $@ $< - -include $(SA_DIR)states/Makefile.states \ No newline at end of file diff --git a/src/charon/charon/sa/authenticator.c b/src/charon/charon/sa/authenticator.c deleted file mode 100644 index 3aeb8795f..000000000 --- a/src/charon/charon/sa/authenticator.c +++ /dev/null @@ -1,405 +0,0 @@ -/** - * @file authenticator.c - * - * @brief Implementation of authenticator_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 - -#include "authenticator.h" - -#include - -/** - * Key pad for the AUTH method SHARED_KEY_MESSAGE_INTEGRITY_CODE. - */ -#define IKEV2_KEY_PAD "Key Pad for IKEv2" - - -typedef struct private_authenticator_t private_authenticator_t; - -/** - * Private data of an authenticator_t object. - */ -struct private_authenticator_t { - - /** - * Public authenticator_t interface. - */ - authenticator_t public; - - /** - * Assigned IKE_SA. Needed to get objects of type prf_t and logger_t. - */ - protected_ike_sa_t *ike_sa; - - /** - * PRF taken from the IKE_SA. - */ - prf_t *prf; - - /** - * A logger for. - * - * Using logger of IKE_SA. - */ - logger_t *logger; - - /** - * @brief Creates the octets which are signed (RSA) or MACed (shared secret) as described in section - * 2.15 of RFC. - * - * @param this calling object - * @param last_message the last message to include in created octets - * (either binary form of IKE_SA_INIT request or IKE_SA_INIT response) - * @param other_nonce Nonce data received from other peer - * @param my_id id_payload_t object representing an ID payload - * @param initiator Type of peer. TRUE, if it is original initiator, FALSE otherwise - * @return octets as described in section 2.15. Memory gets allocated and has to get - * destroyed by caller. - */ - chunk_t (*allocate_octets) (private_authenticator_t *this, - chunk_t last_message, - chunk_t other_nonce, - id_payload_t *my_id, - bool initiator); - - /** - * @brief Creates the AUTH data using auth method SHARED_KEY_MESSAGE_INTEGRITY_CODE. - * - * @param this calling object - * @param last_message the last message - * (either binary form of IKE_SA_INIT request or IKE_SA_INIT response) - * @param nonce Nonce data to include in auth data compution - * @param id_payload id_payload_t object representing an ID payload - * @param initiator Type of peer. TRUE, if it is original initiator, FALSE otherwise - * @param shared_secret shared secret as chunk_t. If shared secret is a string, - * the NULL termination is not included. - * @return AUTH data as dscribed in section 2.15 for - * AUTH method SHARED_KEY_MESSAGE_INTEGRITY_CODE. - * Memory gets allocated and has to get destroyed by caller. - */ - chunk_t (*build_preshared_secret_signature) (private_authenticator_t *this, - chunk_t last_message, - chunk_t nonce, - id_payload_t *id_payload, - bool initiator, - chunk_t preshared_secret); -}; - -/** - * Implementation of private_authenticator_t.allocate_octets. - */ -static chunk_t allocate_octets(private_authenticator_t *this, - chunk_t last_message, - chunk_t other_nonce, - id_payload_t *my_id, - bool initiator) -{ - prf_t *prf; - chunk_t id_chunk = my_id->get_data(my_id); - u_int8_t id_with_header[4 + id_chunk.len]; - /* - * IKEv2 for linux (http://sf.net/projects/ikev2/) - * is not compatible with IKEv2 Draft and so not compatible with this - * implementation, cause AUTH data are computed without - * ID type and the three reserved bytes. - */ - chunk_t id_with_header_chunk = {ptr:id_with_header, len: sizeof(id_with_header)}; - u_int8_t *current_pos; - chunk_t octets; - - id_with_header[0] = my_id->get_id_type(my_id); - id_with_header[1] = 0x00; - id_with_header[2] = 0x00; - id_with_header[3] = 0x00; - memcpy(id_with_header + 4,id_chunk.ptr,id_chunk.len); - - if (initiator) - { - prf = this->ike_sa->get_prf_auth_i(this->ike_sa); - } - else - { - prf = this->ike_sa->get_prf_auth_r(this->ike_sa); - } - - /* 4 bytes are id type and reserved fields of id payload */ - octets.len = last_message.len + other_nonce.len + prf->get_block_size(prf); - octets.ptr = malloc(octets.len); - current_pos = octets.ptr; - memcpy(current_pos,last_message.ptr,last_message.len); - current_pos += last_message.len; - memcpy(current_pos,other_nonce.ptr,other_nonce.len); - current_pos += other_nonce.len; - prf->get_bytes(prf, id_with_header_chunk, current_pos); - - this->logger->log_chunk(this->logger,RAW | LEVEL2, "Octets (Mesage + Nonce + prf(Sk_px,Idx)",octets); - return octets; -} - -/** - * Implementation of private_authenticator_t.build_preshared_secret_signature. - */ -static chunk_t build_preshared_secret_signature(private_authenticator_t *this, - chunk_t last_message, - chunk_t nonce, - id_payload_t *id_payload, - bool initiator, - chunk_t preshared_secret) -{ - chunk_t key_pad = {ptr: IKEV2_KEY_PAD, len:strlen(IKEV2_KEY_PAD)}; - u_int8_t key_buffer[this->prf->get_block_size(this->prf)]; - chunk_t key = {ptr: key_buffer, len: sizeof(key_buffer)}; - chunk_t auth_data; - - chunk_t octets = this->allocate_octets(this,last_message,nonce,id_payload,initiator); - - /* AUTH = prf(prf(Shared Secret,"Key Pad for IKEv2"), ) */ - this->prf->set_key(this->prf, preshared_secret); - this->prf->get_bytes(this->prf, key_pad, key_buffer); - this->prf->set_key(this->prf, key); - this->prf->allocate_bytes(this->prf, octets, &auth_data); - chunk_free(&octets); - this->logger->log_chunk(this->logger,RAW | LEVEL2, "Authenticated data",auth_data); - - return auth_data; -} - -/** - * Implementation of authenticator_t.verify_auth_data. - */ -static status_t verify_auth_data (private_authenticator_t *this, - auth_payload_t *auth_payload, - chunk_t last_received_packet, - chunk_t my_nonce, - id_payload_t *other_id_payload, - bool initiator) -{ - switch(auth_payload->get_auth_method(auth_payload)) - { - case SHARED_KEY_MESSAGE_INTEGRITY_CODE: - { - identification_t *other_id = other_id_payload->get_identification(other_id_payload); - chunk_t auth_data = auth_payload->get_data(auth_payload); - chunk_t preshared_secret; - status_t status; - - status = charon->credentials->get_shared_secret(charon->credentials, - other_id, - &preshared_secret); - if (status != SUCCESS) - { - this->logger->log(this->logger, ERROR|LEVEL1, "No shared secret found for %s", - other_id->get_string(other_id)); - other_id->destroy(other_id); - return status; - } - - chunk_t my_auth_data = this->build_preshared_secret_signature(this, - last_received_packet, - my_nonce, - other_id_payload, - initiator, - preshared_secret); - chunk_free(&preshared_secret); - - if (auth_data.len != my_auth_data.len) - { - chunk_free(&my_auth_data); - status = FAILED; - } - else if (memcmp(auth_data.ptr,my_auth_data.ptr, my_auth_data.len) == 0) - { - this->logger->log(this->logger, CONTROL, "Authentication of %s with preshared secret successful", - other_id->get_string(other_id)); - status = SUCCESS; - } - else - { - this->logger->log(this->logger, CONTROL, "Authentication of %s with preshared secret failed", - other_id->get_string(other_id)); - status = FAILED; - } - other_id->destroy(other_id); - chunk_free(&my_auth_data); - return status; - } - case RSA_DIGITAL_SIGNATURE: - { - identification_t *other_id = other_id_payload->get_identification(other_id_payload); - rsa_public_key_t *public_key; - status_t status; - chunk_t octets, auth_data; - - auth_data = auth_payload->get_data(auth_payload); - - public_key = charon->credentials->get_rsa_public_key(charon->credentials, - other_id); - if (public_key == NULL) - { - this->logger->log(this->logger, ERROR|LEVEL1, "No RSA public key found for %s", - other_id->get_string(other_id)); - other_id->destroy(other_id); - return NOT_FOUND; - } - - octets = this->allocate_octets(this,last_received_packet, my_nonce,other_id_payload, initiator); - - status = public_key->verify_emsa_pkcs1_signature(public_key, octets, auth_data); - if (status == SUCCESS) - { - this->logger->log(this->logger, CONTROL, "Authentication of %s with RSA successful", - other_id->get_string(other_id)); - } - else - { - this->logger->log(this->logger, CONTROL, "Authentication of %s with RSA failed", - other_id->get_string(other_id)); - } - - public_key->destroy(public_key); - other_id->destroy(other_id); - chunk_free(&octets); - return status; - } - default: - { - return NOT_SUPPORTED; - } - } -} - -/** - * Implementation of authenticator_t.compute_auth_data. - */ -static status_t compute_auth_data (private_authenticator_t *this, - auth_payload_t **auth_payload, - chunk_t last_sent_packet, - chunk_t other_nonce, - id_payload_t *my_id_payload, - bool initiator) -{ - connection_t *connection = this->ike_sa->get_connection(this->ike_sa); - - switch(connection->get_auth_method(connection)) - { - case SHARED_KEY_MESSAGE_INTEGRITY_CODE: - { - identification_t *my_id = my_id_payload->get_identification(my_id_payload); - chunk_t preshared_secret; - status_t status; - chunk_t auth_data; - - status = charon->credentials->get_shared_secret(charon->credentials, - my_id, - &preshared_secret); - - if (status != SUCCESS) - { - this->logger->log(this->logger, ERROR|LEVEL1, "No shared secret found for %s", - my_id->get_string(my_id)); - my_id->destroy(my_id); - return status; - } - my_id->destroy(my_id); - - auth_data = this->build_preshared_secret_signature(this, last_sent_packet, other_nonce, - my_id_payload, initiator, preshared_secret); - chunk_free(&preshared_secret); - *auth_payload = auth_payload_create(); - (*auth_payload)->set_auth_method(*auth_payload, SHARED_KEY_MESSAGE_INTEGRITY_CODE); - (*auth_payload)->set_data(*auth_payload, auth_data); - - chunk_free(&auth_data); - return SUCCESS; - } - case RSA_DIGITAL_SIGNATURE: - { - identification_t *my_id = my_id_payload->get_identification(my_id_payload); - rsa_private_key_t *private_key; - status_t status; - chunk_t octets, auth_data; - - private_key = charon->credentials->get_rsa_private_key(charon->credentials, my_id); - if (private_key == NULL) - { - this->logger->log(this->logger, ERROR|LEVEL1, "No RSA private key found for %s", - my_id->get_string(my_id)); - my_id->destroy(my_id); - return NOT_FOUND; - } - my_id->destroy(my_id); - - octets = this->allocate_octets(this,last_sent_packet,other_nonce,my_id_payload,initiator); - - status = private_key->build_emsa_pkcs1_signature(private_key, HASH_SHA1, octets, &auth_data); - chunk_free(&octets); - if (status != SUCCESS) - { - private_key->destroy(private_key); - return status; - } - - *auth_payload = auth_payload_create(); - (*auth_payload)->set_auth_method(*auth_payload, RSA_DIGITAL_SIGNATURE); - (*auth_payload)->set_data(*auth_payload, auth_data); - - private_key->destroy(private_key); - chunk_free(&auth_data); - return SUCCESS; - } - default: - { - return NOT_SUPPORTED; - } - } -} - -/** - * Implementation of authenticator_t.destroy. - */ -static void destroy (private_authenticator_t *this) -{ - free(this); -} - -/* - * Described in header. - */ -authenticator_t *authenticator_create(protected_ike_sa_t *ike_sa) -{ - private_authenticator_t *this = malloc_thing(private_authenticator_t); - - /* Public functions */ - this->public.destroy = (void(*)(authenticator_t*))destroy; - this->public.verify_auth_data = (status_t (*) (authenticator_t *,auth_payload_t *, chunk_t ,chunk_t ,id_payload_t *,bool)) verify_auth_data; - this->public.compute_auth_data = (status_t (*) (authenticator_t *,auth_payload_t **, chunk_t ,chunk_t ,id_payload_t *,bool)) compute_auth_data; - - /* private functions */ - this->allocate_octets = allocate_octets; - this->build_preshared_secret_signature = build_preshared_secret_signature; - - /* private data */ - this->ike_sa = ike_sa; - this->prf = this->ike_sa->get_prf(this->ike_sa); - this->logger = logger_manager->get_logger(logger_manager, IKE_SA); - - return &(this->public); -} diff --git a/src/charon/charon/sa/authenticator.h b/src/charon/charon/sa/authenticator.h deleted file mode 100644 index b6bc317ac..000000000 --- a/src/charon/charon/sa/authenticator.h +++ /dev/null @@ -1,138 +0,0 @@ -/** - * @file authenticator.h - * - * @brief Interface of authenticator_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef AUTHENTICATOR_H_ -#define AUTHENTICATOR_H_ - -#include -#include -#include -#include -#include - - -typedef struct authenticator_t authenticator_t; - -/** - * @brief Class used to authenticate a peer. - * - * Currently the following two AUTH methods are supported: - * - SHARED_KEY_MESSAGE_INTEGRITY_CODE - * - RSA_DIGITAL_SIGNATURE - * - * This class retrieves needed data for specific AUTH methods (RSA keys, shared secrets, etc.) - * over an internal stored protected_ike_sa_t object or directly from the configuration_t over - * the daemon_t object "charon". - * - * @b Constructors: - * - authenticator_create() - * - * @ingroup sa - */ -struct authenticator_t { - - /** - * @brief Verify's given authentication data. - * - * To verify a received AUTH payload the following data must be provided: - * - the last received IKEv2 Message from the other peer in binary form - * - the nonce value sent to the other peer - * - the ID payload of the other peer - * - * @param this calling object - * @param last_received_packet binary representation of the last received IKEv2-Message - * @param my_nonce the sent nonce (without payload header) - * @param other_id_payload the ID payload received from other peer - * @param initiator type of other peer. TRUE, if it is original initiator, FALSE otherwise - * - * @todo Document RSA error status types - * - * @return - * - SUCCESS if verification successful - * - FAILED if verification failed - * - NOT_SUPPORTED if AUTH method not supported - * - NOT_FOUND if the data for specific AUTH method could not be found - * (e.g. shared secret, rsa key) - */ - status_t (*verify_auth_data) (authenticator_t *this, - auth_payload_t *auth_payload, - chunk_t last_received_packet, - chunk_t my_nonce, - id_payload_t *other_id_payload, - bool initiator); - - /** - * @brief Computes authentication data and creates specific AUTH payload. - * - * To create an AUTH payload, the following data must be provided: - * - the last sent IKEv2 Message in binary form - * - the nonce value received from the other peer - * - the ID payload of myself - * - * @param this calling object - * @param[out] auth_payload The object of typee auth_payload_t will be created at pointing location - * @param last_sent_packet binary representation of the last sent IKEv2-Message - * @param other_nonce the received nonce (without payload header) - * @param my_id_payload the ID payload going to send to other peer - * @param initiator type of myself. TRUE, if I'm original initiator, FALSE otherwise - * - * @todo Document RSA error status types - * - * @return - * - SUCCESS if authentication data could be computed - * - NOT_SUPPORTED if AUTH method not supported - * - NOT_FOUND if the data for AUTH method could not be found - */ - status_t (*compute_auth_data) (authenticator_t *this, - auth_payload_t **auth_payload, - chunk_t last_sent_packet, - chunk_t other_nonce, - id_payload_t *my_id_payload, - bool initiator); - - /** - * @brief Destroys a authenticator_t object. - * - * @param this calling object - */ - void (*destroy) (authenticator_t *this); -}; - -/** - * @brief Creates an authenticator object. - * - * @warning: The following functions of the assigned protected_ike_sa_t object - * must return a valid value: - * - protected_ike_sa_t.get_policy - * - protected_ike_sa_t.get_prf - * - protected_ike_sa_t.get_logger - * This preconditions are not given in IKE_SA states INITIATOR_INIT or RESPONDER_INIT! - * - * @param ike_sa object of type protected_ike_sa_t - * - * @return authenticator_t object - * - * @ingroup sa - */ -authenticator_t *authenticator_create(protected_ike_sa_t *ike_sa); - -#endif /* AUTHENTICATOR_H_ */ diff --git a/src/charon/charon/sa/child_sa.c b/src/charon/charon/sa/child_sa.c deleted file mode 100644 index a678ea9b8..000000000 --- a/src/charon/charon/sa/child_sa.c +++ /dev/null @@ -1,590 +0,0 @@ -/** - * @file child_sa.c - * - * @brief Implementation of child_sa_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 - -#include "child_sa.h" - -#include - - -typedef struct sa_policy_t sa_policy_t; - -/** - * Struct used to store information for a policy. This - * is needed since we must provide all this information - * for deleting a policy... - */ -struct sa_policy_t { - - /** - * Network on local side - */ - host_t *my_net; - - /** - * Network on remote side - */ - host_t *other_net; - - /** - * Number of bits for local network (subnet size) - */ - u_int8_t my_net_mask; - - /** - * Number of bits for remote network (subnet size) - */ - u_int8_t other_net_mask; - - /** - * Protocol for this policy, such as TCP/UDP/ICMP... - */ - int upper_proto; -}; - -typedef struct private_child_sa_t private_child_sa_t; - -/** - * Private data of a child_sa_t object. - */ -struct private_child_sa_t { - /** - * Public interface of child_sa_t. - */ - child_sa_t public; - - /** - * IP of this peer - */ - host_t *me; - - /** - * IP of other peer - */ - host_t *other; - - /** - * Local security parameter index for AH protocol, 0 if not used - */ - u_int32_t my_ah_spi; - - /** - * Local security parameter index for ESP protocol, 0 if not used - */ - u_int32_t my_esp_spi; - - /** - * Remote security parameter index for AH protocol, 0 if not used - */ - u_int32_t other_ah_spi; - - /** - * Remote security parameter index for ESP protocol, 0 if not used - */ - u_int32_t other_esp_spi; - - /** - * List containing policy_id_t objects - */ - linked_list_t *policies; - - /** - * reqid used for this child_sa - */ - u_int32_t reqid; - - /** - * CHILD_SAs own logger - */ - logger_t *logger; -}; - -/** - * Implements child_sa_t.alloc - */ -static status_t alloc(private_child_sa_t *this, linked_list_t *proposals) -{ - protocol_id_t protocols[2]; - iterator_t *iterator; - proposal_t *proposal; - status_t status; - u_int i; - - /* iterator through proposals */ - iterator = proposals->create_iterator(proposals, TRUE); - while(iterator->has_next(iterator)) - { - iterator->current(iterator, (void**)&proposal); - proposal->get_protocols(proposal, protocols); - - /* check all protocols */ - for (i = 0; i<2; i++) - { - switch (protocols[i]) - { - case PROTO_AH: - /* do we already have an spi for AH?*/ - if (this->my_ah_spi == 0) - { - /* nope, get one */ - status = charon->kernel_interface->get_spi( - charon->kernel_interface, - this->me, this->other, - PROTO_AH, FALSE, - &(this->my_ah_spi)); - } - /* update proposal */ - proposal->set_spi(proposal, PROTO_AH, (u_int64_t)this->my_ah_spi); - break; - case PROTO_ESP: - /* do we already have an spi for ESP?*/ - if (this->my_esp_spi == 0) - { - /* nope, get one */ - status = charon->kernel_interface->get_spi( - charon->kernel_interface, - this->me, this->other, - PROTO_ESP, FALSE, - &(this->my_esp_spi)); - } - /* update proposal */ - proposal->set_spi(proposal, PROTO_ESP, (u_int64_t)this->my_esp_spi); - break; - default: - break; - } - if (status != SUCCESS) - { - iterator->destroy(iterator); - return FAILED; - } - } - } - iterator->destroy(iterator); - return SUCCESS; -} - -static status_t install(private_child_sa_t *this, proposal_t *proposal, prf_plus_t *prf_plus, bool mine) -{ - protocol_id_t protocols[2]; - u_int32_t spi; - encryption_algorithm_t enc_algo; - integrity_algorithm_t int_algo; - chunk_t enc_key, int_key; - algorithm_t *algo; - crypter_t *crypter; - signer_t *signer; - size_t key_size; - host_t *src; - host_t *dst; - status_t status; - u_int i; - - /* we must assign the roles to correctly set up the SAs */ - if (mine) - { - src = this->me; - dst = this->other; - } - else - { - dst = this->me; - src = this->other; - } - - proposal->get_protocols(proposal, protocols); - /* derive keys in order as protocols appear */ - for (i = 0; i<2; i++) - { - if (protocols[i] != PROTO_NONE) - { - - /* now we have to decide which spi to use. Use self allocated, if "mine", - * or the one in the proposal, if not "mine" (others). */ - if (mine) - { - if (protocols[i] == PROTO_AH) - { - spi = this->my_ah_spi; - } - else - { - spi = this->my_esp_spi; - } - } - else /* use proposals spi */ - { - spi = proposal->get_spi(proposal, protocols[i]); - if (protocols[i] == PROTO_AH) - { - this->other_ah_spi = spi; - } - else - { - this->other_esp_spi = spi; - } - } - - /* derive encryption key first */ - if (proposal->get_algorithm(proposal, protocols[i], ENCRYPTION_ALGORITHM, &algo)) - { - enc_algo = algo->algorithm; - this->logger->log(this->logger, CONTROL|LEVEL1, "%s for %s: using %s %s, ", - mapping_find(protocol_id_m, protocols[i]), - mine ? "me" : "other", - mapping_find(transform_type_m, ENCRYPTION_ALGORITHM), - mapping_find(encryption_algorithm_m, enc_algo)); - - /* we must create a (unused) crypter, since its the only way to get the size - * of the key. This is not so nice, since charon must support all algorithms - * the kernel supports... - * TODO: build something of a encryption algorithm lookup function - */ - crypter = crypter_create(enc_algo, algo->key_size); - key_size = crypter->get_key_size(crypter); - crypter->destroy(crypter); - prf_plus->allocate_bytes(prf_plus, key_size, &enc_key); - this->logger->log_chunk(this->logger, PRIVATE, "key:", enc_key); - } - else - { - enc_algo = ENCR_UNDEFINED; - } - - /* derive integrity key */ - if (proposal->get_algorithm(proposal, protocols[i], INTEGRITY_ALGORITHM, &algo)) - { - int_algo = algo->algorithm; - this->logger->log(this->logger, CONTROL|LEVEL1, "%s for %s: using %s %s,", - mapping_find(protocol_id_m, protocols[i]), - mine ? "me" : "other", - mapping_find(transform_type_m, INTEGRITY_ALGORITHM), - mapping_find(integrity_algorithm_m, algo->algorithm)); - - signer = signer_create(int_algo); - key_size = signer->get_key_size(signer); - signer->destroy(signer); - prf_plus->allocate_bytes(prf_plus, key_size, &int_key); - this->logger->log_chunk(this->logger, PRIVATE, "key:", int_key); - } - else - { - int_algo = AUTH_UNDEFINED; - } - /* send keys down to kernel */ - this->logger->log(this->logger, CONTROL|LEVEL1, - "installing 0x%.8x for %s, src %s dst %s", - ntohl(spi), mapping_find(protocol_id_m, protocols[i]), - src->get_address(src), dst->get_address(dst)); - status = charon->kernel_interface->add_sa(charon->kernel_interface, - src, dst, - spi, protocols[i], - this->reqid, - enc_algo, enc_key, - int_algo, int_key, mine); - /* clean up for next round */ - if (enc_algo != ENCR_UNDEFINED) - { - chunk_free(&enc_key); - } - if (int_algo != AUTH_UNDEFINED) - { - chunk_free(&int_key); - } - - if (status != SUCCESS) - { - return FAILED; - } - - - } - } - return SUCCESS; -} - -static status_t add(private_child_sa_t *this, proposal_t *proposal, prf_plus_t *prf_plus) -{ - linked_list_t *list; - - /* install others (initiators) SAs*/ - if (install(this, proposal, prf_plus, FALSE) != SUCCESS) - { - return FAILED; - } - - /* get SPIs for our SAs */ - list = linked_list_create(); - list->insert_last(list, proposal); - if (alloc(this, list) != SUCCESS) - { - list->destroy(list); - return FAILED; - } - list->destroy(list); - - /* install our (responders) SAs */ - if (install(this, proposal, prf_plus, TRUE) != SUCCESS) - { - return FAILED; - } - - return SUCCESS; -} - -static status_t update(private_child_sa_t *this, proposal_t *proposal, prf_plus_t *prf_plus) -{ - /* install our (initator) SAs */ - if (install(this, proposal, prf_plus, TRUE) != SUCCESS) - { - return FAILED; - } - /* install his (responder) SAs */ - if (install(this, proposal, prf_plus, FALSE) != SUCCESS) - { - return FAILED; - } - - return SUCCESS; -} - -static status_t add_policies(private_child_sa_t *this, linked_list_t *my_ts_list, linked_list_t *other_ts_list) -{ - iterator_t *my_iter, *other_iter; - traffic_selector_t *my_ts, *other_ts; - - /* iterate over both lists */ - my_iter = my_ts_list->create_iterator(my_ts_list, TRUE); - other_iter = other_ts_list->create_iterator(other_ts_list, TRUE); - while (my_iter->has_next(my_iter)) - { - my_iter->current(my_iter, (void**)&my_ts); - other_iter->reset(other_iter); - while (other_iter->has_next(other_iter)) - { - /* set up policies for every entry in my_ts_list to every entry in other_ts_list */ - int family; - chunk_t from_addr; - u_int16_t from_port, to_port; - sa_policy_t *policy; - status_t status; - - other_iter->current(other_iter, (void**)&other_ts); - - /* only set up policies if protocol matches */ - if (my_ts->get_protocol(my_ts) != other_ts->get_protocol(other_ts)) - { - continue; - } - policy = malloc_thing(sa_policy_t); - policy->upper_proto = my_ts->get_protocol(my_ts); - - /* calculate net and ports for local side */ - family = my_ts->get_type(my_ts) == TS_IPV4_ADDR_RANGE ? AF_INET : AF_INET6; - from_addr = my_ts->get_from_address(my_ts); - from_port = my_ts->get_from_port(my_ts); - to_port = my_ts->get_to_port(my_ts); - from_port = (from_port != to_port) ? 0 : from_port; - policy->my_net = host_create_from_chunk(family, from_addr, from_port); - policy->my_net_mask = my_ts->get_netmask(my_ts); - chunk_free(&from_addr); - - /* calculate net and ports for remote side */ - family = other_ts->get_type(other_ts) == TS_IPV4_ADDR_RANGE ? AF_INET : AF_INET6; - from_addr = other_ts->get_from_address(other_ts); - from_port = other_ts->get_from_port(other_ts); - to_port = other_ts->get_to_port(other_ts); - from_port = (from_port != to_port) ? 0 : from_port; - policy->other_net = host_create_from_chunk(family, from_addr, from_port); - policy->other_net_mask = other_ts->get_netmask(other_ts); - chunk_free(&from_addr); - - /* install 3 policies: out, in and forward */ - status = charon->kernel_interface->add_policy(charon->kernel_interface, - this->me, this->other, - policy->my_net, policy->other_net, - policy->my_net_mask, policy->other_net_mask, - XFRM_POLICY_OUT, policy->upper_proto, - this->my_ah_spi, this->my_esp_spi, - this->reqid); - - status |= charon->kernel_interface->add_policy(charon->kernel_interface, - this->other, this->me, - policy->other_net, policy->my_net, - policy->other_net_mask, policy->my_net_mask, - XFRM_POLICY_IN, policy->upper_proto, - this->my_ah_spi, this->my_esp_spi, - this->reqid); - - status |= charon->kernel_interface->add_policy(charon->kernel_interface, - this->other, this->me, - policy->other_net, policy->my_net, - policy->other_net_mask, policy->my_net_mask, - XFRM_POLICY_FWD, policy->upper_proto, - this->my_ah_spi, this->my_esp_spi, - this->reqid); - - if (status != SUCCESS) - { - my_iter->destroy(my_iter); - other_iter->destroy(other_iter); - policy->my_net->destroy(policy->my_net); - policy->other_net->destroy(policy->other_net); - free(policy); - return status; - } - - /* add it to the policy list, since we want to know which policies we own */ - this->policies->insert_last(this->policies, policy); - } - } - - my_iter->destroy(my_iter); - other_iter->destroy(other_iter); - return SUCCESS; -} - -/** - * Implementation of child_sa_t.log_status. - */ -static void log_status(private_child_sa_t *this, logger_t *logger, char* name) -{ - iterator_t *iterator; - sa_policy_t *policy; - struct protoent *proto; - char proto_buf[8] = ""; - char *proto_name = proto_buf; - - if (logger == NULL) - { - logger = this->logger; - } - logger->log(logger, CONTROL|LEVEL1, "\"%s\": protected with ESP (0x%x/0x%x), AH (0x%x,0x%x):", - name, - htonl(this->my_esp_spi), htonl(this->other_esp_spi), - htonl(this->my_ah_spi), htonl(this->other_ah_spi)); - iterator = this->policies->create_iterator(this->policies, TRUE); - while (iterator->has_next(iterator)) - { - iterator->current(iterator, (void**)&policy); - if (policy->upper_proto) - { - proto = getprotobynumber(policy->upper_proto); - if (proto) - { - proto_name = proto->p_name; - } - else - { - snprintf(proto_buf, sizeof(proto_buf), "<%d>", policy->upper_proto); - } - } - logger->log(logger, CONTROL, "\"%s\": %s/%d==%s==%s/%d", - name, - policy->my_net->get_address(policy->my_net), policy->my_net_mask, - proto_name, - policy->other_net->get_address(policy->other_net), policy->other_net_mask); - } - iterator->destroy(iterator); -} - -/** - * Implementation of child_sa_t.destroy. - */ -static void destroy(private_child_sa_t *this) -{ - /* delete all policys in the kernel */ - sa_policy_t *policy; - while (this->policies->remove_last(this->policies, (void**)&policy) == SUCCESS) - { - charon->kernel_interface->del_policy(charon->kernel_interface, - this->me, this->other, - policy->my_net, policy->other_net, - policy->my_net_mask, policy->other_net_mask, - XFRM_POLICY_OUT, policy->upper_proto); - - charon->kernel_interface->del_policy(charon->kernel_interface, - this->other, this->me, - policy->other_net, policy->my_net, - policy->other_net_mask, policy->my_net_mask, - XFRM_POLICY_IN, policy->upper_proto); - - charon->kernel_interface->del_policy(charon->kernel_interface, - this->other, this->me, - policy->other_net, policy->my_net, - policy->other_net_mask, policy->my_net_mask, - XFRM_POLICY_FWD, policy->upper_proto); - - policy->my_net->destroy(policy->my_net); - policy->other_net->destroy(policy->other_net); - free(policy); - } - this->policies->destroy(this->policies); - - /* delete SAs in the kernel, if they are set up */ - if (this->my_ah_spi) - { - charon->kernel_interface->del_sa(charon->kernel_interface, - this->other, this->my_ah_spi, PROTO_AH); - charon->kernel_interface->del_sa(charon->kernel_interface, - this->me, this->other_ah_spi, PROTO_AH); - } - if (this->my_esp_spi) - { - charon->kernel_interface->del_sa(charon->kernel_interface, - this->other, this->my_esp_spi, PROTO_ESP); - charon->kernel_interface->del_sa(charon->kernel_interface, - this->me, this->other_esp_spi, PROTO_ESP); - } - free(this); -} - -/* - * Described in header. - */ -child_sa_t * child_sa_create(host_t *me, host_t* other) -{ - static u_int32_t reqid = 0xc0000000; - private_child_sa_t *this = malloc_thing(private_child_sa_t); - - /* public functions */ - this->public.alloc = (status_t(*)(child_sa_t*,linked_list_t*))alloc; - this->public.add = (status_t(*)(child_sa_t*,proposal_t*,prf_plus_t*))add; - this->public.update = (status_t(*)(child_sa_t*,proposal_t*,prf_plus_t*))update; - this->public.add_policies = (status_t (*)(child_sa_t*, linked_list_t*,linked_list_t*))add_policies; - this->public.log_status = (void (*)(child_sa_t*, logger_t*, char*))log_status; - this->public.destroy = (void(*)(child_sa_t*))destroy; - - /* private data */ - this->logger = logger_manager->get_logger(logger_manager, CHILD_SA); - this->me = me; - this->other = other; - this->my_ah_spi = 0; - this->my_esp_spi = 0; - this->other_ah_spi = 0; - this->other_esp_spi = 0; - this->reqid = reqid++; - this->policies = linked_list_create(); - - return (&this->public); -} diff --git a/src/charon/charon/sa/child_sa.h b/src/charon/charon/sa/child_sa.h deleted file mode 100644 index 6ccbff13f..000000000 --- a/src/charon/charon/sa/child_sa.h +++ /dev/null @@ -1,149 +0,0 @@ -/** - * @file child_sa.h - * - * @brief Interface of child_sa_t. - * - */ - -/* - * Copyright (C) 2005 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - - -#ifndef CHILD_SA_H_ -#define CHILD_SA_H_ - -#include -#include -#include -#include - -typedef struct child_sa_t child_sa_t; - -/** - * @brief Represents multiple IPsec SAs between two hosts. - * - * A child_sa_t contains multiple SAs. SAs for both - * directions are managed in one child_sa_t object, and - * if both AH and ESP is set up, both protocols are managed - * by one child_sa_t. This means we can have two or - * in the AH+ESP case four IPsec-SAs in one child_sa_t. - * - * The procedure for child sa setup is as follows: - * - A gets SPIs for a proposal via child_sa_t.alloc - * - A send the updated proposal to B - * - B selects a suitable proposal - * - B calls child_sa_t.add to add and update the selected proposal - * - B sends the updated proposal to A - * - A calls child_sa_t.update to update the already allocated SPIs with the chosen proposal - * - * Once SAs are set up, policies can be added using add_policies. - * - * - * @b Constructors: - * - child_sa_create() - * - * @ingroup sa - */ -struct child_sa_t { - - /** - * @brief Allocate SPIs for a given proposals. - * - * Since the kernel manages SPIs for us, we need - * to allocate them. If the proposal contains more - * than one protocol, for each protocol an SPI is - * allocated. SPIs are stored internally and written - * back to the proposal. - * - * @param this calling object - * @param proposal proposal for which SPIs are allocated - */ - status_t (*alloc)(child_sa_t *this, linked_list_t* proposals); - - /** - * @brief Install the kernel SAs for a proposal. - * - * Since the kernel manages SPIs for us, we need - * to allocate them. If the proposal contains more - * than one protocol, for each protocol an SPI is - * allocated. SPIs are stored internally and written - * back to the proposal. - * - * @param this calling object - * @param proposal proposal for which SPIs are allocated - * @param prf_plus key material to use for key derivation - */ - status_t (*add)(child_sa_t *this, proposal_t *proposal, prf_plus_t *prf_plus); - - /** - * @brief Install the kernel SAs for a proposal, if SPIs already allocated. - * - * This one updates the SAs in the kernel, which are - * allocated via alloc, with a selected proposals. - * - * @param this calling object - * @param proposal proposal for which SPIs are allocated - * @param prf_plus key material to use for key derivation - */ - status_t (*update)(child_sa_t *this, proposal_t *proposal, prf_plus_t *prf_plus); - - /** - * @brief Install the policies using some traffic selectors. - * - * Spplied lists of traffic_selector_t's specify the policies - * to use for this child sa. - * - * @param this calling object - * @param my_ts traffic selectors for local site - * @param other_ts traffic selectors for remote site - * @return SUCCESS or FAILED - */ - status_t (*add_policies) (child_sa_t *this, linked_list_t *my_ts_list, linked_list_t *other_ts_list); - - /** - * @brief Log the status of a child_sa to a logger. - * - * The status of ESP/AH SAs is logged with the supplied logger in - * a human readable form. - * Supplying NULL as logger uses the internal child_sa logger - * to do the logging. The name is only a log-prefix without further - * meaning. - * - * @param this calling object - * @param logger logger to use for logging - * @param name connection name - */ - void (*log_status) (child_sa_t *this, logger_t *logger, char *name); - - /** - * @brief Destroys a child_sa. - * - * @param this calling object - */ - void (*destroy) (child_sa_t *this); -}; - -/** - * @brief Constructor to create a new child_sa_t. - * - * @param me own address - * @param other remote address - * @return child_sa_t object - * - * @ingroup sa - */ -child_sa_t * child_sa_create(host_t *me, host_t *other); - -#endif /*CHILD_SA_H_*/ diff --git a/src/charon/charon/sa/ike_sa.c b/src/charon/charon/sa/ike_sa.c deleted file mode 100644 index 6322eb8e9..000000000 --- a/src/charon/charon/sa/ike_sa.c +++ /dev/null @@ -1,1199 +0,0 @@ -/** - * @file ike_sa.c - * - * @brief Implementation of ike_sa_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 - -#include "ike_sa.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - - - -typedef struct private_ike_sa_t private_ike_sa_t; - -/** - * Private data of an ike_sa_t object. - */ -struct private_ike_sa_t { - - /** - * Protected part of a ike_sa_t object. - */ - protected_ike_sa_t protected; - - /** - * Identifier for the current IKE_SA. - */ - ike_sa_id_t *ike_sa_id; - - /** - * Linked List containing the child sa's of the current IKE_SA. - */ - linked_list_t *child_sas; - - /** - * Current state of the IKE_SA represented as state_t object. - * - * A state object representates one of the following states and is processing - * messages in the specific state: - * - INITIATOR_INIT - * - RESPONDER_INIT - * - IKE_SA_INIT_REQUESTED - * - IKE_SA_INIT_RESPONDED - * - IKE_AUTH_REQUESTED - * -IKE_SA_ESTABLISHED - */ - state_t *current_state; - - /** - * INIT configuration, needed for the IKE_SA_INIT exchange. - * - * Gets set in states: - * - INITATOR_INIT - * - RESPONDER_INIT - * - * Available in states: - * - IKE_SA_INIT_REQUESTED - * - IKE_SA_INIT_RESPONDED - * - IKE_AUTH_REQUESTED - * -IKE_SA_ESTABLISHED - */ - connection_t *connection; - - /** - * SA configuration, needed for all other exchanges after IKE_SA_INIT exchange. - * - * Gets set in states: - * - IKE_SA_INIT_REQUESTED - * - IKE_SA_INIT_RESPONDED - * - * Available in states: - * - IKE_AUTH_REQUESTED - * -IKE_SA_ESTABLISHED - */ - policy_t *policy; - - /** - * This SA's source for random data. - * - * Is available in every state. - */ - randomizer_t *randomizer; - - /** - * The last responded message. - */ - message_t *last_responded_message; - - /** - * The ast requested message. - */ - message_t *last_requested_message; - - /** - * Crypter object for initiator. - */ - crypter_t *crypter_initiator; - - /** - * Crypter object for responder. - */ - crypter_t *crypter_responder; - - /** - * Signer object for initiator. - */ - signer_t *signer_initiator; - - /** - * Signer object for responder. - */ - signer_t *signer_responder; - - /** - * Multi purpose prf, set key, use it, forget it - */ - prf_t *prf; - - /** - * Prf function for derivating keymat child SAs - */ - prf_t *child_prf; - - /** - * PRF, with key set to pi_key, used for authentication - */ - prf_t *prf_auth_i; - - /** - * PRF, with key set to pr_key, used for authentication - */ - prf_t *prf_auth_r; - - /** - * Next message id to receive. - */ - u_int32_t message_id_in; - - /** - * Next message id to send. - */ - u_int32_t message_id_out; - - /** - * Last reply id which was successfully received. - */ - int32_t last_replied_message_id; - - /** - * A logger for this IKE_SA. - */ - logger_t *logger; - - /** - * Resends the last sent reply. - * - * @param this calling object - */ - status_t (*resend_last_reply) (private_ike_sa_t *this); -}; - -/** - * Implementation of ike_sa_t.process_message. - */ -static status_t process_message (private_ike_sa_t *this, message_t *message) -{ - u_int32_t message_id; - exchange_type_t exchange_type; - bool is_request; - - /* We must process each request or response from remote host */ - - /* Find out type of message (request or response) */ - is_request = message->get_request(message); - exchange_type = message->get_exchange_type(message); - - this->logger->log(this->logger, CONTROL|LEVEL1, "Process %s of exchange type %s", - (is_request) ? "request" : "response",mapping_find(exchange_type_m,exchange_type)); - - message_id = message->get_message_id(message); - - /* - * It has to be checked, if the message has to be resent cause of lost packets! - */ - if (is_request && (message_id == (this->message_id_in - 1))) - { - /* Message can be resent ! */ - this->logger->log(this->logger, CONTROL|LEVEL1, "Resent request detected. Send stored reply."); - return (this->resend_last_reply(this)); - } - - /* Now, the message id is checked for request AND reply */ - if (is_request) - { - /* In a request, the message has to be this->message_id_in (other case is already handled) */ - if (message_id != this->message_id_in) - { - this->logger->log(this->logger, ERROR | LEVEL1, - "Message request with message id %d received, but %d expected", - message_id,this->message_id_in); - return FAILED; - } - } - else - { - /* In a reply, the message has to be this->message_id_out -1 cause it is the reply to the last sent message*/ - if (message_id != (this->message_id_out - 1)) - { - this->logger->log(this->logger, ERROR | LEVEL1, - "Message reply with message id %d received, but %d expected", - message_id,this->message_id_in); - return FAILED; - } - } - - /* now the message is processed by the current state object. - * The specific state object is responsible to check if a message can be received in - * the state it represents. - * The current state is also responsible to change the state object to the next state - * by calling protected_ike_sa_t.set_new_state*/ - return this->current_state->process_message(this->current_state,message); -} - -/** - * Implementation of protected_ike_sa_t.build_message. - */ -static void build_message(private_ike_sa_t *this, exchange_type_t type, bool request, message_t **message) -{ - message_t *new_message; - host_t *me, *other; - - me = this->connection->get_my_host(this->connection); - other = this->connection->get_other_host(this->connection); - - this->logger->log(this->logger, CONTROL|LEVEL2, "Build empty message"); - new_message = message_create(); - new_message->set_source(new_message, me->clone(me)); - new_message->set_destination(new_message, other->clone(other)); - new_message->set_exchange_type(new_message, type); - new_message->set_request(new_message, request); - new_message->set_message_id(new_message, (request) ? this->message_id_out : this->message_id_in); - new_message->set_ike_sa_id(new_message, this->ike_sa_id); - - *message = new_message; -} - -/** - * Implementation of protected_ike_sa_t.initiate_connection. - */ -static status_t initiate_connection(private_ike_sa_t *this, connection_t *connection) -{ - initiator_init_t *current_state; - - /* Work is done in state object of type INITIATOR_INIT. All other states are not - * initial states and so don't have a initiate_connection function */ - - if (this->current_state->get_state(this->current_state) != INITIATOR_INIT) - { - return FAILED; - } - - current_state = (initiator_init_t *) this->current_state; - - return current_state->initiate_connection(current_state, connection); -} - -/** - * Implementation of ike_sa_t.send_delete_ike_sa_request. - */ -static void send_delete_ike_sa_request (private_ike_sa_t *this) -{ - message_t *informational_request; - delete_payload_t *delete_payload; - crypter_t *crypter; - signer_t *signer; - packet_t *packet; - status_t status; - - if (this->current_state->get_state(this->current_state) != IKE_SA_ESTABLISHED) - { - return; - } - - /* build empty INFORMATIONAL message */ - this->protected.build_message(&(this->protected), INFORMATIONAL, TRUE, &informational_request); - - delete_payload = delete_payload_create(); - delete_payload->set_protocol_id(delete_payload, PROTO_IKE); - - informational_request->add_payload(informational_request,(payload_t *)delete_payload); - - if (this->ike_sa_id->is_initiator(this->ike_sa_id)) - { - crypter = this->crypter_initiator; - signer = this->signer_initiator; - } - else - { - crypter = this->crypter_responder; - signer = this->signer_responder; - } - - status = informational_request->generate(informational_request, - crypter, - signer, &packet); - informational_request->destroy(informational_request); - if (status != SUCCESS) - { - this->logger->log(this->logger, ERROR, "Could not generate packet from message"); - return ; - } - - charon->send_queue->add(charon->send_queue,packet); -} - -/** - * Implementation of ike_sa_t.get_id. - */ -static ike_sa_id_t* get_id(private_ike_sa_t *this) -{ - return this->ike_sa_id; -} - -/** - * Implementation of ike_sa_t.get_my_host. - */ -static host_t* get_my_host(private_ike_sa_t *this) -{ - return this->connection->get_my_host(this->connection);; -} - -/** - * Implementation of ike_sa_t.get_other_host. - */ -static host_t* get_other_host(private_ike_sa_t *this) -{ - return this->connection->get_other_host(this->connection);; -} - -/** - * Implementation of ike_sa_t.get_my_id. - */ -static identification_t* get_my_id(private_ike_sa_t *this) -{ - return this->connection->get_my_id(this->connection);; -} - -/** - * Implementation of ike_sa_t.get_other_id. - */ -static identification_t* get_other_id(private_ike_sa_t *this) -{ - return this->connection->get_other_id(this->connection);; -} - -/** - * Implementation of private_ike_sa_t.resend_last_reply. - */ -static status_t resend_last_reply(private_ike_sa_t *this) -{ - packet_t *packet; - - this->logger->log(this->logger, CONTROL | LEVEL1, "Going to retransmit last reply"); - packet = this->last_responded_message->get_packet(this->last_responded_message); - charon->send_queue->add(charon->send_queue, packet); - - return SUCCESS; -} - -/** - * Implementation of ike_sa_t.retransmit_request. - */ -status_t retransmit_request (private_ike_sa_t *this, u_int32_t message_id) -{ - packet_t *packet; - - if (this->last_requested_message == NULL) - { - return NOT_FOUND; - } - - if (message_id == this->last_replied_message_id) - { - return NOT_FOUND; - } - - if ((this->last_requested_message->get_message_id(this->last_requested_message)) != message_id) - { - return NOT_FOUND; - } - - this->logger->log(this->logger, CONTROL | LEVEL1, "Going to retransmit message with id %d",message_id); - packet = this->last_requested_message->get_packet(this->last_requested_message); - charon->send_queue->add(charon->send_queue, packet); - - return SUCCESS; -} - -/** - * Implementation of protected_ike_sa_t.set_new_state. - */ -static void set_new_state (private_ike_sa_t *this, state_t *state) -{ - this->logger->log(this->logger, CONTROL, "statechange: %s => %s", - mapping_find(ike_sa_state_m,this->current_state->get_state(this->current_state)), - mapping_find(ike_sa_state_m,state->get_state(state))); - this->current_state = state; -} - -/** - * Implementation of protected_ike_sa_t.get_connection. - */ -static connection_t *get_connection (private_ike_sa_t *this) -{ - return this->connection; -} - -/** - * Implementation of protected_ike_sa_t.set_connection. - */ -static void set_connection (private_ike_sa_t *this,connection_t * connection) -{ - this->connection = connection; -} - -/** - * Implementation of protected_ike_sa_t.get_policy. - */ -static policy_t *get_policy (private_ike_sa_t *this) -{ - return this->policy; -} - -/** - * Implementation of protected_ike_sa_t.set_policy. - */ -static void set_policy (private_ike_sa_t *this,policy_t * policy) -{ - this->policy = policy; -} - -/** - * Implementation of protected_ike_sa_t.get_prf. - */ -static prf_t *get_prf (private_ike_sa_t *this) -{ - return this->prf; -} - -/** - * Implementation of protected_ike_sa_t.get_prf. - */ -static prf_t *get_child_prf (private_ike_sa_t *this) -{ - return this->child_prf; -} - -/** - * Implementation of protected_ike_sa_t.get_prf_auth_i. - */ -static prf_t *get_prf_auth_i (private_ike_sa_t *this) -{ - return this->prf_auth_i; -} - -/** - * Implementation of protected_ike_sa_t.get_prf_auth_r. - */ -static prf_t *get_prf_auth_r (private_ike_sa_t *this) -{ - return this->prf_auth_r; -} - - -/** - * Implementation of protected_ike_sa_t.build_transforms. - */ -static status_t build_transforms(private_ike_sa_t *this, proposal_t *proposal, diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r) -{ - chunk_t nonces, nonces_spis, skeyseed, key, secret; - u_int64_t spi_i, spi_r; - prf_plus_t *prf_plus; - algorithm_t *algo; - size_t key_size; - - /* - * Build the PRF+ instance for deriving keys - */ - if (this->prf != NULL) - { - this->prf->destroy(this->prf); - } - proposal->get_algorithm(proposal, PROTO_IKE, PSEUDO_RANDOM_FUNCTION, &algo); - if (algo == NULL) - { - this->logger->log(this->logger, ERROR|LEVEL2, "No PRF algoithm selected!?"); - return FAILED; - } - this->prf = prf_create(algo->algorithm); - if (this->prf == NULL) - { - this->logger->log(this->logger, ERROR|LEVEL1, - "PSEUDO_RANDOM_FUNCTION %s not supported!", - mapping_find(pseudo_random_function_m, algo->algorithm)); - return FAILED; - } - - /* concatenate nonces = nonce_i | nonce_r */ - nonces = chunk_alloc(nonce_i.len + nonce_r.len); - memcpy(nonces.ptr, nonce_i.ptr, nonce_i.len); - memcpy(nonces.ptr + nonce_i.len, nonce_r.ptr, nonce_r.len); - - /* concatenate prf_seed = nonce_i | nonce_r | spi_i | spi_r */ - nonces_spis = chunk_alloc(nonces.len + 16); - memcpy(nonces_spis.ptr, nonces.ptr, nonces.len); - spi_i = this->ike_sa_id->get_initiator_spi(this->ike_sa_id); - spi_r = this->ike_sa_id->get_responder_spi(this->ike_sa_id); - memcpy(nonces_spis.ptr + nonces.len, &spi_i, 8); - memcpy(nonces_spis.ptr + nonces.len + 8, &spi_r, 8); - - /* SKEYSEED = prf(Ni | Nr, g^ir) */ - dh->get_shared_secret(dh, &secret); - this->logger->log_chunk(this->logger, PRIVATE, "Shared Diffie Hellman secret", secret); - this->prf->set_key(this->prf, nonces); - this->prf->allocate_bytes(this->prf, secret, &skeyseed); - this->logger->log_chunk(this->logger, PRIVATE | LEVEL1, "SKEYSEED", skeyseed); - chunk_free(&secret); - - /* prf+ (SKEYSEED, Ni | Nr | SPIi | SPIr ) - * = SK_d | SK_ai | SK_ar | SK_ei | SK_er | SK_pi | SK_pr - * - * we use the prf directly for prf+ - */ - this->prf->set_key(this->prf, skeyseed); - prf_plus = prf_plus_create(this->prf, nonces_spis); - - /* clean up unused stuff */ - chunk_free(&nonces); - chunk_free(&nonces_spis); - chunk_free(&skeyseed); - - - /* - * We now can derive all of our key. We build the transforms - * directly. - */ - - - /* SK_d used for prf+ to derive keys for child SAs */ - this->child_prf = prf_create(algo->algorithm); - key_size = this->child_prf->get_key_size(this->child_prf); - prf_plus->allocate_bytes(prf_plus, key_size, &key); - this->logger->log_chunk(this->logger, PRIVATE, "Sk_d secret", key); - this->child_prf->set_key(this->child_prf, key); - chunk_free(&key); - - - /* SK_ai/SK_ar used for integrity protection */ - proposal->get_algorithm(proposal, PROTO_IKE, INTEGRITY_ALGORITHM, &algo); - if (algo == NULL) - { - this->logger->log(this->logger, ERROR|LEVEL2, "No integrity algoithm selected?!"); - return FAILED; - } - if (this->signer_initiator != NULL) - { - this->signer_initiator->destroy(this->signer_initiator); - } - if (this->signer_responder != NULL) - { - this->signer_responder->destroy(this->signer_responder); - } - - this->signer_initiator = signer_create(algo->algorithm); - this->signer_responder = signer_create(algo->algorithm); - if (this->signer_initiator == NULL || this->signer_responder == NULL) - { - this->logger->log(this->logger, ERROR|LEVEL1, - "INTEGRITY_ALGORITHM %s not supported!", - mapping_find(integrity_algorithm_m,algo->algorithm)); - return FAILED; - } - key_size = this->signer_initiator->get_key_size(this->signer_initiator); - - prf_plus->allocate_bytes(prf_plus, key_size, &key); - this->logger->log_chunk(this->logger, PRIVATE, "Sk_ai secret", key); - this->signer_initiator->set_key(this->signer_initiator, key); - chunk_free(&key); - - prf_plus->allocate_bytes(prf_plus, key_size, &key); - this->logger->log_chunk(this->logger, PRIVATE, "Sk_ar secret", key); - this->signer_responder->set_key(this->signer_responder, key); - chunk_free(&key); - - - /* SK_ei/SK_er used for encryption */ - proposal->get_algorithm(proposal, PROTO_IKE, ENCRYPTION_ALGORITHM, &algo); - if (algo == NULL) - { - this->logger->log(this->logger, ERROR|LEVEL2, "No encryption algoithm selected!?"); - return FAILED; - } - if (this->crypter_initiator != NULL) - { - this->crypter_initiator->destroy(this->crypter_initiator); - } - if (this->crypter_responder != NULL) - { - this->crypter_responder->destroy(this->crypter_responder); - } - - this->crypter_initiator = crypter_create(algo->algorithm, algo->key_size); - this->crypter_responder = crypter_create(algo->algorithm, algo->key_size); - if (this->crypter_initiator == NULL || this->crypter_responder == NULL) - { - this->logger->log(this->logger, ERROR|LEVEL1, - "ENCRYPTION_ALGORITHM %s (key size %d) not supported!", - mapping_find(encryption_algorithm_m, algo->algorithm), - algo->key_size); - return FAILED; - } - key_size = this->crypter_initiator->get_key_size(this->crypter_initiator); - - prf_plus->allocate_bytes(prf_plus, key_size, &key); - this->logger->log_chunk(this->logger, PRIVATE, "Sk_ei secret", key); - this->crypter_initiator->set_key(this->crypter_initiator, key); - chunk_free(&key); - - prf_plus->allocate_bytes(prf_plus, key_size, &key); - this->logger->log_chunk(this->logger, PRIVATE, "Sk_er secret", key); - this->crypter_responder->set_key(this->crypter_responder, key); - chunk_free(&key); - - /* SK_pi/SK_pr used for authentication */ - proposal->get_algorithm(proposal, PROTO_IKE, PSEUDO_RANDOM_FUNCTION, &algo); - if (this->prf_auth_i != NULL) - { - this->prf_auth_i->destroy(this->prf_auth_i); - } - if (this->prf_auth_r != NULL) - { - this->prf_auth_r->destroy(this->prf_auth_r); - } - - this->prf_auth_i = prf_create(algo->algorithm); - this->prf_auth_r = prf_create(algo->algorithm); - - key_size = this->prf_auth_i->get_key_size(this->prf_auth_i); - prf_plus->allocate_bytes(prf_plus, key_size, &key); - this->logger->log_chunk(this->logger, PRIVATE, "Sk_pi secret", key); - this->prf_auth_i->set_key(this->prf_auth_i, key); - chunk_free(&key); - - prf_plus->allocate_bytes(prf_plus, key_size, &key); - this->logger->log_chunk(this->logger, PRIVATE, "Sk_pr secret", key); - this->prf_auth_r->set_key(this->prf_auth_r, key); - chunk_free(&key); - - /* all done, prf_plus not needed anymore */ - prf_plus->destroy(prf_plus); - - return SUCCESS; -} - -/** - * Implementation of protected_ike_sa_t.get_randomizer. - */ -static randomizer_t *get_randomizer (private_ike_sa_t *this) -{ - return this->randomizer; -} - -/** - * Implementation of protected_ike_sa_t.get_crypter_initiator. - */ -static crypter_t *get_crypter_initiator (private_ike_sa_t *this) -{ - return this->crypter_initiator; -} - -/** - * Implementation of protected_ike_sa_t.get_signer_initiator. - */ -static signer_t *get_signer_initiator (private_ike_sa_t *this) -{ - return this->signer_initiator; -} - -/** - * Implementation of protected_ike_sa_t.get_crypter_responder. - */ -static crypter_t *get_crypter_responder(private_ike_sa_t *this) -{ - return this->crypter_responder; -} - -/** - * Implementation of protected_ike_sa_t.get_signer_responder. - */ -static signer_t *get_signer_responder (private_ike_sa_t *this) -{ - return this->signer_responder; -} - -/** - * Implementation of protected_ike_sa_t.send_request. - */ -static status_t send_request (private_ike_sa_t *this,message_t * message) -{ - retransmit_request_job_t *retransmit_job; - u_int32_t timeout; - crypter_t *crypter; - signer_t *signer; - packet_t *packet; - status_t status; - - if (message->get_message_id(message) != this->message_id_out) - { - this->logger->log(this->logger, ERROR, "Message could not be sent cause id (%d) was not as expected (%d)", - message->get_message_id(message),this->message_id_out); - return FAILED; - } - - /* generate packet */ - this->logger->log(this->logger, CONTROL|LEVEL2, "Generate packet from message"); - - if (this->ike_sa_id->is_initiator(this->ike_sa_id)) - { - crypter = this->crypter_initiator; - signer = this->signer_initiator; - } - else - { - crypter = this->crypter_responder; - signer =this->signer_responder; - } - - status = message->generate(message, crypter,signer, &packet); - if (status != SUCCESS) - { - this->logger->log(this->logger, ERROR, "Could not generate packet from message"); - return FAILED; - } - - this->logger->log(this->logger, CONTROL|LEVEL3, - "Add request packet with message id %d to global send queue", - this->message_id_out); - charon->send_queue->add(charon->send_queue, packet); - - if (this->last_requested_message != NULL) - { - /* destroy message */ - this->last_requested_message->destroy(this->last_requested_message); - } - - this->logger->log(this->logger, CONTROL|LEVEL3, "Replace last requested message with new one"); - this->last_requested_message = message; - - retransmit_job = retransmit_request_job_create(this->message_id_out,this->ike_sa_id); - - status = charon->configuration->get_retransmit_timeout (charon->configuration, - retransmit_job->get_retransmit_count(retransmit_job),&timeout); - - if (status != SUCCESS) - { - this->logger->log(this->logger, CONTROL|LEVEL2, "No retransmit job for message created!"); - retransmit_job->destroy(retransmit_job); - } - else - { - this->logger->log(this->logger, CONTROL|LEVEL2, "Request will be retransmitted in %d ms.",timeout); - charon->event_queue->add_relative(charon->event_queue,(job_t *) retransmit_job,timeout); - } - - /* message counter can now be increased */ - this->logger->log(this->logger, CONTROL|LEVEL3, - "Increase message counter for outgoing messages from %d", - this->message_id_out); - this->message_id_out++; - return SUCCESS; -} - -/** - * Implementation of protected_ike_sa_t.send_response. - */ -static status_t send_response (private_ike_sa_t *this,message_t * message) -{ - crypter_t *crypter; - signer_t *signer; - packet_t *packet; - status_t status; - - if (message->get_message_id(message) != this->message_id_in) - { - this->logger->log(this->logger, ERROR, "Message could not be sent cause id was not as expected"); - return FAILED; - } - - - if (this->ike_sa_id->is_initiator(this->ike_sa_id)) - { - crypter = this->crypter_initiator; - signer = this->signer_initiator; - } - else - { - crypter = this->crypter_responder; - signer =this->signer_responder; - } - - status = message->generate(message, crypter,signer, &packet); - if (status != SUCCESS) - { - this->logger->log(this->logger, ERROR, "Could not generate packet from message"); - return FAILED; - } - - this->logger->log(this->logger, CONTROL|LEVEL3, - "Add response packet with message id %d to global send queue", - this->message_id_in); - charon->send_queue->add(charon->send_queue, packet); - - if (this->last_responded_message != NULL) - { - /* destroy message */ - this->last_responded_message->destroy(this->last_responded_message); - } - - this->logger->log(this->logger, CONTROL|LEVEL3, "Replace last responded message with new one"); - this->last_responded_message = message; - - /* message counter can now be increased */ - this->logger->log(this->logger, CONTROL|LEVEL3, "Increase message counter for incoming messages"); - this->message_id_in++; - - return SUCCESS; -} - -/** - * Implementation of of private_responder_init_t.send_notify_reply. - */ -static void send_notify(private_ike_sa_t *this, exchange_type_t exchange_type, notify_message_type_t type, chunk_t data) -{ - notify_payload_t *payload; - message_t *response; - packet_t *packet; - status_t status; - - this->logger->log(this->logger, CONTROL|LEVEL2, "Going to build message with notify payload"); - /* set up the reply */ - this->protected.build_message(&(this->protected), exchange_type, FALSE, &response); - payload = notify_payload_create_from_protocol_and_type(PROTO_IKE, type); - if ((data.ptr != NULL) && (data.len > 0)) - { - this->logger->log(this->logger, CONTROL|LEVEL2, "Add Data to notify payload"); - payload->set_notification_data(payload,data); - } - - this->logger->log(this->logger, CONTROL|LEVEL2, "Add Notify payload to message"); - response->add_payload(response,(payload_t *) payload); - - /* generate packet */ - this->logger->log(this->logger, CONTROL|LEVEL2, "Generate packet from message"); - status = response->generate(response, this->crypter_responder, this->signer_responder, &packet); - if (status != SUCCESS) - { - this->logger->log(this->logger, ERROR|LEVEL1, "Could not generate notify message"); - response->destroy(response); - return; - } - - this->logger->log(this->logger, CONTROL|LEVEL2, "Add packet to global send queue"); - charon->send_queue->add(charon->send_queue, packet); - this->logger->log(this->logger, CONTROL|LEVEL2, "Destroy message"); - response->destroy(response); -} - -/** - * Implementation of protected_ike_sa_t.set_last_replied_message_id. - */ -static void set_last_replied_message_id (private_ike_sa_t *this,u_int32_t message_id) -{ - this->last_replied_message_id = message_id; -} - -/** - * Implementation of protected_ike_sa_t.get_last_responded_message. - */ -static message_t * get_last_responded_message (private_ike_sa_t *this) -{ - return this->last_responded_message; -} - -/** - * Implementation of protected_ike_sa_t.get_last_requested_message. - */ -static message_t * get_last_requested_message (private_ike_sa_t *this) -{ - return this->last_requested_message; -} - -/** - * Implementation of protected_ike_sa_t.get_state. - */ -static ike_sa_state_t get_state (private_ike_sa_t *this) -{ - return this->current_state->get_state(this->current_state); -} - -/** - * Implementation of protected_ike_sa_t.get_state. - */ -static void add_child_sa (private_ike_sa_t *this, child_sa_t *child_sa) -{ - this->child_sas->insert_last(this->child_sas, child_sa); -} - -/** - * Implementation of protected_ike_sa_t.reset_message_buffers. - */ -static void reset_message_buffers (private_ike_sa_t *this) -{ - this->logger->log(this->logger, CONTROL|LEVEL2, "Reset message counters and destroy stored messages"); - /* destroy stored requested message */ - if (this->last_requested_message != NULL) - { - this->last_requested_message->destroy(this->last_requested_message); - this->last_requested_message = NULL; - } - - /* destroy stored responded messages */ - if (this->last_responded_message != NULL) - { - this->last_responded_message->destroy(this->last_responded_message); - this->last_responded_message = NULL; - } - - this->message_id_out = 0; - this->message_id_in = 0; - this->last_replied_message_id = -1; -} - -/** - * Implementation of protected_ike_sa_t.log_status. - */ -static void log_status(private_ike_sa_t *this, logger_t *logger, char *name) -{ - iterator_t *iterator; - child_sa_t *child_sa; - - /* only log if name == NULL or name == connection_name */ - if (name) - { - if (strcmp(this->connection->get_name(this->connection), name) != 0) - { - return; - } - } - else - { - name = this->connection->get_name(this->connection); - } - - host_t *my_host = this->connection->get_my_host(this->connection); - host_t *other_host = this->connection->get_other_host(this->connection); - - identification_t *my_id = this->connection->get_my_id(this->connection); - identification_t *other_id = this->connection->get_other_id(this->connection); - - if (logger == NULL) - { - logger = this->logger; - } - logger->log(logger, CONTROL|LEVEL1, "\"%s\": IKE_SA in state %s, SPIs: 0x%.16llx 0x%.16llx", - name, - mapping_find(ike_sa_state_m, this->current_state->get_state(this->current_state)), - this->ike_sa_id->get_initiator_spi(this->ike_sa_id), - this->ike_sa_id->get_responder_spi(this->ike_sa_id)); - logger->log(logger, CONTROL, "\"%s\": %s[%s]...%s[%s]", - name, - my_host->get_address(my_host), - my_id->get_string(my_id), - other_host->get_address(other_host), - other_id->get_string(other_id)); - - iterator = this->child_sas->create_iterator(this->child_sas, TRUE); - while (iterator->has_next(iterator)) - { - iterator->current(iterator, (void**)&child_sa); - child_sa->log_status(child_sa, logger, name); - } - iterator->destroy(iterator); -} - -/** - * Implementation of protected_ike_sa_t.destroy. - */ -static void destroy (private_ike_sa_t *this) -{ - child_sa_t *child_sa; - - this->logger->log(this->logger, CONTROL|LEVEL2, "Going to destroy IKE SA %llu:%llu, role %s", - this->ike_sa_id->get_initiator_spi(this->ike_sa_id), - this->ike_sa_id->get_responder_spi(this->ike_sa_id), - this->ike_sa_id->is_initiator(this->ike_sa_id) ? "initiator" : "responder"); - - /* inform other peer of delete */ - send_delete_ike_sa_request(this); - while (this->child_sas->remove_last(this->child_sas, (void**)&child_sa) == SUCCESS) - { - child_sa->destroy(child_sa); - } - this->child_sas->destroy(this->child_sas); - - if (this->crypter_initiator) - { - this->crypter_initiator->destroy(this->crypter_initiator); - } - if (this->crypter_responder) - { - this->crypter_responder->destroy(this->crypter_responder); - } - if (this->signer_initiator) - { - this->signer_initiator->destroy(this->signer_initiator); - } - if (this->signer_responder) - { - this->signer_responder->destroy(this->signer_responder); - } - if (this->prf) - { - this->prf->destroy(this->prf); - } - if (this->child_prf) - { - this->child_prf->destroy(this->child_prf); - } - if (this->prf_auth_i) - { - this->prf_auth_i->destroy(this->prf_auth_i); - } - if (this->prf_auth_r) - { - this->prf_auth_r->destroy(this->prf_auth_r); - } - if (this->connection) - { - host_t *me, *other; - me = this->connection->get_my_host(this->connection); - other = this->connection->get_other_host(this->connection); - - this->logger->log(this->logger, AUDIT, "IKE_SA deleted between %s - %s", - me->get_address(me), other->get_address(other)); - this->connection->destroy(this->connection); - } - if (this->policy) - { - this->policy->destroy(this->policy); - } - if (this->last_requested_message) - { - this->last_requested_message->destroy(this->last_requested_message); - } - if (this->last_responded_message) - { - this->last_responded_message->destroy(this->last_responded_message); - } - this->ike_sa_id->destroy(this->ike_sa_id); - this->randomizer->destroy(this->randomizer); - this->current_state->destroy(this->current_state); - - free(this); -} - -/* - * Described in header. - */ -ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id) -{ - private_ike_sa_t *this = malloc_thing(private_ike_sa_t); - - /* Public functions */ - this->protected.public.process_message = (status_t(*)(ike_sa_t*, message_t*)) process_message; - this->protected.public.initiate_connection = (status_t(*)(ike_sa_t*,connection_t*)) initiate_connection; - this->protected.public.get_id = (ike_sa_id_t*(*)(ike_sa_t*)) get_id; - this->protected.public.get_my_host = (host_t*(*)(ike_sa_t*)) get_my_host; - this->protected.public.get_other_host = (host_t*(*)(ike_sa_t*)) get_other_host; - this->protected.public.get_my_id = (identification_t*(*)(ike_sa_t*)) get_my_id; - this->protected.public.get_other_id = (identification_t*(*)(ike_sa_t*)) get_other_id; - this->protected.public.get_connection = (connection_t*(*)(ike_sa_t*)) get_connection; - this->protected.public.retransmit_request = (status_t (*) (ike_sa_t *, u_int32_t)) retransmit_request; - this->protected.public.get_state = (ike_sa_state_t (*) (ike_sa_t *this)) get_state; - this->protected.public.send_delete_ike_sa_request = (void (*)(ike_sa_t*)) send_delete_ike_sa_request; - this->protected.public.log_status = (void (*) (ike_sa_t*,logger_t*,char*))log_status; - this->protected.public.destroy = (void(*)(ike_sa_t*))destroy; - - /* protected functions */ - this->protected.build_message = (void (*) (protected_ike_sa_t *, exchange_type_t , bool , message_t **)) build_message; - this->protected.get_prf = (prf_t *(*) (protected_ike_sa_t *)) get_prf; - this->protected.get_child_prf = (prf_t *(*) (protected_ike_sa_t *)) get_child_prf; - this->protected.get_prf_auth_i = (prf_t *(*) (protected_ike_sa_t *)) get_prf_auth_i; - this->protected.get_prf_auth_r = (prf_t *(*) (protected_ike_sa_t *)) get_prf_auth_r; - this->protected.add_child_sa = (void (*) (protected_ike_sa_t*,child_sa_t*)) add_child_sa; - this->protected.set_connection = (void (*) (protected_ike_sa_t *,connection_t *)) set_connection; - this->protected.get_connection = (connection_t *(*) (protected_ike_sa_t *)) get_connection; - this->protected.set_policy = (void (*) (protected_ike_sa_t *,policy_t *)) set_policy; - this->protected.get_policy = (policy_t *(*) (protected_ike_sa_t *)) get_policy; - this->protected.get_randomizer = (randomizer_t *(*) (protected_ike_sa_t *)) get_randomizer; - this->protected.send_request = (status_t (*) (protected_ike_sa_t *,message_t *)) send_request; - this->protected.send_response = (status_t (*) (protected_ike_sa_t *,message_t *)) send_response; - this->protected.send_notify = (void (*)(protected_ike_sa_t*,exchange_type_t,notify_message_type_t,chunk_t)) send_notify; - this->protected.build_transforms = (status_t (*) (protected_ike_sa_t *,proposal_t*,diffie_hellman_t*,chunk_t,chunk_t)) build_transforms; - this->protected.set_new_state = (void (*) (protected_ike_sa_t *,state_t *)) set_new_state; - this->protected.get_crypter_initiator = (crypter_t *(*) (protected_ike_sa_t *)) get_crypter_initiator; - this->protected.get_signer_initiator = (signer_t *(*) (protected_ike_sa_t *)) get_signer_initiator; - this->protected.get_crypter_responder = (crypter_t *(*) (protected_ike_sa_t *)) get_crypter_responder; - this->protected.get_signer_responder = (signer_t *(*) (protected_ike_sa_t *)) get_signer_responder; - this->protected.reset_message_buffers = (void (*) (protected_ike_sa_t *)) reset_message_buffers; - this->protected.get_last_responded_message = (message_t * (*) (protected_ike_sa_t *this)) get_last_responded_message; - this->protected.get_last_requested_message = (message_t * (*) (protected_ike_sa_t *this)) get_last_requested_message; - - this->protected.set_last_replied_message_id = (void (*) (protected_ike_sa_t *,u_int32_t)) set_last_replied_message_id; - - /* private functions */ - this->resend_last_reply = resend_last_reply; - - /* initialize private fields */ - this->logger = logger_manager->get_logger(logger_manager, IKE_SA); - - this->ike_sa_id = ike_sa_id->clone(ike_sa_id); - this->child_sas = linked_list_create(); - this->randomizer = randomizer_create(); - - this->last_requested_message = NULL; - this->last_responded_message = NULL; - this->message_id_out = 0; - this->message_id_in = 0; - this->last_replied_message_id = -1; - this->crypter_initiator = NULL; - this->crypter_responder = NULL; - this->signer_initiator = NULL; - this->signer_responder = NULL; - this->prf = NULL; - this->prf_auth_i = NULL; - this->prf_auth_r = NULL; - this->child_prf = NULL; - this->connection = NULL; - this->policy = NULL; - - /* at creation time, IKE_SA is in a initiator state */ - if (ike_sa_id->is_initiator(ike_sa_id)) - { - this->logger->log(this->logger, CONTROL | LEVEL2, "Create first state_t object of type INITIATOR_INIT"); - this->current_state = (state_t *) initiator_init_create(&(this->protected)); - } - else - { - this->logger->log(this->logger, CONTROL | LEVEL2, "Create first state_t object of type RESPONDER_INIT"); - this->current_state = (state_t *) responder_init_create(&(this->protected)); - } - return &(this->protected.public); -} diff --git a/src/charon/charon/sa/ike_sa.h b/src/charon/charon/sa/ike_sa.h deleted file mode 100644 index c526c6347..000000000 --- a/src/charon/charon/sa/ike_sa.h +++ /dev/null @@ -1,462 +0,0 @@ -/** - * @file ike_sa.h - * - * @brief Interface of ike_sa_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef IKE_SA_H_ -#define IKE_SA_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/** - * Nonce size in bytes for nonces sending to other peer. - * - * @warning Nonce size MUST be between 16 and 256 bytes. - * - * @ingroup sa - */ -#define NONCE_SIZE 16 - - -typedef struct ike_sa_t ike_sa_t; - -/** - * @brief Class ike_sa_t representing an IKE_SA. - * - * An object of this type is managed by an ike_sa_manager_t object - * and represents an IKE_SA. Message processing is split up in different states. - * They will handle all related things for the state they represent. - * - * @b Constructors: - * - ike_sa_create() - * - * @ingroup sa - */ -struct ike_sa_t { - - /** - * @brief Processes a incoming IKEv2-Message of type message_t. - * - * @param this ike_sa_t object object - * @param[in] message message_t object to process - * @return - * - SUCCESS - * - FAILED - * - DELETE_ME if this IKE_SA MUST be deleted - */ - status_t (*process_message) (ike_sa_t *this,message_t *message); - - /** - * @brief Initiate a new connection with given connection_t object. - * - * The connection_t object is owned by the IKE_SA after the call, so - * do not modify or destroy it. - * - * @param this calling object - * @param connection connection to initiate - * @return - * - SUCCESS if initialization started - * - FAILED if in wrong state - * - DELETE_ME if initialization failed and IKE_SA MUST be deleted - */ - status_t (*initiate_connection) (ike_sa_t *this, connection_t *connection); - - /** - * @brief Retransmits a request. - * - * @param this calling object - * @param message_id ID of the request to retransmit - * @return - * - SUCCESS - * - NOT_FOUND if request doesn't have to be retransmited - */ - status_t (*retransmit_request) (ike_sa_t *this, u_int32_t message_id); - - /** - * @brief Sends a request to delete IKE_SA. - * - * Only supported in state IKE_SA_ESTABLISHED - * - * @param this calling object - */ - void (*send_delete_ike_sa_request) (ike_sa_t *this); - - /** - * @brief Get the id of the SA. - * - * Returned ike_sa_id_t object is not getting cloned! - * - * @param this calling object - * @return ike_sa's ike_sa_id_t - */ - ike_sa_id_t* (*get_id) (ike_sa_t *this); - - /** - * @brief Get local peer address of the IKE_SA. - * - * @param this calling object - * @return local host_t - */ - host_t* (*get_my_host) (ike_sa_t *this); - - /** - * @brief Get remote peer address of the IKE_SA. - * - * @param this calling object - * @return remote host_t - */ - host_t* (*get_other_host) (ike_sa_t *this); - - /** - * @brief Get own ID of the IKE_SA. - * - * @param this calling object - * @return local identification_t - */ - identification_t* (*get_my_id) (ike_sa_t *this); - - /** - * @brief Get remote ID the IKE_SA. - * - * @param this calling object - * @return remote identification_t - */ - identification_t* (*get_other_id) (ike_sa_t *this); - - /** - * @brief Get the connection of the IKE_SA. - * - * The internal used connection specification - * can be queried to get some data of an IKE_SA. - * The connection is still owned to the IKE_SA - * and must not be manipulated. - * - * @param this calling object - * @return connection_t - */ - connection_t* (*get_connection) (ike_sa_t *this); - - /** - * @brief Get the state of type of associated state object. - * - * @param this calling object - * @return state of IKE_SA - */ - ike_sa_state_t (*get_state) (ike_sa_t *this); - - /** - * @brief Log the status of a the ike sa to a logger. - * - * The status of the IKE SA and all child SAs is logged. - * Supplying NULL as logger uses the internal child_sa logger - * to do the logging. The log is only done if the supplied - * connection name is NULL or matches the connections name. - * - * @param this calling object - * @param logger logger to use for logging - * @param name name of the connection - */ - void (*log_status) (ike_sa_t *this, logger_t *logger, char *name); - - /** - * @brief Destroys a ike_sa_t object. - * - * @param this calling object - */ - void (*destroy) (ike_sa_t *this); -}; - - -typedef struct protected_ike_sa_t protected_ike_sa_t; - -/** - * @brief Protected functions of an ike_sa_t object. - * - * This members are only accessed out from - * the various state_t implementations. - * - * @ingroup sa - */ -struct protected_ike_sa_t { - - /** - * Public interface of an ike_sa_t object. - */ - ike_sa_t public; - - /** - * @brief Build an empty IKEv2-Message and fills in default informations. - * - * Depending on the type of message (request or response), the message id is - * either message_id_out or message_id_in. - * - * Used in state_t Implementation to build an empty IKEv2-Message. - * - * @param this calling object - * @param type exchange type of new message - * @param request TRUE, if message has to be a request - * @param message new message is stored at this location - */ - void (*build_message) (protected_ike_sa_t *this, exchange_type_t type, bool request, message_t **message); - - /** - * @brief Get the internal stored connection_t object. - * - * @param this calling object - * @return pointer to the internal stored connection_t object - */ - connection_t *(*get_connection) (protected_ike_sa_t *this); - - /** - * @brief Set the internal connection object. - * - * @param this calling object - * @param connection object of type connection_t - */ - void (*set_connection) (protected_ike_sa_t *this, connection_t *connection); - - /** - * @brief Get the internal stored policy object. - * - * @param this calling object - * @return pointer to the internal stored policy_t object - */ - policy_t *(*get_policy) (protected_ike_sa_t *this); - - /** - * @brief Set the internal policy_t object. - * - * @param this calling object - * @param policy object of type policy_t - */ - void (*set_policy) (protected_ike_sa_t *this,policy_t *policy); - - /** - * @brief Derive all keys and create the transforms for IKE communication. - * - * Keys are derived using the diffie hellman secret, nonces and internal - * stored SPIs. - * Allready existing objects get destroyed. - * - * @param this calling object - * @param proposal proposal which contains algorithms to use - * @param dh diffie hellman object with shared secret - * @param nonce_i initiators nonce - * @param nonce_r responders nonce - */ - status_t (*build_transforms) (protected_ike_sa_t *this, proposal_t* proposal, - diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r); - - /** - * @brief Send the next request message. - * - * Also the first retransmit job is created. - * - * Last stored requested message gets destroyed. Object gets not cloned! - * - * @param this calling object - * @param message pointer to the message which should be sent - * @return - * - SUCCESS - * - FAILED if message id is not next expected one - */ - status_t (*send_request) (protected_ike_sa_t *this,message_t * message); - - /** - * @brief Send the next response message. - * - * Last stored responded message gets destroyed. Object gets not cloned! - * - * @param this calling object - * @param message pointer to the message which should be sent - * return - * - SUCCESS - * - FAILED if message id is not next expected one - */ - status_t (*send_response) (protected_ike_sa_t *this,message_t * message); - - /** - * @brief Send a notify reply message. - * - * @param this calling object - * @param exchange_type type of exchange in which the notify should be wrapped - * @param type type of the notify message to send - * @param data notification data - */ - void (*send_notify) (protected_ike_sa_t *this, exchange_type_t exchange_type, notify_message_type_t type, chunk_t data); - - /** - * @brief Get the internal stored randomizer_t object. - * - * @param this calling object - * @return pointer to the internal randomizer_t object - */ - randomizer_t *(*get_randomizer) (protected_ike_sa_t *this); - - /** - * @brief Set the new state_t object of the IKE_SA object. - * - * The old state_t object gets not destroyed. It's the callers duty to - * make sure old state is destroyed (Normally the old state is the caller). - * - * @param this calling object - * @param state pointer to the new state_t object - */ - void (*set_new_state) (protected_ike_sa_t *this,state_t *state); - - /** - * @brief Set the last replied message id. - * - * @param this calling object - * @param message_id message id - */ - void (*set_last_replied_message_id) (protected_ike_sa_t *this,u_int32_t message_id); - - /** - * @brief Get the internal stored initiator crypter_t object. - * - * @param this calling object - * @return pointer to crypter_t object - */ - crypter_t *(*get_crypter_initiator) (protected_ike_sa_t *this); - - /** - * @brief Get the internal stored initiator signer_t object. - * - * @param this calling object - * @return pointer to signer_t object - */ - signer_t *(*get_signer_initiator) (protected_ike_sa_t *this); - - /** - * @brief Get the internal stored responder crypter_t object. - * - * @param this calling object - * @return pointer to crypter_t object - */ - crypter_t *(*get_crypter_responder) (protected_ike_sa_t *this); - - /** - * @brief Get the internal stored responder signer object. - * - * @param this calling object - * @return pointer to signer_t object - */ - signer_t *(*get_signer_responder) (protected_ike_sa_t *this); - - /** - * @brief Get the multi purpose prf. - * - * @param this calling object - * @return pointer to prf_t object - */ - prf_t *(*get_prf) (protected_ike_sa_t *this); - - /** - * @brief Get the prf-object, which is used to derive keys for child SAs. - * - * @param this calling object - * @return pointer to prf_t object - */ - prf_t *(*get_child_prf) (protected_ike_sa_t *this); - - /** - * @brief Get the prf used for authentication of initiator. - * - * @param this calling object - * @return pointer to prf_t object - */ - prf_t *(*get_prf_auth_i) (protected_ike_sa_t *this); - - /** - * @brief Get the prf used for authentication of responder. - * - * @param this calling object - * @return pointer to prf_t object - */ - prf_t *(*get_prf_auth_r) (protected_ike_sa_t *this); - - /** - * @brief Associates a child SA to this IKE SA - * - * @param this calling object - * @param child_sa child_sa to add - */ - void (*add_child_sa) (protected_ike_sa_t *this, child_sa_t *child_sa); - - /** - * @brief Get the last responded message. - * - * @param this calling object - * @return - * - last received as message_t object - * - NULL if no last request available - */ - message_t *(*get_last_responded_message) (protected_ike_sa_t *this); - - /** - * @brief Get the last requested message. - * - * @param this calling object - * @return - * - last sent as message_t object - * - NULL if no last request available - */ - message_t *(*get_last_requested_message) (protected_ike_sa_t *this); - - /** - * @brief Resets message counters and does destroy stored received and sent messages. - * - * @param this calling object - */ - void (*reset_message_buffers) (protected_ike_sa_t *this); -}; - - -/** - * @brief Creates an ike_sa_t object with a specific ID. - * - * @warning the Content of internal ike_sa_id_t object can change over time - * e.g. when a IKE_SA_INIT has been finished. - * - * @param[in] ike_sa_id ike_sa_id_t object to associate with new IKE_SA. - * The object is internal getting cloned - * and so has to be destroyed by the caller. - * @return ike_sa_t object - * - * @ingroup sa - */ -ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id); - -#endif /*IKE_SA_H_*/ diff --git a/src/charon/charon/sa/ike_sa_id.c b/src/charon/charon/sa/ike_sa_id.c deleted file mode 100644 index bf3a05d11..000000000 --- a/src/charon/charon/sa/ike_sa_id.c +++ /dev/null @@ -1,185 +0,0 @@ -/** - * @file ike_sa_id.c - * - * @brief Implementation of ike_sa_id_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 "ike_sa_id.h" - - - -typedef struct private_ike_sa_id_t private_ike_sa_id_t; - -/** - * Private data of an ike_sa_id_t object. - */ -struct private_ike_sa_id_t { - /** - * Public interface of ike_sa_id_t. - */ - ike_sa_id_t public; - - /** - * SPI of Initiator. - */ - u_int64_t initiator_spi; - - /** - * SPI of Responder. - */ - u_int64_t responder_spi; - - /** - * Role for specific IKE_SA. - */ - bool is_initiator_flag; -}; - -/** - * Implementation of ike_sa_id_t.set_responder_spi. - */ -static void set_responder_spi (private_ike_sa_id_t *this, u_int64_t responder_spi) -{ - this->responder_spi = responder_spi; -} - -/** - * Implementation of ike_sa_id_t.set_initiator_spi. - */ -static void set_initiator_spi(private_ike_sa_id_t *this, u_int64_t initiator_spi) -{ - this->initiator_spi = initiator_spi; -} - -/** - * Implementation of ike_sa_id_t.get_initiator_spi. - */ -static u_int64_t get_initiator_spi (private_ike_sa_id_t *this) -{ - return this->initiator_spi; -} - -/** - * Implementation of ike_sa_id_t.get_responder_spi. - */ -static u_int64_t get_responder_spi (private_ike_sa_id_t *this) -{ - return this->responder_spi; -} - -/** - * Implementation of ike_sa_id_t.equals. - */ -static bool equals (private_ike_sa_id_t *this, private_ike_sa_id_t *other) -{ - if (other == NULL) - { - return FALSE; - } - if ((this->is_initiator_flag == other->is_initiator_flag) && - (this->initiator_spi == other->initiator_spi) && - (this->responder_spi == other->responder_spi)) - { - /* private_ike_sa_id's are equal */ - return TRUE; - } - else - { - /* private_ike_sa_id's are not equal */ - return FALSE; - } -} - -/** - * Implementation of ike_sa_id_t.replace_values. - */ -static void replace_values(private_ike_sa_id_t *this, private_ike_sa_id_t *other) -{ - this->initiator_spi = other->initiator_spi; - this->responder_spi = other->responder_spi; - this->is_initiator_flag = other->is_initiator_flag; -} - -/** - * Implementation of ike_sa_id_t.is_initiator. - */ -static bool is_initiator(private_ike_sa_id_t *this) -{ - return this->is_initiator_flag; -} - -/** - * Implementation of ike_sa_id_t.switch_initiator. - */ -static bool switch_initiator(private_ike_sa_id_t *this) -{ - if (this->is_initiator_flag) - { - this->is_initiator_flag = FALSE; - } - else - { - this->is_initiator_flag = TRUE; - } - return this->is_initiator_flag; -} - -/** - * Implementation of ike_sa_id_t.clone. - */ -static ike_sa_id_t* clone(private_ike_sa_id_t *this) -{ - return ike_sa_id_create(this->initiator_spi, this->responder_spi, this->is_initiator_flag); -} - -/** - * Implementation of ike_sa_id_t.destroy. - */ -static void destroy(private_ike_sa_id_t *this) -{ - free(this); -} - -/* - * Described in header. - */ -ike_sa_id_t * ike_sa_id_create(u_int64_t initiator_spi, u_int64_t responder_spi, bool is_initiator_flag) -{ - private_ike_sa_id_t *this = malloc_thing(private_ike_sa_id_t); - - /* public functions */ - this->public.set_responder_spi = (void(*)(ike_sa_id_t*,u_int64_t)) set_responder_spi; - this->public.set_initiator_spi = (void(*)(ike_sa_id_t*,u_int64_t)) set_initiator_spi; - this->public.get_responder_spi = (u_int64_t(*)(ike_sa_id_t*)) get_responder_spi; - this->public.get_initiator_spi = (u_int64_t(*)(ike_sa_id_t*)) get_initiator_spi; - this->public.equals = (bool(*)(ike_sa_id_t*,ike_sa_id_t*)) equals; - this->public.replace_values = (void(*)(ike_sa_id_t*,ike_sa_id_t*)) replace_values; - this->public.is_initiator = (bool(*)(ike_sa_id_t*)) is_initiator; - this->public.switch_initiator = (bool(*)(ike_sa_id_t*)) switch_initiator; - this->public.clone = (ike_sa_id_t*(*)(ike_sa_id_t*)) clone; - this->public.destroy = (void(*)(ike_sa_id_t*))destroy; - - /* private data */ - this->initiator_spi = initiator_spi; - this->responder_spi = responder_spi; - this->is_initiator_flag = is_initiator_flag; - - return (&this->public); -} diff --git a/src/charon/charon/sa/ike_sa_id.h b/src/charon/charon/sa/ike_sa_id.h deleted file mode 100644 index 0f16f7637..000000000 --- a/src/charon/charon/sa/ike_sa_id.h +++ /dev/null @@ -1,146 +0,0 @@ -/** - * @file ike_sa_id.h - * - * @brief Interface of ike_sa_id_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - - -#ifndef IKE_SA_ID_H_ -#define IKE_SA_ID_H_ - -#include - - -typedef struct ike_sa_id_t ike_sa_id_t; - -/** - * @brief An object of type ike_sa_id_t is used to identify an IKE_SA. - * - * An IKE_SA is identified by its initiator and responder spi's. - * Additionaly it contains the role of the actual running IKEv2-Daemon - * for the specific IKE_SA (original initiator or responder). - * - * @b Constructors: - * - ike_sa_id_create() - * - * @ingroup sa - */ -struct ike_sa_id_t { - - /** - * @brief Set the SPI of the responder. - * - * This function is called when a request or reply of a IKE_SA_INIT is received. - * - * @param this calling object - * @param responder_spi SPI of responder to set - */ - void (*set_responder_spi) (ike_sa_id_t *this, u_int64_t responder_spi); - - /** - * @brief Set the SPI of the initiator. - * - * @param this calling object - * @param initiator_spi SPI to set - */ - void (*set_initiator_spi) (ike_sa_id_t *this, u_int64_t initiator_spi); - - /** - * @brief Get the initiator SPI. - * - * @param this calling object - * @return SPI of the initiator - */ - u_int64_t (*get_initiator_spi) (ike_sa_id_t *this); - - /** - * @brief Get the responder SPI. - * - * @param this calling object - * @return SPI of the responder - */ - u_int64_t (*get_responder_spi) (ike_sa_id_t *this); - - /** - * @brief Check if two ike_sa_id_t objects are equal. - * - * Two ike_sa_id_t objects are equal if both SPI values and the role matches. - * - * @param this calling object - * @param other ike_sa_id_t object to check if equal - * @return TRUE if given ike_sa_id_t are equal, FALSE otherwise - */ - bool (*equals) (ike_sa_id_t *this, ike_sa_id_t *other); - - /** - * @brief Replace all values of a given ike_sa_id_t object with values. - * from another ike_sa_id_t object. - * - * After calling this function, both objects are equal. - * - * @param this calling object - * @param other ike_sa_id_t object from which values will be taken - */ - void (*replace_values) (ike_sa_id_t *this, ike_sa_id_t *other); - - /** - * @brief Get the initiator flag. - * - * @param this calling object - * @return TRUE if we are the original initator - */ - bool (*is_initiator) (ike_sa_id_t *this); - - /** - * @brief Switche the original initiator flag. - * - * @param this calling object - * @return TRUE if we are the original initator after switch, FALSE otherwise - */ - bool (*switch_initiator) (ike_sa_id_t *this); - - /** - * @brief Clones a given ike_sa_id_t object. - * - * @param this calling object - * @return cloned ike_sa_id_t object - */ - ike_sa_id_t *(*clone) (ike_sa_id_t *this); - - /** - * @brief Destroys an ike_sa_id_t object. - * - * @param this calling object - */ - void (*destroy) (ike_sa_id_t *this); -}; - -/** - * @brief Creates an ike_sa_id_t object with specific SPI's and defined role. - * - * @param initiator_spi initiators SPI - * @param responder_spi responders SPI - * @param is_initiaor TRUE if we are the original initiator - * @return ike_sa_id_t object - * - * @ingroup sa - */ -ike_sa_id_t * ike_sa_id_create(u_int64_t initiator_spi, u_int64_t responder_spi, bool is_initiaor); - -#endif /*IKE_SA_ID_H_*/ diff --git a/src/charon/charon/sa/ike_sa_manager.c b/src/charon/charon/sa/ike_sa_manager.c deleted file mode 100644 index a65f41042..000000000 --- a/src/charon/charon/sa/ike_sa_manager.c +++ /dev/null @@ -1,843 +0,0 @@ -/** - * @file ike_sa_manager.c - * - * @brief Implementation of ike_sa_mananger_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 -#include - -#include "ike_sa_manager.h" - -#include -#include -#include -#include -#include - -typedef struct ike_sa_entry_t ike_sa_entry_t; - -/** - * An entry in the linked list, contains IKE_SA, locking and lookup data. - */ -struct ike_sa_entry_t { - /** - * Destructor, also destroys associated ike_sa_t object. - */ - status_t (*destroy) (ike_sa_entry_t *this); - - /** - * Number of threads waiting for this ike_sa_t object. - */ - int waiting_threads; - - /** - * Condvar where threads can wait until ike_sa_t object is free for use again. - */ - pthread_cond_t condvar; - - /** - * Is this ike_sa currently checked out? - */ - bool checked_out; - - /** - * Does this SA drives out new threads? - */ - bool driveout_new_threads; - - /** - * Does this SA drives out waiting threads? - */ - bool driveout_waiting_threads; - - /** - * Identifiaction of an IKE_SA (SPIs). - */ - ike_sa_id_t *ike_sa_id; - - /** - * The contained ike_sa_t object. - */ - ike_sa_t *ike_sa; -}; - -/** - * Implementation of ike_sa_entry_t.destroy. - */ -static status_t ike_sa_entry_destroy(ike_sa_entry_t *this) -{ - /* also destroy IKE SA */ - this->ike_sa->destroy(this->ike_sa); - this->ike_sa_id->destroy(this->ike_sa_id); - free(this); - return SUCCESS; -} - -/** - * @brief Creates a new entry for the ike_sa_t list. - * - * This constructor additionaly creates a new and empty SA. - * - * @param ike_sa_id The associated ike_sa_id_t, will be cloned - * @return ike_sa_entry_t object - */ -static ike_sa_entry_t *ike_sa_entry_create(ike_sa_id_t *ike_sa_id) -{ - ike_sa_entry_t *this = malloc_thing(ike_sa_entry_t); - - /* destroy function */ - this->destroy = ike_sa_entry_destroy; - - this->waiting_threads = 0; - pthread_cond_init(&(this->condvar), NULL); - - /* we set checkout flag when we really give it out */ - this->checked_out = FALSE; - this->driveout_new_threads = FALSE; - this->driveout_waiting_threads = FALSE; - - /* ike_sa_id is always cloned */ - this->ike_sa_id = ike_sa_id->clone(ike_sa_id); - - /* create new ike_sa */ - this->ike_sa = ike_sa_create(ike_sa_id); - - return this; -} - - -typedef struct private_ike_sa_manager_t private_ike_sa_manager_t; - -/** - * Additional private members of ike_sa_manager_t. - */ -struct private_ike_sa_manager_t { - /** - * Public interface of ike_sa_manager_t. - */ - ike_sa_manager_t public; - - /** - * @brief Get next spi. - * - * We give out SPIs incremental starting at 1. - * - * @param this the ike_sa_manager - * @return the next spi - */ - u_int64_t (*get_next_spi) (private_ike_sa_manager_t *this); - - /** - * @brief Find the ike_sa_entry_t object in the list by SPIs. - * - * This function simply iterates over the linked list. A hash-table - * would be more efficient when storing a lot of IKE_SAs... - * - * @param this calling object - * @param ike_sa_id id of the ike_sa, containing SPIs - * @param[out] entry pointer to set to the found entry - * @return - * - SUCCESS when found, - * - NOT_FOUND when no such ike_sa_id in list - */ - status_t (*get_entry_by_id) (private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id, ike_sa_entry_t **entry); - - /** - * @brief Find the ike_sa_entry_t in the list by pointer to SA. - * - * This function simply iterates over the linked list. A hash-table - * would be more efficient when storing a lot of IKE_SAs... - * - * @param this calling object - * @param ike_sa pointer to the ike_sa - * @param[out] entry pointer to set to the found entry - * @return - * - SUCCESS when found, - * - NOT_FOUND when no such ike_sa_id in list - */ - status_t (*get_entry_by_sa) (private_ike_sa_manager_t *this, ike_sa_t *ike_sa, ike_sa_entry_t **entry); - - /** - * @brief Felete an entry from the linked list. - * - * @param this calling object - * @param entry entry to delete - * @return - * - SUCCESS when found, - * - NOT_FOUND when no such ike_sa_id in list - */ - status_t (*delete_entry) (private_ike_sa_manager_t *this, ike_sa_entry_t *entry); - - /** - * Lock for exclusivly accessing the manager. - */ - pthread_mutex_t mutex; - - /** - * Logger used for this IKE SA Manager. - */ - logger_t *logger; - - /** - * Linked list with entries for the ike_sa_t objects. - */ - linked_list_t *ike_sa_list; - - /** - * A randomizer, to get random SPIs for our side - */ - randomizer_t *randomizer; -}; - -/** - * Implementation of private_ike_sa_manager_t.get_entry_by_id. - */ -static status_t get_entry_by_id(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id, ike_sa_entry_t **entry) -{ - linked_list_t *list = this->ike_sa_list; - iterator_t *iterator; - status_t status; - - /* create iterator over list of ike_sa's */ - iterator = list->create_iterator(list, TRUE); - - /* default status */ - status = NOT_FOUND; - - while (iterator->has_next(iterator)) - { - ike_sa_entry_t *current; - - iterator->current(iterator, (void**)¤t); - if (current->ike_sa_id->get_responder_spi(current->ike_sa_id) == 0) - { - /* seems to be a half ready ike_sa */ - if ((current->ike_sa_id->get_initiator_spi(current->ike_sa_id) == ike_sa_id->get_initiator_spi(ike_sa_id)) - && (ike_sa_id->is_initiator(ike_sa_id) == current->ike_sa_id->is_initiator(current->ike_sa_id))) - { - this->logger->log(this->logger,CONTROL | LEVEL2,"Found entry by initiator spi %d",ike_sa_id->get_initiator_spi(ike_sa_id)); - *entry = current; - status = SUCCESS; - break; - } - } - else if (ike_sa_id->get_responder_spi(ike_sa_id) == 0) - { - if ((current->ike_sa_id->get_initiator_spi(current->ike_sa_id) == ike_sa_id->get_initiator_spi(ike_sa_id)) - && (ike_sa_id->is_initiator(ike_sa_id) == current->ike_sa_id->is_initiator(current->ike_sa_id))) - { - this->logger->log(this->logger,CONTROL | LEVEL2,"Found entry by initiator spi %d",ike_sa_id->get_initiator_spi(ike_sa_id)); - *entry = current; - status = SUCCESS; - break; - } - } - if (current->ike_sa_id->equals(current->ike_sa_id, ike_sa_id)) - { - this->logger->log(this->logger,CONTROL | LEVEL2,"Found entry by full ID"); - *entry = current; - status = SUCCESS; - break; - } - } - - iterator->destroy(iterator); - return status; -} - -/** - * Implementation of private_ike_sa_manager_t.get_entry_by_sa. - */ -static status_t get_entry_by_sa(private_ike_sa_manager_t *this, ike_sa_t *ike_sa, ike_sa_entry_t **entry) -{ - linked_list_t *list = this->ike_sa_list; - iterator_t *iterator; - status_t status; - - iterator = list->create_iterator(list, TRUE); - - /* default status */ - status = NOT_FOUND; - - while (iterator->has_next(iterator)) - { - ike_sa_entry_t *current; - iterator->current(iterator, (void**)¤t); - /* only pointers are compared */ - if (current->ike_sa == ike_sa) - { - this->logger->log(this->logger,CONTROL | LEVEL2,"Found entry by pointer"); - *entry = current; - status = SUCCESS; - break; - } - } - iterator->destroy(iterator); - - return status; -} - -/** - * Implementation of private_ike_sa_manager_s.delete_entry. - */ -static status_t delete_entry(private_ike_sa_manager_t *this, ike_sa_entry_t *entry) -{ - linked_list_t *list = this->ike_sa_list; - iterator_t *iterator; - status_t status; - - iterator = list->create_iterator(list, TRUE); - - status = NOT_FOUND; - - while (iterator->has_next(iterator)) - { - ike_sa_entry_t *current; - iterator->current(iterator, (void**)¤t); - if (current == entry) - { - this->logger->log(this->logger,CONTROL | LEVEL2,"Found entry by pointer. Going to delete it."); - iterator->remove(iterator); - entry->destroy(entry); - status = SUCCESS; - break; - } - } - iterator->destroy(iterator); - return status; -} - - -/** - * Implementation of private_ike_sa_manager_t.get_next_spi. - */ -static u_int64_t get_next_spi(private_ike_sa_manager_t *this) -{ - u_int64_t spi; - - this->randomizer->get_pseudo_random_bytes(this->randomizer, 8, (u_int8_t*)&spi); - - return spi; -} - -/** - * Implementation of of ike_sa_manager.create_and_checkout. - */ -static void create_and_checkout(private_ike_sa_manager_t *this,ike_sa_t **ike_sa) -{ - u_int64_t initiator_spi; - ike_sa_entry_t *new_ike_sa_entry; - ike_sa_id_t *new_ike_sa_id; - - initiator_spi = this->get_next_spi(this); - new_ike_sa_id = ike_sa_id_create(0, 0, TRUE); - new_ike_sa_id->set_initiator_spi(new_ike_sa_id, initiator_spi); - - /* create entry */ - new_ike_sa_entry = ike_sa_entry_create(new_ike_sa_id); - new_ike_sa_id->destroy(new_ike_sa_id); - - /* each access is locked */ - pthread_mutex_lock(&(this->mutex)); - - this->ike_sa_list->insert_last(this->ike_sa_list, new_ike_sa_entry); - - /* check ike_sa out */ - this->logger->log(this->logger,CONTROL | LEVEL1 ,"New IKE_SA created and added to list of known IKE_SA's"); - new_ike_sa_entry->checked_out = TRUE; - *ike_sa = new_ike_sa_entry->ike_sa; - - pthread_mutex_unlock(&(this->mutex)); -} - -/** - * Implementation of of ike_sa_manager.checkout. - */ -static status_t checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id, ike_sa_t **ike_sa) -{ - bool responder_spi_set; - bool initiator_spi_set; - bool original_initiator; - status_t retval; - - /* each access is locked */ - pthread_mutex_lock(&(this->mutex)); - - responder_spi_set = (FALSE != ike_sa_id->get_responder_spi(ike_sa_id)); - initiator_spi_set = (FALSE != ike_sa_id->get_initiator_spi(ike_sa_id)); - original_initiator = ike_sa_id->is_initiator(ike_sa_id); - - if ((initiator_spi_set && responder_spi_set) || - ((initiator_spi_set && !responder_spi_set) && (original_initiator))) - { - /* we SHOULD have an IKE_SA for these SPIs in the list, - * if not, we can't handle the request... - */ - ike_sa_entry_t *entry; - /* look for the entry */ - if (this->get_entry_by_id(this, ike_sa_id, &entry) == SUCCESS) - { - /* can we give this ike_sa out to new requesters?*/ - if (entry->driveout_new_threads) - { - this->logger->log(this->logger,CONTROL|LEVEL1,"Drive out new thread for existing IKE_SA"); - /* no we can't */ - retval = NOT_FOUND; - } - else - { - /* is this IKE_SA already checked out ?? - * are we welcome to get this SA ? */ - while (entry->checked_out && !entry->driveout_waiting_threads) - { - /* so wait until we can get it for us. - * we register us as waiting. - */ - entry->waiting_threads++; - pthread_cond_wait(&(entry->condvar), &(this->mutex)); - entry->waiting_threads--; - } - - /* hm, a deletion request forbids us to get this SA, go home */ - if (entry->driveout_waiting_threads) - { - /* we must signal here, others are interested that we leave */ - pthread_cond_signal(&(entry->condvar)); - this->logger->log(this->logger,CONTROL|LEVEL1,"Drive out waiting thread for existing IKE_SA"); - retval = NOT_FOUND; - } - else - { - this->logger->log(this->logger,CONTROL|LEVEL2,"IKE SA successfully checked out"); - /* ok, this IKE_SA is finally ours */ - entry->checked_out = TRUE; - *ike_sa = entry->ike_sa; - /* DON'T use return, we must unlock the mutex! */ - retval = SUCCESS; - } - } - } - else - { - this->logger->log(this->logger,ERROR | LEVEL1,"IKE SA not stored in known IKE_SA list"); - /* looks like there is no such IKE_SA, better luck next time... */ - /* DON'T use return, we must unlock the mutex! */ - retval = NOT_FOUND; - } - } - else if ((initiator_spi_set && !responder_spi_set) && (!original_initiator)) - { - /* an IKE_SA_INIT from an another endpoint, - * he is the initiator. - * For simplicity, we do NOT check for retransmitted - * IKE_SA_INIT-Requests here, so EVERY single IKE_SA_INIT- - * Request (even a retransmitted one) will result in a - * IKE_SA. This could be improved... - */ - u_int64_t responder_spi; - ike_sa_entry_t *new_ike_sa_entry; - - - /* set SPIs, we are the responder */ - responder_spi = this->get_next_spi(this); - - /* we also set arguments spi, so its still valid */ - ike_sa_id->set_responder_spi(ike_sa_id, responder_spi); - - /* create entry */ - new_ike_sa_entry = ike_sa_entry_create(ike_sa_id); - - this->ike_sa_list->insert_last(this->ike_sa_list, new_ike_sa_entry); - - /* check ike_sa out */ - this->logger->log(this->logger,CONTROL | LEVEL1 ,"IKE_SA added to list of known IKE_SA's"); - new_ike_sa_entry->checked_out = TRUE; - *ike_sa = new_ike_sa_entry->ike_sa; - - retval = CREATED; - } - else - { - /* responder set, initiator not: here is something seriously wrong! */ - this->logger->log(this->logger,ERROR | LEVEL1, "Invalid IKE_SA SPI's"); - /* DON'T use return, we must unlock the mutex! */ - retval = INVALID_ARG; - } - - pthread_mutex_unlock(&(this->mutex)); - /* OK, unlocked... */ - return retval; -} - -/** - * Implementation of of ike_sa_manager.checkout_by_hosts. - */ -static status_t checkout_by_hosts(private_ike_sa_manager_t *this, host_t *me, host_t *other, ike_sa_t **ike_sa) -{ - iterator_t *iterator; - ike_sa_id_t *ike_sa_id = NULL; - - pthread_mutex_lock(&(this->mutex)); - - iterator = this->ike_sa_list->create_iterator(this->ike_sa_list, TRUE); - while (iterator->has_next(iterator)) - { - ike_sa_entry_t *current; - host_t *sa_me, *sa_other; - - iterator->current(iterator, (void**)¤t); - sa_me = current->ike_sa->get_my_host(current->ike_sa); - sa_other = current->ike_sa->get_other_host(current->ike_sa); - - /* one end may be default/any, but not both */ - if (me->is_default_route(me)) - { - if (other->is_default_route(other)) - { - break; - } - if (other->equals(other, sa_other)) - { - /* other matches */ - ike_sa_id = current->ike_sa_id; - } - } - else if (other->is_default_route(other)) - { - if (me->equals(me, sa_me)) - { - /* ME matches */ - ike_sa_id = current->ike_sa_id; - } - } - else - { - if (me->equals(me, sa_me) && other->equals(other, sa_other)) - { - /* both matches */ - ike_sa_id = current->ike_sa_id; - } - } - } - iterator->destroy(iterator); - pthread_mutex_unlock(&(this->mutex)); - - if (ike_sa_id) - { - /* checkout is done in the checkout function, since its rather complex */ - return checkout(this, ike_sa_id, ike_sa); - } - return NOT_FOUND; -} - -/** - * Implementation of ike_sa_manager_t.get_ike_sa_list. - */ -linked_list_t *get_ike_sa_list(private_ike_sa_manager_t* this) -{ - linked_list_t *list; - iterator_t *iterator; - - pthread_mutex_lock(&(this->mutex)); - - list = linked_list_create(); - iterator = this->ike_sa_list->create_iterator(this->ike_sa_list, TRUE); - while (iterator->has_next(iterator)) - { - ike_sa_entry_t *entry; - iterator->current(iterator, (void**)&entry); - list->insert_last(list, (void*)entry->ike_sa_id->clone(entry->ike_sa_id)); - } - iterator->destroy(iterator); - - pthread_mutex_unlock(&(this->mutex)); - return list; -} - -/** - * Implementation of ike_sa_manager_t.get_ike_sa_list_by_name. - */ -linked_list_t *get_ike_sa_list_by_name(private_ike_sa_manager_t* this, const char *name) -{ - linked_list_t *list; - iterator_t *iterator; - - pthread_mutex_lock(&(this->mutex)); - - list = linked_list_create(); - iterator = this->ike_sa_list->create_iterator(this->ike_sa_list, TRUE); - while (iterator->has_next(iterator)) - { - ike_sa_entry_t *entry; - connection_t *connection; - - iterator->current(iterator, (void**)&entry); - connection = entry->ike_sa->get_connection(entry->ike_sa); - if (strcmp(name, connection->get_name(connection)) == 0) - { - list->insert_last(list, (void*)entry->ike_sa_id->clone(entry->ike_sa_id)); - } - } - iterator->destroy(iterator); - - pthread_mutex_unlock(&(this->mutex)); - return list; -} - -/** - * Implementation of ike_sa_manager_t.log_status. - */ -static void log_status(private_ike_sa_manager_t* this, logger_t* logger, char* name) -{ - iterator_t *iterator; - - pthread_mutex_lock(&(this->mutex)); - - iterator = this->ike_sa_list->create_iterator(this->ike_sa_list, TRUE); - while (iterator->has_next(iterator)) - { - ike_sa_entry_t *entry; - iterator->current(iterator, (void**)&entry); - entry->ike_sa->log_status(entry->ike_sa, logger, name); - } - iterator->destroy(iterator); - - pthread_mutex_unlock(&(this->mutex)); -} - -/** - * Implementation of ike_sa_manager_t.checkin. - */ -static status_t checkin(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. - * We can't search by SPI's since the MAY have changed (e.g. on reception - * of a IKE_SA_INIT response). Updating of the SPI MAY be necessary... - */ - status_t retval; - ike_sa_entry_t *entry; - - pthread_mutex_lock(&(this->mutex)); - - /* look for the entry */ - if (this->get_entry_by_sa(this, ike_sa, &entry) == SUCCESS) - { - /* ike_sa_id must be updated */ - entry->ike_sa_id->replace_values(entry->ike_sa_id, ike_sa->get_id(ike_sa)); - /* signal waiting threads */ - entry->checked_out = FALSE; - this->logger->log(this->logger,CONTROL | LEVEL1,"Checkin of IKE_SA successful."); - pthread_cond_signal(&(entry->condvar)); - retval = SUCCESS; - } - else - { - this->logger->log(this->logger,ERROR,"Fatal Error: Tried to checkin nonexisting IKE_SA"); - /* this SA is no more, this REALLY should not happen */ - retval = NOT_FOUND; - } - pthread_mutex_unlock(&(this->mutex)); - return retval; -} - - -/** - * Implementation of ike_sa_manager_t.checkin_and_delete. - */ -static status_t checkin_and_delete(private_ike_sa_manager_t *this, ike_sa_t *ike_sa) -{ - /* deletion is a bit complex, we must garant that no thread is waiting for - * this SA. - * We take this SA from the list, and start signaling while threads - * are in the condvar. - */ - ike_sa_entry_t *entry; - status_t retval; - - pthread_mutex_lock(&(this->mutex)); - - if (this->get_entry_by_sa(this, ike_sa, &entry) == SUCCESS) - { - /* mark it, so now new threads can acquire this SA */ - entry->driveout_new_threads = TRUE; - /* additionaly, drive out waiting threads */ - entry->driveout_waiting_threads = TRUE; - - /* wait until all workers have done their work */ - while (entry->waiting_threads > 0) - { - /* let the other threads do some work*/ - pthread_cond_signal(&(entry->condvar)); - /* and the nice thing, they will wake us again when their work is done */ - pthread_cond_wait(&(entry->condvar), &(this->mutex)); - } - /* ok, we are alone now, no threads waiting in the entry's condvar */ - this->delete_entry(this, entry); - this->logger->log(this->logger,CONTROL | LEVEL1,"Checkin and delete of IKE_SA successful"); - retval = SUCCESS; - } - else - { - this->logger->log(this->logger,ERROR,"Fatal Error: Tried to checkin and delete nonexisting IKE_SA"); - retval = NOT_FOUND; - } - - pthread_mutex_unlock(&(this->mutex)); - return retval; -} - -/** - * Implementation of ike_sa_manager_t.delete. - */ -static status_t delete(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id) -{ - /* deletion is a bit complex, we must garant that no thread is waiting for - * this SA. - * We take this SA from the list, and start signaling while threads - * are in the condvar. - */ - ike_sa_entry_t *entry; - status_t retval; - - pthread_mutex_lock(&(this->mutex)); - - if (this->get_entry_by_id(this, ike_sa_id, &entry) == SUCCESS) - { - /* mark it, so now new threads can acquire this SA */ - entry->driveout_new_threads = TRUE; - - /* wait until all workers have done their work */ - while (entry->waiting_threads) - { - /* wake up all */ - pthread_cond_signal(&(entry->condvar)); - /* and the nice thing, they will wake us again when their work is done */ - pthread_cond_wait(&(entry->condvar), &(this->mutex)); - } - /* ok, we are alone now, no threads waiting in the entry's condvar */ - this->delete_entry(this, entry); - this->logger->log(this->logger,CONTROL | LEVEL1,"Delete of IKE_SA successful"); - retval = SUCCESS; - } - else - { - this->logger->log(this->logger,ERROR,"Fatal Error: Tried to delete nonexisting IKE_SA"); - retval = NOT_FOUND; - } - - pthread_mutex_unlock(&(this->mutex)); - return retval; -} - -/** - * Implementation of ike_sa_manager_t.destroy. - */ -static void destroy(private_ike_sa_manager_t *this) -{ - /* destroy all list entries */ - linked_list_t *list = this->ike_sa_list; - iterator_t *iterator; - ike_sa_entry_t *entry; - - pthread_mutex_lock(&(this->mutex)); - - this->logger->log(this->logger,CONTROL | LEVEL1,"Going to destroy IKE_SA manager and all managed IKE_SA's"); - - /* Step 1: drive out all waiting threads */ - iterator = list->create_iterator(list, TRUE); - - this->logger->log(this->logger,CONTROL | LEVEL2,"Set driveout flags for all stored IKE_SA's"); - while (iterator->has_next(iterator)) - { - iterator->current(iterator, (void**)&entry); - /* do not accept new threads, drive out waiting threads */ - entry->driveout_new_threads = TRUE; - entry->driveout_waiting_threads = TRUE; - } - - this->logger->log(this->logger,CONTROL | LEVEL2,"Wait for all threads to leave IKE_SA's"); - /* Step 2: wait until all are gone */ - iterator->reset(iterator); - while (iterator->has_next(iterator)) - { - iterator->current(iterator, (void**)&entry); - while (entry->waiting_threads) - { - /* wake up all */ - pthread_cond_signal(&(entry->condvar)); - /* go sleeping until they are gone */ - pthread_cond_wait(&(entry->condvar), &(this->mutex)); - } - } - this->logger->log(this->logger,CONTROL | LEVEL2,"Delete all IKE_SA's"); - /* Step 3: delete all entries */ - iterator->destroy(iterator); - - while (list->get_count(list) > 0) - { - list->get_first(list, (void**)&entry); - this->delete_entry(this, entry); - } - list->destroy(list); - this->logger->log(this->logger,CONTROL | LEVEL2,"IKE_SA's deleted"); - pthread_mutex_unlock(&(this->mutex)); - - this->randomizer->destroy(this->randomizer); - - free(this); -} - -/* - * Described in header. - */ -ike_sa_manager_t *ike_sa_manager_create() -{ - private_ike_sa_manager_t *this = malloc_thing(private_ike_sa_manager_t); - - /* assign public functions */ - this->public.destroy = (void(*)(ike_sa_manager_t*))destroy; - this->public.create_and_checkout = (void(*)(ike_sa_manager_t*,ike_sa_t**))create_and_checkout; - this->public.checkout = (status_t(*)(ike_sa_manager_t*, ike_sa_id_t*,ike_sa_t**))checkout; - this->public.checkout_by_hosts = (status_t(*)(ike_sa_manager_t*,host_t*,host_t*,ike_sa_t**))checkout_by_hosts; - this->public.get_ike_sa_list = (linked_list_t*(*)(ike_sa_manager_t*))get_ike_sa_list; - this->public.get_ike_sa_list_by_name = (linked_list_t*(*)(ike_sa_manager_t*,const char*))get_ike_sa_list_by_name; - this->public.log_status = (void(*)(ike_sa_manager_t*,logger_t*,char*))log_status; - this->public.checkin = (status_t(*)(ike_sa_manager_t*,ike_sa_t*))checkin; - this->public.delete = (status_t(*)(ike_sa_manager_t*,ike_sa_id_t*))delete; - this->public.checkin_and_delete = (status_t(*)(ike_sa_manager_t*,ike_sa_t*))checkin_and_delete; - - /* initialize private functions */ - this->get_next_spi = get_next_spi; - this->get_entry_by_sa = get_entry_by_sa; - this->get_entry_by_id = get_entry_by_id; - this->delete_entry = delete_entry; - - /* initialize private variables */ - this->logger = logger_manager->get_logger(logger_manager, IKE_SA_MANAGER); - - this->ike_sa_list = linked_list_create(); - - pthread_mutex_init(&(this->mutex), NULL); - - this->randomizer = randomizer_create(); - - return (ike_sa_manager_t*)this; -} diff --git a/src/charon/charon/sa/ike_sa_manager.h b/src/charon/charon/sa/ike_sa_manager.h deleted file mode 100644 index d4cd749dc..000000000 --- a/src/charon/charon/sa/ike_sa_manager.h +++ /dev/null @@ -1,194 +0,0 @@ -/** - * @file ike_sa_manager.h - * - * @brief Interface of ike_sa_manager_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef IKE_SA_MANAGER_H_ -#define IKE_SA_MANAGER_H_ - -#include -#include -#include - - -typedef struct ike_sa_manager_t ike_sa_manager_t; - -/** - * @brief The IKE_SA-Manager is responsible for managing all initiated and responded IKE_SA's. - * - * To avoid access from multiple threads, IKE_SAs must be checked out from - * the manager, and checked in after usage. - * The manager also handles deletion of SAs. - * - * @todo checking of double-checkouts from the same threads would be nice. - * This could be done by comparing thread-ids via pthread_self()... - * - * @todo Managing of ike_sa_t objects in a hash table instead of linked list. - * - * @b Constructors: - * - ike_sa_manager_create() - * - * @ingroup sa - */ -struct ike_sa_manager_t { - /** - * @brief Checkout an IKE_SA, create it when necesarry. - * - * Checks out a SA by its ID. An SA will be created, when: - * - Responder SPI is not set (when received an IKE_SA_INIT from initiator) - * Management of SPIs is the managers job, he will set it. - * This function blocks until SA is available for checkout. - * - * @warning checking out two times without checking in will - * result in a deadlock! - * - * @param this the manager object - * @param ike_sa_id[in/out] the SA identifier, will be updated - * @param ike_sa[out] checked out SA - * @returns - * - SUCCESS if checkout successful - * - NOT_FOUND when no such SA is available - * - CREATED if a new IKE_SA got created - */ - status_t (*checkout) (ike_sa_manager_t* this, ike_sa_id_t *sa_id, ike_sa_t **ike_sa); - - /** - * @brief Create and checkout an IKE_SA as original initator. - * - * Creates and checks out a SA as initiator. - * Management of SPIs is the managers job, he will set it. - * - * @param this the manager object - * @param ike_sa[out] checked out SA - */ - void (*create_and_checkout) (ike_sa_manager_t* this,ike_sa_t **ike_sa); - - /** - * @brief Check out an IKE_SA, defined be the two peers. - * - * Checking out an IKE_SA by their peer addresses may be necessary - * for kernel traps, status querying and so on... one of the hosts - * may be 0.0.0.0 (defaultroute/any), but not both. - * - * @param this the manager object - * @param me host on local side - * @param other host on remote side - * @param ike_sa[out] checked out SA - * @return - * - NOT_FOUND, if no such SA found - * - SUCCESS, if SA found and ike_sa set appropriatly - */ - status_t (*checkout_by_hosts) (ike_sa_manager_t* this, host_t *me, host_t *other, ike_sa_t **ike_sa); - - /** - * @brief Get a list of all IKE_SA SAs currently set up. - * - * The resulting list with all IDs must be destroyd by - * the caller. There is no guarantee an ike_sa with the - * corrensponding ID really exists, since it may be deleted - * in the meantime by another thread. - * - * @param this the manager object - * @return a list with ike_sa_id_t s - */ - linked_list_t *(*get_ike_sa_list) (ike_sa_manager_t* this); - - /** - * @brief Get a list of all IKE_SA SAs currently set up specified - * by the connections name. - * - * @param this the manager object - * @return a list with ike_sa_id_t s - */ - linked_list_t *(*get_ike_sa_list_by_name) (ike_sa_manager_t* this, const char *name); - - /** - * @brief Log the status of the IKE_SA's in the manager. - * - * A informational log is done to the supplied logger. If logger is - * NULL, an internal logger is used. If a name is supplied, - * only connections with the matching name will be logged. - * - * @param this the manager object - * @param logger logger to do the log, or NULL - * @param name name of a connection, or NULL - */ - void (*log_status) (ike_sa_manager_t* this, logger_t* logger, char* name); - - /** - * @brief Checkin the SA after usage. - * - * @warning the SA pointer MUST NOT be used after checkin! - * The SA must be checked out again! - * - * @param this the manager object - * @param ike_sa_id[in/out] the SA identifier, will be updated - * @param ike_sa[out] checked out SA - * @returns - * - SUCCESS if checked in - * - NOT_FOUND when not found (shouldn't happen!) - */ - status_t (*checkin) (ike_sa_manager_t* this, ike_sa_t *ike_sa); - - /** - * @brief Delete a SA, which was not checked out. - * - * @warning do not use this when the SA is already checked out, this will - * deadlock! - * - * @param this the manager object - * @param ike_sa_id[in/out] the SA identifier - * @returns - * - SUCCESS if found - * - NOT_FOUND when no such SA is available - */ - status_t (*delete) (ike_sa_manager_t* this, ike_sa_id_t *ike_sa_id); - - /** - * @brief Delete a checked out SA. - * - * @param this the manager object - * @param ike_sa SA to delete - * @returns - * - SUCCESS if found - * - NOT_FOUND when no such SA is available - */ - status_t (*checkin_and_delete) (ike_sa_manager_t* this, ike_sa_t *ike_sa); - - /** - * @brief Destroys the manager with all associated SAs. - * - * Threads will be driven out, so all SAs can be deleted cleanly. - * - * @param this the manager object - */ - void (*destroy) (ike_sa_manager_t *this); -}; - -/** - * @brief Create a manager. - * - * @returns ike_sa_manager_t object - * - * @ingroup sa - */ -ike_sa_manager_t *ike_sa_manager_create(void); - -#endif /*IKE_SA_MANAGER_H_*/ diff --git a/src/charon/charon/sa/states/Makefile.states b/src/charon/charon/sa/states/Makefile.states deleted file mode 100644 index a258ebef0..000000000 --- a/src/charon/charon/sa/states/Makefile.states +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright (C) 2005 Jan Hutter, 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 . -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# for more details. -# - -STATES_DIR= $(SA_DIR)states/ - -CHARON_OBJS+= $(BUILD_DIR)ike_auth_requested.o -$(BUILD_DIR)ike_auth_requested.o : $(STATES_DIR)ike_auth_requested.c $(STATES_DIR)ike_auth_requested.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)ike_sa_established.o -$(BUILD_DIR)ike_sa_established.o : $(STATES_DIR)ike_sa_established.c $(STATES_DIR)ike_sa_established.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)ike_sa_init_requested.o -$(BUILD_DIR)ike_sa_init_requested.o : $(STATES_DIR)ike_sa_init_requested.c $(STATES_DIR)ike_sa_init_requested.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)ike_sa_init_responded.o -$(BUILD_DIR)ike_sa_init_responded.o : $(STATES_DIR)ike_sa_init_responded.c $(STATES_DIR)ike_sa_init_responded.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)initiator_init.o -$(BUILD_DIR)initiator_init.o : $(STATES_DIR)initiator_init.c $(STATES_DIR)initiator_init.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)responder_init.o -$(BUILD_DIR)responder_init.o : $(STATES_DIR)responder_init.c $(STATES_DIR)responder_init.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)state.o -$(BUILD_DIR)state.o : $(STATES_DIR)state.c $(STATES_DIR)state.h - $(CC) $(CFLAGS) -c -o $@ $< \ No newline at end of file diff --git a/src/charon/charon/sa/states/ike_auth_requested.c b/src/charon/charon/sa/states/ike_auth_requested.c deleted file mode 100644 index 3d49f440f..000000000 --- a/src/charon/charon/sa/states/ike_auth_requested.c +++ /dev/null @@ -1,671 +0,0 @@ -/** - * @file ike_auth_requested.c - * - * @brief Implementation of ike_auth_requested_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 - -#include "ike_auth_requested.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -typedef struct private_ike_auth_requested_t private_ike_auth_requested_t; - -/** - * Private data of a ike_auth_requested_t object. - * - */ -struct private_ike_auth_requested_t { - /** - * Public interface of ike_auth_requested_t. - */ - ike_auth_requested_t public; - - /** - * Assigned IKE_SA. - */ - protected_ike_sa_t *ike_sa; - - /** - * SA config, just a copy of the one stored in the ike_sa. - */ - policy_t *policy; - - /** - * Received nonce from responder. - */ - chunk_t received_nonce; - - /** - * Sent nonce in IKE_SA_INIT request. - */ - chunk_t sent_nonce; - - /** - * IKE_SA_INIT-Request in binary form. - */ - chunk_t ike_sa_init_reply_data; - - /** - * Proposal to setup CHILD_SA - */ - proposal_t *proposal; - - /** - * Traffic selectors applicable at our site - */ - linked_list_t *my_ts; - - /** - * Traffic selectors applicable at remote site - */ - linked_list_t *other_ts; - - /** - * Child sa created in ike_sa_init_requested - */ - child_sa_t *child_sa; - - /** - * Assigned Logger. - * - * Is logger of ike_sa! - */ - logger_t *logger; - - /** - * Process the IDr payload (check if other id is valid) - * - * @param this calling object - * @param idr_payload ID payload of responder - * @return - * - SUCCESS - * - DELETE_ME - */ - status_t (*process_idr_payload) (private_ike_auth_requested_t *this, id_payload_t *idr_payload); - - /** - * Process the SA payload (check if selected proposals are valid, setup child sa) - * - * @param this calling object - * @param sa_payload SA payload of responder - * - * - SUCCESS - * - DELETE_ME - */ - status_t (*process_sa_payload) (private_ike_auth_requested_t *this, sa_payload_t *sa_payload); - - /** - * Process the AUTH payload (check authenticity of message) - * - * @param this calling object - * @param auth_payload AUTH payload of responder - * @param other_id_payload ID payload of responder - * - * - SUCCESS - * - DELETE_ME - */ - status_t (*process_auth_payload) (private_ike_auth_requested_t *this, auth_payload_t *auth_payload, id_payload_t *other_id_payload); - - /** - * Process the TS payload (check if selected traffic selectors are valid) - * - * @param this calling object - * @param ts_initiator TRUE if TS payload is TSi, FALSE for TSr - * @param ts_payload TS payload of responder - * - * - SUCCESS - * - DELETE_ME - */ - status_t (*process_ts_payload) (private_ike_auth_requested_t *this, bool ts_initiator, ts_payload_t *ts_payload); - - /** - * Process a notify payload - * - * @param this calling object - * @param notify_payload notify payload - * - * - SUCCESS - * - FAILED - * - DELETE_ME - */ - status_t (*process_notify_payload) (private_ike_auth_requested_t *this, notify_payload_t *notify_payload); - - /** - * Destroy function called internally of this class after state change to - * state IKE_SA_ESTABLISHED succeeded. - * - * This destroy function does not destroy objects which were passed to the new state. - * - * @param this calling object - */ - void (*destroy_after_state_change) (private_ike_auth_requested_t *this); -}; - - -/** - * Implements state_t.process_message - */ -static status_t process_message(private_ike_auth_requested_t *this, message_t *ike_auth_reply) -{ - ts_payload_t *tsi_payload = NULL, *tsr_payload = NULL; - id_payload_t *idr_payload = NULL; - auth_payload_t *auth_payload = NULL; - sa_payload_t *sa_payload = NULL; - iterator_t *payloads = NULL; - crypter_t *crypter = NULL; - signer_t *signer = NULL; - status_t status; - host_t *my_host, *other_host; - chunk_t seed; - prf_plus_t *prf_plus; - connection_t *connection; - - if (ike_auth_reply->get_exchange_type(ike_auth_reply) != IKE_AUTH) - { - this->logger->log(this->logger, ERROR | LEVEL1, "Message of type %s not supported in state ike_auth_requested", - mapping_find(exchange_type_m,ike_auth_reply->get_exchange_type(ike_auth_reply))); - return FAILED; - } - - if (ike_auth_reply->get_request(ike_auth_reply)) - { - this->logger->log(this->logger, ERROR | LEVEL1, "IKE_AUTH requests not allowed state ike_sa_init_responded"); - return FAILED; - } - - /* get signer for verification and crypter for decryption */ - signer = this->ike_sa->get_signer_responder(this->ike_sa); - crypter = this->ike_sa->get_crypter_responder(this->ike_sa); - - /* parse incoming message */ - status = ike_auth_reply->parse_body(ike_auth_reply, crypter, signer); - if (status != SUCCESS) - { - this->logger->log(this->logger, AUDIT, "IKE_AUTH reply decryption failed. Ignoring message"); - return status; - } - - this->policy = this->ike_sa->get_policy(this->ike_sa); - - /* we collect all payloads, which are processed later. Notify's are processed - * in place, since we don't know how may are there. - */ - payloads = ike_auth_reply->get_payload_iterator(ike_auth_reply); - while (payloads->has_next(payloads)) - { - payload_t *payload; - payloads->current(payloads, (void**)&payload); - - switch (payload->get_type(payload)) - { - case AUTHENTICATION: - { - auth_payload = (auth_payload_t*)payload; - break; - } - case ID_RESPONDER: - { - idr_payload = (id_payload_t*)payload; - break; - } - case SECURITY_ASSOCIATION: - { - sa_payload = (sa_payload_t*)payload; - break; - } - case TRAFFIC_SELECTOR_INITIATOR: - { - tsi_payload = (ts_payload_t*)payload; - break; - } - case TRAFFIC_SELECTOR_RESPONDER: - { - tsr_payload = (ts_payload_t*)payload; - break; - } - case NOTIFY: - { - notify_payload_t *notify_payload = (notify_payload_t *) payload; - /* handle the notify directly, abort if no further processing required */ - status = this->process_notify_payload(this, notify_payload); - if (status != SUCCESS) - { - payloads->destroy(payloads); - return status; - } - } - case CERTIFICATE: - { - /* TODO handle cert payloads */ - } - default: - { - this->logger->log(this->logger, ERROR|LEVEL1, "Ignoring Payload %s (%d)", - mapping_find(payload_type_m, payload->get_type(payload)), payload->get_type(payload)); - break; - } - } - } - /* iterator can be destroyed */ - payloads->destroy(payloads); - - /* check if we have all payloads */ - if (!(idr_payload && sa_payload && auth_payload && tsi_payload && tsr_payload)) - { - this->logger->log(this->logger, AUDIT, "IKE_AUTH reply did not contain all required payloads. Deleting IKE_SA"); - return DELETE_ME; - } - - /* process all payloads */ - status = this->process_idr_payload(this, idr_payload); - if (status != SUCCESS) - { - return status; - } - status = this->process_auth_payload(this, auth_payload,idr_payload); - if (status != SUCCESS) - { - return status; - } - status = this->process_sa_payload(this, sa_payload); - if (status != SUCCESS) - { - return status; - } - status = this->process_ts_payload(this, TRUE, tsi_payload); - if (status != SUCCESS) - { - return status; - } - status = this->process_ts_payload(this, FALSE, tsr_payload); - if (status != SUCCESS) - { - return status; - } - - /* install child SAs for AH and esp */ - if (!this->child_sa) - { - this->logger->log(this->logger, CONTROL, "No CHILD_SA requested, no CHILD_SA built"); - } - if (!this->proposal) - { - this->logger->log(this->logger, CONTROL, "Proposal negotiation failed, no CHILD_SA built"); - this->child_sa->destroy(this->child_sa); - this->child_sa = NULL; - } - else if (this->my_ts->get_count(this->my_ts) == 0 || this->other_ts->get_count(this->other_ts) == 0) - { - this->logger->log(this->logger, CONTROL, "Traffic selector negotiation failed, no CHILD_SA built"); - this->child_sa->destroy(this->child_sa); - this->child_sa = NULL; - } - else - { - seed = chunk_alloc(this->sent_nonce.len + this->received_nonce.len); - memcpy(seed.ptr, this->sent_nonce.ptr, this->sent_nonce.len); - memcpy(seed.ptr + this->sent_nonce.len, this->received_nonce.ptr, this->received_nonce.len); - prf_plus = prf_plus_create(this->ike_sa->get_child_prf(this->ike_sa), seed); - chunk_free(&seed); - - status = this->child_sa->update(this->child_sa, this->proposal, prf_plus); - prf_plus->destroy(prf_plus); - if (status != SUCCESS) - { - this->logger->log(this->logger, AUDIT, "Could not install CHILD_SA! Deleting IKE_SA"); - return DELETE_ME; - } - status = this->child_sa->add_policies(this->child_sa, this->my_ts, this->other_ts); - if (status != SUCCESS) - { - this->logger->log(this->logger, AUDIT, "Could not install CHILD_SA policy! Deleting IKE_SA"); - return DELETE_ME; - } - this->ike_sa->add_child_sa(this->ike_sa, this->child_sa); - } - - this->ike_sa->set_last_replied_message_id(this->ike_sa,ike_auth_reply->get_message_id(ike_auth_reply)); - - /* create new state */ - this->ike_sa->set_new_state(this->ike_sa, (state_t*)ike_sa_established_create(this->ike_sa)); - this->destroy_after_state_change(this); - - connection = this->ike_sa->get_connection(this->ike_sa); - my_host = connection->get_my_host(connection); - other_host = connection->get_other_host(connection); - this->logger->log(this->logger, AUDIT, "IKE_SA established between %s - %s", - my_host->get_address(my_host), other_host->get_address(other_host)); - - return SUCCESS; -} - -/** - * Implements private_ike_auth_requested_t.process_idr_payload - */ -static status_t process_idr_payload(private_ike_auth_requested_t *this, id_payload_t *idr_payload) -{ - identification_t *other_id, *configured_other_id; - connection_t *connection; - - other_id = idr_payload->get_identification(idr_payload); - configured_other_id = this->policy->get_other_id(this->policy); - - this->logger->log(this->logger, CONTROL|LEVEL1, "configured ID: %s, ID of responder: %s", - configured_other_id->get_string(configured_other_id), - other_id->get_string(other_id)); - - if (!other_id->belongs_to(other_id, configured_other_id)) - { - other_id->destroy(other_id); - this->logger->log(this->logger, AUDIT, "IKE_AUTH reply contained a not acceptable ID. Deleting IKE_SA"); - return DELETE_ME; - } - - connection = this->ike_sa->get_connection(this->ike_sa); - connection->update_other_id(connection, other_id->clone(other_id)); - - this->policy->update_other_id(this->policy, other_id); - return SUCCESS; -} - -/** - * Implements private_ike_auth_requested_t.process_sa_payload - */ -static status_t process_sa_payload(private_ike_auth_requested_t *this, sa_payload_t *sa_payload) -{ - proposal_t *proposal, *proposal_tmp; - linked_list_t *proposal_list; - - /* get his selected proposal */ - proposal_list = sa_payload->get_proposals(sa_payload); - /* check count of proposals */ - if (proposal_list->get_count(proposal_list) == 0) - { - /* no proposal? we accept this, but no child sa is built */ - this->logger->log(this->logger, AUDIT, "IKE_AUTH reply's SA_PAYLOAD didn't contain any proposals. No CHILD_SA created", - proposal_list->get_count(proposal_list)); - proposal_list->destroy(proposal_list); - return SUCCESS; - } - if (proposal_list->get_count(proposal_list) > 1) - { - this->logger->log(this->logger, AUDIT, "IKE_AUTH reply's SA_PAYLOAD contained %d proposal. Deleting IKE_SA", - proposal_list->get_count(proposal_list)); - while (proposal_list->remove_last(proposal_list, (void**)&proposal) == SUCCESS) - { - proposal->destroy(proposal); - } - proposal_list->destroy(proposal_list); - return DELETE_ME; - } - - /* we have to re-check here if other's selection is valid */ - proposal = this->policy->select_proposal(this->policy, proposal_list); - /* list not needed anymore */ - while (proposal_list->remove_last(proposal_list, (void**)&proposal_tmp) == SUCCESS) - { - proposal_tmp->destroy(proposal_tmp); - } - proposal_list->destroy(proposal_list); - /* got a match? */ - if (proposal == NULL) - { - this->logger->log(this->logger, AUDIT, "IKE_AUTH reply contained a not offered proposal. Deleting IKE_SA"); - return DELETE_ME; - } - - /* apply proposal */ - this->proposal = proposal; - - return SUCCESS; -} - -/** - * Implements private_ike_auth_requested_t.process_auth_payload - */ -static status_t process_auth_payload(private_ike_auth_requested_t *this, auth_payload_t *auth_payload, id_payload_t *other_id_payload) -{ - authenticator_t *authenticator; - status_t status; - - authenticator = authenticator_create(this->ike_sa); - status = authenticator->verify_auth_data(authenticator,auth_payload,this->ike_sa_init_reply_data,this->sent_nonce,other_id_payload,FALSE); - authenticator->destroy(authenticator); - if (status != SUCCESS) - { - this->logger->log(this->logger, AUDIT, "Verification of IKE_AUTH reply failed. Deleting IKE_SA"); - return DELETE_ME; - } - - this->logger->log(this->logger, CONTROL|LEVEL1, "AUTH data verified successfully"); - return SUCCESS; -} - -/** - * Implements private_ike_auth_requested_t.process_ts_payload - */ -static status_t process_ts_payload(private_ike_auth_requested_t *this, bool ts_initiator, ts_payload_t *ts_payload) -{ - linked_list_t *ts_received, *ts_selected; - traffic_selector_t *ts; - - /* get ts form payload */ - ts_received = ts_payload->get_traffic_selectors(ts_payload); - /* select ts depending on payload type */ - if (ts_initiator) - { - ts_selected = this->policy->select_my_traffic_selectors(this->policy, ts_received); - this->my_ts = ts_selected; - } - else - { - ts_selected = this->policy->select_other_traffic_selectors(this->policy, ts_received); - this->other_ts = ts_selected; - } - /* check if the responder selected valid proposals */ - if (ts_selected->get_count(ts_selected) != ts_received->get_count(ts_received)) - { - this->logger->log(this->logger, AUDIT, "IKE_AUTH reply contained not offered traffic selectors."); - } - - /* cleanup */ - while (ts_received->remove_last(ts_received, (void**)&ts) == SUCCESS) - { - ts->destroy(ts); - } - ts_received->destroy(ts_received); - - return SUCCESS; -} - -/** - * Implements private_ike_auth_requested_t.process_notify_payload - */ -static status_t process_notify_payload(private_ike_auth_requested_t *this, notify_payload_t *notify_payload) -{ - notify_message_type_t notify_message_type = notify_payload->get_notify_message_type(notify_payload); - - this->logger->log(this->logger, CONTROL|LEVEL1, "Process notify type %s", - mapping_find(notify_message_type_m, notify_message_type)); - - switch (notify_message_type) - { - case INVALID_SYNTAX: - { - this->logger->log(this->logger, AUDIT, "IKE_AUTH reply contained an INVALID_SYNTAX notify. Deleting IKE_SA"); - return DELETE_ME; - - } - case AUTHENTICATION_FAILED: - { - this->logger->log(this->logger, AUDIT, "IKE_AUTH reply contained an AUTHENTICATION_FAILED notify. Deleting IKE_SA"); - return DELETE_ME; - - } - case SINGLE_PAIR_REQUIRED: - { - this->logger->log(this->logger, AUDIT, "IKE_AUTH reply contained a SINGLE_PAIR_REQUIRED notify. Deleting IKE_SA"); - return DELETE_ME; - } - default: - { - /* - * - In case of unknown error: IKE_SA gets destroyed. - * - In case of unknown status: logging - */ - - if (notify_message_type < 16383) - { - this->logger->log(this->logger, AUDIT, "IKE_AUTH reply contained an unknown notify error (%d). Deleting IKE_SA", - notify_message_type); - return DELETE_ME; - - } - else - { - this->logger->log(this->logger, CONTROL, "IKE_AUTH reply contained an unknown notify (%d), ignored.", - notify_message_type); - return SUCCESS; - } - } - } -} - -/** - * Implements state_t.get_state - */ -static ike_sa_state_t get_state(private_ike_auth_requested_t *this) -{ - return IKE_AUTH_REQUESTED; -} - -/** - * Implements state_t.get_state - */ -static void destroy(private_ike_auth_requested_t *this) -{ - chunk_free(&(this->received_nonce)); - chunk_free(&(this->sent_nonce)); - chunk_free(&(this->ike_sa_init_reply_data)); - if (this->child_sa) - { - this->child_sa->destroy(this->child_sa); - } - if (this->my_ts) - { - traffic_selector_t *ts; - while (this->my_ts->remove_last(this->my_ts, (void**)&ts) == SUCCESS) - { - ts->destroy(ts); - } - this->my_ts->destroy(this->my_ts); - } - if (this->other_ts) - { - traffic_selector_t *ts; - while (this->other_ts->remove_last(this->other_ts, (void**)&ts) == SUCCESS) - { - ts->destroy(ts); - } - this->other_ts->destroy(this->other_ts); - } - if (this->proposal) - { - this->proposal->destroy(this->proposal); - } - free(this); -} -/** - * Implements protected_ike_sa_t.destroy_after_state_change - */ -static void destroy_after_state_change(private_ike_auth_requested_t *this) -{ - chunk_free(&(this->received_nonce)); - chunk_free(&(this->sent_nonce)); - chunk_free(&(this->ike_sa_init_reply_data)); - if (this->my_ts) - { - traffic_selector_t *ts; - while (this->my_ts->remove_last(this->my_ts, (void**)&ts) == SUCCESS) - { - ts->destroy(ts); - } - this->my_ts->destroy(this->my_ts); - } - if (this->other_ts) - { - traffic_selector_t *ts; - while (this->other_ts->remove_last(this->other_ts, (void**)&ts) == SUCCESS) - { - ts->destroy(ts); - } - this->other_ts->destroy(this->other_ts); - } - if (this->proposal) - { - this->proposal->destroy(this->proposal); - } - free(this); -} - -/* - * Described in header. - */ -ike_auth_requested_t *ike_auth_requested_create(protected_ike_sa_t *ike_sa,chunk_t sent_nonce,chunk_t received_nonce,chunk_t ike_sa_init_reply_data, child_sa_t *child_sa) -{ - private_ike_auth_requested_t *this = malloc_thing(private_ike_auth_requested_t); - - /* interface functions */ - this->public.state_interface.process_message = (status_t (*) (state_t *,message_t *)) process_message; - this->public.state_interface.get_state = (ike_sa_state_t (*) (state_t *)) get_state; - this->public.state_interface.destroy = (void (*) (state_t *)) destroy; - - /* private functions */ - this->process_idr_payload = process_idr_payload; - this->process_sa_payload = process_sa_payload; - this->process_auth_payload = process_auth_payload; - this->process_ts_payload = process_ts_payload; - this->process_notify_payload = process_notify_payload; - this->destroy_after_state_change = destroy_after_state_change; - - /* private data */ - this->ike_sa = ike_sa; - this->received_nonce = received_nonce; - this->sent_nonce = sent_nonce; - this->ike_sa_init_reply_data = ike_sa_init_reply_data; - this->logger = logger_manager->get_logger(logger_manager, IKE_SA); - this->my_ts = NULL; - this->other_ts = NULL; - this->proposal = NULL; - this->child_sa = child_sa; - - return &(this->public); -} diff --git a/src/charon/charon/sa/states/ike_auth_requested.h b/src/charon/charon/sa/states/ike_auth_requested.h deleted file mode 100644 index a8eef014c..000000000 --- a/src/charon/charon/sa/states/ike_auth_requested.h +++ /dev/null @@ -1,72 +0,0 @@ -/** - * @file ike_auth_requested.h - * - * @brief Interface of ike_auth_requested_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef IKE_AUTH_REQUESTED_H_ -#define IKE_AUTH_REQUESTED_H_ - -#include -#include - - -typedef struct ike_auth_requested_t ike_auth_requested_t; - -/** - * @brief This class represents an IKE_SA, which has requested an IKE_AUTH. - * - * The state accpets IKE_AUTH responses. It proves the authenticity - * and sets up the first child sa. After that, it changes IKE_SA state to - * IKE_SA_ESTABLISHED. - * - * @ Constructors: - * - ike_auth_requested_create() - * - * @todo handle certificate payloads - * - * @ingroup states - */ -struct ike_auth_requested_t { - /** - * The state_t interface. - */ - state_t state_interface; - -}; - -/** - * Constructor of class ike_auth_requested_t - * - * @param ike_sa assigned ike_sa object - * @param sent_nonce Sent nonce value in IKE_SA_INIT request - * @param received_nonce Received nonce value in IKE_SA_INIT response - * @param ike_sa_init_reply_data binary representation of IKE_SA_INIT reply - * @param child_sa opened but not completed child_sa - * @return created ike_auth_requested_t object - * - * @ingroup states - */ -ike_auth_requested_t *ike_auth_requested_create(protected_ike_sa_t *ike_sa, - chunk_t sent_nonce, - chunk_t received_nonce, - chunk_t ike_sa_init_reply_data, - child_sa_t *child_sa); - -#endif /*IKE_AUTH_REQUESTED_H_*/ diff --git a/src/charon/charon/sa/states/ike_sa_established.c b/src/charon/charon/sa/states/ike_sa_established.c deleted file mode 100644 index e91409f6a..000000000 --- a/src/charon/charon/sa/states/ike_sa_established.c +++ /dev/null @@ -1,239 +0,0 @@ -/** - * @file ike_sa_established.c - * - * @brief Implementation of ike_sa_established_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 "ike_sa_established.h" - -#include -#include - - -typedef struct private_ike_sa_established_t private_ike_sa_established_t; - -/** - * Private data of a ike_sa_established_t object. - */ -struct private_ike_sa_established_t { - /** - * methods of the state_t interface - */ - ike_sa_established_t public; - - /** - * Assigned IKE_SA. - */ - protected_ike_sa_t *ike_sa; - - /** - * Assigned logger. Use logger of IKE_SA. - */ - logger_t *logger; - - /** - * Process a notify payload - * - * @param this calling object - * @param notify_payload notify payload - * @param response response message of type INFORMATIONAL - * - * - SUCCESS - * - FAILED - * - DELETE_ME - */ - status_t (*process_notify_payload) (private_ike_sa_established_t *this, notify_payload_t *notify_payload,message_t *response); -}; - -/** - * Implements state_t.get_state - */ -static status_t process_message(private_ike_sa_established_t *this, message_t *message) -{ - delete_payload_t *delete_request = NULL; - ike_sa_id_t *ike_sa_id; - iterator_t *payloads; - message_t *response; - crypter_t *crypter; - signer_t *signer; - status_t status; - - if (message->get_exchange_type(message) != INFORMATIONAL) - { - this->logger->log(this->logger, ERROR | LEVEL1, "Message of type %s not supported in state ike_sa_established", - mapping_find(exchange_type_m,message->get_exchange_type(message))); - return FAILED; - } - - if (!message->get_request(message)) - { - this->logger->log(this->logger, ERROR | LEVEL1, "INFORMATIONAL responses not handled in state ike_sa_established"); - return FAILED; - } - - ike_sa_id = this->ike_sa->public.get_id(&(this->ike_sa->public)); - - /* get signer for verification and crypter for decryption */ - if (!ike_sa_id->is_initiator(ike_sa_id)) - { - crypter = this->ike_sa->get_crypter_initiator(this->ike_sa); - signer = this->ike_sa->get_signer_initiator(this->ike_sa); - } - else - { - crypter = this->ike_sa->get_crypter_responder(this->ike_sa); - signer = this->ike_sa->get_signer_responder(this->ike_sa); - } - - /* parse incoming message */ - status = message->parse_body(message, crypter, signer); - if (status != SUCCESS) - { - this->logger->log(this->logger, AUDIT, "INFORMATIONAL request decryption failed. Ignoring message"); - return status; - } - - /* build empty INFORMATIONAL message */ - this->ike_sa->build_message(this->ike_sa, INFORMATIONAL, FALSE, &response); - - payloads = message->get_payload_iterator(message); - - while (payloads->has_next(payloads)) - { - payload_t *payload; - payloads->current(payloads, (void**)&payload); - - switch (payload->get_type(payload)) - { - case NOTIFY: - { - notify_payload_t *notify_payload = (notify_payload_t *) payload; - /* handle the notify directly, abort if no further processing required */ - status = this->process_notify_payload(this, notify_payload,response); - if (status != SUCCESS) - { - payloads->destroy(payloads); - response->destroy(response); - return status; - } - } - case DELETE: - { - delete_request = (delete_payload_t *) payload; - break; - } - default: - { - this->logger->log(this->logger, ERROR|LEVEL1, "Ignoring Payload %s (%d)", - mapping_find(payload_type_m, payload->get_type(payload)), payload->get_type(payload)); - break; - } - } - } - /* iterator can be destroyed */ - payloads->destroy(payloads); - - if (delete_request) - { - if (delete_request->get_protocol_id(delete_request) == PROTO_IKE) - { - this->logger->log(this->logger, AUDIT, "DELETE request for IKE_SA received"); - response->destroy(response); - return DELETE_ME; - } - else - { - this->logger->log(this->logger, AUDIT, "DELETE request for CHILD_SA received. Ignored"); - response->destroy(response); - return SUCCESS; - } - } - - status = this->ike_sa->send_response(this->ike_sa, response); - /* message can now be sent (must not be destroyed) */ - if (status != SUCCESS) - { - this->logger->log(this->logger, AUDIT, "Unable to send INFORMATIONAL reply"); - response->destroy(response); - return FAILED; - } - - return SUCCESS; -} - -/** - * Implementation of private_ike_sa_established_t.process_notify_payload; - */ -static status_t process_notify_payload (private_ike_sa_established_t *this, notify_payload_t *notify_payload, message_t *response) -{ - notify_message_type_t notify_message_type = notify_payload->get_notify_message_type(notify_payload); - - this->logger->log(this->logger, CONTROL|LEVEL1, "Process notify type %s for protocol %s", - mapping_find(notify_message_type_m, notify_message_type), - mapping_find(protocol_id_m, notify_payload->get_protocol_id(notify_payload))); - - switch (notify_message_type) - { - default: - { - this->logger->log(this->logger, AUDIT, "INFORMATIONAL request contained an unknown notify (%d), ignored.", notify_message_type); - } - } - - - return SUCCESS; -} - -/** - * Implementation of state_t.get_state. - */ -static ike_sa_state_t get_state(private_ike_sa_established_t *this) -{ - return IKE_SA_ESTABLISHED; -} - -/** - * Implementation of state_t.get_state - */ -static void destroy(private_ike_sa_established_t *this) -{ - free(this); -} - -/* - * Described in header. - */ -ike_sa_established_t *ike_sa_established_create(protected_ike_sa_t *ike_sa) -{ - private_ike_sa_established_t *this = malloc_thing(private_ike_sa_established_t); - - /* interface functions */ - this->public.state_interface.process_message = (status_t (*) (state_t *,message_t *)) process_message; - this->public.state_interface.get_state = (ike_sa_state_t (*) (state_t *)) get_state; - this->public.state_interface.destroy = (void (*) (state_t *)) destroy; - - /* private functions */ - this->process_notify_payload = process_notify_payload; - - /* private data */ - this->ike_sa = ike_sa; - this->logger = logger_manager->get_logger(logger_manager, IKE_SA); - - return &(this->public); -} diff --git a/src/charon/charon/sa/states/ike_sa_established.h b/src/charon/charon/sa/states/ike_sa_established.h deleted file mode 100644 index 8477ad5bc..000000000 --- a/src/charon/charon/sa/states/ike_sa_established.h +++ /dev/null @@ -1,64 +0,0 @@ -/** - * @file ike_sa_established.h - * - * @brief Interface of ike_sa_established_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef IKE_SA_ESTABLISHED_H_ -#define IKE_SA_ESTABLISHED_H_ - -#include -#include - -typedef struct ike_sa_established_t ike_sa_established_t; - -/** - * @brief This class represents an the state of an established - * IKE_SA. - * - * @b Constructors: - * - ike_sa_established_create() - * - * @todo Implement handling of CREATE_CHILD_SA requests - * - * @todo Implement initialization of CREATE_CHILD_SA requests - * - * @todo Implement handling of any other message - * - * @ingroup states - */ -struct ike_sa_established_t { - /** - * methods of the state_t interface - */ - state_t state_interface; - -}; - -/** - * @brief Constructor of class ike_sa_established_t - * - * @param ike_sa assigned ike_sa - * @return created ike_sa_established_t object - * - * @ingroup states - */ -ike_sa_established_t *ike_sa_established_create(protected_ike_sa_t *ike_sa); - -#endif /*IKE_SA_ESTABLISHED_H_*/ diff --git a/src/charon/charon/sa/states/ike_sa_init_requested.c b/src/charon/charon/sa/states/ike_sa_init_requested.c deleted file mode 100644 index 311cdf0a0..000000000 --- a/src/charon/charon/sa/states/ike_sa_init_requested.c +++ /dev/null @@ -1,798 +0,0 @@ -/** - * @file ike_sa_init_requested.c - * - * @brief Implementation of ike_sa_init_requested_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 "ike_sa_init_requested.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -typedef struct private_ike_sa_init_requested_t private_ike_sa_init_requested_t; - -/** - * Private data of a ike_sa_init_requested_t object. - * - */ -struct private_ike_sa_init_requested_t { - /** - * Public interface of an ike_sa_init_requested_t object. - */ - ike_sa_init_requested_t public; - - /** - * Assigned IKE_SA - */ - protected_ike_sa_t *ike_sa; - - /** - * Diffie Hellman object used to compute shared secret. - */ - diffie_hellman_t *diffie_hellman; - - /** - * Sent nonce value. - */ - chunk_t sent_nonce; - - /** - * Received nonce - */ - chunk_t received_nonce; - - /** - * Selected proposal - */ - proposal_t *proposal; - - /** - * Packet data of ike_sa_init request - */ - chunk_t ike_sa_init_request_data; - - /** - * Created child sa, if any - */ - child_sa_t *child_sa; - - /** - * Assigned logger - * - * Is logger of ike_sa! - */ - logger_t *logger; - - - /** - * Process NONCE payload of IKE_SA_INIT response. - * - * @param this calling object - * @param nonce_payload NONCE payload to process - * @return SUCCESS in any case - */ - status_t (*process_nonce_payload) (private_ike_sa_init_requested_t *this, nonce_payload_t *nonce_payload); - - /** - * Process SA payload of IKE_SA_INIT response. - * - * @param this calling object - * @param sa_payload SA payload to process - * @return - * - SUCCESS - * - FAILED - */ - status_t (*process_sa_payload) (private_ike_sa_init_requested_t *this, sa_payload_t *sa_payload); - - /** - * Process KE payload of IKE_SA_INIT response. - * - * @param this calling object - * @param sa_payload KE payload to process - * @return - * - SUCCESS - * - FAILED - */ - status_t (*process_ke_payload) (private_ike_sa_init_requested_t *this, ke_payload_t *ke_payload); - - /** - * Build ID payload for IKE_AUTH request. - * - * @param this calling object - * @param[out] id_payload buildet ID payload - * @param response created payload will be added to this message_t object - * @return - * - SUCCESS - * - FAILED - */ - status_t (*build_id_payload) (private_ike_sa_init_requested_t *this,id_payload_t **id_payload, message_t *response); - - /** - * Build IDr payload for IKE_AUTH request. - * - * Only built when the ID of the responder contains no wildcards. - * - * @param this calling object - * @param response created payload will be added to this message_t object - * @return - * - SUCCESS - * - FAILED - */ - status_t (*build_idr_payload) (private_ike_sa_init_requested_t *this, message_t *response); - - /** - * Build AUTH payload for IKE_AUTH request. - * - * @param this calling object - * @param my_id_payload buildet ID payload - * @param response created payload will be added to this message_t object - * @return - * - SUCCESS - * - FAILED - */ - status_t (*build_auth_payload) (private_ike_sa_init_requested_t *this,id_payload_t *my_id_payload, message_t *response); - - /** - * Build SA payload for IKE_AUTH request. - * - * @param this calling object - * @param response created payload will be added to this message_t object - * @return - * - SUCCESS - * - FAILED - */ - status_t (*build_sa_payload) (private_ike_sa_init_requested_t *this, message_t *response); - - /** - * Build TSi payload for IKE_AUTH request. - * - * @param this calling object - * @param response created payload will be added to this message_t object - * @return - * - SUCCESS - * - FAILED - */ - status_t (*build_tsi_payload) (private_ike_sa_init_requested_t *this, message_t *response); - - /** - * Build TSr payload for IKE_AUTH request. - * - * @param this calling object - * @param response created payload will be added to this message_t object - * @return - * - SUCCESS - * - FAILED - */ - status_t (*build_tsr_payload) (private_ike_sa_init_requested_t *this, message_t *response); - - /** - * Process a notify payload and react. - * - * @param this calling object - * @param notify_payload notify_payload to handle - */ - status_t (*process_notify_payload) (private_ike_sa_init_requested_t *this, notify_payload_t *notify_payload); - - /** - * Destroy function called internally of this class after state change to - * state IKE_AUTH_REQUESTED succeeded. - * - * This destroy function does not destroy objects which were passed to the new state. - * - * @param this calling object - */ - void (*destroy_after_state_change) (private_ike_sa_init_requested_t *this); -}; - -/** - * Implementation of state_t.process_message. - */ -static status_t process_message(private_ike_sa_init_requested_t *this, message_t *ike_sa_init_reply) -{ - ike_auth_requested_t *next_state; - chunk_t ike_sa_init_reply_data; - sa_payload_t *sa_payload = NULL; - ke_payload_t *ke_payload = NULL; - id_payload_t *id_payload = NULL; - nonce_payload_t *nonce_payload = NULL; - u_int64_t responder_spi; - ike_sa_id_t *ike_sa_id; - iterator_t *payloads; - host_t *me; - connection_t *connection; - policy_t *policy; - - message_t *request; - status_t status; - - /* - * In this state a reply message of type IKE_SA_INIT is expected: - * - * <-- HDR, SAr1, KEr, Nr, [CERTREQ] - * or - * <-- HDR, N - */ - - if (ike_sa_init_reply->get_exchange_type(ike_sa_init_reply) != IKE_SA_INIT) - { - this->logger->log(this->logger, ERROR | LEVEL1, "Message of type %s not supported in state ike_sa_init_requested", - mapping_find(exchange_type_m,ike_sa_init_reply->get_exchange_type(ike_sa_init_reply))); - return FAILED; - } - - if (ike_sa_init_reply->get_request(ike_sa_init_reply)) - { - this->logger->log(this->logger, ERROR | LEVEL1, "IKE_SA_INIT requests not allowed state ike_sa_init_responded"); - return FAILED; - } - - /* parse incoming message */ - status = ike_sa_init_reply->parse_body(ike_sa_init_reply, NULL, NULL); - if (status != SUCCESS) - { - this->logger->log(this->logger, ERROR | LEVEL1, "IKE_SA_INIT reply parsing faild. Ignoring message"); - return status; - } - - /* because we are original initiator we have to update the responder SPI to the new one */ - responder_spi = ike_sa_init_reply->get_responder_spi(ike_sa_init_reply); - if (responder_spi == 0) - { - this->logger->log(this->logger, ERROR | LEVEL1, "IKE_SA_INIT reply contained a SPI of zero"); - return FAILED; - } - ike_sa_id = this->ike_sa->public.get_id(&(this->ike_sa->public)); - ike_sa_id->set_responder_spi(ike_sa_id,responder_spi); - - /* Iterate over all payloads. - * - * The message is allready checked for the right payload types. - */ - payloads = ike_sa_init_reply->get_payload_iterator(ike_sa_init_reply); - while (payloads->has_next(payloads)) - { - payload_t *payload; - payloads->current(payloads, (void**)&payload); - - switch (payload->get_type(payload)) - { - case SECURITY_ASSOCIATION: - { - sa_payload = (sa_payload_t*)payload; - break; - } - case KEY_EXCHANGE: - { - ke_payload = (ke_payload_t*)payload; - break; - } - case NONCE: - { - nonce_payload = (nonce_payload_t*)payload; - break; - } - case NOTIFY: - { - notify_payload_t *notify_payload = (notify_payload_t *) payload; - - status = this->process_notify_payload(this, notify_payload); - if (status != SUCCESS) - { - payloads->destroy(payloads); - return status; - } - break; - } - default: - { - this->logger->log(this->logger, ERROR|LEVEL1, "Ignoring payload %s (%d)", - mapping_find(payload_type_m, payload->get_type(payload)), payload->get_type(payload)); - break; - } - - } - - } - payloads->destroy(payloads); - - if (!(nonce_payload && sa_payload && ke_payload)) - { - this->logger->log(this->logger, AUDIT, "IKE_SA_INIT reply did not contain all required payloads. Deleting IKE_SA"); - return DELETE_ME; - } - - status = this->process_nonce_payload (this,nonce_payload); - if (status != SUCCESS) - { - return status; - } - - status = this->process_sa_payload (this,sa_payload); - if (status != SUCCESS) - { - return status; - } - - status = this->process_ke_payload (this,ke_payload); - if (status != SUCCESS) - { - return status; - } - - /* derive all the keys used in the IKE_SA */ - status = this->ike_sa->build_transforms(this->ike_sa, this->proposal, this->diffie_hellman, this->sent_nonce, this->received_nonce); - if (status != SUCCESS) - { - this->logger->log(this->logger, AUDIT, "Transform objects could not be created from selected proposal. Deleting IKE_SA"); - return DELETE_ME; - } - - /* apply the address on wich we really received the packet */ - connection = this->ike_sa->get_connection(this->ike_sa); - me = ike_sa_init_reply->get_destination(ike_sa_init_reply); - connection->update_my_host(connection, me->clone(me)); - policy = this->ike_sa->get_policy(this->ike_sa); - policy->update_my_ts(policy, me); - - /* build empty message */ - this->ike_sa->build_message(this->ike_sa, IKE_AUTH, TRUE, &request); - - status = this->build_id_payload(this, &id_payload, request); - if (status != SUCCESS) - { - request->destroy(request); - return status; - } - status = this->build_idr_payload(this, request); - if (status != SUCCESS) - { - request->destroy(request); - return status; - } - status = this->build_auth_payload(this, (id_payload_t*)id_payload, request); - if (status != SUCCESS) - { - request->destroy(request); - return status; - } - status = this->build_sa_payload(this, request); - if (status != SUCCESS) - { - request->destroy(request); - return status; - } - status = this->build_tsi_payload(this, request); - if (status != SUCCESS) - { - request->destroy(request); - return status; - } - status = this->build_tsr_payload(this, request); - if (status != SUCCESS) - { - request->destroy(request); - return status; - } - - /* message can now be sent (must not be destroyed) */ - status = this->ike_sa->send_request(this->ike_sa, request); - if (status != SUCCESS) - { - this->logger->log(this->logger, AUDIT, "Unable to send IKE_AUTH request. Deleting IKE_SA"); - request->destroy(request); - return DELETE_ME; - } - - this->ike_sa->set_last_replied_message_id(this->ike_sa,ike_sa_init_reply->get_message_id(ike_sa_init_reply)); - - ike_sa_init_reply_data = ike_sa_init_reply->get_packet_data(ike_sa_init_reply); - - /* state can now be changed */ - next_state = ike_auth_requested_create(this->ike_sa, this->sent_nonce, this->received_nonce, - ike_sa_init_reply_data, this->child_sa); - this->ike_sa->set_new_state(this->ike_sa,(state_t *) next_state); - - this->destroy_after_state_change(this); - return SUCCESS; -} - - -/** - * Implementation of private_ike_sa_init_requested_t.process_nonce_payload. - */ -status_t process_nonce_payload (private_ike_sa_init_requested_t *this, nonce_payload_t *nonce_payload) -{ - free(this->received_nonce.ptr); - this->received_nonce = nonce_payload->get_nonce(nonce_payload); - return SUCCESS; -} - - -/** - * Implementation of private_ike_sa_init_requested_t.process_sa_payload. - */ -status_t process_sa_payload (private_ike_sa_init_requested_t *this, sa_payload_t *sa_payload) -{ - proposal_t *proposal; - linked_list_t *proposal_list; - connection_t *connection; - - connection = this->ike_sa->get_connection(this->ike_sa); - - /* get the list of selected proposals, the peer has to select only one proposal */ - proposal_list = sa_payload->get_proposals (sa_payload); - if (proposal_list->get_count(proposal_list) != 1) - { - this->logger->log(this->logger, AUDIT, "IKE_SA_INIT response did not contain a single proposal. Deleting IKE_SA"); - while (proposal_list->remove_last(proposal_list, (void**)&proposal) == SUCCESS) - { - proposal->destroy(proposal); - } - proposal_list->destroy(proposal_list); - return DELETE_ME; - } - - /* we have to re-check if the others selection is valid */ - this->proposal = connection->select_proposal(connection, proposal_list); - while (proposal_list->remove_last(proposal_list, (void**)&proposal) == SUCCESS) - { - proposal->destroy(proposal); - } - proposal_list->destroy(proposal_list); - - if (this->proposal == NULL) - { - this->logger->log(this->logger, AUDIT, "IKE_SA_INIT response contained selected proposal we did not offer. Deleting IKE_SA"); - return DELETE_ME; - } - - return SUCCESS; -} - -/** - * Implementation of private_ike_sa_init_requested_t.process_ke_payload. - */ -status_t process_ke_payload (private_ike_sa_init_requested_t *this, ke_payload_t *ke_payload) -{ - this->diffie_hellman->set_other_public_value(this->diffie_hellman, ke_payload->get_key_exchange_data(ke_payload)); - - return SUCCESS; -} - -/** - * Implementation of private_ike_sa_init_requested_t.build_id_payload. - */ -static status_t build_id_payload (private_ike_sa_init_requested_t *this,id_payload_t **id_payload, message_t *request) -{ - policy_t *policy; - id_payload_t *new_id_payload; - identification_t *identification; - - policy = this->ike_sa->get_policy(this->ike_sa); - identification = policy->get_my_id(policy); - new_id_payload = id_payload_create_from_identification(TRUE, identification); - - this->logger->log(this->logger, CONTROL|LEVEL2, "Add ID payload to message"); - request->add_payload(request,(payload_t *) new_id_payload); - - *id_payload = new_id_payload; - - return SUCCESS; -} - -/** - * Implementation of private_ike_sa_init_requested_t.build_idr_payload. - */ -static status_t build_idr_payload (private_ike_sa_init_requested_t *this, message_t *request) -{ - policy_t *policy; - id_payload_t *idr_payload; - identification_t *identification; - - policy = this->ike_sa->get_policy(this->ike_sa); - identification = policy->get_other_id(policy); - if (!identification->contains_wildcards(identification)) - { - idr_payload = id_payload_create_from_identification(FALSE, identification); - - this->logger->log(this->logger, CONTROL|LEVEL2, "Add IDr payload to message"); - request->add_payload(request,(payload_t *) idr_payload); - } - return SUCCESS; -} - -/** - * Implementation of private_ike_sa_init_requested_t.build_auth_payload. - */ -static status_t build_auth_payload (private_ike_sa_init_requested_t *this, id_payload_t *my_id_payload, message_t *request) -{ - authenticator_t *authenticator; - auth_payload_t *auth_payload; - status_t status; - - authenticator = authenticator_create(this->ike_sa); - status = authenticator->compute_auth_data(authenticator,&auth_payload,this->ike_sa_init_request_data,this->received_nonce,my_id_payload,TRUE); - authenticator->destroy(authenticator); - - if (status != SUCCESS) - { - this->logger->log(this->logger, AUDIT, "Could not generate AUTH data for IKE_AUTH request. Deleting IKE_SA"); - return DELETE_ME; - } - - this->logger->log(this->logger, CONTROL|LEVEL2, "Add AUTH payload to message"); - request->add_payload(request,(payload_t *) auth_payload); - - return SUCCESS; -} - -/** - * Implementation of private_ike_sa_init_requested_t.build_sa_payload. - */ -static status_t build_sa_payload (private_ike_sa_init_requested_t *this, message_t *request) -{ - linked_list_t *proposal_list; - sa_payload_t *sa_payload; - policy_t *policy; - connection_t *connection; - - /* get proposals form config, add to payload */ - policy = this->ike_sa->get_policy(this->ike_sa); - proposal_list = policy->get_proposals(policy); - /* build child sa */ - connection = this->ike_sa->get_connection(this->ike_sa); - this->child_sa = child_sa_create(connection->get_my_host(connection), - connection->get_other_host(connection)); - if (this->child_sa->alloc(this->child_sa, proposal_list) != SUCCESS) - { - this->logger->log(this->logger, AUDIT, "Could not install CHILD_SA! Deleting IKE_SA"); - return DELETE_ME; - } - - sa_payload = sa_payload_create_from_proposal_list(proposal_list); - - this->logger->log(this->logger, CONTROL|LEVEL2, "Add SA payload to message"); - request->add_payload(request,(payload_t *) sa_payload); - - return SUCCESS; -} - -/** - * Implementation of private_ike_sa_init_requested_t.build_tsi_payload. - */ -static status_t build_tsi_payload (private_ike_sa_init_requested_t *this, message_t *request) -{ - linked_list_t *ts_list; - ts_payload_t *ts_payload; - policy_t *policy; - - policy = this->ike_sa->get_policy(this->ike_sa); - ts_list = policy->get_my_traffic_selectors(policy); - ts_payload = ts_payload_create_from_traffic_selectors(TRUE, ts_list); - - this->logger->log(this->logger, CONTROL|LEVEL2, "Add TSi payload to message"); - request->add_payload(request,(payload_t *) ts_payload); - - return SUCCESS; -} - -/** - * Implementation of private_ike_sa_init_requested_t.build_tsr_payload. - */ -static status_t build_tsr_payload (private_ike_sa_init_requested_t *this, message_t *request) -{ - linked_list_t *ts_list; - ts_payload_t *ts_payload; - policy_t *policy; - - policy = this->ike_sa->get_policy(this->ike_sa); - ts_list = policy->get_other_traffic_selectors(policy); - ts_payload = ts_payload_create_from_traffic_selectors(FALSE, ts_list); - - this->logger->log(this->logger, CONTROL|LEVEL2, "Add TSr payload to message"); - request->add_payload(request,(payload_t *) ts_payload); - - return SUCCESS; -} - -/** - * Implementation of private_ike_sa_init_requested_t.process_notify_payload. - */ -static status_t process_notify_payload(private_ike_sa_init_requested_t *this, notify_payload_t *notify_payload) -{ - notify_message_type_t notify_message_type = notify_payload->get_notify_message_type(notify_payload); - - this->logger->log(this->logger, CONTROL|LEVEL1, "Process notify type %s", - mapping_find(notify_message_type_m, notify_message_type)); - - switch (notify_message_type) - { - case NO_PROPOSAL_CHOSEN: - { - this->logger->log(this->logger, AUDIT, "IKE_SA_INIT response contained a NO_PROPOSAL_CHOSEN notify. Deleting IKE_SA"); - return DELETE_ME; - } - case INVALID_MAJOR_VERSION: - { - this->logger->log(this->logger, AUDIT, "IKE_SA_INIT response contained a INVALID_MAJOR_VERSION notify. Deleting IKE_SA"); - return DELETE_ME; - } - case INVALID_KE_PAYLOAD: - { - initiator_init_t *initiator_init_state; - chunk_t notify_data; - diffie_hellman_group_t dh_group, old_dh_group; - connection_t *connection; - - connection = this->ike_sa->get_connection(this->ike_sa); - old_dh_group = connection->get_dh_group(connection); - notify_data = notify_payload->get_notification_data(notify_payload); - dh_group = ntohs(*((u_int16_t*)notify_data.ptr)); - - /* TODO: - * We are very restrictive here: If the other didn't accept - * our DH group, and we do not accept his offer, continuation - * is cancelled... - */ - - this->logger->log(this->logger, AUDIT, "Peer didn't accept %s, it requested %s!", - mapping_find(diffie_hellman_group_m, old_dh_group), - mapping_find(diffie_hellman_group_m, dh_group)); - /* check if we can accept this dh group */ - if (!connection->check_dh_group(connection, dh_group)) - { - this->logger->log(this->logger, AUDIT, - "Peer does only accept DH group %s, which we do not accept! Aborting", - mapping_find(diffie_hellman_group_m, dh_group)); - return DELETE_ME; - } - - /* Going to change state back to initiator_init_t */ - this->logger->log(this->logger, CONTROL|LEVEL2, "Create next state object"); - initiator_init_state = initiator_init_create(this->ike_sa); - - /* buffer of sent and received messages has to get reseted */ - this->ike_sa->reset_message_buffers(this->ike_sa); - - /* state can now be changed */ - this->ike_sa->set_new_state(this->ike_sa,(state_t *) initiator_init_state); - - /* state has NOW changed :-) */ - this->logger->log(this->logger, CONTROL|LEVEL2, "Destroy old sate object"); - this->logger->log(this->logger, CONTROL|LEVEL2, "Going to retry initialization of connection"); - - this->public.state_interface.destroy(&(this->public.state_interface)); - if (initiator_init_state->retry_initiate_connection (initiator_init_state, dh_group) != SUCCESS) - { - return DELETE_ME; - } - return FAILED; - } - default: - { - /* - * - In case of unknown error: IKE_SA gets destroyed. - * - In case of unknown status: logging - */ - if (notify_message_type < 16383) - { - this->logger->log(this->logger, AUDIT, "IKE_SA_INIT reply contained an unknown notify error (%d). Deleting IKE_SA", - notify_message_type); - return DELETE_ME; - } - else - { - this->logger->log(this->logger, CONTROL, "IKE_SA_INIT reply contained an unknown notify (%d), ignored.", - notify_message_type); - return SUCCESS; - } - } - } -} - -/** - * Implementation of state_t.get_state. - */ -static ike_sa_state_t get_state(private_ike_sa_init_requested_t *this) -{ - return IKE_SA_INIT_REQUESTED; -} - -/** - * Implementation of private_ike_sa_init_requested_t.destroy_after_state_change. - */ -static void destroy_after_state_change (private_ike_sa_init_requested_t *this) -{ - this->diffie_hellman->destroy(this->diffie_hellman); - chunk_free(&(this->ike_sa_init_request_data)); - if (this->proposal) - { - this->proposal->destroy(this->proposal); - } - free(this); -} - -/** - * Implementation state_t.destroy. - */ -static void destroy(private_ike_sa_init_requested_t *this) -{ - this->diffie_hellman->destroy(this->diffie_hellman); - free(this->sent_nonce.ptr); - free(this->received_nonce.ptr); - chunk_free(&(this->ike_sa_init_request_data)); - if (this->child_sa) - { - this->child_sa->destroy(this->child_sa); - } - if (this->proposal) - { - this->proposal->destroy(this->proposal); - } - free(this); -} - -/* - * Described in header. - */ -ike_sa_init_requested_t *ike_sa_init_requested_create(protected_ike_sa_t *ike_sa, diffie_hellman_t *diffie_hellman, chunk_t sent_nonce,chunk_t ike_sa_init_request_data) -{ - private_ike_sa_init_requested_t *this = malloc_thing(private_ike_sa_init_requested_t); - - /* interface functions */ - this->public.state_interface.process_message = (status_t (*) (state_t *,message_t *)) process_message; - this->public.state_interface.get_state = (ike_sa_state_t (*) (state_t *)) get_state; - this->public.state_interface.destroy = (void (*) (state_t *)) destroy; - - /* private functions */ - this->destroy_after_state_change = destroy_after_state_change; - this->process_nonce_payload = process_nonce_payload; - this->process_sa_payload = process_sa_payload; - this->process_ke_payload = process_ke_payload; - this->build_auth_payload = build_auth_payload; - this->build_tsi_payload = build_tsi_payload; - this->build_tsr_payload = build_tsr_payload; - this->build_id_payload = build_id_payload; - this->build_idr_payload = build_idr_payload; - this->build_sa_payload = build_sa_payload; - this->process_notify_payload = process_notify_payload; - - /* private data */ - this->ike_sa = ike_sa; - this->received_nonce = CHUNK_INITIALIZER; - this->logger = logger_manager->get_logger(logger_manager, IKE_SA); - this->diffie_hellman = diffie_hellman; - this->proposal = NULL; - this->sent_nonce = sent_nonce; - this->child_sa = NULL; - this->ike_sa_init_request_data = ike_sa_init_request_data; - - return &(this->public); -} diff --git a/src/charon/charon/sa/states/ike_sa_init_requested.h b/src/charon/charon/sa/states/ike_sa_init_requested.h deleted file mode 100644 index 0a43afad1..000000000 --- a/src/charon/charon/sa/states/ike_sa_init_requested.h +++ /dev/null @@ -1,68 +0,0 @@ -/** - * @file ike_sa_init_requested.h - * - * @brief Interface of ike_sa_init_requestet_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - - -#ifndef IKE_SA_INIT_REQUESTED_H_ -#define IKE_SA_INIT_REQUESTED_H_ - -#include -#include -#include -#include - -typedef struct ike_sa_init_requested_t ike_sa_init_requested_t; - -/** - * @brief This class represents an IKE_SA state when - * requested an IKE_SA_INIT as initiator. - * - * @b Constructors: - * - ike_sa_init_requested_create() - * - * @todo Include valid child sa SPIs in proposal - * - * @ingroup states - */ -struct ike_sa_init_requested_t { - /** - * The state_t interface. - */ - state_t state_interface; -}; - -/** - * Constructor of class ike_sa_init_requested_t. - * - * @param ike_sa assigned ike_sa - * @param diffie_hellman diffie_hellman object use to retrieve shared secret - * @param sent_nonce Sent nonce value - * @param ike_sa_init_request_data the binary representation of the IKE_SA_INIT request message - * @return created ike_sa_init_request_t object - * - * @ingroup states - */ -ike_sa_init_requested_t *ike_sa_init_requested_create(protected_ike_sa_t *ike_sa, - diffie_hellman_t *diffie_hellman, - chunk_t sent_nonce, - chunk_t ike_sa_init_request_data); - -#endif /*IKE_SA_INIT_REQUESTED_H_*/ diff --git a/src/charon/charon/sa/states/ike_sa_init_responded.c b/src/charon/charon/sa/states/ike_sa_init_responded.c deleted file mode 100644 index e40b0cf22..000000000 --- a/src/charon/charon/sa/states/ike_sa_init_responded.c +++ /dev/null @@ -1,695 +0,0 @@ -/** - * @file ike_sa_init_responded.c - * - * @brief State of a IKE_SA after responding to an IKE_SA_INIT request - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 - -#include "ike_sa_init_responded.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -typedef struct private_ike_sa_init_responded_t private_ike_sa_init_responded_t; - -/** - * Private data of a ike_sa_init_responded_t object. - * - */ -struct private_ike_sa_init_responded_t { - /** - * Public interface of ike_sa_init_responded_t. - */ - ike_sa_init_responded_t public; - - /** - * Assigned IKE_SA. - */ - protected_ike_sa_t *ike_sa; - - /** - * Received nonce. - */ - chunk_t received_nonce; - - /** - * Sent nonce. - */ - chunk_t sent_nonce; - - /** - * Binary representation of the IKE_SA_INIT response. - */ - chunk_t ike_sa_init_response_data; - - /** - * Binary representation of the IKE_SA_INIT request. - */ - chunk_t ike_sa_init_request_data; - - /** - * SA config to use. - */ - policy_t *policy; - - /** - * CHILD_SA, if set up - */ - child_sa_t *child_sa; - - /** - * Traffic selectors applicable at our site - */ - linked_list_t *my_ts; - - /** - * Traffic selectors applicable at remote site - */ - linked_list_t *other_ts; - - /** - * Assigned logger. - * - * Is logger of ike_sa! - */ - logger_t *logger; - - /** - * Process received IDi and IDr payload and build IDr payload for IKE_AUTH response. - * - * @param this calling object - * @param request_idi ID payload representing initiator - * @param request_idr ID payload representing responder (May be zero) - * @param response The created IDr payload is added to this message_t object - * @param response_idr The created IDr payload is also written to this location - */ - status_t (*build_idr_payload) (private_ike_sa_init_responded_t *this, - id_payload_t *request_idi, - id_payload_t *request_idr, - message_t *response, - id_payload_t **response_idr); - - /** - * Process received SA payload and build SA payload for IKE_AUTH response. - * - * @param this calling object - * @param request SA payload received in IKE_AUTH request - * @param response The created SA payload is added to this message_t object - */ - status_t (*build_sa_payload) (private_ike_sa_init_responded_t *this, sa_payload_t *request, message_t *response); - - /** - * Process received AUTH payload and build AUTH payload for IKE_AUTH response. - * - * @param this calling object - * @param request AUTH payload received in IKE_AUTH request - * @param other_id_payload other ID payload needed to verify AUTH data - * @param my_id_payload my ID payload needed to compute AUTH data - * @param response The created AUTH payload is added to this message_t object - */ - status_t (*build_auth_payload) (private_ike_sa_init_responded_t *this, auth_payload_t *request,id_payload_t *other_id_payload,id_payload_t *my_id_payload, message_t* response); - - /** - * Process received TS payload and build TS payload for IKE_AUTH response. - * - * @param this calling object - * @param is_initiator type of TS payload. TRUE for TSi, FALSE for TSr - * @param request TS payload received in IKE_AUTH request - * @param response the created TS payload is added to this message_t object - */ - status_t (*build_ts_payload) (private_ike_sa_init_responded_t *this, bool ts_initiator, ts_payload_t *request, message_t *response); - - /** - * Sends a IKE_AUTH reply containing a notify payload. - * - * @param this calling object - * @param notify_payload payload to process - * @return - * - DELETE_ME if IKE_SA should be deleted - * - SUCCSS if processed successfull - */ - status_t (*process_notify_payload) (private_ike_sa_init_responded_t *this, notify_payload_t* notify_payload); - - /** - * Destroy function called internally of this class after state change to - * state IKE_SA_ESTABLISHED succeeded. - * - * This destroy function does not destroy objects which were passed to the new state. - * - * @param this calling object - */ - void (*destroy_after_state_change) (private_ike_sa_init_responded_t *this); -}; - -/** - * Implements state_t.get_state - */ -static status_t process_message(private_ike_sa_init_responded_t *this, message_t *request) -{ - id_payload_t *idi_request = NULL, *idr_request = NULL,*idr_response; - ts_payload_t *tsi_request = NULL, *tsr_request = NULL; - auth_payload_t *auth_request = NULL; - sa_payload_t *sa_request = NULL; - iterator_t *payloads; - message_t *response; - crypter_t *crypter; - signer_t *signer; - status_t status; - host_t *my_host, *other_host; - connection_t *connection; - - if (request->get_exchange_type(request) != IKE_AUTH) - { - this->logger->log(this->logger, ERROR | LEVEL1, "Message of type %s not supported in state ike_sa_init_responded", - mapping_find(exchange_type_m,request->get_exchange_type(request))); - return FAILED; - } - - if (!request->get_request(request)) - { - this->logger->log(this->logger, ERROR | LEVEL1, "IKE_AUTH responses not allowed state ike_sa_init_responded"); - return FAILED; - } - - /* get signer for verification and crypter for decryption */ - signer = this->ike_sa->get_signer_initiator(this->ike_sa); - crypter = this->ike_sa->get_crypter_initiator(this->ike_sa); - - status = request->parse_body(request, crypter, signer); - if (status != SUCCESS) - { - if (status == NOT_SUPPORTED) - { - this->logger->log(this->logger, ERROR | LEVEL1, "IKE_AUTH request contains unsupported payload with critical flag set." - "Deleting IKE_SA"); - this->ike_sa->send_notify(this->ike_sa, IKE_AUTH, UNSUPPORTED_CRITICAL_PAYLOAD, CHUNK_INITIALIZER); - return DELETE_ME; - } - else - { - this->logger->log(this->logger, AUDIT, "IKE_AUTH request decryption faild. Ignoring message"); - } - return status; - } - - /* iterate over incoming payloads. Message is verified, we can be sure there are the required payloads */ - payloads = request->get_payload_iterator(request); - while (payloads->has_next(payloads)) - { - payload_t *payload; - payloads->current(payloads, (void**)&payload); - - switch (payload->get_type(payload)) - { - case ID_INITIATOR: - { - idi_request = (id_payload_t*)payload; - break; - } - case AUTHENTICATION: - { - auth_request = (auth_payload_t*)payload; - break; - } - case ID_RESPONDER: - { - idr_request = (id_payload_t*)payload; - break; - } - case SECURITY_ASSOCIATION: - { - sa_request = (sa_payload_t*)payload; - break; - } - case TRAFFIC_SELECTOR_INITIATOR: - { - tsi_request = (ts_payload_t*)payload; - break; - } - case TRAFFIC_SELECTOR_RESPONDER: - { - tsr_request = (ts_payload_t*)payload; - break; - } - case NOTIFY: - { - notify_payload_t *notify_payload = (notify_payload_t *) payload; - status = this->process_notify_payload(this, notify_payload); - if (status != SUCCESS) - { - payloads->destroy(payloads); - return status; - } - } - case CERTIFICATE: - { - /* TODO handle cert payloads */ - } - case CERTIFICATE_REQUEST: - { - /* TODO handle certrequest payloads */ - } - default: - { - this->logger->log(this->logger, ERROR|LEVEL1, "Ignoring payload %s (%d)", - mapping_find(payload_type_m, payload->get_type(payload)), payload->get_type(payload)); - break; - } - } - } - /* iterator can be destroyed */ - payloads->destroy(payloads); - - /* check if we have all payloads */ - if (!(idi_request && sa_request && auth_request && tsi_request && tsr_request)) - { - this->logger->log(this->logger, AUDIT, "IKE_AUTH reply did not contain all required payloads. Deleting IKE_SA"); - return DELETE_ME; - } - - /* build response */ - this->ike_sa->build_message(this->ike_sa, IKE_AUTH, FALSE, &response); - - /* add payloads to it */ - status = this->build_idr_payload(this, idi_request, idr_request, response,&idr_response); - if (status != SUCCESS) - { - response->destroy(response); - return status; - } - status = this->build_auth_payload(this, auth_request,idi_request, idr_response,response); - if (status != SUCCESS) - { - response->destroy(response); - return status; - } - status = this->build_sa_payload(this, sa_request, response); - if (status != SUCCESS) - { - response->destroy(response); - return status; - } - status = this->build_ts_payload(this, TRUE, tsi_request, response); - if (status != SUCCESS) - { - response->destroy(response); - return status; - } - status = this->build_ts_payload(this, FALSE, tsr_request, response); - if (status != SUCCESS) - { - response->destroy(response); - return status; - } - - status = this->ike_sa->send_response(this->ike_sa, response); - /* message can now be sent (must not be destroyed) */ - if (status != SUCCESS) - { - this->logger->log(this->logger, AUDIT, "Unable to send IKE_AUTH reply. Deleting IKE_SA"); - response->destroy(response); - return DELETE_ME; - } - - /* install child SA policies */ - if (!this->child_sa) - { - this->logger->log(this->logger, CONTROL, "Proposal negotiation failed, no CHILD_SA built"); - } - else if (this->my_ts->get_count(this->my_ts) == 0 || this->other_ts->get_count(this->other_ts) == 0) - { - this->logger->log(this->logger, CONTROL, "Traffic selector negotiation failed, no CHILD_SA built"); - this->child_sa->destroy(this->child_sa); - this->child_sa = NULL; - } - else - { - status = this->child_sa->add_policies(this->child_sa, this->my_ts, this->other_ts); - if (status != SUCCESS) - { - this->logger->log(this->logger, AUDIT, "Could not install CHILD_SA policy! Deleting IKE_SA"); - return DELETE_ME; - } - this->ike_sa->add_child_sa(this->ike_sa, this->child_sa); - } - - /* create new state */ - this->ike_sa->set_new_state(this->ike_sa, (state_t*)ike_sa_established_create(this->ike_sa)); - this->destroy_after_state_change(this); - - connection = this->ike_sa->get_connection(this->ike_sa); - my_host = connection->get_my_host(connection); - other_host = connection->get_other_host(connection); - this->logger->log(this->logger, AUDIT, "IKE_SA established between %s - %s", - my_host->get_address(my_host), other_host->get_address(other_host)); - - return SUCCESS; -} - -/** - * Implementation of private_ike_sa_init_responded_t.build_idr_payload. - */ -static status_t build_idr_payload(private_ike_sa_init_responded_t *this, id_payload_t *request_idi, id_payload_t *request_idr, message_t *response,id_payload_t **response_idr) -{ - identification_t *other_id, *my_id = NULL; - connection_t *connection; - id_payload_t *idr_response; - - connection = this->ike_sa->get_connection(this->ike_sa); - - /* update adresses, as connection may contain wildcards, or wrong IDs */ - other_id = request_idi->get_identification(request_idi); - if (request_idr) - { - my_id = request_idr->get_identification(request_idr); - connection->update_my_id(connection, my_id); - } - else - { - my_id = connection->get_my_id(connection); - } - connection->update_other_id(connection, other_id); - - /* build new sa config */ - this->policy = charon->policies->get_policy(charon->policies, my_id, other_id); - if (this->policy == NULL) - { - this->logger->log(this->logger, AUDIT, "We don't have a policy for IDs %s - %s. Deleting IKE_SA", - my_id->get_string(my_id), other_id->get_string(other_id)); - return DELETE_ME; - } - - /* get my id from policy, which must contain a fully qualified valid id */ - my_id = this->policy->get_my_id(this->policy); - - /* update others traffic selectors with actually used address */ - this->policy->update_other_ts(this->policy, response->get_destination(response)); - - /* set policy in ike_sa for other states */ - this->ike_sa->set_policy(this->ike_sa, this->policy); - - /* build response */ - idr_response = id_payload_create_from_identification(FALSE, my_id); - response->add_payload(response, (payload_t*)idr_response); - *response_idr = idr_response; - - return SUCCESS; -} - -/** - * Implementation of private_ike_sa_init_responded_t.build_sa_payload. - */ -static status_t build_sa_payload(private_ike_sa_init_responded_t *this, sa_payload_t *request, message_t *response) -{ - proposal_t *proposal, *proposal_tmp; - linked_list_t *proposal_list; - sa_payload_t *sa_response; - chunk_t seed; - prf_plus_t *prf_plus; - status_t status; - connection_t *connection; - - /* get proposals from request */ - proposal_list = request->get_proposals(request); - if (proposal_list->get_count(proposal_list) == 0) - { - /* if the other side did not offer any proposals, we do not create child sa's */ - this->logger->log(this->logger, AUDIT, "IKE_AUH request did not contain any proposals. No CHILD_SA created"); - sa_response = sa_payload_create(); - response->add_payload(response, (payload_t*)sa_response); - proposal_list->destroy(proposal_list); - return SUCCESS; - } - - /* now select a proposal */ - this->logger->log(this->logger, CONTROL|LEVEL1, "Selecting proposals:"); - proposal = this->policy->select_proposal(this->policy, proposal_list); - /* list is not needed anymore */ - while (proposal_list->remove_last(proposal_list, (void**)&proposal_tmp) == SUCCESS) - { - proposal_tmp->destroy(proposal_tmp); - } - proposal_list->destroy(proposal_list); - /* do we have a proposal */ - if (proposal == NULL) - { - this->logger->log(this->logger, AUDIT, "IKE_AUTH request did not contain any proposals we accept. Deleting IKE_SA"); - this->ike_sa->send_notify(this->ike_sa, IKE_AUTH, NO_PROPOSAL_CHOSEN, CHUNK_INITIALIZER); - return DELETE_ME; - } - - /* set up child sa */ - seed = chunk_alloc(this->received_nonce.len + this->sent_nonce.len); - memcpy(seed.ptr, this->received_nonce.ptr, this->received_nonce.len); - memcpy(seed.ptr + this->received_nonce.len, this->sent_nonce.ptr, this->sent_nonce.len); - prf_plus = prf_plus_create(this->ike_sa->get_child_prf(this->ike_sa), seed); - chunk_free(&seed); - - connection = this->ike_sa->get_connection(this->ike_sa); - this->child_sa = child_sa_create(connection->get_my_host(connection), - connection->get_other_host(connection)); - - status = this->child_sa->add(this->child_sa, proposal, prf_plus); - prf_plus->destroy(prf_plus); - if (status != SUCCESS) - { - this->logger->log(this->logger, AUDIT, "Could not install CHILD_SA! Deleting IKE_SA"); - return DELETE_ME; - } - - /* create payload with selected propsal */ - sa_response = sa_payload_create_from_proposal(proposal); - response->add_payload(response, (payload_t*)sa_response); - proposal->destroy(proposal); - return SUCCESS; -} - -/** - * Implementation of private_ike_sa_init_responded_t.build_auth_payload. - */ -static status_t build_auth_payload(private_ike_sa_init_responded_t *this, auth_payload_t *auth_request,id_payload_t *other_id_payload,id_payload_t *my_id_payload, message_t* response) -{ - authenticator_t *authenticator; - auth_payload_t *auth_reply; - status_t status; - - authenticator = authenticator_create(this->ike_sa); - status = authenticator->verify_auth_data(authenticator,auth_request, this->ike_sa_init_request_data,this->sent_nonce,other_id_payload,TRUE); - - if (status != SUCCESS) - { - this->logger->log(this->logger, AUDIT, "IKE_AUTH request verification failed. Deleting IKE_SA"); - this->ike_sa->send_notify(this->ike_sa, IKE_AUTH, AUTHENTICATION_FAILED, CHUNK_INITIALIZER); - authenticator->destroy(authenticator); - return DELETE_ME; - } - - status = authenticator->compute_auth_data(authenticator,&auth_reply, this->ike_sa_init_response_data,this->received_nonce,my_id_payload,FALSE); - authenticator->destroy(authenticator); - if (status != SUCCESS) - { - this->logger->log(this->logger, AUDIT, "Unable to build authentication data for IKE_AUTH reply. Deleting IKE_SA"); - return DELETE_ME; - - } - - response->add_payload(response, (payload_t *)auth_reply); - return SUCCESS; -} - -/** - * Implementation of private_ike_sa_init_responded_t.build_ts_payload. - */ -static status_t build_ts_payload(private_ike_sa_init_responded_t *this, bool ts_initiator, ts_payload_t *request, message_t* response) -{ - linked_list_t *ts_received, *ts_selected; - traffic_selector_t *ts; - status_t status = SUCCESS; - ts_payload_t *ts_response; - - /* build a reply payload with selected traffic selectors */ - ts_received = request->get_traffic_selectors(request); - /* select ts depending on payload type */ - if (ts_initiator) - { - ts_selected = this->policy->select_other_traffic_selectors(this->policy, ts_received); - this->other_ts = ts_selected; - } - else - { - ts_selected = this->policy->select_my_traffic_selectors(this->policy, ts_received); - this->my_ts = ts_selected; - } - - ts_response = ts_payload_create_from_traffic_selectors(ts_initiator, ts_selected); - response->add_payload(response, (payload_t*)ts_response); - - /* cleanup */ - while (ts_received->remove_last(ts_received, (void**)&ts) == SUCCESS) - { - ts->destroy(ts); - } - ts_received->destroy(ts_received); - - return status; -} - -static status_t process_notify_payload(private_ike_sa_init_responded_t *this, notify_payload_t *notify_payload) -{ - notify_message_type_t notify_message_type = notify_payload->get_notify_message_type(notify_payload); - - this->logger->log(this->logger, CONTROL|LEVEL1, "Process notify type %s", - mapping_find(notify_message_type_m, notify_message_type)); - - switch (notify_message_type) - { - case SET_WINDOW_SIZE: - /* - * TODO Increase window size. - */ - case INITIAL_CONTACT: - /* - * TODO Delete existing IKE_SA's with other Identity. - */ - default: - { - this->logger->log(this->logger, AUDIT, "IKE_AUTH request contained an unknown notify (%d), ignored.", notify_message_type); - } - } - - return SUCCESS; -} - -/** - * Implementation of state_t.get_state. - */ -static ike_sa_state_t get_state(private_ike_sa_init_responded_t *this) -{ - return IKE_SA_INIT_RESPONDED; -} - -/** - * Implementation of state_t.destroy. - */ -static void destroy(private_ike_sa_init_responded_t *this) -{ - chunk_free(&(this->received_nonce)); - chunk_free(&(this->sent_nonce)); - chunk_free(&(this->ike_sa_init_response_data)); - chunk_free(&(this->ike_sa_init_request_data)); - if (this->my_ts) - { - traffic_selector_t *ts; - while (this->my_ts->remove_last(this->my_ts, (void**)&ts) == SUCCESS) - { - ts->destroy(ts); - } - this->my_ts->destroy(this->my_ts); - } - if (this->other_ts) - { - traffic_selector_t *ts; - while (this->other_ts->remove_last(this->other_ts, (void**)&ts) == SUCCESS) - { - ts->destroy(ts); - } - this->other_ts->destroy(this->other_ts); - } - if (this->child_sa) - { - this->child_sa->destroy(this->child_sa); - } - - free(this); -} -/** - * Implementation of private_ike_sa_init_responded.destroy_after_state_change. - */ -static void destroy_after_state_change(private_ike_sa_init_responded_t *this) -{ - chunk_free(&(this->received_nonce)); - chunk_free(&(this->sent_nonce)); - chunk_free(&(this->ike_sa_init_response_data)); - chunk_free(&(this->ike_sa_init_request_data)); - if (this->my_ts) - { - traffic_selector_t *ts; - while (this->my_ts->remove_last(this->my_ts, (void**)&ts) == SUCCESS) - { - ts->destroy(ts); - } - this->my_ts->destroy(this->my_ts); - } - if (this->other_ts) - { - traffic_selector_t *ts; - while (this->other_ts->remove_last(this->other_ts, (void**)&ts) == SUCCESS) - { - ts->destroy(ts); - } - this->other_ts->destroy(this->other_ts); - } - - free(this); -} - -/* - * Described in header. - */ -ike_sa_init_responded_t *ike_sa_init_responded_create(protected_ike_sa_t *ike_sa, chunk_t received_nonce, chunk_t sent_nonce,chunk_t ike_sa_init_request_data, chunk_t ike_sa_init_response_data) -{ - private_ike_sa_init_responded_t *this = malloc_thing(private_ike_sa_init_responded_t); - - /* interface functions */ - this->public.state_interface.process_message = (status_t (*) (state_t *,message_t *)) process_message; - this->public.state_interface.get_state = (ike_sa_state_t (*) (state_t *)) get_state; - this->public.state_interface.destroy = (void (*) (state_t *)) destroy; - - /* private functions */ - this->build_idr_payload = build_idr_payload; - this->build_sa_payload = build_sa_payload; - this->build_auth_payload = build_auth_payload; - this->build_ts_payload = build_ts_payload; - this->process_notify_payload = process_notify_payload; - this->destroy_after_state_change = destroy_after_state_change; - - /* private data */ - this->ike_sa = ike_sa; - this->received_nonce = received_nonce; - this->sent_nonce = sent_nonce; - this->ike_sa_init_response_data = ike_sa_init_response_data; - this->ike_sa_init_request_data = ike_sa_init_request_data; - this->my_ts = NULL; - this->other_ts = NULL; - this->child_sa = NULL; - this->logger = logger_manager->get_logger(logger_manager, IKE_SA); - - return &(this->public); -} diff --git a/src/charon/charon/sa/states/ike_sa_init_responded.h b/src/charon/charon/sa/states/ike_sa_init_responded.h deleted file mode 100644 index 43aecf26f..000000000 --- a/src/charon/charon/sa/states/ike_sa_init_responded.h +++ /dev/null @@ -1,73 +0,0 @@ -/** - * @file ike_sa_init_responded.h - * - * @brief Interface of ike_sa_init_responded_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef IKE_SA_INIT_RESPONDED_H_ -#define IKE_SA_INIT_RESPONDED_H_ - -#include -#include - -typedef struct ike_sa_init_responded_t ike_sa_init_responded_t; - -/** - * @brief This class represents an IKE_SA state when - * responded to an IKE_SA_INIT request. - * - * The state accpets IKE_AUTH requests. It proves the authenticity - * and sets up the first child sa. Then it sends back an IKE_AUTH - * reply and changes to the IKE_SA_ESTABLISHED state. - * - * @b Constructors: - * - ike_sa_init_response_data() - * - * @todo Implement handling of SET_WINDOW_SIZE notify - * - * @todo Implement handling of INITIAL_CONTACT notify - * - * @ingroup states - */ -struct ike_sa_init_responded_t { - /** - * The state_t interface. - */ - state_t state_interface; - -}; - -/** - * @brief Constructor of class ike_sa_init_responded_t - * - * @param ike_sa assigned IKE_SA - * @param received_nonce received nonce data in IKE_SA_INIT request - * @param sent_nonce sent nonce data in IKE_SA_INIT response - * @param ike_sa_init_request_data binary representation of received IKE_SA_INIT request - * @param ike_sa_init_response_data binary representation of sent IKE_SA_INIT response - * - * @ingroup states - */ -ike_sa_init_responded_t *ike_sa_init_responded_create(protected_ike_sa_t *ike_sa, - chunk_t received_nonce, - chunk_t sent_nonce, - chunk_t ike_sa_init_request_data, - chunk_t ike_sa_init_response_data); - -#endif /*IKE_SA_INIT_RESPONDED_H_*/ diff --git a/src/charon/charon/sa/states/initiator_init.c b/src/charon/charon/sa/states/initiator_init.c deleted file mode 100644 index 35d15235d..000000000 --- a/src/charon/charon/sa/states/initiator_init.c +++ /dev/null @@ -1,360 +0,0 @@ -/** - * @file initiator_init.c - * - * @brief Implementation of initiator_init_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 "initiator_init.h" - - -#include -#include -#include -#include -#include -#include -#include -#include - - -typedef struct private_initiator_init_t private_initiator_init_t; - -/** - * Private data of a initiator_init_t object.. - * - */ -struct private_initiator_init_t { - /** - * Methods of the state_t interface. - */ - initiator_init_t public; - - /** - * Assigned IKE_SA. - */ - protected_ike_sa_t *ike_sa; - - /** - * Diffie hellman object used to generate public DH value. - * This objet is passed to the next state of type IKE_SA_INIT_REQUESTED. - */ - diffie_hellman_t *diffie_hellman; - - /** - * Sent nonce. - * This nonce is passed to the next state of type IKE_SA_INIT_REQUESTED. - */ - chunk_t sent_nonce; - - /** - * Assigned logger. - * - * Is logger of ike_sa! - */ - logger_t *logger; - - /** - * Builds the SA payload for this state. - * - * @param this calling object - * @param request message_t object to add the SA payload - */ - void (*build_sa_payload) (private_initiator_init_t *this, message_t *request); - - /** - * Builds the KE payload for this state. - * - * @param this calling object - * @param request message_t object to add the KE payload - */ - void (*build_ke_payload) (private_initiator_init_t *this, message_t *request); - - /** - * Builds the NONCE payload for this state. - * - * @param this calling object - * @param request message_t object to add the NONCE payload - */ - status_t (*build_nonce_payload) (private_initiator_init_t *this,message_t *request); - - /** - * Destroy function called internally of this class after state change to state - * IKE_SA_INIT_REQUESTED succeeded. - * - * This destroy function does not destroy objects which were passed to the new state. - * - * @param this calling object - */ - void (*destroy_after_state_change) (private_initiator_init_t *this); -}; - -/** - * Implementation of initiator_init_t.initiate_connection. - */ -static status_t initiate_connection (private_initiator_init_t *this, connection_t *connection) -{ - policy_t *policy; - diffie_hellman_group_t dh_group; - host_t *my_host, *other_host; - identification_t *my_id, *other_id; - - my_host = connection->get_my_host(connection); - other_host = connection->get_other_host(connection); - my_id = connection->get_my_id(connection); - other_id = connection->get_other_id(connection); - - this->logger->log(this->logger, CONTROL, "Initiating connection between %s (%s) - %s (%s)", - my_id->get_string(my_id), my_host->get_address(my_host), - other_id->get_string(other_id), other_host->get_address(other_host)); - - this->ike_sa->set_connection(this->ike_sa, connection); - - /* get policy */ - policy = charon->policies->get_policy(charon->policies, my_id, other_id); - if (policy == NULL) - { - this->logger->log(this->logger, ERROR | LEVEL1, "Could not get a policy for '%s - %s', aborting", - my_id->get_string(my_id), other_id->get_string(other_id)); - return DELETE_ME; - } - this->ike_sa->set_policy(this->ike_sa,policy); - - /* we must guess now a DH group. For that we choose our most preferred group */ - dh_group = connection->get_dh_group(connection); - - /* next step is done in retry_initiate_connection */ - return this->public.retry_initiate_connection(&this->public, dh_group); -} - -/** - * Implementation of initiator_init_t.retry_initiate_connection. - */ -status_t retry_initiate_connection (private_initiator_init_t *this, diffie_hellman_group_t dh_group) -{ - ike_sa_init_requested_t *next_state; - chunk_t ike_sa_init_request_data; - connection_t *connection; - ike_sa_id_t *ike_sa_id; - message_t *message; - status_t status; - - if (dh_group == MODP_UNDEFINED) - { - this->logger->log(this->logger, AUDIT, "No DH group acceptable for initialization, Aborting"); - return DELETE_ME; - } - - connection = this->ike_sa->get_connection(this->ike_sa); - this->diffie_hellman = diffie_hellman_create(dh_group); - ike_sa_id = this->ike_sa->public.get_id(&(this->ike_sa->public)); - ike_sa_id->set_responder_spi(ike_sa_id,0); - - /* going to build message */ - this->logger->log(this->logger, CONTROL|LEVEL2, "Going to build message"); - this->ike_sa->build_message(this->ike_sa, IKE_SA_INIT, TRUE, &message); - - /* build SA payload */ - this->build_sa_payload(this, message); - - /* build KE payload */ - this->build_ke_payload(this, message); - - /* build Nonce payload */ - status = this->build_nonce_payload(this, message); - if (status != SUCCESS) - { - this->logger->log(this->logger, ERROR, "Building nonce payload failed. Aborting"); - message->destroy(message); - return DELETE_ME; - } - - /* message can now be sent (must not be destroyed) */ - status = this->ike_sa->send_request(this->ike_sa, message); - if (status != SUCCESS) - { - this->logger->log(this->logger, AUDIT, "Unable to initiate connection, could not send message. Aborting"); - message->destroy(message); - return DELETE_ME; - } - - message = this->ike_sa->get_last_requested_message(this->ike_sa); - - ike_sa_init_request_data = message->get_packet_data(message); - - /* state can now be changed */ - this->logger->log(this->logger, CONTROL|LEVEL2, "Create next state object"); - next_state = ike_sa_init_requested_create(this->ike_sa, this->diffie_hellman, this->sent_nonce,ike_sa_init_request_data); - this->ike_sa->set_new_state(this->ike_sa,(state_t *) next_state); - - this->logger->log(this->logger, CONTROL|LEVEL2, "Destroy old sate object"); - this->destroy_after_state_change(this); - return SUCCESS; -} - -/** - * Implementation of private_initiator_init_t.build_sa_payload. - */ -static void build_sa_payload(private_initiator_init_t *this, message_t *request) -{ - sa_payload_t* sa_payload; - linked_list_t *proposal_list; - connection_t *connection; - - this->logger->log(this->logger, CONTROL|LEVEL1, "Building SA payload"); - - connection = this->ike_sa->get_connection(this->ike_sa); - - proposal_list = connection->get_proposals(connection); - - sa_payload = sa_payload_create_from_proposal_list(proposal_list); - - this->logger->log(this->logger, CONTROL|LEVEL2, "Add SA payload to message"); - request->add_payload(request, (payload_t *) sa_payload); -} - -/** - * Implementation of private_initiator_init_t.build_ke_payload. - */ -static void build_ke_payload(private_initiator_init_t *this, message_t *request) -{ - ke_payload_t *ke_payload; - chunk_t key_data; - diffie_hellman_group_t dh_group; - - this->logger->log(this->logger, CONTROL|LEVEL1, "Building KE payload"); - - this->diffie_hellman->get_my_public_value(this->diffie_hellman,&key_data); - dh_group = this->diffie_hellman->get_dh_group(this->diffie_hellman); - - ke_payload = ke_payload_create(); - ke_payload->set_dh_group_number(ke_payload, dh_group); - ke_payload->set_key_exchange_data(ke_payload, key_data); - - chunk_free(&key_data); - - this->logger->log(this->logger, CONTROL|LEVEL2, "Add KE payload to message"); - request->add_payload(request, (payload_t *) ke_payload); -} - -/** - * Implementation of private_initiator_init_t.build_nonce_payload. - */ -static status_t build_nonce_payload(private_initiator_init_t *this, message_t *request) -{ - nonce_payload_t *nonce_payload; - randomizer_t *randomizer; - status_t status; - - this->logger->log(this->logger, CONTROL|LEVEL1, "Building NONCE payload"); - - this->logger->log(this->logger, CONTROL|LEVEL2, "Get pseudo random bytes for NONCE"); - randomizer = this->ike_sa->get_randomizer(this->ike_sa); - - status = randomizer->allocate_pseudo_random_bytes(randomizer, NONCE_SIZE, &(this->sent_nonce)); - if (status != SUCCESS) - { - return status; - } - - this->logger->log(this->logger, RAW|LEVEL2, "Initiator NONCE",&(this->sent_nonce)); - - nonce_payload = nonce_payload_create(); - - nonce_payload->set_nonce(nonce_payload, this->sent_nonce); - - this->logger->log(this->logger, CONTROL|LEVEL2, "Add NONCE payload to message"); - request->add_payload(request, (payload_t *) nonce_payload); - return SUCCESS; -} - -/** - * Implementation of state_t.process_message. - */ -static status_t process_message(private_initiator_init_t *this, message_t *message) -{ - this->logger->log(this->logger, ERROR, "In state INITIATOR_INIT, no message is processed"); - return FAILED; -} - -/** - * Implementation of state_t.get_state. - */ -static ike_sa_state_t get_state(private_initiator_init_t *this) -{ - return INITIATOR_INIT; -} - -/** - * Implementation of state_t.destroy. - */ -static void destroy(private_initiator_init_t *this) -{ - this->logger->log(this->logger, CONTROL | LEVEL3, "Going to destroy initiator_init_t state object"); - - /* destroy diffie hellman object */ - if (this->diffie_hellman != NULL) - { - this->diffie_hellman->destroy(this->diffie_hellman); - } - if (this->sent_nonce.ptr != NULL) - { - free(this->sent_nonce.ptr); - } - free(this); -} - -/** - * Implementation of private_initiator_init_t.destroy_after_state_change - */ -static void destroy_after_state_change (private_initiator_init_t *this) -{ - this->logger->log(this->logger, CONTROL | LEVEL3, "Going to destroy initiator_init_t state object"); - free(this); -} - -/* - * Described in header. - */ -initiator_init_t *initiator_init_create(protected_ike_sa_t *ike_sa) -{ - private_initiator_init_t *this = malloc_thing(private_initiator_init_t); - - /* interface functions */ - this->public.state_interface.process_message = (status_t (*) (state_t *,message_t *)) process_message; - this->public.state_interface.get_state = (ike_sa_state_t (*) (state_t *)) get_state; - this->public.state_interface.destroy = (void (*) (state_t *)) destroy; - - /* public functions */ - this->public.initiate_connection = (status_t (*)(initiator_init_t *, connection_t*)) initiate_connection; - this->public.retry_initiate_connection = (status_t (*)(initiator_init_t *, int )) retry_initiate_connection; - - /* private functions */ - this->destroy_after_state_change = destroy_after_state_change; - this->build_nonce_payload = build_nonce_payload; - this->build_sa_payload = build_sa_payload; - this->build_ke_payload = build_ke_payload; - - /* private data */ - this->ike_sa = ike_sa; - this->logger = logger_manager->get_logger(logger_manager, IKE_SA); - this->sent_nonce = CHUNK_INITIALIZER; - this->diffie_hellman = NULL; - - return &(this->public); -} diff --git a/src/charon/charon/sa/states/initiator_init.h b/src/charon/charon/sa/states/initiator_init.h deleted file mode 100644 index 6b4940a73..000000000 --- a/src/charon/charon/sa/states/initiator_init.h +++ /dev/null @@ -1,84 +0,0 @@ -/** - * @file initiator_init.h - * - * @brief Interface of initiator_init_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - - -#ifndef INITIATOR_INIT_H_ -#define INITIATOR_INIT_H_ - -#include -#include - - -typedef struct initiator_init_t initiator_init_t; - -/** - * @brief This class represents an IKE_SA state when - * initializing a connection as initiator. - * - * @b Constructors: - * - initiator_init_create() - * - * @ingroup states - */ -struct initiator_init_t { - /** - * The state_t interface. - */ - state_t state_interface; - - /** - * Initiate a new connection with given connection_t object. - * - * @param this calling object - * @param connection connection to initiate - * @return - * - SUCCESS - * - DELETE_ME if something failed - */ - status_t (*initiate_connection) (initiator_init_t *this, connection_t *connection); - - /** - * Retry to initiate a new connection with a specific dh_group_priority. - * - * The dh_group_priority is starting at 1. - * - * @param this calling object - * @param dh_group_priority dh group priority to try with - * @return - * - SUCCESS - * - DELETE_ME if something failed (see log for error) - */ - status_t (*retry_initiate_connection) (initiator_init_t *this, int dh_group_priority); -}; - -/** - * @brief Constructor of class initiator_init_t. - * - * @param ike_sa assigned IKE_SA - * @return created initiator_init_t object - * - * @ingroup states - */ -initiator_init_t *initiator_init_create(protected_ike_sa_t *ike_sa); - - -#endif /*INITIATOR_INIT_H_*/ diff --git a/src/charon/charon/sa/states/responder_init.c b/src/charon/charon/sa/states/responder_init.c deleted file mode 100644 index 10acf645c..000000000 --- a/src/charon/charon/sa/states/responder_init.c +++ /dev/null @@ -1,568 +0,0 @@ -/** - * @file responder_init.c - * - * @brief Implementation of responder_init_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 "responder_init.h" - -#include -#include -#include -#include -#include -#include -#include -#include - - -typedef struct private_responder_init_t private_responder_init_t; - -/** - * Private data of a responder_init_t object. - * - */ -struct private_responder_init_t { - /** - * Methods of the state_t interface. - */ - responder_init_t public; - - /** - * Assigned IKE_SA. - */ - protected_ike_sa_t *ike_sa; - - /** - * Diffie Hellman object used to compute shared secret. - */ - diffie_hellman_t *diffie_hellman; - - /** - * Diffie Hellman group number from selected IKE proposal. - */ - u_int16_t dh_group_number; - - /** - * Priority used to get matching dh_group number. - */ - u_int16_t dh_group_priority; - - /** - * Sent nonce value. - * - * This value is passed to the next state of type IKE_SA_INIT_RESPONDED. - */ - chunk_t sent_nonce; - - /** - * Received nonce value - * - * This value is passed to the next state of type IKE_SA_INIT_RESPONDED. - */ - chunk_t received_nonce; - - /** - * Selected proposal - */ - proposal_t *proposal; - - /** - * Logger used to log data . - * - * Is logger of ike_sa! - */ - logger_t *logger; - - /** - * Handles received SA payload and builds the SA payload for the response. - * - * @param this calling object - * @param sa_request The received SA payload - * @param response the SA payload is added to this response message_t object. - * @return - * - DELETE_ME - * - SUCCESS - */ - status_t (*build_sa_payload) (private_responder_init_t *this,sa_payload_t *sa_request, message_t *response); - - /** - * Handles received KE payload and builds the KE payload for the response. - * - * @param this calling object - * @param ke_request The received KE payload - * @param response the KE payload is added to this response message_t object. - * - DELETE_ME - * - SUCCESS - */ - status_t (*build_ke_payload) (private_responder_init_t *this,ke_payload_t *ke_request, message_t *response); - - /** - * Handles received NONCE payload and builds the NONCE payload for the response. - * - * @param this calling object - * @param nonce_request The received NONCE payload - * @param response the NONCE payload is added to this response message_t object. - * - DELETE_ME - * - SUCCESS - */ - status_t (*build_nonce_payload) (private_responder_init_t *this,nonce_payload_t *nonce_request, message_t *response); - - /** - * Sends a IKE_SA_INIT reply containing a notify payload. - * - * @param this calling object - * @param notify_payload notify_payload to process - */ - status_t (*process_notify_payload) (private_responder_init_t *this, notify_payload_t *notify_payload); - - /** - * Destroy function called internally of this class after change - * to state IKE_SA_INIT_RESPONDED succeeded. - * - * This destroy function does not destroy objects which were passed to the new state. - * - * @param this calling object - */ - void (*destroy_after_state_change) (private_responder_init_t *this); - -}; - -/** - * Implementation of state_t.process_message. - */ -static status_t process_message(private_responder_init_t *this, message_t *message) -{ - ike_sa_init_responded_t *next_state; - chunk_t ike_sa_init_response_data; - chunk_t ike_sa_init_request_data; - sa_payload_t *sa_request = NULL; - ke_payload_t *ke_request = NULL; - nonce_payload_t *nonce_request = NULL; - host_t *source, *destination; - connection_t *connection; - iterator_t *payloads; - message_t *response; - status_t status; - - if (message->get_exchange_type(message) != IKE_SA_INIT) - { - this->logger->log(this->logger, ERROR | LEVEL1, "Message of type %s not supported in state responder_init",mapping_find(exchange_type_m,message->get_exchange_type(message))); - return DELETE_ME; - } - if (!message->get_request(message)) - { - this->logger->log(this->logger, ERROR | LEVEL1, "IKE_SA_INIT responses not allowed state ike_sa_init_responded"); - return DELETE_ME; - } - - /* this is the first message to process, so get host infos */ - source = message->get_source(message); - destination = message->get_destination(message); - - connection = charon->connections->get_connection_by_hosts(charon->connections, destination, source); - if (connection == NULL) - { - /* no configuration matches given hosts */ - this->logger->log(this->logger, AUDIT, "IKE_SA_INIT request does not match any available connection. Deleting IKE_SA"); - /* TODO: inform requestor */ - return DELETE_ME; - } - this->ike_sa->set_connection(this->ike_sa,connection); - - /* parse incoming message */ - status = message->parse_body(message, NULL, NULL); - if (status != SUCCESS) - { - if (status == NOT_SUPPORTED) - { - this->logger->log(this->logger, AUDIT, "IKE_SA_INIT request contains unsupported payload with critical flag set. " - "Deleting IKE_SA"); - this->ike_sa->send_notify(this->ike_sa, IKE_SA_INIT, UNSUPPORTED_CRITICAL_PAYLOAD, CHUNK_INITIALIZER); - } - else - { - this->logger->log(this->logger, AUDIT, "Unable to parse IKE_SA_INIT request. Deleting IKE_SA"); - } - return DELETE_ME; - } - - payloads = message->get_payload_iterator(message); - while (payloads->has_next(payloads)) - { - payload_t *payload; - - payloads->current(payloads, (void**)&payload); - - switch (payload->get_type(payload)) - { - case SECURITY_ASSOCIATION: - { - sa_request = (sa_payload_t*)payload; - break; - } - case KEY_EXCHANGE: - { - ke_request = (ke_payload_t*)payload; - break; - } - case NONCE: - { - nonce_request = (nonce_payload_t*)payload; - break; - } - case NOTIFY: - { - notify_payload_t *notify_payload = (notify_payload_t *) payload; - status = this->process_notify_payload(this, notify_payload); - if (status != SUCCESS) - { - payloads->destroy(payloads); - return status; - } - } - default: - { - this->logger->log(this->logger, ERROR|LEVEL1, "Ignoring payload %s (%d)", - mapping_find(payload_type_m, payload->get_type(payload)), payload->get_type(payload)); - break; - } - } - } - payloads->destroy(payloads); - - /* check if we have all payloads */ - if (!(sa_request && ke_request && nonce_request)) - { - this->logger->log(this->logger, AUDIT, "IKE_SA_INIT request did not contain all required payloads. Deleting IKE_SA"); - return DELETE_ME; - } - - this->ike_sa->build_message(this->ike_sa, IKE_SA_INIT, FALSE, &response); - - status = this->build_sa_payload(this, sa_request, response); - if (status != SUCCESS) - { - response->destroy(response); - return status; - } - - status = this->build_ke_payload(this, ke_request, response); - if (status != SUCCESS) - { - response->destroy(response); - return status; - } - - status = this->build_nonce_payload(this, nonce_request, response); - if (status != SUCCESS) - { - response->destroy(response); - return status; - } - - /* derive all the keys used in the IKE_SA */ - status = this->ike_sa->build_transforms(this->ike_sa, this->proposal, this->diffie_hellman, this->received_nonce, this->sent_nonce); - if (status != SUCCESS) - { - this->logger->log(this->logger, AUDIT, "Transform objects could not be created from selected proposal. Deleting IKE_SA"); - return DELETE_ME; - } - - /* message can now be sent (must not be destroyed) */ - status = this->ike_sa->send_response(this->ike_sa, response); - if (status != SUCCESS) - { - this->logger->log(this->logger, AUDIT, "Unable to send IKE_SA_INIT response. Deleting IKE_SA"); - response->destroy(response); - return DELETE_ME; - } - - /* state can now be changed */ - this->logger->log(this->logger, CONTROL|LEVEL2, "Create next state object of type IKE_SA_INIT_RESPONDED"); - - response = this->ike_sa->get_last_responded_message(this->ike_sa); - ike_sa_init_response_data = response->get_packet_data(response); - ike_sa_init_request_data = message->get_packet_data(message); - - next_state = ike_sa_init_responded_create(this->ike_sa, this->received_nonce, this->sent_nonce,ike_sa_init_request_data, - ike_sa_init_response_data); - - /* state can now be changed */ - this->ike_sa->set_new_state(this->ike_sa, (state_t *) next_state); - this->destroy_after_state_change(this); - - return SUCCESS; -} - -/** - * Implementation of private_initiator_init_t.build_sa_payload. - */ -static status_t build_sa_payload(private_responder_init_t *this,sa_payload_t *sa_request, message_t *response) -{ - proposal_t *proposal; - linked_list_t *proposal_list; - connection_t *connection; - sa_payload_t* sa_payload; - algorithm_t *algo; - - connection = this->ike_sa->get_connection(this->ike_sa); - - this->logger->log(this->logger, CONTROL | LEVEL2, "Process received SA payload"); - - /* get the list of suggested proposals */ - proposal_list = sa_request->get_proposals (sa_request); - - /* select proposal */ - this->proposal = connection->select_proposal(connection, proposal_list); - while(proposal_list->remove_last(proposal_list, (void**)&proposal) == SUCCESS) - { - proposal->destroy(proposal); - } - proposal_list->destroy(proposal_list); - if (this->proposal == NULL) - { - this->logger->log(this->logger, AUDIT, "IKE_SA_INIT request did not contain any acceptable proposals. Deleting IKE_SA"); - this->ike_sa->send_notify(this->ike_sa, IKE_SA_INIT, NO_PROPOSAL_CHOSEN, CHUNK_INITIALIZER); - return DELETE_ME; - } - /* get selected DH group to force policy, this is very restrictive!? */ - this->proposal->get_algorithm(this->proposal, PROTO_IKE, DIFFIE_HELLMAN_GROUP, &algo); - this->dh_group_number = algo->algorithm; - - this->logger->log(this->logger, CONTROL | LEVEL2, "SA Payload processed"); - - this->logger->log(this->logger, CONTROL|LEVEL2, "Building SA payload"); - sa_payload = sa_payload_create_from_proposal(this->proposal); - this->logger->log(this->logger, CONTROL|LEVEL2, "add SA payload to message"); - response->add_payload(response,(payload_t *) sa_payload); - - return SUCCESS; -} - -/** - * Implementation of private_initiator_init_t.build_ke_payload. - */ -static status_t build_ke_payload(private_responder_init_t *this,ke_payload_t *ke_request, message_t *response) -{ - diffie_hellman_group_t group; - ke_payload_t *ke_payload; - diffie_hellman_t *dh; - chunk_t key_data; - - this->logger->log(this->logger, CONTROL | LEVEL2, "Process received KE payload"); - group = ke_request->get_dh_group_number(ke_request); - - if (group == MODP_UNDEFINED) - { - this->logger->log(this->logger, AUDIT, "No diffie hellman group to select. Deleting IKE_SA"); - return DELETE_ME; - } - - if (this->dh_group_number != group) - { - u_int16_t accepted_group; - chunk_t accepted_group_chunk; - /* group not same as selected one - * Maybe key exchange payload is before SA payload */ - this->logger->log(this->logger, AUDIT, "IKE_SA_INIT request did not contain a acceptable diffie hellman group. Deleting IKE_SA"); - - accepted_group = htons(this->dh_group_number); - accepted_group_chunk.ptr = (u_int8_t*) &(accepted_group); - accepted_group_chunk.len = 2; - this->ike_sa->send_notify(this->ike_sa,IKE_SA_INIT,INVALID_KE_PAYLOAD,accepted_group_chunk); - return DELETE_ME; - } - - /* create diffie hellman object to handle DH exchange */ - dh = diffie_hellman_create(group); - if (dh == NULL) - { - this->logger->log(this->logger, AUDIT, "Could not generate DH object with group %d. Deleting IKE_SA", - mapping_find(diffie_hellman_group_m,group) ); - return DELETE_ME; - } - this->logger->log(this->logger, CONTROL | LEVEL2, "Set other DH public value"); - - dh->set_other_public_value(dh, ke_request->get_key_exchange_data(ke_request)); - - this->diffie_hellman = dh; - - this->logger->log(this->logger, CONTROL | LEVEL2, "KE Payload processed."); - - this->logger->log(this->logger, CONTROL|LEVEL2, "Building KE payload"); - this->diffie_hellman->get_my_public_value(this->diffie_hellman,&key_data); - - ke_payload = ke_payload_create(); - ke_payload->set_key_exchange_data(ke_payload,key_data); - ke_payload->set_dh_group_number(ke_payload, this->dh_group_number); - chunk_free(&key_data); - - this->logger->log(this->logger, CONTROL|LEVEL2, "Add KE payload to message"); - response->add_payload(response,(payload_t *) ke_payload); - - return SUCCESS; -} - -/** - * Implementation of private_responder_init_t.build_nonce_payload. - */ -static status_t build_nonce_payload(private_responder_init_t *this,nonce_payload_t *nonce_request, message_t *response) -{ - nonce_payload_t *nonce_payload; - randomizer_t *randomizer; - status_t status; - - this->logger->log(this->logger, CONTROL | LEVEL2, "Process received NONCE payload"); - free(this->received_nonce.ptr); - this->received_nonce = CHUNK_INITIALIZER; - - this->logger->log(this->logger, CONTROL | LEVEL2, "Get NONCE value and store it"); - this->received_nonce = nonce_request->get_nonce(nonce_request); - - this->logger->log(this->logger, CONTROL | LEVEL2, "Create new NONCE value."); - - randomizer = this->ike_sa->get_randomizer(this->ike_sa); - status = randomizer->allocate_pseudo_random_bytes(randomizer, NONCE_SIZE, &(this->sent_nonce)); - if (status != SUCCESS) - { - return status; - } - - this->logger->log(this->logger, CONTROL|LEVEL2, "Building NONCE payload"); - nonce_payload = nonce_payload_create(); - nonce_payload->set_nonce(nonce_payload, this->sent_nonce); - - this->logger->log(this->logger, CONTROL|LEVEL2, "Add NONCE payload to message"); - response->add_payload(response,(payload_t *) nonce_payload); - - return SUCCESS; -} - -/** - * Implementation of private_responder_init_t.process_notify_payload. - */ -static status_t process_notify_payload(private_responder_init_t *this, notify_payload_t *notify_payload) -{ - notify_message_type_t notify_message_type = notify_payload->get_notify_message_type(notify_payload); - - this->logger->log(this->logger, CONTROL|LEVEL1, "Process notify type %s", - mapping_find(notify_message_type_m, notify_message_type)); - - if (notify_payload->get_protocol_id(notify_payload) != PROTO_IKE) - { - this->logger->log(this->logger, ERROR | LEVEL1, "Notify reply not for IKE protocol."); - return FAILED; - } - switch (notify_message_type) - { - default: - { - this->logger->log(this->logger, CONTROL, "IKE_SA_INIT request contained a notify (%d), ignored.", - notify_message_type); - return SUCCESS; - } - } -} - -/** - * Implementation of state_t.get_state. - */ -static ike_sa_state_t get_state(private_responder_init_t *this) -{ - return RESPONDER_INIT; -} - -/** - * Implementation of state_t.destroy. - */ -static void destroy(private_responder_init_t *this) -{ - this->logger->log(this->logger, CONTROL | LEVEL1, "Going to destroy responder init state object"); - - this->logger->log(this->logger, CONTROL | LEVEL2, "Destroy sent nonce"); - chunk_free(&(this->sent_nonce)); - this->logger->log(this->logger, CONTROL | LEVEL2, "Destroy received nonce"); - chunk_free(&(this->received_nonce)); - - if (this->diffie_hellman != NULL) - { - this->logger->log(this->logger, CONTROL | LEVEL2, "Destroy diffie_hellman_t hellman object"); - this->diffie_hellman->destroy(this->diffie_hellman); - } - if (this->proposal) - { - this->proposal->destroy(this->proposal); - } - this->logger->log(this->logger, CONTROL | LEVEL2, "Destroy object"); - free(this); -} - -/** - * Implementation of private_responder_init_t.destroy_after_state_change - */ -static void destroy_after_state_change (private_responder_init_t *this) -{ - this->logger->log(this->logger, CONTROL | LEVEL1, "Going to destroy responder_init_t state object"); - - /* destroy diffie hellman object */ - if (this->diffie_hellman != NULL) - { - this->logger->log(this->logger, CONTROL | LEVEL2, "Destroy diffie_hellman_t object"); - this->diffie_hellman->destroy(this->diffie_hellman); - } - if (this->proposal) - { - this->proposal->destroy(this->proposal); - } - - this->logger->log(this->logger, CONTROL | LEVEL2, "Destroy object"); - free(this); -} - -/* - * Described in header. - */ -responder_init_t *responder_init_create(protected_ike_sa_t *ike_sa) -{ - private_responder_init_t *this = malloc_thing(private_responder_init_t); - - /* interface functions */ - this->public.state_interface.process_message = (status_t (*) (state_t *,message_t *)) process_message; - this->public.state_interface.get_state = (ike_sa_state_t (*) (state_t *)) get_state; - this->public.state_interface.destroy = (void (*) (state_t *)) destroy; - - /* private functions */ - this->build_sa_payload = build_sa_payload; - this->build_ke_payload = build_ke_payload; - this->build_nonce_payload = build_nonce_payload; - this->destroy_after_state_change = destroy_after_state_change; - this->process_notify_payload = process_notify_payload; - - /* private data */ - this->ike_sa = ike_sa; - this->logger = logger_manager->get_logger(logger_manager, IKE_SA); - this->sent_nonce = CHUNK_INITIALIZER; - this->received_nonce = CHUNK_INITIALIZER; - this->dh_group_number = MODP_UNDEFINED; - this->diffie_hellman = NULL; - this->proposal = NULL; - - return &(this->public); -} diff --git a/src/charon/charon/sa/states/responder_init.h b/src/charon/charon/sa/states/responder_init.h deleted file mode 100644 index c8ba73ea3..000000000 --- a/src/charon/charon/sa/states/responder_init.h +++ /dev/null @@ -1,68 +0,0 @@ -/** - * @file responder_init.h - * - * @brief Interface of responder_init_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef RESPONDER_INIT_H_ -#define RESPONDER_INIT_H_ - -#include -#include - - -typedef struct responder_init_t responder_init_t; - -/** - * @brief This class represents an IKE_SA state when - * initializing a connection as responder. - * - * @b Constructors: - * - responder_init_create() - * - * @ingroup states - */ -struct responder_init_t { - /** - * The state_t interface. - */ - state_t state_interface; -}; - -/** - * Constructor of class responder_init_t. - * - * The following functions of the assigned protected_ike_sa_t object are being called with - * valid values after successfully processing a received message and before changing - * to next state IKE_SA_INIT_RESPONDED: - * - protected_ike_sa_t.set_connection() - * - protected_ike_sa_t.set_my_host() - * - protected_ike_sa_t.set_other_host() - * - protected_ike_sa_t.compute_secrets() - * - protected_ike_sa_t.create_transforms_from_proposal() - * - * @param ike_sa assigned IKE_SA - * - * @return responder_init_t object - * - * @ingroup states - */ -responder_init_t *responder_init_create(protected_ike_sa_t *ike_sa); - -#endif /*RESPONDER_INIT_H_*/ diff --git a/src/charon/charon/sa/states/state.c b/src/charon/charon/sa/states/state.c deleted file mode 100644 index 595f5abbb..000000000 --- a/src/charon/charon/sa/states/state.c +++ /dev/null @@ -1,37 +0,0 @@ -/** - * @file state.c - * - * @brief Interface state_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 "state.h" - - -/** - * String mappings for ike_sa_state_t. - */ -mapping_t ike_sa_state_m[] = { - {INITIATOR_INIT, "INITIATOR_INIT"}, - {RESPONDER_INIT, "RESPONDER_INIT"}, - {IKE_SA_INIT_REQUESTED, "IKE_SA_INIT_REQUESTED"}, - {IKE_SA_INIT_RESPONDED, "IKE_SA_INIT_RESPONDED"}, - {IKE_AUTH_REQUESTED, "IKE_AUTH_REQUESTED"}, - {IKE_SA_ESTABLISHED, "IKE_SA_ESTABLISHED"}, - {MAPPING_END, NULL} -}; diff --git a/src/charon/charon/sa/states/state.h b/src/charon/charon/sa/states/state.h deleted file mode 100644 index c93068d35..000000000 --- a/src/charon/charon/sa/states/state.h +++ /dev/null @@ -1,166 +0,0 @@ -/** - * @file state.h - * - * @brief Interface state_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef STATE_H_ -#define STATE_H_ - -#include -#include -#include - -typedef enum ike_sa_state_t ike_sa_state_t; - -/** - * States in which a IKE_SA can be. - * - * @todo Support of more states (CHILD_SA_REQUESTED, etc...) - * - * @ingroup states - */ -enum ike_sa_state_t { - - /** - * @brief IKE_SA is in initial state as initiator and is going to initiate a new connection. - * - * Next state following this state is IKE_SA_INIT_REQUESTED. - * - * Implemented in class initiator_init_t. - */ - INITIATOR_INIT = 1, - - /** - * @brief IKE_SA is in initial state as responder and is going to respond to a initiated connection. - * - * Next state following this state is IKE_SA_INIT_RESPONDED. - * - * Implemented in class responder_init_t. - */ - RESPONDER_INIT = 2, - - /** - * @brief A IKE_SA_INIT request was sent. In this state a reply of type IKE_SA_INIT is expected. - * - * Two states are possible as next states: - * - IKE_AUTH_REQUESTED if IKE_SA_INIT reply could successfully processed and IKE_AUTH request could be sent. - * - INITIATOR_INIT if selected DH group was not the one selected by other peer. - * - * Implemented in class ike_sa_init_requested_t. - */ - IKE_SA_INIT_REQUESTED = 3, - - /** - * @brief A IKE_SA_INIT response was sent. In this state a request of type IKE_AUTH is expected. - * - * Next state following this state is IKE_SA_ESTABLISHED. - * - * Implemented in class ike_sa_init_responded_t. - */ - IKE_SA_INIT_RESPONDED = 4, - - /** - * @brief An IKE_AUTH request was sent after a successful IKE_SA_INIT-exchange. - * - * Next state following this state is IKE_SA_ESTABLISHED. - * - * Implemented in class ike_auth_requested_t. - */ - IKE_AUTH_REQUESTED = 5, - - /** - * @brief An IKE_AUTH exchange was successfuly handled either as initiator or responder. - * - * In this state, all the informations for an IKE_SA and one CHILD_SA are known. - * - * Implemented in class ike_sa_established_t. - */ - IKE_SA_ESTABLISHED = 6 -}; - - -/** - * String mappings for ike_sa_state_t. - */ -extern mapping_t ike_sa_state_m[]; - - -typedef struct state_t state_t; - -/** - * @brief This interface represents an IKE_SA state. - * - * A state_t object is responsible to handle incoming messages. - * - * It's the responsibility of the state_t object to parse the body of the message and to process each - * payload. - * - * Needed Configurations and transform objects can be retrieved over an internal stored protected_ike_sa_t object - * which is passed to a state_t object when creating it (see different constructors). - * - * The following states are supported and implemented: - * - INITIATOR_INIT: implemented in initiator_init_t - * - RESPONDER_INIT: implemented in responder_init_t - * - IKE_SA_INIT_REQUESTED: implemented in ike_sa_init_requested_t - * - IKE_SA_INIT_RESPONDED: implemented in ike_sa_init_responded_t - * - IKE_AUTH_REQUESTED: implemented in ike_auth_requested_t - * - IKE_SA_ESTABLISHED: implemented in ike_sa_established_t - * - * @b Constructors: - * - initiator_init_create() - * - responder_init_create() - * - ike_sa_init_requested_create() - * - ike_sa_init_responded_create() - * - ike_auth_requested_create() - * - ike_sa_established_create() - * - * @ingroup states - */ -struct state_t { - - /** - * @brief Processes a incoming IKEv2-Message of type message_t. - * - * @param this calling object - * @param[in] message message_t object to process - * @return - * - SUCCESSFUL - * - FAILED - * - DELETE_ME if belonging IKE_SA should be deleted - */ - status_t (*process_message) (state_t *this,message_t *message); - - /** - * @brief Get the current state representing by this state_t object. - * - * @param this calling object - * @return state - */ - ike_sa_state_t (*get_state) (state_t *this); - - /** - * @brief Destroys a state_t object. - * - * @param this calling object - */ - void (*destroy) (state_t *this); -}; - -#endif /*STATE_H_*/ diff --git a/src/charon/charon/threads/Makefile.threads b/src/charon/charon/threads/Makefile.threads deleted file mode 100644 index 949c1ad24..000000000 --- a/src/charon/charon/threads/Makefile.threads +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright (C) 2005 Jan Hutter, 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 . -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# for more details. -# - -THREADS_DIR= $(CHARON_DIR)threads/ - -CHARON_OBJS+= $(BUILD_DIR)receiver.o -$(BUILD_DIR)receiver.o : $(THREADS_DIR)receiver.c $(THREADS_DIR)receiver.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)scheduler.o -$(BUILD_DIR)scheduler.o : $(THREADS_DIR)scheduler.c $(THREADS_DIR)scheduler.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)sender.o -$(BUILD_DIR)sender.o : $(THREADS_DIR)sender.c $(THREADS_DIR)sender.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)thread_pool.o -$(BUILD_DIR)thread_pool.o : $(THREADS_DIR)thread_pool.c $(THREADS_DIR)thread_pool.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)kernel_interface.o -$(BUILD_DIR)kernel_interface.o :$(THREADS_DIR)kernel_interface.c $(THREADS_DIR)kernel_interface.h - $(CC) $(CFLAGS) -c -o $@ $< - -CHARON_OBJS+= $(BUILD_DIR)stroke_interface.o -$(BUILD_DIR)stroke_interface.o :$(THREADS_DIR)stroke_interface.c $(THREADS_DIR)stroke_interface.h - $(CC) $(CFLAGS) -c -o $@ $< diff --git a/src/charon/charon/threads/kernel_interface.c b/src/charon/charon/threads/kernel_interface.c deleted file mode 100644 index 679cf69ee..000000000 --- a/src/charon/charon/threads/kernel_interface.c +++ /dev/null @@ -1,729 +0,0 @@ -/** - * @file kernel_interface.c - * - * @brief Implementation of kernel_interface_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, Martin Willi - * Hochschule fuer Technik Rapperswil - * Copyright (C) 2003 Herbert Xu. - * - * Contains modified parts from pluto. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 -#include -#include -#include -#include -#include -#include -#include - -#include "kernel_interface.h" - -#include -#include - - -#define KERNEL_ESP 50 -#define KERNEL_AH 51 - -#define SPD_PRIORITY 1024 - -#define XFRM_DATA_LENGTH 512 - - -typedef struct xfrm_data_t xfrm_data_t; - -/** - * Lenght/Type/data struct for userdata in xfrm - * We dont use the "I-don't-know-where-they-come-from"-structs - * used in the kernel. - */ -struct xfrm_data_t { - /** - * length of the data - */ - u_int16_t length; - - /** - * type of data - */ - u_int16_t type; - - /** - * and the data itself, for different purposes - */ - union { - /** algorithm */ - struct xfrm_algo algo; - /** policy tmpl */ - struct xfrm_user_tmpl tmpl[2]; - }; -}; - - -typedef struct netlink_message_t netlink_message_t; - -/** - * Representation of ANY netlink message used - */ -struct netlink_message_t { - - /** - * header of the netlink message - */ - struct nlmsghdr hdr; - - union { - /** error message */ - struct nlmsgerr e; - /** message for spi allocation */ - struct xfrm_userspi_info spi; - /** message for SA manipulation */ - struct xfrm_usersa_id sa_id; - /** message for SA installation */ - struct xfrm_usersa_info sa; - /** message for policy manipulation */ - struct xfrm_userpolicy_id policy_id; - /** message for policy installation */ - struct xfrm_userpolicy_info policy; - }; - u_int8_t data[XFRM_DATA_LENGTH]; -}; - - -typedef struct private_kernel_interface_t private_kernel_interface_t; - - /** - * @brief Private Variables and Functions of kernel_interface class. - * - */ -struct private_kernel_interface_t { - /** - * Public part of the kernel_interface_t object. - */ - kernel_interface_t public; - - /** - * Netlink communication socket. - */ - int socket; - - /** - * Process id of kernel thread - */ - pid_t pid; - - /** - * Sequence number for messages. - */ - u_int32_t seq; - - /** - * List of responded messages. - */ - linked_list_t *responses; - - /** - * Thread which receives messages. - */ - pthread_t thread; - - /** - * Mutex locks access to replies list. - */ - pthread_mutex_t mutex; - - /** - * Condvar allows signaling of threads waiting for a reply. - */ - pthread_cond_t condvar; - - /** - * Logger for XFRM stuff - */ - logger_t *logger; - - /** - * Function for the thread, receives messages. - */ - void (*receive_messages) (private_kernel_interface_t *this); - - /** - * Sends a netlink_message_t down to the kernel and wait for reply. - */ - status_t (*send_message) (private_kernel_interface_t *this, netlink_message_t *request, netlink_message_t **response); -}; - -/** - * In the kernel, algorithms are identified as strings, we use our - * mapping functions... - * Algorithms for encryption. - * TODO: Add missing algorithm strings - */ -mapping_t kernel_encryption_algs_m[] = { - {ENCR_DES_IV64, ""}, - {ENCR_DES, "des"}, - {ENCR_3DES, "des3_ede"}, - {ENCR_RC5, ""}, - {ENCR_IDEA, "idea"}, - {ENCR_CAST, "cast128"}, - {ENCR_BLOWFISH, "blowfish"}, - {ENCR_3IDEA, ""}, - {ENCR_DES_IV32, ""}, - {ENCR_NULL, ""}, - {ENCR_AES_CBC, "aes"}, - {ENCR_AES_CTR, ""}, - {MAPPING_END, NULL} -}; -/** - * In the kernel, algorithms are identified as strings, we use our - * mapping functions... - * Algorithms for integrity protection. - * TODO: Add missing algorithm strings - */ -mapping_t kernel_integrity_algs_m[] = { - {AUTH_HMAC_MD5_96, "md5"}, - {AUTH_HMAC_SHA1_96, "sha1"}, - {AUTH_DES_MAC, ""}, - {AUTH_KPDK_MD5, ""}, - {AUTH_AES_XCBC_96, ""}, - {MAPPING_END, NULL} -}; - - -/** - * Implementation of kernel_interface_t.get_spi. - */ -static status_t get_spi(private_kernel_interface_t *this, - host_t *src, host_t *dest, - protocol_id_t protocol, u_int32_t reqid, - u_int32_t *spi) -{ - netlink_message_t request, *response; - status_t status = SUCCESS; - - - this->logger->log(this->logger, CONTROL|LEVEL2, "getting spi"); - - memset(&request, 0, sizeof(request)); - request.hdr.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(request.spi))); - request.hdr.nlmsg_flags = NLM_F_REQUEST; - request.hdr.nlmsg_type = XFRM_MSG_ALLOCSPI; - request.spi.info.saddr = src->get_xfrm_addr(src); - request.spi.info.id.daddr = dest->get_xfrm_addr(dest); - request.spi.info.mode = TRUE; /* tunnel mode */ - request.spi.info.reqid = reqid; - request.spi.info.id.proto = (protocol == PROTO_ESP) ? KERNEL_ESP : KERNEL_AH; - request.spi.info.family = PF_INET; - request.spi.min = 0xc0000000; - request.spi.max = 0xcFFFFFFF; - - if (this->send_message(this, &request, &response) != SUCCESS) - { - this->logger->log(this->logger, ERROR, "netlink communication failed"); - return FAILED; - } - else if (response->hdr.nlmsg_type == NLMSG_ERROR) - { - this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_ALLOCSPI got an error: %s", - strerror(-response->e.error)); - status = FAILED; - } - else if (response->hdr.nlmsg_type != XFRM_MSG_NEWSA) - { - this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_ALLOCSPI got a unknown reply"); - status = FAILED; - } - else if (response->hdr.nlmsg_len < NLMSG_LENGTH(sizeof(response->sa))) - { - this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_ALLOCSPI got an invalid reply"); - status = FAILED; - } - else - { - *spi = response->sa.id.spi; - } - free(response); - - return status; -} - -/** - * Implementation of kernel_interface_t.add_sa. - */ -static status_t add_sa( private_kernel_interface_t *this, - host_t *me, - host_t *other, - u_int32_t spi, - int protocol, - u_int32_t reqid, - encryption_algorithm_t enc_alg, - chunk_t encryption_key, - integrity_algorithm_t int_alg, - chunk_t integrity_key, - bool replace) -{ - netlink_message_t request, *response; - memset(&request, 0, sizeof(request)); - status_t status = SUCCESS; - - this->logger->log(this->logger, CONTROL|LEVEL2, "adding SA"); - - request.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; - request.hdr.nlmsg_type = replace ? XFRM_MSG_UPDSA : XFRM_MSG_NEWSA; - - request.sa.saddr = me->get_xfrm_addr(me); - request.sa.id.daddr = other->get_xfrm_addr(other); - - request.sa.id.spi = spi; - request.sa.id.proto = (protocol == PROTO_ESP) ? KERNEL_ESP : KERNEL_AH; - request.sa.family = me->get_family(me); - request.sa.mode = TRUE; /* tunnel mode */ - request.sa.replay_window = 32; - request.sa.reqid = reqid; - request.sa.lft.soft_byte_limit = XFRM_INF; - request.sa.lft.soft_packet_limit = XFRM_INF; - request.sa.lft.hard_byte_limit = XFRM_INF; - request.sa.lft.hard_packet_limit = XFRM_INF; - - request.hdr.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(request.sa))); - - if (enc_alg != ENCR_UNDEFINED) - { - xfrm_data_t *data = (xfrm_data_t*)(((u_int8_t*)&request) + request.hdr.nlmsg_len); - - data->type = XFRMA_ALG_CRYPT; - data->length = 4 + sizeof(data->algo) + encryption_key.len; - data->algo.alg_key_len = encryption_key.len * 8; - request.hdr.nlmsg_len += data->length; - if (request.hdr.nlmsg_len > sizeof(request)) - { - return FAILED; - } - strcpy(data->algo.alg_name, mapping_find(kernel_encryption_algs_m, enc_alg)); - memcpy(data->algo.alg_key, encryption_key.ptr, encryption_key.len); - } - - if (int_alg != AUTH_UNDEFINED) - { - xfrm_data_t *data = (xfrm_data_t*)(((u_int8_t*)&request) + request.hdr.nlmsg_len); - - data->type = XFRMA_ALG_AUTH; - data->length = 4 + sizeof(data->algo) + integrity_key.len; - data->algo.alg_key_len = integrity_key.len * 8; - request.hdr.nlmsg_len += data->length; - if (request.hdr.nlmsg_len > sizeof(request)) - { - return FAILED; - } - strcpy(data->algo.alg_name, mapping_find(kernel_integrity_algs_m, int_alg)); - memcpy(data->algo.alg_key, integrity_key.ptr, integrity_key.len); - } - - /* TODO: add IPComp here*/ - - if (this->send_message(this, &request, &response) != SUCCESS) - { - this->logger->log(this->logger, ERROR, "netlink communication failed"); - return FAILED; - } - else if (response->hdr.nlmsg_type != NLMSG_ERROR) - { - this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_NEWSA not acknowledged"); - status = FAILED; - } - else if (response->e.error) - { - this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_NEWSA got error %s", - strerror(-response->e.error)); - status = FAILED; - } - - free(response); - return status; -} - -static status_t del_sa( private_kernel_interface_t *this, - host_t *dst, - u_int32_t spi, - protocol_id_t protocol) -{ - netlink_message_t request, *response; - memset(&request, 0, sizeof(request)); - status_t status = SUCCESS; - - this->logger->log(this->logger, CONTROL|LEVEL2, "deleting SA"); - - request.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; - request.hdr.nlmsg_type = XFRM_MSG_DELSA; - - request.sa_id.daddr = dst->get_xfrm_addr(dst); - - request.sa_id.spi = spi; - request.sa_id.proto = (protocol == PROTO_ESP) ? KERNEL_ESP : KERNEL_AH; - request.sa_id.family = dst->get_family(dst); - - request.hdr.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(request.sa_id))); - - if (this->send_message(this, &request, &response) != SUCCESS) - { - return FAILED; - } - else if (response->hdr.nlmsg_type != NLMSG_ERROR) - { - status = FAILED; - } - else if (response->e.error) - { - status = FAILED; - } - - free(response); - return status; -} - -/** - * Implementation of kernel_interface_t.add_policy. - */ -static status_t add_policy(private_kernel_interface_t *this, - host_t *me, host_t *other, - host_t *src, host_t *dst, - u_int8_t src_hostbits, u_int8_t dst_hostbits, - int direction, int upper_proto, - bool ah, bool esp, - u_int32_t reqid) -{ - netlink_message_t request, *response; - status_t status = SUCCESS; - - this->logger->log(this->logger, CONTROL|LEVEL2, "adding policy"); - - memset(&request, 0, sizeof(request)); - request.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; - - request.policy.sel.sport = htons(src->get_port(src)); - request.policy.sel.dport = htons(dst->get_port(dst)); - request.policy.sel.sport_mask = (request.policy.sel.sport) ? ~0 : 0; - request.policy.sel.dport_mask = (request.policy.sel.dport) ? ~0 : 0; - request.policy.sel.saddr = src->get_xfrm_addr(src); - request.policy.sel.daddr = dst->get_xfrm_addr(dst); - request.policy.sel.prefixlen_s = src_hostbits; - request.policy.sel.prefixlen_d = dst_hostbits; - request.policy.sel.proto = upper_proto; - request.policy.sel.family = src->get_family(src); - - request.hdr.nlmsg_type = XFRM_MSG_NEWPOLICY; - request.hdr.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(request.policy))); - - request.policy.dir = direction; - request.policy.priority = SPD_PRIORITY; - request.policy.action = XFRM_POLICY_ALLOW; - request.policy.share = XFRM_SHARE_ANY; - - request.policy.lft.soft_byte_limit = XFRM_INF; - request.policy.lft.soft_packet_limit = XFRM_INF; - request.policy.lft.hard_byte_limit = XFRM_INF; - request.policy.lft.hard_packet_limit = XFRM_INF; - - if (esp || ah) - { - xfrm_data_t *data; - int tmpl_pos = 0; - data = (xfrm_data_t*)(((u_int8_t*)&request) + request.hdr.nlmsg_len); - data->type = XFRMA_TMPL; - if (esp) - { - data->tmpl[tmpl_pos].reqid = reqid; - data->tmpl[tmpl_pos].id.proto = KERNEL_ESP; - data->tmpl[tmpl_pos].aalgos = data->tmpl[tmpl_pos].ealgos = data->tmpl[tmpl_pos].calgos = ~0; - data->tmpl[tmpl_pos].mode = TRUE; - - data->tmpl[tmpl_pos].saddr = me->get_xfrm_addr(me); - data->tmpl[tmpl_pos].id.daddr = me->get_xfrm_addr(other); - - tmpl_pos++; - } - if (ah) - { - data->tmpl[tmpl_pos].reqid = reqid; - data->tmpl[tmpl_pos].id.proto = KERNEL_AH; - data->tmpl[tmpl_pos].aalgos = data->tmpl[tmpl_pos].ealgos = data->tmpl[tmpl_pos].calgos = ~0; - data->tmpl[tmpl_pos].mode = TRUE; - - data->tmpl[tmpl_pos].saddr = me->get_xfrm_addr(me); - data->tmpl[tmpl_pos].id.daddr = other->get_xfrm_addr(other); - - tmpl_pos++; - } - data->length = 4 + sizeof(struct xfrm_user_tmpl) * tmpl_pos; - request.hdr.nlmsg_len += data->length; - } - - if (this->send_message(this, &request, &response) != SUCCESS) - { - this->logger->log(this->logger, ERROR, "netlink communication failed"); - return FAILED; - } - else if (response->hdr.nlmsg_type != NLMSG_ERROR) - { - this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_NEWPOLICY not acknowledged"); - status = FAILED; - } - else if (response->e.error) - { - this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_NEWPOLICY got error %s", - strerror(-response->e.error)); - status = FAILED; - } - - free(response); - return status; -} - -/** - * Implementation of kernel_interface_t.del_policy. - */ -static status_t del_policy(private_kernel_interface_t *this, - host_t *me, host_t *other, - host_t *src, host_t *dst, - u_int8_t src_hostbits, u_int8_t dst_hostbits, - int direction, int upper_proto) -{ - netlink_message_t request, *response; - status_t status = SUCCESS; - - - this->logger->log(this->logger, CONTROL|LEVEL2, "deleting policy"); - - memset(&request, 0, sizeof(request)); - request.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; - - request.policy_id.sel.sport = htons(src->get_port(src)); - request.policy_id.sel.dport = htons(dst->get_port(dst)); - request.policy_id.sel.sport_mask = (request.policy.sel.sport) ? ~0 : 0; - request.policy_id.sel.dport_mask = (request.policy.sel.dport) ? ~0 : 0; - request.policy_id.sel.saddr = src->get_xfrm_addr(src); - request.policy_id.sel.daddr = dst->get_xfrm_addr(dst); - request.policy_id.sel.prefixlen_s = src_hostbits; - request.policy_id.sel.prefixlen_d = dst_hostbits; - request.policy_id.sel.proto = upper_proto; - request.policy_id.sel.family = src->get_family(src); - - request.policy_id.dir = direction; - - request.hdr.nlmsg_type = XFRM_MSG_DELPOLICY; - request.hdr.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(request.policy_id))); - - if (this->send_message(this, &request, &response) != SUCCESS) - { - return FAILED; - } - else if (response->hdr.nlmsg_type != NLMSG_ERROR) - { - status = FAILED; - } - else if (response->e.error) - { - status = FAILED; - } - - free(response); - return status; -} - -/** - * Implementation of private_kernel_interface_t.send_message. - */ -static status_t send_message(private_kernel_interface_t *this, netlink_message_t *request, netlink_message_t **response) -{ - size_t length; - struct sockaddr_nl addr; - - request->hdr.nlmsg_seq = ++this->seq; - request->hdr.nlmsg_pid = this->pid; - - memset(&addr, 0, sizeof(struct sockaddr_nl)); - addr.nl_family = AF_NETLINK; - addr.nl_pid = 0; - addr.nl_groups = 0; - - length = sendto(this->socket,(void *)request, request->hdr.nlmsg_len, 0, (struct sockaddr *)&addr, sizeof(addr)); - - if (length < 0) - { - return FAILED; - } - else if (length != request->hdr.nlmsg_len) - { - return FAILED; - } - - pthread_mutex_lock(&(this->mutex)); - - while (TRUE) - { - iterator_t *iterator; - bool found = FALSE; - /* search list, break if found */ - iterator = this->responses->create_iterator(this->responses, TRUE); - while (iterator->has_next(iterator)) - { - netlink_message_t *listed_response; - iterator->current(iterator, (void**)&listed_response); - if (listed_response->hdr.nlmsg_seq == request->hdr.nlmsg_seq) - { - /* matches our request, this is the reply */ - *response = listed_response; - found = TRUE; - break; - } - } - iterator->destroy(iterator); - - if (found) - { - break; - } - /* TODO: we should time out, if something goes wrong!??? */ - pthread_cond_wait(&(this->condvar), &(this->mutex)); - } - - pthread_mutex_unlock(&(this->mutex)); - - return SUCCESS; -} - -/** - * Implementation of private_kernel_interface_t.receive_messages. - */ -static void receive_messages(private_kernel_interface_t *this) -{ - while(TRUE) - { - netlink_message_t response, *listed_response; - while (TRUE) - { - struct sockaddr_nl addr; - socklen_t addr_length; - size_t length; - - addr_length = sizeof(addr); - - response.hdr.nlmsg_type = XFRM_MSG_NEWSA; - length = recvfrom(this->socket, &response, sizeof(response), 0, (struct sockaddr*)&addr, &addr_length); - if (length < 0) - { - if (errno == EINTR) - { - /* interrupted, try again */ - continue; - } - charon->kill(charon, "receiving from netlink socket failed"); - } - if (!NLMSG_OK(&response.hdr, length)) - { - /* bad netlink message */ - continue; - } - if (addr.nl_pid != 0) - { - /* not from kernel. not interested, try another one */ - continue; - } - break; - } - - /* got a valid message. - * requests are handled on our own, - * responses are listed for the requesters - */ - if (response.hdr.nlmsg_flags & NLM_F_REQUEST) - { - /* handle request */ - } - else - { - /* add response to queue */ - listed_response = malloc(sizeof(response)); - memcpy(listed_response, &response, sizeof(response)); - - pthread_mutex_lock(&(this->mutex)); - this->responses->insert_last(this->responses, (void*)listed_response); - pthread_mutex_unlock(&(this->mutex)); - /* signal ALL waiting threads */ - pthread_cond_broadcast(&(this->condvar)); - } - /* get the next one */ - } -} - -/** - * Implementation of kernel_interface_t.destroy. - */ -static void destroy(private_kernel_interface_t *this) -{ - pthread_cancel(this->thread); - pthread_join(this->thread, NULL); - close(this->socket); - this->responses->destroy(this->responses); - free(this); -} - -/* - * Described in header. - */ -kernel_interface_t *kernel_interface_create() -{ - private_kernel_interface_t *this = malloc_thing(private_kernel_interface_t); - - /* public functions */ - this->public.get_spi = (status_t(*)(kernel_interface_t*,host_t*,host_t*,protocol_id_t,u_int32_t,u_int32_t*))get_spi; - this->public.add_sa = (status_t(*)(kernel_interface_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,encryption_algorithm_t,chunk_t,integrity_algorithm_t,chunk_t,bool))add_sa; - this->public.add_policy = (status_t(*)(kernel_interface_t*,host_t*, host_t*,host_t*,host_t*,u_int8_t,u_int8_t,int,int,bool,bool,u_int32_t))add_policy; - this->public.del_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t))del_sa; - this->public.del_policy = (status_t(*)(kernel_interface_t*,host_t*,host_t*,host_t*,host_t*,u_int8_t,u_int8_t,int,int))del_policy; - - this->public.destroy = (void(*)(kernel_interface_t*)) destroy; - - /* private members */ - this->receive_messages = receive_messages; - this->send_message = send_message; - this->pid = getpid(); - this->responses = linked_list_create(); - this->logger = logger_manager->get_logger(logger_manager, XFRM); - pthread_mutex_init(&(this->mutex),NULL); - pthread_cond_init(&(this->condvar),NULL); - this->seq = 0; - this->socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_XFRM); - if (this->socket <= 0) - { - this->responses->destroy(this->responses); - free(this); - charon->kill(charon, "Unable to create netlink socket"); - } - - if (pthread_create(&(this->thread), NULL, (void*(*)(void*))this->receive_messages, this) != 0) - { - this->responses->destroy(this->responses); - close(this->socket); - free(this); - charon->kill(charon, "Unable to create netlink thread"); - } - - return (&this->public); -} diff --git a/src/charon/charon/threads/kernel_interface.h b/src/charon/charon/threads/kernel_interface.h deleted file mode 100644 index b3ca13faa..000000000 --- a/src/charon/charon/threads/kernel_interface.h +++ /dev/null @@ -1,185 +0,0 @@ -/** - * @file kernel_interface.h - * - * @brief Interface of kernel_interface_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef KERNEL_INTERFACE_H_ -#define KERNEL_INTERFACE_H_ - -#include - -#include -#include - -typedef struct kernel_interface_t kernel_interface_t; - -/** - * @brief Interface to the kernel. - * - * The kernel interface handles the communication with the kernel - * for SA and policy management. It allows setup of these, and provides - * further the handling of kernel events. - * - * @b Constructors: - * - kernel_interface_create() - * - * @ingroup threads - */ -struct kernel_interface_t { - - /** - * @brief Get a SPI from the kernel. - * - * @param this calling object - * @param src source address of SA - * @param dst destination address of SA - * @param protocol protocol for SA (ESP/AH) - * @param reqid unique ID for this SA - * @param[out] spi allocated spi - * @return - * - SUCCESS - * - FAILED if kernel comm failed - */ - status_t (*get_spi) (kernel_interface_t *this, - host_t *src, host_t *dst, - protocol_id_t protocol, - u_int32_t reqid, - u_int32_t *spi); - - /** - * @brief Add an SA to the SAD. - * - * add_sa() may update an already allocated - * SPI (via get_spi). In this case, the replace - * flag must be set. - * This function does install a single SA for a - * single protocol in one direction. - * - * @param this calling object - * @param src source address for this SA - * @param dst destination address for this SA - * @param spi SPI allocated by us or remote peer - * @param protocol protocol for this SA (ESP/AH) - * @param reqid unique ID for this SA - * @param enc_alg Algorithm to use for encryption (ESP only) - * @param enc_key Key to use for encryption - * @param int_alg Algorithm to use for integrity protection - * @param int_key Key for integrity protection - * @param replace Should an already installed SA be updated? - * @return - * - SUCCESS - * - FAILED if kernel comm failed - */ - status_t (*add_sa)(kernel_interface_t *this, - host_t *src, host_t *dst, - u_int32_t spi, - protocol_id_t protocol, - u_int32_t reqid, - encryption_algorithm_t enc_alg, - chunk_t enc_key, - integrity_algorithm_t int_alg, - chunk_t int_key, - bool replace); - /** - * @brief Delete a previusly installed SA from the SAD. - * - * @param this calling object - * @param dst destination address for this SA - * @param spi SPI allocated by us or remote peer - * @param protocol protocol for this SA (ESP/AH) - * @return - * - SUCCESS - * - FAILED if kernel comm failed - */ - status_t (*del_sa) (kernel_interface_t *this, - host_t *dst, - u_int32_t spi, - protocol_id_t protocol); - - /** - * @brief Add a policy to the SPD. - * - * A policy is always associated to an SA, so - * traffic applied to a policy. Traffic which - * matches a policy is handled by the SA with the same - * reqid. - * - * @param this calling object - * @param me address of local peer - * @param other address of remote peer - * @param src src address of traffic this policy applies - * @param dst dest address of traffic this policy applies - * @param src_hostbits subnetmask to use for src address - * @param dst_hostbits subnetmask to use for dst address - * @param direction direction of traffic, XFRM_POLICY_OUT, XFRM_POLICY_IN, XFRM_POLICY_FWD - * @param upper_proto upper layer protocol of traffic for this policy (TCP, UDP, ICMP, ...) - * @param ah protect traffic with AH? - * @param esp protect traffic with ESP? - * @param reqid uniqe ID of an SA to use to enforce policy - * @return - * - SUCCESS - * - FAILED if kernel comm failed - */ - status_t (*add_policy) (kernel_interface_t *this, - host_t *me, host_t *other, - host_t *src, host_t *dst, - u_int8_t src_hostbits, u_int8_t dst_hostbits, - int direction, int upper_proto, - bool ah, bool esp, - u_int32_t reqid); - - /** - * @brief Remove a policy from the SPD. - * - * @param this calling object - * @param me address of local peer - * @param other address of remote peer - * @param src src address of traffic this policy applies - * @param dst dest address of traffic this policy applies - * @param src_hostbits subnetmask to use for src address - * @param dst_hostbits subnetmask to use for dst address - * @param direction direction of traffic, XFRM_POLICY_OUT, XFRM_POLICY_IN, XFRM_POLICY_FWD - * @param upper_proto upper layer protocol of traffic for this policy (TCP, UDP, ICMP, ...) - * @return - * - SUCCESS - * - FAILED if kernel comm failed - */ - status_t (*del_policy) (kernel_interface_t *this, - host_t *me, host_t *other, - host_t *src, host_t *dst, - u_int8_t src_hostbits, u_int8_t dst_hostbits, - int direction, int upper_proto); - - /** - * @brief Destroys a kernel_interface object. - * - * @param kernel_interface_t calling object - */ - void (*destroy) (kernel_interface_t *kernel_interface); -}; - -/** - * @brief Creates an object of type kernel_interface_t. - * - * @ingroup threads - */ -kernel_interface_t *kernel_interface_create(void); - -#endif /*KERNEL_INTERFACE_H_*/ diff --git a/src/charon/charon/threads/receiver.c b/src/charon/charon/threads/receiver.c deleted file mode 100644 index 0cf8b7bde..000000000 --- a/src/charon/charon/threads/receiver.c +++ /dev/null @@ -1,128 +0,0 @@ -/** - * @file receiver.c - * - * @brief Implementation of receiver_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 -#include - -#include "receiver.h" - -#include -#include -#include -#include -#include -#include -#include - - -typedef struct private_receiver_t private_receiver_t; - -/** - * Private data of a receiver_t object. - */ -struct private_receiver_t { - /** - * Public part of a receiver_t object. - */ - receiver_t public; - - /** - * @brief Thread function started at creation of the receiver object. - * - * @param this calling object - */ - void (*receive_packets) (private_receiver_t *this); - - /** - * Assigned thread. - */ - pthread_t assigned_thread; - - /** - * A logger for the receiver_t object. - */ - logger_t *logger; -}; - -/** - * Implementation of receiver_t.receive_packets. - */ -static void receive_packets(private_receiver_t * this) -{ - packet_t * current_packet; - job_t *current_job; - - /* cancellation disabled by default */ - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); - - this->logger->log(this->logger, CONTROL, "Receiver thread running, thread_id %u", (int)pthread_self()); - - while (1) - { - while (charon->socket->receive(charon->socket,¤t_packet) == SUCCESS) - { - this->logger->log(this->logger, CONTROL | LEVEL1, "Creating job from packet"); - current_job = (job_t *) incoming_packet_job_create(current_packet); - - charon->job_queue->add(charon->job_queue,current_job); - - } - /* bad bad, rebuild the socket ? */ - this->logger->log(this->logger, ERROR, "Receiving from socket failed!"); - } -} - -/** - * Implementation of receiver_t.destroy. - */ -static void destroy(private_receiver_t *this) -{ - this->logger->log(this->logger, CONTROL | LEVEL1, "Going to terminate receiver thread"); - pthread_cancel(this->assigned_thread); - - pthread_join(this->assigned_thread, NULL); - this->logger->log(this->logger, CONTROL | LEVEL1, "Receiver thread terminated"); - - free(this); -} - -/* - * Described in header. - */ -receiver_t * receiver_create() -{ - private_receiver_t *this = malloc_thing(private_receiver_t); - - this->public.destroy = (void(*)(receiver_t*)) destroy; - this->receive_packets = receive_packets; - - this->logger = logger_manager->get_logger(logger_manager, RECEIVER); - - if (pthread_create(&(this->assigned_thread), NULL, (void*(*)(void*))this->receive_packets, this) != 0) - { - this->logger->log(this->logger, ERROR, "Receiver thread could not be started"); - free(this); - charon->kill(charon, "Unable to create receiver thread"); - } - - return &(this->public); -} diff --git a/src/charon/charon/threads/receiver.h b/src/charon/charon/threads/receiver.h deleted file mode 100644 index 1f9b644b1..000000000 --- a/src/charon/charon/threads/receiver.h +++ /dev/null @@ -1,67 +0,0 @@ -/** - * @file receiver.h - * - * @brief Interface of receiver_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef RECEIVER_H_ -#define RECEIVER_H_ - -#include - - -typedef struct receiver_t receiver_t; - -/** - * @brief Receives packets from the socket and adds them to the job queue. - * - * The receiver starts a thread, wich reads on the blocking socket. If - * data is available, a packet_t object is created , wrapped - * in an incoming_packet_job_t and added to the job queue. - * - * @b Constructors: - * - receiver_create() - * - * @ingroup threads - */ -struct receiver_t { - - /** - * @brief Destroys a receiver_t object. - * - * @param receiver receiver object - */ - void (*destroy) (receiver_t *receiver); -}; - -/** - * @brief Create a receiver_t object. - * - * The receiver thread will start working, get data - * from the socket and add those packets to the job queue. - * - * @return - * - receiver_t object - * - NULL of thread could not be started - * - * @ingroup threads - */ -receiver_t * receiver_create(void); - -#endif /*RECEIVER_H_*/ diff --git a/src/charon/charon/threads/scheduler.c b/src/charon/charon/threads/scheduler.c deleted file mode 100644 index 47c5d6fb9..000000000 --- a/src/charon/charon/threads/scheduler.c +++ /dev/null @@ -1,124 +0,0 @@ -/** - * @file scheduler.c - * - * @brief Implementation of scheduler_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 -#include - -#include "scheduler.h" - -#include -#include -#include -#include - - -typedef struct private_scheduler_t private_scheduler_t; - -/** - * Private data of a scheduler_t object. - */ -struct private_scheduler_t { - /** - * Public part of a scheduler_t object. - */ - scheduler_t public; - - /** - * @brief Get events from the event queue and add them to to job queue. - * - * Thread function started at creation of the scheduler object. - * - * @param this calling object - */ - void (*get_events) (private_scheduler_t *this); - - /** - * Assigned thread. - */ - pthread_t assigned_thread; - - /** - * A logger. - */ - logger_t *logger; -}; - -/** - * Implementation of private_scheduler_t.get_events. - */ -static void get_events(private_scheduler_t * this) -{ - job_t *current_job; - - /* cancellation disabled by default */ - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); - - this->logger->log(this->logger, CONTROL, "Scheduler thread running, thread_id %u", (int)pthread_self()); - - for (;;) - { - this->logger->log(this->logger, CONTROL|LEVEL2, "Waiting for next event..."); - /* get a job, this block until one is available */ - current_job = charon->event_queue->get(charon->event_queue); - /* queue the job in the job queue, workers will eat them */ - charon->job_queue->add(charon->job_queue, current_job); - this->logger->log(this->logger, CONTROL | LEVEL1, "Got event, added job %s to job-queue.", - mapping_find(job_type_m, current_job->get_type(current_job))); - } -} - -/** - * Implementation of scheduler_t.destroy. - */ -static void destroy(private_scheduler_t *this) -{ - this->logger->log(this->logger, CONTROL | LEVEL1, "Going to terminate scheduler thread"); - pthread_cancel(this->assigned_thread); - - pthread_join(this->assigned_thread, NULL); - this->logger->log(this->logger, CONTROL | LEVEL1, "Scheduler thread terminated"); - - free(this); -} - -/* - * Described in header. - */ -scheduler_t * scheduler_create() -{ - private_scheduler_t *this = malloc_thing(private_scheduler_t); - - this->public.destroy = (void(*)(scheduler_t*)) destroy; - this->get_events = get_events; - - this->logger = logger_manager->get_logger(logger_manager, SCHEDULER); - - if (pthread_create(&(this->assigned_thread), NULL, (void*(*)(void*))this->get_events, this) != 0) - { - /* thread could not be created */ - this->logger->log(this->logger, ERROR, "Scheduler thread could not be created!"); - free(this); - charon->kill(charon, "Unable to create scheduler thread"); - } - - return &(this->public); -} diff --git a/src/charon/charon/threads/scheduler.h b/src/charon/charon/threads/scheduler.h deleted file mode 100644 index 04d639d1b..000000000 --- a/src/charon/charon/threads/scheduler.h +++ /dev/null @@ -1,67 +0,0 @@ -/** - * @file scheduler.h - * - * @brief Interface of scheduler_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef SCHEDULER_H_ -#define SCHEDULER_H_ - -#include - -typedef struct scheduler_t scheduler_t; - -/** - * @brief The scheduler thread is responsible for timed events. - * - * The scheduler thread takes out jobs from the event-queue and adds them - * to the job-queue. - * - * Starts a thread which does the work, since event-queue is blocking. - * - * @b Constructors: - * - scheduler_create() - * - * @ingroup threads - */ -struct scheduler_t { - - /** - * @brief Destroys a scheduler object. - * - * @param scheduler calling object - */ - void (*destroy) (scheduler_t *scheduler); -}; - -/** - * @brief Create a scheduler with its associated thread. - * - * The thread will start to get jobs form the event queue - * and adds them to the job queue. - * - * @return - * - scheduler_t object - * - NULL if thread could not be started - * - * @ingroup threads - */ -scheduler_t * scheduler_create(void); - -#endif /*SCHEDULER_H_*/ diff --git a/src/charon/charon/threads/sender.c b/src/charon/charon/threads/sender.c deleted file mode 100644 index 42d11beb9..000000000 --- a/src/charon/charon/threads/sender.c +++ /dev/null @@ -1,126 +0,0 @@ -/** - * @file sender.c - * - * @brief Implementation of sender_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 -#include - -#include "sender.h" - -#include -#include -#include -#include -#include - - -typedef struct private_sender_t private_sender_t; - -/** - * Private data of a sender_t object. - */ -struct private_sender_t { - /** - * Public part of a sender_t object. - */ - sender_t public; - - /** - * Assigned thread. - */ - pthread_t assigned_thread; - - /** - * @brief The thread function, sends out packets. - * - * @param this calling object - */ - void (*send_packets) (private_sender_t * this); - - /** - * A logger for this sender_t object. - */ - logger_t *logger; - -}; - -/** - * Implementation of private_sender_t.send_packets. - */ -static void send_packets(private_sender_t * this) -{ - packet_t * current_packet; - status_t status; - - /* cancellation disabled by default */ - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); - - this->logger->log(this->logger, CONTROL, "Sender thread running, thread_id %u", (int)pthread_self()); - - while (1) - { - current_packet = charon->send_queue->get(charon->send_queue); - this->logger->log(this->logger, CONTROL|LEVEL1, "Got a packet, sending it"); - status = charon->socket->send(charon->socket,current_packet); - if (status != SUCCESS) - { - this->logger->log(this->logger, ERROR, "Sending failed, socket returned %s", - mapping_find(status_m, status)); - } - current_packet->destroy(current_packet); - } -} - -/** - * Implementation of sender_t.destroy. - */ -static void destroy(private_sender_t *this) -{ - this->logger->log(this->logger, CONTROL | LEVEL1, "Going to terminate sender thread"); - pthread_cancel(this->assigned_thread); - - pthread_join(this->assigned_thread, NULL); - this->logger->log(this->logger, CONTROL | LEVEL1, "Sender thread terminated"); - - free(this); -} - -/* - * Described in header. - */ -sender_t * sender_create() -{ - private_sender_t *this = malloc_thing(private_sender_t); - - this->send_packets = send_packets; - this->public.destroy = (void(*)(sender_t*)) destroy; - - this->logger = logger_manager->get_logger(logger_manager, SENDER); - - if (pthread_create(&(this->assigned_thread), NULL, (void*(*)(void*))this->send_packets, this) != 0) - { - this->logger->log(this->logger, ERROR, "Sender thread could not be created"); - free(this); - charon->kill(charon, "Unable to create sender thread"); - } - - return &(this->public); -} diff --git a/src/charon/charon/threads/sender.h b/src/charon/charon/threads/sender.h deleted file mode 100644 index 2a41ccc66..000000000 --- a/src/charon/charon/threads/sender.h +++ /dev/null @@ -1,63 +0,0 @@ -/** - * @file sender.h - * - * @brief Interface of sender_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef SENDER_H_ -#define SENDER_H_ - -#include - -typedef struct sender_t sender_t; - -/** - * @brief Thread responsible for sending packets over the socket. - * - * @b Constructors: - * - sender_create() - * - * @ingroup threads - */ -struct sender_t { - - /** - * @brief Destroys a sender object. - * - * @param sender calling object - */ - void (*destroy) (sender_t *sender); -}; - - -/** - * @brief Create the sender thread. - * - * The thread will start to work, getting packets - * from the send queue and sends them out. - * - * @return - * - sender_t object - * - NULL of thread could not be started - * - * @ingroup threads - */ -sender_t * sender_create(void); - -#endif /*SENDER_H_*/ diff --git a/src/charon/charon/threads/stroke_interface.c b/src/charon/charon/threads/stroke_interface.c deleted file mode 100755 index a9c55673b..000000000 --- a/src/charon/charon/threads/stroke_interface.c +++ /dev/null @@ -1,646 +0,0 @@ -/** - * @file stroke.c - * - * @brief Implementation of stroke_t. - * - */ - -/* - * Copyright (C) 2006 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "stroke_interface.h" - -#include -#include -#include -#include -#include - - -struct sockaddr_un socket_addr = { AF_UNIX, STROKE_SOCKET}; - - -typedef struct private_stroke_t private_stroke_t; - -/** - * Private data of an stroke_t object. - */ -struct private_stroke_t { - - /** - * Public part of stroke_t object. - */ - stroke_t public; - - /** - * Assigned logger_t object in charon. - */ - logger_t *logger; - - /** - * Logger which logs to stroke - */ - logger_t *stroke_logger; - - /** - * Unix socket to listen for strokes - */ - int socket; - - /** - * Thread which reads from the socket - */ - pthread_t assigned_thread; - - /** - * Read from the socket and handle stroke messages - */ - void (*stroke_receive) (private_stroke_t *this); -}; - -/** - * Helper function which corrects the string pointers - * in a stroke_msg_t. Strings in a stroke_msg sent over "wire" - * contains RELATIVE addresses (relative to the beginning of the - * stroke_msg). They must be corrected if they reach our address - * space... - */ -static void pop_string(stroke_msg_t *msg, char **string) -{ - /* check for sanity of string pointer and string */ - if (*string == NULL) - { - *string = ""; - } - else if (string < (char**)msg || - string > (char**)msg + sizeof(stroke_msg_t) || - *string < (char*)msg->buffer - (u_int)msg || - *string > (char*)(u_int)msg->length) - { - *string = "(invalid char* in stroke msg)"; - } - else - { - *string = (char*)msg + (u_int)*string; - } -} - -/** - * Add a connection to the configuration list - */ -static void stroke_add_conn(private_stroke_t *this, stroke_msg_t *msg) -{ - connection_t *connection; - policy_t *policy; - identification_t *my_id, *other_id; - host_t *my_host, *other_host, *my_subnet, *other_subnet; - proposal_t *proposal; - traffic_selector_t *my_ts, *other_ts; - x509_t *cert; - - pop_string(msg, &msg->add_conn.name); - pop_string(msg, &msg->add_conn.me.address); - pop_string(msg, &msg->add_conn.other.address); - pop_string(msg, &msg->add_conn.me.id); - pop_string(msg, &msg->add_conn.other.id); - pop_string(msg, &msg->add_conn.me.cert); - pop_string(msg, &msg->add_conn.other.cert); - pop_string(msg, &msg->add_conn.me.subnet); - pop_string(msg, &msg->add_conn.other.subnet); - - this->logger->log(this->logger, CONTROL, "received stroke: add connection \"%s\"", msg->add_conn.name); - - my_host = host_create(AF_INET, msg->add_conn.me.address, 500); - if (my_host == NULL) - { - this->stroke_logger->log(this->stroke_logger, ERROR, "invalid host: %s", msg->add_conn.me.address); - return; - } - other_host = host_create(AF_INET, msg->add_conn.other.address, 500); - if (other_host == NULL) - { - this->stroke_logger->log(this->stroke_logger, ERROR, "invalid host: %s", msg->add_conn.other.address); - my_host->destroy(my_host); - return; - } - my_id = identification_create_from_string(*msg->add_conn.me.id ? - msg->add_conn.me.id : msg->add_conn.me.address); - if (my_id == NULL) - { - this->stroke_logger->log(this->stroke_logger, ERROR, "invalid id: %s", msg->add_conn.me.id); - my_host->destroy(my_host); - other_host->destroy(other_host); - return; - } - other_id = identification_create_from_string(*msg->add_conn.other.id ? - msg->add_conn.other.id : msg->add_conn.other.address); - if (other_id == NULL) - { - my_host->destroy(my_host); - other_host->destroy(other_host); - my_id->destroy(my_id); - this->stroke_logger->log(this->stroke_logger, ERROR, "invalid id: %s", msg->add_conn.other.id); - return; - } - - my_subnet = host_create(AF_INET, *msg->add_conn.me.subnet ? msg->add_conn.me.subnet : msg->add_conn.me.address, 500); - if (my_subnet == NULL) - { - my_host->destroy(my_host); - other_host->destroy(other_host); - my_id->destroy(my_id); - other_id->destroy(other_id); - this->stroke_logger->log(this->stroke_logger, ERROR, "invalid subnet: %s", msg->add_conn.me.subnet); - return; - } - - other_subnet = host_create(AF_INET, *msg->add_conn.other.subnet ? msg->add_conn.other.subnet : msg->add_conn.other.address, 500); - if (other_subnet == NULL) - { - my_host->destroy(my_host); - other_host->destroy(other_host); - my_id->destroy(my_id); - other_id->destroy(other_id); - my_subnet->destroy(my_subnet); - this->stroke_logger->log(this->stroke_logger, ERROR, "invalid subnet: %s", msg->add_conn.me.subnet); - return; - } - - my_ts = traffic_selector_create_from_subnet(my_subnet, *msg->add_conn.me.subnet ? msg->add_conn.me.subnet_mask : 32); - my_subnet->destroy(my_subnet); - other_ts = traffic_selector_create_from_subnet(other_subnet, *msg->add_conn.other.subnet ? msg->add_conn.other.subnet_mask : 32); - other_subnet->destroy(other_subnet); - - if (charon->socket->is_listening_on(charon->socket, other_host)) - { - this->stroke_logger->log(this->stroke_logger, CONTROL|LEVEL1, "left is other host, switching"); - - host_t *tmp_host = my_host; - identification_t *tmp_id = my_id; - traffic_selector_t *tmp_ts = my_ts; - char *tmp_cert = msg->add_conn.me.cert; - - my_host = other_host; - other_host = tmp_host; - my_id = other_id; - other_id = tmp_id; - my_ts = other_ts; - other_ts = tmp_ts; - msg->add_conn.me.cert = msg->add_conn.other.cert; - msg->add_conn.other.cert = tmp_cert; - } - else if (charon->socket->is_listening_on(charon->socket, my_host)) - { - this->stroke_logger->log(this->stroke_logger, CONTROL|LEVEL1, "left is own host, not switching"); - } - else - { - this->stroke_logger->log(this->stroke_logger, ERROR, "left nor right host is our, aborting"); - - my_host->destroy(my_host); - other_host->destroy(other_host); - my_id->destroy(my_id); - other_id->destroy(other_id); - my_ts->destroy(my_ts); - other_ts->destroy(other_ts); - return; - } - - if (msg->add_conn.me.cert) - { - char file[128]; - snprintf(file, sizeof(file), "%s/%s", CERTIFICATE_DIR, msg->add_conn.me.cert); - cert = x509_create_from_file(file); - if (cert) - { - my_id->destroy(my_id); - my_id = cert->get_subject(cert); - my_id = my_id->clone(my_id); - cert->destroy(cert); - this->logger->log(this->logger, CONTROL, - "valid certificate with ID \"%s\"", - my_id->get_string(my_id)); - } - } - if (msg->add_conn.other.cert) - { - char file[128]; - snprintf(file, sizeof(file), "%s/%s", CERTIFICATE_DIR, msg->add_conn.other.cert); - cert = x509_create_from_file(file); - if (cert) - { - other_id->destroy(other_id); - other_id = cert->get_subject(cert); - other_id = other_id->clone(other_id); - cert->destroy(cert); - this->logger->log(this->logger, CONTROL, - "valid certificate with ID \"%s\"", - other_id->get_string(other_id)); - } - } - - connection = connection_create(msg->add_conn.name, - my_host, other_host, - my_id->clone(my_id), other_id->clone(other_id), - RSA_DIGITAL_SIGNATURE); - proposal = proposal_create(1); - proposal->add_algorithm(proposal, PROTO_IKE, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 16); - proposal->add_algorithm(proposal, PROTO_IKE, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0); - proposal->add_algorithm(proposal, PROTO_IKE, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0); - proposal->add_algorithm(proposal, PROTO_IKE, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_SHA1, 0); - proposal->add_algorithm(proposal, PROTO_IKE, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_MD5, 0); - proposal->add_algorithm(proposal, PROTO_IKE, DIFFIE_HELLMAN_GROUP, MODP_2048_BIT, 0); - proposal->add_algorithm(proposal, PROTO_IKE, DIFFIE_HELLMAN_GROUP, MODP_1536_BIT, 0); - proposal->add_algorithm(proposal, PROTO_IKE, DIFFIE_HELLMAN_GROUP, MODP_1024_BIT, 0); - proposal->add_algorithm(proposal, PROTO_IKE, DIFFIE_HELLMAN_GROUP, MODP_4096_BIT, 0); - proposal->add_algorithm(proposal, PROTO_IKE, DIFFIE_HELLMAN_GROUP, MODP_8192_BIT, 0); - connection->add_proposal(connection, proposal); - /* add to global connection list */ - charon->connections->add_connection(charon->connections, connection); - - policy = policy_create(my_id, other_id); - proposal = proposal_create(1); - proposal->add_algorithm(proposal, PROTO_ESP, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 16); - proposal->add_algorithm(proposal, PROTO_ESP, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0); - proposal->add_algorithm(proposal, PROTO_ESP, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0); - policy->add_proposal(policy, proposal); - policy->add_my_traffic_selector(policy, my_ts); - policy->add_other_traffic_selector(policy, other_ts); - /* add to global policy list */ - charon->policies->add_policy(charon->policies, policy); - - this->stroke_logger->log(this->stroke_logger, CONTROL|LEVEL1, "connection \"%s\" added", msg->add_conn.name); -} - -/** - * initiate a connection by name - */ -static void stroke_initiate(private_stroke_t *this, stroke_msg_t *msg) -{ - initiate_ike_sa_job_t *job; - connection_t *connection; - - pop_string(msg, &(msg->initiate.name)); - this->logger->log(this->logger, CONTROL, "received stroke: initiate \"%s\"", msg->initiate.name); - connection = charon->connections->get_connection_by_name(charon->connections, msg->initiate.name); - if (connection == NULL) - { - this->stroke_logger->log(this->stroke_logger, ERROR, "no connection named \"%s\"", msg->initiate.name); - } - else - { - job = initiate_ike_sa_job_create(connection); - charon->job_queue->add(charon->job_queue, (job_t*)job); - } -} - -/** - * terminate a connection by name - */ -static void stroke_terminate(private_stroke_t *this, stroke_msg_t *msg) -{ - linked_list_t *ike_sas; - iterator_t *iterator; - int instances = 0; - - pop_string(msg, &(msg->terminate.name)); - this->logger->log(this->logger, CONTROL, "received stroke: terminate \"%s\"", msg->terminate.name); - - ike_sas = charon->ike_sa_manager->get_ike_sa_list_by_name(charon->ike_sa_manager, msg->terminate.name); - - iterator = ike_sas->create_iterator(ike_sas, TRUE); - while (iterator->has_next(iterator)) - { - ike_sa_id_t *ike_sa_id; - iterator->current(iterator, (void**)&ike_sa_id); - charon->ike_sa_manager->delete(charon->ike_sa_manager, ike_sa_id); - ike_sa_id->destroy(ike_sa_id); - instances++; - } - iterator->destroy(iterator); - ike_sas->destroy(ike_sas); - this->stroke_logger->log(this->stroke_logger, CONTROL, "terminated %d instances of %s", instances, msg->terminate.name); -} - -/** - * show status of (established) connections - */ -static void stroke_status(private_stroke_t *this, stroke_msg_t *msg) -{ - if (msg->status.name) - { - pop_string(msg, &(msg->status.name)); - } - charon->ike_sa_manager->log_status(charon->ike_sa_manager, this->stroke_logger, msg->status.name); -} - -logger_context_t get_context(char *context) -{ - if (strcasecmp(context, "ALL") == 0) return ALL_LOGGERS; - else if (strcasecmp(context, "PARSR") == 0) return PARSER; - else if (strcasecmp(context, "GNRAT") == 0) return GENERATOR; - else if (strcasecmp(context, "IKESA") == 0) return IKE_SA; - else if (strcasecmp(context, "SAMGR") == 0) return IKE_SA_MANAGER; - else if (strcasecmp(context, "CHDSA") == 0) return CHILD_SA; - else if (strcasecmp(context, "MESSG") == 0) return MESSAGE; - else if (strcasecmp(context, "TPOOL") == 0) return THREAD_POOL; - else if (strcasecmp(context, "WORKR") == 0) return WORKER; - else if (strcasecmp(context, "SCHED") == 0) return SCHEDULER; - else if (strcasecmp(context, "SENDR") == 0) return SENDER; - else if (strcasecmp(context, "RECVR") == 0) return RECEIVER; - else if (strcasecmp(context, "SOCKT") == 0) return SOCKET; - else if (strcasecmp(context, "TESTR") == 0) return TESTER; - else if (strcasecmp(context, "DAEMN") == 0) return DAEMON; - else if (strcasecmp(context, "CONFG") == 0) return CONFIG; - else if (strcasecmp(context, "ENCPL") == 0) return ENCRYPTION_PAYLOAD; - else if (strcasecmp(context, "PAYLD") == 0) return PAYLOAD; - else return -2; -} - -/** - * set the type of logged messages in a context - */ -static void stroke_logtype(private_stroke_t *this, stroke_msg_t *msg) -{ - pop_string(msg, &(msg->logtype.context)); - pop_string(msg, &(msg->logtype.type)); - - this->logger->log(this->logger, CONTROL, "received stroke: logtype for %s", msg->logtype.context); - - log_level_t level; - logger_context_t context = get_context(msg->logtype.context); - if (context == -2) - { - this->stroke_logger->log(this->stroke_logger, ERROR, "invalid context (%s)!", msg->logtype.context); - return; - } - - if (strcasecmp(msg->logtype.type, "CONTROL") == 0) level = CONTROL; - else if (strcasecmp(msg->logtype.type, "ERROR") == 0) level = ERROR; - else if (strcasecmp(msg->logtype.type, "AUDIT") == 0) level = AUDIT; - else if (strcasecmp(msg->logtype.type, "RAW") == 0) level = RAW; - else if (strcasecmp(msg->logtype.type, "PRIVATE") == 0) level = PRIVATE; - else - { - this->stroke_logger->log(this->stroke_logger, ERROR, "invalid type (%s)!", msg->logtype.type); - return; - } - - if (msg->logtype.enable) - { - logger_manager->enable_log_level(logger_manager, context, level); - } - else - { - logger_manager->disable_log_level(logger_manager, context, level); - } -} - -/** - * set the verbosity of a logger - */ -static void stroke_loglevel(private_stroke_t *this, stroke_msg_t *msg) -{ - pop_string(msg, &(msg->loglevel.context)); - - this->logger->log(this->logger, CONTROL, "received stroke: loglevel for %s", msg->loglevel.context); - - log_level_t level; - logger_context_t context = get_context(msg->loglevel.context); - - if (context == -2) - { - this->stroke_logger->log(this->stroke_logger, ERROR, "invalid context (%s)!", msg->loglevel.context); - return; - } - - if (msg->loglevel.level == 0) - { - level = LEVEL0; - } - else if (msg->loglevel.level == 1) - { - level = LEVEL1; - } - else if (msg->loglevel.level == 2) - { - level = LEVEL2; - } - else if (msg->loglevel.level == 3) - { - level = LEVEL3; - } - else - { - this->stroke_logger->log(this->stroke_logger, ERROR, "invalid level (%d)!", msg->loglevel.level); - return; - } - - logger_manager->enable_log_level(logger_manager, context, level); -} - -/** - * Implementation of private_stroke_t.stroke_receive. - */ -static void stroke_receive(private_stroke_t *this) -{ - stroke_msg_t *msg; - u_int16_t msg_length; - struct sockaddr_un strokeaddr; - int strokeaddrlen = sizeof(strokeaddr); - ssize_t bytes_read; - int strokefd; - FILE *strokefile; - int oldstate; - - /* disable cancellation by default */ - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); - - while (1) - { - /* wait for connections, but allow thread to terminate */ - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); - strokefd = accept(this->socket, (struct sockaddr *)&strokeaddr, &strokeaddrlen); - pthread_setcancelstate(oldstate, NULL); - - if (strokefd < 0) - { - this->logger->log(this->logger, ERROR, "accepting stroke connection failed: %s", strerror(errno)); - continue; - } - - /* peek the length */ - bytes_read = recv(strokefd, &msg_length, sizeof(msg_length), MSG_PEEK); - if (bytes_read != sizeof(msg_length)) - { - this->logger->log(this->logger, ERROR, "reading lenght of stroke message failed"); - close(strokefd); - continue; - } - - /* read message */ - msg = malloc(msg_length); - bytes_read = recv(strokefd, msg, msg_length, 0); - if (bytes_read != msg_length) - { - this->logger->log(this->logger, ERROR, "reading stroke message failed: %s"); - close(strokefd); - continue; - } - - strokefile = fdopen(dup(strokefd), "w"); - if (strokefile == NULL) - { - this->logger->log(this->logger, ERROR, "opening stroke output channel failed:", strerror(errno)); - close(strokefd); - free(msg); - continue; - } - - /* setup a logger which writes status to the unix socket */ - this->stroke_logger = logger_create("-", CONTROL|ERROR, FALSE, strokefile); - - this->logger->log_bytes(this->logger, RAW, "stroke message", (void*)msg, msg_length); - - switch (msg->type) - { - case STR_INITIATE: - { - stroke_initiate(this, msg); - break; - } - case STR_TERMINATE: - { - stroke_terminate(this, msg); - break; - } - case STR_STATUS: - { - stroke_status(this, msg); - break; - } - case STR_STATUS_ALL: - { - this->stroke_logger->enable_level(this->stroke_logger, LEVEL1); - stroke_status(this, msg); - break; - } - case STR_ADD_CONN: - { - stroke_add_conn(this, msg); - break; - } - case STR_LOGTYPE: - { - stroke_logtype(this, msg); - break; - } - case STR_LOGLEVEL: - { - stroke_loglevel(this, msg); - break; - } - default: - this->logger->log(this->logger, ERROR, "received invalid stroke"); - } - this->stroke_logger->destroy(this->stroke_logger); - fclose(strokefile); - close(strokefd); - free(msg); - } -} - -/** - * Implementation of stroke_t.destroy. - */ -static void destroy(private_stroke_t *this) -{ - - pthread_cancel(this->assigned_thread); - pthread_join(this->assigned_thread, NULL); - - close(this->socket); - unlink(socket_addr.sun_path); - free(this); -} - - -/* - * Described in header-file - */ -stroke_t *stroke_create() -{ - private_stroke_t *this = malloc_thing(private_stroke_t); - mode_t old; - - /* public functions */ - this->public.destroy = (void (*)(stroke_t*))destroy; - - /* private functions */ - this->stroke_receive = stroke_receive; - - this->logger = logger_manager->get_logger(logger_manager, CONFIG); - - /* set up unix socket */ - this->socket = socket(AF_UNIX, SOCK_STREAM, 0); - if (this->socket == -1) - { - this->logger->log(this->logger, ERROR, "could not create whack socket"); - free(this); - return NULL; - } - - old = umask(~S_IRWXU); - if (bind(this->socket, (struct sockaddr *)&socket_addr, sizeof(socket_addr)) < 0) - { - this->logger->log(this->logger, ERROR, "could not bind stroke socket: %s", strerror(errno)); - close(this->socket); - free(this); - return NULL; - } - umask(old); - - if (listen(this->socket, 0) < 0) - { - this->logger->log(this->logger, ERROR, "could not listen on stroke socket: %s", strerror(errno)); - close(this->socket); - unlink(socket_addr.sun_path); - free(this); - return NULL; - } - - /* start a thread reading from the socket */ - if (pthread_create(&(this->assigned_thread), NULL, (void*(*)(void*))this->stroke_receive, this) != 0) - { - this->logger->log(this->logger, ERROR, "Could not spawn stroke thread"); - close(this->socket); - unlink(socket_addr.sun_path); - free(this); - return NULL; - } - - return (&this->public); -} diff --git a/src/charon/charon/threads/stroke_interface.h b/src/charon/charon/threads/stroke_interface.h deleted file mode 100644 index 16eb66533..000000000 --- a/src/charon/charon/threads/stroke_interface.h +++ /dev/null @@ -1,76 +0,0 @@ -/** - * @file stroke.h - * - * @brief Interface of stroke_t. - * - */ - -/* - * Copyright (C) 2006 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef STROKE_INTERFACE_H_ -#define STROKE_INTERFACE_H_ - -#include -#include -#include - - -typedef struct stroke_t stroke_t; - -/** - * @brief Stroke is a configuration and control interface which - * allows other processes to modify charons behavior. - * - * stroke_t allows config manipulation (as whack in pluto). - * Messages of type stroke_msg_t's are sent over a unix socket - * (/var/run/charon.ctl). stroke_t implements the connections_t - * and the policies_t interface, which means it acts as a - * configuration backend for those too. stroke_t uses an own - * thread to read from the socket. - * - * @warning DO NOT cast stroke_t to any of the implemented interfaces! - * stroke_t implements multiple interfaces, so you must use - * stroke_t.interface_xy to access the specific interface! You have - * been warned... - * - * @todo Add clean thread cancellation - * - * @b Constructors: - * - stroke_create() - * - * @ingroup threads - */ -struct stroke_t { - - /** - * @brief Destroy a stroke_t instance. - * - * @param this stroke_t objec to destroy - */ - void (*destroy) (stroke_t *this); -}; - - -/** - * @brief Create the stroke interface and listen on the socket. - * - * @return stroke_t object - * - * @ingroup threads - */ -stroke_t *stroke_create(void); - -#endif /* STROKE_INTERFACE_H_ */ diff --git a/src/charon/charon/threads/thread_pool.c b/src/charon/charon/threads/thread_pool.c deleted file mode 100644 index 4482e795f..000000000 --- a/src/charon/charon/threads/thread_pool.c +++ /dev/null @@ -1,623 +0,0 @@ -/** - * @file thread_pool.c - * - * @brief Implementation of thread_pool_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 -#include -#include -#include - -#include "thread_pool.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -typedef struct private_thread_pool_t private_thread_pool_t; - -/** - * @brief Private data of thread_pool_t class. - */ -struct private_thread_pool_t { - /** - * Public thread_pool_t interface. - */ - thread_pool_t public; - - /** - * @brief Main processing function for worker threads. - * - * Gets a job from the job queue and calls corresponding - * function for processing. - * - * @param this calling object - */ - void (*process_jobs) (private_thread_pool_t *this); - - /** - * @brief Process a INCOMING_PACKET job. - * - * @param this calling object - * @param job incoming_packet_job_t object - */ - void (*process_incoming_packet_job) (private_thread_pool_t *this, incoming_packet_job_t *job); - - /** - * @brief Process a INITIATE_IKE_SA job. - * - * @param this calling object - * @param job initiate_ike_sa_job_t object - */ - void (*process_initiate_ike_sa_job) (private_thread_pool_t *this, initiate_ike_sa_job_t *job); - - /** - * @brief Process a DELETE_HALF_OPEN_IKE_SA job. - * - * @param this calling object - * @param job delete__half_open_ike_sa_job_t object - */ - void (*process_delete_half_open_ike_sa_job) (private_thread_pool_t *this, delete_half_open_ike_sa_job_t *job); - - /** - * @brief Process a DELETE_ESTABLISHED_IKE_SA job. - * - * @param this calling object - * @param job delete_established_ike_sa_job_t object - */ - void (*process_delete_established_ike_sa_job) (private_thread_pool_t *this, delete_established_ike_sa_job_t *job); - - /** - * @brief Process a RETRANSMIT_REQUEST job. - * - * @param this calling object - * @param job retransmit_request_job_t object - */ - void (*process_retransmit_request_job) (private_thread_pool_t *this, retransmit_request_job_t *job); - - /** - * Creates a job of type DELETE_HALF_OPEN_IKE_SA. - * - * This job is used to delete IKE_SA's which are still in state INITIATOR_INIT, - * RESPONDER_INIT, IKE_AUTH_REQUESTED, IKE_INIT_REQUESTED or IKE_INIT_RESPONDED. - * - * @param ike_sa_id ID of IKE_SA to delete - * @param delay Delay in ms after a half open IKE_SA gets deleted! - */ - void (*create_delete_half_open_ike_sa_job) (private_thread_pool_t *this,ike_sa_id_t *ike_sa_id, u_int32_t delay); - - /** - * Number of running threads. - */ - size_t pool_size; - - /** - * Array of thread ids. - */ - pthread_t *threads; - - /** - * Logger of the thread pool. - */ - logger_t *pool_logger; - - /** - * Logger of the worker threads. - */ - logger_t *worker_logger; -} ; - -/** - * Implementation of private_thread_pool_t.process_jobs. - */ -static void process_jobs(private_thread_pool_t *this) -{ - job_t *job; - job_type_t job_type; - timeval_t start_time; - timeval_t end_time; - - /* cancellation disabled by default */ - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); - - this->worker_logger->log(this->worker_logger, CONTROL, "Worker thread running, thread_id: %u", (int)pthread_self()); - - for (;;) { - - job = charon->job_queue->get(charon->job_queue); - job_type = job->get_type(job); - this->worker_logger->log(this->worker_logger, CONTROL|LEVEL2, "Process job of type %s", - mapping_find(job_type_m,job_type)); - gettimeofday(&start_time,NULL); - switch (job_type) - { - case INCOMING_PACKET: - { - this->process_incoming_packet_job(this, (incoming_packet_job_t*)job); - job->destroy(job); - break; - } - case INITIATE_IKE_SA: - { - this->process_initiate_ike_sa_job(this, (initiate_ike_sa_job_t*)job); - job->destroy(job); - break; - } - case DELETE_HALF_OPEN_IKE_SA: - { - this->process_delete_half_open_ike_sa_job(this, (delete_half_open_ike_sa_job_t*)job); - job->destroy(job); - break; - } - case DELETE_ESTABLISHED_IKE_SA: - { - this->process_delete_established_ike_sa_job(this, (delete_established_ike_sa_job_t*)job); - job->destroy(job); - break; - } - case RETRANSMIT_REQUEST: - { - this->process_retransmit_request_job(this, (retransmit_request_job_t*)job); - break; - } - default: - { - this->worker_logger->log(this->worker_logger, ERROR, "Job of type %s not supported!", - mapping_find(job_type_m,job_type)); - job->destroy(job); - break; - } - } - gettimeofday(&end_time,NULL); - - this->worker_logger->log(this->worker_logger, CONTROL | LEVEL2, "Processed job of type %s in %d us", - mapping_find(job_type_m,job_type), - (((end_time.tv_sec - start_time.tv_sec) * 1000000) + (end_time.tv_usec - start_time.tv_usec))); - - - } -} - -/** - * Implementation of private_thread_pool_t.process_incoming_packet_job. - */ -static void process_incoming_packet_job(private_thread_pool_t *this, incoming_packet_job_t *job) -{ - packet_t *packet; - message_t *message; - ike_sa_t *ike_sa; - ike_sa_id_t *ike_sa_id; - status_t status; - - - packet = job->get_packet(job); - - message = message_create_from_packet(packet); - - status = message->parse_header(message); - if (status != SUCCESS) - { - this->worker_logger->log(this->worker_logger, ERROR, "Message header could not be verified!"); - message->destroy(message); - return; - } - - this->worker_logger->log(this->worker_logger, CONTROL|LEVEL2, "Message is a %s %s", - mapping_find(exchange_type_m, message->get_exchange_type(message)), - message->get_request(message) ? "request" : "reply"); - - if ((message->get_major_version(message) != IKE_MAJOR_VERSION) || - (message->get_minor_version(message) != IKE_MINOR_VERSION)) - { - this->worker_logger->log(this->worker_logger, ERROR | LEVEL2, "IKE version %d.%d not supported", - message->get_major_version(message), - message->get_minor_version(message)); - /* - * This check is not handled in state_t object of IKE_SA to increase speed. - */ - if ((message->get_exchange_type(message) == IKE_SA_INIT) && (message->get_request(message))) - { - message_t *response; - message->get_ike_sa_id(message, &ike_sa_id); - ike_sa_id->switch_initiator(ike_sa_id); - response = message_create_notify_reply(message->get_destination(message), - message->get_source(message), - IKE_SA_INIT, - FALSE,ike_sa_id,INVALID_MAJOR_VERSION); - message->destroy(message); - ike_sa_id->destroy(ike_sa_id); - status = response->generate(response, NULL, NULL, &packet); - if (status != SUCCESS) - { - this->worker_logger->log(this->worker_logger, ERROR, "Could not generate packet from message"); - response->destroy(response); - return; - } - this->worker_logger->log(this->worker_logger, ERROR, "Send notify reply of type INVALID_MAJOR_VERSION"); - charon->send_queue->add(charon->send_queue, packet); - response->destroy(response); - return; - } - message->destroy(message); - return; - } - - message->get_ike_sa_id(message, &ike_sa_id); - - ike_sa_id->switch_initiator(ike_sa_id); - - this->worker_logger->log(this->worker_logger, CONTROL|LEVEL3, "Checking out IKE SA %lld:%lld, role %s", - ike_sa_id->get_initiator_spi(ike_sa_id), - ike_sa_id->get_responder_spi(ike_sa_id), - ike_sa_id->is_initiator(ike_sa_id) ? "initiator" : "responder"); - - status = charon->ike_sa_manager->checkout(charon->ike_sa_manager,ike_sa_id, &ike_sa); - if ((status != SUCCESS) && (status != CREATED)) - { - this->worker_logger->log(this->worker_logger, ERROR, "IKE SA could not be checked out"); - ike_sa_id->destroy(ike_sa_id); - message->destroy(message); - - /* - * TODO send notify reply of type INVALID_IKE_SPI if SPI could not be found ? - */ - - return; - } - - if (status == CREATED) - { - this->worker_logger->log(this->worker_logger, CONTROL|LEVEL3, - "Create Job to delete half open IKE_SA."); - this->create_delete_half_open_ike_sa_job(this,ike_sa_id, - charon->configuration->get_half_open_ike_sa_timeout(charon->configuration)); - } - - status = ike_sa->process_message(ike_sa, message); - - this->worker_logger->log(this->worker_logger, CONTROL|LEVEL3, "%s IKE SA %lld:%lld, role %s", - (status == DELETE_ME) ? "Checkin and delete" : "Checkin", - ike_sa_id->get_initiator_spi(ike_sa_id), - ike_sa_id->get_responder_spi(ike_sa_id), - ike_sa_id->is_initiator(ike_sa_id) ? "initiator" : "responder"); - ike_sa_id->destroy(ike_sa_id); - - if (status == DELETE_ME) - { - status = charon->ike_sa_manager->checkin_and_delete(charon->ike_sa_manager, ike_sa); - } - else - { - status = charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); - } - - if (status != SUCCESS) - { - this->worker_logger->log(this->worker_logger, ERROR, "Checkin of IKE SA failed!"); - } - message->destroy(message); -} - -/** - * Implementation of private_thread_pool_t.process_initiate_ike_sa_job. - */ -static void process_initiate_ike_sa_job(private_thread_pool_t *this, initiate_ike_sa_job_t *job) -{ - /* - * Initiatie an IKE_SA: - * - is defined by a name of a configuration - * - create an empty IKE_SA via manager - * - call initiate_connection on this sa - */ - ike_sa_t *ike_sa; - status_t status; - - - this->worker_logger->log(this->worker_logger, CONTROL|LEVEL2, "Creating and checking out IKE SA"); - charon->ike_sa_manager->create_and_checkout(charon->ike_sa_manager, &ike_sa); - - status = ike_sa->initiate_connection(ike_sa, job->get_connection(job)); - if (status != SUCCESS) - { - this->worker_logger->log(this->worker_logger, ERROR, "Initiation returned %s, going to delete IKE_SA.", - mapping_find(status_m, status)); - charon->ike_sa_manager->checkin_and_delete(charon->ike_sa_manager, ike_sa); - return; - } - - this->worker_logger->log(this->worker_logger, CONTROL|LEVEL3, "Create Job to delete half open IKE_SA."); - this->create_delete_half_open_ike_sa_job(this,ike_sa->get_id(ike_sa), - charon->configuration->get_half_open_ike_sa_timeout(charon->configuration)); - - this->worker_logger->log(this->worker_logger, CONTROL|LEVEL2, "Checking in IKE SA"); - status = charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); - if (status != SUCCESS) - { - this->worker_logger->log(this->worker_logger, ERROR, "Could not checkin IKE_SA (%s)", - mapping_find(status_m, status)); - } -} - -/** - * Implementation of private_thread_pool_t.process_delete_ike_sa_job. - */ -static void process_delete_half_open_ike_sa_job(private_thread_pool_t *this, delete_half_open_ike_sa_job_t *job) -{ - ike_sa_id_t *ike_sa_id = job->get_ike_sa_id(job); - ike_sa_t *ike_sa; - status_t status; - status = charon->ike_sa_manager->checkout(charon->ike_sa_manager,ike_sa_id, &ike_sa); - if ((status != SUCCESS) && (status != CREATED)) - { - this->worker_logger->log(this->worker_logger, CONTROL | LEVEL3, "IKE SA seems to be allready deleted and so doesn't have to be deleted"); - return; - } - - - switch (ike_sa->get_state(ike_sa)) - { - case INITIATOR_INIT: - case RESPONDER_INIT: - case IKE_SA_INIT_REQUESTED: - case IKE_SA_INIT_RESPONDED: - case IKE_AUTH_REQUESTED: - { - /* IKE_SA is half open and gets deleted! */ - status = charon->ike_sa_manager->checkin_and_delete(charon->ike_sa_manager, ike_sa); - if (status != SUCCESS) - { - this->worker_logger->log(this->worker_logger, ERROR, "Could not checkin and delete checked out IKE_SA!"); - } - break; - } - default: - { - /* IKE_SA is established and so is not getting deleted! */ - status = charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); - if (status != SUCCESS) - { - this->worker_logger->log(this->worker_logger, ERROR, "Could not checkin a checked out IKE_SA!"); - } - break; - } - } -} - -/** - * Implementation of private_thread_pool_t.process_delete_established_ike_sa_job. - */ -static void process_delete_established_ike_sa_job(private_thread_pool_t *this, delete_established_ike_sa_job_t *job) -{ - ike_sa_id_t *ike_sa_id = job->get_ike_sa_id(job); - ike_sa_t *ike_sa; - status_t status; - status = charon->ike_sa_manager->checkout(charon->ike_sa_manager,ike_sa_id, &ike_sa); - if ((status != SUCCESS) && (status != CREATED)) - { - this->worker_logger->log(this->worker_logger, CONTROL | LEVEL3, "IKE SA seems to be allready deleted and so doesn't have to be deleted"); - return; - } - - switch (ike_sa->get_state(ike_sa)) - { - case INITIATOR_INIT: - case RESPONDER_INIT: - case IKE_SA_INIT_REQUESTED: - case IKE_SA_INIT_RESPONDED: - case IKE_AUTH_REQUESTED: - { - break; - } - default: - { - this->worker_logger->log(this->worker_logger, CONTROL, "Send delete request for IKE_SA."); - ike_sa->send_delete_ike_sa_request(ike_sa); - break; - } - } - this->worker_logger->log(this->worker_logger, CONTROL, "Delete established IKE_SA."); - status = charon->ike_sa_manager->checkin_and_delete(charon->ike_sa_manager, ike_sa); - if (status != SUCCESS) - { - this->worker_logger->log(this->worker_logger, ERROR, "Could not checkin and delete checked out IKE_SA!"); - } -} - - -/** - * Implementation of private_thread_pool_t.process_retransmit_request_job. - */ -static void process_retransmit_request_job(private_thread_pool_t *this, retransmit_request_job_t *job) -{ - - ike_sa_id_t *ike_sa_id = job->get_ike_sa_id(job); - u_int32_t message_id = job->get_message_id(job); - bool stop_retransmitting = FALSE; - u_int32_t timeout; - ike_sa_t *ike_sa; - status_t status; - - this->worker_logger->log(this->worker_logger, CONTROL|LEVEL2, "Checking out IKE SA %lld:%lld, role %s", - ike_sa_id->get_initiator_spi(ike_sa_id), - ike_sa_id->get_responder_spi(ike_sa_id), - ike_sa_id->is_initiator(ike_sa_id) ? "initiator" : "responder"); - - status = charon->ike_sa_manager->checkout(charon->ike_sa_manager,ike_sa_id, &ike_sa); - if ((status != SUCCESS) && (status != CREATED)) - { - job->destroy(job); - this->worker_logger->log(this->worker_logger, ERROR, "IKE SA could not be checked out. Allready deleted?"); - return; - } - - status = ike_sa->retransmit_request(ike_sa, message_id); - - if (status != SUCCESS) - { - this->worker_logger->log(this->worker_logger, CONTROL | LEVEL3, "Message doesn't have to be retransmitted"); - stop_retransmitting = TRUE; - } - - this->worker_logger->log(this->worker_logger, CONTROL|LEVEL2, "Checkin IKE SA %lld:%lld, role %s", - ike_sa_id->get_initiator_spi(ike_sa_id), - ike_sa_id->get_responder_spi(ike_sa_id), - ike_sa_id->is_initiator(ike_sa_id) ? "initiator" : "responder"); - - status = charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); - if (status != SUCCESS) - { - this->worker_logger->log(this->worker_logger, ERROR, "Checkin of IKE SA failed!"); - } - - if (stop_retransmitting) - { - job->destroy(job); - return; - } - - job->increase_retransmit_count(job); - status = charon->configuration->get_retransmit_timeout (charon->configuration,job->get_retransmit_count(job),&timeout); - if (status != SUCCESS) - { - this->worker_logger->log(this->worker_logger, CONTROL | LEVEL2, "Message will not be anymore retransmitted"); - job->destroy(job); - /* - * TODO delete IKE_SA ? - */ - return; - } - charon->event_queue->add_relative(charon->event_queue,(job_t *) job,timeout); -} - - - -/** - * Implementation of private_thread_pool_t.create_delete_half_open_ike_sa_job. - */ -static void create_delete_half_open_ike_sa_job(private_thread_pool_t *this,ike_sa_id_t *ike_sa_id, u_int32_t delay) -{ - job_t *delete_job; - - this->worker_logger->log(this->worker_logger, CONTROL | LEVEL2, "Going to create job to delete half open IKE_SA in %d ms", delay); - - delete_job = (job_t *) delete_half_open_ike_sa_job_create(ike_sa_id); - charon->event_queue->add_relative(charon->event_queue,delete_job, delay); -} - - -/** - * Implementation of thread_pool_t.get_pool_size. - */ -static size_t get_pool_size(private_thread_pool_t *this) -{ - return this->pool_size; -} - -/** - * Implementation of thread_pool_t.destroy. - */ -static void destroy(private_thread_pool_t *this) -{ - int current; - /* flag thread for termination */ - for (current = 0; current < this->pool_size; current++) { - this->pool_logger->log(this->pool_logger, CONTROL, "cancelling worker thread #%d", current+1); - pthread_cancel(this->threads[current]); - } - - /* wait for all threads */ - for (current = 0; current < this->pool_size; current++) { - if (pthread_join(this->threads[current], NULL) == 0) - { - this->pool_logger->log(this->pool_logger, CONTROL, "worker thread #%d terminated", current+1); - } - else - { - this->pool_logger->log(this->pool_logger, ERROR, "could not terminate worker thread #%d", current+1); - } - } - - /* free mem */ - free(this->threads); - free(this); -} - -/* - * Described in header. - */ -thread_pool_t *thread_pool_create(size_t pool_size) -{ - int current; - - private_thread_pool_t *this = malloc_thing(private_thread_pool_t); - - /* fill in public fields */ - this->public.destroy = (void(*)(thread_pool_t*))destroy; - this->public.get_pool_size = (size_t(*)(thread_pool_t*))get_pool_size; - - this->process_jobs = process_jobs; - this->process_initiate_ike_sa_job = process_initiate_ike_sa_job; - this->process_delete_half_open_ike_sa_job = process_delete_half_open_ike_sa_job; - this->process_delete_established_ike_sa_job = process_delete_established_ike_sa_job; - this->process_incoming_packet_job = process_incoming_packet_job; - this->process_retransmit_request_job = process_retransmit_request_job; - this->create_delete_half_open_ike_sa_job = create_delete_half_open_ike_sa_job; - - this->pool_size = pool_size; - - this->threads = malloc(sizeof(pthread_t) * pool_size); - - this->pool_logger = logger_manager->get_logger(logger_manager, THREAD_POOL); - - this->worker_logger = logger_manager->get_logger(logger_manager, WORKER); - - /* try to create as many threads as possible, up tu pool_size */ - for (current = 0; current < pool_size; current++) - { - if (pthread_create(&(this->threads[current]), NULL, (void*(*)(void*))this->process_jobs, this) == 0) - { - this->pool_logger->log(this->pool_logger, CONTROL, "Created worker thread #%d", current+1); - } - else - { - /* creation failed, is it the first one? */ - if (current == 0) - { - this->pool_logger->log(this->pool_logger, ERROR, "Could not create any thread"); - free(this->threads); - free(this); - return NULL; - } - /* not all threads could be created, but at least one :-/ */ - this->pool_logger->log(this->pool_logger, ERROR, "Could only create %d from requested %d threads!", current, pool_size); - - this->pool_size = current; - return (thread_pool_t*)this; - } - } - return (thread_pool_t*)this; -} diff --git a/src/charon/charon/threads/thread_pool.h b/src/charon/charon/threads/thread_pool.h deleted file mode 100644 index b33be08e3..000000000 --- a/src/charon/charon/threads/thread_pool.h +++ /dev/null @@ -1,78 +0,0 @@ -/** - * @file thread_pool.h - * - * @brief Interface of thread_pool_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, 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 . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef THREAD_POOL_H_ -#define THREAD_POOL_H_ - -#include - -#include - - -typedef struct thread_pool_t thread_pool_t; - -/** - * @brief A thread_pool consists of a pool of threads processing jobs from the job queue. - * - * Current implementation uses as many threads as specified in constructor. - * A more improved version would dynamically increase thread count if necessary. - * - * @b Constructors: - * - thread_pool_create() - * - * @todo Add support for dynamic thread handling - * - * @ingroup threads - */ -struct thread_pool_t { - /** - * @brief Return currently instanciated thread count. - * - * @param thread_pool calling object - * @return size of thread pool - */ - size_t (*get_pool_size) (thread_pool_t *thread_pool); - - /** - * @brief Destroy a thread_pool_t object. - * - * Sends cancellation request to all threads and AWAITS their termination. - * - * @param thread_pool calling object - */ - void (*destroy) (thread_pool_t *thread_pool); -}; - -/** - * @brief Create the thread pool using using pool_size of threads. - * - * @param pool_size desired pool size - * @return - * - thread_pool_t object if one ore more threads could be started, or - * - NULL if no threads could be created - * - * @ingroup threads - */ -thread_pool_t *thread_pool_create(size_t pool_size); - - -#endif /*THREAD_POOL_H_*/ diff --git a/src/charon/config/Makefile.config b/src/charon/config/Makefile.config new file mode 100644 index 000000000..d4638b318 --- /dev/null +++ b/src/charon/config/Makefile.config @@ -0,0 +1,32 @@ +# Copyright (C) 2005 Jan Hutter, 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 . +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# + +CONFIG_DIR= $(CHARON_DIR)config/ + + +CHARON_OBJS+= $(BUILD_DIR)traffic_selector.o +$(BUILD_DIR)traffic_selector.o : $(CONFIG_DIR)traffic_selector.c $(CONFIG_DIR)traffic_selector.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)proposal.o +$(BUILD_DIR)proposal.o : $(CONFIG_DIR)proposal.c $(CONFIG_DIR)proposal.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)configuration.o +$(BUILD_DIR)configuration.o : $(CONFIG_DIR)configuration.c $(CONFIG_DIR)configuration.h + $(CC) $(CFLAGS) -c -o $@ $< + +include $(CONFIG_DIR)connections/Makefile.connections +include $(CONFIG_DIR)credentials/Makefile.credentials +include $(CONFIG_DIR)policies/Makefile.policies \ No newline at end of file diff --git a/src/charon/config/configuration.c b/src/charon/config/configuration.c new file mode 100755 index 000000000..eac1bd43a --- /dev/null +++ b/src/charon/config/configuration.c @@ -0,0 +1,112 @@ +/** + * @file configuration.c + * + * @brief Implementation of configuration_t. + * + */ + +/* + * Copyright (C) 2006 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 + +#include "configuration.h" + +#include + +/** + * First retransmit timeout in milliseconds. + * Timeout value is increasing in each retransmit round. + */ +#define RETRANSMIT_TIMEOUT 3000 + +/** + * Timeout in milliseconds after that a half open IKE_SA gets deleted. + */ +#define HALF_OPEN_IKE_SA_TIMEOUT 30000 + +/** + * Max retransmit count. + * 0 for infinite. The max time a half open IKE_SA is alive is set by + * RETRANSMIT_TIMEOUT. + */ +#define MAX_RETRANSMIT_COUNT 0 + + +typedef struct private_configuration_t private_configuration_t; + +/** + * Private data of an configuration_t object. + */ +struct private_configuration_t { + + /** + * Public part of configuration_t object. + */ + configuration_t public; + +}; + +/** + * Implementation of configuration_t.get_retransmit_timeout. + */ +static status_t get_retransmit_timeout (private_configuration_t *this, u_int32_t retransmit_count, u_int32_t *timeout) +{ + int new_timeout = RETRANSMIT_TIMEOUT, i; + if (retransmit_count > MAX_RETRANSMIT_COUNT && MAX_RETRANSMIT_COUNT != 0) + { + return FAILED; + } + + for (i = 0; i < retransmit_count; i++) + { + new_timeout *= 2; + } + + *timeout = new_timeout; + + return SUCCESS; +} + +/** + * Implementation of configuration_t.get_half_open_ike_sa_timeout. + */ +static u_int32_t get_half_open_ike_sa_timeout (private_configuration_t *this) +{ + return HALF_OPEN_IKE_SA_TIMEOUT; +} + +/** + * Implementation of configuration_t.destroy. + */ +static void destroy(private_configuration_t *this) +{ + free(this); +} + +/* + * Described in header-file + */ +configuration_t *configuration_create() +{ + private_configuration_t *this = malloc_thing(private_configuration_t); + + /* public functions */ + this->public.destroy = (void(*)(configuration_t*))destroy; + this->public.get_retransmit_timeout = (status_t (*) (configuration_t *, u_int32_t retransmit_count, u_int32_t *timeout))get_retransmit_timeout; + this->public.get_half_open_ike_sa_timeout = (u_int32_t (*) (configuration_t *)) get_half_open_ike_sa_timeout; + + return (&this->public); +} diff --git a/src/charon/config/configuration.h b/src/charon/config/configuration.h new file mode 100755 index 000000000..3696215f0 --- /dev/null +++ b/src/charon/config/configuration.h @@ -0,0 +1,89 @@ +/** + * @file configuration.h + * + * @brief Interface configuration_t. + * + */ + +/* + * Copyright (C) 2006 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef CONFIGURATION_H_ +#define CONFIGURATION_H_ + +#include + + +typedef struct configuration_t configuration_t; + +/** + * @brief The interface for various daemon related configs. + * + * @b Constructors: + * - configuration_create() + * + * @ingroup config + */ +struct configuration_t { + + /** + * @brief Returns the retransmit timeout. + * + * The timeout values are managed by the configuration, so + * another backoff algorithm may be implemented here. + * + * @param this calling object + * @param retransmit_count number of times a message was retransmitted so far + * @param[out] timeout the new retransmit timeout in milliseconds + * + * @return + * - FAILED, if the message should not be retransmitted + * - SUCCESS + */ + status_t (*get_retransmit_timeout) (configuration_t *this, u_int32_t retransmit_count, u_int32_t *timeout); + + /** + * @brief Returns the timeout for an half open IKE_SA in ms. + * + * Half open means that the IKE_SA is still in one of the following states: + * - INITIATOR_INIT + * - RESPONDER_INIT + * - IKE_SA_INIT_REQUESTED + * - IKE_SA_INIT_RESPONDED + * - IKE_AUTH_REQUESTED + * + * @param this calling object + * @return timeout in milliseconds (ms) + */ + u_int32_t (*get_half_open_ike_sa_timeout) (configuration_t *this); + + /** + * @brief Destroys a configuration_t object. + * + * @param this calling object + */ + void (*destroy) (configuration_t *this); +}; + +/** + * @brief Creates a configuration backend. + * + * @return static_configuration_t object + * + * @ingroup config + */ +configuration_t *configuration_create(void); + +#endif /*CONFIGURATION_H_*/ diff --git a/src/charon/config/connections/Makefile.connections b/src/charon/config/connections/Makefile.connections new file mode 100644 index 000000000..8fbc983f6 --- /dev/null +++ b/src/charon/config/connections/Makefile.connections @@ -0,0 +1,24 @@ +# Copyright (C) 2006 Martin Willi +# Hochschule fuer Technik Rapperswil +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. See . +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# + +CONNECTIONS_DIR= $(CONFIG_DIR)connections/ + + +CHARON_OBJS+= $(BUILD_DIR)connection.o +$(BUILD_DIR)connection.o : $(CONNECTIONS_DIR)connection.c $(CONNECTIONS_DIR)connection.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)local_connection_store.o +$(BUILD_DIR)local_connection_store.o : $(CONNECTIONS_DIR)local_connection_store.c $(CONNECTIONS_DIR)local_connection_store.h + $(CC) $(CFLAGS) -c -o $@ $< \ No newline at end of file diff --git a/src/charon/config/connections/connection.c b/src/charon/config/connections/connection.c new file mode 100644 index 000000000..74e6762b4 --- /dev/null +++ b/src/charon/config/connections/connection.c @@ -0,0 +1,367 @@ +/** + * @file connection.c + * + * @brief Implementation of connection_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 + +#include "connection.h" + +#include +#include + +/** + * String mappings for auth_method_t. + */ +mapping_t auth_method_m[] = { + {RSA_DIGITAL_SIGNATURE, "RSA"}, + {SHARED_KEY_MESSAGE_INTEGRITY_CODE, "SHARED_KEY"}, + {DSS_DIGITAL_SIGNATURE, "DSS"}, + {MAPPING_END, NULL} +}; + + +typedef struct private_connection_t private_connection_t; + +/** + * Private data of an connection_t object + */ +struct private_connection_t { + + /** + * Public part + */ + connection_t public; + + /** + * Name of the connection + */ + char *name; + + /** + * ID of us + */ + identification_t *my_id; + + /** + * ID of remote peer + */ + identification_t *other_id; + + /** + * Host information of my host. + */ + host_t *my_host; + + /** + * Host information of other host. + */ + host_t *other_host; + + /** + * Method to use for own authentication data + */ + auth_method_t auth_method; + + /** + * Supported proposals + */ + linked_list_t *proposals; +}; + +/** + * Implementation of connection_t.get_name. + */ +static char *get_name (private_connection_t *this) +{ + return this->name; +} + +/** + * Implementation of connection_t.get_my_id. + */ +static identification_t *get_my_id (private_connection_t *this) +{ + return this->my_id; +} + +/** + * Implementation of connection_t.get_other_id. + */ +static identification_t *get_other_id(private_connection_t *this) +{ + return this->other_id; +} + +/** + * Implementation of connection_t.update_my_id + */ +static void update_my_id(private_connection_t *this, identification_t *my_id) +{ + this->my_id->destroy(this->my_id); + this->my_id = my_id; +} + +/** + * Implementation of connection_t.update_other_id + */ +static void update_other_id(private_connection_t *this, identification_t *other_id) +{ + this->other_id->destroy(this->other_id); + this->other_id = other_id; +} + +/** + * Implementation of connection_t.get_my_host. + */ +static host_t * get_my_host (private_connection_t *this) +{ + return this->my_host; +} + +/** + * Implementation of connection_t.update_my_host. + */ +static void update_my_host(private_connection_t *this, host_t *my_host) +{ + this->my_host->destroy(this->my_host); + this->my_host = my_host; +} + +/** + * Implementation of connection_t.update_other_host. + */ +static void update_other_host(private_connection_t *this, host_t *other_host) +{ + this->other_host->destroy(this->other_host); + this->other_host = other_host; +} + +/** + * Implementation of connection_t.get_other_host. + */ +static host_t * get_other_host (private_connection_t *this) +{ + return this->other_host; +} + +/** + * Implementation of connection_t.get_proposals. + */ +static linked_list_t* get_proposals (private_connection_t *this) +{ + return this->proposals; +} + +/** + * Implementation of connection_t.select_proposal. + */ +static proposal_t *select_proposal(private_connection_t *this, linked_list_t *proposals) +{ + iterator_t *stored_iter, *supplied_iter; + proposal_t *stored, *supplied, *selected; + + stored_iter = this->proposals->create_iterator(this->proposals, TRUE); + supplied_iter = proposals->create_iterator(proposals, TRUE); + + /* compare all stored proposals with all supplied. Stored ones are preferred. */ + while (stored_iter->has_next(stored_iter)) + { + supplied_iter->reset(supplied_iter); + stored_iter->current(stored_iter, (void**)&stored); + + while (supplied_iter->has_next(supplied_iter)) + { + supplied_iter->current(supplied_iter, (void**)&supplied); + selected = stored->select(stored, supplied); + if (selected) + { + /* they match, return */ + stored_iter->destroy(stored_iter); + supplied_iter->destroy(supplied_iter); + return selected; + } + } + } + + /* no proposal match :-(, will result in a NO_PROPOSAL_CHOSEN... */ + stored_iter->destroy(stored_iter); + supplied_iter->destroy(supplied_iter); + + return NULL; +} + +/** + * Implementation of connection_t.add_proposal. + */ +static void add_proposal (private_connection_t *this, proposal_t *proposal) +{ + this->proposals->insert_last(this->proposals, proposal); +} + +/** + * Implementation of connection_t.auth_method_t. + */ +static auth_method_t get_auth_method(private_connection_t *this) +{ + return this->auth_method; +} + +/** + * Implementation of connection_t.get_dh_group. + */ +static diffie_hellman_group_t get_dh_group(private_connection_t *this) +{ + iterator_t *iterator; + proposal_t *proposal; + algorithm_t *algo; + + iterator = this->proposals->create_iterator(this->proposals, TRUE); + while (iterator->has_next(iterator)) + { + iterator->current(iterator, (void**)&proposal); + proposal->get_algorithm(proposal, PROTO_IKE, DIFFIE_HELLMAN_GROUP, &algo); + if (algo) + { + iterator->destroy(iterator); + return algo->algorithm; + } + } + iterator->destroy(iterator); + return MODP_UNDEFINED; +} + +/** + * Implementation of connection_t.check_dh_group. + */ +static bool check_dh_group(private_connection_t *this, diffie_hellman_group_t dh_group) +{ + iterator_t *prop_iter, *alg_iter; + proposal_t *proposal; + algorithm_t *algo; + + prop_iter = this->proposals->create_iterator(this->proposals, TRUE); + while (prop_iter->has_next(prop_iter)) + { + prop_iter->current(prop_iter, (void**)&proposal); + alg_iter = proposal->create_algorithm_iterator(proposal, PROTO_IKE, DIFFIE_HELLMAN_GROUP); + while (alg_iter->has_next(alg_iter)) + { + alg_iter->current(alg_iter, (void**)&algo); + if (algo->algorithm == dh_group) + { + prop_iter->destroy(prop_iter); + alg_iter->destroy(alg_iter); + return TRUE; + } + } + } + prop_iter->destroy(prop_iter); + alg_iter->destroy(alg_iter); + return FALSE; +} + +/** + * Implementation of connection_t.clone. + */ +static connection_t *clone(private_connection_t *this) +{ + iterator_t *iterator; + proposal_t *proposal; + private_connection_t *clone = (private_connection_t*)connection_create( + this->name, + this->my_host->clone(this->my_host), + this->other_host->clone(this->other_host), + this->my_id->clone(this->my_id), + this->other_id->clone(this->other_id), + this->auth_method); + + /* clone all proposals */ + iterator = this->proposals->create_iterator(this->proposals, TRUE); + while (iterator->has_next(iterator)) + { + iterator->current(iterator, (void**)&proposal); + proposal = proposal->clone(proposal); + clone->proposals->insert_last(clone->proposals, (void*)proposal); + } + iterator->destroy(iterator); + + return &clone->public; +} + +/** + * Implementation of connection_t.destroy. + */ +static void destroy (private_connection_t *this) +{ + proposal_t *proposal; + + while (this->proposals->remove_last(this->proposals, (void**)&proposal) == SUCCESS) + { + proposal->destroy(proposal); + } + this->proposals->destroy(this->proposals); + + this->my_host->destroy(this->my_host); + this->other_host->destroy(this->other_host); + this->my_id->destroy(this->my_id); + this->other_id->destroy(this->other_id); + free(this->name); + free(this); +} + +/** + * Described in header. + */ +connection_t * connection_create(char *name, host_t *my_host, host_t *other_host, identification_t *my_id, identification_t *other_id, auth_method_t auth_method) +{ + private_connection_t *this = malloc_thing(private_connection_t); + + /* public functions */ + this->public.get_name = (char*(*)(connection_t*))get_name; + this->public.get_my_id = (identification_t*(*)(connection_t*))get_my_id; + this->public.get_other_id = (identification_t*(*)(connection_t*))get_other_id; + this->public.get_my_host = (host_t*(*)(connection_t*))get_my_host; + this->public.update_my_host = (void(*)(connection_t*,host_t*))update_my_host; + this->public.update_other_host = (void(*)(connection_t*,host_t*))update_other_host; + this->public.update_my_id = (void(*)(connection_t*,identification_t*))update_my_id; + this->public.update_other_id = (void(*)(connection_t*,identification_t*))update_other_id; + this->public.get_other_host = (host_t*(*)(connection_t*))get_other_host; + this->public.get_proposals = (linked_list_t*(*)(connection_t*))get_proposals; + this->public.select_proposal = (proposal_t*(*)(connection_t*,linked_list_t*))select_proposal; + this->public.add_proposal = (void(*)(connection_t*, proposal_t*)) add_proposal; + this->public.get_auth_method = (auth_method_t(*)(connection_t*)) get_auth_method; + this->public.get_dh_group = (diffie_hellman_group_t(*)(connection_t*)) get_dh_group; + this->public.check_dh_group = (bool(*)(connection_t*,diffie_hellman_group_t)) check_dh_group; + this->public.clone = (connection_t*(*)(connection_t*))clone; + this->public.destroy = (void(*)(connection_t*))destroy; + + /* private variables */ + this->name = strdup(name); + this->my_host = my_host; + this->other_host = other_host; + this->my_id = my_id; + this->other_id = other_id; + this->auth_method = auth_method; + + this->proposals = linked_list_create(); + + return (&this->public); +} diff --git a/src/charon/config/connections/connection.h b/src/charon/config/connections/connection.h new file mode 100644 index 000000000..2cb3c20b8 --- /dev/null +++ b/src/charon/config/connections/connection.h @@ -0,0 +1,283 @@ +/** + * @file connection.h + * + * @brief Interface of connection_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef CONNECTION_H_ +#define CONNECTION_H_ + +#include +#include +#include +#include +#include +#include + + +typedef enum auth_method_t auth_method_t; + +/** + * AUTH Method to use. + * + * @ingroup config + */ +enum auth_method_t { + /** + * Computed as specified in section 2.15 of RFC using + * an RSA private key over a PKCS#1 padded hash. + */ + RSA_DIGITAL_SIGNATURE = 1, + + /** + * Computed as specified in section 2.15 of RFC using the + * shared key associated with the identity in the ID payload + * and the negotiated prf function + */ + SHARED_KEY_MESSAGE_INTEGRITY_CODE = 2, + + /** + * Computed as specified in section 2.15 of RFC using a + * DSS private key over a SHA-1 hash. + */ + DSS_DIGITAL_SIGNATURE = 3, +}; + +/** + * string mappings for auth method. + * + * @ingroup config + */ +extern mapping_t auth_method_m[]; + + +typedef struct connection_t connection_t; + +/** + * @brief A connection_t defines the rules to set up an IKE_SA. + * + * + * @b Constructors: + * - connection_create() + * + * @ingroup config + */ +struct connection_t { + + /** + * @brief Get my ID for this connection. + * + * Object is NOT getting cloned. + * + * @param this calling object + * @return host information as identification_t object + */ + identification_t *(*get_my_id) (connection_t *this); + + /** + * @brief Get others ID for this connection. + * + * Object is NOT getting cloned. + * + * @param this calling object + * @return host information as identification_t object + */ + identification_t *(*get_other_id) (connection_t *this); + + /** + * @brief Get my address as host_t object. + * + * Object is NOT getting cloned. + * + * @param this calling object + * @return host information as host_t object + */ + host_t *(*get_my_host) (connection_t *this); + + /** + * @brief Get others address as host_t object. + * + * Object is NOT getting cloned. + * + * @param this calling object + * @return host information as host_t object + */ + host_t *(*get_other_host) (connection_t *this); + + /** + * @brief Update address of my host. + * + * It may be necessary to uptdate own address, as it + * is set to the default route (0.0.0.0) in some cases. + * Old host is destroyed, new one NOT cloned. + * + * @param this calling object + * @param my_host new host to set as my_host + */ + void (*update_my_host) (connection_t *this, host_t *my_host); + + /** + * @brief Update address of remote host. + * + * It may be necessary to uptdate remote address, as a + * connection may define %any (0.0.0.0) or a subnet. + * Old host is destroyed, new one NOT cloned. + * + * @param this calling object + * @param my_host new host to set as other_host + */ + void (*update_other_host) (connection_t *this, host_t *other_host); + + /** + * @brief Update own ID. + * + * It may be necessary to uptdate own ID, as it + * is set to %any or to e.g. *@strongswan.org in + * some cases. + * Old ID is destroyed, new one NOT cloned. + * + * @param this calling object + * @param my_id new ID to set as my_id + */ + void (*update_my_id) (connection_t *this, identification_t *my_id); + + /** + * @brief Update others ID. + * + * It may be necessary to uptdate others ID, as it + * is set to %any or to e.g. *@strongswan.org in + * some cases. + * Old ID is destroyed, new one NOT cloned. + * + * @param this calling object + * @param other_id new ID to set as other_id + */ + void (*update_other_id) (connection_t *this, identification_t *other_id); + + /** + * @brief Returns a list of all supported proposals. + * + * Returned list is still owned by connection and MUST NOT + * modified or destroyed. + * + * @param this calling object + * @return list containing all the proposals + */ + linked_list_t *(*get_proposals) (connection_t *this); + + /** + * @brief Adds a proposal to the list. + * + * The first added proposal has the highest priority, the last + * added the lowest. + * + * @param this calling object + * @param proposal proposal to add + */ + void (*add_proposal) (connection_t *this, proposal_t *proposal); + + /** + * @brief Select a proposed from suggested proposals. + * + * Returned proposal must be destroyed after usage. + * + * @param this calling object + * @param proposals list of proposals to select from + * @return selected proposal, or NULL if none matches. + */ + proposal_t *(*select_proposal) (connection_t *this, linked_list_t *proposals); + + /** + * @brief Get the authentication method to use + * + * @param this calling object + * @return authentication method + */ + auth_method_t (*get_auth_method) (connection_t *this); + + /** + * @brief Get the connection name. + * + * Name must not be freed, since it points to + * internal data. + * + * @param this calling object + * @return name of the connection + */ + char* (*get_name) (connection_t *this); + + /** + * @brief Get the DH group to use for connection initialization. + * + * @param this calling object + * @return dh group to use for initialization + */ + diffie_hellman_group_t (*get_dh_group) (connection_t *this); + + /** + * @brief Check if a suggested dh group is acceptable. + * + * If we guess a wrong DH group for IKE_SA_INIT, the other + * peer will send us a offer. But is this acceptable for us? + * + * @param this calling object + * @return TRUE if group acceptable + */ + bool (*check_dh_group) (connection_t *this, diffie_hellman_group_t dh_group); + + /** + * @brief Clone a connection_t object. + * + * @param this connection to clone + * @return clone of it + */ + connection_t *(*clone) (connection_t *this); + + /** + * @brief Destroys a connection_t object. + * + * @param this calling object + */ + void (*destroy) (connection_t *this); +}; + +/** + * @brief Creates a connection_t object. + * + * Supplied hosts/IDs become owned by connection, so + * do not modify or destroy them after a call to + * connection_create(). Name gets cloned internally. + * + * @param name connection identifier + * @param my_host host_t representing local address + * @param other_host host_t representing remote address + * @param my_id identification_t for me + * @param other_id identification_t for other + * @param auth_method Authentication method to use for our(!) auth data + * @return connection_t object. + * + * @ingroup config + */ +connection_t * connection_create(char *name, + host_t *my_host, host_t *other_host, + identification_t *my_id, + identification_t *other_id, + auth_method_t auth_method); + +#endif /* CONNECTION_H_ */ diff --git a/src/charon/config/connections/connection_store.h b/src/charon/config/connections/connection_store.h new file mode 100755 index 000000000..41fd58e42 --- /dev/null +++ b/src/charon/config/connections/connection_store.h @@ -0,0 +1,112 @@ +/** + * @file connection_store.h + * + * @brief Interface connection_store_t. + * + */ + +/* + * Copyright (C) 2006 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef CONNECTION_STORE_H_ +#define CONNECTION_STORE_H_ + +#include +#include + + +typedef struct connection_store_t connection_store_t; + +/** + * @brief The interface for a store of connection_t's. + * + * @b Constructors: + * - stroke_create() + * + * @ingroup config + */ +struct connection_store_t { + + /** + * @brief Returns a connection definition identified by two IDs. + * + * This call is useful to get a connection which is identified by IDs + * rather than addresses, e.g. for connection setup on user request. + * The returned connection gets created/cloned and therefore must + * be destroyed after usage. + * + * @param this calling object + * @param my_id own ID of connection + * @param other_id others ID of connection + * @return + * - connection_t, if found + * - NULL otherwise + */ + connection_t *(*get_connection_by_ids) (connection_store_t *this, identification_t *my_id, identification_t *other_id); + + /** + * @brief Returns a connection definition identified by two hosts. + * + * This call is usefull to get a connection identified by addresses. + * It may be used after kernel request for traffic protection. + * The returned connection gets created/cloned and therefore must + * be destroyed after usage. + * + * @param this calling object + * @param my_id own address of connection + * @param other_id others address of connection + * @return + * - connection_t, if found + * - NULL otherwise + */ + connection_t *(*get_connection_by_hosts) (connection_store_t *this, host_t *my_host, host_t *other_host); + + /** + * @brief Returns a connection identified by its name. + * + * This call is usefull to get a connection identified its + * name, as on an connection setup. + * + * @param this calling object + * @param name name of the connection to get + * @return + * - connection_t, if found + * - NULL otherwise + */ + connection_t *(*get_connection_by_name) (connection_store_t *this, char *name); + + /** + * @brief Add a connection to the store. + * + * After a successful call, the connection is owned by the store and may + * not be manipulated nor destroyed. + * + * @param this calling object + * @param connection connection to add + * @return + * - SUCCESS, or + * - FAILED + */ + status_t (*add_connection) (connection_store_t *this, connection_t *connection); + + /** + * @brief Destroys a connection_store_t object. + * + * @param this calling object + */ + void (*destroy) (connection_store_t *this); +}; + +#endif /* CONNECTION_STORE_H_ */ diff --git a/src/charon/config/connections/local_connection_store.c b/src/charon/config/connections/local_connection_store.c new file mode 100644 index 000000000..0ae18e0a7 --- /dev/null +++ b/src/charon/config/connections/local_connection_store.c @@ -0,0 +1,228 @@ +/** + * @file local_connection_store.c + * + * @brief Implementation of local_connection_store_t. + * + */ + +/* + * Copyright (C) 2006 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 + +#include "local_connection_store.h" + +#include +#include + + +typedef struct private_local_connection_store_t private_local_connection_store_t; + +/** + * Private data of an local_connection_store_t object + */ +struct private_local_connection_store_t { + + /** + * Public part + */ + local_connection_store_t public; + + /** + * stored connection + */ + linked_list_t *connections; + + /** + * Assigned logger + */ + logger_t *logger; +}; + + +/** + * Implementation of connection_store_t.get_connection_by_hosts. + */ +static connection_t *get_connection_by_hosts(private_local_connection_store_t *this, host_t *my_host, host_t *other_host) +{ + iterator_t *iterator; + connection_t *current, *found = NULL; + + this->logger->log(this->logger, CONTROL|LEVEL1, "getting config for hosts %s - %s", + my_host->get_address(my_host), other_host->get_address(other_host)); + + iterator = this->connections->create_iterator(this->connections, TRUE); + while (iterator->has_next(iterator)) + { + host_t *config_my_host, *config_other_host; + + iterator->current(iterator, (void**)¤t); + + config_my_host = current->get_my_host(current); + config_other_host = current->get_other_host(current); + + /* first check if ip is equal */ + if(config_other_host->ip_equals(config_other_host, other_host)) + { + this->logger->log(this->logger, CONTROL|LEVEL2, "config entry with remote host %s", + config_other_host->get_address(config_other_host)); + /* could be right one, check my_host for default route*/ + if (config_my_host->is_default_route(config_my_host)) + { + found = current->clone(current); + break; + } + /* check now if host informations are the same */ + else if (config_my_host->ip_equals(config_my_host,my_host)) + { + found = current->clone(current); + break; + } + + } + /* Then check for wildcard hosts! + * TODO + * actually its only checked if other host with default route can be found! */ + else if (config_other_host->is_default_route(config_other_host)) + { + /* could be right one, check my_host for default route*/ + if (config_my_host->is_default_route(config_my_host)) + { + found = current->clone(current); + break; + } + /* check now if host informations are the same */ + else if (config_my_host->ip_equals(config_my_host,my_host)) + { + found = current->clone(current); + break; + } + } + } + iterator->destroy(iterator); + + /* apply hosts as they are supplied since my_host may be %defaultroute, and other_host may be %any. */ + if (found) + { + found->update_my_host(found, my_host->clone(my_host)); + found->update_other_host(found, other_host->clone(other_host)); + } + + return found; +} + +/** + * Implementation of connection_store_t.get_connection_by_ids. + */ +static connection_t *get_connection_by_ids(private_local_connection_store_t *this, identification_t *my_id, identification_t *other_id) +{ + iterator_t *iterator; + connection_t *current, *found = NULL; + + this->logger->log(this->logger, CONTROL|LEVEL1, "getting config for ids %s - %s", + my_id->get_string(my_id), other_id->get_string(other_id)); + + iterator = this->connections->create_iterator(this->connections, TRUE); + while (iterator->has_next(iterator)) + { + identification_t *config_my_id, *config_other_id; + + iterator->current(iterator, (void**)¤t); + + config_my_id = current->get_my_id(current); + config_other_id = current->get_other_id(current); + + /* first check if ids are equal + * TODO: Add wildcard checks */ + if (config_other_id->equals(config_other_id, other_id) && + config_my_id->equals(config_my_id, my_id)) + { + this->logger->log(this->logger, CONTROL|LEVEL2, "config entry with remote id %s", + config_other_id->get_string(config_other_id)); + found = current->clone(current); + break; + } + } + iterator->destroy(iterator); + + return found; +} + +/** + * Implementation of connection_store_t.get_connection_by_name. + */ +static connection_t *get_connection_by_name(private_local_connection_store_t *this, char *name) +{ + iterator_t *iterator; + connection_t *current, *found = NULL; + + iterator = this->connections->create_iterator(this->connections, TRUE); + while (iterator->has_next(iterator)) + { + iterator->current(iterator, (void**)¤t); + if (strcmp(name, current->get_name(current)) == 0) + { + found = current->clone(current); + break; + } + } + iterator->destroy(iterator); + + return found; +} + +/** + * Implementation of connection_store_t.add_connection. + */ +static status_t add_connection(private_local_connection_store_t *this, connection_t *connection) +{ + this->connections->insert_last(this->connections, connection); + return SUCCESS; +} + +/** + * Implementation of connection_store_t.destroy. + */ +static void destroy (private_local_connection_store_t *this) +{ + connection_t *connection; + + while (this->connections->remove_last(this->connections, (void**)&connection) == SUCCESS) + { + connection->destroy(connection); + } + this->connections->destroy(this->connections); + free(this); +} + +/** + * Described in header. + */ +local_connection_store_t * local_connection_store_create(void) +{ + private_local_connection_store_t *this = malloc_thing(private_local_connection_store_t); + + this->public.connection_store.get_connection_by_hosts = (connection_t*(*)(connection_store_t*,host_t*,host_t*))get_connection_by_hosts; + this->public.connection_store.get_connection_by_ids = (connection_t*(*)(connection_store_t*,identification_t*,identification_t*))get_connection_by_ids; + this->public.connection_store.get_connection_by_name = (connection_t*(*)(connection_store_t*,char*))get_connection_by_name; + this->public.connection_store.add_connection = (status_t(*)(connection_store_t*,connection_t*))add_connection; + this->public.connection_store.destroy = (void(*)(connection_store_t*))destroy; + + /* private variables */ + this->connections = linked_list_create(); + this->logger = logger_manager->get_logger(logger_manager, CONFIG); + + return (&this->public); +} diff --git a/src/charon/config/connections/local_connection_store.h b/src/charon/config/connections/local_connection_store.h new file mode 100644 index 000000000..6e73ef945 --- /dev/null +++ b/src/charon/config/connections/local_connection_store.h @@ -0,0 +1,63 @@ +/** + * @file local_connection_store.h + * + * @brief Interface of local_connection_store_t. + * + */ + +/* + * Copyright (C) 2006 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef LOCAL_CONNECTION_H_ +#define LOCAL_CONNECTION_H_ + +#include +#include + + +typedef struct local_connection_store_t local_connection_store_t; + +/** + * @brief A connection_store_t implementation using a simple connection list. + * + * The local_connection_store_t class implements the connection_store_t interface + * as simple as possible. connection_t's are stored in an in-memory list. + * + * @b Constructors: + * - local_connection_store_create() + * + * @todo Make thread-save first + * @todo Add remove_connection method + * + * @ingroup config + */ +struct local_connection_store_t { + + /** + * Implements connection_store_t interface + */ + connection_store_t connection_store; +}; + +/** + * @brief Creates a local_connection_store_t instance. + * + * @return connection store instance. + * + * @ingroup config + */ +local_connection_store_t * local_connection_store_create(void); + +#endif /* LOCAL_CONNECTION_H_ */ diff --git a/src/charon/config/credentials/Makefile.credentials b/src/charon/config/credentials/Makefile.credentials new file mode 100644 index 000000000..720d56656 --- /dev/null +++ b/src/charon/config/credentials/Makefile.credentials @@ -0,0 +1,20 @@ +# Copyright (C) 2006 Martin Willi +# Hochschule fuer Technik Rapperswil +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. See . +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# + +CREDENTIALS_DIR= $(CONFIG_DIR)credentials/ + + +CHARON_OBJS+= $(BUILD_DIR)local_credential_store.o +$(BUILD_DIR)local_credential_store.o : $(CREDENTIALS_DIR)local_credential_store.c $(CREDENTIALS_DIR)local_credential_store.h + $(CC) $(CFLAGS) -c -o $@ $< diff --git a/src/charon/config/credentials/credential_store.h b/src/charon/config/credentials/credential_store.h new file mode 100755 index 000000000..2339469c0 --- /dev/null +++ b/src/charon/config/credentials/credential_store.h @@ -0,0 +1,91 @@ +/** + * @file credential_store.h + * + * @brief Interface credential_store_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef CREDENTIAL_STORE_H_ +#define CREDENTIAL_STORE_H_ + +#include +#include +#include +#include + + +typedef struct credential_store_t credential_store_t; + +/** + * @brief The interface for a credential_store backend. + * + * @b Constructors: + * - stroke_create() + * + * @ingroup config + */ +struct credential_store_t { + + /** + * @brief Returns the preshared secret of a specific ID. + * + * The returned chunk must be destroyed by the caller after usage. + * + * @param this calling object + * @param identification identification_t object identifiying the secret. + * @param[out] preshared_secret the preshared secret will be written there. + * @return + * - NOT_FOUND if no preshared secrets for specific ID could be found + * - SUCCESS + * + * @todo We should use two IDs to query shared secrets, since we want to use different + * keys for different peers... + */ + status_t (*get_shared_secret) (credential_store_t *this, identification_t *identification, chunk_t *preshared_secret); + + /** + * @brief Returns the RSA public key of a specific ID. + * + * The returned rsa_public_key_t must be destroyed by the caller after usage. + * + * @param this calling object + * @param identification identification_t object identifiying the key. + * @return public key, or NULL if not found + */ + rsa_public_key_t * (*get_rsa_public_key) (credential_store_t *this, identification_t *identification); + + /** + * @brief Returns the RSA private key of a specific ID. + * + * The returned rsa_private_key_t must be destroyed by the caller after usage. + * + * @param this calling object + * @param identification identification_t object identifiying the key + * @return private key, or NULL if not found + */ + rsa_private_key_t *(*get_rsa_private_key) (credential_store_t *this, identification_t *identification); + + /** + * @brief Destroys a credential_store_t object. + * + * @param this calling object + */ + void (*destroy) (credential_store_t *this); +}; + +#endif /*CREDENTIAL_STORE_H_*/ diff --git a/src/charon/config/credentials/local_credential_store.c b/src/charon/config/credentials/local_credential_store.c new file mode 100644 index 000000000..2554eec4a --- /dev/null +++ b/src/charon/config/credentials/local_credential_store.c @@ -0,0 +1,381 @@ +/** + * @file local_credential_store.c + * + * @brief Implementation of local_credential_store_t. + * + */ + +/* + * Copyright (C) 2006 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 +#include +#include + +#include "local_credential_store.h" + +#include +#include +#include +#include + +#define PATH_BUF 256 + +typedef struct key_entry_t key_entry_t; + +/** + * Private key with an associated ID to find it + */ +struct key_entry_t { + + /** + * ID, as added + */ + identification_t *id; + + /** + * Associated rsa private key + */ + rsa_private_key_t *key; +}; + + +typedef struct private_local_credential_store_t private_local_credential_store_t; + +/** + * Private data of an local_credential_store_t object + */ +struct private_local_credential_store_t { + + /** + * Public part + */ + local_credential_store_t public; + + /** + * list of key_entry_t's with private keys + */ + linked_list_t *private_keys; + + /** + * list of x509 certificates with public keys + */ + linked_list_t *certificates; + + /** + * Assigned logger + */ + logger_t *logger; +}; + + +/** + * Implementation of credential_store_t.get_shared_secret. + */ +static status_t get_shared_secret(private_local_credential_store_t *this, identification_t *identification, chunk_t *preshared_secret) +{ + return FAILED; +} + +/** + * Implementation of credential_store_t.get_rsa_public_key. + */ +static rsa_public_key_t * get_rsa_public_key(private_local_credential_store_t *this, identification_t *identification) +{ + x509_t *current; + rsa_public_key_t *found = NULL; + iterator_t *iterator; + + this->logger->log(this->logger, CONTROL|LEVEL2, "Looking for public key for %s", + identification->get_string(identification)); + iterator = this->certificates->create_iterator(this->certificates, TRUE); + while (iterator->has_next(iterator)) + { + iterator->current(iterator, (void**)¤t); + identification_t *stored = current->get_subject(current); + this->logger->log(this->logger, CONTROL|LEVEL2, "there is one for %s", + stored->get_string(stored)); + if (identification->equals(identification, stored)) + { + found = current->get_public_key(current); + break; + } + } + iterator->destroy(iterator); + return found; +} + +/** + * Implementation of credential_store_t.get_rsa_private_key. + */ +static rsa_private_key_t *get_rsa_private_key(private_local_credential_store_t *this, identification_t *identification) +{ + rsa_private_key_t *found = NULL; + key_entry_t *current; + iterator_t *iterator; + + iterator = this->private_keys->create_iterator(this->private_keys, TRUE); + while (iterator->has_next(iterator)) + { + iterator->current(iterator, (void**)¤t); + if (identification->equals(identification, current->id)) + { + found = current->key->clone(current->key); + break; + } + } + iterator->destroy(iterator); + return found; +} + +/** + * Implements local_credential_store_t.load_certificates + */ +static void load_certificates(private_local_credential_store_t *this, const char *path) +{ + struct dirent* entry; + struct stat stb; + DIR* dir; + x509_t *cert; + + dir = opendir(path); + if (dir == NULL) { + this->logger->log(this->logger, ERROR, "error opening certificate directory \"%s\"", path); + return; + } + while ((entry = readdir(dir)) != NULL) + { + char file[PATH_BUF]; + + snprintf(file, sizeof(file), "%s/%s", path, entry->d_name); + + if (stat(file, &stb) == -1) + { + continue; + } + /* try to parse all regular files */ + if (stb.st_mode & S_IFREG) + { + cert = x509_create_from_file(file); + if (cert) + { + this->certificates->insert_last(this->certificates, (void*)cert); + } + else + { + this->logger->log(this->logger, ERROR, "certificate \"%s\" invalid, skipped", file); + } + } + } + closedir(dir); +} + +/** + * Query the ID for a private key, by doing a lookup in the certificates + */ +static identification_t *get_id_for_private_key(private_local_credential_store_t *this, rsa_private_key_t *private_key) +{ + iterator_t *iterator; + x509_t *cert; + identification_t *found = NULL; + rsa_public_key_t *public_key; + + this->logger->log(this->logger, CONTROL|LEVEL2, "Getting ID for a private key..."); + + iterator = this->certificates->create_iterator(this->certificates, TRUE); + while (!found && iterator->has_next(iterator)) + { + iterator->current(iterator, (void**)&cert); + public_key = cert->get_public_key(cert); + if (public_key) + { + if (private_key->belongs_to(private_key, public_key)) + { + this->logger->log(this->logger, CONTROL|LEVEL2, "found a match"); + found = cert->get_subject(cert); + found = found->clone(found); + } + else + { + this->logger->log(this->logger, CONTROL|LEVEL3, "this one did not match"); + } + public_key->destroy(public_key); + } + } + iterator->destroy(iterator); + return found; +} + +/** + * Implements local_credential_store_t.load_private_keys + */ +static void load_private_keys(private_local_credential_store_t *this, const char *secretsfile, const char *defaultpath) +{ + FILE *fd = fopen(secretsfile, "r"); + + if (fd) + { + int bytes; + int line_nr = 0; + chunk_t chunk, src, line; + + this->logger->log(this->logger, CONTROL, "loading secrets from \"%s\"", secretsfile); + + fseek(fd, 0, SEEK_END); + chunk.len = ftell(fd); + rewind(fd); + chunk.ptr = malloc(chunk.len); + bytes = fread(chunk.ptr, 1, chunk.len, fd); + fclose(fd); + + src = chunk; + + while (fetchline(&src, &line)) + { + chunk_t ids, token; + + line_nr++; + + if (!eat_whitespace(&line)) + { + continue; + } + if (!extract_token(&ids, ':', &line)) + { + this->logger->log(this->logger, ERROR, "line %d: missing ':' separator", line_nr); + goto error; + } + if (!eat_whitespace(&line) || !extract_token(&token, ' ', &line)) + { + this->logger->log(this->logger, ERROR, "line %d: missing token", line_nr); + goto error; + } + if (match("RSA", &token)) + { + char path[PATH_BUF]; + chunk_t filename; + + err_t ugh = extract_value(&filename, &line); + + if (ugh != NULL) + { + this->logger->log(this->logger, ERROR, "line %d: %s", line_nr, ugh); + goto error; + } + if (filename.len == 0) + { + this->logger->log(this->logger, ERROR, + "line %d: empty filename", line_nr); + goto error; + } + if (*filename.ptr == '/') + { + /* absolute path name */ + snprintf(path, sizeof(path), "%.*s", filename.len, filename.ptr); + } + else + { + /* relative path name */ + snprintf(path, sizeof(path), "%s/%.*s", defaultpath, filename.len, filename.ptr); + } + + rsa_private_key_t *key = rsa_private_key_create_from_file(path, NULL); + if (key) + { + key_entry_t *entry; + identification_t *id = get_id_for_private_key(this, key); + + if (!id) + { + this->logger->log(this->logger, ERROR, + "no certificate found for private key \"%s\", skipped", path); + key->destroy(key); + continue; + } + entry = malloc_thing(key_entry_t); + entry->key = key; + entry->id = id; + this->private_keys->insert_last(this->private_keys, (void*)entry); + } + } + else if (match("PSK", &token)) + { + + } + else if (match("PIN", &token)) + { + + } + else + { + this->logger->log(this->logger, ERROR, + "line %d: token must be either RSA, PSK, or PIN", + line_nr, token.len); + goto error; + } + } +error: + free(chunk.ptr); + } + else + { + this->logger->log(this->logger, ERROR, "could not open file '%s'", secretsfile); + } +} + +/** + * Implementation of credential_store_t.destroy. + */ +static void destroy(private_local_credential_store_t *this) +{ + x509_t *certificate; + key_entry_t *key_entry; + + while (this->certificates->remove_last(this->certificates, (void**)&certificate) == SUCCESS) + { + certificate->destroy(certificate); + } + this->certificates->destroy(this->certificates); + while (this->private_keys->remove_last(this->private_keys, (void**)&key_entry) == SUCCESS) + { + key_entry->id->destroy(key_entry->id); + key_entry->key->destroy(key_entry->key); + free(key_entry); + } + this->private_keys->destroy(this->private_keys); + free(this); +} + +/** + * Described in header. + */ +local_credential_store_t * local_credential_store_create(void) +{ + private_local_credential_store_t *this = malloc_thing(private_local_credential_store_t); + + this->public.credential_store.get_shared_secret = (status_t(*)(credential_store_t*,identification_t*,chunk_t*))get_shared_secret; + this->public.credential_store.get_rsa_private_key = (rsa_private_key_t*(*)(credential_store_t*,identification_t*))get_rsa_private_key; + this->public.credential_store.get_rsa_public_key = (rsa_public_key_t*(*)(credential_store_t*,identification_t*))get_rsa_public_key; + this->public.load_certificates = (void(*)(local_credential_store_t*,const char*))load_certificates; + this->public.load_private_keys = (void(*)(local_credential_store_t*,const char*, const char*))load_private_keys; + this->public.credential_store.destroy = (void(*)(credential_store_t*))destroy; + + /* private variables */ + this->private_keys = linked_list_create(); + this->certificates = linked_list_create(); + this->logger = logger_manager->get_logger(logger_manager, CONFIG); + + return (&this->public); +} diff --git a/src/charon/config/credentials/local_credential_store.h b/src/charon/config/credentials/local_credential_store.h new file mode 100644 index 000000000..81b7568d7 --- /dev/null +++ b/src/charon/config/credentials/local_credential_store.h @@ -0,0 +1,85 @@ +/** + * @file local_credential_store.h + * + * @brief Interface of local_credential_store_t. + * + */ + +/* + * Copyright (C) 2006 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef LOCAL_CREDENTIAL_H_ +#define LOCAL_CREDENTIAL_H_ + +#include +#include + + +typedef struct local_credential_store_t local_credential_store_t; + +/** + * @brief A credential_store_t implementation using simple credentail lists. + * + * The local_credential_store_t class implements the credential_store_t interface + * as simple as possible. The credentials are stored in lists, and can be loaded + * from folders. + * Shared secret are not handled yet, so get_shared_secret always returns NOT_FOUND. + * + * @b Constructors: + * - local_credential_store_create() + * + * @ingroup config + */ +struct local_credential_store_t { + + /** + * Implements credential_store_t interface + */ + credential_store_t credential_store; + + /** + * @brief Loads trusted certificates from a folder. + * + * Currently, all keys must be in binary DER format. + * + * @param this calling object + * @param path directory to load certificates from + */ + void (*load_certificates) (local_credential_store_t *this, const char *path); + + /** + * @brief Loads RSA private keys from a folder. + * + * Currently, all keys must be unencrypted in binary DER format. Anything + * other gets ignored. Further, a certificate for the specific private + * key must already be loaded to get the ID from. + * + * @param this calling object + * @param secretsfile file where secrets are stored + * @param defaultpath default directory for private keys + */ + void (*load_private_keys) (local_credential_store_t *this, const char *secretsfile, const char *defaultpath); +}; + +/** + * @brief Creates a local_credential_store_t instance. + * + * @return credential store instance. + * + * @ingroup config + */ +local_credential_store_t *local_credential_store_create(void); + +#endif /* LOCAL_CREDENTIAL_H_ */ diff --git a/src/charon/config/policies/Makefile.policies b/src/charon/config/policies/Makefile.policies new file mode 100644 index 000000000..e7ed8ab13 --- /dev/null +++ b/src/charon/config/policies/Makefile.policies @@ -0,0 +1,24 @@ +# Copyright (C) 2006 Martin Willi +# Hochschule fuer Technik Rapperswil +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. See . +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# + +POLICIES_DIR= $(CONFIG_DIR)policies/ + + +CHARON_OBJS+= $(BUILD_DIR)policy.o +$(BUILD_DIR)policy.o : $(POLICIES_DIR)policy.c $(POLICIES_DIR)policy.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)local_policy_store.o +$(BUILD_DIR)local_policy_store.o : $(POLICIES_DIR)local_policy_store.c $(POLICIES_DIR)local_policy_store.h + $(CC) $(CFLAGS) -c -o $@ $< \ No newline at end of file diff --git a/src/charon/config/policies/local_policy_store.c b/src/charon/config/policies/local_policy_store.c new file mode 100644 index 000000000..24d22f485 --- /dev/null +++ b/src/charon/config/policies/local_policy_store.c @@ -0,0 +1,136 @@ +/** + * @file local_policy_store.c + * + * @brief Implementation of local_policy_store_t. + * + */ + +/* + * Copyright (C) 2006 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 "local_policy_store.h" + +#include +#include + + +typedef struct private_local_policy_store_t private_local_policy_store_t; + +/** + * Private data of an local_policy_store_t object + */ +struct private_local_policy_store_t { + + /** + * Public part + */ + local_policy_store_t public; + + /** + * list of policy_t's + */ + linked_list_t *policies; + + /** + * Assigned logger + */ + logger_t *logger; +}; + +/** + * Implementation of policy_store_t.add_policy. + */ +static void add_policy(private_local_policy_store_t *this, policy_t *policy) +{ + this->policies->insert_last(this->policies, (void*)policy); +} + + +/** + * Implementation of policy_store_t.get_policy. + */ +static policy_t *get_policy(private_local_policy_store_t *this, identification_t *my_id, identification_t *other_id) +{ + iterator_t *iterator; + policy_t *current, *found = NULL; + + this->logger->log(this->logger, CONTROL|LEVEL1, "Looking for policy for IDs %s - %s", + my_id ? my_id->get_string(my_id) : "%any", + other_id->get_string(other_id)); + iterator = this->policies->create_iterator(this->policies, TRUE); + while (iterator->has_next(iterator)) + { + iterator->current(iterator, (void **)¤t); + identification_t *config_my_id = current->get_my_id(current); + identification_t *config_other_id = current->get_other_id(current); + + this->logger->log(this->logger, CONTROL|LEVEL2, "Found one for %s - %s", + config_my_id->get_string(config_my_id), + config_other_id->get_string(config_other_id)); + + /* check other host first */ + if (other_id->belongs_to(other_id, config_other_id)) + { + /* get it if my_id not specified */ + if (my_id->belongs_to(my_id, config_my_id)) + { + found = current->clone(current); + break; + } + } + } + iterator->destroy(iterator); + + /* apply IDs as they are requsted, since they may be configured as %any or such */ + if (found) + { + found->update_my_id(found, my_id->clone(my_id)); + found->update_other_id(found, other_id->clone(other_id)); + } + return found; +} + +/** + * Implementation of policy_store_t.destroy. + */ +static void destroy(private_local_policy_store_t *this) +{ + policy_t *policy; + + while (this->policies->remove_last(this->policies, (void**)&policy) == SUCCESS) + { + policy->destroy(policy); + } + this->policies->destroy(this->policies); + free(this); +} + +/** + * Described in header. + */ +local_policy_store_t *local_policy_store_create(void) +{ + private_local_policy_store_t *this = malloc_thing(private_local_policy_store_t); + + this->public.policy_store.add_policy = (void(*)(policy_store_t*,policy_t*))add_policy; + this->public.policy_store.get_policy = (policy_t*(*)(policy_store_t*,identification_t*,identification_t*))get_policy; + this->public.policy_store.destroy = (void(*)(policy_store_t*))destroy; + + /* private variables */ + this->policies = linked_list_create(); + this->logger = logger_manager->get_logger(logger_manager, CONFIG); + + return (&this->public); +} diff --git a/src/charon/config/policies/local_policy_store.h b/src/charon/config/policies/local_policy_store.h new file mode 100644 index 000000000..ce9b33d71 --- /dev/null +++ b/src/charon/config/policies/local_policy_store.h @@ -0,0 +1,60 @@ +/** + * @file local_policy_store.h + * + * @brief Interface of local_policy_store_t. + * + */ + +/* + * Copyright (C) 2006 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef LOCAL_POLICY_STORE_H_ +#define LOCAL_POLICY_STORE_H_ + +#include +#include + + +typedef struct local_policy_store_t local_policy_store_t; + +/** + * @brief A policy_store_t implementation using a simple policy lists. + * + * The local_policy_store_t class implements the policy_store_t interface + * as simple as possible. The policies are stored in a in-memory list. + * + * @b Constructors: + * - local_policy_store_create() + * + * @ingroup config + */ +struct local_policy_store_t { + + /** + * Implements policy_store_t interface + */ + policy_store_t policy_store; +}; + +/** + * @brief Creates a local_policy_store_t instance. + * + * @return policy store instance. + * + * @ingroup config + */ +local_policy_store_t *local_policy_store_create(void); + +#endif /* LOCAL_POLICY_STORE_H_ */ diff --git a/src/charon/config/policies/policy.c b/src/charon/config/policies/policy.c new file mode 100644 index 000000000..cff87fc6b --- /dev/null +++ b/src/charon/config/policies/policy.c @@ -0,0 +1,397 @@ +/** + * @file policy.c + * + * @brief Implementation of policy_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 "policy.h" + +#include +#include +#include + +typedef struct private_policy_t private_policy_t; + +/** + * Private data of an policy_t object + */ +struct private_policy_t { + + /** + * Public part + */ + policy_t public; + + /** + * id to use to identify us + */ + identification_t *my_id; + + /** + * allowed id for other + */ + identification_t *other_id; + + /** + * list for all proposals + */ + linked_list_t *proposals; + + /** + * list for traffic selectors for my site + */ + linked_list_t *my_ts; + + /** + * list for traffic selectors for others site + */ + linked_list_t *other_ts; + + /** + * select_traffic_selectors for both + */ + linked_list_t *(*select_traffic_selectors) (private_policy_t *,linked_list_t*,linked_list_t*); +}; + +/** + * Implementation of policy_t.get_my_id + */ +static identification_t *get_my_id(private_policy_t *this) +{ + return this->my_id; +} + +/** + * Implementation of policy_t.get_other_id + */ +static identification_t *get_other_id(private_policy_t *this) +{ + return this->other_id; +} + +/** + * Implementation of policy_t.update_my_id + */ +static void update_my_id(private_policy_t *this, identification_t *my_id) +{ + this->my_id->destroy(this->my_id); + this->my_id = my_id; +} + +/** + * Implementation of policy_t.update_other_id + */ +static void update_other_id(private_policy_t *this, identification_t *other_id) +{ + this->other_id->destroy(this->other_id); + this->other_id = other_id; +} + +/** + * Helper function which does the work for policy_t.update_my_ts and update_other_ts + */ +static void update_ts(linked_list_t* list, host_t *new_host) +{ + traffic_selector_t *ts; + iterator_t *iterator; + + iterator = list->create_iterator(list, TRUE); + while (iterator->has_next(iterator)) + { + iterator->current(iterator, (void**)&ts); + ts->update_address_range(ts, new_host); + } + iterator->destroy(iterator); +} + +/** + * Implementation of policy_t.update_my_id + */ +static void update_my_ts(private_policy_t *this, host_t *my_host) +{ + update_ts(this->my_ts, my_host); +} + +/** + * Implementation of policy_t.update_other_ts + */ +static void update_other_ts(private_policy_t *this, host_t *my_host) +{ + update_ts(this->other_ts, my_host); +} + +/** + * Implementation of policy_t.get_my_traffic_selectors + */ +static linked_list_t *get_my_traffic_selectors(private_policy_t *this) +{ + return this->my_ts; +} + +/** + * Implementation of policy_t.get_other_traffic_selectors + */ +static linked_list_t *get_other_traffic_selectors(private_policy_t *this, traffic_selector_t **traffic_selectors[]) +{ + return this->other_ts; +} + +/** + * Implementation of private_policy_t.select_my_traffic_selectors + */ +static linked_list_t *select_my_traffic_selectors(private_policy_t *this, linked_list_t *supplied) +{ + return this->select_traffic_selectors(this, this->my_ts, supplied); +} + +/** + * Implementation of private_policy_t.select_other_traffic_selectors + */ +static linked_list_t *select_other_traffic_selectors(private_policy_t *this, linked_list_t *supplied) +{ + return this->select_traffic_selectors(this, this->other_ts, supplied); +} +/** + * Implementation of private_policy_t.select_traffic_selectors + */ +static linked_list_t *select_traffic_selectors(private_policy_t *this, linked_list_t *stored, linked_list_t *supplied) +{ + iterator_t *supplied_iter, *stored_iter; + traffic_selector_t *supplied_ts, *stored_ts, *selected_ts; + linked_list_t *selected = linked_list_create(); + + + stored_iter = stored->create_iterator(stored, TRUE); + supplied_iter = supplied->create_iterator(supplied, TRUE); + + /* iterate over all stored selectors */ + while (stored_iter->has_next(stored_iter)) + { + stored_iter->current(stored_iter, (void**)&stored_ts); + + supplied_iter->reset(supplied_iter); + /* iterate over all supplied traffic selectors */ + while (supplied_iter->has_next(supplied_iter)) + { + supplied_iter->current(supplied_iter, (void**)&supplied_ts); + + selected_ts = stored_ts->get_subset(stored_ts, supplied_ts); + if (selected_ts) + { + /* got a match, add to list */ + selected->insert_last(selected, (void*)selected_ts); + } + } + } + stored_iter->destroy(stored_iter); + supplied_iter->destroy(supplied_iter); + + return selected; +} + +/** + * Implementation of policy_t.get_proposal_iterator + */ +static linked_list_t *get_proposals(private_policy_t *this) +{ + return this->proposals; +} + +/** + * Implementation of policy_t.select_proposal + */ +static proposal_t *select_proposal(private_policy_t *this, linked_list_t *proposals) +{ + iterator_t *stored_iter, *supplied_iter; + proposal_t *stored, *supplied, *selected; + + stored_iter = this->proposals->create_iterator(this->proposals, TRUE); + supplied_iter = proposals->create_iterator(proposals, TRUE); + + /* compare all stored proposals with all supplied. Stored ones are preferred. */ + while (stored_iter->has_next(stored_iter)) + { + supplied_iter->reset(supplied_iter); + stored_iter->current(stored_iter, (void**)&stored); + + while (supplied_iter->has_next(supplied_iter)) + { + supplied_iter->current(supplied_iter, (void**)&supplied); + selected = stored->select(stored, supplied); + if (selected) + { + /* they match, return */ + stored_iter->destroy(stored_iter); + supplied_iter->destroy(supplied_iter); + return selected; + } + } + } + + /* no proposal match :-(, will result in a NO_PROPOSAL_CHOSEN... */ + stored_iter->destroy(stored_iter); + supplied_iter->destroy(supplied_iter); + + return NULL; +} + +/** + * Implementation of policy_t.add_my_traffic_selector + */ +static void add_my_traffic_selector(private_policy_t *this, traffic_selector_t *traffic_selector) +{ + this->my_ts->insert_last(this->my_ts, (void*)traffic_selector); +} + +/** + * Implementation of policy_t.add_other_traffic_selector + */ +static void add_other_traffic_selector(private_policy_t *this, traffic_selector_t *traffic_selector) +{ + this->other_ts->insert_last(this->other_ts, (void*)traffic_selector); +} + +/** + * Implementation of policy_t.add_proposal + */ +static void add_proposal(private_policy_t *this, proposal_t *proposal) +{ + this->proposals->insert_last(this->proposals, (void*)proposal); +} + +/** + * Implements policy_t.destroy. + */ +static status_t destroy(private_policy_t *this) +{ + proposal_t *proposal; + traffic_selector_t *traffic_selector; + + + /* delete proposals */ + while(this->proposals->remove_last(this->proposals, (void**)&proposal) == SUCCESS) + { + proposal->destroy(proposal); + } + this->proposals->destroy(this->proposals); + + /* delete traffic selectors */ + while(this->my_ts->remove_last(this->my_ts, (void**)&traffic_selector) == SUCCESS) + { + traffic_selector->destroy(traffic_selector); + } + this->my_ts->destroy(this->my_ts); + + /* delete traffic selectors */ + while(this->other_ts->remove_last(this->other_ts, (void**)&traffic_selector) == SUCCESS) + { + traffic_selector->destroy(traffic_selector); + } + this->other_ts->destroy(this->other_ts); + + /* delete ids */ + this->my_id->destroy(this->my_id); + this->other_id->destroy(this->other_id); + + free(this); + return SUCCESS; +} + +/** + * Implements policy_t.clone. + */ +static policy_t *clone(private_policy_t *this) +{ + private_policy_t *clone = (private_policy_t*)policy_create(this->my_id->clone(this->my_id), + this->other_id->clone(this->other_id)); + iterator_t *iterator; + proposal_t *proposal; + traffic_selector_t *ts; + + /* clone all proposals */ + iterator = this->proposals->create_iterator(this->proposals, TRUE); + while (iterator->has_next(iterator)) + { + iterator->current(iterator, (void**)&proposal); + proposal = proposal->clone(proposal); + clone->proposals->insert_last(clone->proposals, (void*)proposal); + } + iterator->destroy(iterator); + + /* clone all local traffic selectors */ + iterator = this->my_ts->create_iterator(this->my_ts, TRUE); + while (iterator->has_next(iterator)) + { + iterator->current(iterator, (void**)&ts); + ts = ts->clone(ts); + clone->my_ts->insert_last(clone->my_ts, (void*)ts); + } + iterator->destroy(iterator); + + /* clone all remote traffic selectors */ + iterator = this->other_ts->create_iterator(this->other_ts, TRUE); + while (iterator->has_next(iterator)) + { + iterator->current(iterator, (void**)&ts); + ts = ts->clone(ts); + clone->other_ts->insert_last(clone->other_ts, (void*)ts); + } + iterator->destroy(iterator); + + return &clone->public; +} + +/* + * Described in header-file + */ +policy_t *policy_create(identification_t *my_id, identification_t *other_id) +{ + private_policy_t *this = malloc_thing(private_policy_t); + + /* public functions */ + this->public.get_my_id = (identification_t*(*)(policy_t*))get_my_id; + this->public.get_other_id = (identification_t*(*)(policy_t*))get_other_id; + this->public.update_my_id = (void(*)(policy_t*,identification_t*))update_my_id; + this->public.update_other_id = (void(*)(policy_t*,identification_t*))update_other_id; + this->public.update_my_ts = (void(*)(policy_t*,host_t*))update_my_ts; + this->public.update_other_ts = (void(*)(policy_t*,host_t*))update_other_ts; + this->public.get_my_traffic_selectors = (linked_list_t*(*)(policy_t*))get_my_traffic_selectors; + this->public.select_my_traffic_selectors = (linked_list_t*(*)(policy_t*,linked_list_t*))select_my_traffic_selectors; + this->public.get_other_traffic_selectors = (linked_list_t*(*)(policy_t*))get_other_traffic_selectors; + this->public.select_other_traffic_selectors = (linked_list_t*(*)(policy_t*,linked_list_t*))select_other_traffic_selectors; + this->public.get_proposals = (linked_list_t*(*)(policy_t*))get_proposals; + this->public.select_proposal = (proposal_t*(*)(policy_t*,linked_list_t*))select_proposal; + this->public.add_my_traffic_selector = (void(*)(policy_t*,traffic_selector_t*))add_my_traffic_selector; + this->public.add_other_traffic_selector = (void(*)(policy_t*,traffic_selector_t*))add_other_traffic_selector; + this->public.add_proposal = (void(*)(policy_t*,proposal_t*))add_proposal; + this->public.clone = (policy_t*(*)(policy_t*))clone; + this->public.destroy = (void(*)(policy_t*))destroy; + + /* apply init values */ + this->my_id = my_id; + this->other_id = other_id; + + /* init private members*/ + this->select_traffic_selectors = select_traffic_selectors; + this->proposals = linked_list_create(); + this->my_ts = linked_list_create(); + this->other_ts = linked_list_create(); + + return (&this->public); +} diff --git a/src/charon/config/policies/policy.h b/src/charon/config/policies/policy.h new file mode 100644 index 000000000..78cda1e8b --- /dev/null +++ b/src/charon/config/policies/policy.h @@ -0,0 +1,249 @@ +/** + * @file policy.h + * + * @brief Interface of policy_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef POLICY_H_ +#define POLICY_H_ + +#include +#include +#include +#include +#include + + +typedef struct policy_t policy_t; + +/** + * @brief A policy_t defines the policies to apply to CHILD_SAs. + * + * The given two IDs identify a policy. These rules define how + * child SAs may be set up and which traffic may be IPsec'ed. + * + * @b Constructors: + * - policy_create() + * + * @ingroup config + */ +struct policy_t { + + /** + * @brief Get own id to use for identification. + * + * Returned object is not getting cloned. + * + * @param this calling object + * @return own id + */ + identification_t *(*get_my_id) (policy_t *this); + + /** + * @brief Get id of communication partner. + * + * Returned object is not getting cloned. + * + * @param this calling object + * @return other id + */ + identification_t *(*get_other_id) (policy_t *this); + + /** + * @brief Update own ID. + * + * It may be necessary to uptdate own ID, as it + * is set to %any or to e.g. *@strongswan.org in + * some cases. + * Old ID is destroyed, new one NOT cloned. + * + * @param this calling object + * @param my_id new ID to set as my_id + */ + void (*update_my_id) (policy_t *this, identification_t *my_id); + + /** + * @brief Update others ID. + * + * It may be necessary to uptdate others ID, as it + * is set to %any or to e.g. *@strongswan.org in + * some cases. + * Old ID is destroyed, new one NOT cloned. + * + * @param this calling object + * @param other_id new ID to set as other_id + */ + void (*update_other_id) (policy_t *this, identification_t *other_id); + + /** + * @brief Update own address in traffic selectors. + * + * Update own 0.0.0.0 address in traffic selectors + * with supplied one. The size of the subnet will be + * set to /32. + * + * @param this calling object + * @param my_host new address to set in traffic selectors + */ + void (*update_my_ts) (policy_t *this, host_t *my_host); + + /** + * @brief Update others address in traffic selectors. + * + * Update remote 0.0.0.0 address in traffic selectors + * with supplied one. The size of the subnet will be + * set to /32. + * + * @param this calling object + * @param other_host new address to set in traffic selectors + */ + void (*update_other_ts) (policy_t *this, host_t *other_host); + + /** + * @brief Get configured traffic selectors for our site. + * + * Returns a list with all traffic selectors for the local + * site. List and items MUST NOT be freed nor modified. + * + * @param this calling object + * @return list with traffic selectors + */ + linked_list_t *(*get_my_traffic_selectors) (policy_t *this); + + /** + * @brief Get configured traffic selectors for others site. + * + * Returns a list with all traffic selectors for the remote + * site. List and items MUST NOT be freed nor modified. + * + * @param this calling object + * @return list with traffic selectors + */ + linked_list_t *(*get_other_traffic_selectors) (policy_t *this); + + /** + * @brief Select traffic selectors from a supplied list for local site. + * + * Resulted list and traffic selectors must be destroyed after usage. + * + * @param this calling object + * @param supplied linked list with traffic selectors + * @return list containing the selected traffic selectors + */ + linked_list_t *(*select_my_traffic_selectors) (policy_t *this, linked_list_t *supplied); + + /** + * @brief Select traffic selectors from a supplied list for remote site. + * + * Resulted list and traffic selectors must be destroyed after usage. + * + * @param this calling object + * @param supplied linked list with traffic selectors + * @return list containing the selected traffic selectors + */ + linked_list_t *(*select_other_traffic_selectors) (policy_t *this, linked_list_t *supplied); + + /** + * @brief Get the list of internally stored proposals. + * + * Rembember: policy_t does store proposals for AH/ESP, + * IKE proposals are in the connection_t + * + * @warning List and Items are still owned by policy and MUST NOT + * be manipulated or freed! + * + * @param this calling object + * @return lists with proposals + */ + linked_list_t *(*get_proposals) (policy_t *this); + + /** + * @brief Select a proposal from a supplied list. + * + * @param this calling object + * @param proposals list from from wich proposals are selected + * @return selected proposal, or NULL if nothing matches + */ + proposal_t *(*select_proposal) (policy_t *this, linked_list_t *proposals); + + /** + * @brief Add a traffic selector to the list for local site. + * + * After add, proposal is owned by policy. + * + * @warning Do not add while other threads are reading. + * + * @param this calling object + * @param traffic_selector traffic_selector to add + */ + void (*add_my_traffic_selector) (policy_t *this, traffic_selector_t *traffic_selector); + + /** + * @brief Add a traffic selector to the list for remote site. + * + * After add, proposal is owned by policy. + * + * @warning Do not add while other threads are reading. + * + * @param this calling object + * @param traffic_selector traffic_selector to add + */ + void (*add_other_traffic_selector) (policy_t *this, traffic_selector_t *traffic_selector); + + /** + * @brief Add a proposal to the list. + * + * The proposals are stored by priority, first added + * is the most prefered. + * + * @warning Do not add while other threads are reading. + * + * @param this calling object + * @param proposal proposal to add + */ + void (*add_proposal) (policy_t *this, proposal_t *proposal); + + /** + * @brief Clone a policy. + * + * @param this policy to clone + * @return clone of it + */ + policy_t *(*clone) (policy_t *this); + + /** + * @brief Destroys the policy object + * + * @param this calling object + */ + void (*destroy) (policy_t *this); +}; + +/** + * @brief Create a configuration object for IKE_AUTH and later. + * + * @param my_id identification_t for ourselves + * @param other_id identification_t for the remote guy + * @return policy_t object + * + * @ingroup config + */ +policy_t *policy_create(identification_t *my_id, identification_t *other_id); + +#endif /* POLICY_H_ */ diff --git a/src/charon/config/policies/policy_store.h b/src/charon/config/policies/policy_store.h new file mode 100755 index 000000000..651dea634 --- /dev/null +++ b/src/charon/config/policies/policy_store.h @@ -0,0 +1,76 @@ +/** + * @file policy_store.h + * + * @brief Interface policy_store_t. + * + */ + +/* + * Copyright (C) 2006 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef POLICY_STORE_H_ +#define POLICY_STORE_H_ + +#include +#include + + +typedef struct policy_store_t policy_store_t; + +/** + * @brief The interface for a store of policy_t's. + * + * @b Constructors: + * - stroke_create() + * + * @ingroup config + */ +struct policy_store_t { + + /** + * @brief Returns a policy identified by two IDs. + * + * The returned policy gets created/cloned and therefore must be + * destroyed by the caller. + * + * @param this calling object + * @param my_id own ID of the policy + * @param other_id others ID of the policy + * @return + * - matching policy_t, if found + * - NULL otherwise + */ + policy_t *(*get_policy) (policy_store_t *this, identification_t *my_id, identification_t *other_id); + + /** + * @brief Add a policy to the list. + * + * The policy is owned by the store after the call. Do + * not modify nor free. + * + * @param this calling object + * @param policy policy to add + */ + void (*add_policy) (policy_store_t *this, policy_t *policy); + + /** + * @brief Destroys a policy_store_t object. + * + * @param this calling object + */ + void (*destroy) (policy_store_t *this); +}; + +#endif /*POLICY_STORE_H_*/ diff --git a/src/charon/config/proposal.c b/src/charon/config/proposal.c new file mode 100644 index 000000000..cb71a756a --- /dev/null +++ b/src/charon/config/proposal.c @@ -0,0 +1,642 @@ +/** + * @file proposal.c + * + * @brief Implementation of proposal_t. + * + */ + +/* + * Copyright (C) 2006 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 + +#include "proposal.h" + +#include +#include +#include + + +/** + * String mappings for protocol_id_t. + */ +mapping_t protocol_id_m[] = { + {PROTO_NONE, "PROTO_NONE"}, + {PROTO_IKE, "PROTO_IKE"}, + {PROTO_AH, "PROTO_AH"}, + {PROTO_ESP, "PROTO_ESP"}, + {MAPPING_END, NULL} +}; + +/** + * String mappings for transform_type_t. + */ +mapping_t transform_type_m[] = { + {UNDEFINED_TRANSFORM_TYPE, "UNDEFINED_TRANSFORM_TYPE"}, + {ENCRYPTION_ALGORITHM, "ENCRYPTION_ALGORITHM"}, + {PSEUDO_RANDOM_FUNCTION, "PSEUDO_RANDOM_FUNCTION"}, + {INTEGRITY_ALGORITHM, "INTEGRITY_ALGORITHM"}, + {DIFFIE_HELLMAN_GROUP, "DIFFIE_HELLMAN_GROUP"}, + {EXTENDED_SEQUENCE_NUMBERS, "EXTENDED_SEQUENCE_NUMBERS"}, + {MAPPING_END, NULL} +}; + +/** + * String mappings for extended_sequence_numbers_t. + */ +mapping_t extended_sequence_numbers_m[] = { + {NO_EXT_SEQ_NUMBERS, "NO_EXT_SEQ_NUMBERS"}, + {EXT_SEQ_NUMBERS, "EXT_SEQ_NUMBERS"}, + {MAPPING_END, NULL} +}; + + +typedef struct protocol_proposal_t protocol_proposal_t; + +/** + * substructure which holds all data algos for a specific protocol + */ +struct protocol_proposal_t { + /** + * protocol (ESP or AH) + */ + protocol_id_t protocol; + + /** + * priority ordered list of encryption algorithms + */ + linked_list_t *encryption_algos; + + /** + * priority ordered list of integrity algorithms + */ + linked_list_t *integrity_algos; + + /** + * priority ordered list of pseudo random functions + */ + linked_list_t *prf_algos; + + /** + * priority ordered list of dh groups + */ + linked_list_t *dh_groups; + + /** + * priority ordered list of extended sequence number flags + */ + linked_list_t *esns; + + /** + * senders SPI + */ + chunk_t spi; +}; + + +typedef struct private_proposal_t private_proposal_t; + +/** + * Private data of an proposal_t object + */ +struct private_proposal_t { + + /** + * Public part + */ + proposal_t public; + + /** + * number of this proposal, as used in the payload + */ + u_int8_t number; + + /** + * list of protocol_proposal_t's + */ + linked_list_t *protocol_proposals; +}; + +/** + * Look up a protocol_proposal, or create one if necessary... + */ +static protocol_proposal_t *get_protocol_proposal(private_proposal_t *this, protocol_id_t proto, bool create) +{ + protocol_proposal_t *proto_proposal = NULL, *current_proto_proposal;; + iterator_t *iterator; + + /* find our protocol in the proposals */ + iterator = this->protocol_proposals->create_iterator(this->protocol_proposals, TRUE); + while (iterator->has_next(iterator)) + { + iterator->current(iterator, (void**)¤t_proto_proposal); + if (current_proto_proposal->protocol == proto) + { + proto_proposal = current_proto_proposal; + break; + } + } + iterator->destroy(iterator); + + if (!proto_proposal && create) + { + /* nope, create a new one */ + proto_proposal = malloc_thing(protocol_proposal_t); + proto_proposal->protocol = proto; + proto_proposal->encryption_algos = linked_list_create(); + proto_proposal->integrity_algos = linked_list_create(); + proto_proposal->prf_algos = linked_list_create(); + proto_proposal->dh_groups = linked_list_create(); + proto_proposal->esns = linked_list_create(); + if (proto == PROTO_IKE) + { + proto_proposal->spi.len = 8; + } + else + { + proto_proposal->spi.len = 4; + } + proto_proposal->spi.ptr = malloc(proto_proposal->spi.len); + /* add to the list */ + this->protocol_proposals->insert_last(this->protocol_proposals, (void*)proto_proposal); + } + return proto_proposal; +} + +/** + * Add algorithm/keysize to a algorithm list + */ +static void add_algo(linked_list_t *list, u_int8_t algo, size_t key_size) +{ + algorithm_t *algo_key = malloc_thing(algorithm_t); + + algo_key->algorithm = algo; + algo_key->key_size = key_size; + list->insert_last(list, (void*)algo_key); +} + +/** + * Implements proposal_t.add_algorithm + */ +static void add_algorithm(private_proposal_t *this, protocol_id_t proto, transform_type_t type, u_int16_t algo, size_t key_size) +{ + protocol_proposal_t *proto_proposal = get_protocol_proposal(this, proto, TRUE); + + switch (type) + { + case ENCRYPTION_ALGORITHM: + add_algo(proto_proposal->encryption_algos, algo, key_size); + break; + case INTEGRITY_ALGORITHM: + add_algo(proto_proposal->integrity_algos, algo, key_size); + break; + case PSEUDO_RANDOM_FUNCTION: + add_algo(proto_proposal->prf_algos, algo, key_size); + break; + case DIFFIE_HELLMAN_GROUP: + add_algo(proto_proposal->dh_groups, algo, 0); + break; + case EXTENDED_SEQUENCE_NUMBERS: + add_algo(proto_proposal->esns, algo, 0); + break; + default: + break; + } +} + +/** + * Implements proposal_t.get_algorithm. + */ +static bool get_algorithm(private_proposal_t *this, protocol_id_t proto, transform_type_t type, algorithm_t** algo) +{ + linked_list_t * list; + protocol_proposal_t *proto_proposal = get_protocol_proposal(this, proto, FALSE); + + if (proto_proposal == NULL) + { + return FALSE; + } + switch (type) + { + case ENCRYPTION_ALGORITHM: + list = proto_proposal->encryption_algos; + break; + case INTEGRITY_ALGORITHM: + list = proto_proposal->integrity_algos; + break; + case PSEUDO_RANDOM_FUNCTION: + list = proto_proposal->prf_algos; + break; + case DIFFIE_HELLMAN_GROUP: + list = proto_proposal->dh_groups; + break; + case EXTENDED_SEQUENCE_NUMBERS: + list = proto_proposal->esns; + break; + default: + return FALSE; + } + if (list->get_first(list, (void**)algo) != SUCCESS) + { + return FALSE; + } + return TRUE; +} + +/** + * Implements proposal_t.create_algorithm_iterator. + */ +static iterator_t *create_algorithm_iterator(private_proposal_t *this, protocol_id_t proto, transform_type_t type) +{ + protocol_proposal_t *proto_proposal = get_protocol_proposal(this, proto, FALSE); + if (proto_proposal == NULL) + { + return NULL; + } + + switch (type) + { + case ENCRYPTION_ALGORITHM: + return proto_proposal->encryption_algos->create_iterator(proto_proposal->encryption_algos, TRUE); + case INTEGRITY_ALGORITHM: + return proto_proposal->integrity_algos->create_iterator(proto_proposal->integrity_algos, TRUE); + case PSEUDO_RANDOM_FUNCTION: + return proto_proposal->prf_algos->create_iterator(proto_proposal->prf_algos, TRUE); + case DIFFIE_HELLMAN_GROUP: + return proto_proposal->dh_groups->create_iterator(proto_proposal->dh_groups, TRUE); + case EXTENDED_SEQUENCE_NUMBERS: + return proto_proposal->esns->create_iterator(proto_proposal->esns, TRUE); + default: + break; + } + return NULL; +} + +/** + * Find a matching alg/keysize in two linked lists + */ +static bool select_algo(linked_list_t *first, linked_list_t *second, bool *add, u_int16_t *alg, size_t *key_size) +{ + iterator_t *first_iter, *second_iter; + algorithm_t *first_alg, *second_alg; + + /* if in both are zero algorithms specified, we HAVE a match */ + if (first->get_count(first) == 0 && second->get_count(second) == 0) + { + *add = FALSE; + return TRUE; + } + + first_iter = first->create_iterator(first, TRUE); + second_iter = second->create_iterator(second, TRUE); + /* compare algs, order of algs in "first" is preferred */ + while (first_iter->has_next(first_iter)) + { + first_iter->current(first_iter, (void**)&first_alg); + second_iter->reset(second_iter); + while (second_iter->has_next(second_iter)) + { + second_iter->current(second_iter, (void**)&second_alg); + if (first_alg->algorithm == second_alg->algorithm && + first_alg->key_size == second_alg->key_size) + { + /* ok, we have an algorithm */ + *alg = first_alg->algorithm; + *key_size = first_alg->key_size; + *add = TRUE; + first_iter->destroy(first_iter); + second_iter->destroy(second_iter); + return TRUE; + } + } + } + /* no match in all comparisons */ + first_iter->destroy(first_iter); + second_iter->destroy(second_iter); + return FALSE; +} + +/** + * Implements proposal_t.select. + */ +static proposal_t *select_proposal(private_proposal_t *this, private_proposal_t *other) +{ + proposal_t *selected; + u_int16_t algo; + size_t key_size; + iterator_t *iterator; + protocol_proposal_t *this_prop, *other_prop; + protocol_id_t proto; + bool add; + u_int64_t spi; + + /* empty proposal? no match */ + if (this->protocol_proposals->get_count(this->protocol_proposals) == 0 || + other->protocol_proposals->get_count(other->protocol_proposals) == 0) + { + return NULL; + } + /* they MUST have the same amount of protocols */ + if (this->protocol_proposals->get_count(this->protocol_proposals) != + other->protocol_proposals->get_count(other->protocol_proposals)) + { + return NULL; + } + + selected = proposal_create(this->number); + + /* iterate over supplied proposals */ + iterator = other->protocol_proposals->create_iterator(other->protocol_proposals, TRUE); + while (iterator->has_next(iterator)) + { + iterator->current(iterator, (void**)&other_prop); + /* get the proposal with the same protocol */ + proto = other_prop->protocol; + this_prop = get_protocol_proposal(this, proto, FALSE); + + if (this_prop == NULL) + { + iterator->destroy(iterator); + selected->destroy(selected); + return NULL; + } + + /* select encryption algorithm */ + if (select_algo(this_prop->encryption_algos, other_prop->encryption_algos, &add, &algo, &key_size)) + { + if (add) + { + selected->add_algorithm(selected, proto, ENCRYPTION_ALGORITHM, algo, key_size); + } + } + else + { + iterator->destroy(iterator); + selected->destroy(selected); + return NULL; + } + /* select integrity algorithm */ + if (select_algo(this_prop->integrity_algos, other_prop->integrity_algos, &add, &algo, &key_size)) + { + if (add) + { + selected->add_algorithm(selected, proto, INTEGRITY_ALGORITHM, algo, key_size); + } + } + else + { + iterator->destroy(iterator); + selected->destroy(selected); + return NULL; + } + /* select prf algorithm */ + if (select_algo(this_prop->prf_algos, other_prop->prf_algos, &add, &algo, &key_size)) + { + if (add) + { + selected->add_algorithm(selected, proto, PSEUDO_RANDOM_FUNCTION, algo, key_size); + } + } + else + { + iterator->destroy(iterator); + selected->destroy(selected); + return NULL; + } + /* select a DH-group */ + if (select_algo(this_prop->dh_groups, other_prop->dh_groups, &add, &algo, &key_size)) + { + if (add) + { + selected->add_algorithm(selected, proto, DIFFIE_HELLMAN_GROUP, algo, 0); + } + } + else + { + iterator->destroy(iterator); + selected->destroy(selected); + return NULL; + } + /* select if we use ESNs */ + if (select_algo(this_prop->esns, other_prop->esns, &add, &algo, &key_size)) + { + if (add) + { + selected->add_algorithm(selected, proto, EXTENDED_SEQUENCE_NUMBERS, algo, 0); + } + } + else + { + iterator->destroy(iterator); + selected->destroy(selected); + return NULL; + } + } + iterator->destroy(iterator); + + /* apply spis from "other" */ + spi = other->public.get_spi(&(other->public), PROTO_AH); + if (spi) + { + selected->set_spi(selected, PROTO_AH, spi); + } + spi = other->public.get_spi(&(other->public), PROTO_ESP); + if (spi) + { + selected->set_spi(selected, PROTO_ESP, spi); + } + + /* everything matched, return new proposal */ + return selected; +} + +/** + * Implements proposal_t.get_number. + */ +static u_int8_t get_number(private_proposal_t *this) +{ + return this->number; +} + +/** + * Implements proposal_t.get_protocols. + */ +static void get_protocols(private_proposal_t *this, protocol_id_t ids[2]) +{ + iterator_t *iterator = this->protocol_proposals->create_iterator(this->protocol_proposals, TRUE); + u_int i = 0; + + ids[0] = PROTO_NONE; + ids[1] = PROTO_NONE; + while (iterator->has_next(iterator)) + { + protocol_proposal_t *proto_prop; + iterator->current(iterator, (void**)&proto_prop); + ids[i++] = proto_prop->protocol; + if (i>1) + { + /* should not happen, but who knows */ + break; + } + } + iterator->destroy(iterator); +} + +/** + * Implements proposal_t.set_spi. + */ +static void set_spi(private_proposal_t *this, protocol_id_t proto, u_int64_t spi) +{ + protocol_proposal_t *proto_proposal = get_protocol_proposal(this, proto, FALSE); + if (proto_proposal) + { + if (proto == PROTO_AH || proto == PROTO_ESP) + { + *((u_int32_t*)proto_proposal->spi.ptr) = (u_int32_t)spi; + } + else + { + *((u_int64_t*)proto_proposal->spi.ptr) = spi; + } + } +} + +/** + * Implements proposal_t.get_spi. + */ +static u_int64_t get_spi(private_proposal_t *this, protocol_id_t proto) +{ + protocol_proposal_t *proto_proposal = get_protocol_proposal(this, proto, FALSE); + if (proto_proposal) + { + if (proto == PROTO_AH || proto == PROTO_ESP) + { + return (u_int64_t)*((u_int32_t*)proto_proposal->spi.ptr); + } + else + { + return *((u_int64_t*)proto_proposal->spi.ptr); + } + } + return 0; +} + +/** + * Clone a algorithm list + */ +static void clone_algo_list(linked_list_t *list, linked_list_t *clone_list) +{ + algorithm_t *algo, *clone_algo; + iterator_t *iterator = list->create_iterator(list, TRUE); + while (iterator->has_next(iterator)) + { + iterator->current(iterator, (void**)&algo); + clone_algo = malloc_thing(algorithm_t); + memcpy(clone_algo, algo, sizeof(algorithm_t)); + clone_list->insert_last(clone_list, (void*)clone_algo); + } + iterator->destroy(iterator); +} + +/** + * Implements proposal_t.clone + */ +static proposal_t *clone(private_proposal_t *this) +{ + private_proposal_t *clone = (private_proposal_t*)proposal_create(this->number); + + iterator_t *iterator = this->protocol_proposals->create_iterator(this->protocol_proposals, TRUE); + while (iterator->has_next(iterator)) + { + protocol_proposal_t *proto_prop, *clone_proto_prop; + iterator->current(iterator, (void**)&proto_prop); + + clone_proto_prop = get_protocol_proposal(clone, proto_prop->protocol, TRUE); + memcpy(clone_proto_prop->spi.ptr, proto_prop->spi.ptr, clone_proto_prop->spi.len); + + clone_algo_list(proto_prop->encryption_algos, clone_proto_prop->encryption_algos); + clone_algo_list(proto_prop->integrity_algos, clone_proto_prop->integrity_algos); + clone_algo_list(proto_prop->prf_algos, clone_proto_prop->prf_algos); + clone_algo_list(proto_prop->dh_groups, clone_proto_prop->dh_groups); + clone_algo_list(proto_prop->esns, clone_proto_prop->esns); + } + iterator->destroy(iterator); + + return &clone->public; +} + +/** + * Frees all list items and destroys the list + */ +static void free_algo_list(linked_list_t *list) +{ + algorithm_t *algo; + + while(list->get_count(list) > 0) + { + list->remove_last(list, (void**)&algo); + free(algo); + } + list->destroy(list); +} + +/** + * Implements proposal_t.destroy. + */ +static void destroy(private_proposal_t *this) +{ + while(this->protocol_proposals->get_count(this->protocol_proposals) > 0) + { + protocol_proposal_t *proto_prop; + this->protocol_proposals->remove_last(this->protocol_proposals, (void**)&proto_prop); + + free_algo_list(proto_prop->encryption_algos); + free_algo_list(proto_prop->integrity_algos); + free_algo_list(proto_prop->prf_algos); + free_algo_list(proto_prop->dh_groups); + free_algo_list(proto_prop->esns); + + free(proto_prop->spi.ptr); + free(proto_prop); + } + this->protocol_proposals->destroy(this->protocol_proposals); + + free(this); +} + +/* + * Describtion in header-file + */ +proposal_t *proposal_create(u_int8_t number) +{ + private_proposal_t *this = malloc_thing(private_proposal_t); + + this->public.add_algorithm = (void (*)(proposal_t*,protocol_id_t,transform_type_t,u_int16_t,size_t))add_algorithm; + this->public.create_algorithm_iterator = (iterator_t* (*)(proposal_t*,protocol_id_t,transform_type_t))create_algorithm_iterator; + this->public.get_algorithm = (bool (*)(proposal_t*,protocol_id_t,transform_type_t,algorithm_t**))get_algorithm; + this->public.select = (proposal_t* (*)(proposal_t*,proposal_t*))select_proposal; + this->public.get_number = (u_int8_t (*)(proposal_t*))get_number; + this->public.get_protocols = (void(*)(proposal_t *this, protocol_id_t ids[2]))get_protocols; + this->public.set_spi = (void(*)(proposal_t*,protocol_id_t,u_int64_t spi))set_spi; + this->public.get_spi = (u_int64_t(*)(proposal_t*,protocol_id_t))get_spi; + this->public.clone = (proposal_t*(*)(proposal_t*))clone; + this->public.destroy = (void(*)(proposal_t*))destroy; + + /* init private members*/ + this->number = number; + this->protocol_proposals = linked_list_create(); + + return (&this->public); +} diff --git a/src/charon/config/proposal.h b/src/charon/config/proposal.h new file mode 100644 index 000000000..48e3ad8d5 --- /dev/null +++ b/src/charon/config/proposal.h @@ -0,0 +1,269 @@ +/** + * @file proposal.h + * + * @brief Interface of proposal_t. + * + */ + +/* + * Copyright (C) 2006 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef PROPOSAL_H_ +#define PROPOSAL_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + + +typedef enum protocol_id_t protocol_id_t; + +/** + * Protocol ID of a proposal. + * + * @ingroup config + */ +enum protocol_id_t { + PROTO_NONE = 0, + PROTO_IKE = 1, + PROTO_AH = 2, + PROTO_ESP = 3, +}; + +/** + * String mappings for protocol_id_t. + * + * @ingroup config + */ +extern mapping_t protocol_id_m[]; + + +typedef enum transform_type_t transform_type_t; + +/** + * Type of a transform, as in IKEv2 RFC 3.3.2. + * + * @ingroup payloads + */ +enum transform_type_t { + UNDEFINED_TRANSFORM_TYPE = 241, + ENCRYPTION_ALGORITHM = 1, + PSEUDO_RANDOM_FUNCTION = 2, + INTEGRITY_ALGORITHM = 3, + DIFFIE_HELLMAN_GROUP = 4, + EXTENDED_SEQUENCE_NUMBERS = 5 +}; + +/** + * String mappings for transform_type_t. + * + * @ingroup payloads + */ +extern mapping_t transform_type_m[]; + + +typedef enum extended_sequence_numbers_t extended_sequence_numbers_t; + +/** + * Extended sequence numbers, as in IKEv2 RFC 3.3.2. + * + * @ingroup payloads + */ +enum extended_sequence_numbers_t { + NO_EXT_SEQ_NUMBERS = 0, + EXT_SEQ_NUMBERS = 1 +}; + +/** + * String mappings for extended_sequence_numbers_t. + * + * @ingroup payloads + */ +extern mapping_t extended_sequence_numbers_m[]; + + +typedef struct algorithm_t algorithm_t; + +/** + * Struct used to store different kinds of algorithms. The internal + * lists of algorithms contain such structures. + */ +struct algorithm_t { + /** + * Value from an encryption_algorithm_t/integrity_algorithm_t/... + */ + u_int16_t algorithm; + + /** + * the associated key size, or zero if not needed + */ + u_int16_t key_size; +}; + +typedef struct proposal_t proposal_t; + +/** + * @brief Stores a set of algorithms used for an SA. + * + * A proposal stores algorithms for a specific + * protocol. It can store algorithms for more than + * one protocol (e.g. AH and ESP). Then the proposal + * means both protocols must be used. + * A proposal may contain more than one algorithm + * of the same kind. ONE of them can be selected. + * + * @warning This class is NOT thread-save! + * + * @b Constructors: + * - proposal_create() + * + * @ingroup config + */ +struct proposal_t { + + /** + * @brief Add an algorithm to the proposal. + * + * The algorithms are stored by priority, first added + * is the most preferred. + * Key size is only needed for encryption algorithms + * with variable key size (such as AES). Must be set + * to zero if key size is not specified. + * The alg parameter accepts encryption_algorithm_t, + * integrity_algorithm_t, dh_group_number_t and + * extended_sequence_numbers_t. + * + * @warning Do not add while other threads are reading. + * + * @param this calling object + * @param proto desired protocol + * @param type kind of algorithm + * @param alg identifier for algorithm + * @param key_size key size to use + */ + void (*add_algorithm) (proposal_t *this, protocol_id_t proto, transform_type_t type, u_int16_t alg, size_t key_size); + + /** + * @brief Get an iterator over algorithms for a specifc protocol/algo type. + * + * @param this calling object + * @param proto desired protocol + * @param type kind of algorithm + * @return iterator over algorithms + */ + iterator_t *(*create_algorithm_iterator) (proposal_t *this, protocol_id_t proto, transform_type_t type); + + /** + * @brief Get the algorithm for a type to use. + * + * If there are multiple algorithms, only the first is returned. + * Result is still owned by proposal, do not modify! + * + * @param this calling object + * @param proto desired protocol + * @param type kind of algorithm + * @param[out] algo pointer which receives algorithm and key size + * @return TRUE if algorithm of this kind available + */ + bool (*get_algorithm) (proposal_t *this, protocol_id_t proto, transform_type_t type, algorithm_t** algo); + + /** + * @brief Compare two proposal, and select a matching subset. + * + * If the proposals are for the same protocols (AH/ESP), they are + * compared. If they have at least one algorithm of each type + * in common, a resulting proposal of this kind is created. + * + * @param this calling object + * @param other proposal to compair agains + * @return + * - selected proposal, if possible + * - NULL, if proposals don't match + */ + proposal_t *(*select) (proposal_t *this, proposal_t *other); + + /** + * @brief Get the number set on construction. + * + * @param this calling object + * @return number + */ + u_int8_t (*get_number) (proposal_t *this); + + /** + * @brief Get the protocol ids in the proposals. + * + * With AH and ESP, there could be two protocols in one + * proposal. + * + * @param this calling object + * @param ids array of protocol ids, + */ + void (*get_protocols) (proposal_t *this, protocol_id_t ids[2]); + + /** + * @brief Get the spi for a specific protocol. + * + * @param this calling object + * @param proto AH/ESP + * @return spi for proto + */ + u_int64_t (*get_spi) (proposal_t *this, protocol_id_t proto); + + /** + * @brief Set the spi for a specific protocol. + * + * @param this calling object + * @param proto AH/ESP + * @param spi spi to set for proto + */ + void (*set_spi) (proposal_t *this, protocol_id_t proto, u_int64_t spi); + + /** + * @brief Clone a proposal. + * + * @param this proposal to clone + * @return clone of it + */ + proposal_t *(*clone) (proposal_t *this); + + /** + * @brief Destroys the proposal object. + * + * @param this calling object + */ + void (*destroy) (proposal_t *this); +}; + +/** + * @brief Create a child proposal for AH and/or ESP. + * + * Since the order of multiple proposals is important for + * key derivation, we must assign them numbers as they + * appear in the raw payload. Numbering starts at 1. + * + * @param number number of the proposal, as in the payload + * @return proposal_t object + * + * @ingroup config + */ +proposal_t *proposal_create(u_int8_t number); + +#endif /* PROPOSAL_H_ */ diff --git a/src/charon/config/traffic_selector.c b/src/charon/config/traffic_selector.c new file mode 100644 index 000000000..81272659a --- /dev/null +++ b/src/charon/config/traffic_selector.c @@ -0,0 +1,425 @@ +/** + * @file traffic_selector.c + * + * @brief Implementation of traffic_selector_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 "traffic_selector.h" + +#include +#include +#include +#include + +typedef struct private_traffic_selector_t private_traffic_selector_t; + +/** + * Private data of an traffic_selector_t object + */ +struct private_traffic_selector_t { + + /** + * Public part + */ + traffic_selector_t public; + + /** + * Type of address + */ + ts_type_t type; + + /** + * IP protocol (UDP, TCP, ICMP, ...) + */ + u_int8_t protocol; + + /** + * begin of address range, host order + */ + union { + u_int32_t from_addr_ipv4; + }; + + /** + * end of address range, host order + */ + union { + u_int32_t to_addr_ipv4; + }; + + /** + * begin of port range + */ + u_int16_t from_port; + + /** + * end of port range + */ + u_int16_t to_port; +}; + +/** + * internal generic constructor + */ +static private_traffic_selector_t *traffic_selector_create(u_int8_t protocol, ts_type_t type, u_int16_t from_port, u_int16_t to_port); + +/** + * implements traffic_selector_t.get_subset + */ +static traffic_selector_t *get_subset(private_traffic_selector_t *this, private_traffic_selector_t *other) +{ + if ((this->type == TS_IPV4_ADDR_RANGE) && + (other->type == TS_IPV4_ADDR_RANGE) && + (this->protocol == other->protocol)) + { + u_int32_t from_addr, to_addr; + u_int16_t from_port, to_port; + private_traffic_selector_t *new_ts; + + /* calculate the maximum address range allowed for both */ + from_addr = max(this->from_addr_ipv4, other->from_addr_ipv4); + to_addr = min(this->to_addr_ipv4, other->to_addr_ipv4); + if (from_addr > to_addr) + { + /* no match */ + return NULL; + } + + /* calculate the maximum port range allowed for both */ + from_port = max(this->from_port, other->from_port); + to_port = min(this->to_port, other->to_port); + if (from_port > to_port) + { + /* no match */ + return NULL; + } + + /* got a match, return it */ + new_ts = traffic_selector_create(this->protocol, this->type, from_port, to_port); + new_ts->from_addr_ipv4 = from_addr; + new_ts->to_addr_ipv4 = to_addr; + new_ts->type = TS_IPV4_ADDR_RANGE; + return &(new_ts->public); + } + return NULL; +} + +/** + * Implements traffic_selector_t.get_from_address. + */ +static chunk_t get_from_address(private_traffic_selector_t *this) +{ + chunk_t from_addr = CHUNK_INITIALIZER; + + switch (this->type) + { + case TS_IPV4_ADDR_RANGE: + { + u_int32_t network; + from_addr.len = sizeof(network); + from_addr.ptr = malloc(from_addr.len); + /* chunk must contain network order, convert! */ + network = htonl(this->from_addr_ipv4); + memcpy(from_addr.ptr, &network, from_addr.len); + break; + } + case TS_IPV6_ADDR_RANGE: + { + break; + } + } + return from_addr; +} + +/** + * Implements traffic_selector_t.get_to_address. + */ +static chunk_t get_to_address(private_traffic_selector_t *this) +{ + chunk_t to_addr = CHUNK_INITIALIZER; + + switch (this->type) + { + case TS_IPV4_ADDR_RANGE: + { + u_int32_t network; + to_addr.len = sizeof(network); + to_addr.ptr = malloc(to_addr.len); + /* chunk must contain network order, convert! */ + network = htonl(this->to_addr_ipv4); + memcpy(to_addr.ptr, &network, to_addr.len); + break; + } + case TS_IPV6_ADDR_RANGE: + { + break; + } + } + return to_addr; +} + +/** + * Implements traffic_selector_t.get_from_port. + */ +static u_int16_t get_from_port(private_traffic_selector_t *this) +{ + return this->from_port; +} + +/** + * Implements traffic_selector_t.get_to_port. + */ +static u_int16_t get_to_port(private_traffic_selector_t *this) +{ + return this->to_port; +} + +/** + * Implements traffic_selector_t.get_type. + */ +static ts_type_t get_type(private_traffic_selector_t *this) +{ + return this->type; +} + +/** + * Implements traffic_selector_t.get_protocol. + */ +static u_int8_t get_protocol(private_traffic_selector_t *this) +{ + return this->protocol; +} + +/** + * Implements traffic_selector_t.get_netmask. + */ +static u_int8_t get_netmask(private_traffic_selector_t *this) +{ + switch (this->type) + { + case TS_IPV4_ADDR_RANGE: + { + u_int32_t from, to, bit; + from = htonl(this->from_addr_ipv4); + to = htonl(this->to_addr_ipv4); + for (bit = 0; bit < 32; bit++) + { + if ((1<get_family(host) == AF_INET && + this->type == TS_IPV4_ADDR_RANGE) + { + if (this->from_addr_ipv4 == 0) + { + chunk_t from = host->get_address_as_chunk(host); + this->from_addr_ipv4 = ntohl(*((u_int32_t*)from.ptr)); + this->to_addr_ipv4 = this->from_addr_ipv4; + chunk_free(&from); + } + } +} + +/** + * Implements traffic_selector_t.clone. + */ +static traffic_selector_t *clone(private_traffic_selector_t *this) +{ + private_traffic_selector_t *clone = traffic_selector_create(this->protocol, this->type, this->from_port, this->to_port); + clone->type = this->type; + switch (clone->type) + { + case TS_IPV4_ADDR_RANGE: + { + clone->from_addr_ipv4 = this->from_addr_ipv4; + clone->to_addr_ipv4 = this->to_addr_ipv4; + return &(clone->public); + } + case TS_IPV6_ADDR_RANGE: + default: + { + free(this); + return NULL; + } + } +} + +/** + * Implements traffic_selector_t.destroy. + */ +static void destroy(private_traffic_selector_t *this) +{ + free(this); +} + +/* + * see header + */ +traffic_selector_t *traffic_selector_create_from_bytes(u_int8_t protocol, ts_type_t type, chunk_t from_addr, int16_t from_port, chunk_t to_addr, u_int16_t to_port) +{ + private_traffic_selector_t *this = traffic_selector_create(protocol, type, from_port, to_port); + + this->type = type; + switch (type) + { + case TS_IPV4_ADDR_RANGE: + { + if (from_addr.len != 4 || to_addr.len != 4) + { + free(this); + return NULL; + } + /* chunk contains network order, convert! */ + this->from_addr_ipv4 = ntohl(*((u_int32_t*)from_addr.ptr)); + this->to_addr_ipv4 = ntohl(*((u_int32_t*)to_addr.ptr)); + break; + } + case TS_IPV6_ADDR_RANGE: + default: + { + free(this); + return NULL; + } + } + return (&this->public); +} + +/* + * see header + */ +traffic_selector_t *traffic_selector_create_from_subnet(host_t *net, u_int8_t netbits) +{ + private_traffic_selector_t *this = traffic_selector_create(0, 0, 0, 65535); + + switch (net->get_family(net)) + { + case AF_INET: + { + chunk_t from; + + this->type = TS_IPV4_ADDR_RANGE; + from = net->get_address_as_chunk(net); + this->from_addr_ipv4 = ntohl(*((u_int32_t*)from.ptr)); + if (this->from_addr_ipv4 == 0) + { + /* use /32 for 0.0.0.0 */ + this->to_addr_ipv4 = 0xFFFFFF; + } + else + { + this->to_addr_ipv4 = this->from_addr_ipv4 | ((1 << (32 - netbits)) - 1); + } + chunk_free(&from); + break; + } + case AF_INET6: + default: + { + free(this); + return NULL; + } + } + return (&this->public); +} + +/* + * see header + */ +traffic_selector_t *traffic_selector_create_from_string(u_int8_t protocol, ts_type_t type, char *from_addr, u_int16_t from_port, char *to_addr, u_int16_t to_port) +{ + private_traffic_selector_t *this = traffic_selector_create(protocol, type, from_port, to_port); + + /* public functions */ + this->public.get_subset = (traffic_selector_t*(*)(traffic_selector_t*,traffic_selector_t*))get_subset; + this->public.destroy = (void(*)(traffic_selector_t*))destroy; + + this->type = type; + switch (type) + { + case TS_IPV4_ADDR_RANGE: + { + if (inet_aton(from_addr, (struct in_addr*)&(this->from_addr_ipv4)) == 0) + { + free(this); + return NULL; + } + if (inet_aton(to_addr, (struct in_addr*)&(this->to_addr_ipv4)) == 0) + { + free(this); + return NULL; + } + /* convert to host order, inet_aton has network order */ + this->from_addr_ipv4 = ntohl(this->from_addr_ipv4); + this->to_addr_ipv4 = ntohl(this->to_addr_ipv4); + break; + } + case TS_IPV6_ADDR_RANGE: + { + free(this); + return NULL; + } + } + + return (&this->public); +} + +/* + * see declaration + */ +static private_traffic_selector_t *traffic_selector_create(u_int8_t protocol, ts_type_t type, u_int16_t from_port, u_int16_t to_port) +{ + private_traffic_selector_t *this = malloc_thing(private_traffic_selector_t); + + /* public functions */ + this->public.get_subset = (traffic_selector_t*(*)(traffic_selector_t*,traffic_selector_t*))get_subset; + this->public.get_from_address = (chunk_t(*)(traffic_selector_t*))get_from_address; + this->public.get_to_address = (chunk_t(*)(traffic_selector_t*))get_to_address; + this->public.get_from_port = (u_int16_t(*)(traffic_selector_t*))get_from_port; + this->public.get_to_port = (u_int16_t(*)(traffic_selector_t*))get_to_port; + this->public.get_type = (ts_type_t(*)(traffic_selector_t*))get_type; + this->public.get_protocol = (u_int8_t(*)(traffic_selector_t*))get_protocol; + this->public.get_netmask = (u_int8_t(*)(traffic_selector_t*))get_netmask; + this->public.update_address_range = (void(*)(traffic_selector_t*,host_t*))update_address_range; + this->public.clone = (traffic_selector_t*(*)(traffic_selector_t*))clone; + this->public.destroy = (void(*)(traffic_selector_t*))destroy; + + this->from_port = from_port; + this->to_port = to_port; + this->protocol = protocol; + this->type = type; + + return this; +} diff --git a/src/charon/config/traffic_selector.h b/src/charon/config/traffic_selector.h new file mode 100644 index 000000000..5ac5bdeb1 --- /dev/null +++ b/src/charon/config/traffic_selector.h @@ -0,0 +1,258 @@ +/** + * @file traffic_selector.h + * + * @brief Interface of traffic_selector_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef TRAFFIC_SELECTOR_H_ +#define TRAFFIC_SELECTOR_H_ + +#include +#include + +typedef enum ts_type_t ts_type_t; + +/** + * Traffic selector types. + * + * @ingroup config + */ +enum ts_type_t { + + /** + * A range of IPv4 addresses, represented by two four (4) octet + * values. The first value is the beginning IPv4 address + * (inclusive) and the second value is the ending IPv4 address + * (inclusive). All addresses falling between the two specified + * addresses are considered to be within the list. + */ + TS_IPV4_ADDR_RANGE = 7, + + /** + * A range of IPv6 addresses, represented by two sixteen (16) + * octet values. The first value is the beginning IPv6 address + * (inclusive) and the second value is the ending IPv6 address + * (inclusive). All addresses falling between the two specified + * addresses are considered to be within the list. + */ + TS_IPV6_ADDR_RANGE = 8 +}; + +/** + * string mappings for ts_type_t + */ +extern mapping_t ts_type_m[]; + + +typedef struct traffic_selector_t traffic_selector_t; + +/** + * @brief Object representing a traffic selector entry. + * + * A traffic selector defines an range of addresses + * and a range of ports. IPv6 is not fully supported yet. + * + * @b Constructors: + * - traffic_selector_create_from_bytes() + * - traffic_selector_create_from_string() + * + * @todo Add IPv6 support + * + * @ingroup config + */ +struct traffic_selector_t { + + /** + * @brief Compare two traffic selectors, and create a new one + * which is the largest subset of both (subnet & port). + * + * Resulting traffic_selector is newly created and must be destroyed. + * + * @param this first to compare + * @param other second to compare + * @return + * - created subset of them + * - or NULL if no match between this and other + */ + traffic_selector_t *(*get_subset) (traffic_selector_t *this, traffic_selector_t *other); + + /** + * @brief Clone a traffic selector. + * + * @param this traffic selector to clone + * @return clone of it + */ + traffic_selector_t *(*clone) (traffic_selector_t *this); + + /** + * @brief Get starting address of this ts as a chunk. + * + * Data is in network order and represents the address. + * Size depends on protocol. + * + * Resulting chunk data is allocated and must be freed! + * + * @param this calling object + * @return chunk containing the address + */ + chunk_t (*get_from_address) (traffic_selector_t *this); + + /** + * @brief Get ending address of this ts as a chunk. + * + * Data is in network order and represents the address. + * Size depends on protocol. + * + * Resulting chunk data is allocated and must be freed! + * + * @param this calling object + * @return chunk containing the address + */ + chunk_t (*get_to_address) (traffic_selector_t *this); + + /** + * @brief Get starting port of this ts. + * + * Port is in host order, since the parser converts it. + * Size depends on protocol. + * + * @param this calling object + * @return port + */ + u_int16_t (*get_from_port) (traffic_selector_t *this); + + /** + * @brief Get ending port of this ts. + * + * Port is in host order, since the parser converts it. + * Size depends on protocol. + * + * @param this calling object + * @return port + */ + u_int16_t (*get_to_port) (traffic_selector_t *this); + + /** + * @brief Get the type of the traffic selector. + * + * @param this calling obect + * @return ts_type_t specifying the type + */ + ts_type_t (*get_type) (traffic_selector_t *this); + + /** + * @brief Get the protocol id of this ts. + * + * @param this calling obect + * @return protocol id + */ + u_int8_t (*get_protocol) (traffic_selector_t *this); + + /** + * @brief Get the netmask of the address range. + * + * Returns the number of bits associated to the subnet. + * (As the "24" in "192.168.0.0/24"). This is approximated + * if the address range is not a complete subnet! Since Linux + * does not support full IP address ranges (yet), we can't do this + * (much) better. + * + * @param this calling obect + * @return netmask as "bits for subnet" + */ + u_int8_t (*get_netmask) (traffic_selector_t *this); + + /** + * @brief Update the address of a traffic selector. + * + * Update the address range of a traffic selector, + * if the current address is 0.0.0.0. The new address range + * starts from the supplied address and also ends there + * (which means it is a one-host-address-range ;-). + * + * @param this calling obect + * @param host host_t specifying the address range + */ + void (*update_address_range) (traffic_selector_t *this, host_t* host); + + /** + * @brief Destroys the ts object + * + * @param this calling object + */ + void (*destroy) (traffic_selector_t *this); +}; + +/** + * @brief Create a new traffic selector using human readable params. + * + * @param protocol protocol for this ts, such as TCP or UDP + * @param type type of following addresses, such as TS_IPV4_ADDR_RANGE + * @param from_addr start of address range as string + * @param from_port port number in host order + * @param to_addr end of address range as string + * @param to_port port number in host order + * @return + * - traffic_selector_t object + * - NULL if invalid address strings/protocol + * + * @ingroup config + */ +traffic_selector_t *traffic_selector_create_from_string(u_int8_t protocol, ts_type_t type, char *from_addr, u_int16_t from_port, char *to_addr, u_int16_t to_port); + +/** + * @brief Create a new traffic selector using data read from the net. + * + * There exists a mix of network and host order in the params. + * But the parser gives us this data in this format, so we + * don't have to convert twice. + * + * @param protocol protocol for this ts, such as TCP or UDP + * @param type type of following addresses, such as TS_IPV4_ADDR_RANGE + * @param from_address start of address range, network order + * @param from_port port number, host order + * @param to_address end of address range as string, network + * @param to_port port number, host order + * @return + * - traffic_selector_t object + * - NULL if invalid address input/protocol + * + * @ingroup config + */ +traffic_selector_t *traffic_selector_create_from_bytes(u_int8_t protocol, ts_type_t type, chunk_t from_address, int16_t from_port, chunk_t to_address, u_int16_t to_port); + +/** + * @brief Create a new traffic selector defining a whole subnet. + * + * In most cases, definition of a traffic selector for full subnets + * is sufficient. This constructor creates a traffic selector for + * all protocols, all ports and the address range specified by the + * subnet. + * + * @param net subnet to use + * @param netbits size of the subnet, as used in e.g. 192.168.0.0/24 notation + * @return + * - traffic_selector_t object + * - NULL if address family of net not supported + * + * @ingroup config + */ +traffic_selector_t *traffic_selector_create_from_subnet(host_t *net, u_int8_t netbits); + +#endif /* TRAFFIC_SELECTOR_H_ */ diff --git a/src/charon/daemon.c b/src/charon/daemon.c new file mode 100644 index 000000000..c3d7ed766 --- /dev/null +++ b/src/charon/daemon.c @@ -0,0 +1,390 @@ +/** + * @file daemon.c + * + * @brief Implementation of daemon_t and main of IKEv2-Daemon. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 +#include +#include +#include +#include +#include +#include +#include + +#include "daemon.h" + +#include +#include +#include +#include + + +typedef struct private_daemon_t private_daemon_t; + +/** + * Private additions to daemon_t, contains threads and internal functions. + */ +struct private_daemon_t { + /** + * Public members of daemon_t. + */ + daemon_t public; + + /** + * A logger_t object assigned for daemon things. + */ + logger_t *logger; + + /** + * Signal set used for signal handling. + */ + sigset_t signal_set; + + /** + * The thread_id of main-thread. + */ + pthread_t main_thread_id; + + /** + * Main loop function. + * + * @param this calling object + */ + void (*run) (private_daemon_t *this); + + /** + * Initialize the daemon. + * + * @param this calling object + */ + void (*initialize) (private_daemon_t *this); + + /** + * Destroy the daemon. + * + * @param this calling object + */ + void (*destroy) (private_daemon_t *this); +}; + +/** + * One and only instance of the daemon. + */ +daemon_t *charon; + +/** + * Implementation of private_daemon_t.run. + */ +static void run(private_daemon_t *this) +{ + /* reselect signals for this thread */ + sigemptyset(&(this->signal_set)); + sigaddset(&(this->signal_set), SIGINT); + sigaddset(&(this->signal_set), SIGHUP); + sigaddset(&(this->signal_set), SIGTERM); + pthread_sigmask(SIG_BLOCK, &(this->signal_set), 0); + + while(TRUE) + { + int signal_number; + int error; + + error = sigwait(&(this->signal_set), &signal_number); + if(error) + { + this->logger->log(this->logger, ERROR, "Error %d when waiting for signal", error); + return; + } + switch (signal_number) + { + case SIGHUP: + { + this->logger->log(this->logger, CONTROL, "Signal of type SIGHUP received. Do nothing"); + break; + } + case SIGINT: + { + this->logger->log(this->logger, CONTROL, "Signal of type SIGINT received. Exit main loop"); + return; + } + case SIGTERM: + this->logger->log(this->logger, CONTROL, "Signal of type SIGTERM received. Exit main loop"); + return; + default: + { + this->logger->log(this->logger, CONTROL, "Unknown signal %d received. Do nothing", signal_number); + break; + } + } + } +} + +/** + * Implementation of daemon_t.kill. + */ +static void kill_daemon(private_daemon_t *this, char *reason) +{ + /* we send SIGTERM, so the daemon can cleanly shut down */ + this->logger->log(this->logger, CONTROL, "Killing daemon: %s", reason); + if (this->main_thread_id == pthread_self()) + { + /* initialization failed, terminate daemon */ + this->destroy(this); + unlink(PID_FILE); + exit(-1); + } + else + { + this->logger->log(this->logger, CONTROL, "sending SIGTERM to ourself", reason); + kill(0, SIGTERM); + /* thread must die, since he produced a ciritcal failure and can't continue */ + pthread_exit(NULL); + } +} + +/** + * Implementation of private_daemon_t.initialize. + */ +static void initialize(private_daemon_t *this) +{ + local_credential_store_t* cred_store; + + this->public.configuration = configuration_create(); + this->public.socket = socket_create(IKEV2_UDP_PORT); + this->public.ike_sa_manager = ike_sa_manager_create(); + this->public.job_queue = job_queue_create(); + this->public.event_queue = event_queue_create(); + this->public.send_queue = send_queue_create(); + this->public.connections = (connection_store_t*)local_connection_store_create(); + this->public.policies = (policy_store_t*)local_policy_store_create(); + this->public.credentials = (credential_store_t*)(cred_store = local_credential_store_create()); + + /* load keys & certs */ + cred_store->load_certificates(cred_store, CERTIFICATE_DIR); + cred_store->load_private_keys(cred_store, SECRETS_FILE, PRIVATE_KEY_DIR); + + + /* start building threads, we are multi-threaded NOW */ + this->public.stroke = stroke_create(); + this->public.sender = sender_create(); + this->public.receiver = receiver_create(); + this->public.scheduler = scheduler_create(); + this->public.kernel_interface = kernel_interface_create(); + this->public.thread_pool = thread_pool_create(NUMBER_OF_WORKING_THREADS); +} + +/** + * Destory all initiated objects + */ +static void destroy(private_daemon_t *this) +{ + if (this->public.ike_sa_manager != NULL) + { + this->public.ike_sa_manager->destroy(this->public.ike_sa_manager); + } + if (this->public.kernel_interface != NULL) + { + this->public.kernel_interface->destroy(this->public.kernel_interface); + } + if (this->public.receiver != NULL) + { + this->public.receiver->destroy(this->public.receiver); + } + if (this->public.scheduler != NULL) + { + this->public.scheduler->destroy(this->public.scheduler); + } + if (this->public.sender != NULL) + { + this->public.sender->destroy(this->public.sender); + } + if (this->public.thread_pool != NULL) + { + this->public.thread_pool->destroy(this->public.thread_pool); + } + if (this->public.job_queue != NULL) + { + this->public.job_queue->destroy(this->public.job_queue); + } + if (this->public.event_queue != NULL) + { + this->public.event_queue->destroy(this->public.event_queue); + } + if (this->public.send_queue != NULL) + { + this->public.send_queue->destroy(this->public.send_queue); + } + if (this->public.socket != NULL) + { + this->public.socket->destroy(this->public.socket); + } + if (this->public.configuration != NULL) + { + this->public.configuration->destroy(this->public.configuration); + } + if (this->public.credentials != NULL) + { + this->public.credentials->destroy(this->public.credentials); + } + if (this->public.connections != NULL) + { + this->public.connections->destroy(this->public.connections); + } + if (this->public.policies != NULL) + { + this->public.policies->destroy(this->public.policies); + } + if (this->public.stroke != NULL) + { + this->public.stroke->destroy(this->public.stroke); + } + free(this); +} + +void signal_handler(int signal) +{ + void *array[20]; + size_t size; + char **strings; + size_t i; + logger_t *logger; + + size = backtrace(array, 20); + strings = backtrace_symbols(array, size); + logger = logger_manager->get_logger(logger_manager, DAEMON); + + logger->log(logger, ERROR, "Thread %u received SIGSEGV. Dumping %d frames from stack:", pthread_self(), size); + + for (i = 0; i < size; i++) + { + logger->log(logger, ERROR, " %s", strings[i]); + } + free (strings); + logger->log(logger, ERROR, "Killing ourself hard after SIGSEGV"); + kill(getpid(), SIGKILL); +} + +/** + * @brief Create the daemon. + * + * @return created daemon_t + */ +private_daemon_t *daemon_create(void) +{ + private_daemon_t *this = malloc_thing(private_daemon_t); + struct sigaction action; + + /* assign methods */ + this->run = run; + this->destroy = destroy; + this->initialize = initialize; + this->public.kill = (void (*) (daemon_t*,char*))kill_daemon; + + /* NULL members for clean destruction */ + this->public.socket = NULL; + this->public.ike_sa_manager = NULL; + this->public.job_queue = NULL; + this->public.event_queue = NULL; + this->public.send_queue = NULL; + this->public.configuration = NULL; + this->public.credentials = NULL; + this->public.connections = NULL; + this->public.policies = NULL; + this->public.sender= NULL; + this->public.receiver = NULL; + this->public.scheduler = NULL; + this->public.kernel_interface = NULL; + this->public.thread_pool = NULL; + this->public.stroke = NULL; + + this->main_thread_id = pthread_self(); + + /* setup signal handling for all threads */ + sigemptyset(&(this->signal_set)); + sigaddset(&(this->signal_set), SIGSEGV); + sigaddset(&(this->signal_set), SIGINT); + sigaddset(&(this->signal_set), SIGHUP); + sigaddset(&(this->signal_set), SIGTERM); + pthread_sigmask(SIG_BLOCK, &(this->signal_set), 0); + + /* setup SIGSEGV handler for all threads */ + action.sa_handler = signal_handler; + action.sa_mask = this->signal_set; + action.sa_flags = 0; + if (sigaction(SIGSEGV, &action, NULL) == -1) + { + this->logger->log(this->logger, ERROR, "signal handler setup for SIGSEGV failed"); + } + return this; +} + +/** + * Main function, manages the daemon. + */ +int main(int argc, char *argv[]) +{ + private_daemon_t *private_charon; + FILE *pid_file; + struct stat stb; + int i; + + /* trivial argument parsing */ + for (i = 1; i < argc; i++) + { + if (strcmp(argv[i], "--use-syslog") == 0) + { + logger_manager->set_output(logger_manager, ALL_LOGGERS, NULL); + } + } + private_charon = daemon_create(); + charon = (daemon_t*)private_charon; + + private_charon->logger = logger_manager->get_logger(logger_manager, DAEMON); + + /* initialize daemon */ + private_charon->initialize(private_charon); + + /* check/setup PID file */ + if (stat(PID_FILE, &stb) == 0) + { + private_charon->logger->log(private_charon->logger, ERROR, + "charon already running (\""PID_FILE"\" exists)"); + private_charon->destroy(private_charon); + exit(-1); + } + pid_file = fopen(PID_FILE, "w"); + if (pid_file) + { + fprintf(pid_file, "%d\n", getpid()); + fclose(pid_file); + } + + /* run daemon */ + private_charon->run(private_charon); + + /* normal termination, cleanup and exit */ + private_charon->destroy(private_charon); + unlink(PID_FILE); + + return 0; +} + + diff --git a/src/charon/daemon.h b/src/charon/daemon.h new file mode 100644 index 000000000..5cad1339b --- /dev/null +++ b/src/charon/daemon.h @@ -0,0 +1,337 @@ +/** + * @file daemon.h + * + * @brief Interface of daemon_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef DAEMON_H_ +#define DAEMON_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * @defgroup charon charon + * + * @brief IKEv2 keying daemon. + * + * @section Architecture + * + * All IKEv2 stuff is handled in charon. It uses a newer and more flexible + * architecture than pluto. Charon uses a thread-pool, which allows parallel + * execution SA-management. Beside the thread-pool, there are some special purpose + * threads which do their job for the common health of the daemon. + @verbatim + +------+ + | E Q | + | v u |---+ +------+ +------+ + | e e | | | | | IKE- | + | n u | +-----------+ | |--| SA | + | t e | | | | I M | +------+ + +------------+ | - | | Scheduler | | K a | + | receiver | +------+ | | | E n | +------+ + +----+-------+ +-----------+ | - a | | IKE- | + | | +------+ | | S g |--| SA | + +-------+--+ +-----| J Q |---+ +------------+ | A e | +------+ + -| socket | | o u | | | | - r | + +-------+--+ | b e | | Thread- | | | + | | - u | | Pool | | | + +----+-------+ | e |------| |---| | + | sender | +------+ +------------+ +------+ + +----+-------+ + | +------+ + | | S Q | + | | e u | + | | n e | + +------------| d u | + | - e | + +--+---+ + @endverbatim + * The thread-pool is the heart of the architecture. It processes jobs from a + * (fully synchronized) job-queue. Mostly, a job is associated with a specific + * IKE SA. These IKE SAs are synchronized, only one thread can work one an IKE SA. + * This makes it unnecesary to use further synchronisation methods once a IKE SA + * is checked out. The (rather complex) synchronization of IKE SAs is completely + * done in the IKE SA manager. + * The sceduler is responsible for event firing. It waits until a event in the + * (fully synchronized) event-queue is ready for processing and pushes the event + * down to the job-queue. A thread form the pool will pick it up as quick as + * possible. Every thread can queue events or jobs. Furter, an event can place a + * packet in the send-queue. The sender thread waits for those packets and sends + * them over the wire, via the socket. The receiver does exactly the opposite of + * the sender. It waits on the socket, reads in packets an places them on the + * job-queue for further processing by a thread from the pool. + * There are even more threads, not drawn in the upper scheme. The stroke thread + * is responsible for reading and processessing commands from another process. The + * kernel interface thread handles communication from and to the kernel via a + * netlink socket. It waits for kernel events and processes them appropriately. + */ + +/** + * @defgroup config config + * + * Classes implementing configuration related things. + * + * @ingroup charon + */ + +/** + * @defgroup encoding encoding + * + * Classes used to encode and decode IKEv2 messages. + * + * @ingroup charon + */ + + /** + * @defgroup payloads payloads + * + * Classes representing specific IKEv2 payloads. + * + * @ingroup encoding + */ + +/** + * @defgroup network network + * + * Classes for network relevant stuff. + * + * @ingroup charon + */ + +/** + * @defgroup queues queues + * + * Different kind of queues + * (thread save lists). + * + * @ingroup charon + */ + +/** + * @defgroup jobs jobs + * + * Jobs used in job queue and event queue. + * + * @ingroup queues + */ + +/** + * @defgroup sa sa + * + * Security associations for IKE and IPSec, + * and some helper classes. + * + * @ingroup charon + */ + +/** + * @defgroup states states + * + * Varius states in which an IKE SA can be. + * + * @ingroup sa + */ + +/** + * @defgroup threads threads + * + * Threaded classes, which will do their job alone. + * + * @ingroup charon + */ + +/** + * Name of the daemon. + * + * @ingroup charon + */ +#define DAEMON_NAME "charon" + +/** + * @brief Number of threads in the thread pool. + * + * There are several other threads, this defines + * only the number of threads in thread_pool_t. + * + * @ingroup charon + */ +#define NUMBER_OF_WORKING_THREADS 4 + +/** + * UDP Port on which the daemon will listen for incoming traffic. + * + * @ingroup charon + */ +#define IKEV2_UDP_PORT 500 + +/** + * PID file, in which charon stores its process id + * + * @ingroup charon + */ +#define PID_FILE "/var/run/charon.pid" + +/** + * Configuration directory + * + * @ingroup charon + */ +#define CONFIG_DIR "/etc" + +/** + * Directory of IPsec relevant files + * + * @ingroup charon + */ +#define IPSEC_DIR CONFIG_DIR "/ipsec.d" + +/** + * Directory for private keys + * + * @ingroup charon + */ +#define PRIVATE_KEY_DIR IPSEC_DIR "/private" + +/** + * Directory for trusted certificates + * + * @ingroup charon + */ +#define CERTIFICATE_DIR IPSEC_DIR "/certs" + +/** + * Secrets files + * + * @ingroup charon + */ +#define SECRETS_FILE CONFIG_DIR "/ipsec.secrets" + +typedef struct daemon_t daemon_t; + +/** + * @brief Main class of daemon, contains some globals. + * + * @ingroup charon + */ +struct daemon_t { + /** + * A socket_t instance. + */ + socket_t *socket; + + /** + * A send_queue_t instance. + */ + send_queue_t *send_queue; + + /** + * A job_queue_t instance. + */ + job_queue_t *job_queue; + + /** + * A event_queue_t instance. + */ + event_queue_t *event_queue; + + /** + * A ike_sa_manager_t instance. + */ + ike_sa_manager_t *ike_sa_manager; + + /** + * A configuration_t instance. + */ + configuration_t *configuration; + + /** + * A connection_store_t instance. + */ + connection_store_t *connections; + + /** + * A policy_store_t instance. + */ + policy_store_t *policies; + + /** + * A credential_store_t instance. + */ + credential_store_t *credentials; + + /** + * The Sender-Thread. + */ + sender_t *sender; + + /** + * The Receiver-Thread. + */ + receiver_t *receiver; + + /** + * The Scheduler-Thread. + */ + scheduler_t *scheduler; + + /** + * The Thread pool managing the worker threads. + */ + thread_pool_t *thread_pool; + + /** + * Kernel Interface to communicate with kernel + */ + kernel_interface_t *kernel_interface; + + /** + * IPC interface, as whack in pluto + */ + stroke_t *stroke; + + /** + * @brief Shut down the daemon. + * + * @param this the daemon to kill + * @param reason describtion why it will be killed + */ + void (*kill) (daemon_t *this, char *reason); +}; + +/** + * The one and only instance of the daemon. + */ +extern daemon_t *charon; + +#endif /*DAEMON_H_*/ diff --git a/src/charon/encoding/Makefile.encoding b/src/charon/encoding/Makefile.encoding new file mode 100644 index 000000000..ccdb42f79 --- /dev/null +++ b/src/charon/encoding/Makefile.encoding @@ -0,0 +1,30 @@ +# Copyright (C) 2005 Jan Hutter, 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 . +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# + +ENCODING_DIR= $(CHARON_DIR)encoding/ + +CHARON_OBJS+= $(BUILD_DIR)generator.o +$(BUILD_DIR)generator.o : $(ENCODING_DIR)generator.c $(ENCODING_DIR)generator.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)parser.o +$(BUILD_DIR)parser.o : $(ENCODING_DIR)parser.c $(ENCODING_DIR)parser.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)message.o +$(BUILD_DIR)message.o : $(ENCODING_DIR)message.c $(ENCODING_DIR)message.h + $(CC) $(CFLAGS) -c -o $@ $< + + +include $(ENCODING_DIR)payloads/Makefile.payloads \ No newline at end of file diff --git a/src/charon/encoding/generator.c b/src/charon/encoding/generator.c new file mode 100644 index 000000000..ba12190dd --- /dev/null +++ b/src/charon/encoding/generator.c @@ -0,0 +1,1077 @@ +/** + * @file generator.c + * + * @brief Implementation of generator_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 +#include +#include +#include + + +#include "generator.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +typedef struct private_generator_t private_generator_t; + +/** + * Private part of a generator_t object. + */ +struct private_generator_t { + /** + * Public part of a generator_t object. + */ + generator_t public; + + /** + * Generates a U_INT-Field type and writes it to buffer. + * + * @param this private_generator_t object + * @param int_type type of U_INT field (U_INT_4, U_INT_8, etc.) + * ATTRIBUTE_TYPE is also generated in this function + * @param offset offset of value in data struct + * @param generator_contexts generator_contexts_t object where the context is written or read from + * @return + * - SUCCESS + * - FAILED if allignment is wrong + */ + void (*generate_u_int_type) (private_generator_t *this,encoding_type_t int_type,u_int32_t offset); + + /** + * Get size of current buffer in bytes. + * + * @param this private_generator_t object + * @return Size of buffer in bytes + */ + size_t (*get_current_buffer_size) (private_generator_t *this); + + /** + * Get free space of current buffer in bytes. + * + * @param this private_generator_t object + * @return space in buffer in bytes + */ + size_t (*get_current_buffer_space) (private_generator_t *this); + + /** + * Get length of data in buffer (in bytes). + * + * @param this private_generator_t object + * @return length of data in bytes + */ + size_t (*get_current_data_length) (private_generator_t *this); + + /** + * Get current offset in buffer (in bytes). + * + * @param this private_generator_t object + * @return offset in bytes + */ + u_int32_t (*get_current_buffer_offset) (private_generator_t *this); + + /** + * Generates a RESERVED BIT field or a RESERVED BYTE field and writes + * it to the buffer. + * + * @param this private_generator_t object + * @param generator_contexts generator_contexts_t object where the context is written or read from + * @param bits number of bits to generate + */ + void (*generate_reserved_field) (private_generator_t *this,int bits); + + /** + * Generates a FLAG field. + * + * @param this private_generator_t object + * @param generator_contexts generator_contexts_t object where the context is written or read from + * @param offset offset of flag value in data struct + */ + void (*generate_flag) (private_generator_t *this,u_int32_t offset); + + /** + * Writes the current buffer content into a chunk_t. + * + * Memory of specific chunk_t gets allocated. + * + * @param this calling private_generator_t object + * @param data pointer of chunk_t to write to + */ + void (*write_chunk) (private_generator_t *this,chunk_t *data); + + /** + * Generates a bytestream from a chunk_t. + * + * @param this private_generator_t object + * @param offset offset of chunk_t value in data struct + */ + void (*generate_from_chunk) (private_generator_t *this,u_int32_t offset); + + /** + * Makes sure enough space is available in buffer to store amount of bits. + * + * If buffer is to small to hold the specific amount of bits it + * is increased using reallocation function of allocator. + * + * @param this calling private_generator_t object + * @param bits number of bits to make available in buffer + */ + void (*make_space_available) (private_generator_t *this,size_t bits); + + /** + * Writes a specific amount of byte into the buffer. + * + * If buffer is to small to hold the specific amount of bytes it + * is increased. + * + * @param this calling private_generator_t object + * @param bytes pointer to bytes to write + * @param number_of_bytes number of bytes to write into buffer + */ + void (*write_bytes_to_buffer) (private_generator_t *this,void * bytes,size_t number_of_bytes); + + + /** + * Writes a specific amount of byte into the buffer at a specific offset. + * + * @warning buffer size is not check to hold the data if offset is to large. + * + * @param this calling private_generator_t object + * @param bytes pointer to bytes to write + * @param number_of_bytes number of bytes to write into buffer + * @param offset offset to write the data into + */ + void (*write_bytes_to_buffer_at_offset) (private_generator_t *this,void * bytes,size_t number_of_bytes,u_int32_t offset); + + /** + * Buffer used to generate the data into. + */ + u_int8_t *buffer; + + /** + * Current write position in buffer (one byte aligned). + */ + u_int8_t *out_position; + + /** + * Position of last byte in buffer. + */ + u_int8_t *roof_position; + + /** + * Current bit writing to in current byte (between 0 and 7). + */ + size_t current_bit; + + /** + * Associated data struct to read informations from. + */ + 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; + + /* + * Attribute format of the last generated transform attribute. + * + * Used to check if a variable value field is used or not for + * the transform attribute value. + */ + bool attribute_format; + + /* + * Depending on the value of attribute_format this field is used + * to hold the length of the transform attribute in bytes. + */ + u_int16_t attribute_length; + + /** + * Associated Logger. + */ + logger_t *logger; +}; + +/** + * Implementation of private_generator_t.get_current_buffer_size. + */ +static size_t get_current_buffer_size (private_generator_t *this) +{ + return ((this->roof_position) - (this->buffer)); +} + +/** + * Implementation of private_generator_t.get_current_buffer_space. + */ +static size_t get_current_buffer_space (private_generator_t *this) +{ + /* we know, one byte more */ + size_t space = (this->roof_position) - (this->out_position); + return (space); +} + +/** + * Implementation of private_generator_t.get_current_data_length. + */ +static size_t get_current_data_length (private_generator_t *this) +{ + return (this->out_position - this->buffer); +} + +/** + * Implementation of private_generator_t.get_current_buffer_offset. + */ +static u_int32_t get_current_buffer_offset (private_generator_t *this) +{ + return (this->out_position - this->buffer); +} + +/** + * Implementation of private_generator_t.generate_u_int_type. + */ +static void generate_u_int_type (private_generator_t *this,encoding_type_t int_type,u_int32_t offset) +{ + size_t number_of_bits = 0; + + /* find out number of bits of each U_INT type to check for enough space + in buffer */ + switch (int_type) + { + case U_INT_4: + number_of_bits = 4; + break; + case TS_TYPE: + case U_INT_8: + number_of_bits = 8; + break; + case U_INT_16: + case CONFIGURATION_ATTRIBUTE_LENGTH: + number_of_bits = 16; + break; + case U_INT_32: + number_of_bits = 32; + break; + case U_INT_64: + number_of_bits = 64; + break; + case ATTRIBUTE_TYPE: + number_of_bits = 15; + break; + case IKE_SPI: + number_of_bits = 64; + break; + + default: + this->logger->log(this->logger, ERROR, "U_INT Type %s is not supported", + mapping_find(encoding_type_m,int_type)); + + return; + } + /* U_INT Types of multiple then 8 bits must be aligned */ + if (((number_of_bits % 8) == 0) && (this->current_bit != 0)) + { + this->logger->log(this->logger, ERROR, "U_INT Type %s is not 8 Bit aligned", + mapping_find(encoding_type_m,int_type)); + /* current bit has to be zero for values multiple of 8 bits */ + return; + } + + /* make sure enough space is available in buffer */ + this->make_space_available(this,number_of_bits); + /* now handle each u int type differently */ + switch (int_type) + { + case U_INT_4: + { + if (this->current_bit == 0) + { + /* highval of current byte in buffer has to be set to the new value*/ + u_int8_t high_val = *((u_int8_t *)(this->data_struct + offset)) << 4; + /* lowval in buffer is not changed */ + u_int8_t low_val = *(this->out_position) & 0x0F; + /* highval is set, low_val is not changed */ + *(this->out_position) = high_val | low_val; + this->logger->log(this->logger, RAW|LEVEL2, " => %d", *(this->out_position)); + /* write position is not changed, just bit position is moved */ + this->current_bit = 4; + } + else if (this->current_bit == 4) + { + /* highval in buffer is not changed */ + u_int high_val = *(this->out_position) & 0xF0; + /* lowval of current byte in buffer has to be set to the new value*/ + u_int low_val = *((u_int8_t *)(this->data_struct + offset)) & 0x0F; + *(this->out_position) = high_val | low_val; + this->logger->log(this->logger, RAW|LEVEL2, " => %d", *(this->out_position)); + this->out_position++; + this->current_bit = 0; + + } + else + { + this->logger->log(this->logger, ERROR, "U_INT_4 Type is not 4 Bit aligned"); + /* 4 Bit integers must have a 4 bit alignment */ + return; + }; + break; + } + case TS_TYPE: + case U_INT_8: + { + /* 8 bit values are written as they are */ + *this->out_position = *((u_int8_t *)(this->data_struct + offset)); + this->logger->log(this->logger, RAW|LEVEL2, " => %d", *(this->out_position)); + this->out_position++; + break; + + } + case ATTRIBUTE_TYPE: + { + /* attribute type must not change first bit uf current byte ! */ + if (this->current_bit != 1) + { + this->logger->log(this->logger, ERROR, "ATTRIBUTE FORMAT flag is not set"); + /* first bit has to be set! */ + return; + } + /* get value of attribute format flag */ + u_int8_t attribute_format_flag = *(this->out_position) & 0x80; + /* get attribute type value as 16 bit integer*/ + u_int16_t int16_val = htons(*((u_int16_t*)(this->data_struct + offset))); + /* last bit must be unset */ + int16_val = int16_val & 0xFF7F; + + int16_val = int16_val | attribute_format_flag; + this->logger->log(this->logger, RAW|LEVEL2, " => %d", int16_val); + /* write bytes to buffer (set bit is overwritten)*/ + this->write_bytes_to_buffer(this,&int16_val,sizeof(u_int16_t)); + this->current_bit = 0; + break; + + } + case U_INT_16: + case CONFIGURATION_ATTRIBUTE_LENGTH: + { + u_int16_t int16_val = htons(*((u_int16_t*)(this->data_struct + offset))); + this->logger->log_bytes(this->logger, RAW|LEVEL2, " =>", (void*)&int16_val, sizeof(int16_val)); + this->write_bytes_to_buffer(this,&int16_val,sizeof(u_int16_t)); + break; + } + case U_INT_32: + { + u_int32_t int32_val = htonl(*((u_int32_t*)(this->data_struct + offset))); + this->logger->log_bytes(this->logger, RAW|LEVEL2, " =>", (void*)&int32_val, sizeof(int32_val)); + this->write_bytes_to_buffer(this,&int32_val,sizeof(u_int32_t)); + break; + } + case U_INT_64: + { + /* 64 bit integers are written as two 32 bit integers */ + u_int32_t int32_val_low = htonl(*((u_int32_t*)(this->data_struct + offset))); + u_int32_t int32_val_high = htonl(*((u_int32_t*)(this->data_struct + offset) + 1)); + this->logger->log_bytes(this->logger, RAW|LEVEL2, " => (low)", (void*)&int32_val_low, sizeof(int32_val_low)); + this->logger->log_bytes(this->logger, RAW|LEVEL2, " => (high)", (void*)&int32_val_high, sizeof(int32_val_high)); + /* TODO add support for big endian machines */ + this->write_bytes_to_buffer(this,&int32_val_high,sizeof(u_int32_t)); + this->write_bytes_to_buffer(this,&int32_val_low,sizeof(u_int32_t)); + break; + } + + case IKE_SPI: + { + /* 64 bit are written as they come :-) */ + this->write_bytes_to_buffer(this,(this->data_struct + offset),sizeof(u_int64_t)); + this->logger->log_bytes(this->logger, RAW|LEVEL2, " =>", (void*)(this->data_struct + offset), sizeof(u_int64_t)); + break; + } + default: + { + this->logger->log(this->logger, ERROR, "U_INT Type %s is not supported", mapping_find(encoding_type_m,int_type)); + return; + } + } +} + +/** + * Implementation of private_generator_t.generate_reserved_field. + */ +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)) + { + this->logger->log(this->logger, ERROR, "Reserved field of %d bits cannot be generated", bits); + return ; + } + /* make sure enough space is available in buffer */ + this->make_space_available(this,bits); + + if (bits == 1) + { + /* one bit processing */ + 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 + { + /* one byte processing*/ + if (this->current_bit > 0) + { + this->logger->log(this->logger, ERROR, + "Reserved field cannot be written cause allignement of current bit is %d", + this->current_bit); + return; + } + *(this->out_position) = 0x00; + this->out_position++; + } +} + +/** + * Implementation of private_generator_t.generate_flag. + */ +static void generate_flag (private_generator_t *this,u_int32_t offset) +{ + /* value of current flag */ + u_int8_t flag_value; + /* position of flag in current byte */ + u_int8_t flag; + + /* if the value in the data_struct is TRUE, flag_value is set to 1, 0 otherwise */ + flag_value = (*((bool *) (this->data_struct + offset))) ? 1 : 0; + /* get flag position */ + flag = (flag_value << (7 - this->current_bit)); + + /* make sure one bit is available in buffer */ + this->make_space_available(this,1); + if (this->current_bit == 0) + { + /* memory must be zero */ + *(this->out_position) = 0x00; + } + + *(this->out_position) = *(this->out_position) | flag; + + + this->logger->log(this->logger, RAW|LEVEL2, " => %d", *(this->out_position)); + + this->current_bit++; + if (this->current_bit >= 8) + { + this->current_bit = this->current_bit % 8; + this->out_position++; + } +} + +/** + * Implementation of private_generator_t.generate_from_chunk. + */ +static void generate_from_chunk (private_generator_t *this,u_int32_t offset) +{ + if (this->current_bit != 0) + { + this->logger->log(this->logger, ERROR, "can not generate a chunk at Bitpos %d", this->current_bit); + return ; + } + + /* position in buffer */ + chunk_t *attribute_value = (chunk_t *)(this->data_struct + offset); + + this->logger->log_chunk(this->logger, RAW|LEVEL2, " =>", *attribute_value); + + /* use write_bytes_to_buffer function to do the job */ + this->write_bytes_to_buffer(this,attribute_value->ptr,attribute_value->len); +} + +/** + * Implementation of private_generator_t.make_space_available. + */ +static void make_space_available (private_generator_t *this, size_t bits) +{ + while (((this->get_current_buffer_space(this) * 8) - this->current_bit) < bits) + { + /* must increase buffer */ + size_t old_buffer_size = this->get_current_buffer_size(this); + size_t new_buffer_size = old_buffer_size + GENERATOR_DATA_BUFFER_INCREASE_VALUE; + size_t out_position_offset = ((this->out_position) - (this->buffer)); + + this->logger->log(this->logger, CONTROL|LEVEL3, "increased gen buffer from %d to %d byte", + old_buffer_size, new_buffer_size); + + /* Reallocate space for new buffer */ + this->buffer = realloc(this->buffer,new_buffer_size); + + this->out_position = (this->buffer + out_position_offset); + this->roof_position = (this->buffer + new_buffer_size); + } +} + +/** + * Implementation of private_generator_t.write_bytes_to_buffer. + */ +static void write_bytes_to_buffer (private_generator_t *this,void * bytes, size_t number_of_bytes) +{ + int i; + u_int8_t *read_position = (u_int8_t *) bytes; + + this->make_space_available(this,number_of_bytes * 8); + + for (i = 0; i < number_of_bytes; i++) + { + *(this->out_position) = *(read_position); + read_position++; + this->out_position++; + } +} + +/** + * Implementation of private_generator_t.write_bytes_to_buffer_at_offset. + */ +static void write_bytes_to_buffer_at_offset (private_generator_t *this,void * bytes,size_t 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 = (this->get_current_buffer_size(this) - offset); + + /* check first if enough space for new data is available */ + if (number_of_bytes > free_space_after_offset) + { + this->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++; + } +} + +/** + * Implementation of private_generator_t.write_to_chunk. + */ +static void write_to_chunk (private_generator_t *this,chunk_t *data) +{ + size_t data_length = this->get_current_data_length(this); + u_int32_t header_length_field = data_length; + + /* write length into header length field */ + if (this->header_length_position_offset > 0) + { + u_int32_t int32_val = htonl(header_length_field); + this->write_bytes_to_buffer_at_offset(this,&int32_val,sizeof(u_int32_t),this->header_length_position_offset); + } + + if (this->current_bit > 0) + data_length++; + data->ptr = malloc(data_length); + memcpy(data->ptr,this->buffer,data_length); + data->len = data_length; + + this->logger->log_chunk(this->logger, RAW|LEVEL3, "generated data of this generator", *data); +} + +/** + * Implementation of private_generator_t.generate_payload. + */ +static void generate_payload (private_generator_t *this,payload_t *payload) +{ + int i; + this->data_struct = payload; + size_t rule_count; + encoding_rule_t *rules; + payload_type_t payload_type; + u_int8_t *payload_start; + + /* get payload type */ + payload_type = payload->get_type(payload); + /* spi size has to get reseted */ + this->last_spi_size = 0; + + payload_start = this->out_position; + + this->logger->log(this->logger, CONTROL|LEVEL1, "generating payload of type %s", + mapping_find(payload_type_m,payload_type)); + + /* each payload has its own encoding rules */ + payload->get_encoding_rules(payload,&rules,&rule_count); + + for (i = 0; i < rule_count;i++) + { + this->logger->log(this->logger, CONTROL|LEVEL2, " generating rule %d %s", + i, mapping_find(encoding_type_m,rules[i].type)); + switch (rules[i].type) + { + /* all u int values, IKE_SPI,TS_TYPE and ATTRIBUTE_TYPE are generated in generate_u_int_type */ + case U_INT_4: + case U_INT_8: + case U_INT_16: + case U_INT_32: + case U_INT_64: + case IKE_SPI: + case TS_TYPE: + case ATTRIBUTE_TYPE: + case CONFIGURATION_ATTRIBUTE_LENGTH: + { + this->generate_u_int_type(this,rules[i].type,rules[i].offset); + break; + } + case RESERVED_BIT: + { + this->generate_reserved_field(this,1); + break; + } + case RESERVED_BYTE: + { + this->generate_reserved_field(this,8); + break; + } + case FLAG: + { + this->generate_flag(this,rules[i].offset); + break; + } + case PAYLOAD_LENGTH: + { + /* position of payload lenght field is temporary stored */ + this->last_payload_length_position_offset = this->get_current_buffer_offset(this); + /* payload length is generated like an U_INT_16 */ + this->generate_u_int_type(this,U_INT_16,rules[i].offset); + break; + } + case HEADER_LENGTH: + { + /* position of header length field is temporary stored */ + this->header_length_position_offset = this->get_current_buffer_offset(this); + /* header length is generated like an U_INT_32 */ + this->generate_u_int_type(this,U_INT_32,rules[i].offset); + break; + } + case SPI_SIZE: + /* spi size is handled as 8 bit unsigned integer */ + this->generate_u_int_type(this,U_INT_8,rules[i].offset); + /* last spi size is temporary stored */ + this->last_spi_size = *((u_int8_t *)(this->data_struct + rules[i].offset)); + break; + case ADDRESS: + { + /* the Address value is generated from chunk */ + this->generate_from_chunk(this,rules[i].offset); + break; + } + case SPI: + { + /* the SPI value is generated from chunk */ + this->generate_from_chunk(this,rules[i].offset); + break; + } + case KEY_EXCHANGE_DATA: + case NOTIFICATION_DATA: + case NONCE_DATA: + case ID_DATA: + case AUTH_DATA: + case CERT_DATA: + case CERTREQ_DATA: + case SPIS: + case CONFIGURATION_ATTRIBUTE_VALUE: + case VID_DATA: + case EAP_MESSAGE: + { + 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_MESSAGE: + header_length = EAP_PAYLOAD_HEADER_LENGTH; + break; + default: + break; + } + + /* the data value is generated from chunk */ + this->generate_from_chunk(this,rules[i].offset); + + payload_length_position_offset = this->last_payload_length_position_offset; + + + /* Length of payload is calculated */ + length_of_payload = header_length + ((chunk_t *)(this->data_struct + rules[i].offset))->len; + + length_in_network_order = htons(length_of_payload); + this->write_bytes_to_buffer_at_offset(this,&length_in_network_order,sizeof(u_int16_t),payload_length_position_offset); + break; + } + case PROPOSALS: + { + /* before iterative generate the transforms, store the current payload length position */ + 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; + /* proposals are stored in a linked list and so accessed */ + linked_list_t *proposals = *((linked_list_t **)(this->data_struct + rules[i].offset)); + + iterator_t *iterator; + /* create forward iterator */ + iterator = proposals->create_iterator(proposals,TRUE); + /* every proposal is processed (iterative call )*/ + while (iterator->has_next(iterator)) + { + payload_t *current_proposal; + u_int32_t before_generate_position_offset; + u_int32_t after_generate_position_offset; + + iterator->current(iterator,(void **)¤t_proposal); + + before_generate_position_offset = this->get_current_buffer_offset(this); + this->public.generate_payload(&(this->public),current_proposal); + after_generate_position_offset = this->get_current_buffer_offset(this); + + /* increase size of transform */ + length_of_sa_payload += (after_generate_position_offset - before_generate_position_offset); + } + iterator->destroy(iterator); + + int16_val = htons(length_of_sa_payload); + this->write_bytes_to_buffer_at_offset(this,&int16_val,sizeof(u_int16_t),payload_length_position_offset); + break; + } + case TRANSFORMS: + { + /* before iterative generate the transforms, store the current length position */ + 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; + + /* create forward iterator */ + iterator = transforms->create_iterator(transforms,TRUE); + while (iterator->has_next(iterator)) + { + payload_t *current_transform; + u_int32_t before_generate_position_offset; + u_int32_t after_generate_position_offset; + + iterator->current(iterator,(void **)¤t_transform); + + before_generate_position_offset = this->get_current_buffer_offset(this); + this->public.generate_payload(&(this->public),current_transform); + after_generate_position_offset = this->get_current_buffer_offset(this); + + /* increase size of transform */ + length_of_proposal += (after_generate_position_offset - before_generate_position_offset); + } + + iterator->destroy(iterator); + + int16_val = htons(length_of_proposal); + this->write_bytes_to_buffer_at_offset(this,&int16_val,sizeof(u_int16_t),payload_length_position_offset); + + break; + } + case TRANSFORM_ATTRIBUTES: + { + /* before iterative generate the transform attributes, store the current length position */ + 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; + /* create forward iterator */ + iterator = transform_attributes->create_iterator(transform_attributes,TRUE); + while (iterator->has_next(iterator)) + { + payload_t *current_attribute; + u_int32_t before_generate_position_offset; + u_int32_t after_generate_position_offset; + + iterator->current(iterator,(void **)¤t_attribute); + + before_generate_position_offset = this->get_current_buffer_offset(this); + this->public.generate_payload(&(this->public),current_attribute); + after_generate_position_offset = this->get_current_buffer_offset(this); + + /* increase size of transform */ + length_of_transform += (after_generate_position_offset - before_generate_position_offset); + } + + iterator->destroy(iterator); + + int16_val = htons(length_of_transform); + this->write_bytes_to_buffer_at_offset(this,&int16_val,sizeof(u_int16_t),transform_length_position_offset); + + break; + } + case CONFIGURATION_ATTRIBUTES: + { + /* before iterative generate the configuration attributes, store the current length position */ + 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; + /* create forward iterator */ + iterator = configuration_attributes->create_iterator(configuration_attributes,TRUE); + while (iterator->has_next(iterator)) + { + payload_t *current_attribute; + u_int32_t before_generate_position_offset; + u_int32_t after_generate_position_offset; + + iterator->current(iterator,(void **)¤t_attribute); + + before_generate_position_offset = this->get_current_buffer_offset(this); + this->public.generate_payload(&(this->public),current_attribute); + after_generate_position_offset = this->get_current_buffer_offset(this); + + /* increase size of transform */ + length_of_configurations += (after_generate_position_offset - before_generate_position_offset); + } + + iterator->destroy(iterator); + + int16_val = htons(length_of_configurations); + this->write_bytes_to_buffer_at_offset(this,&int16_val,sizeof(u_int16_t),configurations_length_position_offset); + + break; + } + case ATTRIBUTE_FORMAT: + { + this->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) + { + this->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 + { + this->generate_u_int_type(this,U_INT_16,rules[i].offset); + } + break; + } + case ATTRIBUTE_VALUE: + { + if (this->attribute_format == FALSE) + { + this->logger->log(this->logger, CONTROL|LEVEL3, "attribute value has not fixed size"); + /* the attribute value is generated */ + this->generate_from_chunk(this,rules[i].offset); + } + break; + } + case TRAFFIC_SELECTORS: + { + /* before iterative generate the traffic_selectors, store the current payload length position */ + u_int32_t payload_length_position_offset = this->last_payload_length_position_offset; + /* Length of SA_PAYLOAD is calculated */ + u_int16_t length_of_ts_payload = TS_PAYLOAD_HEADER_LENGTH; + u_int16_t int16_val; + /* traffic selectors are stored in a linked list and so accessed */ + linked_list_t *traffic_selectors = *((linked_list_t **)(this->data_struct + rules[i].offset)); + + iterator_t *iterator; + /* create forward iterator */ + iterator = traffic_selectors->create_iterator(traffic_selectors,TRUE); + /* every proposal is processed (iterative call )*/ + while (iterator->has_next(iterator)) + { + payload_t *current_traffic_selector_substructure; + u_int32_t before_generate_position_offset; + u_int32_t after_generate_position_offset; + + iterator->current(iterator,(void **)¤t_traffic_selector_substructure); + + before_generate_position_offset = this->get_current_buffer_offset(this); + this->public.generate_payload(&(this->public),current_traffic_selector_substructure); + after_generate_position_offset = this->get_current_buffer_offset(this); + + /* increase size of transform */ + length_of_ts_payload += (after_generate_position_offset - before_generate_position_offset); + } + iterator->destroy(iterator); + + int16_val = htons(length_of_ts_payload); + this->write_bytes_to_buffer_at_offset(this,&int16_val,sizeof(u_int16_t),payload_length_position_offset); + break; + } + + case ENCRYPTED_DATA: + { + this->generate_from_chunk(this, rules[i].offset); + break; + } + default: + this->logger->log(this->logger, ERROR, "field type %s is not supported", + mapping_find(encoding_type_m,rules[i].type)); + return; + } + } + this->logger->log(this->logger, CONTROL|LEVEL2, "generating %s payload finished.", + mapping_find(payload_type_m, payload_type)); + this->logger->log_bytes(this->logger, RAW|LEVEL3, "generated data for this payload", + payload_start, this->out_position-payload_start); +} + +/** + * Implementation of generator_t.destroy. + */ +static status_t destroy(private_generator_t *this) +{ + free(this->buffer); + free(this); + return SUCCESS; +} + +/* + * Described in header + */ +generator_t *generator_create() +{ + private_generator_t *this; + + this = malloc_thing(private_generator_t); + + /* initiate public functions */ + this->public.generate_payload = (void(*)(generator_t*, payload_t *)) generate_payload; + this->public.destroy = (void(*)(generator_t*)) destroy; + this->public.write_to_chunk = (void (*) (generator_t *,chunk_t *)) write_to_chunk; + + + /* initiate private functions */ + this->get_current_buffer_size = get_current_buffer_size; + this->get_current_buffer_space = get_current_buffer_space; + this->get_current_data_length = get_current_data_length; + this->get_current_buffer_offset = get_current_buffer_offset; + this->generate_u_int_type = generate_u_int_type; + this->generate_reserved_field = generate_reserved_field; + this->generate_flag = generate_flag; + this->generate_from_chunk = generate_from_chunk; + this->make_space_available = make_space_available; + this->write_bytes_to_buffer = write_bytes_to_buffer; + this->write_bytes_to_buffer_at_offset = write_bytes_to_buffer_at_offset; + + + /* allocate memory for buffer */ + this->buffer = malloc(GENERATOR_DATA_BUFFER_SIZE); + + /* initiate private variables */ + this->out_position = this->buffer; + this->roof_position = this->buffer + GENERATOR_DATA_BUFFER_SIZE; + this->data_struct = NULL; + this->current_bit = 0; + this->last_payload_length_position_offset = 0; + this->header_length_position_offset = 0; + this->logger = logger_manager->get_logger(logger_manager, GENERATOR); + + return &(this->public); +} diff --git a/src/charon/encoding/generator.h b/src/charon/encoding/generator.h new file mode 100644 index 000000000..4bbca162a --- /dev/null +++ b/src/charon/encoding/generator.h @@ -0,0 +1,101 @@ +/** + * @file generator.h + * + * @brief Interface of generator_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef GENERATOR_H_ +#define GENERATOR_H_ + +#include +#include +#include + +/** + * Generating is done in a data buffer. + * This is thehe start size of this buffer in bytes. + * + * @ingroup enconding + */ +#define GENERATOR_DATA_BUFFER_SIZE 500 + +/** + * Number of bytes to increase the buffer, if it is to small. + * + * @ingroup enconding + */ +#define GENERATOR_DATA_BUFFER_INCREASE_VALUE 500 + + +typedef struct generator_t generator_t; + +/** + * @brief A generator_t class used to generate IKEv2 payloads. + * + * After creation, multiple payloads can be generated with the generate_payload + * method. The generated bytes are appended. After all payloads are added, + * the write_to_chunk method writes out all generated data since + * the creation of the generator. After that, the generator must be destroyed. + * The generater uses a set of encoding rules, which it can get from + * the supplied payload. With this rules, the generater can generate + * the payload and all substructures automatically. + * + * @b Constructor: + * - generator_create() + * + * @ingroup encoding + */ +struct generator_t { + + /** + * @brief Generates a specific payload from given payload object. + * + * Remember: Header and substructures are also handled as payloads. + * + * @param this generator_t object + * @param[in] payload interface payload_t implementing object + */ + void (*generate_payload) (generator_t *this,payload_t *payload); + + /** + * @brief Writes all generated data of the generator to a chunk. + * + * @param this generator_t object + * @param[out] data chunk to write the data to + */ + void (*write_to_chunk) (generator_t *this,chunk_t *data); + + /** + * @brief Destroys a generator_t object. + * + * @param this generator_t object + */ + void (*destroy) (generator_t *this); +}; + +/** + * @brief Constructor to create a generator. + * + * @return generator_t object. + * + * @ingroup encoding + */ +generator_t *generator_create(void); + +#endif /*GENERATOR_H_*/ diff --git a/src/charon/encoding/message.c b/src/charon/encoding/message.c new file mode 100644 index 000000000..a57315272 --- /dev/null +++ b/src/charon/encoding/message.c @@ -0,0 +1,1251 @@ +/** + * @file message.c + * + * @brief Implementation of message_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 + +#include "message.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * Max number of notify payloads per IKEv2 Message + */ +#define MAX_NOTIFY_PAYLOADS 10 + + +typedef struct payload_rule_t payload_rule_t; + +/** + * A payload rule defines the rules for a payload + * in a specific message rule. It defines if and how + * many times a payload must/can occur in a message + * and if it must be encrypted. + */ +struct payload_rule_t { + /** + * Payload type. + */ + payload_type_t payload_type; + + /** + * Minimal occurence of this payload. + */ + size_t min_occurence; + + /** + * Max occurence of this payload. + */ + size_t max_occurence; + + /** + * TRUE if payload must be encrypted + */ + bool encrypted; + + /** + * If this payload occurs, the message rule is + * fullfilled in any case. This applies e.g. to + * notify_payloads. + */ + bool sufficient; +}; + +typedef struct message_rule_t message_rule_t; + +/** + * A message rule defines the kind of a message, + * if it has encrypted contents and a list + * of payload rules. + * + */ +struct message_rule_t { + /** + * Type of message. + */ + exchange_type_t exchange_type; + + /** + * Is message a request or response. + */ + bool is_request; + + /** + * Message contains encrypted content. + */ + bool encrypted_content; + + /** + * Number of payload rules which will follow + */ + size_t payload_rule_count; + + /** + * Pointer to first payload rule + */ + payload_rule_t *payload_rules; +}; + +/** + * Message rule for IKE_SA_INIT from initiator. + */ +static payload_rule_t ike_sa_init_i_payload_rules[] = { + {NOTIFY,0,MAX_NOTIFY_PAYLOADS,FALSE,FALSE}, + {SECURITY_ASSOCIATION,1,1,FALSE,FALSE}, + {KEY_EXCHANGE,1,1,FALSE,FALSE}, + {NONCE,1,1,FALSE,FALSE}, +}; + +/** + * Message rule for IKE_SA_INIT from responder. + */ +static payload_rule_t ike_sa_init_r_payload_rules[] = { + {NOTIFY,0,MAX_NOTIFY_PAYLOADS,FALSE,TRUE}, + {SECURITY_ASSOCIATION,1,1,FALSE,FALSE}, + {KEY_EXCHANGE,1,1,FALSE,FALSE}, + {NONCE,1,1,FALSE,FALSE}, +}; + +/** + * Message rule for IKE_AUTH from initiator. + */ +static payload_rule_t ike_auth_i_payload_rules[] = { + {NOTIFY,0,MAX_NOTIFY_PAYLOADS,TRUE,FALSE}, + {ID_INITIATOR,1,1,TRUE,FALSE}, + {CERTIFICATE,0,1,TRUE,FALSE}, + {CERTIFICATE_REQUEST,0,1,TRUE,FALSE}, + {ID_RESPONDER,0,1,TRUE,FALSE}, + {AUTHENTICATION,1,1,TRUE,FALSE}, + {SECURITY_ASSOCIATION,1,1,TRUE,FALSE}, + {TRAFFIC_SELECTOR_INITIATOR,1,1,TRUE,FALSE}, + {TRAFFIC_SELECTOR_RESPONDER,1,1,TRUE,FALSE}, + {CONFIGURATION,0,1,TRUE,FALSE}, +}; + +/** + * Message rule for IKE_AUTH from responder. + */ +static payload_rule_t ike_auth_r_payload_rules[] = { + {NOTIFY,0,MAX_NOTIFY_PAYLOADS,TRUE,TRUE}, + {CERTIFICATE,0,1,TRUE,FALSE}, + {ID_RESPONDER,1,1,TRUE,FALSE}, + {AUTHENTICATION,1,1,TRUE,FALSE}, + {SECURITY_ASSOCIATION,1,1,TRUE,FALSE}, + {TRAFFIC_SELECTOR_INITIATOR,1,1,TRUE,FALSE}, + {TRAFFIC_SELECTOR_RESPONDER,1,1,TRUE,FALSE}, + {CONFIGURATION,0,1,TRUE,FALSE}, +}; + + +/** + * Message rule for INFORMATIONAL from initiator. + */ +static payload_rule_t informational_i_payload_rules[] = { + {NOTIFY,0,MAX_NOTIFY_PAYLOADS,TRUE,FALSE}, + {CONFIGURATION,0,1,TRUE,FALSE}, + {DELETE,0,1,TRUE,FALSE}, + +}; + +/** + * Message rule for INFORMATIONAL from responder. + */ +static payload_rule_t informational_r_payload_rules[] = { + {NOTIFY,0,MAX_NOTIFY_PAYLOADS,TRUE,FALSE}, + {CONFIGURATION,0,1,TRUE,FALSE}, + {DELETE,0,1,TRUE,FALSE}, +}; + + +/** + * Message rules, defines allowed payloads. + */ +static message_rule_t message_rules[] = { + {IKE_SA_INIT,TRUE,FALSE,(sizeof(ike_sa_init_i_payload_rules)/sizeof(payload_rule_t)),ike_sa_init_i_payload_rules}, + {IKE_SA_INIT,FALSE,FALSE,(sizeof(ike_sa_init_r_payload_rules)/sizeof(payload_rule_t)),ike_sa_init_r_payload_rules}, + {IKE_AUTH,TRUE,TRUE,(sizeof(ike_auth_i_payload_rules)/sizeof(payload_rule_t)),ike_auth_i_payload_rules}, + {IKE_AUTH,FALSE,TRUE,(sizeof(ike_auth_r_payload_rules)/sizeof(payload_rule_t)),ike_auth_r_payload_rules}, + {INFORMATIONAL,TRUE,TRUE,(sizeof(informational_i_payload_rules)/sizeof(payload_rule_t)),informational_i_payload_rules}, + {INFORMATIONAL,FALSE,TRUE,(sizeof(informational_r_payload_rules)/sizeof(payload_rule_t)),informational_r_payload_rules} +}; + + +typedef struct private_message_t private_message_t; + +/** + * Private data of an message_t object. + */ +struct private_message_t { + + /** + * Public part of a message_t object. + */ + message_t public; + + /** + * Minor version of message. + */ + u_int8_t major_version; + + /** + * Major version of message. + */ + u_int8_t minor_version; + + /** + * First Payload in message. + */ + payload_type_t first_payload; + + /** + * Assigned exchange type. + */ + exchange_type_t exchange_type; + + /** + * TRUE if message is a request, FALSE if a reply. + */ + bool is_request; + + /** + * Message ID of this message. + */ + u_int32_t message_id; + + /** + * ID of assigned IKE_SA. + */ + ike_sa_id_t *ike_sa_id; + + /** + * Assigned UDP packet, stores incoming packet or last generated one. + */ + packet_t *packet; + + /** + * Linked List where payload data are stored in. + */ + linked_list_t *payloads; + + /** + * Assigned parser to parse Header and Body of this message. + */ + parser_t *parser; + + /** + * The message rule for this message instance + */ + message_rule_t *message_rule; + + /** + * Assigned logger. + */ + logger_t *logger; + + /** + * Sets the private message_rule member to the rule which + * applies to this message. Must be called before get_payload_rule(). + * + * @param this calling object + * @return + * - SUCCESS + * - NOT_FOUND if no message rule applies to this message. + */ + status_t (*set_message_rule) (private_message_t *this); + + /** + * Gets the payload_rule_t for a specific message_rule_t and payload type. + * + * @param this calling object + * @param payload_type payload type + * @param[out] payload_rule returned payload_rule_t + * @return + * - SUCCESS + * - NOT_FOUND if payload not defined in current message rule + * - INVALID_STATE if message rule is not set via set_message_rule() + */ + status_t (*get_payload_rule) (private_message_t *this, payload_type_t payload_type, payload_rule_t **payload_rule); + + /** + * Encrypts all payloads which has to get encrypted. + * + * Can also be called with messages not containing encrypted content. + * + * @param this calling object + * @param crypter crypter_t object + * @param signer signer_t object + * @return + * - SUCCESS + * - INVALID_STATE if no crypter/signer supplied but needed + */ + status_t (*encrypt_payloads) (private_message_t *this,crypter_t *crypter, signer_t* signer); + + /** + * Decrypts encrypted contents, and checks if a payload is encrypted if it has to be. + * + * @param this calling object + * @param crypter crypter_t object + * @param signer signer_t object + * @return + * - SUCCESS + * - FAILED if decryption not successfull + * - INVALID_STATE if no crypter/signer supplied but needed + */ + status_t (*decrypt_payloads) (private_message_t *this,crypter_t *crypter, signer_t* signer); + + /** + * Verifies the message. Checks for payloads count. + * + * @param calling object + * @return + * - SUCCESS if message valid, or + * - FAILED if message does not align with message rules. + */ + status_t (*verify) (private_message_t *this); +}; + +/** + * Implementation of private_message_t.set_message_rule. + */ +static status_t set_message_rule(private_message_t *this) +{ + int i; + + for (i = 0; i < (sizeof(message_rules) / sizeof(message_rule_t)); i++) + { + if ((this->exchange_type == message_rules[i].exchange_type) && + (this->is_request == message_rules[i].is_request)) + { + /* found rule for given exchange_type*/ + this->message_rule = &(message_rules[i]); + return SUCCESS; + } + } + this->message_rule = NULL; + return NOT_FOUND; +} + +/** + * Implementation of private_message_t.get_payload_rule. + */ +static status_t get_payload_rule(private_message_t *this, payload_type_t payload_type, payload_rule_t **payload_rule) +{ + int i; + + for (i = 0; i < this->message_rule->payload_rule_count;i++) + { + if (this->message_rule->payload_rules[i].payload_type == payload_type) + { + *payload_rule = &(this->message_rule->payload_rules[i]); + return SUCCESS; + } + } + + *payload_rule = NULL; + return NOT_FOUND; +} + +/** + * Implementation of message_t.set_ike_sa_id. + */ +static void set_ike_sa_id (private_message_t *this,ike_sa_id_t *ike_sa_id) +{ + this->ike_sa_id = ike_sa_id->clone(ike_sa_id); +} + +/** + * Implementation of message_t.get_ike_sa_id. + */ +static status_t get_ike_sa_id (private_message_t *this,ike_sa_id_t **ike_sa_id) +{ + if (this->ike_sa_id == NULL) + { + return FAILED; + } + *ike_sa_id = this->ike_sa_id->clone(this->ike_sa_id); + return SUCCESS; +} + +/** + * Implementation of message_t.set_message_id. + */ +static void set_message_id (private_message_t *this,u_int32_t message_id) +{ + this->message_id = message_id; +} + +/** + * Implementation of message_t.get_message_id. + */ +static u_int32_t get_message_id (private_message_t *this) +{ + return this->message_id; +} + +/** + * Implementation of message_t.get_responder_spi. + */ +static u_int64_t get_responder_spi (private_message_t *this) +{ + return (this->ike_sa_id->get_responder_spi(this->ike_sa_id)); +} + +/** + * Implementation of message_t.set_major_version. + */ +static void set_major_version (private_message_t *this,u_int8_t major_version) +{ + this->major_version = major_version; +} + + +/** + * Implementation of message_t.set_major_version. + */ +static u_int8_t get_major_version (private_message_t *this) +{ + return this->major_version; +} + +/** + * Implementation of message_t.set_minor_version. + */ +static void set_minor_version (private_message_t *this,u_int8_t minor_version) +{ + this->minor_version = minor_version; +} + +/** + * Implementation of message_t.get_minor_version. + */ +static u_int8_t get_minor_version (private_message_t *this) +{ + return this->minor_version; +} + +/** + * Implementation of message_t.set_exchange_type. + */ +static void set_exchange_type (private_message_t *this,exchange_type_t exchange_type) +{ + this->exchange_type = exchange_type; +} + +/** + * Implementation of message_t.get_exchange_type. + */ +static exchange_type_t get_exchange_type (private_message_t *this) +{ + return this->exchange_type; +} + +/** + * Implementation of message_t.set_request. + */ +static void set_request (private_message_t *this,bool request) +{ + this->is_request = request; +} + +/** + * Implementation of message_t.get_request. + */ +static exchange_type_t get_request (private_message_t *this) +{ + return this->is_request; +} + +/** + * Implementation of message_t.add_payload. + */ +static void add_payload(private_message_t *this, payload_t *payload) +{ + payload_t *last_payload; + if (this->payloads->get_count(this->payloads) > 0) + { + this->payloads->get_last(this->payloads,(void **) &last_payload); + last_payload->set_next_type(last_payload, payload->get_type(payload)); + } + else + { + this->first_payload = payload->get_type(payload); + } + payload->set_next_type(payload, NO_PAYLOAD); + this->payloads->insert_last(this->payloads, (void*)payload); + + this->logger->log(this->logger, CONTROL|LEVEL1, "Added payload of type %s to message", + mapping_find(payload_type_m, payload->get_type(payload))); +} + +/** + * Implementation of message_t.set_source. + */ +static void set_source(private_message_t *this, host_t *host) +{ + this->packet->set_source(this->packet, host); +} + +/** + * Implementation of message_t.set_destination. + */ +static void set_destination(private_message_t *this, host_t *host) +{ + + this->packet->set_destination(this->packet, host); +} + +/** + * Implementation of message_t.get_source. + */ +static host_t* get_source(private_message_t *this) +{ + return this->packet->get_source(this->packet); +} + +/** + * Implementation of message_t.get_destination. + */ +static host_t * get_destination(private_message_t *this) +{ + return this->packet->get_destination(this->packet); +} + +/** + * Implementation of message_t.get_destination. + */ +static iterator_t *get_payload_iterator(private_message_t *this) +{ + return this->payloads->create_iterator(this->payloads, TRUE); +} + + +/** + * Implementation of message_t.generate. + */ +static status_t generate(private_message_t *this, crypter_t *crypter, signer_t* signer, packet_t **packet) +{ + generator_t *generator; + ike_header_t *ike_header; + payload_t *payload, *next_payload; + iterator_t *iterator; + status_t status; + chunk_t packet_data; + + this->logger->log(this->logger, CONTROL, "Generating message of type %s, contains %d payloads", + mapping_find(exchange_type_m,this->exchange_type), + this->payloads->get_count(this->payloads)); + + if (this->exchange_type == EXCHANGE_TYPE_UNDEFINED) + { + this->logger->log(this->logger, ERROR | LEVEL1, "Exchange type %s is not defined", + mapping_find(exchange_type_m,this->exchange_type)); + return INVALID_STATE; + } + + if (this->packet->get_source(this->packet) == NULL || + this->packet->get_destination(this->packet) == NULL) + { + this->logger->log(this->logger, ERROR|LEVEL1, "%s not defined", + !this->packet->get_source(this->packet) ? "source" : "destination"); + return INVALID_STATE; + } + + /* set the rules for this messge */ + status = this->set_message_rule(this); + if (status != SUCCESS) + { + this->logger->log(this->logger, ERROR, "No message rules specified for a %s %s", + mapping_find(exchange_type_m,this->exchange_type), + this->is_request ? "request" : "response"); + return NOT_SUPPORTED; + } + + + /* going to encrypt all content which have to be encrypted */ + status = this->encrypt_payloads(this, crypter, signer); + if (status != SUCCESS) + { + this->logger->log(this->logger, ERROR | LEVEL1, "Could not encrypt payloads"); + return status; + } + + /* build ike header */ + ike_header = ike_header_create(); + + 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_initiator_flag(ike_header, this->ike_sa_id->is_initiator(this->ike_sa_id)); + ike_header->set_initiator_spi(ike_header, this->ike_sa_id->get_initiator_spi(this->ike_sa_id)); + ike_header->set_responder_spi(ike_header, this->ike_sa_id->get_responder_spi(this->ike_sa_id)); + + generator = generator_create(); + + payload = (payload_t*)ike_header; + + + /* generate every payload expect last one, this is doen later*/ + iterator = this->payloads->create_iterator(this->payloads, TRUE); + while(iterator->has_next(iterator)) + { + iterator->current(iterator, (void**)&next_payload); + payload->set_next_type(payload, next_payload->get_type(next_payload)); + generator->generate_payload(generator, payload); + payload = next_payload; + } + iterator->destroy(iterator); + + /* last payload has no next payload*/ + payload->set_next_type(payload, NO_PAYLOAD); + + generator->generate_payload(generator, payload); + + ike_header->destroy(ike_header); + + /* build packet */ + generator->write_to_chunk(generator, &packet_data); + generator->destroy(generator); + + /* if last payload is of type encrypted, integrity checksum if necessary */ + if (payload->get_type(payload) == ENCRYPTED) + { + this->logger->log(this->logger, CONTROL | LEVEL1, "Build signature on whole message"); + encryption_payload_t *encryption_payload = (encryption_payload_t*)payload; + status = encryption_payload->build_signature(encryption_payload, packet_data); + if (status != SUCCESS) + { + return status; + } + } + + this->packet->set_data(this->packet, packet_data); + + /* clone packet for caller */ + *packet = this->packet->clone(this->packet); + + this->logger->log(this->logger, CONTROL|LEVEL1, "Message of type %s generated successfully", + mapping_find(exchange_type_m,this->exchange_type)); + return SUCCESS; +} + +/** + * Implementation of message_t.get_packet. + */ +static packet_t *get_packet (private_message_t *this) +{ + return this->packet->clone(this->packet); +} + +/** + * Implementation of message_t.get_packet_data. + */ +static chunk_t get_packet_data (private_message_t *this) +{ + return chunk_clone(this->packet->get_data(this->packet)); +} + +/** + * Implementation of message_t.parse_header. + */ +static status_t parse_header(private_message_t *this) +{ + ike_header_t *ike_header; + status_t status; + + + this->logger->log(this->logger, CONTROL|LEVEL1, "parsing Header of message"); + + this->parser->reset_context(this->parser); + status = this->parser->parse_payload(this->parser,HEADER,(payload_t **) &ike_header); + if (status != SUCCESS) + { + this->logger->log(this->logger, ERROR | LEVEL1, "Header could not be parsed"); + return status; + + } + + /* verify payload */ + status = ike_header->payload_interface.verify(&(ike_header->payload_interface)); + if (status != SUCCESS) + { + this->logger->log(this->logger, ERROR | LEVEL1, "Header verification failed"); + ike_header->destroy(ike_header); + return status; + } + + if (this->ike_sa_id != NULL) + { + this->ike_sa_id->destroy(this->ike_sa_id); + } + + this->ike_sa_id = ike_sa_id_create(ike_header->get_initiator_spi(ike_header), + ike_header->get_responder_spi(ike_header), + ike_header->get_initiator_flag(ike_header)); + + this->exchange_type = ike_header->get_exchange_type(ike_header); + this->message_id = ike_header->get_message_id(ike_header); + this->is_request = (!(ike_header->get_response_flag(ike_header))); + this->major_version = ike_header->get_maj_version(ike_header); + this->minor_version = ike_header->get_min_version(ike_header); + this->first_payload = ike_header->payload_interface.get_next_type(&(ike_header->payload_interface)); + + this->logger->log(this->logger, CONTROL, "Parsed a %s %s", + mapping_find(exchange_type_m, this->exchange_type), + this->is_request ? "request" : "response"); + + ike_header->destroy(ike_header); + + /* get the rules for this messge */ + status = this->set_message_rule(this); + if (status != SUCCESS) + { + this->logger->log(this->logger, ERROR, "No message rules specified for a %s %s", + mapping_find(exchange_type_m,this->exchange_type), + this->is_request ? "request" : "response"); + } + + return status; +} + +/** + * Implementation of message_t.parse_body. + */ +static status_t parse_body(private_message_t *this, crypter_t *crypter, signer_t *signer) +{ + status_t status = SUCCESS; + payload_type_t current_payload_type; + + current_payload_type = this->first_payload; + + this->logger->log(this->logger, CONTROL|LEVEL1, "Parsing body of message, first payload is %s", + mapping_find(payload_type_m, current_payload_type)); + + /* parse payload for payload, while there are more available */ + while ((current_payload_type != NO_PAYLOAD)) + { + payload_t *current_payload; + + this->logger->log(this->logger, CONTROL|LEVEL2, "Start parsing a %s payload", + mapping_find(payload_type_m, current_payload_type)); + + /* parse current payload */ + status = this->parser->parse_payload(this->parser,current_payload_type,(payload_t **) ¤t_payload); + + if (status != SUCCESS) + { + this->logger->log(this->logger, ERROR, "Payload type %s could not be parsed", + mapping_find(payload_type_m,current_payload_type)); + return status; + } + + this->logger->log(this->logger, CONTROL|LEVEL2, "Verify payload of type %s", + mapping_find(payload_type_m, current_payload_type)); + + /* verify it, stop parsig if its invalid */ + status = current_payload->verify(current_payload); + if (status != SUCCESS) + { + this->logger->log(this->logger, ERROR, "%s payload verification failed", + mapping_find(payload_type_m,current_payload_type)); + current_payload->destroy(current_payload); + status = VERIFY_ERROR; + return status; + } + + this->logger->log(this->logger, CONTROL|LEVEL2, "%s payload verified. Adding to payload list", + mapping_find(payload_type_m, current_payload_type)); + this->payloads->insert_last(this->payloads,current_payload); + + /* an encryption payload is the last one, so STOP here. decryption is done later */ + if (current_payload_type == ENCRYPTED) + { + this->logger->log(this->logger, CONTROL|LEVEL2, "%s payload found. Stop parsing", + mapping_find(payload_type_m, current_payload_type)); + break; + } + + /* get next payload type */ + current_payload_type = current_payload->get_next_type(current_payload); + } + + if (current_payload_type == ENCRYPTED) + status = this->decrypt_payloads(this,crypter,signer); + if (status != SUCCESS) + { + this->logger->log(this->logger, ERROR, "Could not decrypt payloads"); + return status; + } + + status = this->verify(this); + if (status != SUCCESS) + { + this->logger->log(this->logger, ERROR, "Verification of message failed"); + } + + this->logger->log(this->logger, CONTROL, "Message %s %s contains %d payloads", + mapping_find(exchange_type_m, this->exchange_type), + this->is_request ? "request" : "response", + this->payloads->get_count(this->payloads)); + + return status; +} + +/** + * Implementation of private_message_t.verify. + */ +static status_t verify(private_message_t *this) +{ + int i; + iterator_t *iterator; + size_t total_found_payloads = 0; + + this->logger->log(this->logger, CONTROL|LEVEL1, "Verifying message structure"); + + iterator = this->payloads->create_iterator(this->payloads,TRUE); + /* check for payloads with wrong count*/ + for (i = 0; i < this->message_rule->payload_rule_count;i++) + { + size_t found_payloads = 0; + + /* check all payloads for specific rule */ + iterator->reset(iterator); + + while(iterator->has_next(iterator)) + { + payload_t *current_payload; + payload_type_t current_payload_type; + + iterator->current(iterator,(void **)¤t_payload); + current_payload_type = current_payload->get_type(current_payload); + + if (current_payload_type == UNKNOWN_PAYLOAD) + { + /* unknown payloads are ignored, IF they are not critical */ + unknown_payload_t *unknown_payload = (unknown_payload_t*)current_payload; + if (unknown_payload->is_critical(unknown_payload)) + { + this->logger->log(this->logger, ERROR|LEVEL1, "%s (%d) is not supported, but its critical!", + mapping_find(payload_type_m, current_payload_type), current_payload_type); + iterator->destroy(iterator); + return NOT_SUPPORTED; + } + } + else if (current_payload_type == this->message_rule->payload_rules[i].payload_type) + { + found_payloads++; + total_found_payloads++; + this->logger->log(this->logger, CONTROL|LEVEL2, "Found payload of type %s", + mapping_find(payload_type_m, this->message_rule->payload_rules[i].payload_type)); + + /* as soon as ohe payload occures more then specified, the verification fails */ + if (found_payloads > this->message_rule->payload_rules[i].max_occurence) + { + this->logger->log(this->logger, ERROR|LEVEL1, "Payload of type %s more than %d times (%d) occured in current message", + mapping_find(payload_type_m, current_payload_type), + this->message_rule->payload_rules[i].max_occurence, found_payloads); + iterator->destroy(iterator); + return FAILED; + } + } + } + + if (found_payloads < this->message_rule->payload_rules[i].min_occurence) + { + this->logger->log(this->logger, ERROR|LEVEL1, "Payload of type %s not occured %d times (%d)", + mapping_find(payload_type_m, this->message_rule->payload_rules[i].payload_type), + this->message_rule->payload_rules[i].min_occurence, found_payloads); + iterator->destroy(iterator); + return FAILED; + } + if ((this->message_rule->payload_rules[i].sufficient) && (this->payloads->get_count(this->payloads) == total_found_payloads)) + { + iterator->destroy(iterator); + return SUCCESS; + } + } + iterator->destroy(iterator); + return SUCCESS; +} + + +/** + * Implementation of private_message_t.decrypt_and_verify_payloads. + */ +static status_t decrypt_payloads(private_message_t *this,crypter_t *crypter, signer_t* signer) +{ + bool current_payload_was_encrypted = FALSE; + payload_t *previous_payload = NULL; + int payload_number = 1; + iterator_t *iterator; + status_t status; + + iterator = this->payloads->create_iterator(this->payloads,TRUE); + + /* process each payload and decrypt a encryption payload */ + while(iterator->has_next(iterator)) + { + payload_rule_t *payload_rule; + payload_type_t current_payload_type; + payload_t *current_payload; + + /* get current payload */ + iterator->current(iterator,(void **)¤t_payload); + + /* needed to check */ + current_payload_type = current_payload->get_type(current_payload); + + this->logger->log(this->logger, CONTROL|LEVEL2, "Process payload of type %s", + mapping_find(payload_type_m,current_payload_type)); + + if (current_payload_type == ENCRYPTED) + { + encryption_payload_t *encryption_payload; + payload_t *current_encrypted_payload; + + encryption_payload = (encryption_payload_t*)current_payload; + + this->logger->log(this->logger, CONTROL | LEVEL2, "Found an encryption payload"); + + if (payload_number != this->payloads->get_count(this->payloads)) + { + /* encrypted payload is not last one */ + this->logger->log(this->logger, ERROR | LEVEL1, "Encrypted payload is not last payload"); + iterator->destroy(iterator); + return FAILED; + } + /* decrypt */ + encryption_payload->set_transforms(encryption_payload, crypter, signer); + this->logger->log(this->logger, CONTROL | LEVEL1, "Verify signature of encryption payload"); + status = encryption_payload->verify_signature(encryption_payload, this->packet->get_data(this->packet)); + if (status != SUCCESS) + { + this->logger->log(this->logger, ERROR | LEVEL1, "encryption payload signature invalid"); + iterator->destroy(iterator); + return status; + } + this->logger->log(this->logger, CONTROL | LEVEL2, "Decrypt content of encryption payload"); + status = encryption_payload->decrypt(encryption_payload); + if (status != SUCCESS) + { + this->logger->log(this->logger, ERROR | LEVEL1, "Encrypted payload could not be decrypted and parsed: %s", + mapping_find(status_m, status)); + iterator->destroy(iterator); + return status; + } + + /* needed later to find out if a payload was encrypted */ + current_payload_was_encrypted = TRUE; + + /* check if there are payloads contained in the encryption payload */ + if (encryption_payload->get_payload_count(encryption_payload) == 0) + { + this->logger->log(this->logger, CONTROL|LEVEL2, "Encrypted payload is empty"); + /* remove the encryption payload, is not needed anymore */ + iterator->remove(iterator); + /* encrypted payload contains no other payload */ + current_payload_type = NO_PAYLOAD; + } + else + { + /* encryption_payload is replaced with first payload contained in encryption_payload */ + encryption_payload->remove_first_payload(encryption_payload, ¤t_encrypted_payload); + iterator->replace(iterator,NULL,(void *) current_encrypted_payload); + current_payload_type = current_encrypted_payload->get_type(current_encrypted_payload); + } + + /* is the current paylad the first in the message? */ + if (previous_payload == NULL) + { + /* yes, set the first payload type of the message to the current type */ + this->first_payload = current_payload_type; + } + else + { + /* no, set the next_type of the previous payload to the current type */ + previous_payload->set_next_type(previous_payload, current_payload_type); + } + + /* all encrypted payloads are added to the payload list */ + while (encryption_payload->get_payload_count(encryption_payload) > 0) + { + encryption_payload->remove_first_payload(encryption_payload, ¤t_encrypted_payload); + this->logger->log(this->logger, CONTROL | LEVEL1, "Insert unencrypted payload of type %s at end of list.", + mapping_find(payload_type_m,current_encrypted_payload->get_type(current_encrypted_payload))); + this->payloads->insert_last(this->payloads,current_encrypted_payload); + } + + /* encryption payload is processed, payloads are moved. Destroy it. */ + encryption_payload->destroy(encryption_payload); + } + + /* we allow unknown payloads of any type and don't bother if it was encrypted. Not our problem. */ + if (current_payload_type != UNKNOWN_PAYLOAD) + { + /* get the ruleset for found payload */ + status = this->get_payload_rule(this, current_payload_type, &payload_rule); + if (status != SUCCESS) + { + /* payload is not allowed */ + this->logger->log(this->logger, ERROR | LEVEL1, "Payload type %s not allowed",mapping_find(payload_type_m,current_payload_type)); + iterator->destroy(iterator); + return status; + } + + /* check if the payload was encrypted, and if it should been have encrypted */ + if (payload_rule->encrypted != current_payload_was_encrypted) + { + /* payload was not encrypted, but should have been. or vice-versa */ + this->logger->log(this->logger, ERROR | LEVEL1, "Payload type %s should be %s!", + mapping_find(payload_type_m,current_payload_type), + (payload_rule->encrypted) ? "encrypted" : "not encrypted"); + iterator->destroy(iterator); + return FAILED; + } + } + /* advance to the next payload */ + payload_number++; + /* is stored to set next payload in case of found encryption payload */ + previous_payload = current_payload; + } + iterator->destroy(iterator); + return SUCCESS; +} + +/** + * Implementation of private_message_t.encrypt_payloads. + */ +static status_t encrypt_payloads (private_message_t *this,crypter_t *crypter, signer_t* signer) +{ + encryption_payload_t *encryption_payload = NULL; + status_t status; + linked_list_t *all_payloads; + + if (!this->message_rule->encrypted_content) + { + this->logger->log(this->logger, CONTROL | LEVEL1, "Message doesn't have to be encrypted"); + /* message contains no content to encrypt */ + return SUCCESS; + } + + this->logger->log(this->logger, CONTROL | LEVEL2, "Copy all payloads to a temporary list"); + all_payloads = linked_list_create(); + + /* first copy all payloads in a temporary list */ + while (this->payloads->get_count(this->payloads) > 0) + { + void *current_payload; + this->payloads->remove_first(this->payloads,¤t_payload); + all_payloads->insert_last(all_payloads,current_payload); + } + + encryption_payload = encryption_payload_create(); + + this->logger->log(this->logger, CONTROL | LEVEL2, "Check each payloads if they have to get encrypted"); + while (all_payloads->get_count(all_payloads) > 0) + { + payload_rule_t *payload_rule; + payload_t *current_payload; + bool to_encrypt = FALSE; + + all_payloads->remove_first(all_payloads,(void **)¤t_payload); + this->logger->log(this->logger, CONTROL | LEVEL3, "Get rule for payload %s", + mapping_find(payload_type_m,current_payload->get_type(current_payload))); + + status = this->get_payload_rule(this,current_payload->get_type(current_payload),&payload_rule); + /* for payload types which are not found in supported payload list, it is presumed + * that they don't have to be encrypted */ + if ((status == SUCCESS) && (payload_rule->encrypted)) + { + this->logger->log(this->logger, CONTROL | LEVEL2, "Payload %s has to get encrypted", + mapping_find(payload_type_m,current_payload->get_type(current_payload))); + to_encrypt = TRUE; + } + else if (status != SUCCESS) + { + this->logger->log(this->logger, CONTROL | LEVEL2, "Payload %s not defined for exchange type %s. Handle it anyway", + mapping_find(payload_type_m,current_payload->get_type(current_payload)), + mapping_find(exchange_type_m,this->exchange_type)); + } + + if (to_encrypt) + { + this->logger->log(this->logger, CONTROL | LEVEL2, "Insert payload %s to encryption payload", + mapping_find(payload_type_m,current_payload->get_type(current_payload))); + + encryption_payload->add_payload(encryption_payload,current_payload); + } + else + { + this->logger->log(this->logger, CONTROL | LEVEL2, "Insert payload %s as payload wich does not have to be encrypted", + mapping_find(payload_type_m,current_payload->get_type(current_payload))); + this->public.add_payload(&(this->public), (payload_t*)encryption_payload); + } + } + + status = SUCCESS; + this->logger->log(this->logger, CONTROL | LEVEL2, "Set transforms for encryption payload "); + encryption_payload->set_transforms(encryption_payload,crypter,signer); + this->logger->log(this->logger, CONTROL | LEVEL1, "Encrypt all payloads of encrypted payload"); + status = encryption_payload->encrypt(encryption_payload); + this->logger->log(this->logger, CONTROL | LEVEL2, "Add encrypted payload to payload list"); + this->public.add_payload(&(this->public), (payload_t*)encryption_payload); + + all_payloads->destroy(all_payloads); + + return status; +} + + +/** + * Implementation of message_t.destroy. + */ +static void destroy (private_message_t *this) +{ + iterator_t *iterator; + + this->logger->log(this->logger, CONTROL|LEVEL3, "Going to destroy message_t object"); + + this->packet->destroy(this->packet); + + if (this->ike_sa_id != NULL) + { + this->ike_sa_id->destroy(this->ike_sa_id); + } + + iterator = this->payloads->create_iterator(this->payloads, TRUE); + while (iterator->has_next(iterator)) + { + payload_t *payload; + iterator->current(iterator, (void**)&payload); + this->logger->log(this->logger, CONTROL|LEVEL3, "Destroying payload of type %s", + mapping_find(payload_type_m, payload->get_type(payload))); + payload->destroy(payload); + } + iterator->destroy(iterator); + this->payloads->destroy(this->payloads); + this->parser->destroy(this->parser); + + free(this); +} + +/* + * Described in Header-File + */ +message_t *message_create_from_packet(packet_t *packet) +{ + private_message_t *this = malloc_thing(private_message_t); + + /* public functions */ + this->public.set_major_version = (void(*)(message_t*, u_int8_t))set_major_version; + this->public.get_major_version = (u_int8_t(*)(message_t*))get_major_version; + this->public.set_minor_version = (void(*)(message_t*, u_int8_t))set_minor_version; + this->public.get_minor_version = (u_int8_t(*)(message_t*))get_minor_version; + this->public.set_message_id = (void(*)(message_t*, u_int32_t))set_message_id; + this->public.get_message_id = (u_int32_t(*)(message_t*))get_message_id; + this->public.get_responder_spi = (u_int64_t(*)(message_t*))get_responder_spi; + this->public.set_ike_sa_id = (void(*)(message_t*, ike_sa_id_t *))set_ike_sa_id; + this->public.get_ike_sa_id = (status_t(*)(message_t*, ike_sa_id_t **))get_ike_sa_id; + this->public.set_exchange_type = (void(*)(message_t*, exchange_type_t))set_exchange_type; + this->public.get_exchange_type = (exchange_type_t(*)(message_t*))get_exchange_type; + this->public.set_request = (void(*)(message_t*, bool))set_request; + this->public.get_request = (bool(*)(message_t*))get_request; + this->public.add_payload = (void(*)(message_t*,payload_t*))add_payload; + this->public.generate = (status_t (*) (message_t *,crypter_t*,signer_t*,packet_t**)) generate; + this->public.set_source = (void (*) (message_t*,host_t*)) set_source; + this->public.get_source = (host_t * (*) (message_t*)) get_source; + this->public.set_destination = (void (*) (message_t*,host_t*)) set_destination; + this->public.get_destination = (host_t * (*) (message_t*)) get_destination; + this->public.get_payload_iterator = (iterator_t * (*) (message_t *)) get_payload_iterator; + this->public.parse_header = (status_t (*) (message_t *)) parse_header; + this->public.parse_body = (status_t (*) (message_t *,crypter_t*,signer_t*)) parse_body; + this->public.get_packet = (packet_t * (*) (message_t*)) get_packet; + this->public.get_packet_data = (chunk_t (*) (message_t *this)) get_packet_data; + this->public.destroy = (void(*)(message_t*))destroy; + + /* private values */ + this->exchange_type = EXCHANGE_TYPE_UNDEFINED; + this->is_request = TRUE; + this->ike_sa_id = NULL; + this->first_payload = NO_PAYLOAD; + this->message_id = 0; + + /* private functions */ + this->set_message_rule = set_message_rule; + this->get_payload_rule = get_payload_rule; + this->encrypt_payloads = encrypt_payloads; + this->decrypt_payloads = decrypt_payloads; + this->verify = verify; + + /* private values */ + if (packet == NULL) + { + packet = packet_create(); + } + this->message_rule = NULL; + this->packet = packet; + this->payloads = linked_list_create(); + + /* parser is created from data of packet */ + this->parser = parser_create(this->packet->get_data(this->packet)); + + this->logger = logger_manager->get_logger(logger_manager, MESSAGE); + + return (&this->public); +} + +/* + * Described in Header. + */ +message_t *message_create() +{ + return message_create_from_packet(NULL); +} + +/* + * Described in Header. + */ +message_t *message_create_notify_reply(host_t *source, host_t *destination, exchange_type_t exchange_type, bool original_initiator,ike_sa_id_t *ike_sa_id,notify_message_type_t notify_type) +{ + message_t *message = message_create_from_packet(NULL); + notify_payload_t *payload; + + message->set_source(message, source->clone(source)); + message->set_destination(message, destination->clone(destination)); + message->set_exchange_type(message, exchange_type); + message->set_request(message, FALSE); + message->set_message_id(message,0); + message->set_ike_sa_id(message, ike_sa_id); + + payload = notify_payload_create_from_protocol_and_type(PROTO_IKE, notify_type); + message->add_payload(message,(payload_t *) payload); + + return message; +} diff --git a/src/charon/encoding/message.h b/src/charon/encoding/message.h new file mode 100644 index 000000000..4b3f8e997 --- /dev/null +++ b/src/charon/encoding/message.h @@ -0,0 +1,367 @@ +/** + * @file message.h + * + * @brief Interface of message_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef MESSAGE_H_ +#define MESSAGE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + + +typedef struct message_t message_t; + +/** + * @brief This class is used to represent an IKEv2-Message. + * + * The message handles parsing and generation of payloads + * via parser_t/generator_t. Encryption is done transparently + * via the encryption_payload_t. A set of rules for messages + * and payloads does check parsed messages. + * + * @b Constructors: + * - message_create() + * - message_create_from_packet() + * - message_create_notify_reply() + * + * @ingroup encoding + */ +struct message_t { + + /** + * @brief Sets the IKE major version of the message. + * + * @param this message_t object + * @param major_version major version to set + */ + void (*set_major_version) (message_t *this,u_int8_t major_version); + + /** + * @brief Gets the IKE major version of the message. + * + * @param this message_t object + * @return major version of the message + */ + u_int8_t (*get_major_version) (message_t *this); + + /** + * @brief Sets the IKE minor version of the message. + * + * @param this message_t object + * @param minor_version minor version to set + */ + void (*set_minor_version) (message_t *this,u_int8_t minor_version); + + /** + * @brief Gets the IKE minor version of the message. + * + * @param this message_t object + * @return minor version of the message + */ + u_int8_t (*get_minor_version) (message_t *this); + + /** + * @brief Sets the Message ID of the message. + * + * @param this message_t object + * @param message_id message_id to set + */ + void (*set_message_id) (message_t *this,u_int32_t message_id); + + /** + * @brief Gets the Message ID of the message. + * + * @param this message_t object + * @return message_id type of the message + */ + u_int32_t (*get_message_id) (message_t *this); + + /** + * @brief Gets the responder SPI of the message. + * + * @param this message_t object + * @return responder spi of the message + */ + u_int64_t (*get_responder_spi) (message_t *this); + + /** + * @brief Sets the IKE_SA ID of the message. + * + * @warning ike_sa_id gets cloned internaly and + * so can be destroyed afterwards. + * + * @param this message_t object + * @param ike_sa_id ike_sa_id to set + */ + void (*set_ike_sa_id) (message_t *this,ike_sa_id_t * ike_sa_id); + + /** + * @brief Gets the IKE_SA ID of the message. + * + * @warning The returned ike_sa_id is a clone of the internal one. + * So it has to be destroyed by the caller. + * + * @param this message_t object + * @param ike_sa_id pointer to ike_sa_id pointer which will be set + * @return + * - SUCCESS + * - FAILED if no ike_sa_id is set + */ + status_t (*get_ike_sa_id) (message_t *this,ike_sa_id_t **ike_sa_id); + + /** + * @brief Sets the exchange type of the message. + * + * @param this message_t object + * @param exchange_type exchange_type to set + */ + void (*set_exchange_type) (message_t *this,exchange_type_t exchange_type); + + /** + * @brief Gets the exchange type of the message. + * + * @param this message_t object + * @return exchange type of the message + */ + exchange_type_t (*get_exchange_type) (message_t *this); + + /** + * @brief Sets the request flag. + * + * @param this message_t object + * @param original_initiator TRUE if message is a request, FALSE if it is a reply + */ + void (*set_request) (message_t *this,bool request); + + /** + * @brief Gets request flag. + * + * @param this message_t object + * @return TRUE if message is a request, FALSE if it is a reply + */ + bool (*get_request) (message_t *this); + + /** + * @brief Append a payload to the message. + * + * If the payload must be encrypted is not specified here. Encryption + * of payloads is evaluated via internal rules for the messages and + * is done before generation. The order of payloads may change, since + * all payloads to encrypt are added to the encryption payload, which is + * always the last one. + * + * @param this message_t object + * @param payload payload to append + */ + void (*add_payload) (message_t *this, payload_t *payload); + + /** + * @brief Parses header of message. + * + * Begins parisng of a message created via message_create_from_packet(). + * The parsing context is stored, so a subsequent call to parse_body() + * will continue the parsing process. + * + * @param this message_t object + * @return + * - SUCCESS if header could be parsed + * - PARSE_ERROR if corrupted/invalid data found + * - FAILED if consistence check of header failed + */ + status_t (*parse_header) (message_t *this); + + /** + * @brief Parses body of message. + * + * The body gets not only parsed, but rather it gets verified. + * All payloads are verified if they are allowed to exist in the message + * of this type and if their own structure is ok. + * If there are encrypted payloads, they get decrypted via the supplied + * crypter. Also the message integrity gets verified with the supplied + * signer. + * Crypter/signer can be omitted (by passing NULL) when no encryption + * payload is expected. + * + * @param this message_t object + * @param crypter crypter to decrypt encryption payloads + * @param signer signer to verifiy a message with an encryption payload + * @return + * - SUCCESS if header could be parsed + * - NOT_SUPPORTED if ciritcal unknown payloads found + * - FAILED if message type is not suppported! + * - PARSE_ERROR if corrupted/invalid data found + * - VERIFY_ERROR if verification of some payload failed + * - INVALID_STATE if crypter/signer not supplied, but needed + */ + status_t (*parse_body) (message_t *this, crypter_t *crypter, signer_t *signer); + + /** + * @brief Generates the UDP packet of specific message. + * + * Payloads which must be encrypted are generated first and added to + * an encryption payload. This encryption payload will get encrypted via + * the supplied crypter. Then all other payloads and the header get generated. + * After that, the checksum is added to the encryption payload over the full + * message. + * Crypter/signer can be omitted (by passing NULL) when no encryption + * payload is expected. + * + * @param this message_t object + * @param crypter crypter to use when a payload must be encrypted + * @param signer signer to build a mac + * @return + * - SUCCESS if packet could be generated + * - INVALID_STATE if exchange type is currently not set + * - NOT_FOUND if no rules found for message generation + * - INVALID_STATE if crypter/signer not supplied but needed. + */ + status_t (*generate) (message_t *this, crypter_t *crypter, signer_t *signer, packet_t **packet); + + /** + * @brief Gets the source host informations. + * + * @warning Returned host_t object is not getting cloned, + * do not destroy nor modify. + * + * @param this message_t object + * @return host_t object representing source host + */ + host_t * (*get_source) (message_t *this); + + /** + * @brief Sets the source host informations. + * + * @warning host_t object is not getting cloned and gets destroyed by + * message_t.destroy or next call of message_t.set_source. + * + * @param this message_t object + * @param host host_t object representing source host + */ + void (*set_source) (message_t *this, host_t *host); + + /** + * @brief Gets the destination host informations. + * + * @warning Returned host_t object is not getting cloned, + * do not destroy nor modify. + * + * @param this message_t object + * @return host_t object representing destination host + */ + host_t * (*get_destination) (message_t *this); + + /** + * @brief Sets the destination host informations. + * + * @warning host_t object is not getting cloned and gets destroyed by + * message_t.destroy or next call of message_t.set_destination. + * + * @param this message_t object + * @param host host_t object representing destination host + */ + void (*set_destination) (message_t *this, host_t *host); + + /** + * @brief Returns an iterator on all stored payloads. + * + * @warning Don't insert payloads over this iterator. + * Use add_payload() instead. + * + * @param this message_t object + * @return iterator_t object which has to get destroyd by the caller + */ + iterator_t * (*get_payload_iterator) (message_t *this); + + /** + * Returns a clone of the internal stored packet_t object. + * + * @param this message_t object + * @return packet_t object as clone of internal one + */ + packet_t * (*get_packet) (message_t *this); + + /** + * Returns a clone of the internal stored packet_t data. + * + * @param this message_t object + * @return clone of the internal stored packet_t data. + */ + chunk_t (*get_packet_data) (message_t *this); + + + /** + * @brief Destroys a message and all including objects. + * + * @param this message_t object + */ + void (*destroy) (message_t *this); +}; + +/** + * @brief Creates an message_t object from a incoming UDP Packet. + * + * @warning the given packet_t object is not copied and gets + * destroyed in message_t's destroy call. + * + * @warning Packet is not parsed in here! + * + * - exchange_type is set to NOT_SET + * - original_initiator is set to TRUE + * - is_request is set to TRUE + * Call message_t.parse_header afterwards. + * + * @param packet packet_t object which is assigned to message + * @return message_t object + * + * @ingroup encoding + */ +message_t * message_create_from_packet(packet_t *packet); + + +/** + * @brief Creates an empty message_t object. + * + * - exchange_type is set to NOT_SET + * - original_initiator is set to TRUE + * - is_request is set to TRUE + * + * @return message_t object + * + * @ingroup encoding + */ +message_t * message_create(void); + +/** + * @brief Creates an message_t object of type reply containing a notify payload. + * + * @return message_t object + * + * @ingroup encoding + */ +message_t *message_create_notify_reply(host_t *source, host_t *destination, exchange_type_t exchange_type, bool original_initiator,ike_sa_id_t *ike_sa_id,notify_message_type_t notify_type); + +#endif /*MESSAGE_H_*/ diff --git a/src/charon/encoding/parser.c b/src/charon/encoding/parser.c new file mode 100644 index 000000000..a589e9bde --- /dev/null +++ b/src/charon/encoding/parser.c @@ -0,0 +1,1065 @@ +/** + * @file parser.c + * + * @brief Implementation of parser_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 +#include +#include + +#include "parser.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +typedef struct private_parser_t private_parser_t; + +/** + * Private data stored in a context. + * + * Contains pointers and counters to store current state. + */ +struct private_parser_t { + /** + * Public members, see parser_t. + */ + parser_t public; + + /** + * @brief Parse a 4-Bit unsigned integer from the current parsing position. + * + * @param this parser_t object + * @param rule_number number of current rule + * @param[out] output_pos pointer where to write the parsed result + * @return + * - SUCCESS or + * - PARSE_ERROR when not successful + */ + status_t (*parse_uint4) (private_parser_t *this, int rule_number, u_int8_t *output_pos); + + /** + * @brief Parse a 8-Bit unsigned integer from the current parsing position. + * + * @param this parser_t object + * @param rule_number number of current rule + * @param[out] output_pos pointer where to write the parsed result + * @return + * - SUCCESS or + * - PARSE_ERROR when not successful + */ + status_t (*parse_uint8) (private_parser_t *this, int rule_number, u_int8_t *output_pos); + + /** + * @brief Parse a 15-Bit unsigned integer from the current parsing position. + * + * This is a special case used for ATTRIBUTE_TYPE. + * Big-/Little-endian conversion is done here. + * + * @param this parser_t object + * @param rule_number number of current rule + * @param[out] output_pos pointer where to write the parsed result + * @return + * - SUCCESS or + * - PARSE_ERROR when not successful + */ + status_t (*parse_uint15) (private_parser_t *this, int rule_number, u_int16_t *output_pos); + + /** + * @brief Parse a 16-Bit unsigned integer from the current parsing position. + * + * Big-/Little-endian conversion is done here. + * + * @param this parser_t object + * @param rule_number number of current rule + * @param[out] output_pos pointer where to write the parsed result + * @return + * - SUCCESS or + * - PARSE_ERROR when not successful + */ + status_t (*parse_uint16) (private_parser_t *this, int rule_number, u_int16_t *output_pos); + + /** + * @brief Parse a 32-Bit unsigned integer from the current parsing position. + * + * Big-/Little-endian conversion is done here. + * + * @param this parser_t object + * @param rule_number number of current rule + * @param[out] output_pos pointer where to write the parsed result + * @return + * - SUCCESS or + * - PARSE_ERROR when not successful + */ + status_t (*parse_uint32) (private_parser_t *this, int rule_number, u_int32_t *output_pos); + + /** + * @brief Parse a 64-Bit unsigned integer from the current parsing position. + * + * @todo add support for big-endian machines. + * + * @param this parser_t object + * @param rule_number number of current rule + * @param[out] output_pos pointer where to write the parsed result + * @return + * - SUCCESS or + * - PARSE_ERROR when not successful + */ + status_t (*parse_uint64) (private_parser_t *this, int rule_number, u_int64_t *output_pos); + + /** + * @brief Parse a given amount of bytes and writes them to a specific location + * + * @param this parser_t object + * @param rule_number number of current rule + * @param[out] output_pos pointer where to write the parsed result + * @param bytes number of bytes to parse + * @return + * - SUCCESS or + * - PARSE_ERROR when not successful + */ + status_t (*parse_bytes) (private_parser_t *this, int rule_number, u_int8_t *output_pos,size_t bytes); + + /** + * @brief Parse a single Bit from the current parsing position + * + * @param this parser_t object + * @param rule_number number of current rule + * @param[out] output_pos pointer where to write the parsed result + * @return + * - SUCCESS or + * - PARSE_ERROR when not successful + */ + status_t (*parse_bit) (private_parser_t *this, int rule_number, bool *output_pos); + + /** + * @brief Parse substructures in a list + * + * This function calls the parser recursivly to parse contained substructures + * in a linked_list_t. The list must already be created. Payload defines + * the type of the substructures. parsing is continued until the specified length + * is completely parsed. + * + * @param this parser_t object + * @param rule_number number of current rule + * @param[out] output_pos pointer of a linked_list where substructures are added + * @param payload_type type of the contained substructures to parse + * @param length number of bytes to parse in this list + * @return + * - SUCCESS or + * - PARSE_ERROR when not successful + */ + status_t (*parse_list) (private_parser_t *this, int rule_number, linked_list_t **output_pos, payload_type_t payload_ype, size_t length); + + /** + * @brief Parse data from current parsing position in a chunk. + * + * This function clones length number of bytes to output_pos, without + * modifiyng them. Space will be allocated and must be freed by caller. + * + * @param this parser_t object + * @param rule_number number of current rule + * @param[out] output_pos pointer of a chunk which will point to the allocated data + * @param length number of bytes to clone + * @return + * - SUCCESS or + * - PARSE_ERROR when not successful + */ + status_t (*parse_chunk) (private_parser_t *this, int rule_number, chunk_t *output_pos, size_t length); + + /** + * Current bit for reading in input data. + */ + u_int8_t bit_pos; + + /** + * Current byte for reading in input data. + */ + u_int8_t *byte_pos; + + /** + * Input data to parse. + */ + u_int8_t *input; + + /** + * Roof of input, used for length-checking. + */ + u_int8_t *input_roof; + + /** + * Set of encoding rules for this parsing session. + */ + encoding_rule_t *rules; + + /** + * Assigned logger_t object. + */ + logger_t *logger; +}; + +/** + * Implementation of private_parser_t.parse_uint4. + */ +static status_t parse_uint4(private_parser_t *this, int rule_number, u_int8_t *output_pos) +{ + if (this->byte_pos + sizeof(u_int8_t) > this->input_roof) + { + this->logger->log(this->logger, ERROR|LEVEL1, " not enough input to parse rule %d %s", + rule_number, mapping_find(encoding_type_m, + this->rules[rule_number].type)); + return PARSE_ERROR; + } + switch (this->bit_pos) + { + case 0: + /* caller interested in result ? */ + if (output_pos != NULL) + { + *output_pos = *(this->byte_pos) >> 4; + } + this->bit_pos = 4; + break; + case 4: + /* caller interested in result ? */ + if (output_pos != NULL) + { + *output_pos = *(this->byte_pos) & 0x0F; + } + this->bit_pos = 0; + this->byte_pos++; + break; + default: + this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d", + rule_number, mapping_find(encoding_type_m, + this->rules[rule_number].type), this->bit_pos); + return PARSE_ERROR; + } + + if (output_pos != NULL) + { + this->logger->log(this->logger, RAW|LEVEL2, " => %d", *output_pos); + } + + return SUCCESS; +} + +/** + * Implementation of private_parser_t.parse_uint8. + */ +static status_t parse_uint8(private_parser_t *this, int rule_number, u_int8_t *output_pos) +{ + if (this->byte_pos + sizeof(u_int8_t) > this->input_roof) + { + this->logger->log(this->logger, ERROR|LEVEL1, " not enough input to parse rule %d %s", + rule_number, mapping_find(encoding_type_m, + this->rules[rule_number].type)); + return PARSE_ERROR; + } + if (this->bit_pos) + { + this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d", + rule_number, mapping_find(encoding_type_m, + this->rules[rule_number].type), this->bit_pos); + return PARSE_ERROR; + } + + /* caller interested in result ? */ + if (output_pos != NULL) + { + *output_pos = *(this->byte_pos); + this->logger->log(this->logger, RAW|LEVEL2, " => %d", *output_pos); + } + this->byte_pos++; + + return SUCCESS; +} + +/** + * Implementation of private_parser_t.parse_uint15. + */ +static status_t parse_uint15(private_parser_t *this, int rule_number, u_int16_t *output_pos) +{ + if (this->byte_pos + sizeof(u_int16_t) > this->input_roof) + { + this->logger->log(this->logger, ERROR|LEVEL1, " not enough input to parse rule %d %s", + rule_number, mapping_find(encoding_type_m, + this->rules[rule_number].type)); + return PARSE_ERROR; + } + if (this->bit_pos != 1) + { + this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d", + rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type), + this->bit_pos); + return PARSE_ERROR; + } + /* caller interested in result ? */ + if (output_pos != NULL) + { + *output_pos = ntohs(*((u_int16_t*)this->byte_pos)) & ~0x8000; + this->logger->log(this->logger, RAW|LEVEL2, " => %d", *output_pos); + } + this->byte_pos += 2; + this->bit_pos = 0; + + return SUCCESS; +} + +/** + * Implementation of private_parser_t.parse_uint16. + */ +static status_t parse_uint16(private_parser_t *this, int rule_number, u_int16_t *output_pos) +{ + if (this->byte_pos + sizeof(u_int16_t) > this->input_roof) + { + this->logger->log(this->logger, ERROR|LEVEL1, " not enough input to parse rule %d %s", + rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type)); + return PARSE_ERROR; + } + if (this->bit_pos) + { + this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d", + rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type), + this->bit_pos); + return PARSE_ERROR; + } + /* caller interested in result ? */ + if (output_pos != NULL) + { + *output_pos = ntohs(*((u_int16_t*)this->byte_pos)); + + this->logger->log(this->logger, RAW|LEVEL2, " => %d", *output_pos); + } + this->byte_pos += 2; + + return SUCCESS; +} +/** + * Implementation of private_parser_t.parse_uint32. + */ +static status_t parse_uint32(private_parser_t *this, int rule_number, u_int32_t *output_pos) +{ + if (this->byte_pos + sizeof(u_int32_t) > this->input_roof) + { + this->logger->log(this->logger, ERROR|LEVEL1, " not enough input to parse rule %d %s", + rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type)); + return PARSE_ERROR; + } + if (this->bit_pos) + { + this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d", + rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type), + this->bit_pos); + return PARSE_ERROR; + } + /* caller interested in result ? */ + if (output_pos != NULL) + { + *output_pos = ntohl(*((u_int32_t*)this->byte_pos)); + + this->logger->log(this->logger, RAW|LEVEL2, " => %d", *output_pos); + } + this->byte_pos += 4; + + return SUCCESS; +} + +/** + * Implementation of private_parser_t.parse_uint64. + */ +static status_t parse_uint64(private_parser_t *this, int rule_number, u_int64_t *output_pos) +{ + if (this->byte_pos + sizeof(u_int64_t) > this->input_roof) + { + this->logger->log(this->logger, ERROR|LEVEL1, " not enough input to parse rule %d %s", + rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type)); + return PARSE_ERROR; + } + if (this->bit_pos) + { + this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d", + rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type), + this->bit_pos); + return PARSE_ERROR; + } + /* caller interested in result ? */ + if (output_pos != NULL) + { + /* assuming little endian host order */ + *(output_pos + 1) = ntohl(*((u_int32_t*)this->byte_pos)); + *output_pos = ntohl(*(((u_int32_t*)this->byte_pos) + 1)); + + this->logger->log_bytes(this->logger, RAW|LEVEL2, " =>", (void*)output_pos, 8); + } + this->byte_pos += 8; + + return SUCCESS; +} + +/** + * Implementation of private_parser_t.parse_bytes. + */ +static status_t parse_bytes (private_parser_t *this, int rule_number, u_int8_t *output_pos,size_t bytes) +{ + if (this->byte_pos + bytes > this->input_roof) + { + this->logger->log(this->logger, ERROR|LEVEL1, " not enough input to parse rule %d %s", + rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type)); + return PARSE_ERROR; + } + if (this->bit_pos) + { + this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d", + rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type), + this->bit_pos); + return PARSE_ERROR; + } + + /* caller interested in result ? */ + if (output_pos != NULL) + { + memcpy(output_pos,this->byte_pos,bytes); + + this->logger->log_bytes(this->logger, RAW|LEVEL2, " =>", (void*)output_pos, bytes); + } + this->byte_pos += bytes; + + return SUCCESS; +} + +/** + * Implementation of private_parser_t.parse_bit. + */ +static status_t parse_bit(private_parser_t *this, int rule_number, bool *output_pos) +{ + if (this->byte_pos + sizeof(u_int8_t) > this->input_roof) + { + this->logger->log(this->logger, ERROR|LEVEL1, " not enough input to parse rule %d %s", + rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type)); + return PARSE_ERROR; + } + /* caller interested in result ? */ + if (output_pos != NULL) + { + u_int8_t mask; + mask = 0x01 << (7 - this->bit_pos); + *output_pos = *this->byte_pos & mask; + + if (*output_pos) + { + /* set to a "clean", comparable true */ + *output_pos = TRUE; + } + + this->logger->log(this->logger, RAW|LEVEL2, " => %d", *output_pos); + } + this->bit_pos = (this->bit_pos + 1) % 8; + if (this->bit_pos == 0) + { + this->byte_pos++; + } + + return SUCCESS; +} + +/** + * Implementation of private_parser_t.parse_list. + */ +static status_t parse_list(private_parser_t *this, int rule_number, linked_list_t **output_pos, payload_type_t payload_type, size_t length) +{ + linked_list_t * list = *output_pos; + + if (length < 0) + { + this->logger->log(this->logger, ERROR|LEVEL1, " invalid length for rule %d %s", + rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type)); + return PARSE_ERROR; + } + + if (this->bit_pos) + { + this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d", + rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type), this->bit_pos); + return PARSE_ERROR; + } + + while (length > 0) + { + u_int8_t *pos_before = this->byte_pos; + payload_t *payload; + status_t status; + this->logger->log(this->logger, CONTROL|LEVEL1, " %d bytes left, parsing recursivly %s", + length, mapping_find(payload_type_m, payload_type)); + status = this->public.parse_payload((parser_t*)this, payload_type, &payload); + if (status != SUCCESS) + { + this->logger->log(this->logger, ERROR, " parsing of a %s substructure failed", + mapping_find(payload_type_m, payload_type)); + return status; + } + list->insert_last(list, payload); + length -= this->byte_pos - pos_before; + } + *output_pos = list; + return SUCCESS; +} + +/** + * Implementation of private_parser_t.parse_chunk. + */ +static status_t parse_chunk(private_parser_t *this, int rule_number, chunk_t *output_pos, size_t length) +{ + if (this->byte_pos + length > this->input_roof) + { + this->logger->log(this->logger, ERROR, " not enough input (%d bytes) to parse rule %d %s", + length, rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type)); + return PARSE_ERROR; + } + if (this->bit_pos) + { + this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d", + rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type), this->bit_pos); + return PARSE_ERROR; + } + if (output_pos != NULL) + { + output_pos->len = length; + output_pos->ptr = malloc(length); + memcpy(output_pos->ptr, this->byte_pos, length); + } + this->byte_pos += length; + this->logger->log_bytes(this->logger, RAW|LEVEL2, " =>", (void*)output_pos->ptr, length); + + return SUCCESS; +} + +/** + * Implementation of parser_t.parse_payload. + */ +static status_t parse_payload(private_parser_t *this, payload_type_t payload_type, payload_t **payload) +{ + payload_t *pld; + void *output; + size_t rule_count, payload_length, spi_size, attribute_length; + u_int16_t ts_type; + bool attribute_format; + int rule_number; + encoding_rule_t *rule; + + /* create instance of the payload to parse */ + pld = payload_create(payload_type); + + this->logger->log(this->logger, CONTROL|LEVEL1, "parsing %s payload, %d bytes left", + mapping_find(payload_type_m, payload_type), + this->input_roof-this->byte_pos); + + this->logger->log_bytes(this->logger, RAW|LEVEL3, "parsing payload from", this->byte_pos, + this->input_roof-this->byte_pos); + + if (pld->get_type(pld) == UNKNOWN_PAYLOAD) + { + this->logger->log(this->logger, ERROR|LEVEL1, " payload type %d is unknown, handling as %s", + payload_type, mapping_find(payload_type_m, UNKNOWN_PAYLOAD)); + } + + /* base pointer for output, avoids casting in every rule */ + output = pld; + + /* parse the payload with its own rulse */ + pld->get_encoding_rules(pld, &(this->rules), &rule_count); + for (rule_number = 0; rule_number < rule_count; rule_number++) + { + rule = &(this->rules[rule_number]); + this->logger->log(this->logger, CONTROL|LEVEL2, " parsing rule %d %s", + rule_number, mapping_find(encoding_type_m, rule->type)); + switch (rule->type) + { + case U_INT_4: + { + if (this->parse_uint4(this, rule_number, output + rule->offset) != SUCCESS) + { + pld->destroy(pld); + return PARSE_ERROR; + } + break; + } + case U_INT_8: + { + if (this->parse_uint8(this, rule_number, output + rule->offset) != SUCCESS) + { + pld->destroy(pld); + return PARSE_ERROR; + } + break; + } + case U_INT_16: + { + if (this->parse_uint16(this, rule_number, output + rule->offset) != SUCCESS) + { + pld->destroy(pld); + return PARSE_ERROR; + } + break; + } + case U_INT_32: + { + if (this->parse_uint32(this, rule_number, output + rule->offset) != SUCCESS) + { + pld->destroy(pld); + return PARSE_ERROR; + } + break; + } + case U_INT_64: + { + if (this->parse_uint64(this, rule_number, output + rule->offset) != SUCCESS) + { + pld->destroy(pld); + return PARSE_ERROR; + } + break; + } + case IKE_SPI: + { + if (this->parse_bytes(this, rule_number, output + rule->offset,8) != SUCCESS) + { + pld->destroy(pld); + return PARSE_ERROR; + } + break; + } + case RESERVED_BIT: + { + if (this->parse_bit(this, rule_number, NULL) != SUCCESS) + { + pld->destroy(pld); + return PARSE_ERROR; + } + break; + } + case RESERVED_BYTE: + { + if (this->parse_uint8(this, rule_number, NULL) != SUCCESS) + { + pld->destroy(pld); + return PARSE_ERROR; + } + break; + } + case FLAG: + { + if (this->parse_bit(this, rule_number, output + rule->offset) != SUCCESS) + { + pld->destroy(pld); + return PARSE_ERROR; + } + break; + } + case PAYLOAD_LENGTH: + { + if (this->parse_uint16(this, rule_number, output + rule->offset) != SUCCESS) + { + pld->destroy(pld); + return PARSE_ERROR; + } + payload_length = *(u_int16_t*)(output + rule->offset); + break; + } + case HEADER_LENGTH: + { + if (this->parse_uint32(this, rule_number, output + rule->offset) != SUCCESS) + { + pld->destroy(pld); + return PARSE_ERROR; + } + break; + } + case SPI_SIZE: + { + if (this->parse_uint8(this, rule_number, output + rule->offset) != SUCCESS) + { + pld->destroy(pld); + return PARSE_ERROR; + } + spi_size = *(u_int8_t*)(output + rule->offset); + break; + } + case SPI: + { + if (this->parse_chunk(this, rule_number, output + rule->offset, spi_size) != SUCCESS) + { + pld->destroy(pld); + return PARSE_ERROR; + } + break; + } + case PROPOSALS: + { + size_t proposals_length = payload_length - SA_PAYLOAD_HEADER_LENGTH; + if (this->parse_list(this, rule_number, output + rule->offset, PROPOSAL_SUBSTRUCTURE, proposals_length) != SUCCESS) + { + pld->destroy(pld); + return PARSE_ERROR; + } + break; + } + case TRANSFORMS: + { + size_t transforms_length = payload_length - spi_size - PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH; + if (this->parse_list(this, rule_number, output + rule->offset, TRANSFORM_SUBSTRUCTURE, transforms_length) != SUCCESS) + { + pld->destroy(pld); + return PARSE_ERROR; + } + break; + } + case TRANSFORM_ATTRIBUTES: + { + size_t transform_a_length = payload_length - TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH; + if (this->parse_list(this, rule_number, output + rule->offset, TRANSFORM_ATTRIBUTE, transform_a_length) != SUCCESS) + { + pld->destroy(pld); + return PARSE_ERROR; + } + break; + } + case CONFIGURATION_ATTRIBUTES: + { + size_t configuration_attributes_length = payload_length - CP_PAYLOAD_HEADER_LENGTH; + if (this->parse_list(this, rule_number, output + rule->offset, CONFIGURATION_ATTRIBUTE, configuration_attributes_length) != SUCCESS) + { + pld->destroy(pld); + return PARSE_ERROR; + } + break; + } + case ATTRIBUTE_FORMAT: + { + if (this->parse_bit(this, rule_number, output + rule->offset) != SUCCESS) + { + pld->destroy(pld); + return PARSE_ERROR; + } + attribute_format = *(bool*)(output + rule->offset); + break; + } + case ATTRIBUTE_TYPE: + { + if (this->parse_uint15(this, rule_number, output + rule->offset) != SUCCESS) + { + pld->destroy(pld); + return PARSE_ERROR; + } + attribute_format = *(bool*)(output + rule->offset); + break; + } + case CONFIGURATION_ATTRIBUTE_LENGTH: + { + if (this->parse_uint16(this, rule_number, output + rule->offset) != SUCCESS) + { + pld->destroy(pld); + return PARSE_ERROR; + } + attribute_length = *(u_int16_t*)(output + rule->offset); + break; + } + case ATTRIBUTE_LENGTH_OR_VALUE: + { + if (this->parse_uint16(this, rule_number, output + rule->offset) != SUCCESS) + { + pld->destroy(pld); + return PARSE_ERROR; + } + attribute_length = *(u_int16_t*)(output + rule->offset); + break; + } + case ATTRIBUTE_VALUE: + { + if (attribute_format == FALSE) + { + if (this->parse_chunk(this, rule_number, output + rule->offset, attribute_length) != SUCCESS) + { + pld->destroy(pld); + return PARSE_ERROR; + } + } + break; + } + case NONCE_DATA: + { + size_t nonce_length = payload_length - NONCE_PAYLOAD_HEADER_LENGTH; + if (this->parse_chunk(this, rule_number, output + rule->offset, nonce_length) != SUCCESS) + { + pld->destroy(pld); + return PARSE_ERROR; + } + break; + } + case ID_DATA: + { + size_t data_length = payload_length - ID_PAYLOAD_HEADER_LENGTH; + if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS) + { + pld->destroy(pld); + return PARSE_ERROR; + } + break; + } + case AUTH_DATA: + { + size_t data_length = payload_length - AUTH_PAYLOAD_HEADER_LENGTH; + if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS) + { + pld->destroy(pld); + return PARSE_ERROR; + } + break; + } + case CERT_DATA: + { + size_t data_length = payload_length - CERT_PAYLOAD_HEADER_LENGTH; + if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS) + { + pld->destroy(pld); + return PARSE_ERROR; + } + break; + } + case CERTREQ_DATA: + { + size_t data_length = payload_length - CERTREQ_PAYLOAD_HEADER_LENGTH; + if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS) + { + pld->destroy(pld); + return PARSE_ERROR; + } + break; + } + case EAP_MESSAGE: + { + size_t data_length = payload_length - EAP_PAYLOAD_HEADER_LENGTH; + if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS) + { + pld->destroy(pld); + return PARSE_ERROR; + } + break; + } + case SPIS: + { + size_t data_length = payload_length - DELETE_PAYLOAD_HEADER_LENGTH; + if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS) + { + pld->destroy(pld); + return PARSE_ERROR; + } + break; + } + case VID_DATA: + { + size_t data_length = payload_length - VENDOR_ID_PAYLOAD_HEADER_LENGTH; + if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS) + { + pld->destroy(pld); + return PARSE_ERROR; + } + break; + } + case CONFIGURATION_ATTRIBUTE_VALUE: + { + size_t data_length = attribute_length; + if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS) + { + pld->destroy(pld); + return PARSE_ERROR; + } + break; + } + case KEY_EXCHANGE_DATA: + { + size_t keydata_length = payload_length - KE_PAYLOAD_HEADER_LENGTH; + if (this->parse_chunk(this, rule_number, output + rule->offset, keydata_length) != SUCCESS) + { + pld->destroy(pld); + return PARSE_ERROR; + } + break; + } + case NOTIFICATION_DATA: + { + size_t notify_length = payload_length - NOTIFY_PAYLOAD_HEADER_LENGTH - spi_size; + if (this->parse_chunk(this, rule_number, output + rule->offset, notify_length) != SUCCESS) + { + pld->destroy(pld); + return PARSE_ERROR; + } + break; + } + case ENCRYPTED_DATA: + { + size_t data_length = payload_length - ENCRYPTION_PAYLOAD_HEADER_LENGTH; + if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS) + { + pld->destroy(pld); + return PARSE_ERROR; + } + break; + } + case TS_TYPE: + { + if (this->parse_uint8(this, rule_number, output + rule->offset) != SUCCESS) + { + pld->destroy(pld); + return PARSE_ERROR; + } + ts_type = *(u_int8_t*)(output + rule->offset); + break; + } + case ADDRESS: + { + size_t address_length = (ts_type == TS_IPV4_ADDR_RANGE) ? 4 : 16; + if (this->parse_chunk(this, rule_number, output + rule->offset,address_length) != SUCCESS) + { + pld->destroy(pld); + return PARSE_ERROR; + } + break; + } + case TRAFFIC_SELECTORS: + { + size_t traffic_selectors_length = payload_length - TS_PAYLOAD_HEADER_LENGTH; + if (this->parse_list(this, rule_number, output + rule->offset, TRAFFIC_SELECTOR_SUBSTRUCTURE, traffic_selectors_length) != SUCCESS) + { + pld->destroy(pld); + return PARSE_ERROR; + } + break; + } + case UNKNOWN_PAYLOAD: + { + size_t unknown_payload_data_length = payload_length - UNKNOWN_PAYLOAD_HEADER_LENGTH; + if (this->parse_chunk(this, rule_number, output + rule->offset, unknown_payload_data_length) != SUCCESS) + { + pld->destroy(pld); + return PARSE_ERROR; + } + break; + } + default: + { + this->logger->log(this->logger, ERROR, " no rule to parse rule %d %s (%d)", rule_number, mapping_find(encoding_type_m, rule->type), rule->type); + pld->destroy(pld); + return PARSE_ERROR; + } + } + /* process next rulue */ + rule++; + } + + *payload = pld; + this->logger->log(this->logger, CONTROL|LEVEL2, "parsing %s payload finished.", + mapping_find(payload_type_m, payload_type)); + return SUCCESS; +} + +/** + * Implementation of parser_t.get_remaining_byte_count. + */ +static int get_remaining_byte_count (private_parser_t *this) +{ + int count = (this->input_roof - this->byte_pos); + return count; +} + +/** + * Implementation of parser_t.reset_context. + */ +static void reset_context (private_parser_t *this) +{ + this->byte_pos = this->input; + this->bit_pos = 0; +} + +/** + * Implementation of parser_t.destroy. + */ +static void destroy(private_parser_t *this) +{ + free(this); +} + +/* + * Described in header. + */ +parser_t *parser_create(chunk_t data) +{ + private_parser_t *this = malloc_thing(private_parser_t); + + this->logger = logger_manager->get_logger(logger_manager, PARSER); + + this->public.parse_payload = (status_t(*)(parser_t*,payload_type_t,payload_t**)) parse_payload; + this->public.reset_context = (void(*)(parser_t*)) reset_context; + this->public.get_remaining_byte_count = (int (*) (parser_t *))get_remaining_byte_count; + this->public.destroy = (void(*)(parser_t*)) destroy; + + this->parse_uint4 = parse_uint4; + this->parse_uint8 = parse_uint8; + this->parse_uint15 = parse_uint15; + this->parse_uint16 = parse_uint16; + this->parse_uint32 = parse_uint32; + this->parse_uint64 = parse_uint64; + this->parse_bytes = parse_bytes; + this->parse_bit = parse_bit; + this->parse_list = parse_list; + this->parse_chunk = parse_chunk; + + this->input = data.ptr; + this->byte_pos = data.ptr; + this->bit_pos = 0; + this->input_roof = data.ptr + data.len; + + return (parser_t*)this; +} + diff --git a/src/charon/encoding/parser.h b/src/charon/encoding/parser.h new file mode 100644 index 000000000..216fac9b7 --- /dev/null +++ b/src/charon/encoding/parser.h @@ -0,0 +1,95 @@ +/** + * @file parser.h + * + * @brief Interface of parser_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef PARSER_H_ +#define PARSER_H_ + +#include +#include +#include + + +typedef struct parser_t parser_t; + +/** + * @brief A parser_t class to parse IKEv2 payloads. + * + * A parser is used for parsing one chunk of data. Multiple + * payloads can be parsed out of the chunk using parse_payload. + * The parser remains the state until destroyed. + * + * @b Constructors: + * - parser_create() + * + * @ingroup encoding + */ +struct parser_t { + + /** + * @brief Parses the next payload. + * + * @warning Caller is responsible for freeing allocated payload. + * + * Rules for parsing are described in the payload definition. + * + * @param this parser_t bject + * @param payload_type payload type to parse + * @param[out] payload pointer where parsed payload was allocated + * @return + * - SUCCESSFUL if succeeded, + * - PARSE_ERROR if corrupted/invalid data found + */ + status_t (*parse_payload) (parser_t *this, payload_type_t payload_type, payload_t **payload); + + /** + * Gets the remaining byte count which is not currently parsed. + * + * @param parser parser_t object + */ + int (*get_remaining_byte_count) (parser_t *this); + + /** + * @brief Resets the current parser context. + * + * @param parser parser_t object + */ + void (*reset_context) (parser_t *this); + + /** + * @brief Destroys a parser_t object. + * + * @param parser parser_t object + */ + void (*destroy) (parser_t *this); +}; + +/** + * @brief Constructor to create a parser_t object. + * + * @param data chunk of data to parse with this parser_t object + * @return parser_t object + * + * @ingroup encoding + */ +parser_t *parser_create(chunk_t data); + +#endif /*PARSER_H_*/ diff --git a/src/charon/encoding/payloads/Makefile.payloads b/src/charon/encoding/payloads/Makefile.payloads new file mode 100644 index 000000000..61d920907 --- /dev/null +++ b/src/charon/encoding/payloads/Makefile.payloads @@ -0,0 +1,108 @@ +# Copyright (C) 2005 Jan Hutter, 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 . +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# + +PAYLOADS_DIR= $(ENCODING_DIR)payloads/ + +CHARON_OBJS+= $(BUILD_DIR)encodings.o +$(BUILD_DIR)encodings.o : $(PAYLOADS_DIR)encodings.c $(PAYLOADS_DIR)encodings.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)ike_header.o +$(BUILD_DIR)ike_header.o : $(PAYLOADS_DIR)ike_header.c $(PAYLOADS_DIR)ike_header.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)ke_payload.o +$(BUILD_DIR)ke_payload.o : $(PAYLOADS_DIR)ke_payload.c $(PAYLOADS_DIR)ke_payload.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)nonce_payload.o +$(BUILD_DIR)nonce_payload.o : $(PAYLOADS_DIR)nonce_payload.c $(PAYLOADS_DIR)nonce_payload.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)notify_payload.o +$(BUILD_DIR)notify_payload.o : $(PAYLOADS_DIR)notify_payload.c $(PAYLOADS_DIR)notify_payload.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)id_payload.o +$(BUILD_DIR)id_payload.o : $(PAYLOADS_DIR)id_payload.c $(PAYLOADS_DIR)id_payload.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)auth_payload.o +$(BUILD_DIR)auth_payload.o : $(PAYLOADS_DIR)auth_payload.c $(PAYLOADS_DIR)auth_payload.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)cert_payload.o +$(BUILD_DIR)cert_payload.o : $(PAYLOADS_DIR)cert_payload.c $(PAYLOADS_DIR)cert_payload.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)certreq_payload.o +$(BUILD_DIR)certreq_payload.o : $(PAYLOADS_DIR)certreq_payload.c $(PAYLOADS_DIR)certreq_payload.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)delete_payload.o +$(BUILD_DIR)delete_payload.o : $(PAYLOADS_DIR)delete_payload.c $(PAYLOADS_DIR)delete_payload.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)vendor_id_payload.o +$(BUILD_DIR)vendor_id_payload.o : $(PAYLOADS_DIR)vendor_id_payload.c $(PAYLOADS_DIR)vendor_id_payload.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)cp_payload.o +$(BUILD_DIR)cp_payload.o : $(PAYLOADS_DIR)cp_payload.c $(PAYLOADS_DIR)cp_payload.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)configuration_attribute.o +$(BUILD_DIR)configuration_attribute.o : $(PAYLOADS_DIR)configuration_attribute.c $(PAYLOADS_DIR)configuration_attribute.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)eap_payload.o +$(BUILD_DIR)eap_payload.o : $(PAYLOADS_DIR)eap_payload.c $(PAYLOADS_DIR)eap_payload.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)unknown_payload.o +$(BUILD_DIR)unknown_payload.o : $(PAYLOADS_DIR)unknown_payload.c $(PAYLOADS_DIR)unknown_payload.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)ts_payload.o +$(BUILD_DIR)ts_payload.o : $(PAYLOADS_DIR)ts_payload.c $(PAYLOADS_DIR)ts_payload.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)traffic_selector_substructure.o +$(BUILD_DIR)traffic_selector_substructure.o : $(PAYLOADS_DIR)traffic_selector_substructure.c $(PAYLOADS_DIR)traffic_selector_substructure.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)payload.o +$(BUILD_DIR)payload.o : $(PAYLOADS_DIR)payload.c $(PAYLOADS_DIR)payload.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)proposal_substructure.o +$(BUILD_DIR)proposal_substructure.o : $(PAYLOADS_DIR)proposal_substructure.c $(PAYLOADS_DIR)proposal_substructure.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)sa_payload.o +$(BUILD_DIR)sa_payload.o : $(PAYLOADS_DIR)sa_payload.c $(PAYLOADS_DIR)sa_payload.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)transform_attribute.o +$(BUILD_DIR)transform_attribute.o : $(PAYLOADS_DIR)transform_attribute.c $(PAYLOADS_DIR)transform_attribute.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)transform_substructure.o +$(BUILD_DIR)transform_substructure.o : $(PAYLOADS_DIR)transform_substructure.c $(PAYLOADS_DIR)transform_substructure.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)encryption_payload.o +$(BUILD_DIR)encryption_payload.o : $(PAYLOADS_DIR)encryption_payload.c $(PAYLOADS_DIR)encryption_payload.h + $(CC) $(CFLAGS) -c -o $@ $< + diff --git a/src/charon/encoding/payloads/auth_payload.c b/src/charon/encoding/payloads/auth_payload.c new file mode 100644 index 000000000..cc7c4bfb1 --- /dev/null +++ b/src/charon/encoding/payloads/auth_payload.c @@ -0,0 +1,265 @@ +/** + * @file auth_payload.h + * + * @brief Implementation of auth_payload_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 "auth_payload.h" + +#include + + +typedef struct private_auth_payload_t private_auth_payload_t; + +/** + * Private data of an auth_payload_t object. + * + */ +struct private_auth_payload_t { + + /** + * Public auth_payload_t interface. + */ + auth_payload_t public; + + /** + * Next payload type. + */ + u_int8_t next_payload; + + /** + * Critical flag. + */ + bool critical; + + /** + * Length of this payload. + */ + u_int16_t payload_length; + + /** + * Method of the AUTH Data. + */ + u_int8_t auth_method; + + /** + * The contained auth data value. + */ + chunk_t auth_data; +}; + +/** + * Encoding rules to parse or generate a AUTH payload + * + * The defined offsets are the positions in a object of type + * 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) }, + /* 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 }, + /* Length of the whole payload*/ + { PAYLOAD_LENGTH, offsetof(private_auth_payload_t, payload_length)}, + /* 1 Byte AUTH type*/ + { U_INT_8, offsetof(private_auth_payload_t, auth_method) }, + /* 3 reserved bytes */ + { RESERVED_BYTE, 0 }, + { RESERVED_BYTE, 0 }, + { RESERVED_BYTE, 0 }, + /* some auth data bytes, length is defined in PAYLOAD_LENGTH */ + { AUTH_DATA, offsetof(private_auth_payload_t, auth_data) } +}; + +/* + 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! Next Payload !C! RESERVED ! Payload Length ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! Auth Method ! RESERVED ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! ! + ~ Authentication Data ~ + ! ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ + +/** + * Implementation of payload_t.verify. + */ +static status_t verify(private_auth_payload_t *this) +{ + if ((this->auth_method == 0) || + ((this->auth_method >= 4) && (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) +{ + *rules = auth_payload_encodings; + *rule_count = sizeof(auth_payload_encodings) / sizeof(encoding_rule_t); +} + +/** + * Implementation of payload_t.get_type. + */ +static payload_type_t get_payload_type(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) +{ + 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) +{ + this->next_payload = type; +} + +/** + * Implementation of payload_t.get_length. + */ +static size_t get_length(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) +{ + this->auth_method = method; +} + +/** + * Implementation of auth_payload_t.get_auth_method. + */ +static auth_method_t get_auth_method (private_auth_payload_t *this) +{ + return (this->auth_method); +} + +/** + * Implementation of auth_payload_t.set_data. + */ +static void set_data (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; + 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) +{ + return (this->auth_data); +} + +/** + * Implementation of auth_payload_t.get_data_clone. + */ +static chunk_t get_data_clone (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); +} + +/* + * Described in header + */ +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_INITIALIZER; + + return (&(this->public)); +} diff --git a/src/charon/encoding/payloads/auth_payload.h b/src/charon/encoding/payloads/auth_payload.h new file mode 100644 index 000000000..30db4f254 --- /dev/null +++ b/src/charon/encoding/payloads/auth_payload.h @@ -0,0 +1,122 @@ +/** + * @file auth_payload.h + * + * @brief Interface of auth_payload_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + + +#ifndef AUTH_PAYLOAD_H_ +#define AUTH_PAYLOAD_H_ + +#include +#include +#include + +/** + * Length of a auth payload without the auth data in bytes. + * + * @ingroup payloads + */ +#define AUTH_PAYLOAD_HEADER_LENGTH 8 + + +typedef struct auth_payload_t auth_payload_t; + +/** + * @brief Class representing an IKEv2 AUTH payload. + * + * The AUTH payload format is described in RFC section 3.8. + * + * @b Constructors: + * - auth_payload_create() + * + * @ingroup payloads + */ +struct auth_payload_t { + + /** + * The payload_t interface. + */ + payload_t payload_interface; + + /** + * @brief Set the AUTH method. + * + * @param this calling auth_payload_t object + * @param method auth_method_t to use + */ + void (*set_auth_method) (auth_payload_t *this, auth_method_t method); + + /** + * @brief Get the AUTH method. + * + * @param this calling auth_payload_t object + * @return auth_method_t used + */ + auth_method_t (*get_auth_method) (auth_payload_t *this); + + /** + * @brief Set the AUTH data. + * + * Data are getting cloned. + * + * @param this calling auth_payload_t object + * @param data AUTH data as chunk_t + */ + void (*set_data) (auth_payload_t *this, chunk_t data); + + /** + * @brief Get the AUTH data. + * + * Returned data are a copy of the internal one. + * + * @param this calling auth_payload_t object + * @return AUTH data as chunk_t + */ + chunk_t (*get_data_clone) (auth_payload_t *this); + + /** + * @brief Get the AUTH data. + * + * Returned data are NOT copied + * + * @param this calling auth_payload_t object + * @return AUTH data as chunk_t + */ + chunk_t (*get_data) (auth_payload_t *this); + + /** + * @brief Destroys an auth_payload_t object. + * + * @param this auth_payload_t object to destroy + */ + void (*destroy) (auth_payload_t *this); +}; + +/** + * @brief Creates an empty auth_payload_t object. + * + * @return auth_payload_t object + * + * @ingroup payloads + */ +auth_payload_t *auth_payload_create(void); + + +#endif /* AUTH_PAYLOAD_H_ */ diff --git a/src/charon/encoding/payloads/cert_payload.c b/src/charon/encoding/payloads/cert_payload.c new file mode 100644 index 000000000..146d42eda --- /dev/null +++ b/src/charon/encoding/payloads/cert_payload.c @@ -0,0 +1,279 @@ +/** + * @file cert_payload.c + * + * @brief Implementation of cert_payload_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 + +#include "cert_payload.h" + + +/** + * String mappings for cert_encoding_t. + */ +mapping_t cert_encoding_m[] = { + {PKCS7_WRAPPED_X509_CERTIFICATE, "PKCS7_WRAPPED_X509_CERTIFICATE"}, + {PGP_CERTIFICATE, "PGP_CERTIFICATE"}, + {DNS_SIGNED_KEY, "DNS_SIGNED_KEY"}, + {X509_CERTIFICATE_SIGNATURE, "X509_CERTIFICATE_SIGNATURE"}, + {KERBEROS_TOKEN, "KERBEROS_TOKEN"}, + {CERTIFICATE_REVOCATION_LIST, "CERTIFICATE_REVOCATION_LIST"}, + {AUTHORITY_REVOCATION_LIST, "AUTHORITY_REVOCATION_LIST"}, + {SPKI_CERTIFICATE, "SPKI_CERTIFICATE"}, + {X509_CERTIFICATE_ATTRIBUTE, "X509_CERTIFICATE_ATTRIBUTE"}, + {RAW_SA_KEY, "RAW_SA_KEY"}, + {HASH_AND_URL_X509_CERTIFICATE, "HASH_AND_URL_X509_CERTIFICATE"}, + {HASH_AND_URL_X509_BUNDLE, "HASH_AND_URL_X509_BUNDLE"}, + {MAPPING_END, NULL} +}; + + +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. + */ + cert_payload_t public; + + /** + * Next payload type. + */ + u_int8_t next_payload; + + /** + * Critical flag. + */ + bool critical; + + /** + * Length of this payload. + */ + u_int16_t payload_length; + + /** + * Encoding of the CERT Data. + */ + u_int8_t cert_encoding; + + /** + * The contained cert data value. + */ + chunk_t cert_data; +}; + +/** + * Encoding rules to parse or generate a CERT payload + * + * The defined offsets are the positions in a object of type + * 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) }, + /* the critical bit */ + { 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 }, + /* 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, cert_encoding) }, + /* some cert data bytes, length is defined in PAYLOAD_LENGTH */ + { CERT_DATA, offsetof(private_cert_payload_t, cert_data) } +}; + +/* + 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! Next Payload !C! RESERVED ! Payload Length ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! Cert Encoding ! ! + +-+-+-+-+-+-+-+-+ ! + ~ Certificate Data ~ + ! ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ + +/** + * Implementation of payload_t.verify. + */ +static status_t verify(private_cert_payload_t *this) +{ + if ((this->cert_encoding == 0) || + ((this->cert_encoding >= 14) && (this->cert_encoding <= 200))) + { + /* reserved IDs */ + return FAILED; + } + 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) +{ + *rules = cert_payload_encodings; + *rule_count = sizeof(cert_payload_encodings) / sizeof(encoding_rule_t); +} + +/** + * Implementation of payload_t.get_type. + */ +static payload_type_t get_payload_type(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) +{ + 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) +{ + this->next_payload = type; +} + +/** + * Implementation of payload_t.get_length. + */ +static size_t get_length(private_cert_payload_t *this) +{ + return this->payload_length; +} + +/** + * Implementation of cert_payload_t.set_cert_encoding. + */ +static void set_cert_encoding (private_cert_payload_t *this, cert_encoding_t encoding) +{ + this->cert_encoding = encoding; +} + +/** + * Implementation of cert_payload_t.get_cert_encoding. + */ +static cert_encoding_t get_cert_encoding (private_cert_payload_t *this) +{ + return (this->cert_encoding); +} + +/** + * Implementation of cert_payload_t.set_data. + */ +static void set_data (private_cert_payload_t *this, chunk_t data) +{ + if (this->cert_data.ptr != NULL) + { + chunk_free(&(this->cert_data)); + } + this->cert_data.ptr = clalloc(data.ptr,data.len); + this->cert_data.len = data.len; + this->payload_length = CERT_PAYLOAD_HEADER_LENGTH + this->cert_data.len; +} + +/** + * Implementation of cert_payload_t.get_data. + */ +static chunk_t get_data (private_cert_payload_t *this) +{ + return (this->cert_data); +} + +/** + * Implementation of cert_payload_t.get_data_clone. + */ +static chunk_t get_data_clone (private_cert_payload_t *this) +{ + chunk_t cloned_data; + if (this->cert_data.ptr == NULL) + { + return (this->cert_data); + } + cloned_data.ptr = clalloc(this->cert_data.ptr,this->cert_data.len); + cloned_data.len = this->cert_data.len; + return cloned_data; +} + +/** + * Implementation of payload_t.destroy and cert_payload_t.destroy. + */ +static void destroy(private_cert_payload_t *this) +{ + if (this->cert_data.ptr != NULL) + { + chunk_free(&(this->cert_data)); + } + + free(this); +} + +/* + * Described in header + */ +cert_payload_t *cert_payload_create() +{ + private_cert_payload_t *this = malloc_thing(private_cert_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 (*) (cert_payload_t *)) destroy; + this->public.set_cert_encoding = (void (*) (cert_payload_t *,cert_encoding_t)) set_cert_encoding; + this->public.get_cert_encoding = (cert_encoding_t (*) (cert_payload_t *)) get_cert_encoding; + this->public.set_data = (void (*) (cert_payload_t *,chunk_t)) set_data; + this->public.get_data_clone = (chunk_t (*) (cert_payload_t *)) get_data_clone; + this->public.get_data = (chunk_t (*) (cert_payload_t *)) get_data; + + /* private variables */ + this->critical = FALSE; + this->next_payload = NO_PAYLOAD; + this->payload_length =CERT_PAYLOAD_HEADER_LENGTH; + this->cert_data = CHUNK_INITIALIZER; + + return (&(this->public)); +} diff --git a/src/charon/encoding/payloads/cert_payload.h b/src/charon/encoding/payloads/cert_payload.h new file mode 100644 index 000000000..51620d699 --- /dev/null +++ b/src/charon/encoding/payloads/cert_payload.h @@ -0,0 +1,155 @@ +/** + * @file cert_payload.h + * + * @brief Interface of cert_payload_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef CERT_PAYLOAD_H_ +#define CERT_PAYLOAD_H_ + +#include +#include + +/** + * Length of a cert payload without the cert data in bytes. + * + * @ingroup payloads + */ +#define CERT_PAYLOAD_HEADER_LENGTH 5 + + +typedef enum cert_encoding_t cert_encoding_t; + +/** + * @brief Certificate encoding, as described in IKEv2 RFC section 3.6 + * + * @ingroup payloads + */ +enum cert_encoding_t { + PKCS7_WRAPPED_X509_CERTIFICATE = 1, + PGP_CERTIFICATE = 2, + DNS_SIGNED_KEY = 3, + X509_CERTIFICATE_SIGNATURE = 4, + KERBEROS_TOKEN = 6, + CERTIFICATE_REVOCATION_LIST = 7, + AUTHORITY_REVOCATION_LIST = 8, + SPKI_CERTIFICATE = 9, + X509_CERTIFICATE_ATTRIBUTE = 10, + RAW_SA_KEY = 11, + HASH_AND_URL_X509_CERTIFICATE = 12, + HASH_AND_URL_X509_BUNDLE = 13 +}; + +/** + * string mappings for cert_encoding_t. + * + * @ingroup payloads + */ +extern mapping_t cert_encoding_m[]; + + +typedef struct cert_payload_t cert_payload_t; + +/** + * @brief Class representing an IKEv2 CERT payload. + * + * The CERT payload format is described in RFC section 3.6. + * This is just a dummy implementation to fullfill the standards + * requirements. A full implementation would offer setters/getters + * for the different encoding types. + * + * @b Constructors: + * - cert_payload_create() + * + * @todo Implement setters/getters for the different certificate encodings. + * + * @ingroup payloads + */ +struct cert_payload_t { + + /** + * The payload_t interface. + */ + payload_t payload_interface; + + /** + * @brief Set the CERT encoding. + * + * @param this calling cert_payload_t object + * @param encoding CERT encoding + */ + void (*set_cert_encoding) (cert_payload_t *this, cert_encoding_t encoding); + + /** + * @brief Get the CERT encoding. + * + * @param this calling cert_payload_t object + * @return Encoding of the CERT + */ + cert_encoding_t (*get_cert_encoding) (cert_payload_t *this); + + /** + * @brief Set the CERT data. + * + * Data are getting cloned. + * + * @param this calling cert_payload_t object + * @param data CERT data as chunk_t + */ + void (*set_data) (cert_payload_t *this, chunk_t data); + + /** + * @brief Get the CERT data. + * + * Returned data are a copy of the internal one. + * + * @param this calling cert_payload_t object + * @return CERT data as chunk_t + */ + chunk_t (*get_data_clone) (cert_payload_t *this); + + /** + * @brief Get the CERT data. + * + * Returned data are NOT copied. + * + * @param this calling cert_payload_t object + * @return CERT data as chunk_t + */ + chunk_t (*get_data) (cert_payload_t *this); + + /** + * @brief Destroys an cert_payload_t object. + * + * @param this cert_payload_t object to destroy + */ + void (*destroy) (cert_payload_t *this); +}; + +/** + * @brief Creates an empty cert_payload_t object. + * + * @return cert_payload_t object + * + * @ingroup payloads + */ +cert_payload_t *cert_payload_create(void); + + +#endif /* CERT_PAYLOAD_H_ */ diff --git a/src/charon/encoding/payloads/certreq_payload.c b/src/charon/encoding/payloads/certreq_payload.c new file mode 100644 index 000000000..cdab82be4 --- /dev/null +++ b/src/charon/encoding/payloads/certreq_payload.c @@ -0,0 +1,259 @@ +/** + * @file certreq_payload.c + * + * @brief Implementation of certreq_payload_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 + +#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. + */ + certreq_payload_t public; + + /** + * Next payload type. + */ + u_int8_t next_payload; + + /** + * Critical flag. + */ + bool critical; + + /** + * Length of this payload. + */ + u_int16_t payload_length; + + /** + * Encoding of the CERT Data. + */ + u_int8_t cert_encoding; + + /** + * The contained certreq data value. + */ + chunk_t certreq_data; +}; + +/** + * Encoding rules to parse or generate a CERTREQ payload + * + * The defined offsets are the positions in a object of type + * private_certreq_payload_t. + * + */ +encoding_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) }, + /* 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 }, + /* Length of the whole payload*/ + { PAYLOAD_LENGTH, offsetof(private_certreq_payload_t, payload_length)}, + /* 1 Byte CERTREQ type*/ + { U_INT_8, offsetof(private_certreq_payload_t, cert_encoding)}, + /* some certreq data bytes, length is defined in PAYLOAD_LENGTH */ + { CERTREQ_DATA, offsetof(private_certreq_payload_t, certreq_data)} +}; + +/* + 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! Next Payload !C! RESERVED ! Payload Length ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! Cert Encoding ! ! + +-+-+-+-+-+-+-+-+ ! + ~ Certification Authority ~ + ! ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ + +/** + * Implementation of payload_t.verify. + */ +static status_t verify(private_certreq_payload_t *this) +{ + if ((this->cert_encoding == 0) || + ((this->cert_encoding >= 14) && (this->cert_encoding <= 200))) + { + /* reserved IDs */ + return FAILED; + } + 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) +{ + *rules = certreq_payload_encodings; + *rule_count = sizeof(certreq_payload_encodings) / sizeof(encoding_rule_t); +} + +/** + * Implementation of payload_t.get_type. + */ +static payload_type_t get_payload_type(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) +{ + 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) +{ + this->next_payload = type; +} + +/** + * Implementation of payload_t.get_length. + */ +static size_t get_length(private_certreq_payload_t *this) +{ + return this->payload_length; +} + +/** + * Implementation of certreq_payload_t.set_cert_encoding. + */ +static void set_cert_encoding (private_certreq_payload_t *this, cert_encoding_t encoding) +{ + this->cert_encoding = encoding; +} + +/** + * Implementation of certreq_payload_t.get_cert_encoding. + */ +static cert_encoding_t get_cert_encoding (private_certreq_payload_t *this) +{ + return (this->cert_encoding); +} + +/** + * Implementation of certreq_payload_t.set_data. + */ +static void set_data (private_certreq_payload_t *this, chunk_t data) +{ + if (this->certreq_data.ptr != NULL) + { + chunk_free(&(this->certreq_data)); + } + this->certreq_data.ptr = clalloc(data.ptr,data.len); + this->certreq_data.len = data.len; + this->payload_length = CERTREQ_PAYLOAD_HEADER_LENGTH + this->certreq_data.len; +} + +/** + * Implementation of certreq_payload_t.get_data. + */ +static chunk_t get_data (private_certreq_payload_t *this) +{ + return (this->certreq_data); +} + +/** + * Implementation of certreq_payload_t.get_data_clone. + */ +static chunk_t get_data_clone (private_certreq_payload_t *this) +{ + chunk_t cloned_data; + if (this->certreq_data.ptr == NULL) + { + return (this->certreq_data); + } + cloned_data.ptr = clalloc(this->certreq_data.ptr,this->certreq_data.len); + cloned_data.len = this->certreq_data.len; + return cloned_data; +} + +/** + * Implementation of payload_t.destroy and certreq_payload_t.destroy. + */ +static void destroy(private_certreq_payload_t *this) +{ + if (this->certreq_data.ptr != NULL) + { + chunk_free(&(this->certreq_data)); + } + + free(this); +} + +/* + * Described in header + */ +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.set_cert_encoding = (void (*) (certreq_payload_t *,cert_encoding_t)) set_cert_encoding; + this->public.get_cert_encoding = (cert_encoding_t (*) (certreq_payload_t *)) get_cert_encoding; + this->public.set_data = (void (*) (certreq_payload_t *,chunk_t)) set_data; + this->public.get_data_clone = (chunk_t (*) (certreq_payload_t *)) get_data_clone; + this->public.get_data = (chunk_t (*) (certreq_payload_t *)) get_data; + + /* private variables */ + this->critical = FALSE; + this->next_payload = NO_PAYLOAD; + this->payload_length =CERTREQ_PAYLOAD_HEADER_LENGTH; + this->certreq_data = CHUNK_INITIALIZER; + + return (&(this->public)); +} diff --git a/src/charon/encoding/payloads/certreq_payload.h b/src/charon/encoding/payloads/certreq_payload.h new file mode 100644 index 000000000..a4b0f1f50 --- /dev/null +++ b/src/charon/encoding/payloads/certreq_payload.h @@ -0,0 +1,125 @@ +/** + * @file certreq_payload.h + * + * @brief Interface of certreq_payload_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef CERTREQ_PAYLOAD_H_ +#define CERTREQ_PAYLOAD_H_ + +#include +#include +#include + +/** + * Length of a CERTREQ payload without the CERTREQ data in bytes. + * + * @ingroup payloads + */ +#define CERTREQ_PAYLOAD_HEADER_LENGTH 5 + + +typedef struct certreq_payload_t certreq_payload_t; + +/** + * @brief Class representing an IKEv2 CERTREQ payload. + * + * The CERTREQ payload format is described in RFC section 3.7. + * This is just a dummy implementation to fullfill the standards + * requirements. A full implementation would offer setters/getters + * for the different encoding types. + * + * @b Constructors: + * - certreq_payload_create() + * + * @todo Implement payload functionality. + * + * @ingroup payloads + */ +struct certreq_payload_t { + /** + * The payload_t interface. + */ + payload_t payload_interface; + + /** + * @brief Set the CERT encoding. + * + * @param this calling certreq_payload_t object + * @param encoding CERT encoding + */ + void (*set_cert_encoding) (certreq_payload_t *this, cert_encoding_t encoding); + + /** + * @brief Get the CERT encoding. + * + * @param this calling certreq_payload_t object + * @return Encoding of the CERT + */ + cert_encoding_t (*get_cert_encoding) (certreq_payload_t *this); + + /** + * @brief Set the CERTREQ data. + * + * Data are getting cloned. + * + * @param this calling certreq_payload_t object + * @param data CERTREQ data as chunk_t + */ + void (*set_data) (certreq_payload_t *this, chunk_t data); + + /** + * @brief Get the CERTREQ data. + * + * Returned data are a copy of the internal one. + * + * @param this calling certreq_payload_t object + * @return CERTREQ data as chunk_t + */ + chunk_t (*get_data_clone) (certreq_payload_t *this); + + /** + * @brief Get the CERTREQ data. + * + * Returned data are NOT copied. + * + * @param this calling certreq_payload_t object + * @return CERTREQ data as chunk_t + */ + chunk_t (*get_data) (certreq_payload_t *this); + + /** + * @brief Destroys an certreq_payload_t object. + * + * @param this certreq_payload_t object to destroy + */ + void (*destroy) (certreq_payload_t *this); +}; + +/** + * @brief Creates an empty certreq_payload_t object. + * + * @return certreq_payload_t object + * + * @ingroup payloads + */ +certreq_payload_t *certreq_payload_create(void); + + +#endif /* CERTREQ_PAYLOAD_H_ */ diff --git a/src/charon/encoding/payloads/configuration_attribute.c b/src/charon/encoding/payloads/configuration_attribute.c new file mode 100644 index 000000000..489d7f372 --- /dev/null +++ b/src/charon/encoding/payloads/configuration_attribute.c @@ -0,0 +1,282 @@ +/** + * @file configuration_attribute.c + * + * @brief Implementation of configuration_attribute_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 + +#include "configuration_attribute.h" + +#include +#include + + +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; + + /** + * Type of the attribute. + */ + u_int16_t attribute_type; + + /** + * Length of the attribute. + */ + u_int16_t attribute_length; + + + /** + * Attribute value as chunk. + */ + chunk_t attribute_value; +}; + +/** + * String mappings for configuration_attribute_type_t. + */ +mapping_t configuration_attribute_type_m[] = { + {INTERNAL_IP4_ADDRESS, "INTERNAL_IP4_ADDRESS"}, + {INTERNAL_IP4_NETMASK, "INTERNAL_IP4_NETMASK"}, + {INTERNAL_IP4_DNS, "INTERNAL_IP4_DNS"}, + {INTERNAL_IP4_NBNS, "INTERNAL_IP4_NBNS"}, + {INTERNAL_ADDRESS_EXPIRY, "INTERNAL_ADDRESS_EXPIRY"}, + {INTERNAL_IP4_DHCP, "INTERNAL_IP4_DHCP"}, + {APPLICATION_VERSION, "APPLICATION_VERSION"}, + {INTERNAL_IP6_ADDRESS, "INTERNAL_IP6_ADDRESS"}, + {INTERNAL_IP6_DNS, "INTERNAL_IP6_DNS"}, + {INTERNAL_IP6_NBNS, "INTERNAL_IP6_NBNS"}, + {INTERNAL_IP6_DHCP, "INTERNAL_IP6_DHCP"}, + {INTERNAL_IP4_SUBNET, "INTERNAL_IP4_SUBNET"}, + {SUPPORTED_ATTRIBUTES, "SUPPORTED_ATTRIBUTES"}, + {INTERNAL_IP6_SUBNET, "INTERNAL_IP6_SUBNET"}, + {MAPPING_END, NULL} +}; + + +/** + * Encoding rules to parse or generate a configuration attribute. + * + * The defined offsets are the positions in a object of type + * private_configuration_attribute_t. + * + */ +encoding_rule_t configuration_attribute_encodings[] = { + + { RESERVED_BIT, 0 }, + /* type of the attribute as 15 bit unsigned integer */ + { ATTRIBUTE_TYPE, offsetof(private_configuration_attribute_t, attribute_type) }, + /* Length of attribute value */ + { CONFIGURATION_ATTRIBUTE_LENGTH, offsetof(private_configuration_attribute_t, attribute_length)}, + /* Value of attribute if attribute format flag is zero */ + { CONFIGURATION_ATTRIBUTE_VALUE, offsetof(private_configuration_attribute_t, attribute_value)} +}; + +/* + 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + !R| Attribute Type ! Length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + ~ Value ~ + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ + +/** + * Implementation of payload_t.verify. + */ +static status_t verify(private_configuration_attribute_t *this) +{ + switch (this->attribute_type) + { + case INTERNAL_IP4_ADDRESS: + case INTERNAL_IP4_NETMASK: + case INTERNAL_IP4_DNS: + case INTERNAL_IP4_NBNS: + case INTERNAL_ADDRESS_EXPIRY: + case INTERNAL_IP4_DHCP: + case APPLICATION_VERSION: + case INTERNAL_IP6_ADDRESS: + case INTERNAL_IP6_DNS: + case INTERNAL_IP6_NBNS: + case INTERNAL_IP6_DHCP: + case INTERNAL_IP4_SUBNET: + case SUPPORTED_ATTRIBUTES: + case INTERNAL_IP6_SUBNET: + { + /* Attribute types are not checked in here */ + break; + } + default: + return FAILED; + } + + if (this->attribute_length != this->attribute_value.len) + { + return FAILED; + } + + 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) +{ + *rules = configuration_attribute_encodings; + *rule_count = sizeof(configuration_attribute_encodings) / sizeof(encoding_rule_t); +} + +/** + * Implementation of payload_t.get_type. + */ +static payload_type_t get_type(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) +{ + return (NO_PAYLOAD); +} + +/** + * Implementation of payload_t.set_next_type. + */ +static void set_next_type(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) +{ + return (this->attribute_value.len + CONFIGURATION_ATTRIBUTE_HEADER_LENGTH); +} + +/** + * Implementation of configuration_attribute_t.set_value. + */ +static void set_value(private_configuration_attribute_t *this, chunk_t value) +{ + if (this->attribute_value.ptr != NULL) + { + /* free existing value */ + chunk_free(&(this->attribute_value)); + } + + this->attribute_value.ptr = clalloc(value.ptr,value.len); + this->attribute_value.len = value.len; + + this->attribute_length = this->attribute_value.len; +} + +/** + * Implementation of configuration_attribute_t.get_value. + */ +static chunk_t get_value (private_configuration_attribute_t *this) +{ + return this->attribute_value; +} + + +/** + * Implementation of configuration_attribute_t.set_attribute_type. + */ +static void set_attribute_type (private_configuration_attribute_t *this, u_int16_t type) +{ + this->attribute_type = type & 0x7FFF; +} + +/** + * Implementation of configuration_attribute_t.get_attribute_type. + */ +static u_int16_t get_attribute_type (private_configuration_attribute_t *this) +{ + return this->attribute_type; +} + +/** + * Implementation of configuration_attribute_t.get_attribute_length. + */ +static u_int16_t get_attribute_length (private_configuration_attribute_t *this) +{ + return this->attribute_length; +} + + +/** + * Implementation of configuration_attribute_t.destroy and payload_t.destroy. + */ +static void destroy(private_configuration_attribute_t *this) +{ + if (this->attribute_value.ptr != NULL) + { + free(this->attribute_value.ptr); + } + free(this); +} + +/* + * Described in header. + */ +configuration_attribute_t *configuration_attribute_create() +{ + private_configuration_attribute_t *this = malloc_thing(private_configuration_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 = (void (*) (configuration_attribute_t *,chunk_t)) set_value; + this->public.get_value = (chunk_t (*) (configuration_attribute_t *)) get_value; + this->public.set_attribute_type = (void (*) (configuration_attribute_t *,u_int16_t type)) set_attribute_type; + this->public.get_attribute_type = (u_int16_t (*) (configuration_attribute_t *)) get_attribute_type; + this->public.get_attribute_length = (u_int16_t (*) (configuration_attribute_t *)) get_attribute_length; + this->public.destroy = (void (*) (configuration_attribute_t *)) destroy; + + /* set default values of the fields */ + this->attribute_type = 0; + this->attribute_value = CHUNK_INITIALIZER; + this->attribute_length = 0; + + return (&(this->public)); +} diff --git a/src/charon/encoding/payloads/configuration_attribute.h b/src/charon/encoding/payloads/configuration_attribute.h new file mode 100644 index 000000000..b8d95a190 --- /dev/null +++ b/src/charon/encoding/payloads/configuration_attribute.h @@ -0,0 +1,149 @@ +/** + * @file configuration_attribute.h + * + * @brief Interface of configuration_attribute_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef CONFIGURATION_ATTRIBUTE_H_ +#define CONFIGURATION_ATTRIBUTE_H_ + +#include +#include + + + +/** + * Configuration attribute header length in bytes. + * + * @ingroup payloads + */ +#define CONFIGURATION_ATTRIBUTE_HEADER_LENGTH 4 + + +typedef enum configuration_attribute_type_t configuration_attribute_type_t; + +/** + * Type of the attribute, as in IKEv2 RFC 3.15.1. + * + * @ingroup payloads + */ +enum configuration_attribute_type_t { + INTERNAL_IP4_ADDRESS = 1, + INTERNAL_IP4_NETMASK = 2, + INTERNAL_IP4_DNS = 3, + INTERNAL_IP4_NBNS = 4, + INTERNAL_ADDRESS_EXPIRY = 5, + INTERNAL_IP4_DHCP = 6, + APPLICATION_VERSION = 7, + INTERNAL_IP6_ADDRESS = 8, + INTERNAL_IP6_DNS = 10, + INTERNAL_IP6_NBNS = 11, + INTERNAL_IP6_DHCP = 12, + INTERNAL_IP4_SUBNET = 13, + SUPPORTED_ATTRIBUTES = 14, + INTERNAL_IP6_SUBNET = 15 +}; + +/** + * String mappings for configuration_attribute_type_t. + * + * @ingroup payloads + */ +extern mapping_t configuration_attribute_type_m[]; + +typedef struct configuration_attribute_t configuration_attribute_t; + +/** + * @brief Class representing an IKEv2-CONFIGURATION Attribute. + * + * The CONFIGURATION ATTRIBUTE format is described in RFC section 3.15.1. + * + * @b Constructors: + * - configuration_attribute_create() + * + * @ingroup payloads + */ +struct configuration_attribute_t { + /** + * The payload_t interface. + */ + payload_t payload_interface; + + /** + * @brief Returns the currently set value of the attribute. + * + * @warning Returned data are not copied. + * + * @param this calling configuration_attribute_t object + * @return chunk_t pointing to the value + */ + chunk_t (*get_value) (configuration_attribute_t *this); + + /** + * @brief Sets the value of the attribute. + * + * @warning Value is getting copied. + * + * @param this calling configuration_attribute_t object + * @param value chunk_t pointing to the value to set + */ + void (*set_value) (configuration_attribute_t *this, chunk_t value); + + /** + * @brief Sets the type of the attribute. + * + * @param this calling configuration_attribute_t object + * @param type type to set (most significant bit is set to zero) + */ + void (*set_attribute_type) (configuration_attribute_t *this, u_int16_t type); + + /** + * @brief get the type of the attribute. + * + * @param this calling configuration_attribute_t object + * @return type of the value + */ + u_int16_t (*get_attribute_type) (configuration_attribute_t *this); + + /** + * @brief get the length of an attribute. + * + * @param this calling configuration_attribute_t object + * @return type of the value + */ + u_int16_t (*get_attribute_length) (configuration_attribute_t *this); + + /** + * @brief Destroys an configuration_attribute_t object. + * + * @param this configuration_attribute_t object to destroy + */ + void (*destroy) (configuration_attribute_t *this); +}; + +/** + * @brief Creates an empty configuration_attribute_t object. + * + * @return created configuration_attribute_t object + * + * @ingroup payloads + */ +configuration_attribute_t *configuration_attribute_create(void); + +#endif /* CONFIGURATION_ATTRIBUTE_H_*/ diff --git a/src/charon/encoding/payloads/cp_payload.c b/src/charon/encoding/payloads/cp_payload.c new file mode 100644 index 000000000..583488382 --- /dev/null +++ b/src/charon/encoding/payloads/cp_payload.c @@ -0,0 +1,305 @@ +/** + * @file cp_payload.c + * + * @brief Implementation of cp_payload_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 + +#include "cp_payload.h" + +#include +#include + + +/** + * String mappings for config_type_t. + */ +mapping_t config_type_m[] = { + {CFG_REQUEST, "CFG_REQUEST"}, + {CFG_REPLY, "CFG_REPLY"}, + {CFG_SET, "CFG_SET"}, + {CFG_ACK, "CFG_ACK"}, + {MAPPING_END, NULL} +}; + + +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. + */ + cp_payload_t public; + + /** + * Next payload type. + */ + u_int8_t next_payload; + + /** + * Critical flag. + */ + bool critical; + + /** + * Length of this payload. + */ + u_int16_t payload_length; + + /** + * Configuration Attributes in this payload are stored in a linked_list_t. + */ + linked_list_t * attributes; + + /** + * Config Type. + */ + u_int8_t config_type; + + /** + * @brief Computes the length of this payload. + * + * @param this calling private_cp_payload_t object + */ + void (*compute_length) (private_cp_payload_t *this); +}; + +/** + * Encoding rules to parse or generate a IKEv2-CP Payload + * + * The defined offsets are the positions in a object of type + * private_cp_payload_t. + * + */ +encoding_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) }, + /* 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 }, + /* Length of the whole CP payload*/ + { PAYLOAD_LENGTH, offsetof(private_cp_payload_t, payload_length) }, + /* Proposals are stored in a proposal substructure, + offset points to a linked_list_t pointer */ + { U_INT_8, offsetof(private_cp_payload_t, config_type) }, + { RESERVED_BYTE,0 }, + { RESERVED_BYTE,0 }, + { RESERVED_BYTE,0 }, + { CONFIGURATION_ATTRIBUTES, offsetof(private_cp_payload_t, attributes) } +}; + +/* + 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! Next Payload !C! RESERVED ! Payload Length ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! CFG Type ! RESERVED ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! ! + ~ Configuration Attributes ~ + ! ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ + +/** + * Implementation of payload_t.verify. + */ +static status_t verify(private_cp_payload_t *this) +{ + status_t status = SUCCESS; + iterator_t *iterator; + + iterator = this->attributes->create_iterator(this->attributes,TRUE); + + while(iterator->has_next(iterator)) + { + configuration_attribute_t *attribute; + iterator->current(iterator,(void **)&attribute); + status = attribute->payload_interface.verify(&(attribute->payload_interface)); + if (status != SUCCESS) + { + break; + } + } + + iterator->destroy(iterator); + 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) +{ + *rules = cp_payload_encodings; + *rule_count = sizeof(cp_payload_encodings) / sizeof(encoding_rule_t); +} + +/** + * Implementation of payload_t.get_type. + */ +static payload_type_t get_type(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) +{ + 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) +{ + this->next_payload = type; +} + +/** + * Implementation of payload_t.get_length. + */ +static size_t get_length(private_cp_payload_t *this) +{ + this->compute_length(this); + return this->payload_length; +} + +/** + * Implementation of cp_payload_t.create_configuration_attribute_iterator. + */ +static iterator_t *create_configuration_attribute_iterator (private_cp_payload_t *this,bool forward) +{ + return this->attributes->create_iterator(this->attributes,forward); +} + +/** + * Implementation of cp_payload_t.add_proposal_substructure. + */ +static void add_configuration_attribute (private_cp_payload_t *this,configuration_attribute_t *attribute) +{ + this->attributes->insert_last(this->attributes,(void *) attribute); + this->compute_length(this); +} + +/** + * Implementation of cp_payload_t.set_config_type. + */ +static void set_config_type (private_cp_payload_t *this,config_type_t config_type) +{ + this->config_type = config_type; +} + +/** + * Implementation of cp_payload_t.get_config_type. + */ +static config_type_t get_config_type (private_cp_payload_t *this) +{ + return this->config_type; +} + +/** + * Implementation of private_cp_payload_t.compute_length. + */ +static void compute_length (private_cp_payload_t *this) +{ + iterator_t *iterator; + size_t length = CP_PAYLOAD_HEADER_LENGTH; + iterator = this->attributes->create_iterator(this->attributes,TRUE); + while (iterator->has_next(iterator)) + { + payload_t *current_attribute; + iterator->current(iterator,(void **) ¤t_attribute); + length += current_attribute->get_length(current_attribute); + } + iterator->destroy(iterator); + + this->payload_length = length; +} + +/** + * Implementation of payload_t.destroy and cp_payload_t.destroy. + */ +static status_t destroy(private_cp_payload_t *this) +{ + /* all attributes are getting destroyed */ + while (this->attributes->get_count(this->attributes) > 0) + { + configuration_attribute_t *current_attribute; + this->attributes->remove_last(this->attributes,(void **)¤t_attribute); + current_attribute->destroy(current_attribute); + } + this->attributes->destroy(this->attributes); + + free(this); + + return SUCCESS; +} + +/* + * Described in header. + */ +cp_payload_t *cp_payload_create() +{ + private_cp_payload_t *this = malloc_thing(private_cp_payload_t); + + /* public 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_configuration_attribute_iterator = (iterator_t* (*) (cp_payload_t *,bool)) create_configuration_attribute_iterator; + this->public.add_configuration_attribute = (void (*) (cp_payload_t *,configuration_attribute_t *)) add_configuration_attribute; + this->public.set_config_type = (void (*) (cp_payload_t *, config_type_t)) set_config_type; + this->public.get_config_type = (config_type_t (*) (cp_payload_t *)) get_config_type; + this->public.destroy = (void (*) (cp_payload_t *)) destroy; + + + /* private functions */ + this->compute_length = compute_length; + + /* 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(); + return (&(this->public)); +} diff --git a/src/charon/encoding/payloads/cp_payload.h b/src/charon/encoding/payloads/cp_payload.h new file mode 100644 index 000000000..235d36f43 --- /dev/null +++ b/src/charon/encoding/payloads/cp_payload.h @@ -0,0 +1,138 @@ +/** + * @file cp_payload.h + * + * @brief Interface of cp_payload_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef CP_PAYLOAD_H_ +#define CP_PAYLOAD_H_ + +#include +#include +#include +#include + +/** + * CP_PAYLOAD length in bytes without any proposal substructure. + * + * @ingroup payloads + */ +#define CP_PAYLOAD_HEADER_LENGTH 8 + + +typedef enum config_type_t config_type_t; + +/** + * Config Type of an Configuration Payload. + * + * @ingroup payloads + */ +enum config_type_t { + CFG_REQUEST = 1, + CFG_REPLY = 2, + CFG_SET = 3, + CFG_ACK = 4, +}; + +/** + * string mappings for config_type_t. + * + * @ingroup payloads + */ +extern mapping_t config_type_m[]; + + +typedef struct cp_payload_t cp_payload_t; + +/** + * @brief Class representing an IKEv2-CP Payload. + * + * The CP Payload format is described in RFC section 3.15. + * + * @b Constructors: + * - cp_payload_create() + * + * @ingroup payloads + */ +struct cp_payload_t { + /** + * The payload_t interface. + */ + payload_t payload_interface; + + /** + * @brief Creates an iterator of stored configuration_attribute_t objects. + * + * @warning The created iterator has to get destroyed by the caller! + * + * @warning When deleting an attribute using this iterator, + * the length of this configuration_attribute_t has to be refreshed + * by calling get_length()! + * + * @param this calling cp_payload_t object + * @param[in] forward iterator direction (TRUE: front to end) + * @return created iterator_t object + */ + iterator_t *(*create_configuration_attribute_iterator) (cp_payload_t *this, bool forward); + + /** + * @brief Adds a configuration_attribute_t object to this object. + * + * @warning The added configuration_attribute_t object is + * getting destroyed in destroy function of cp_payload_t. + * + * @param this calling cp_payload_t object + * @param attribute configuration_attribute_t object to add + */ + void (*add_configuration_attribute) (cp_payload_t *this, configuration_attribute_t *attribute); + + /** + * @brief Set the config type. + * + * @param this calling cp_payload_t object + * @param config_type config_type_t to set + */ + void (*set_config_type) (cp_payload_t *this,config_type_t config_type); + + /** + * @brief Get the config type. + * + * @param this calling cp_payload_t object + * @return config_type_t + */ + config_type_t (*get_config_type) (cp_payload_t *this); + + /** + * @brief Destroys an cp_payload_t object. + * + * @param this cp_payload_t object to destroy + */ + void (*destroy) (cp_payload_t *this); +}; + +/** + * @brief Creates an empty cp_payload_t object + * + * @return cp_payload_t object + * + * @ingroup payloads + */ +cp_payload_t *cp_payload_create(void); + +#endif /*CP_PAYLOAD_H_*/ diff --git a/src/charon/encoding/payloads/delete_payload.c b/src/charon/encoding/payloads/delete_payload.c new file mode 100644 index 000000000..28e78800f --- /dev/null +++ b/src/charon/encoding/payloads/delete_payload.c @@ -0,0 +1,322 @@ +/** + * @file delete_payload.c + * + * @brief Implementation of delete_payload_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 + +#include "delete_payload.h" + + +typedef struct private_delete_payload_t private_delete_payload_t; + +/** + * Private data of an delete_payload_t object. + * + */ +struct private_delete_payload_t { + /** + * Public delete_payload_t interface. + */ + delete_payload_t public; + + /** + * Next payload type. + */ + u_int8_t next_payload; + + /** + * Critical flag. + */ + bool critical; + + /** + * Length of this payload. + */ + u_int16_t payload_length; + + /** + * Protocol ID. + */ + u_int8_t protocol_id; + + /** + * SPI Size. + */ + u_int8_t spi_size; + + /** + * Number of SPI's. + */ + u_int16_t spi_count; + + /** + * The contained SPI's. + */ + chunk_t spis; +}; + +/** + * Encoding rules to parse or generate a DELETE payload + * + * The defined offsets are the positions in a object of type + * private_delete_payload_t. + * + */ +encoding_rule_t delete_payload_encodings[] = { + /* 1 Byte next payload type, stored in the field next_payload */ + { 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 }, + /* Length of the whole payload*/ + { PAYLOAD_LENGTH, offsetof(private_delete_payload_t, payload_length)}, + { U_INT_8, offsetof(private_delete_payload_t, protocol_id) }, + { U_INT_8, offsetof(private_delete_payload_t, spi_size) }, + { U_INT_16, offsetof(private_delete_payload_t, spi_count) }, + /* some delete data bytes, length is defined in PAYLOAD_LENGTH */ + { SPIS, offsetof(private_delete_payload_t, spis) } +}; + +/* + 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! Next Payload !C! RESERVED ! Payload Length ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! Protocol ID ! SPI Size ! # of SPIs ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! ! + ~ Security Parameter Index(es) (SPI) ~ + ! ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ + +/** + * Implementation of payload_t.verify. + */ +static status_t verify(private_delete_payload_t *this) +{ + if ((this->protocol_id == 0) || + (this->protocol_id > 3)) + { + /* reserved IDs */ + return FAILED; + } + if (this->spis.len != (this->spi_count * this->spi_size)) + { + return FAILED; + } + if ((this->protocol_id == PROTO_IKE) && (this->spis.len != 0)) + { + /* IKE deletion has no spi assigned! */ + return FAILED; + } + + + return SUCCESS; +} + +/** + * Implementation of delete_payload_t.get_encoding_rules. + */ +static void get_encoding_rules(private_delete_payload_t *this, encoding_rule_t **rules, size_t *rule_count) +{ + *rules = delete_payload_encodings; + *rule_count = sizeof(delete_payload_encodings) / sizeof(encoding_rule_t); +} + +/** + * Implementation of payload_t.get_type. + */ +static payload_type_t get_payload_type(private_delete_payload_t *this) +{ + return DELETE; +} + +/** + * Implementation of payload_t.get_next_type. + */ +static payload_type_t get_next_type(private_delete_payload_t *this) +{ + return (this->next_payload); +} + +/** + * Implementation of payload_t.set_next_type. + */ +static void set_next_type(private_delete_payload_t *this,payload_type_t type) +{ + this->next_payload = type; +} + +/** + * Implementation of payload_t.get_length. + */ +static size_t get_length(private_delete_payload_t *this) +{ + return this->payload_length; +} + +/** + * Implementation of delete_payload_t.set_protocol_id. + */ +static void set_protocol_id (private_delete_payload_t *this, protocol_id_t protocol_id) +{ + this->protocol_id = protocol_id; +} + +/** + * Implementation of delete_payload_t.get_protocol_id. + */ +static protocol_id_t get_protocol_id (private_delete_payload_t *this) +{ + return (this->protocol_id); +} + +/** + * Implementation of delete_payload_t.set_spi_size. + */ +static void set_spi_size (private_delete_payload_t *this, u_int8_t spi_size) +{ + this->spi_size = spi_size; +} + +/** + * Implementation of delete_payload_t.get_spi_size. + */ +static u_int8_t get_spi_size (private_delete_payload_t *this) +{ + return (this->spi_size); +} + +/** + * Implementation of delete_payload_t.set_spi_count. + */ +static void set_spi_count (private_delete_payload_t *this, u_int16_t spi_count) +{ + this->spi_count = spi_count; +} + +/** + * Implementation of delete_payload_t.get_spi_count. + */ +static u_int16_t get_spi_count (private_delete_payload_t *this) +{ + return (this->spi_count); +} + + +/** + * Implementation of delete_payload_t.set_spis. + */ +static void set_spis (private_delete_payload_t *this, chunk_t spis) +{ + if (this->spis.ptr != NULL) + { + chunk_free(&(this->spis)); + } + this->spis.ptr = clalloc(spis.ptr,spis.len); + this->spis.len = spis.len; + this->payload_length = DELETE_PAYLOAD_HEADER_LENGTH + this->spis.len; +} + +/** + * Implementation of delete_payload_t.get_spis. + */ +static chunk_t get_spis (private_delete_payload_t *this) +{ + return (this->spis); +} + +/** + * Implementation of delete_payload_t.get_spis_clone. + */ +static chunk_t get_spis_clone (private_delete_payload_t *this) +{ + chunk_t cloned_spis; + if (this->spis.ptr == NULL) + { + return (this->spis); + } + cloned_spis.ptr = clalloc(this->spis.ptr,this->spis.len); + cloned_spis.len = this->spis.len; + return cloned_spis; +} + +/** + * Implementation of payload_t.destroy and delete_payload_t.destroy. + */ +static void destroy(private_delete_payload_t *this) +{ + if (this->spis.ptr != NULL) + { + chunk_free(&(this->spis)); + } + + free(this); +} + +/* + * Described in header + */ +delete_payload_t *delete_payload_create() +{ + private_delete_payload_t *this = malloc_thing(private_delete_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 (*) (delete_payload_t *)) destroy; + this->public.set_protocol_id = (void (*) (delete_payload_t *,protocol_id_t)) set_protocol_id; + this->public.get_protocol_id = (protocol_id_t (*) (delete_payload_t *)) get_protocol_id; + this->public.set_spi_size = (void (*) (delete_payload_t *,u_int8_t)) set_spi_size; + this->public.get_spi_size = (u_int8_t (*) (delete_payload_t *)) get_spi_size; + this->public.set_spi_count = (void (*) (delete_payload_t *,u_int16_t)) set_spi_count; + this->public.get_spi_count = (u_int16_t (*) (delete_payload_t *)) get_spi_count; + this->public.set_spis = (void (*) (delete_payload_t *,chunk_t)) set_spis; + this->public.get_spis_clone = (chunk_t (*) (delete_payload_t *)) get_spis_clone; + this->public.get_spis = (chunk_t (*) (delete_payload_t *)) get_spis; + + /* private variables */ + this->critical = FALSE; + this->next_payload = NO_PAYLOAD; + this->payload_length =DELETE_PAYLOAD_HEADER_LENGTH; + this->protocol_id = PROTO_NONE; + this->spi_size = 0; + this->spi_count = 0; + this->spis = CHUNK_INITIALIZER; + + return (&(this->public)); +} diff --git a/src/charon/encoding/payloads/delete_payload.h b/src/charon/encoding/payloads/delete_payload.h new file mode 100644 index 000000000..a25d0f116 --- /dev/null +++ b/src/charon/encoding/payloads/delete_payload.h @@ -0,0 +1,156 @@ +/** + * @file delete_payload.h + * + * @brief Interface of delete_payload_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef DELETE_PAYLOAD_H_ +#define DELETE_PAYLOAD_H_ + +#include +#include +#include + +/** + * Length of a delete payload without the SPI in bytes. + * + * @ingroup payloads + */ +#define DELETE_PAYLOAD_HEADER_LENGTH 8 + + + +typedef struct delete_payload_t delete_payload_t; + +/** + * @brief Class representing an IKEv2 DELETE payload. + * + * The DELETE payload format is described in RFC section 3.11. + * + * @b Constructors: + * - delete_payload_create() + * + * @todo Implement better setter/getters + * + * @ingroup payloads + */ +struct delete_payload_t { + /** + * The payload_t interface. + */ + payload_t payload_interface; + + /** + * @brief Set the protocol ID. + * + * @param this calling delete_payload_t object + * @param protocol_id protocol ID + */ + void (*set_protocol_id) (delete_payload_t *this, protocol_id_t protocol_id); + + /** + * @brief Get the protocol ID. + * + * @param this calling delete_payload_t object + * @return protocol ID + */ + protocol_id_t (*get_protocol_id) (delete_payload_t *this); + + /** + * @brief Set the SPI size. + * + * + * @param this calling delete_payload_t object + * @param spi_size SPI size + */ + void (*set_spi_size) (delete_payload_t *this, u_int8_t spi_size); + + /** + * @brief Get the SPI size. + * + * @param this calling delete_payload_t object + * @return SPI size + */ + u_int8_t (*get_spi_size) (delete_payload_t *this); + + /** + * @brief Set the SPI count. + * + * @param this calling delete_payload_t object + * @param spi_count SPI count + */ + void (*set_spi_count) (delete_payload_t *this, u_int16_t spi_count); + + /** + * @brief Get the SPI count. + * + * @param this calling delete_payload_t object + * @return Number of SPI's + */ + u_int16_t (*get_spi_count) (delete_payload_t *this); + + /** + * @brief Set the SPI's. + * + * Data are getting cloned. + * + * @param this calling delete_payload_t object + * @param data SPI's as chunk_t + */ + void (*set_spis) (delete_payload_t *this, chunk_t spis); + + /** + * @brief Get the SPI's. + * + * Returned data are a copy of the internal one. + * + * @param this calling delete_payload_t object + * @return SPI's chunk_t + */ + chunk_t (*get_spis_clone) (delete_payload_t *this); + + /** + * @brief Get the SPI's. + * + * Returned data are NOT copied. + * + * @param this calling delete_payload_t object + * @return SPI's as chunk_t + */ + chunk_t (*get_spis) (delete_payload_t *this); + + /** + * @brief Destroys an delete_payload_t object. + * + * @param this delete_payload_t object to destroy + */ + void (*destroy) (delete_payload_t *this); +}; + +/** + * @brief Creates an empty delete_payload_t object. + * + * @return delete_payload_t object + * + * @ingroup payloads + */ +delete_payload_t *delete_payload_create(void); + + +#endif /* DELETE_PAYLOAD_H_ */ diff --git a/src/charon/encoding/payloads/eap_payload.c b/src/charon/encoding/payloads/eap_payload.c new file mode 100644 index 000000000..2a0e17679 --- /dev/null +++ b/src/charon/encoding/payloads/eap_payload.c @@ -0,0 +1,227 @@ +/** + * @file eap_payload.c + * + * @brief Implementation of eap_payload_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 + +#include "eap_payload.h" + + +typedef struct private_eap_payload_t private_eap_payload_t; + +/** + * Private data of an eap_payload_t object. + * + */ +struct private_eap_payload_t { + /** + * Public eap_payload_t interface. + */ + eap_payload_t public; + + /** + * Next payload type. + */ + u_int8_t next_payload; + + /** + * Critical flag. + */ + bool critical; + + /** + * Length of this payload. + */ + u_int16_t payload_length; + + /** + * The contained message. + */ + chunk_t message; +}; + +/** + * Encoding rules to parse or generate a EAP payload. + * + * The defined offsets are the positions in a object of type + * private_eap_payload_t. + * + */ +encoding_rule_t eap_payload_encodings[] = { + /* 1 Byte next payload type, stored in the field next_payload */ + { U_INT_8, offsetof(private_eap_payload_t, next_payload) }, + /* the critical bit */ + { 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 }, + /* Length of the whole payload*/ + { PAYLOAD_LENGTH, offsetof(private_eap_payload_t, payload_length)}, + /* some eap data bytes, length is defined in PAYLOAD_LENGTH */ + { EAP_MESSAGE, offsetof(private_eap_payload_t, message) } +}; + +/* + 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! Next Payload !C! RESERVED ! Payload Length ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! ! + ~ EAP Message ~ + ! ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ + +/** + * Implementation of payload_t.verify. + */ +static status_t verify(private_eap_payload_t *this) +{ + return SUCCESS; +} + +/** + * Implementation of eap_payload_t.get_encoding_rules. + */ +static void get_encoding_rules(private_eap_payload_t *this, encoding_rule_t **rules, size_t *rule_count) +{ + *rules = eap_payload_encodings; + *rule_count = sizeof(eap_payload_encodings) / sizeof(encoding_rule_t); +} + +/** + * Implementation of payload_t.get_type. + */ +static payload_type_t get_payload_type(private_eap_payload_t *this) +{ + return EXTENSIBLE_AUTHENTICATION; +} + +/** + * Implementation of payload_t.get_next_type. + */ +static payload_type_t get_next_type(private_eap_payload_t *this) +{ + return (this->next_payload); +} + +/** + * Implementation of payload_t.set_next_type. + */ +static void set_next_type(private_eap_payload_t *this,payload_type_t type) +{ + this->next_payload = type; +} + +/** + * Implementation of payload_t.get_length. + */ +static size_t get_length(private_eap_payload_t *this) +{ + return this->payload_length; +} + +/** + * Implementation of eap_payload_t.set_message. + */ +static void set_message (private_eap_payload_t *this, chunk_t message) +{ + if (this->message.ptr != NULL) + { + chunk_free(&(this->message)); + } + this->message.ptr = clalloc(message.ptr,message.len); + this->message.len = message.len; + this->payload_length = EAP_PAYLOAD_HEADER_LENGTH + this->message.len; +} + +/** + * Implementation of eap_payload_t.get_message. + */ +static chunk_t get_message (private_eap_payload_t *this) +{ + return (this->message); +} + +/** + * Implementation of eap_payload_t.get_data_clone. + */ +static chunk_t get_message_clone (private_eap_payload_t *this) +{ + chunk_t cloned_message; + if (this->message.ptr == NULL) + { + return (this->message); + } + cloned_message.ptr = clalloc(this->message.ptr,this->message.len); + cloned_message.len = this->message.len; + return cloned_message; +} + +/** + * Implementation of payload_t.destroy and eap_payload_t.destroy. + */ +static void destroy(private_eap_payload_t *this) +{ + if (this->message.ptr != NULL) + { + chunk_free(&(this->message)); + } + + free(this); +} + +/* + * Described in header + */ +eap_payload_t *eap_payload_create() +{ + private_eap_payload_t *this = malloc_thing(private_eap_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 (*) (eap_payload_t *)) destroy; + this->public.set_message = (void (*) (eap_payload_t *,chunk_t)) set_message; + this->public.get_message_clone = (chunk_t (*) (eap_payload_t *)) get_message_clone; + this->public.get_message = (chunk_t (*) (eap_payload_t *)) get_message; + + /* private variables */ + this->critical = FALSE; + this->next_payload = NO_PAYLOAD; + this->payload_length = EAP_PAYLOAD_HEADER_LENGTH; + this->message = CHUNK_INITIALIZER; + + return (&(this->public)); +} diff --git a/src/charon/encoding/payloads/eap_payload.h b/src/charon/encoding/payloads/eap_payload.h new file mode 100644 index 000000000..044d89cf8 --- /dev/null +++ b/src/charon/encoding/payloads/eap_payload.h @@ -0,0 +1,105 @@ +/** + * @file eap_payload.h + * + * @brief Interface of eap_payload_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef EAP_PAYLOAD_H_ +#define EAP_PAYLOAD_H_ + +#include +#include + +/** + * Length of a EAP payload without the EAP Message in bytes. + * + * @ingroup payloads + */ +#define EAP_PAYLOAD_HEADER_LENGTH 4 + + +typedef struct eap_payload_t eap_payload_t; + +/** + * @brief Class representing an IKEv2 EAP payload. + * + * The EAP payload format is described in RFC section 3.16. + * + * @b Constructors: + * - eap_payload_create() + * + * @todo Implement functionality for this payload + * + * @ingroup payloads + */ +struct eap_payload_t { + /** + * The payload_t interface. + */ + payload_t payload_interface; + + /** + * @brief Set the EAP Message. + * + * Data are getting cloned. + * + * @param this calling eap_payload_t object + * @param message EAP message as chunk_t + */ + void (*set_message) (eap_payload_t *this, chunk_t message); + + /** + * @brief Get the EAP message. + * + * Returned data are a copy of the internal one. + * + * @param this calling eap_payload_t object + * @return EAP message as chunk_t + */ + chunk_t (*get_message_clone) (eap_payload_t *this); + + /** + * @brief Get the EAP message. + * + * Returned data are NOT copied. + * + * @param this calling eap_payload_t object + * @return EAP message as chunk_t + */ + chunk_t (*get_message) (eap_payload_t *this); + + /** + * @brief Destroys an eap_payload_t object. + * + * @param this eap_payload_t object to destroy + */ + void (*destroy) (eap_payload_t *this); +}; + +/** + * @brief Creates an empty eap_payload_t object. + * + * @return eap_payload_t object + * + * @ingroup payloads + */ +eap_payload_t *eap_payload_create(void); + + +#endif /* EAP_PAYLOAD_H_ */ diff --git a/src/charon/encoding/payloads/encodings.c b/src/charon/encoding/payloads/encodings.c new file mode 100644 index 000000000..da39467a9 --- /dev/null +++ b/src/charon/encoding/payloads/encodings.c @@ -0,0 +1,68 @@ +/** + * @file encodings.c + * + * @brief String mappings of encoding_type_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 "encodings.h" + + +mapping_t encoding_type_m[] = { + {U_INT_4, "U_INT_4"}, + {U_INT_8, "U_INT_8"}, + {U_INT_16, "U_INT_16"}, + {U_INT_32, "U_INT_32"}, + {U_INT_64, "U_INT_64"}, + {IKE_SPI, "IKE_SPI"}, + {RESERVED_BIT, "RESERVED_BIT"}, + {RESERVED_BYTE, "RESERVED_BYTE"}, + {FLAG, "FLAG"}, + {PAYLOAD_LENGTH, "PAYLOAD_LENGTH"}, + {HEADER_LENGTH, "HEADER_LENGTH"}, + {SPI_SIZE, "SPI_SIZE"}, + {SPI, "SPI"}, + {KEY_EXCHANGE_DATA, "KEY_EXCHANGE_DATA"}, + {NOTIFICATION_DATA, "NOTIFICATION_DATA"}, + {PROPOSALS, "PROPOSALS"}, + {TRANSFORMS, "TRANSFORMS"}, + {TRANSFORM_ATTRIBUTES, "TRANSFORM_ATTRIBUTES"}, + {ATTRIBUTE_FORMAT, "ATTRIBUTE_FORMAT"}, + {ATTRIBUTE_TYPE, "ATTRIBUTE_TYPE"}, + {ATTRIBUTE_LENGTH_OR_VALUE, "ATTRIBUTE_LENGTH_OR_VALUE"}, + {ATTRIBUTE_VALUE, "ATTRIBUTE_VALUE"}, + {NONCE_DATA, "NONCE_DATA"}, + {ID_DATA, "ID_DATA"}, + {AUTH_DATA, "AUTH_DATA"}, + {ENCRYPTED_DATA, "ENCRYPTED_DATA"}, + {TS_TYPE, "TS_TYPE"}, + {ADDRESS, "ADDRESS"}, + {TRAFFIC_SELECTORS, "TRAFFIC_SELECTORS"}, + {CERT_DATA, "CERT_DATA"}, + {CERTREQ_DATA, "CERTREQ_DATA"}, + {SPIS, "SPIS"}, + {VID_DATA, "VID_DATA"}, + {VID_DATA, "VID_DATA"}, + {CONFIGURATION_ATTRIBUTES, "CONFIGURATION_ATTRIBUTES"}, + {CONFIGURATION_ATTRIBUTE_LENGTH, "CONFIGURATION_ATTRIBUTE_LENGTH"}, + {CONFIGURATION_ATTRIBUTE_VALUE, "CONFIGURATION_ATTRIBUTE_VALUE"}, + {EAP_MESSAGE, "EAP_MESSAGE"}, + {UNKNOWN_DATA,"UNKNOWN_DATA"}, + {MAPPING_END, NULL} +}; diff --git a/src/charon/encoding/payloads/encodings.h b/src/charon/encoding/payloads/encodings.h new file mode 100644 index 000000000..e30e1c215 --- /dev/null +++ b/src/charon/encoding/payloads/encodings.h @@ -0,0 +1,540 @@ +/** + * @file encodings.h + * + * @brief Definition of encoding_type_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef ENCODINGS_H_ +#define ENCODINGS_H_ + +#include +#include + + +typedef enum encoding_type_t encoding_type_t; + +/** + * @brief All different kinds of encoding types. + * + * Each field of an IKEv2-Message (in header or payload) + * which has to be parsed or generated differently has its own + * type defined here. + * + * Header is parsed like a payload and gets its one payload_id + * from PRIVATE USE space. Also the substructures + * of specific payload types get their own payload_id + * from PRIVATE_USE space. See IKEv2-Draft for more informations. + * + * @ingroup payloads + */ +enum encoding_type_t { + + /** + * Representing a 4 Bit unsigned int value. + * + * + * When generating it must be changed from host to network order. + * The value is read from the associated data struct. + * The current write position is moved 4 bit forward afterwards. + * + * When parsing it must be changed from network to host order. + * The value is written to the associated data struct. + * The current read pointer is moved 4 bit forward afterwards. + */ + U_INT_4, + + /** + * Representing a 8 Bit unsigned int value. + * + * + * When generating it must be changed from host to network order. + * The value is read from the associated data struct. + * The current write position is moved 8 bit forward afterwards. + * + * When parsing it must be changed from network to host order. + * The value is written to the associated data struct. + * The current read pointer is moved 8 bit forward afterwards. + */ + U_INT_8, + + /** + * Representing a 16 Bit unsigned int value. + * + * + * When generating it must be changed from host to network order. + * The value is read from the associated data struct. + * The current write position is moved 16 bit forward afterwards. + * + * When parsing it must be changed from network to host order. + * The value is written to the associated data struct. + * The current read pointer is moved 16 bit forward afterwards. + */ + U_INT_16, + + /** + * Representing a 32 Bit unsigned int value. + * + * When generating it must be changed from host to network order. + * The value is read from the associated data struct. + * The current write position is moved 32 bit forward afterwards. + * + * When parsing it must be changed from network to host order. + * The value is written to the associated data struct. + * The current read pointer is moved 32 bit forward afterwards. + */ + U_INT_32, + + /** + * Representing a 64 Bit unsigned int value. + * + * When generating it must be changed from host to network order. + * The value is read from the associated data struct. + * The current write position is moved 64 bit forward afterwards. + * + * When parsing it must be changed from network to host order. + * The value is written to the associated data struct. + * The current read pointer is moved 64 bit forward afterwards. + */ + U_INT_64, + + /** + * @brief represents a RESERVED_BIT used in FLAG-Bytes. + * + * When generating, the next bit is set to zero and the current write + * position is moved one bit forward. + * No value is read from the associated data struct. + * The current write position is moved 1 bit forward afterwards. + * + * When parsing, the current read pointer is moved one bit forward. + * No value is written to the associated data struct. + * The current read pointer is moved 1 bit forward afterwards. + */ + RESERVED_BIT, + + /** + * @brief represents a RESERVED_BYTE. + * + * When generating, the next byte is set to zero and the current write + * position is moved one byte forward. + * No value is read from the associated data struct. + * The current write position is moved 1 byte forward afterwards. + * + * When parsing, the current read pointer is moved one byte forward. + * No value is written to the associated data struct. + * The current read pointer is moved 1 byte forward afterwards. + */ + RESERVED_BYTE, + + /** + * Representing a 1 Bit flag. + * + * When generation, the next bit is set to 1 if the associated value + * in the data struct is TRUE, 0 otherwise. The current write position + * is moved 1 bit forward afterwards. + * + * When parsing, the next bit is read and stored in the associated data + * struct. 0 means FALSE, 1 means TRUE, The current read pointer + * is moved 1 bit forward afterwards + */ + FLAG, + + /** + * Representating a length field of a payload. + * + * When generating it must be changed from host to network order. + * The value is read from the associated data struct. + * The current write position is moved 16 bit forward afterwards. + * + * When parsing it must be changed from network to host order. + * The value is written to the associated data struct. + * The current read pointer is moved 16 bit forward afterwards. + */ + PAYLOAD_LENGTH, + + /** + * Representating a length field of a header. + * + * When generating it must be changed from host to network order. + * The value is read from the associated data struct. + * The current write position is moved 32 bit forward afterwards. + * + * When parsing it must be changed from network to host order. + * The value is written to the associated data struct. + * The current read pointer is moved 32 bit forward afterwards. + */ + HEADER_LENGTH, + + /** + * Representating a spi size field. + * + * When generating it must be changed from host to network order. + * The value is read from the associated data struct. + * The current write position is moved 8 bit forward afterwards. + * + * When parsing it must be changed from network to host order. + * The value is written to the associated data struct. + * The current read pointer is moved 8 bit forward afterwards. + */ + SPI_SIZE, + + /** + * Representating a spi field. + * + * When generating the content of the chunkt pointing to + * is written. + * + * When parsing SPI_SIZE bytes are read and written into the chunk pointing to. + */ + SPI, + + /** + * Representating a Key Exchange Data field. + * + * When generating the content of the chunkt pointing to + * is written. + * + * When parsing (Payload Length - 8) bytes are read and written into the chunk pointing to. + */ + KEY_EXCHANGE_DATA, + + /** + * Representating a Notification field. + * + * When generating the content of the chunkt pointing to + * is written. + * + * When parsing (Payload Length - spi size - 8) bytes are read and written into the chunk pointing to. + */ + NOTIFICATION_DATA, + + /** + * Representating one or more proposal substructures. + * + * The offset points to a linked_list_t pointer. + * + * When generating the proposal_substructure_t objects are stored + * in the pointed linked_list. + * + * When parsing the parsed proposal_substructure_t objects have + * to be stored in the pointed linked_list. + */ + PROPOSALS, + + /** + * Representating one or more transform substructures. + * + * The offset points to a linked_list_t pointer. + * + * When generating the transform_substructure_t objects are stored + * in the pointed linked_list. + * + * When parsing the parsed transform_substructure_t objects have + * to be stored in the pointed linked_list. + */ + TRANSFORMS, + + /** + * Representating one or more Attributes of a transform substructure. + * + * The offset points to a linked_list_t pointer. + * + * When generating the transform_attribute_t objects are stored + * in the pointed linked_list. + * + * When parsing the parsed transform_attribute_t objects have + * to be stored in the pointed linked_list. + */ + TRANSFORM_ATTRIBUTES, + + /** + * Representating one or more Attributes of a configuration payload. + * + * The offset points to a linked_list_t pointer. + * + * When generating the configuration_attribute_t objects are stored + * in the pointed linked_list. + * + * When parsing the parsed configuration_attribute_t objects have + * to be stored in the pointed linked_list. + */ + CONFIGURATION_ATTRIBUTES, + + /** + * + * When generating the content of the chunkt pointing to + * is written. + * + * When parsing (Payload Length - 4) bytes are read and written into the chunk pointing to. + */ + CONFIGURATION_ATTRIBUTE_VALUE, + + /** + * Representing a 1 Bit flag specifying the format of a transform attribute. + * + * When generation, the next bit is set to 1 if the associated value + * in the data struct is TRUE, 0 otherwise. The current write position + * is moved 1 bit forward afterwards. + * + * When parsing, the next bit is read and stored in the associated data + * struct. 0 means FALSE, 1 means TRUE, The current read pointer + * is moved 1 bit forward afterwards. + */ + ATTRIBUTE_FORMAT, + /** + * Representing a 15 Bit unsigned int value used as attribute type + * in an attribute transform. + * + * + * When generating it must be changed from host to network order. + * The value is read from the associated data struct. + * The current write position is moved 15 bit forward afterwards. + * + * When parsing it must be changed from network to host order. + * The value is written to the associated data struct. + * The current read pointer is moved 15 bit forward afterwards. + */ + ATTRIBUTE_TYPE, + + /** + * Depending on the field of type ATTRIBUTE_FORMAT + * this field contains the length or the value of an transform attribute. + * Its stored in a 16 unsigned integer field. + * + * When generating it must be changed from host to network order. + * The value is read from the associated data struct. + * The current write position is moved 16 bit forward afterwards. + * + * When parsing it must be changed from network to host order. + * The value is written to the associated data struct. + * The current read pointer is moved 16 bit forward afterwards. + */ + ATTRIBUTE_LENGTH_OR_VALUE, + + /** + * This field contains the length or the value of an configuration attribute. + * Its stored in a 16 unsigned integer field. + * + * When generating it must be changed from host to network order. + * The value is read from the associated data struct. + * The current write position is moved 16 bit forward afterwards. + * + * When parsing it must be changed from network to host order. + * The value is written to the associated data struct. + * The current read pointer is moved 16 bit forward afterwards. + */ + CONFIGURATION_ATTRIBUTE_LENGTH, + + /** + * Depending on the field of type ATTRIBUTE_FORMAT + * this field is available or missing and so parsed/generated + * or not parsed/not generated. + * + * When generating the content of the chunkt pointing to + * is written. + * + * When parsing SPI_SIZE bytes are read and written into the chunk pointing to. + */ + ATTRIBUTE_VALUE, + + /** + * Representating one or more Traffic selectors of a TS payload. + * + * The offset points to a linked_list_t pointer. + * + * When generating the traffic_selector_substructure_t objects are stored + * in the pointed linked_list. + * + * When parsing the parsed traffic_selector_substructure_t objects have + * to be stored in the pointed linked_list. + */ + TRAFFIC_SELECTORS, + + /** + * Representating a Traffic selector type field. + * + * When generating it must be changed from host to network order. + * The value is read from the associated data struct. + * The current write position is moved 16 bit forward afterwards. + * + * When parsing it must be changed from network to host order. + * The value is written to the associated data struct. + * The current read pointer is moved 16 bit forward afterwards. + */ + TS_TYPE, + + /** + * Representating an address field in a traffic selector. + * + * Depending on the last field of type TS_TYPE + * this field is either 4 or 16 byte long. + * + * When generating the content of the chunkt pointing to + * is written. + * + * When parsing 4 or 16 bytes are read and written into the chunk pointing to. + */ + ADDRESS, + + /** + * Representating a Nonce Data field. + * + * When generating the content of the chunkt pointing to + * is written. + * + * When parsing (Payload Length - 4) bytes are read and written into the chunk pointing to. + */ + NONCE_DATA, + + /** + * Representating a ID Data field. + * + * When generating the content of the chunkt pointing to + * is written. + * + * When parsing (Payload Length - 8) bytes are read and written into the chunk pointing to. + */ + ID_DATA, + + /** + * Representating a AUTH Data field. + * + * When generating the content of the chunkt pointing to + * is written. + * + * When parsing (Payload Length - 8) bytes are read and written into the chunk pointing to. + */ + AUTH_DATA, + + /** + * Representating a CERT Data field. + * + * When generating the content of the chunkt pointing to + * is written. + * + * When parsing (Payload Length - 5) bytes are read and written into the chunk pointing to. + */ + CERT_DATA, + + /** + * Representating a CERTREQ Data field. + * + * When generating the content of the chunkt pointing to + * is written. + * + * When parsing (Payload Length - 5) bytes are read and written into the chunk pointing to. + */ + CERTREQ_DATA, + + /** + * Representating an EAP message field. + * + * When generating the content of the chunkt pointing to + * is written. + * + * When parsing (Payload Length - 4) bytes are read and written into the chunk pointing to. + */ + EAP_MESSAGE, + + /** + * Representating the SPIS field in a DELETE payload. + * + * When generating the content of the chunkt pointing to + * is written. + * + * When parsing (Payload Length - 8) bytes are read and written into the chunk pointing to. + */ + SPIS, + + /** + * Representating the VID DATA field in a VENDOR ID payload. + * + * When generating the content of the chunkt pointing to + * is written. + * + * When parsing (Payload Length - 4) bytes are read and written into the chunk pointing to. + */ + VID_DATA, + + /** + * Representating the DATA of an unknown payload. + * + * When generating the content of the chunkt pointing to + * is written. + * + * When parsing (Payload Length - 4) bytes are read and written into the chunk pointing to. + */ + UNKNOWN_DATA, + + /** + * Representating an IKE_SPI field in an IKEv2 Header. + * + * When generating the value of the u_int64_t pointing to + * is written (host and networ order is not changed). + * + * When parsing 8 bytes are read and written into the u_int64_t pointing to. + */ + IKE_SPI, + + /** + * Representing the encrypted data body of a encryption payload. + */ + ENCRYPTED_DATA, +}; + +/** + * mappings to map encoding_type_t's to strings + * + * @ingroup payloads + */ +extern mapping_t encoding_type_m[]; + + +typedef struct encoding_rule_t encoding_rule_t; + +/** + * An encoding rule is a mapping of a specific encoding type to + * a location in the data struct where the current field is stored to + * or read from. + * + * For examples see files in this directory. + * + * This rules are used by parser and generator. + * + * @ingroup payloads + */ +struct encoding_rule_t { + + /** + * Encoding type. + */ + encoding_type_t type; + + /** + * Offset in the data struct. + * + * When parsing, data are written to this offset of the + * data struct. + * + * When generating, data are read from this offset in the + * data struct. + */ + u_int32_t offset; +}; + +#endif /*ENCODINGS_H_*/ diff --git a/src/charon/encoding/payloads/encryption_payload.c b/src/charon/encoding/payloads/encryption_payload.c new file mode 100644 index 000000000..e0ca74ff4 --- /dev/null +++ b/src/charon/encoding/payloads/encryption_payload.c @@ -0,0 +1,702 @@ +/** + * @file encryption_payload.c + * + * @brief Implementation of encryption_payload_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 +#include + +#include "encryption_payload.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + + +typedef struct private_encryption_payload_t private_encryption_payload_t; + +/** + * Private data of an encryption_payload_t' Object. + * + */ +struct private_encryption_payload_t { + + /** + * Public encryption_payload_t interface. + */ + encryption_payload_t public; + + /** + * There is no next payload for an encryption payload, + * since encryption payload MUST be the last one. + * next_payload means here the first payload of the + * contained, encrypted payload. + */ + u_int8_t next_payload; + + /** + * Critical flag. + */ + bool critical; + + /** + * Length of this payload + */ + u_int16_t payload_length; + + /** + * Chunk containing the iv, data, padding, + * and (an eventually not calculated) signature. + */ + chunk_t encrypted; + + /** + * Chunk containing the data in decrypted (unpadded) form. + */ + chunk_t decrypted; + + /** + * Signer set by set_signer. + */ + signer_t *signer; + + /** + * Crypter, supplied by encrypt/decrypt + */ + crypter_t *crypter; + + /** + * Contained payloads of this encrpytion_payload. + */ + linked_list_t *payloads; + + /** + * logger for this payload, uses MESSAGE context + */ + logger_t *logger; + + /** + * @brief Computes the length of this payload. + * + * @param this calling private_encryption_payload_t object + */ + void (*compute_length) (private_encryption_payload_t *this); + + /** + * @brief Generate payloads (unencrypted) in chunk decrypted. + * + * @param this calling private_encryption_payload_t object + */ + void (*generate) (private_encryption_payload_t *this); + + /** + * @brief Parse payloads from a (unencrypted) chunk. + * + * @param this calling private_encryption_payload_t object + */ + status_t (*parse) (private_encryption_payload_t *this); +}; + +/** + * Encoding rules to parse or generate a IKEv2-Encryption Payload. + * + * The defined offsets are the positions in a object of type + * private_encryption_payload_t. + * + */ +encoding_rule_t encryption_payload_encodings[] = { + /* 1 Byte next payload type, stored in the field next_payload */ + { U_INT_8, offsetof(private_encryption_payload_t, next_payload) }, + /* the critical bit */ + { FLAG, offsetof(private_encryption_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 }, + /* Length of the whole encryption payload*/ + { PAYLOAD_LENGTH, offsetof(private_encryption_payload_t, payload_length) }, + /* encrypted data, stored in a chunk. contains iv, data, padding */ + { ENCRYPTED_DATA, offsetof(private_encryption_payload_t, encrypted) }, +}; + +/* + 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! Next Payload !C! RESERVED ! Payload Length ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! Initialization Vector ! + ! (length is block size for encryption algorithm) ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! Encrypted IKE Payloads ! + + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! ! Padding (0-255 octets) ! + +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ + ! ! Pad Length ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ~ Integrity Checksum Data ~ + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ + +/** + * Implementation of payload_t.verify. + */ +static status_t verify(private_encryption_payload_t *this) +{ + return SUCCESS; +} + +/** + * Implementation of payload_t.get_encoding_rules. + */ +static void get_encoding_rules(private_encryption_payload_t *this, encoding_rule_t **rules, size_t *rule_count) +{ + *rules = encryption_payload_encodings; + *rule_count = sizeof(encryption_payload_encodings) / sizeof(encoding_rule_t); +} + +/** + * Implementation of payload_t.get_type. + */ +static payload_type_t get_type(private_encryption_payload_t *this) +{ + return ENCRYPTED; +} + +/** + * Implementation of payload_t.get_next_type. + */ +static payload_type_t get_next_type(private_encryption_payload_t *this) +{ + /* returns first contained payload here */ + return (this->next_payload); +} + +/** + * Implementation of payload_t.set_next_type. + */ +static void set_next_type(private_encryption_payload_t *this, payload_type_t type) +{ + /* set next type is not allowed, since this payload MUST be the last one + * and so nothing is done in here*/ +} + +/** + * Implementation of payload_t.get_length. + */ +static size_t get_length(private_encryption_payload_t *this) +{ + this->compute_length(this); + return this->payload_length; +} + +/** + * Implementation of payload_t.create_payload_iterator. + */ +static iterator_t *create_payload_iterator (private_encryption_payload_t *this, bool forward) +{ + return (this->payloads->create_iterator(this->payloads, forward)); +} + +/** + * Implementation of payload_t.add_payload. + */ +static void add_payload(private_encryption_payload_t *this, payload_t *payload) +{ + payload_t *last_payload; + if (this->payloads->get_count(this->payloads) > 0) + { + this->payloads->get_last(this->payloads,(void **) &last_payload); + last_payload->set_next_type(last_payload, payload->get_type(payload)); + } + else + { + this->next_payload = payload->get_type(payload); + } + payload->set_next_type(payload, NO_PAYLOAD); + this->payloads->insert_last(this->payloads, (void*)payload); + this->compute_length(this); +} + +/** + * Implementation of encryption_payload_t.remove_first_payload. + */ +static status_t remove_first_payload(private_encryption_payload_t *this, payload_t **payload) +{ + return this->payloads->remove_first(this->payloads, (void**)payload); +} + +/** + * Implementation of encryption_payload_t.get_payload_count. + */ +static size_t get_payload_count(private_encryption_payload_t *this) +{ + return this->payloads->get_count(this->payloads); +} + + +/** + * Implementation of encryption_payload_t.encrypt. + */ +static status_t encrypt(private_encryption_payload_t *this) +{ + chunk_t iv, padding, to_crypt, result; + randomizer_t *randomizer; + status_t status; + size_t block_size; + + if (this->signer == NULL || this->crypter == NULL) + { + this->logger->log(this->logger, ERROR, "could not encrypt, signer/crypter not set"); + return INVALID_STATE; + } + + /* for random data in iv and padding */ + randomizer = randomizer_create(); + + + /* build payload chunk */ + this->generate(this); + + this->logger->log(this->logger, CONTROL|LEVEL2, "encrypting payloads"); + this->logger->log_chunk(this->logger, RAW|LEVEL2, "data to encrypt", this->decrypted); + + /* build padding */ + block_size = this->crypter->get_block_size(this->crypter); + padding.len = block_size - ((this->decrypted.len + 1) % block_size); + status = randomizer->allocate_pseudo_random_bytes(randomizer, padding.len, &padding); + if (status != SUCCESS) + { + randomizer->destroy(randomizer); + return status; + } + + /* concatenate payload data, padding, padding len */ + to_crypt.len = this->decrypted.len + padding.len + 1; + to_crypt.ptr = malloc(to_crypt.len); + + memcpy(to_crypt.ptr, this->decrypted.ptr, this->decrypted.len); + memcpy(to_crypt.ptr + this->decrypted.len, padding.ptr, padding.len); + *(to_crypt.ptr + to_crypt.len - 1) = padding.len; + + /* build iv */ + iv.len = block_size; + status = randomizer->allocate_pseudo_random_bytes(randomizer, iv.len, &iv); + randomizer->destroy(randomizer); + if (status != SUCCESS) + { + chunk_free(&to_crypt); + chunk_free(&padding); + return status; + } + + this->logger->log_chunk(this->logger, RAW|LEVEL2, "data before encryption with padding", to_crypt); + + /* encrypt to_crypt chunk */ + free(this->encrypted.ptr); + status = this->crypter->encrypt(this->crypter, to_crypt, iv, &result); + free(padding.ptr); + free(to_crypt.ptr); + if (status != SUCCESS) + { + this->logger->log(this->logger, ERROR|LEVEL1, "encryption failed"); + free(iv.ptr); + return status; + } + this->logger->log_chunk(this->logger, RAW|LEVEL2, "data after encryption", result); + + + /* build encrypted result with iv and signature */ + this->encrypted.len = iv.len + result.len + this->signer->get_block_size(this->signer); + free(this->encrypted.ptr); + this->encrypted.ptr = malloc(this->encrypted.len); + + /* fill in result, signature is left out */ + memcpy(this->encrypted.ptr, iv.ptr, iv.len); + memcpy(this->encrypted.ptr + iv.len, result.ptr, result.len); + + free(result.ptr); + free(iv.ptr); + this->logger->log_chunk(this->logger, RAW|LEVEL2, "data after encryption with IV and (invalid) signature", this->encrypted); + + return SUCCESS; +} + +/** + * Implementation of encryption_payload_t.encrypt. + */ +static status_t decrypt(private_encryption_payload_t *this) +{ + chunk_t iv, concatenated; + u_int8_t padding_length; + status_t status; + + + this->logger->log(this->logger, CONTROL|LEVEL2, "decrypting encryption payload"); + this->logger->log_chunk(this->logger, RAW|LEVEL2, "data before decryption with IV and (invalid) signature", this->encrypted); + + + if (this->signer == NULL || this->crypter == NULL) + { + this->logger->log(this->logger, ERROR, "could not decrypt, no crypter/signer set"); + return INVALID_STATE; + } + + /* get IV */ + iv.len = this->crypter->get_block_size(this->crypter); + + iv.ptr = this->encrypted.ptr; + + /* point concatenated to data + padding + padding_length*/ + concatenated.ptr = this->encrypted.ptr + iv.len; + concatenated.len = this->encrypted.len - iv.len - this->signer->get_block_size(this->signer); + + /* check the size of input: + * concatenated must be at least on block_size of crypter + */ + if (concatenated.len < iv.len) + { + this->logger->log(this->logger, ERROR|LEVEL1, "could not decrypt, invalid input"); + return FAILED; + } + + /* free previus data, if any */ + free(this->decrypted.ptr); + + this->logger->log_chunk(this->logger, RAW|LEVEL2, "data before decryption", concatenated); + + status = this->crypter->decrypt(this->crypter, concatenated, iv, &(this->decrypted)); + if (status != SUCCESS) + { + this->logger->log(this->logger, ERROR|LEVEL1, "could not decrypt, decryption failed"); + return FAILED; + } + this->logger->log_chunk(this->logger, RAW|LEVEL2, "data after decryption with padding", this->decrypted); + + + /* get padding length, sits just bevore signature */ + padding_length = *(this->decrypted.ptr + this->decrypted.len - 1); + /* add one byte to the padding length, since the padding_length field is not included */ + padding_length++; + this->decrypted.len -= padding_length; + + /* check size again */ + if (padding_length > concatenated.len || this->decrypted.len < 0) + { + this->logger->log(this->logger, ERROR|LEVEL1, "decryption failed, invalid padding length found. Invalid key?"); + /* decryption failed :-/ */ + return FAILED; + } + + /* free padding */ + this->decrypted.ptr = realloc(this->decrypted.ptr, this->decrypted.len); + this->logger->log_chunk(this->logger, RAW|LEVEL2, "data after decryption without padding", this->decrypted); + this->logger->log(this->logger, CONTROL|LEVEL2, "decryption successful, trying to parse content"); + return (this->parse(this)); +} + +/** + * Implementation of encryption_payload_t.set_transforms. + */ +static void set_transforms(private_encryption_payload_t *this, crypter_t* crypter, signer_t* signer) +{ + this->signer = signer; + this->crypter = crypter; +} + +/** + * Implementation of encryption_payload_t.build_signature. + */ +static status_t build_signature(private_encryption_payload_t *this, chunk_t data) +{ + chunk_t data_without_sig = data; + chunk_t sig; + + if (this->signer == NULL) + { + this->logger->log(this->logger, ERROR, "unable to build signature, no signer set"); + return INVALID_STATE; + } + + sig.len = this->signer->get_block_size(this->signer); + data_without_sig.len -= sig.len; + sig.ptr = data.ptr + data_without_sig.len; + this->logger->log(this->logger, CONTROL|LEVEL2, "building signature"); + this->signer->get_signature(this->signer, data_without_sig, sig.ptr); + return SUCCESS; +} + +/** + * Implementation of encryption_payload_t.verify_signature. + */ +static status_t verify_signature(private_encryption_payload_t *this, chunk_t data) +{ + chunk_t sig, data_without_sig; + bool valid; + + if (this->signer == NULL) + { + this->logger->log(this->logger, ERROR, "unable to verify signature, no signer set"); + return INVALID_STATE; + } + /* find signature in data chunk */ + sig.len = this->signer->get_block_size(this->signer); + if (data.len <= sig.len) + { + this->logger->log(this->logger, ERROR|LEVEL1, "unable to verify signature, invalid input"); + return FAILED; + } + sig.ptr = data.ptr + data.len - sig.len; + + /* verify it */ + data_without_sig.len = data.len - sig.len; + data_without_sig.ptr = data.ptr; + valid = this->signer->verify_signature(this->signer, data_without_sig, sig); + + if (!valid) + { + this->logger->log(this->logger, ERROR|LEVEL1, "signature verification failed"); + return FAILED; + } + + this->logger->log(this->logger, CONTROL|LEVEL2, "signature verification successful"); + return SUCCESS; +} + +/** + * Implementation of private_encryption_payload_t.generate. + */ +static void generate(private_encryption_payload_t *this) +{ + payload_t *current_payload, *next_payload; + generator_t *generator; + iterator_t *iterator; + + /* recalculate length before generating */ + this->compute_length(this); + + /* create iterator */ + iterator = this->payloads->create_iterator(this->payloads, TRUE); + + /* get first payload */ + if (iterator->has_next(iterator)) + { + iterator->current(iterator, (void**)¤t_payload); + this->next_payload = current_payload->get_type(current_payload); + } + else + { + /* no paylads? */ + this->logger->log(this->logger, CONTROL|LEVEL1, "generating contained payloads, but no available"); + free(this->decrypted.ptr); + this->decrypted = CHUNK_INITIALIZER; + iterator->destroy(iterator); + return; + } + + generator = generator_create(); + + /* build all payload, except last */ + while(iterator->has_next(iterator)) + { + iterator->current(iterator, (void**)&next_payload); + current_payload->set_next_type(current_payload, next_payload->get_type(next_payload)); + generator->generate_payload(generator, current_payload); + current_payload = next_payload; + } + iterator->destroy(iterator); + + /* build last payload */ + current_payload->set_next_type(current_payload, NO_PAYLOAD); + generator->generate_payload(generator, current_payload); + + /* free already generated data */ + free(this->decrypted.ptr); + + generator->write_to_chunk(generator, &(this->decrypted)); + generator->destroy(generator); + this->logger->log(this->logger, CONTROL|LEVEL1, "successfully generated content in encrpytion payload"); +} + +/** + * Implementation of private_encryption_payload_t.parse. + */ +static status_t parse(private_encryption_payload_t *this) +{ + parser_t *parser; + status_t status; + payload_type_t current_payload_type; + + /* check if there is decrypted data */ + if (this->decrypted.ptr == NULL) + { + this->logger->log(this->logger, ERROR, "unable to parse, no input!"); + return INVALID_STATE; + } + + /* build a parser on the decrypted data */ + parser = parser_create(this->decrypted); + + current_payload_type = this->next_payload; + /* parse all payloads */ + while (current_payload_type != NO_PAYLOAD) + { + payload_t *current_payload; + + status = parser->parse_payload(parser, current_payload_type, (payload_t**)¤t_payload); + if (status != SUCCESS) + { + parser->destroy(parser); + return PARSE_ERROR; + } + + status = current_payload->verify(current_payload); + if (status != SUCCESS) + { + this->logger->log(this->logger, ERROR|LEVEL1, "%s verification failed: %s", + mapping_find(payload_type_m,current_payload->get_type(current_payload)), + mapping_find(status_m, status)); + current_payload->destroy(current_payload); + parser->destroy(parser); + return VERIFY_ERROR; + } + + /* get next payload type */ + current_payload_type = current_payload->get_next_type(current_payload); + + this->payloads->insert_last(this->payloads,current_payload); + } + parser->destroy(parser); + this->logger->log(this->logger, CONTROL|LEVEL1, "succesfully parsed content of encryption payload"); + return SUCCESS; +} + +/** + * Implementation of private_encryption_payload_t.compute_length. + */ +static void compute_length(private_encryption_payload_t *this) +{ + iterator_t *iterator; + size_t block_size, length = 0; + iterator = this->payloads->create_iterator(this->payloads, TRUE); + + /* count payload length */ + while (iterator->has_next(iterator)) + { + payload_t *current_payload; + iterator->current(iterator, (void **) ¤t_payload); + length += current_payload->get_length(current_payload); + } + iterator->destroy(iterator); + + if (this->crypter && this->signer) + { + /* append one byte for padding length */ + length++; + /* append padding */ + block_size = this->crypter->get_block_size(this->crypter); + length += block_size - length % block_size; + /* add iv */ + length += block_size; + /* add signature */ + length += this->signer->get_block_size(this->signer); + } + length += ENCRYPTION_PAYLOAD_HEADER_LENGTH; + this->payload_length = length; +} + + +/** + * Implementation of payload_t.destroy. + */ +static void destroy(private_encryption_payload_t *this) +{ + /* all proposals are getting destroyed */ + while (this->payloads->get_count(this->payloads) > 0) + { + payload_t *current_payload; + this->payloads->remove_last(this->payloads,(void **)¤t_payload); + current_payload->destroy(current_payload); + } + this->payloads->destroy(this->payloads); + free(this->encrypted.ptr); + free(this->decrypted.ptr); + free(this); +} + +/* + * Described in header + */ +encryption_payload_t *encryption_payload_create() +{ + private_encryption_payload_t *this = malloc_thing(private_encryption_payload_t); + + /* 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.create_payload_iterator = (iterator_t * (*) (encryption_payload_t *,bool)) create_payload_iterator; + this->public.add_payload = (void (*) (encryption_payload_t *,payload_t *)) add_payload; + this->public.remove_first_payload = (status_t (*)(encryption_payload_t*, payload_t **)) remove_first_payload; + this->public.get_payload_count = (size_t (*)(encryption_payload_t*)) get_payload_count; + + this->public.encrypt = (status_t (*) (encryption_payload_t *)) encrypt; + this->public.decrypt = (status_t (*) (encryption_payload_t *)) decrypt; + this->public.set_transforms = (void (*) (encryption_payload_t*,crypter_t*,signer_t*)) set_transforms; + this->public.build_signature = (status_t (*) (encryption_payload_t*, chunk_t)) build_signature; + this->public.verify_signature = (status_t (*) (encryption_payload_t*, chunk_t)) verify_signature; + this->public.destroy = (void (*) (encryption_payload_t *)) destroy; + + /* private functions */ + this->compute_length = compute_length; + this->generate = generate; + this->parse = parse; + this->logger = logger_manager->get_logger(logger_manager, ENCRYPTION_PAYLOAD); + + /* set default values of the fields */ + this->critical = FALSE; + this->next_payload = NO_PAYLOAD; + this->payload_length = ENCRYPTION_PAYLOAD_HEADER_LENGTH; + this->encrypted = CHUNK_INITIALIZER; + this->decrypted = CHUNK_INITIALIZER; + this->signer = NULL; + this->crypter = NULL; + this->payloads = linked_list_create(); + + return (&(this->public)); +} diff --git a/src/charon/encoding/payloads/encryption_payload.h b/src/charon/encoding/payloads/encryption_payload.h new file mode 100644 index 000000000..006df969c --- /dev/null +++ b/src/charon/encoding/payloads/encryption_payload.h @@ -0,0 +1,196 @@ +/** + * @file encryption_payload.h + * + * @brief Interface of encryption_payload_t. + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef ENCRYPTION_PAYLOAD_H_ +#define ENCRYPTION_PAYLOAD_H_ + +#include +#include +#include +#include +#include + +/** + * Encrpytion payload length in bytes without IV and following data. + * + * @ingroup payloads + */ +#define ENCRYPTION_PAYLOAD_HEADER_LENGTH 4 + + +typedef struct encryption_payload_t encryption_payload_t; + +/** + * @brief The encryption payload as described in RFC section 3.14. + * + * Before any crypt/decrypt/sign/verify operation can occur, + * the transforms must be set. After that, a parsed encryption payload + * can be decrypted, which also will parse the contained payloads. + * Encryption is done the same way, added payloads will get generated + * and then encrypted. + * For signature building, there is the FULL packet needed. Meaning it + * must be builded after generation of all payloads and the encryption + * of the encryption payload. + * Signature verificatin is done before decryption. + * + * @b Constructors: + * - encryption_payload_create() + * + * @ingroup payloads + */ +struct encryption_payload_t { + /** + * Implements payload_t interface. + */ + payload_t payload_interface; + + /** + * @brief Creates an iterator for all contained payloads. + * + * @warning iterator_t object has to get destroyed by the caller. + * + * @param this calling encryption_payload_t object + * @param[in] forward iterator direction (TRUE: front to end) + * return created iterator_t object + */ + iterator_t *(*create_payload_iterator) (encryption_payload_t *this, bool forward); + + /** + * @brief Adds a payload to this encryption payload. + * + * @param this calling encryption_payload_t object + * @param payload payload_t object to add + */ + void (*add_payload) (encryption_payload_t *this, payload_t *payload); + + /** + * @brief Reove the last payload in the contained payload list. + * + * @param this calling encryption_payload_t object + * @param[out] payload removed payload + * @return + * - SUCCESS, or + * - NOT_FOUND if list empty + */ + status_t (*remove_first_payload) (encryption_payload_t *this, payload_t **payload); + + /** + * @brief Get the number of payloads. + * + * @param this calling encryption_payload_t object + * @return number of contained payloads + */ + size_t (*get_payload_count) (encryption_payload_t *this); + + /** + * @brief Set transforms to use. + * + * To decryption, encryption, signature building and verifying, + * the payload needs a crypter and a signer object. + * + * @warning Do NOT call this function again after encryption, since + * the signer must be the same while encrypting and signature building! + * + * @param this calling encryption_payload_t + * @param crypter crypter_t to use for data de-/encryption + * @param signer signer_t to use for data signing/verifying + */ + void (*set_transforms) (encryption_payload_t *this, crypter_t *crypter, signer_t *signer); + + /** + * @brief Generate and encrypt contained payloads. + * + * This function generates the content for added payloads + * and encrypts them. Signature is not built, since we need + * additional data (the full message). + * + * @param this calling encryption_payload_t + * @return + * - SUCCESS, or + * - INVALID_STATE if transforms not set + */ + status_t (*encrypt) (encryption_payload_t *this); + + /** + * @brief Decrypt and parse contained payloads. + * + * This function decrypts the contained data. After, + * the payloads are parsed internally and are accessible + * via the iterator. + * + * @param this calling encryption_payload_t + * @return + * - SUCCESS, or + * - INVALID_STATE if transforms not set, or + * - FAILED if data is invalid + */ + status_t (*decrypt) (encryption_payload_t *this); + + /** + * @brief Build the signature. + * + * The signature is built over the FULL message, so the header + * and every payload (inclusive this one) must already be generated. + * The generated message is supplied via the data paramater. + * + * @param this calling encryption_payload_t + * @param data chunk contains the already generated message + * @return + * - SUCCESS, or + * - INVALID_STATE if transforms not set + */ + status_t (*build_signature) (encryption_payload_t *this, chunk_t data); + + /** + * @brief Verify the signature. + * + * Since the signature is built over the full message, we need + * this data to do the verification. The message data + * is supplied via the data argument. + * + * @param this calling encryption_payload_t + * @param data chunk contains the message + * @return + * - SUCCESS, or + * - FAILED if signature invalid, or + * - INVALID_STATE if transforms not set + */ + status_t (*verify_signature) (encryption_payload_t *this, chunk_t data); + + /** + * @brief Destroys an encryption_payload_t object. + * + * @param this encryption_payload_t object to destroy + */ + void (*destroy) (encryption_payload_t *this); +}; + +/** + * @brief Creates an empty encryption_payload_t object. + * + * @return encryption_payload_t object + * + * @ingroup payloads + */ +encryption_payload_t *encryption_payload_create(void); + + +#endif /*ENCRYPTION_PAYLOAD_H_*/ diff --git a/src/charon/encoding/payloads/id_payload.c b/src/charon/encoding/payloads/id_payload.c new file mode 100644 index 000000000..6a8d7738d --- /dev/null +++ b/src/charon/encoding/payloads/id_payload.c @@ -0,0 +1,320 @@ +/** + * @file id_payload.h + * + * @brief Interface of id_payload_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 + +#include "id_payload.h" + +#include + +typedef struct private_id_payload_t private_id_payload_t; + +/** + * Private data of an id_payload_t object. + * + */ +struct private_id_payload_t { + /** + * Public id_payload_t interface. + */ + id_payload_t public; + + /** + * TRUE if this ID payload is of type IDi, FALSE for IDr. + */ + bool is_initiator; + + /** + * Next payload type. + */ + u_int8_t next_payload; + + /** + * Critical flag. + */ + bool critical; + + /** + * Length of this payload. + */ + u_int16_t payload_length; + + /** + * Type of the ID Data. + */ + u_int8_t id_type; + + /** + * The contained id data value. + */ + chunk_t id_data; +}; + +/** + * Encoding rules to parse or generate a ID payload + * + * The defined offsets are the positions in a object of type + * private_id_payload_t. + * + */ +encoding_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 }, + /* 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 }, + /* some id data bytes, length is defined in PAYLOAD_LENGTH */ + { ID_DATA, offsetof(private_id_payload_t, id_data) } +}; + +/* + 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! Next Payload !C! RESERVED ! Payload Length ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! ID Type ! RESERVED | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! ! + ~ Identification Data ~ + ! ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ + +/** + * Implementation of payload_t.verify. + */ +static status_t verify(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))) + { + /* reserved IDs */ + 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) +{ + *rules = id_payload_encodings; + *rule_count = sizeof(id_payload_encodings) / sizeof(encoding_rule_t); +} + +/** + * Implementation of payload_t.get_type. + */ +static payload_type_t get_payload_type(private_id_payload_t *this) +{ + if (this->is_initiator) + { + return ID_INITIATOR; + } + else + { + return ID_RESPONDER; + } +} + +/** + * Implementation of payload_t.get_next_type. + */ +static payload_type_t get_next_type(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) +{ + this->next_payload = type; +} + +/** + * Implementation of payload_t.get_length. + */ +static size_t get_length(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) +{ + return (this->id_type); +} + +/** + * Implementation of id_payload_t.set_data. + */ +static void set_data (private_id_payload_t *this, chunk_t data) +{ + 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_initiator. + */ +static bool get_initiator (private_id_payload_t *this) +{ + return (this->is_initiator); +} + +/** + * Implementation of id_payload_t.set_initiator. + */ +static void set_initiator (private_id_payload_t *this,bool is_initiator) +{ + this->is_initiator = is_initiator; +} + +/** + * 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); +} + +/* + * Described in header. + */ +id_payload_t *id_payload_create(bool is_initiator) +{ + 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_initiator = (bool (*) (id_payload_t *)) get_initiator; + this->public.set_initiator = (void (*) (id_payload_t *,bool)) set_initiator; + 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_INITIALIZER; + this->is_initiator = is_initiator; + + return (&(this->public)); +} + +/* + * Described in header. + */ +id_payload_t *id_payload_create_from_identification(bool is_initiator,identification_t *identification) +{ + id_payload_t *this= id_payload_create(is_initiator); + this->set_data(this,identification->get_encoding(identification)); + this->set_id_type(this,identification->get_type(identification)); + return this; +} diff --git a/src/charon/encoding/payloads/id_payload.h b/src/charon/encoding/payloads/id_payload.h new file mode 100644 index 000000000..c35b44d59 --- /dev/null +++ b/src/charon/encoding/payloads/id_payload.h @@ -0,0 +1,172 @@ +/** + * @file id_payload.h + * + * @brief Interface of id_payload_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + + +#ifndef ID_PAYLOAD_H_ +#define ID_PAYLOAD_H_ + +#include +#include +#include + +/** + * Length of a id payload without the data in bytes. + * + * @ingroup payloads + */ +#define ID_PAYLOAD_HEADER_LENGTH 8 + + +typedef struct id_payload_t id_payload_t; + +/** + * Object representing an IKEv2 ID payload. + * + * The ID payload format is described in RFC section 3.5. + * + * @b Constructors: + * - id_payload_create_from_identification() + * - id_payload_create() + * + * @ingroup payloads + */ +struct id_payload_t { + /** + * The payload_t interface. + */ + payload_t payload_interface; + + /** + * @brief Set the ID type. + * + * @param this calling id_payload_t object + * @param type Type of ID + */ + void (*set_id_type) (id_payload_t *this, id_type_t type); + + /** + * @brief Get the ID type. + * + * @param this calling id_payload_t object + * @return type of the ID + */ + id_type_t (*get_id_type) (id_payload_t *this); + + /** + * @brief Set the ID data. + * + * Data are getting cloned. + * + * @param this calling id_payload_t object + * @param data ID data as chunk_t + */ + void (*set_data) (id_payload_t *this, chunk_t data); + + /** + * @brief Get the ID data. + * + * Returned data are a copy of the internal one + * + * @param this calling id_payload_t object + * @return ID data as chunk_t + */ + chunk_t (*get_data_clone) (id_payload_t *this); + + /** + * @brief Get the ID data. + * + * Returned data are NOT copied. + * + * @param this calling id_payload_t object + * @return ID data as chunk_t + */ + chunk_t (*get_data) (id_payload_t *this); + + /** + * @brief Creates an identification object of this id payload. + * + * Returned object has to get destroyed by the caller. + * + * @param this calling id_payload_t object + * @return identification_t object + */ + identification_t *(*get_identification) (id_payload_t *this); + + /** + * @brief Get the type of ID payload (IDi or IDr). + * + * @param this calling id_payload_t object + * @return + * - TRUE if this payload is of type IDi + * - FALSE if this payload is of type IDr + * + */ + bool (*get_initiator) (id_payload_t *this); + + /** + * @brief Set the type of ID payload (IDi or IDr). + * + * @param this calling id_payload_t object + * @param is_initiator + * - TRUE if this payload is of type IDi + * - FALSE if this payload is of type IDr + * + */ + void (*set_initiator) (id_payload_t *this,bool is_initiator); + + /** + * @brief Destroys an id_payload_t object. + * + * @param this id_payload_t object to destroy + */ + void (*destroy) (id_payload_t *this); +}; + +/** + * @brief Creates an empty id_payload_t object. + * + * @param is_initiator + * - TRUE if this payload is of type IDi + * - FALSE if this payload is of type IDr + * + * @return id_payload_t object + * + * @ingroup payloads + */ +id_payload_t *id_payload_create(bool is_initiator); + +/** + * @brief Creates an id_payload_t from an existing identification_t object. + * + * @param is_initiator + * - TRUE if this payload is of type IDi + * - FALSE if this payload is of type IDr + * @param identification identification_t object + * @return id_payload_t object + * + * @ingroup payloads + */ +id_payload_t *id_payload_create_from_identification(bool is_initiator,identification_t *identification); + + + +#endif /* ID_PAYLOAD_H_ */ diff --git a/src/charon/encoding/payloads/ike_header.c b/src/charon/encoding/payloads/ike_header.c new file mode 100644 index 000000000..ad46d3d29 --- /dev/null +++ b/src/charon/encoding/payloads/ike_header.c @@ -0,0 +1,408 @@ +/** + * @file ike_header.c + * + * @brief Implementation of ike_header_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/* offsetof macro */ +#include + +#include "ike_header.h" + +#include + + +typedef struct private_ike_header_t private_ike_header_t; + +/** + * Private data of an ike_header_t object. + * + */ +struct private_ike_header_t { + /** + * Public interface. + */ + ike_header_t public; + + /** + * SPI of the initiator. + */ + u_int64_t initiator_spi; + + /** + * SPI of the responder. + */ + u_int64_t responder_spi; + + /** + * Next payload type. + */ + u_int8_t next_payload; + /** + * IKE major version. + */ + u_int8_t maj_version; + + /** + * IKE minor version. + */ + u_int8_t min_version; + + /** + * Exchange type . + */ + u_int8_t exchange_type; + + /** + * Flags of the Message. + * + */ + struct { + /** + * Sender is initiator of the associated IKE_SA_INIT-Exchange. + */ + bool initiator; + + /** + * Is protocol supporting higher version? + */ + bool version; + + /** + * TRUE, if this is a response, FALSE if its a Request. + */ + bool response; + } flags; + + /** + * Associated Message-ID. + */ + u_int32_t message_id; + + /** + * Length of the whole IKEv2-Message (header and all payloads). + */ + u_int32_t length; +}; + +/** + * Mappings used to get strings for exchange_type_t. + */ +mapping_t exchange_type_m[] = { + {EXCHANGE_TYPE_UNDEFINED, "EXCHANGE_TYPE_UNDEFINED"}, + {IKE_SA_INIT, "IKE_SA_INIT"}, + {IKE_AUTH, "IKE_AUTH"}, + {CREATE_CHILD_SA, "CREATE_CHILD_SA"}, + {INFORMATIONAL, "INFORMATIONAL"} +}; + + +/** + * Encoding rules to parse or generate a IKEv2-Header. + * + * The defined offsets are the positions in a object of type + * ike_header_t. + * + */ +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) }, + /* 1 Byte next payload type, stored in the field 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) }, + /* 4 Bit minor version, stored in the field 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 }, + /* 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 }, + /* 4 Byte message id, stored in the field message_id */ + { U_INT_32, offsetof(private_ike_header_t, message_id) }, + /* 4 Byte length fied, stored in the field length */ + { HEADER_LENGTH, offsetof(private_ike_header_t, length) } +}; + + +/* 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! IKE_SA Initiator's SPI ! + ! ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! IKE_SA Responder's SPI ! + ! ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! Next Payload ! MjVer ! MnVer ! Exchange Type ! Flags ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! Message ID ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! Length ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ + + +/** + * Implementation of payload_t.verify. + */ +static status_t verify(private_ike_header_t *this) +{ + if ((this->exchange_type < IKE_SA_INIT) || (this->exchange_type > INFORMATIONAL)) + { + /* unsupported exchange type */ + return FAILED; + } + if (this->initiator_spi == 0) + { + /* initiator spi not set */ + return FAILED; + } + + /* verification of version is not done in here */ + + return SUCCESS; +} + +/** + * Implementation of payload_t.set_next_type. + */ +static void set_next_type(payload_t *this,payload_type_t type) +{ + ((private_ike_header_t *)this)->next_payload = type; +} +/** + * Implementation of ike_header_t.get_initiator_spi. + */ +static u_int64_t get_initiator_spi(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) +{ + 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) +{ + 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) +{ + 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) +{ + return this->maj_version; +} + +/** + * Implementation of ike_header_t.get_min_version. + */ +static u_int8_t get_min_version(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) +{ + return this->flags.response; +} + +/** + * Implementation of ike_header_t.set_response_flag. + */ +static void set_response_flag(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) +{ + return this->flags.version; +} + +/** + * Implementation of ike_header_t.get_initiator_flag. + */ +static bool get_initiator_flag(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) +{ + this->flags.initiator = initiator; +} + +/** + * Implementation of ike_header_t.get_exchange_type. + */ +static u_int8_t get_exchange_type(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) +{ + 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) +{ + 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) +{ + this->message_id = message_id; +} + +/** + * Implementation of ike_header_t.destroy and payload_t.destroy. + */ +static void destroy(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; +} diff --git a/src/charon/encoding/payloads/ike_header.h b/src/charon/encoding/payloads/ike_header.h new file mode 100644 index 000000000..bc4c40a5b --- /dev/null +++ b/src/charon/encoding/payloads/ike_header.h @@ -0,0 +1,261 @@ +/** + * @file ike_header.h + * + * @brief Interface of ike_header_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef IKE_HEADER_H_ +#define IKE_HEADER_H_ + +#include +#include + +/** + * Major Version of IKEv2. + * + * @ingroup payloads + */ +#define IKE_MAJOR_VERSION 2 + +/** + * Minor Version of IKEv2. + * + * @ingroup payloads + */ +#define IKE_MINOR_VERSION 0 + +/** + * Flag in IKEv2-Header. Always 0. + * + * @ingroup payloads + */ +#define HIGHER_VERSION_SUPPORTED_FLAG 0 + +/** + * Length of IKE Header in Bytes. + * + * @ingroup payloads + */ +#define IKE_HEADER_LENGTH 28 + +typedef enum exchange_type_t exchange_type_t; + +/** + * @brief Different types of IKE-Exchanges. + * + * See Draft for different types. + * + * @ingroup payloads + */ +enum exchange_type_t{ + + /** + * EXCHANGE_TYPE_UNDEFINED. In private space, since not a official message type. + */ + EXCHANGE_TYPE_UNDEFINED = 240, + + /** + * IKE_SA_INIT. + */ + IKE_SA_INIT = 34, + + /** + * IKE_AUTH. + */ + IKE_AUTH = 35, + + /** + * CREATE_CHILD_SA. + */ + CREATE_CHILD_SA = 36, + + /** + * INFORMATIONAL. + */ + INFORMATIONAL = 37 +}; + +/** + * string mappings for exchange_type_t + * + * @ingroup payloads + */ +extern mapping_t exchange_type_m[]; + + +typedef struct ike_header_t ike_header_t; + +/** + * @brief An object of this type represents an IKEv2 header and is used to + * generate and parse IKEv2 headers. + * + * The header format of an IKEv2-Message is compatible to the + * ISAKMP-Header format to allow implementations supporting + * both versions of the IKE-protocol. + * + * @b Constructors: + * - ike_header_create() + * + * @ingroup payloads + */ +struct ike_header_t { + /** + * The payload_t interface. + */ + payload_t payload_interface; + + /** + * @brief Get the initiator spi. + * + * @param this ike_header_t object + * @return initiator_spi + */ + u_int64_t (*get_initiator_spi) (ike_header_t *this); + + /** + * @brief Set the initiator spi. + * + * @param this ike_header_t object + * @param initiator_spi initiator_spi + */ + void (*set_initiator_spi) (ike_header_t *this, u_int64_t initiator_spi); + + /** + * @brief Get the responder spi. + * + * @param this ike_header_t object + * @return responder_spi + */ + u_int64_t (*get_responder_spi) (ike_header_t *this); + + /** + * @brief Set the responder spi. + * + * @param this ike_header_t object + * @param responder_spi responder_spi + */ + void (*set_responder_spi) (ike_header_t *this, u_int64_t responder_spi); + + /** + * @brief Get the major version. + * + * @param this ike_header_t object + * @return major version + */ + u_int8_t (*get_maj_version) (ike_header_t *this); + + /** + * @brief Get the minor version. + * + * @param this ike_header_t object + * @return minor version + */ + u_int8_t (*get_min_version) (ike_header_t *this); + + /** + * @brief Get the response flag. + * + * @param this ike_header_t object + * @return response flag + */ + bool (*get_response_flag) (ike_header_t *this); + + /** + * @brief Set the response flag- + * + * @param this ike_header_t object + * @param response response flag + * + */ + void (*set_response_flag) (ike_header_t *this, bool response); + /** + * @brief Get "higher version supported"-flag. + * + * @param this ike_header_t object + * @return version flag + */ + bool (*get_version_flag) (ike_header_t *this); + + /** + * @brief Get the initiator flag. + * + * @param this ike_header_t object + * @return initiator flag + */ + bool (*get_initiator_flag) (ike_header_t *this); + + /** + * @brief Set the initiator flag. + * + * @param this ike_header_t object + * @param initiator initiator flag + * + */ + void (*set_initiator_flag) (ike_header_t *this, bool initiator); + + /** + * @brief Get the exchange type. + * + * @param this ike_header_t object + * @return exchange type + */ + u_int8_t (*get_exchange_type) (ike_header_t *this); + + /** + * @brief Set the exchange type. + * + * @param this ike_header_t object + * @param exchange_type exchange type + */ + void (*set_exchange_type) (ike_header_t *this, u_int8_t exchange_type); + + /** + * @brief Get the message id. + * + * @param this ike_header_t object + * @return message id + */ + u_int32_t (*get_message_id) (ike_header_t *this); + + /** + * @brief Set the message id. + * + * @param this ike_header_t object + * @param initiator_spi message id + */ + void (*set_message_id) (ike_header_t *this, u_int32_t message_id); + + /** + * @brief Destroys a ike_header_t object. + * + * @param this ike_header_t object to destroy + */ + void (*destroy) (ike_header_t *this); +}; + +/** + * @brief Create an ike_header_t object + * + * @return ike_header_t object + * + * @ingroup payloads + */ +ike_header_t *ike_header_create(void); + +#endif /*IKE_HEADER_H_*/ diff --git a/src/charon/encoding/payloads/ke_payload.c b/src/charon/encoding/payloads/ke_payload.c new file mode 100644 index 000000000..0c92e033d --- /dev/null +++ b/src/charon/encoding/payloads/ke_payload.c @@ -0,0 +1,276 @@ +/** + * @file ke_payload.c + * + * @brief Implementation of ke_payload_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 + +#include "ke_payload.h" + +#include + + +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. + */ + ke_payload_t public; + + /** + * Next payload type. + */ + u_int8_t next_payload; + + /** + * Critical flag. + */ + bool critical; + + /** + * Length of this payload. + */ + u_int16_t payload_length; + + /** + * DH Group Number. + */ + diffie_hellman_group_t dh_group_number; + + /** + * Key Exchange Data of this KE payload. + */ + chunk_t key_exchange_data; + + /** + * @brief Computes the length of this payload. + * + * @param this calling private_ke_payload_t object + */ + void (*compute_length) (private_ke_payload_t *this); +}; + +/** + * Encoding rules to parse or generate a IKEv2-KE Payload. + * + * The defined offsets are the positions in a object of type + * private_ke_payload_t. + * + */ +encoding_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) }, + /* 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 }, + /* Length of the whole payload*/ + { 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 }, + /* Key Exchange Data is from variable size */ + { KEY_EXCHANGE_DATA, offsetof(private_ke_payload_t, key_exchange_data)} +}; + +/* + 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! Next Payload !C! RESERVED ! Payload Length ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! DH Group # ! RESERVED ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! ! + ~ Key Exchange Data ~ + ! ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ + +/** + * Implementation of payload_t.verify. + */ +static status_t verify(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) +{ + *rules = ke_payload_encodings; + *rule_count = sizeof(ke_payload_encodings) / sizeof(encoding_rule_t); +} + +/** + * Implementation of payload_t.get_type. + */ +static payload_type_t get_type(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) +{ + 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) +{ + this->next_payload = type; +} + +/** + * Implementation of payload_t.get_length. + */ +static size_t get_length(private_ke_payload_t *this) +{ + this->compute_length(this); + return this->payload_length; +} + +/** + * Implementation of private_ke_payload_t.compute_length. + */ +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 ke_payload_t.get_key_exchange_data. + */ +static chunk_t get_key_exchange_data(private_ke_payload_t *this) +{ + 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.ptr = clalloc(key_exchange_data.ptr,key_exchange_data.len); + + this->key_exchange_data.len = key_exchange_data.len; + this->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) +{ + 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) +{ + this->dh_group_number = dh_group_number; +} + +/* + * Described in header + */ +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; + + /* private functions */ + this->compute_length = compute_length; + + /* 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.ptr = NULL; + this->key_exchange_data.len = 0; + this->dh_group_number = 0; + + return (&(this->public)); +} diff --git a/src/charon/encoding/payloads/ke_payload.h b/src/charon/encoding/payloads/ke_payload.h new file mode 100644 index 000000000..9490bef89 --- /dev/null +++ b/src/charon/encoding/payloads/ke_payload.h @@ -0,0 +1,110 @@ +/** + * @file ke_payload.h + * + * @brief Interface of ke_payload_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef KE_PAYLOAD_H_ +#define KE_PAYLOAD_H_ + +#include +#include +#include +#include +/** + * KE payload length in bytes without any key exchange data. + * + * @ingroup payloads + */ +#define KE_PAYLOAD_HEADER_LENGTH 8 + + +typedef struct ke_payload_t ke_payload_t; + +/** + * @brief Class representing an IKEv2-KE Payload. + * + * The KE Payload format is described in RFC section 3.4. + * + * @b Constructors: + * - ke_payload_create() + * + * @ingroup payloads + */ +struct ke_payload_t { + /** + * The payload_t interface. + */ + payload_t payload_interface; + + /** + * @brief Returns the currently set key exchange data of this KE payload. + * + * @warning Returned data are not copied. + * + * @param this calling ke_payload_t object + * @return chunk_t pointing to the value + */ + chunk_t (*get_key_exchange_data) (ke_payload_t *this); + + /** + * @brief Sets the key exchange data of this KE payload. + * + * @warning Value is getting copied. + * + * @param this calling ke_payload_t object + * @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); + + /** + * @brief Gets the Diffie-Hellman Group Number of this KE payload. + * + * @param this calling ke_payload_t object + * @return DH Group Number of this payload + */ + diffie_hellman_group_t (*get_dh_group_number) (ke_payload_t *this); + + /** + * @brief Sets the Diffie-Hellman Group Number of this KE payload. + * + * @param this calling ke_payload_t object + * @param dh_group_number DH Group to set + */ + void (*set_dh_group_number) (ke_payload_t *this, diffie_hellman_group_t dh_group_number); + + /** + * @brief Destroys an ke_payload_t object. + * + * @param this ke_payload_t object to destroy + */ + void (*destroy) (ke_payload_t *this); +}; + +/** + * @brief Creates an empty ke_payload_t object + * + * @return ke_payload_t object + * + * @ingroup payloads + */ +ke_payload_t *ke_payload_create(void); + + +#endif /*KE_PAYLOAD_H_*/ diff --git a/src/charon/encoding/payloads/nonce_payload.c b/src/charon/encoding/payloads/nonce_payload.c new file mode 100644 index 000000000..a7528fbfb --- /dev/null +++ b/src/charon/encoding/payloads/nonce_payload.c @@ -0,0 +1,241 @@ +/** + * @file nonce_payload.h + * + * @brief Implementation of nonce_payload_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/* offsetof macro */ +#include + +#include "nonce_payload.h" + +#include + + +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. + */ + nonce_payload_t public; + + /** + * Next payload type. + */ + u_int8_t next_payload; + + /** + * Critical flag. + */ + bool critical; + + /** + * Length of this payload. + */ + u_int16_t payload_length; + + /** + * The contained nonce value. + */ + chunk_t nonce; + + /** + * @brief Computes the length of this payload. + * + * @param this calling private_nonce_payload_t object + */ + void (*compute_length) (private_nonce_payload_t *this); +}; + +/** + * Encoding rules to parse or generate a nonce payload + * + * 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) }, + /* 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 }, + /* Length of the whole nonce payload*/ + { PAYLOAD_LENGTH, offsetof(private_nonce_payload_t, payload_length) }, + /* some nonce bytes, lenth is defined in PAYLOAD_LENGTH */ + { NONCE_DATA, offsetof(private_nonce_payload_t, nonce) } +}; + +/* 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! Next Payload !C! RESERVED ! Payload Length ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! ! + ~ Nonce Data ~ + ! ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ + +/** + * Implementation of payload_t.verify. + */ +static status_t verify(private_nonce_payload_t *this) +{ + 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) +{ + *rules = nonce_payload_encodings; + *rule_count = sizeof(nonce_payload_encodings) / sizeof(encoding_rule_t); +} + +/** + * Implementation of payload_t.get_type. + */ +static payload_type_t get_type(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) +{ + 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) +{ + this->next_payload = type; +} + +/** + * Implementation of payload_t.get_length. + */ +static size_t get_length(private_nonce_payload_t *this) +{ + this->compute_length(this); + return this->payload_length; +} + +/** + * Implementation of private_id_payload_t.compute_length. + */ +static void compute_length(private_nonce_payload_t *this) +{ + this->payload_length = NONCE_PAYLOAD_HEADER_LENGTH + this->nonce.len; +} + +/** + * Implementation of payload_t.destroy and nonce_payload_t.destroy. + */ +static void destroy(private_nonce_payload_t *this) +{ + if (this->nonce.ptr != NULL) + { + free(this->nonce.ptr); + } + + free(this); +} + +/* + * Described in header + */ +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 functions */ + this->compute_length = compute_length; + + /* 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)); +} + + diff --git a/src/charon/encoding/payloads/nonce_payload.h b/src/charon/encoding/payloads/nonce_payload.h new file mode 100644 index 000000000..e875fb263 --- /dev/null +++ b/src/charon/encoding/payloads/nonce_payload.h @@ -0,0 +1,89 @@ +/** + * @file nonce_payload.h + * + * @brief Interface of nonce_payload_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef NONCE_PAYLOAD_H_ +#define NONCE_PAYLOAD_H_ + +#include +#include + +/** + * Length of a nonce payload without a nonce in bytes. + * + * @ingroup payloads + */ +#define NONCE_PAYLOAD_HEADER_LENGTH 4 + +typedef struct nonce_payload_t nonce_payload_t; + +/** + * Object representing an IKEv2 Nonce payload. + * + * The Nonce payload format is described in RFC section 3.3. + * + * @b Constructors: + * - nonce_payload_create() + * + * @ingroup payloads + */ +struct nonce_payload_t { + /** + * The payload_t interface. + */ + payload_t payload_interface; + + /** + * @brief Set the nonce value. + * + * @param this calling nonce_payload_t object + * @param nonce chunk containing the nonce, will be cloned + */ + void (*set_nonce) (nonce_payload_t *this, chunk_t nonce); + + /** + * @brief Get the nonce value. + * + * @param this calling nonce_payload_t object + * @return a chunk containing the cloned nonce + */ + chunk_t (*get_nonce) (nonce_payload_t *this); + + /** + * @brief Destroys an nonce_payload_t object. + * + * @param this nonce_payload_t object to destroy + */ + void (*destroy) (nonce_payload_t *this); +}; + +/** + * @brief Creates an empty nonce_payload_t object + * + * @return nonce_payload_t object + * + * @ingroup payloads + */ + +nonce_payload_t *nonce_payload_create(void); + + +#endif /*NONCE_PAYLOAD_H_*/ diff --git a/src/charon/encoding/payloads/notify_payload.c b/src/charon/encoding/payloads/notify_payload.c new file mode 100644 index 000000000..43d0c5322 --- /dev/null +++ b/src/charon/encoding/payloads/notify_payload.c @@ -0,0 +1,441 @@ +/** + * @file notify_payload.c + * + * @brief Implementation of notify_payload_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 + +#include "notify_payload.h" + +#include +#include + +/** + * String mappings for notify_message_type_t. + */ +mapping_t notify_message_type_m[] = { + {UNSUPPORTED_CRITICAL_PAYLOAD, "UNSUPPORTED_CRITICAL_PAYLOAD"}, + {INVALID_IKE_SPI, "INVALID_IKE_SPI"}, + {INVALID_MAJOR_VERSION, "INVALID_MAJOR_VERSION"}, + {INVALID_SYNTAX, "INVALID_SYNTAX"}, + {INVALID_MESSAGE_ID, "INVALID_MESSAGE_ID"}, + {INVALID_SPI, "INVALID_SPI"}, + {NO_PROPOSAL_CHOSEN, "NO_PROPOSAL_CHOSEN"}, + {INVALID_KE_PAYLOAD, "INVALID_KE_PAYLOAD"}, + {AUTHENTICATION_FAILED, "AUTHENTICATION_FAILED"}, + {SINGLE_PAIR_REQUIRED, "SINGLE_PAIR_REQUIRED"}, + {NO_ADDITIONAL_SAS, "NO_ADDITIONAL_SAS"}, + {INTERNAL_ADDRESS_FAILURE, "INTERNAL_ADDRESS_FAILURE"}, + {FAILED_CP_REQUIRED, "FAILED_CP_REQUIRED"}, + {TS_UACCEPTABLE, "TS_UACCEPTABLE"}, + {INVALID_SELECTORS, "INVALID_SELECTORS"}, + {INITIAL_CONTACT, "INITIAL_CONTACT"}, + {SET_WINDOW_SIZE, "SET_WINDOW_SIZE"}, + {MAPPING_END, NULL} +}; + +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. + */ + notify_payload_t public; + + /** + * Next payload type. + */ + u_int8_t next_payload; + + /** + * Critical flag. + */ + bool critical; + + /** + * Length of this payload. + */ + u_int16_t payload_length; + + /** + * Protocol id. + */ + u_int8_t protocol_id; + + /** + * Spi size. + */ + u_int8_t spi_size; + + /** + * Notify message type. + */ + u_int16_t notify_message_type; + + /** + * Security parameter index (spi). + */ + chunk_t spi; + + /** + * Notification data. + */ + chunk_t notification_data; + + /** + * Assigned logger + */ + logger_t *logger; + + /** + * @brief Computes the length of this payload. + * + * @param this calling private_ke_payload_t object + */ + void (*compute_length) (private_notify_payload_t *this); +}; + +/** + * Encoding rules to parse or generate a IKEv2-Notify Payload. + * + * The defined offsets are the positions in a object of type + * private_notify_payload_t. + * + */ +encoding_rule_t notify_payload_encodings[] = { + /* 1 Byte next payload type, stored in the field next_payload */ + { U_INT_8, offsetof(private_notify_payload_t, next_payload) }, + /* 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 }, + /* Length of the whole payload*/ + { PAYLOAD_LENGTH, offsetof(private_notify_payload_t, payload_length) }, + /* Protocol ID as 8 bit field*/ + { U_INT_8, offsetof(private_notify_payload_t, protocol_id) }, + /* 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_message_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) } +}; + +/* + 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! Next Payload !C! RESERVED ! Payload Length ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! Protocol ID ! SPI Size ! Notify Message Type ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! ! + ~ Security Parameter Index (SPI) ~ + ! ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! ! + ~ Notification Data ~ + ! ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ + +/** + * Implementation of payload_t.verify. + */ +static status_t verify(private_notify_payload_t *this) +{ + if (this->protocol_id > 3) + { + /* reserved for future use */ + return FAILED; + } + + /* TODO: Check all kinds of notify */ + + if (this->notify_message_type == INVALID_KE_PAYLOAD) + { + /* check notification data */ + diffie_hellman_group_t dh_group; + if (this->notification_data.len != 2) + { + return FAILED; + } + dh_group = ntohs(*((u_int16_t*)this->notification_data.ptr)); + switch (dh_group) + { + case MODP_768_BIT: + case MODP_1024_BIT: + case MODP_1536_BIT: + case MODP_2048_BIT: + case MODP_3072_BIT: + case MODP_4096_BIT: + case MODP_6144_BIT: + case MODP_8192_BIT: + break; + default: + this->logger->log(this->logger, ERROR, "Bad DH group (%d)", dh_group); + return FAILED; + } + } + 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) +{ + *rules = notify_payload_encodings; + *rule_count = sizeof(notify_payload_encodings) / sizeof(encoding_rule_t); +} + +/** + * Implementation of payload_t.get_type. + */ +static payload_type_t get_type(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) +{ + 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) +{ + this->next_payload = type; +} + +/** + * Implementation of payload_t.get_length. + */ +static size_t get_length(private_notify_payload_t *this) +{ + this->compute_length(this); + return this->payload_length; +} + +/** + * Implementation of private_notify_payload_t.compute_length. + */ +static void compute_length (private_notify_payload_t *this) +{ + size_t length = NOTIFY_PAYLOAD_HEADER_LENGTH; + if (this->notification_data.ptr != NULL) + { + length += this->notification_data.len; + } + if (this->spi.ptr != NULL) + { + length += this->spi.len; + } + + this->payload_length = length; + +} + +/** + * Implementation of notify_payload_t.get_protocol_id. + */ +static u_int8_t get_protocol_id(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) +{ + this->protocol_id = protocol_id; +} + +/** + * Implementation of notify_payload_t.get_notify_message_type. + */ +static u_int16_t get_notify_message_type(private_notify_payload_t *this) +{ + return this->notify_message_type; +} + +/** + * Implementation of notify_payload_t.set_notify_message_type. + */ +static void set_notify_message_type(private_notify_payload_t *this, u_int16_t notify_message_type) +{ + this->notify_message_type = notify_message_type; +} + +/** + * Implementation of notify_payload_t.get_spi. + */ +static chunk_t get_spi(private_notify_payload_t *this) +{ + return (this->spi); +} + +/** + * Implementation of notify_payload_t.set_spi. + */ +static void set_spi(private_notify_payload_t *this, chunk_t spi) +{ + /* destroy existing data first */ + if (this->spi.ptr != NULL) + { + /* free existing value */ + free(this->spi.ptr); + this->spi.ptr = NULL; + this->spi.len = 0; + + } + + this->spi.ptr = clalloc(spi.ptr,spi.len); + + this->spi.len = spi.len; + this->spi_size = spi.len; + this->compute_length(this); + +} + +/** + * Implementation of notify_payload_t.get_notification_data. + */ +static chunk_t get_notification_data(private_notify_payload_t *this) +{ + 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) +{ + /* destroy existing data first */ + if (this->notification_data.ptr != NULL) + { + /* free existing value */ + free(this->notification_data.ptr); + this->notification_data.ptr = NULL; + this->notification_data.len = 0; + + } + + this->notification_data.ptr = clalloc(notification_data.ptr,notification_data.len); + this->notification_data.len = notification_data.len; + this->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) +{ + if (this->notification_data.ptr != NULL) + { + free(this->notification_data.ptr); + } + if (this->spi.ptr != NULL) + { + free(this->spi.ptr); + } + + free(this); + return SUCCESS; +} + +/* + * Described in header + */ +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_message_type = (u_int16_t (*) (notify_payload_t *)) get_notify_message_type; + this->public.set_notify_message_type = (void (*) (notify_payload_t *,u_int16_t)) set_notify_message_type; + this->public.get_spi = (chunk_t (*) (notify_payload_t *)) get_spi; + this->public.set_spi = (void (*) (notify_payload_t *,chunk_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; + + /* private functions */ + this->compute_length = compute_length; + + /* 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_message_type = 0; + this->spi.ptr = NULL; + this->spi.len = 0; + this->spi_size = 0; + this->notification_data.ptr = NULL; + this->notification_data.len = 0; + this->logger = logger_manager->get_logger(logger_manager, PAYLOAD); + + return (&(this->public)); +} + +/* + * Described in header. + */ +notify_payload_t *notify_payload_create_from_protocol_and_type(protocol_id_t protocol_id, notify_message_type_t notify_message_type) +{ + notify_payload_t *notify = notify_payload_create(); + + notify->set_notify_message_type(notify,notify_message_type); + notify->set_protocol_id(notify,protocol_id); + + return notify; +} diff --git a/src/charon/encoding/payloads/notify_payload.h b/src/charon/encoding/payloads/notify_payload.h new file mode 100644 index 000000000..4c9383e49 --- /dev/null +++ b/src/charon/encoding/payloads/notify_payload.h @@ -0,0 +1,200 @@ +/** + * @file notify_payload.h + * + * @brief Interface of notify_payload_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + + +#ifndef NOTIFY_PAYLOAD_H_ +#define NOTIFY_PAYLOAD_H_ + +#include +#include +#include +#include + +/** + * Notify payload length in bytes without any spi and notification data. + * + * @ingroup payloads + */ +#define NOTIFY_PAYLOAD_HEADER_LENGTH 8 + +typedef enum notify_message_type_t notify_message_type_t; + + +/** + * @brief Notify message types. + * + * See IKEv2 RFC 3.10.1. + * + * @ingroup payloads + */ +enum notify_message_type_t { + UNSUPPORTED_CRITICAL_PAYLOAD = 1, + INVALID_IKE_SPI = 4, + INVALID_MAJOR_VERSION = 5, + INVALID_SYNTAX = 7, + INVALID_MESSAGE_ID = 9, + INVALID_SPI = 11, + NO_PROPOSAL_CHOSEN = 14, + INVALID_KE_PAYLOAD = 17, + AUTHENTICATION_FAILED = 24, + SINGLE_PAIR_REQUIRED = 34, + NO_ADDITIONAL_SAS = 35, + INTERNAL_ADDRESS_FAILURE = 36, + FAILED_CP_REQUIRED = 37, + TS_UACCEPTABLE = 38, + INVALID_SELECTORS = 39, + + INITIAL_CONTACT = 16384, + SET_WINDOW_SIZE = 16385 +}; + +/** + * String mappings for notify_message_type_t. + * + * @ingroup payloads + */ +extern mapping_t notify_message_type_m[]; + + +typedef struct notify_payload_t notify_payload_t; + +/** + * @brief Class representing an IKEv2-Notify Payload. + * + * The Notify Payload format is described in Draft section 3.10. + * + * @b Constructors: + * - notify_payload_create() + * - notify_payload_create_from_protocol_and_type() + * + * @todo Build specified constructor/getter for notify's + * + * @ingroup payloads + */ +struct notify_payload_t { + /** + * The payload_t interface. + */ + payload_t payload_interface; + + /** + * @brief Gets the protocol id of this payload. + * + * @param this calling notify_payload_t object + * @return protocol id of this payload + */ + u_int8_t (*get_protocol_id) (notify_payload_t *this); + + /** + * @brief Sets the protocol id of this payload. + * + * @param this calling notify_payload_t object + * @param protocol_id protocol id to set + */ + void (*set_protocol_id) (notify_payload_t *this, u_int8_t protocol_id); + + /** + * @brief Gets the notify message type of this payload. + * + * @param this calling notify_payload_t object + * @return notify message type of this payload + */ + u_int16_t (*get_notify_message_type) (notify_payload_t *this); + + /** + * @brief Sets notify message type of this payload. + * + * @param this calling notify_payload_t object + * @param notify_message_type notify message type to set + */ + void (*set_notify_message_type) (notify_payload_t *this, u_int16_t notify_message_type); + + /** + * @brief Returns the currently set spi of this payload. + * + * @warning Returned data are not copied. + * + * @param this calling notify_payload_t object + * @return chunk_t pointing to the value + */ + chunk_t (*get_spi) (notify_payload_t *this); + + /** + * @brief Sets the spi of this payload. + * + * @warning Value is getting copied. + * + * @param this calling notify_payload_t object + * @param spi chunk_t pointing to the value to set + */ + void (*set_spi) (notify_payload_t *this, chunk_t spi); + + /** + * @brief Returns the currently set notification data of payload. + * + * @warning Returned data are not copied. + * + * @param this calling notify_payload_t object + * @return chunk_t pointing to the value + */ + chunk_t (*get_notification_data) (notify_payload_t *this); + + /** + * @brief Sets the notification data of this payload. + * + * @warning Value is getting copied. + * + * @param this calling notify_payload_t object + * @param notification_data chunk_t pointing to the value to set + */ + void (*set_notification_data) (notify_payload_t *this, chunk_t notification_data); + + /** + * @brief Destroys an notify_payload_t object. + * + * @param this notify_payload_t object to destroy + */ + void (*destroy) (notify_payload_t *this); +}; + +/** + * @brief Creates an empty notify_payload_t object + * + * @return created notify_payload_t object + * + * @ingroup payloads + */ +notify_payload_t *notify_payload_create(void); + +/** + * @brief Creates an notify_payload_t object of specific type for specific protocol id. + * + * @param protocol_id protocol id (IKE, AH or ESP) + * @param notify_message_type notify type (see notify_message_type_t) + * @return notify_payload_t object + * + * @ingroup payloads + */ +notify_payload_t *notify_payload_create_from_protocol_and_type(protocol_id_t protocol_id, notify_message_type_t notify_message_type); + + +#endif /*NOTIFY_PAYLOAD_H_*/ diff --git a/src/charon/encoding/payloads/payload.c b/src/charon/encoding/payloads/payload.c new file mode 100644 index 000000000..b89e80a53 --- /dev/null +++ b/src/charon/encoding/payloads/payload.c @@ -0,0 +1,131 @@ +/** + * @file payload.c + * + * @brief Generic constructor to the payload_t interface. + * + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 "payload.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * build the mappings for payload_type_t + */ +mapping_t payload_type_m[] = { + {NO_PAYLOAD, "NO_PAYLOAD"}, + {SECURITY_ASSOCIATION, "SECURITY_ASSOCIATION"}, + {KEY_EXCHANGE, "KEY_EXCHANGE"}, + {ID_INITIATOR, "ID_INITIATOR"}, + {ID_RESPONDER, "ID_RESPONDER"}, + {CERTIFICATE, "CERTIFICATE"}, + {CERTIFICATE_REQUEST, "CERTIFICATE_REQUEST"}, + {AUTHENTICATION, "AUTHENTICATION"}, + {NONCE, "NONCE"}, + {NOTIFY, "NOTIFY"}, + {DELETE, "DELETE"}, + {VENDOR_ID, "VENDOR_ID"}, + {TRAFFIC_SELECTOR_INITIATOR, "TRAFFIC_SELECTOR_INITIATOR"}, + {TRAFFIC_SELECTOR_RESPONDER, "TRAFFIC_SELECTOR_RESPONDER"}, + {ENCRYPTED, "ENCRYPTED"}, + {CONFIGURATION, "CONFIGURATION"}, + {EXTENSIBLE_AUTHENTICATION, "EXTENSIBLE_AUTHENTICATION"}, + {HEADER, "HEADER"}, + {PROPOSAL_SUBSTRUCTURE, "PROPOSAL_SUBSTRUCTURE"}, + {TRANSFORM_SUBSTRUCTURE, "TRANSFORM_SUBSTRUCTURE"}, + {TRANSFORM_ATTRIBUTE, "TRANSFORM_ATTRIBUTE"}, + {TRAFFIC_SELECTOR_SUBSTRUCTURE, "TRAFFIC_SELECTOR_SUBSTRUCTURE"}, + {CONFIGURATION_ATTRIBUTE,"CONFIGURATION_ATTRIBUTE"}, + {UNKNOWN_PAYLOAD,"UNKNOWN_PAYLOAD"}, + {MAPPING_END, NULL} +}; + +/* + * see header + */ +payload_t *payload_create(payload_type_t type) +{ + switch (type) + { + case HEADER: + return (payload_t*)ike_header_create(); + case SECURITY_ASSOCIATION: + return (payload_t*)sa_payload_create(); + case PROPOSAL_SUBSTRUCTURE: + return (payload_t*)proposal_substructure_create(); + case TRANSFORM_SUBSTRUCTURE: + return (payload_t*)transform_substructure_create(); + case TRANSFORM_ATTRIBUTE: + return (payload_t*)transform_attribute_create(); + case NONCE: + return (payload_t*)nonce_payload_create(); + case ID_INITIATOR: + return (payload_t*)id_payload_create(TRUE); + case ID_RESPONDER: + return (payload_t*)id_payload_create(FALSE); + case AUTHENTICATION: + return (payload_t*)auth_payload_create(); + case CERTIFICATE: + return (payload_t*)cert_payload_create(); + case CERTIFICATE_REQUEST: + return (payload_t*)certreq_payload_create(); + case TRAFFIC_SELECTOR_SUBSTRUCTURE: + return (payload_t*)traffic_selector_substructure_create(); + case TRAFFIC_SELECTOR_INITIATOR: + return (payload_t*)ts_payload_create(TRUE); + case TRAFFIC_SELECTOR_RESPONDER: + return (payload_t*)ts_payload_create(FALSE); + case KEY_EXCHANGE: + return (payload_t*)ke_payload_create(); + case NOTIFY: + return (payload_t*)notify_payload_create(); + case DELETE: + return (payload_t*)delete_payload_create(); + case VENDOR_ID: + return (payload_t*)vendor_id_payload_create(); + case CONFIGURATION: + return (payload_t*)cp_payload_create(); + case CONFIGURATION_ATTRIBUTE: + return (payload_t*)configuration_attribute_create(); + case EXTENSIBLE_AUTHENTICATION: + return (payload_t*)eap_payload_create(); + case ENCRYPTED: + return (payload_t*)encryption_payload_create(); + default: + return (payload_t*)unknown_payload_create(); + } +} + diff --git a/src/charon/encoding/payloads/payload.h b/src/charon/encoding/payloads/payload.h new file mode 100644 index 000000000..fc3457832 --- /dev/null +++ b/src/charon/encoding/payloads/payload.h @@ -0,0 +1,279 @@ +/** + * @file payload.h + * + * @brief Interface payload_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef PAYLOAD_H_ +#define PAYLOAD_H_ + +#include +#include +#include + + +typedef enum payload_type_t payload_type_t; + +/** + * @brief Payload-Types of a IKEv2-Message. + * + * Header and substructures are also defined as + * payload types with values from PRIVATE USE space. + * + * @ingroup payloads + */ +enum payload_type_t{ + + /** + * End of payload list in next_payload + */ + NO_PAYLOAD = 0, + + /** + * The security association (SA) payload containing proposals. + */ + SECURITY_ASSOCIATION = 33, + + /** + * The key exchange (KE) payload containing diffie-hellman values. + */ + KEY_EXCHANGE = 34, + + /** + * Identification for the original initiator (IDi). + */ + ID_INITIATOR = 35, + + /** + * Identification for the original responder (IDr). + */ + ID_RESPONDER = 36, + + /** + * Certificate payload with certificates (CERT). + */ + CERTIFICATE = 37, + + /** + * Certificate request payload (CERTREQ). + */ + CERTIFICATE_REQUEST = 38, + + /** + * Authentication payload contains auth data (AUTH). + */ + AUTHENTICATION = 39, + + /** + * Nonces, for initator and responder (Ni, Nr, N) + */ + NONCE = 40, + + /** + * Notif paylaod (N). + */ + NOTIFY = 41, + + /** + * Delete payload (D) + */ + DELETE = 42, + + /** + * Vendor id paylpoad (V). + */ + VENDOR_ID = 43, + + /** + * Traffic selector for the original initiator (TSi). + */ + TRAFFIC_SELECTOR_INITIATOR = 44, + + /** + * Traffic selector for the original responser (TSr). + */ + TRAFFIC_SELECTOR_RESPONDER = 45, + + /** + * Encryption payload, contains other payloads (E). + */ + ENCRYPTED = 46, + + /** + * Configuration payload (CP). + */ + CONFIGURATION = 47, + + /** + * Extensible authentication payload (EAP). + */ + EXTENSIBLE_AUTHENTICATION = 48, + + /** + * Header has a value of PRIVATE USE space. + * + * This payload type is not send over wire and just + * used internally to handle IKEv2-Header like a payload. + */ + HEADER = 140, + + /** + * PROPOSAL_SUBSTRUCTURE has a value of PRIVATE USE space. + * + * This payload type is not send over wire and just + * used internally to handle a proposal substructure like a payload. + */ + PROPOSAL_SUBSTRUCTURE = 141, + + /** + * TRANSFORM_SUBSTRUCTURE has a value of PRIVATE USE space. + * + * This payload type is not send over wire and just + * used internally to handle a transform substructure like a payload. + */ + TRANSFORM_SUBSTRUCTURE = 142, + + /** + * TRANSFORM_ATTRIBUTE has a value of PRIVATE USE space. + * + * This payload type is not send over wire and just + * used internally to handle a transform attribute like a payload. + */ + TRANSFORM_ATTRIBUTE = 143, + + /** + * TRAFFIC_SELECTOR_SUBSTRUCTURE has a value of PRIVATE USE space. + * + * This payload type is not send over wire and just + * used internally to handle a transform selector like a payload. + */ + TRAFFIC_SELECTOR_SUBSTRUCTURE = 144, + + /** + * CONFIGURATION_ATTRIBUTE has a value of PRIVATE USE space. + * + * This payload type is not send 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 send over wire and just + * used internally to handle a unknown payload. + */ + UNKNOWN_PAYLOAD = 146, +}; + + +/** + * String mappings for payload_type_t. + */ +extern mapping_t payload_type_m[]; + + +typedef struct payload_t payload_t; + +/** + * @brief Generic interface for all payload types (incl.header and substructures). + * + * To handle all kinds of payloads on a generic way, this interface must + * be implemented by every payload. This allows parser_t/generator_t a simple + * handling of all payloads. + * + * @b Constructors: + * - payload_create() with the payload to instanciate. + * + * @ingroup payloads + */ +struct payload_t { + + /** + * @brief Get encoding rules for this payload. + * + * @param this calling object + * @param[out] rules location to store pointer of first rule + * @param[out] rule_count location to store number of rules + */ + void (*get_encoding_rules) (payload_t *this, encoding_rule_t **rules, size_t *rule_count); + + /** + * @brief Get type of payload. + * + * @param this calling object + * @return type of this payload + */ + payload_type_t (*get_type) (payload_t *this); + + /** + * @brief Get type of next payload or NO_PAYLOAD (0) if this is the last one. + * + * @param this calling object + * @return type of next payload + */ + payload_type_t (*get_next_type) (payload_t *this); + + /** + * @brief Set type of next payload. + * + * @param this calling object + * @param type type of next payload + */ + void (*set_next_type) (payload_t *this,payload_type_t type); + + /** + * @brief Get length of payload. + * + * @param this calling object + * @return length of this payload + */ + size_t (*get_length) (payload_t *this); + + /** + * @brief Verifies payload structure and makes consistence check. + * + * @param this calling object + * @return + * - SUCCESS + * - FAILED if consistence not given + */ + status_t (*verify) (payload_t *this); + + /** + * @brief Destroys a payload and all included substructures. + * + * @param this payload to destroy + */ + void (*destroy) (payload_t *this); +}; + +/** + * @brief Create an empty payload. + * + * Useful for the parser, who wants a generic constructor for all payloads. + * It supports all payload_t methods. If a payload type is not known, + * an unknwon_paylod is created with the chunk of data in it. + * + * @param type type of the payload to create + * @return payload_t object + */ +payload_t *payload_create(payload_type_t type); + +#endif /*PAYLOAD_H_*/ diff --git a/src/charon/encoding/payloads/proposal_substructure.c b/src/charon/encoding/payloads/proposal_substructure.c new file mode 100644 index 000000000..cb3c695b2 --- /dev/null +++ b/src/charon/encoding/payloads/proposal_substructure.c @@ -0,0 +1,629 @@ +/** + * @file proposal_substructure.h + * + * @brief Implementation of proposal_substructure_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 + +#include "proposal_substructure.h" + +#include +#include +#include +#include + + +/** + * IKEv1 Value for a proposal payload. + */ +#define PROPOSAL_TYPE_VALUE 2 + + +typedef struct private_proposal_substructure_t private_proposal_substructure_t; + +/** + * Private data of an proposal_substructure_t object. + * + */ +struct private_proposal_substructure_t { + /** + * Public proposal_substructure_t interface. + */ + proposal_substructure_t public; + + /** + * Next payload type. + */ + u_int8_t next_payload; + + /** + * Length of this payload. + */ + u_int16_t proposal_length; + + /** + * Proposal number. + */ + u_int8_t proposal_number; + + /** + * Protocol ID. + */ + u_int8_t protocol_id; + + /** + * SPI size of the following SPI. + */ + u_int8_t spi_size; + + /** + * Number of transforms. + */ + u_int8_t transforms_count; + + /** + * SPI is stored as chunk. + */ + chunk_t spi; + + /** + * Transforms are stored in a linked_list_t. + */ + linked_list_t * transforms; + + /** + * @brief Computes the length of this substructure. + * + * @param this calling private_proposal_substructure_t object + */ + void (*compute_length) (private_proposal_substructure_t *this); +}; + +/** + * Encoding rules to parse or generate a Proposal substructure. + * + * The defined offsets are the positions in a object of type + * private_proposal_substructure_t. + * + */ +encoding_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 }, + /* Length of the whole proposal substructure payload*/ + { PAYLOAD_LENGTH, offsetof(private_proposal_substructure_t, proposal_length) }, + /* proposal number is a number of 8 bit */ + { U_INT_8, offsetof(private_proposal_substructure_t, proposal_number) }, + /* protocol ID is a number of 8 bit */ + { U_INT_8, offsetof(private_proposal_substructure_t, protocol_id) }, + /* SPI Size has its own type */ + { SPI_SIZE, offsetof(private_proposal_substructure_t, spi_size) }, + /* Number of transforms is a number of 8 bit */ + { U_INT_8, offsetof(private_proposal_substructure_t, transforms_count) }, + /* SPI is a chunk of variable size*/ + { SPI, offsetof(private_proposal_substructure_t, spi) }, + /* Transforms are stored in a transform substructure, + offset points to a linked_list_t pointer */ + { TRANSFORMS, offsetof(private_proposal_substructure_t, transforms) } +}; + +/* + 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 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! 0 (last) or 2 ! RESERVED ! Proposal Length ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! Proposal # ! Protocol ID ! SPI Size !# of Transforms! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ~ SPI (variable) ~ + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! ! + ~ ~ + ! ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ + +/** + * Implementation of payload_t.verify. + */ +static status_t verify(private_proposal_substructure_t *this) +{ + status_t status = SUCCESS; + iterator_t *iterator; + + if ((this->next_payload != NO_PAYLOAD) && (this->next_payload != 2)) + { + /* must be 0 or 2 */ + return FAILED; + } + if (this->transforms_count != this->transforms->get_count(this->transforms)) + { + /* must be the same! */ + return FAILED; + } + + if ((this->protocol_id == 0) || (this->protocol_id >= 4)) + { + /* reserved are not supported */ + return FAILED; + } + + iterator = this->transforms->create_iterator(this->transforms,TRUE); + + while(iterator->has_next(iterator)) + { + payload_t *current_transform; + iterator->current(iterator,(void **)¤t_transform); + + status = current_transform->verify(current_transform); + if (status != SUCCESS) + { + break; + } + } + + iterator->destroy(iterator); + + + /* proposal number is checked in SA payload */ + return status; +} + +/** + * Implementation of payload_t.get_encoding_rules. + */ +static void get_encoding_rules(private_proposal_substructure_t *this, encoding_rule_t **rules, size_t *rule_count) +{ + *rules = proposal_substructure_encodings; + *rule_count = sizeof(proposal_substructure_encodings) / sizeof(encoding_rule_t); +} + +/** + * Implementation of payload_t.get_type. + */ +static payload_type_t get_type(private_proposal_substructure_t *this) +{ + return PROPOSAL_SUBSTRUCTURE; +} + +/** + * Implementation of payload_t.get_next_type. + */ +static payload_type_t get_next_type(private_proposal_substructure_t *this) +{ + return (this->next_payload); +} + +/** + * Implementation of payload_t.set_next_type. + */ +static void set_next_type(private_proposal_substructure_t *this,payload_type_t type) +{ +} + +/** + * Implementation of payload_t.get_length. + */ +static size_t get_length(private_proposal_substructure_t *this) +{ + this->compute_length(this); + return this->proposal_length; +} + +/** + * Implementation of proposal_substructure_t.create_transform_substructure_iterator. + */ +static iterator_t *create_transform_substructure_iterator (private_proposal_substructure_t *this,bool forward) +{ + return (this->transforms->create_iterator(this->transforms,forward)); +} + +/** + * Implementation of proposal_substructure_t.add_transform_substructure. + */ +static void add_transform_substructure (private_proposal_substructure_t *this,transform_substructure_t *transform) +{ + status_t status; + if (this->transforms->get_count(this->transforms) > 0) + { + transform_substructure_t *last_transform; + status = this->transforms->get_last(this->transforms,(void **) &last_transform); + /* last transform is now not anymore last one */ + last_transform->set_is_last_transform(last_transform,FALSE); + + } + transform->set_is_last_transform(transform,TRUE); + + this->transforms->insert_last(this->transforms,(void *) transform); + this->compute_length(this); +} + +/** + * Implementation of proposal_substructure_t.proposal_substructure_t. + */ +static void set_is_last_proposal (private_proposal_substructure_t *this, bool is_last) +{ + this->next_payload = (is_last) ? 0: PROPOSAL_TYPE_VALUE; +} + + +/** + * Implementation of proposal_substructure_t.set_proposal_number. + */ +static void set_proposal_number(private_proposal_substructure_t *this,u_int8_t proposal_number) +{ + this->proposal_number = proposal_number; +} + +/** + * Implementation of proposal_substructure_t.get_proposal_number. + */ +static u_int8_t get_proposal_number (private_proposal_substructure_t *this) +{ + return (this->proposal_number); +} + +/** + * Implementation of proposal_substructure_t.set_protocol_id. + */ +static void set_protocol_id(private_proposal_substructure_t *this,u_int8_t protocol_id) +{ + this->protocol_id = protocol_id; +} + +/** + * Implementation of proposal_substructure_t.get_protocol_id. + */ +static u_int8_t get_protocol_id (private_proposal_substructure_t *this) +{ + return (this->protocol_id); +} + +/** + * Implementation of proposal_substructure_t.set_spi. + */ +static void set_spi (private_proposal_substructure_t *this, chunk_t spi) +{ + /* first delete already set spi value */ + if (this->spi.ptr != NULL) + { + free(this->spi.ptr); + this->spi.ptr = NULL; + this->spi.len = 0; + this->compute_length(this); + } + + this->spi.ptr = clalloc(spi.ptr,spi.len); + this->spi.len = spi.len; + this->spi_size = spi.len; + this->compute_length(this); +} + +/** + * Implementation of proposal_substructure_t.get_spi. + */ +static chunk_t get_spi (private_proposal_substructure_t *this) +{ + chunk_t spi; + spi.ptr = this->spi.ptr; + spi.len = this->spi.len; + + return spi; +} + +/** + * Implementation of proposal_substructure_t.get_info_for_transform_type. + */ +static status_t get_info_for_transform_type (private_proposal_substructure_t *this,transform_type_t type, u_int16_t *transform_id, u_int16_t *key_length) +{ + iterator_t *iterator; + status_t status; + u_int16_t found_transform_id; + u_int16_t found_key_length; + + iterator = this->transforms->create_iterator(this->transforms,TRUE); + + while (iterator->has_next(iterator)) + { + transform_substructure_t *current_transform; + status = iterator->current(iterator,(void **) ¤t_transform); + if (status != SUCCESS) + { + break; + } + if (current_transform->get_transform_type(current_transform) == type) + { + /* now get data for specific type */ + found_transform_id = current_transform->get_transform_id(current_transform); + status = current_transform->get_key_length(current_transform,&found_key_length); + *transform_id = found_transform_id; + *key_length = found_key_length; + iterator->destroy(iterator); + return status; + } + } + iterator->destroy(iterator); + return NOT_FOUND; +} + +/** + * Implementation of private_proposal_substructure_t.compute_length. + */ +static void compute_length (private_proposal_substructure_t *this) +{ + iterator_t *iterator; + size_t transforms_count = 0; + size_t length = PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH; + iterator = this->transforms->create_iterator(this->transforms,TRUE); + while (iterator->has_next(iterator)) + { + payload_t * current_transform; + iterator->current(iterator,(void **) ¤t_transform); + length += current_transform->get_length(current_transform); + transforms_count++; + } + iterator->destroy(iterator); + + length += this->spi.len; + this->transforms_count = transforms_count; + this->proposal_length = length; +} + +/** + * Implementation of proposal_substructure_t.get_transform_count. + */ +static size_t get_transform_count (private_proposal_substructure_t *this) +{ + return this->transforms->get_count(this->transforms); +} + +/** + * Implementation of proposal_substructure_t.get_spi_size. + */ +static size_t get_spi_size (private_proposal_substructure_t *this) +{ + return this->spi.len; +} + +/** + * Implementation of proposal_substructure_t.add_to_proposal. + */ +void add_to_proposal(private_proposal_substructure_t *this, proposal_t *proposal) +{ + iterator_t *iterator = this->transforms->create_iterator(this->transforms, TRUE); + u_int32_t spi; + + + while (iterator->has_next(iterator)) + { + transform_substructure_t *transform; + transform_type_t transform_type; + u_int16_t transform_id; + u_int16_t key_length = 0; + + iterator->current(iterator, (void**)&transform); + + transform_type = transform->get_transform_type(transform); + transform_id = transform->get_transform_id(transform); + transform->get_key_length(transform, &key_length); + + proposal->add_algorithm(proposal, this->protocol_id, transform_type, transform_id, key_length); + } + iterator->destroy(iterator); + + spi = *((u_int32_t*)this->spi.ptr); + + proposal->set_spi(proposal, this->protocol_id, spi); +} + +/** + * Implementation of proposal_substructure_t.clone. + */ +static private_proposal_substructure_t* clone(private_proposal_substructure_t *this) +{ + private_proposal_substructure_t * new_clone; + iterator_t *transforms; + + new_clone = (private_proposal_substructure_t *) proposal_substructure_create(); + + new_clone->next_payload = this->next_payload; + new_clone->proposal_number = this->proposal_number; + new_clone->protocol_id = this->protocol_id; + new_clone->spi_size = this->spi_size; + if (this->spi.ptr != NULL) + { + new_clone->spi.ptr = clalloc(this->spi.ptr,this->spi.len); + new_clone->spi.len = this->spi.len; + } + + transforms = this->transforms->create_iterator(this->transforms,FALSE); + + while (transforms->has_next(transforms)) + { + transform_substructure_t *current_transform; + transform_substructure_t *current_transform_clone; + + transforms->current(transforms,(void **) ¤t_transform); + + current_transform_clone = current_transform->clone(current_transform); + + new_clone->public.add_transform_substructure(&(new_clone->public),current_transform_clone); + } + + transforms->destroy(transforms); + + return new_clone; +} + +/** + * Implements payload_t's and proposal_substructure_t's destroy function. + * See #payload_s.destroy or proposal_substructure_s.destroy for description. + */ +static status_t destroy(private_proposal_substructure_t *this) +{ + /* all proposals are getting destroyed */ + while (this->transforms->get_count(this->transforms) > 0) + { + transform_substructure_t *current_transform; + if (this->transforms->remove_last(this->transforms,(void **)¤t_transform) != SUCCESS) + { + break; + } + current_transform->destroy(current_transform); + } + this->transforms->destroy(this->transforms); + + if (this->spi.ptr != NULL) + { + free(this->spi.ptr); + } + + free(this); + + return SUCCESS; +} + +/* + * Described in header. + */ +proposal_substructure_t *proposal_substructure_create() +{ + private_proposal_substructure_t *this = malloc_thing(private_proposal_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_type; + this->public.payload_interface.destroy = (void (*) (payload_t *))destroy; + + + /* public functions */ + this->public.create_transform_substructure_iterator = (iterator_t* (*) (proposal_substructure_t *,bool)) create_transform_substructure_iterator; + this->public.add_transform_substructure = (void (*) (proposal_substructure_t *,transform_substructure_t *)) add_transform_substructure; + this->public.set_proposal_number = (void (*) (proposal_substructure_t *,u_int8_t))set_proposal_number; + this->public.get_proposal_number = (u_int8_t (*) (proposal_substructure_t *)) get_proposal_number; + this->public.set_protocol_id = (void (*) (proposal_substructure_t *,u_int8_t))set_protocol_id; + this->public.get_protocol_id = (u_int8_t (*) (proposal_substructure_t *)) get_protocol_id; + this->public.get_info_for_transform_type = (status_t (*) (proposal_substructure_t *,transform_type_t,u_int16_t *, u_int16_t *))get_info_for_transform_type; + this->public.set_is_last_proposal = (void (*) (proposal_substructure_t *,bool)) set_is_last_proposal; + this->public.add_to_proposal = (void (*) (proposal_substructure_t*,proposal_t*))add_to_proposal; + this->public.set_spi = (void (*) (proposal_substructure_t *,chunk_t))set_spi; + this->public.get_spi = (chunk_t (*) (proposal_substructure_t *)) get_spi; + this->public.get_transform_count = (size_t (*) (proposal_substructure_t *)) get_transform_count; + this->public.get_spi_size = (size_t (*) (proposal_substructure_t *)) get_spi_size; + this->public.clone = (proposal_substructure_t * (*) (proposal_substructure_t *)) clone; + this->public.destroy = (void (*) (proposal_substructure_t *)) destroy; + + /* private functions */ + this->compute_length = compute_length; + + /* set default values of the fields */ + this->next_payload = NO_PAYLOAD; + this->proposal_length = 0; + this->proposal_number = 0; + this->protocol_id = 0; + this->transforms_count = 0; + this->spi_size = 0; + this->spi.ptr = NULL; + this->spi.len = 0; + + this->transforms = linked_list_create(); + + return (&(this->public)); +} + +/* + * Described in header. + */ +proposal_substructure_t *proposal_substructure_create_from_proposal(proposal_t *proposal, protocol_id_t proto) +{ + private_proposal_substructure_t *this = (private_proposal_substructure_t*)proposal_substructure_create(); + iterator_t *iterator; + algorithm_t *algo; + transform_substructure_t *transform; + + /* encryption algorithm is only availble in ESP */ + iterator = proposal->create_algorithm_iterator(proposal, proto, ENCRYPTION_ALGORITHM); + while (iterator->has_next(iterator)) + { + iterator->current(iterator, (void**)&algo); + transform = transform_substructure_create_type(ENCRYPTION_ALGORITHM, algo->algorithm, algo->key_size); + this->public.add_transform_substructure(&(this->public), transform); + } + iterator->destroy(iterator); + + /* integrity algorithms */ + iterator = proposal->create_algorithm_iterator(proposal, proto, INTEGRITY_ALGORITHM); + while (iterator->has_next(iterator)) + { + algorithm_t *algo; + iterator->current(iterator, (void**)&algo); + transform = transform_substructure_create_type(INTEGRITY_ALGORITHM, algo->algorithm, algo->key_size); + this->public.add_transform_substructure(&(this->public), transform); + } + iterator->destroy(iterator); + + /* prf algorithms */ + iterator = proposal->create_algorithm_iterator(proposal, proto, PSEUDO_RANDOM_FUNCTION); + while (iterator->has_next(iterator)) + { + algorithm_t *algo; + iterator->current(iterator, (void**)&algo); + transform = transform_substructure_create_type(PSEUDO_RANDOM_FUNCTION, algo->algorithm, algo->key_size); + this->public.add_transform_substructure(&(this->public), transform); + } + iterator->destroy(iterator); + + /* dh groups */ + iterator = proposal->create_algorithm_iterator(proposal, proto, DIFFIE_HELLMAN_GROUP); + while (iterator->has_next(iterator)) + { + algorithm_t *algo; + iterator->current(iterator, (void**)&algo); + transform = transform_substructure_create_type(DIFFIE_HELLMAN_GROUP, algo->algorithm, 0); + this->public.add_transform_substructure(&(this->public), transform); + } + iterator->destroy(iterator); + + /* extended sequence numbers */ + iterator = proposal->create_algorithm_iterator(proposal, proto, EXTENDED_SEQUENCE_NUMBERS); + while (iterator->has_next(iterator)) + { + algorithm_t *algo; + iterator->current(iterator, (void**)&algo); + transform = transform_substructure_create_type(EXTENDED_SEQUENCE_NUMBERS, algo->algorithm, 0); + this->public.add_transform_substructure(&(this->public), transform); + } + iterator->destroy(iterator); + + /* take over general infos */ + this->spi_size = proto == PROTO_IKE ? 8 : 4; + this->spi.len = this->spi_size; + this->spi.ptr = malloc(this->spi_size); + *((u_int32_t*)this->spi.ptr) = proposal->get_spi(proposal, proto); + this->proposal_number = proposal->get_number(proposal); + this->protocol_id = proto; + + return &(this->public); +} diff --git a/src/charon/encoding/payloads/proposal_substructure.h b/src/charon/encoding/payloads/proposal_substructure.h new file mode 100644 index 000000000..a59f9532f --- /dev/null +++ b/src/charon/encoding/payloads/proposal_substructure.h @@ -0,0 +1,231 @@ +/** + * @file proposal_substructure.h + * + * @brief Interface of proposal_substructure_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef PROPOSAL_SUBSTRUCTURE_H_ +#define PROPOSAL_SUBSTRUCTURE_H_ + +#include +#include +#include +#include +#include + + +/** + * Length of the proposal substructure header (without spi). + * + * @ingroup payloads + */ +#define PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH 8 + + +typedef struct proposal_substructure_t proposal_substructure_t; + +/** + * @brief Class representing an IKEv2-PROPOSAL SUBSTRUCTURE. + * + * The PROPOSAL SUBSTRUCTURE format is described in RFC section 3.3.1. + * + * @b Constructors: + * - proposal_substructure_create() + * + * @ingroup payloads + */ +struct proposal_substructure_t { + /** + * The payload_t interface. + */ + payload_t payload_interface; + + /** + * @brief Creates an iterator of stored transform_substructure_t objects. + * + * @warning The created iterator has to get destroyed by the caller! + * When deleting any transform over this iterator, call + * get_size to make sure the length and number values are ok. + * + * @param this calling proposal_substructure_t object + * @param forward iterator direction (TRUE: front to end) + * @return created iterator_t object + */ + iterator_t * (*create_transform_substructure_iterator) (proposal_substructure_t *this, bool forward); + + /** + * @brief Adds a transform_substructure_t object to this object. + * + * @warning The added transform_substructure_t object is + * getting destroyed in destroy function of proposal_substructure_t. + * + * @param this calling proposal_substructure_t object + * @param transform transform_substructure_t object to add + */ + void (*add_transform_substructure) (proposal_substructure_t *this,transform_substructure_t *transform); + + /** + * @brief Sets the proposal number of current proposal. + * + * @param this calling proposal_substructure_t object + * @param id proposal number to set + */ + void (*set_proposal_number) (proposal_substructure_t *this,u_int8_t proposal_number); + + /** + * @brief get proposal number of current proposal. + * + * @param this calling proposal_substructure_t object + * @return proposal number of current proposal substructure. + */ + u_int8_t (*get_proposal_number) (proposal_substructure_t *this); + + /** + * @brief get the number of transforms in current proposal. + * + * @param this calling proposal_substructure_t object + * @return transform count in current proposal + */ + size_t (*get_transform_count) (proposal_substructure_t *this); + + /** + * @brief get size of the set spi in bytes. + * + * @param this calling proposal_substructure_t object + * @return size of the spi in bytes + */ + size_t (*get_spi_size) (proposal_substructure_t *this); + + /** + * @brief Sets the protocol id of current proposal. + * + * @param this calling proposal_substructure_t object + * @param id protocol id to set + */ + void (*set_protocol_id) (proposal_substructure_t *this,u_int8_t protocol_id); + + /** + * @brief get protocol id of current proposal. + * + * @param this calling proposal_substructure_t object + * @return protocol id of current proposal substructure. + */ + u_int8_t (*get_protocol_id) (proposal_substructure_t *this); + + /** + * @brief Get informations for a specific transform type. + * + * @param this calling proposal_substructure_t object + * @param type type to get informations for + * @param transform_id transform id of the specific type + * @param key_length key length of the specific key length transform attribute + * @return + * - SUCCESS if transform type is part of this proposal and + * all data (incl. key length) could be fetched + * - NOT_FOUND if transform type is not part of this proposal + */ + status_t (*get_info_for_transform_type) (proposal_substructure_t *this,transform_type_t type, u_int16_t *transform_id, u_int16_t *key_length); + + /** + * @brief Sets the next_payload field of this substructure + * + * If this is the last proposal, next payload field is set to 0, + * otherwise to 2 + * + * @param this calling proposal_substructure_t object + * @param is_last When TRUE, next payload field is set to 0, otherwise to 2 + */ + void (*set_is_last_proposal) (proposal_substructure_t *this, bool is_last); + + /** + * @brief Returns the currently set SPI of this proposal. + * + * @warning Returned data are not copied + * + * @param this calling proposal_substructure_t object + * @return chunk_t pointing to the value + */ + chunk_t (*get_spi) (proposal_substructure_t *this); + + /** + * @brief Sets the SPI of the current proposal. + * + * @warning SPI is getting copied + * + * @param this calling proposal_substructure_t object + * @param spi chunk_t pointing to the value to set + */ + void (*set_spi) (proposal_substructure_t *this, chunk_t spi); + + /** + * @brief Add this proposal_substructure to a proposal. + * + * Since a proposal_t may contain the data of multiple + * proposal_sbustructure_t's, it may be necessary to call + * the function multiple times with the same proposal. + * + * @param this calling proposal_substructure_t object + * @param proposal proposal where the data should be added + */ + void (*add_to_proposal) (proposal_substructure_t *this, proposal_t *proposal); + + /** + * @brief Clones an proposal_substructure_t object. + * + * @param this proposal_substructure_t object to clone + * @return cloned object + */ + proposal_substructure_t* (*clone) (proposal_substructure_t *this); + + /** + * @brief Destroys an proposal_substructure_t object. + * + * @param this proposal_substructure_t object to destroy + */ + void (*destroy) (proposal_substructure_t *this); +}; + +/** + * @brief Creates an empty proposal_substructure_t object + * + * @return proposal_substructure_t object + * + * @ingroup payloads + */ +proposal_substructure_t *proposal_substructure_create(void); + +/** + * @brief Creates a proposal substructure from a proposal. + * + * Since a child proposal may contain data for both AH and ESP, + * the protocol must be specified. If the proposal does not contain + * data for proto, NULL is returned. Call twice, once with AH, once + * with ESP, with the same proposal to build the two substructures + * for it. + * + * @param proposal proposal to build a substruct out of it + * @param proto for which protocol the substructure should be built + * @return proposal_substructure_t object, or NULL + * + * @ingroup payloads + */ +proposal_substructure_t *proposal_substructure_create_from_proposal(proposal_t *proposal, protocol_id_t proto); + + +#endif /*PROPOSAL_SUBSTRUCTURE_H_*/ diff --git a/src/charon/encoding/payloads/sa_payload.c b/src/charon/encoding/payloads/sa_payload.c new file mode 100644 index 000000000..81b4e6709 --- /dev/null +++ b/src/charon/encoding/payloads/sa_payload.c @@ -0,0 +1,390 @@ +/** + * @file sa_payload.c + * + * @brief Implementation of sa_payload_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 + +#include "sa_payload.h" + +#include +#include + + +typedef struct private_sa_payload_t private_sa_payload_t; + +/** + * Private data of an sa_payload_t object. + * + */ +struct private_sa_payload_t { + /** + * Public sa_payload_t interface. + */ + sa_payload_t public; + + /** + * Next payload type. + */ + u_int8_t next_payload; + + /** + * Critical flag. + */ + bool critical; + + /** + * Length of this payload. + */ + u_int16_t payload_length; + + /** + * Proposals in this payload are stored in a linked_list_t. + */ + linked_list_t * proposals; + + /** + * @brief Computes the length of this payload. + * + * @param this calling private_sa_payload_t object + */ + void (*compute_length) (private_sa_payload_t *this); +}; + +/** + * Encoding rules to parse or generate a IKEv2-SA Payload + * + * The defined offsets are the positions in a object of type + * private_sa_payload_t. + * + */ +encoding_rule_t sa_payload_encodings[] = { + /* 1 Byte next payload type, stored in the field next_payload */ + { U_INT_8, offsetof(private_sa_payload_t, next_payload) }, + /* the critical bit */ + { FLAG, offsetof(private_sa_payload_t, critical) }, + /* 7 Bit reserved bits, nowhere stored */ + { RESERVED_BIT, 0 }, + { RESERVED_BIT, 0 }, + { RESERVED_BIT, 0 }, + { RESERVED_BIT, 0 }, + { RESERVED_BIT, 0 }, + { RESERVED_BIT, 0 }, + { RESERVED_BIT, 0 }, + /* Length of the whole SA payload*/ + { PAYLOAD_LENGTH, offsetof(private_sa_payload_t, payload_length) }, + /* Proposals are stored in a proposal substructure, + offset points to a linked_list_t pointer */ + { PROPOSALS, offsetof(private_sa_payload_t, proposals) } +}; + +/* + 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! Next Payload !C! RESERVED ! Payload Length ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! ! + ~ ~ + ! ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ + +/** + * Implementation of payload_t.verify. + */ +static status_t verify(private_sa_payload_t *this) +{ + int proposal_number = 1; + status_t status = SUCCESS; + iterator_t *iterator; + bool first = TRUE; + + /* check proposal numbering */ + iterator = this->proposals->create_iterator(this->proposals,TRUE); + + while(iterator->has_next(iterator)) + { + proposal_substructure_t *current_proposal; + iterator->current(iterator,(void **)¤t_proposal); + if (current_proposal->get_proposal_number(current_proposal) > proposal_number) + { + if (first) + { + /* first number must be 1 */ + status = FAILED; + break; + } + + if (current_proposal->get_proposal_number(current_proposal) != (proposal_number + 1)) + { + /* must be only one more then previous proposal */ + status = FAILED; + break; + } + } + else if (current_proposal->get_proposal_number(current_proposal) < proposal_number) + { + /* must not be smaller then proceeding one */ + status = FAILED; + break; + } + + status = current_proposal->payload_interface.verify(&(current_proposal->payload_interface)); + if (status != SUCCESS) + { + break; + } + first = FALSE; + } + + iterator->destroy(iterator); + return status; +} + + +/** + * Implementation of payload_t.destroy and sa_payload_t.destroy. + */ +static status_t destroy(private_sa_payload_t *this) +{ + /* all proposals are getting destroyed */ + while (this->proposals->get_count(this->proposals) > 0) + { + proposal_substructure_t *current_proposal; + this->proposals->remove_last(this->proposals,(void **)¤t_proposal); + current_proposal->destroy(current_proposal); + } + this->proposals->destroy(this->proposals); + + free(this); + + return SUCCESS; +} + +/** + * Implementation of payload_t.get_encoding_rules. + */ +static void get_encoding_rules(private_sa_payload_t *this, encoding_rule_t **rules, size_t *rule_count) +{ + *rules = sa_payload_encodings; + *rule_count = sizeof(sa_payload_encodings) / sizeof(encoding_rule_t); +} + +/** + * Implementation of payload_t.get_type. + */ +static payload_type_t get_type(private_sa_payload_t *this) +{ + return SECURITY_ASSOCIATION; +} + +/** + * Implementation of payload_t.get_next_type. + */ +static payload_type_t get_next_type(private_sa_payload_t *this) +{ + return (this->next_payload); +} + +/** + * Implementation of payload_t.set_next_type. + */ +static void set_next_type(private_sa_payload_t *this,payload_type_t type) +{ + this->next_payload = type; +} + +/** + * Implementation of payload_t.get_length. + */ +static size_t get_length(private_sa_payload_t *this) +{ + this->compute_length(this); + return this->payload_length; +} + +/** + * Implementation of sa_payload_t.create_proposal_substructure_iterator. + */ +static iterator_t *create_proposal_substructure_iterator (private_sa_payload_t *this,bool forward) +{ + return this->proposals->create_iterator(this->proposals,forward); +} + +/** + * Implementation of sa_payload_t.add_proposal_substructure. + */ +static void add_proposal_substructure (private_sa_payload_t *this,proposal_substructure_t *proposal) +{ + status_t status; + if (this->proposals->get_count(this->proposals) > 0) + { + proposal_substructure_t *last_proposal; + status = this->proposals->get_last(this->proposals,(void **) &last_proposal); + /* last transform is now not anymore last one */ + last_proposal->set_is_last_proposal(last_proposal,FALSE); + } + proposal->set_is_last_proposal(proposal,TRUE); + + this->proposals->insert_last(this->proposals,(void *) proposal); + this->compute_length(this); +} + +/** + * Implementation of sa_payload_t.add_proposal. + */ +static void add_proposal(private_sa_payload_t *this, proposal_t *proposal) +{ + proposal_substructure_t *substructure; + protocol_id_t proto[2]; + u_int i; + + /* build the substructures for every protocol */ + proposal->get_protocols(proposal, proto); + for (i = 0; i<2; i++) + { + if (proto[i] != PROTO_NONE) + { + substructure = proposal_substructure_create_from_proposal(proposal, proto[i]); + add_proposal_substructure(this, substructure); + } + } +} + +/** + * Implementation of sa_payload_t.get_proposals. + */ +static linked_list_t *get_proposals(private_sa_payload_t *this) +{ + int proposal_struct_number = 0; + iterator_t *iterator; + proposal_t *proposal; + linked_list_t *proposal_list; + + /* this list will hold our proposals */ + proposal_list = linked_list_create(); + + /* iterate over structures, one OR MORE structures will result in a proposal */ + iterator = this->proposals->create_iterator(this->proposals,TRUE); + while (iterator->has_next(iterator)) + { + proposal_substructure_t *proposal_struct; + iterator->current(iterator,(void **)&(proposal_struct)); + + if (proposal_struct->get_proposal_number(proposal_struct) > proposal_struct_number) + { + /* here starts a new proposal, create a new one and add it to the list */ + proposal_struct_number = proposal_struct->get_proposal_number(proposal_struct); + proposal = proposal_create(proposal_struct_number); + proposal_list->insert_last(proposal_list, proposal); + } + /* proposal_substructure_t does the dirty work and builds up the proposal */ + proposal_struct->add_to_proposal(proposal_struct, proposal); + } + iterator->destroy(iterator); + return proposal_list; +} + +/** + * Implementation of private_sa_payload_t.compute_length. + */ +static void compute_length (private_sa_payload_t *this) +{ + iterator_t *iterator; + size_t length = SA_PAYLOAD_HEADER_LENGTH; + iterator = this->proposals->create_iterator(this->proposals,TRUE); + while (iterator->has_next(iterator)) + { + payload_t *current_proposal; + iterator->current(iterator,(void **) ¤t_proposal); + length += current_proposal->get_length(current_proposal); + } + iterator->destroy(iterator); + + this->payload_length = length; +} + +/* + * Described in header. + */ +sa_payload_t *sa_payload_create() +{ + private_sa_payload_t *this = malloc_thing(private_sa_payload_t); + + /* public 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_proposal_substructure_iterator = (iterator_t* (*) (sa_payload_t *,bool)) create_proposal_substructure_iterator; + this->public.add_proposal_substructure = (void (*) (sa_payload_t *,proposal_substructure_t *)) add_proposal_substructure; + this->public.get_proposals = (linked_list_t* (*) (sa_payload_t *)) get_proposals; + this->public.destroy = (void (*) (sa_payload_t *)) destroy; + + /* private functions */ + this->compute_length = compute_length; + + /* set default values of the fields */ + this->critical = FALSE; + this->next_payload = NO_PAYLOAD; + this->payload_length = SA_PAYLOAD_HEADER_LENGTH; + + this->proposals = linked_list_create(); + return (&(this->public)); +} + +/* + * Described in header. + */ +sa_payload_t *sa_payload_create_from_proposal_list(linked_list_t *proposals) +{ + iterator_t *iterator; + proposal_t *proposal; + sa_payload_t *sa_payload = sa_payload_create(); + + /* add every payload from the list */ + iterator = proposals->create_iterator(proposals, TRUE); + while (iterator->has_next(iterator)) + { + iterator->current(iterator, (void**)&proposal); + add_proposal((private_sa_payload_t*)sa_payload, proposal); + } + iterator->destroy(iterator); + + return sa_payload; +} + +/* + * Described in header. + */ +sa_payload_t *sa_payload_create_from_proposal(proposal_t *proposal) +{ + sa_payload_t *sa_payload = sa_payload_create(); + + add_proposal((private_sa_payload_t*)sa_payload, proposal); + + return sa_payload; +} diff --git a/src/charon/encoding/payloads/sa_payload.h b/src/charon/encoding/payloads/sa_payload.h new file mode 100644 index 000000000..3cf6f5065 --- /dev/null +++ b/src/charon/encoding/payloads/sa_payload.h @@ -0,0 +1,140 @@ +/** + * @file sa_payload.h + * + * @brief Interface of sa_payload_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef SA_PAYLOAD_H_ +#define SA_PAYLOAD_H_ + +#include +#include +#include +#include + +/** + * SA_PAYLOAD length in bytes without any proposal substructure. + * + * @ingroup payloads + */ +#define SA_PAYLOAD_HEADER_LENGTH 4 + +typedef struct sa_payload_t sa_payload_t; + +/** + * @brief Class representing an IKEv2-SA Payload. + * + * The SA Payload format is described in RFC section 3.3. + * + * @b Constructors: + * - sa_payload_create() + * - sa_payload_create_from_ike_proposals() + * - sa_payload_create_from_proposal() + * + * @todo Add support of algorithms without specified keylength in get_proposals and get_ike_proposals. + * + * @ingroup payloads + */ +struct sa_payload_t { + /** + * The payload_t interface. + */ + payload_t payload_interface; + + /** + * @brief Creates an iterator of stored proposal_substructure_t objects. + * + * @warning The created iterator has to get destroyed by the caller! + * + * @warning When deleting an proposal using this iterator, + * the length of this transform substructure has to be refreshed + * by calling get_length()! + * + * @param this calling sa_payload_t object + * @param[in] forward iterator direction (TRUE: front to end) + * @return created iterator_t object + */ + iterator_t *(*create_proposal_substructure_iterator) (sa_payload_t *this, bool forward); + + /** + * @brief Adds a proposal_substructure_t object to this object. + * + * @warning The added proposal_substructure_t object is + * getting destroyed in destroy function of sa_payload_t. + * + * @param this calling sa_payload_t object + * @param proposal proposal_substructure_t object to add + */ + void (*add_proposal_substructure) (sa_payload_t *this,proposal_substructure_t *proposal); + + /** + * @brief Gets the proposals in this payload as a list. + * + * @return a list containing proposal_t s + */ + linked_list_t *(*get_proposals) (sa_payload_t *this); + + /** + * @brief Add a child proposal (AH/ESP) to the payload. + * + * @param proposal child proposal to add to the payload + */ + void (*add_proposal) (sa_payload_t *this, proposal_t *proposal); + + /** + * @brief Destroys an sa_payload_t object. + * + * @param this sa_payload_t object to destroy + */ + void (*destroy) (sa_payload_t *this); +}; + +/** + * @brief Creates an empty sa_payload_t object + * + * @return created sa_payload_t object + * + * @ingroup payloads + */ +sa_payload_t *sa_payload_create(void); + +/** + * @brief Creates a sa_payload_t object from a list of proposals. + * + * @param proposals list of proposals to build the payload from + * @return sa_payload_t object + * + * @ingroup payloads + */ +sa_payload_t *sa_payload_create_from_proposal_list(linked_list_t *proposals); + +/** + * @brief Creates a sa_payload_t object from a single proposal. + * + * This is only for convenience. Use sa_payload_create_from_proposal_list + * if you want to add more than one proposal. + * + * @param proposal proposal from which the payload should be built. + * @return sa_payload_t object + * + * @ingroup payloads + */ +sa_payload_t *sa_payload_create_from_proposal(proposal_t *proposal); + +#endif /*SA_PAYLOAD_H_*/ diff --git a/src/charon/encoding/payloads/traffic_selector_substructure.c b/src/charon/encoding/payloads/traffic_selector_substructure.c new file mode 100644 index 000000000..c1a461e8a --- /dev/null +++ b/src/charon/encoding/payloads/traffic_selector_substructure.c @@ -0,0 +1,374 @@ +/** + * @file traffic_selector_substructure.c + * + * @brief Interface of traffic_selector_substructure_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 "traffic_selector_substructure.h" + +#include +#include + +/** + * String mappings for ts_type_t. + */ +mapping_t ts_type_m[] = { + {TS_IPV4_ADDR_RANGE, "TS_IPV4_ADDR_RANGE"}, + {TS_IPV6_ADDR_RANGE, "TS_IPV6_ADDR_RANGE"}, + {MAPPING_END, NULL} +}; + + +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. + */ + traffic_selector_substructure_t public; + + /** + * Type of traffic selector. + */ + u_int8_t ts_type; + + /** + * IP Protocol ID. + */ + u_int8_t ip_protocol_id; + + /** + * Length of this payload. + */ + u_int16_t payload_length; + + /** + * Start port number. + */ + u_int16_t start_port; + + /** + * End port number. + */ + u_int16_t end_port; + + /** + * Starting address. + */ + chunk_t starting_address; + + /** + * Ending address. + */ + chunk_t ending_address; + + /** + * update length + */ + void (*compute_length) (private_traffic_selector_substructure_t *this); +}; + +/** + * Encoding rules to parse or generate a TS payload + * + * 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) }, + /* 1 Byte 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) }, + /* 2 Byte 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) }, + /* ending address is either 4 or 16 byte */ + { ADDRESS, offsetof(private_traffic_selector_substructure_t, ending_address) } + +}; + +/* + 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 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! TS Type !IP Protocol ID*| Selector Length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Start Port* | End Port* | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! ! + ~ Starting Address* ~ + ! ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! ! + ~ Ending Address* ~ + ! ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ + +/** + * Implementation of payload_t.verify. + */ +static status_t verify(private_traffic_selector_substructure_t *this) +{ + + if (this->start_port > this->end_port) + { + return FAILED; + } + switch (this->ts_type) + { + case TS_IPV4_ADDR_RANGE: + { + if ((this->starting_address.len != 4) || + (this->ending_address.len != 4)) + { + /* ipv4 address must be 4 bytes long */ + return FAILED; + } + break; + } + case TS_IPV6_ADDR_RANGE: + default: + { + /* not supported ts type */ + return FAILED; + } + } + + + 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) +{ + *rules = traffic_selector_substructure_encodings; + *rule_count = sizeof(traffic_selector_substructure_encodings) / sizeof(encoding_rule_t); +} + +/** + * Implementation of payload_t.get_type. + */ +static payload_type_t get_payload_type(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) +{ + return 0; +} + +/** + * Implementation of payload_t.set_next_type. + */ +static void set_next_type(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) +{ + return this->payload_length; +} + +/** + * Implementation of traffic_selector_substructure_t.get_ts_type. + */ +static ts_type_t get_ts_type (private_traffic_selector_substructure_t *this) +{ + return this->ts_type; +} + +/** + * Implementation of traffic_selector_substructure_t.set_ts_type. + */ +static void set_ts_type (private_traffic_selector_substructure_t *this,ts_type_t ts_type) +{ + this->ts_type = ts_type; +} + +/** + * Implementation of traffic_selector_substructure_t.get_protocol_id. + */ +static u_int8_t get_protocol_id (private_traffic_selector_substructure_t *this) +{ + return this->ip_protocol_id; +} + +/** + * Implementation of traffic_selector_substructure_t.set_protocol_id. + */ +static void set_protocol_id (private_traffic_selector_substructure_t *this,u_int8_t protocol_id) +{ + this->ip_protocol_id = protocol_id; +} + +/** + * Implementation of traffic_selector_substructure_t.get_start_host. + */ +static host_t * get_start_host (private_traffic_selector_substructure_t *this) +{ + return (host_create_from_chunk(AF_INET,this->starting_address, this->start_port)); +} + +/** + * Implementation of traffic_selector_substructure_t.set_start_host. + */ +static void set_start_host (private_traffic_selector_substructure_t *this,host_t *start_host) +{ + this->start_port = start_host->get_port(start_host); + if (this->starting_address.ptr != NULL) + { + chunk_free(&(this->starting_address)); + } + this->starting_address = start_host->get_address_as_chunk(start_host); + this->compute_length(this); +} + +/** + * Implementation of traffic_selector_substructure_t.get_end_host. + */ +static host_t *get_end_host (private_traffic_selector_substructure_t *this) +{ + return (host_create_from_chunk(AF_INET,this->ending_address, this->end_port)); +} + +/** + * Implementation of traffic_selector_substructure_t.set_end_host. + */ +static void set_end_host (private_traffic_selector_substructure_t *this,host_t *end_host) +{ + this->end_port = end_host->get_port(end_host); + if (this->ending_address.ptr != NULL) + { + chunk_free(&(this->ending_address)); + } + this->ending_address = end_host->get_address_as_chunk(end_host); + this->compute_length(this); +} + +/** + * Implementation of traffic_selector_substructure_t.get_traffic_selector. + */ +static traffic_selector_t *get_traffic_selector(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; +} + +/** + * Implementation of private_ts_payload_t.compute_length + */ +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) +{ + free(this->starting_address.ptr); + free(this->ending_address.ptr); + free(this); +} + +/* + * Described in header + */ +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.destroy = (void (*) (traffic_selector_substructure_t *)) destroy; + this->public.get_ts_type = (ts_type_t (*) (traffic_selector_substructure_t *)) get_ts_type; + this->public.set_ts_type = (void (*) (traffic_selector_substructure_t *,ts_type_t)) set_ts_type; + this->public.get_protocol_id = (u_int8_t (*) (traffic_selector_substructure_t *)) get_protocol_id; + this->public.set_protocol_id = (void (*) (traffic_selector_substructure_t *,u_int8_t)) set_protocol_id; + this->public.get_start_host = (host_t * (*) (traffic_selector_substructure_t *))get_start_host; + this->public.set_start_host = (void (*) (traffic_selector_substructure_t *, host_t *))set_start_host; + this->public.get_end_host = (host_t * (*) (traffic_selector_substructure_t *))get_end_host; + this->public.set_end_host = (void (*) (traffic_selector_substructure_t *, host_t *))set_end_host; + this->public.get_traffic_selector = (traffic_selector_t* (*)(traffic_selector_substructure_t*))get_traffic_selector; + + /* private functions */ + this->compute_length = compute_length; + + /* private variables */ + this->payload_length = TRAFFIC_SELECTOR_HEADER_LENGTH; + this->start_port = 0; + this->end_port = 0; + this->starting_address = CHUNK_INITIALIZER; + this->ending_address = CHUNK_INITIALIZER; + this->ip_protocol_id = 0; + /* must be set to be valid */ + this->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) +{ + 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 = traffic_selector->get_from_address(traffic_selector); + this->ending_address = traffic_selector->get_to_address(traffic_selector); + + this->compute_length(this); + + return &(this->public); +} diff --git a/src/charon/encoding/payloads/traffic_selector_substructure.h b/src/charon/encoding/payloads/traffic_selector_substructure.h new file mode 100644 index 000000000..65b61dccf --- /dev/null +++ b/src/charon/encoding/payloads/traffic_selector_substructure.h @@ -0,0 +1,171 @@ +/** + * @file traffic_selector_substructure.h + * + * @brief Interface of traffic_selector_substructure_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + + +#ifndef TRAFFIC_SELECTOR_SUBSTRUCTURE_H_ +#define TRAFFIC_SELECTOR_SUBSTRUCTURE_H_ + +#include +#include +#include +#include + +/** + * Length of a TRAFFIC SELECTOR SUBSTRUCTURE without start and end address. + * + * @ingroup payloads + */ +#define TRAFFIC_SELECTOR_HEADER_LENGTH 8 + +typedef struct traffic_selector_substructure_t traffic_selector_substructure_t; + +/** + * @brief Class representing an IKEv2 TRAFFIC SELECTOR. + * + * The TRAFFIC SELECTOR format is described in RFC section 3.13.1. + * + * @b Constructors: + * - traffic_selector_substructure_create() + * - traffic_selector_substructure_create_from_traffic_selector() + * + * @ingroup payloads + */ +struct traffic_selector_substructure_t { + /** + * The payload_t interface. + */ + payload_t payload_interface; + + /** + * @brief Get the type of Traffic selector. + * + * @param this calling traffic_selector_substructure_t object + * @return type of traffic selector + * + */ + ts_type_t (*get_ts_type) (traffic_selector_substructure_t *this); + + /** + * @brief Set the type of Traffic selector. + * + * @param this calling traffic_selector_substructure_t object + * @param ts_type type of traffic selector + */ + void (*set_ts_type) (traffic_selector_substructure_t *this,ts_type_t ts_type); + + /** + * @brief Get the IP protocol ID of Traffic selector. + * + * @param this calling traffic_selector_substructure_t object + * @return type of traffic selector + * + */ + u_int8_t (*get_protocol_id) (traffic_selector_substructure_t *this); + + /** + * @brief Set the IP protocol ID of Traffic selector + * + * @param this calling traffic_selector_substructure_t object + * @param protocol_id protocol ID of traffic selector + */ + void (*set_protocol_id) (traffic_selector_substructure_t *this,u_int8_t protocol_id); + + /** + * @brief Get the start port and address as host_t object. + * + * Returned host_t object has to get destroyed by the caller. + * + * @param this calling traffic_selector_substructure_t object + * @return start host as host_t object + * + */ + host_t *(*get_start_host) (traffic_selector_substructure_t *this); + + /** + * @brief Set the start port and address as host_t object. + * + * @param this calling traffic_selector_substructure_t object + * @param start_host start host as host_t object + */ + void (*set_start_host) (traffic_selector_substructure_t *this,host_t *start_host); + + /** + * @brief Get the end port and address as host_t object. + * + * Returned host_t object has to get destroyed by the caller. + * + * @param this calling traffic_selector_substructure_t object + * @return end host as host_t object + * + */ + host_t *(*get_end_host) (traffic_selector_substructure_t *this); + + /** + * @brief Set the end port and address as host_t object. + * + * @param this calling traffic_selector_substructure_t object + * @param end_host end host as host_t object + */ + void (*set_end_host) (traffic_selector_substructure_t *this,host_t *end_host); + + /** + * @brief Get a traffic_selector_t from this substructure. + * + * @warning traffic_selector_t must be destroyed after usage. + * + * @param this calling traffic_selector_substructure_t object + * @return contained traffic_selector_t + */ + traffic_selector_t *(*get_traffic_selector) (traffic_selector_substructure_t *this); + + /** + * @brief Destroys an traffic_selector_substructure_t object. + * + * @param this traffic_selector_substructure_t object to destroy + */ + void (*destroy) (traffic_selector_substructure_t *this); +}; + +/** + * @brief Creates an empty traffic_selector_substructure_t object. + * + * TS type is set to default TS_IPV4_ADDR_RANGE! + * + * @return traffic_selector_substructure_t object + * + * @ingroup payloads + */ +traffic_selector_substructure_t *traffic_selector_substructure_create(void); + +/** + * @brief Creates an initialized traffif selector substructure using + * the values from a traffic_selector_t. + * + * @param traffic_selector traffic_selector_t to use for initialization + * @return traffic_selector_substructure_t object + * + * @ingroup payloads + */ +traffic_selector_substructure_t *traffic_selector_substructure_create_from_traffic_selector(traffic_selector_t *traffic_selector); + + +#endif /* /TRAFFIC_SELECTOR_SUBSTRUCTURE_H_ */ diff --git a/src/charon/encoding/payloads/transform_attribute.c b/src/charon/encoding/payloads/transform_attribute.c new file mode 100644 index 000000000..71cdd59e2 --- /dev/null +++ b/src/charon/encoding/payloads/transform_attribute.c @@ -0,0 +1,333 @@ +/** + * @file transform_attribute.c + * + * @brief Implementation of transform_attribute_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 +#include + +#include "transform_attribute.h" + +#include +#include + +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. + */ + transform_attribute_t public; + + /** + * Attribute Format Flag. + * + * - TRUE means value is stored in attribute_length_or_value + * - FALSE means value is stored in attribute_value + */ + bool attribute_format; + + /** + * Type of the attribute. + */ + u_int16_t attribute_type; + + /** + * Attribute Length if attribute_format is 0, attribute Value otherwise. + */ + u_int16_t attribute_length_or_value; + + /** + * Attribute value as chunk if attribute_format is 0 (FALSE). + */ + chunk_t attribute_value; +}; + +/** + * String mappings for transform_attribute_type_t. + */ +mapping_t transform_attribute_type_m[] = { + {ATTRIBUTE_UNDEFINED, "ATTRIBUTE_UNDEFINED"}, + {KEY_LENGTH, "KEY_LENGTH"}, + {MAPPING_END, NULL} +}; + +/** + * Encoding rules to parse or generate a Transform attribute. + * + * The defined offsets are the positions in a object of type + * private_transform_attribute_t. + * + */ +encoding_rule_t transform_attribute_encodings[] = { + /* Flag defining the format of this payload */ + { ATTRIBUTE_FORMAT, offsetof(private_transform_attribute_t, attribute_format) }, + /* type of the attribute as 15 bit unsigned integer */ + { ATTRIBUTE_TYPE, offsetof(private_transform_attribute_t, attribute_type) }, + /* Length or value, depending on the attribute format flag */ + { ATTRIBUTE_LENGTH_OR_VALUE, offsetof(private_transform_attribute_t, attribute_length_or_value) }, + /* Value of attribute if attribute format flag is zero */ + { ATTRIBUTE_VALUE, offsetof(private_transform_attribute_t, attribute_value) } +}; + +/* + 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + !A! Attribute Type ! AF=0 Attribute Length ! + !F! ! AF=1 Attribute Value ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! AF=0 Attribute Value ! + ! AF=1 Not Transmitted ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ + +/** + * Implementation of payload_t.verify. + */ +static status_t verify(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) +{ + *rules = transform_attribute_encodings; + *rule_count = sizeof(transform_attribute_encodings) / sizeof(encoding_rule_t); +} + +/** + * Implementation of payload_t.get_type. + */ +static payload_type_t get_type(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) +{ + return (NO_PAYLOAD); +} + +/** + * Implementation of payload_t.set_next_type. + */ +static void set_next_type(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) +{ + if (this->attribute_format == TRUE) + { + /*Attribute size is only 4 byte */ + return 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) +{ + if (this->attribute_value.ptr != NULL) + { + /* free existing value */ + free(this->attribute_value.ptr); + this->attribute_value.ptr = NULL; + this->attribute_value.len = 0; + + } + + if (value.len > 2) + { + this->attribute_value.ptr = clalloc(value.ptr,value.len); + this->attribute_value.len = value.len; + 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); + } +} + +/** + * Implementation of transform_attribute_t.set_value. + */ +static void set_value(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; + + } + this->attribute_length_or_value = value; +} + +/** + * Implementation of transform_attribute_t.get_value_chunk. + */ +static chunk_t get_value_chunk (private_transform_attribute_t *this) +{ + chunk_t value; + + if (this->attribute_format == FALSE) + { + value.ptr = this->attribute_value.ptr; + value.len = this->attribute_value.len; + } + else + { + value.ptr = (void *) &(this->attribute_length_or_value); + value.len = 2; + } + + return value; +} + +/** + * Implementation of transform_attribute_t.get_value. + */ +static u_int16_t get_value (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) +{ + 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) +{ + return this->attribute_type; +} + +/** + * Implementation of transform_attribute_t.clone. + */ +static transform_attribute_t * clone(private_transform_attribute_t *this) +{ + private_transform_attribute_t *new_clone; + + new_clone = (private_transform_attribute_t *) transform_attribute_create(); + + new_clone->attribute_format = this->attribute_format; + new_clone->attribute_type = this->attribute_type; + new_clone->attribute_length_or_value = this->attribute_length_or_value; + + if (!new_clone->attribute_format) + { + new_clone->attribute_value.ptr = clalloc(this->attribute_value.ptr,this->attribute_value.len); + new_clone->attribute_value.len = this->attribute_value.len; + } + + return (transform_attribute_t *) new_clone; +} + +/** + * Implementation of transform_attribute_t.destroy and payload_t.destroy. + */ +static void destroy(private_transform_attribute_t *this) +{ + if (this->attribute_value.ptr != NULL) + { + free(this->attribute_value.ptr); + } + free(this); +} + +/* + * Described in header. + */ +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)); +} + +/* + * Described in header. + */ +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); + return attribute; +} diff --git a/src/charon/encoding/payloads/transform_attribute.h b/src/charon/encoding/payloads/transform_attribute.h new file mode 100644 index 000000000..e2ac946f6 --- /dev/null +++ b/src/charon/encoding/payloads/transform_attribute.h @@ -0,0 +1,154 @@ +/** + * @file transform_attribute.h + * + * @brief Interface of transform_attribute_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef TRANSFORM_ATTRIBUTE_H_ +#define TRANSFORM_ATTRIBUTE_H_ + +#include +#include + + +typedef enum transform_attribute_type_t transform_attribute_type_t; + +/** + * Type of the attribute, as in IKEv2 RFC 3.3.5. + * + * @ingroup payloads + */ +enum transform_attribute_type_t { + ATTRIBUTE_UNDEFINED = 16384, + KEY_LENGTH = 14 +}; + +/** + * String mappings for transform_attribute_type_t. + * + * @ingroup payloads + */ +extern mapping_t transform_attribute_type_m[]; + +typedef struct transform_attribute_t transform_attribute_t; + +/** + * @brief Class representing an IKEv2- TRANSFORM Attribute. + * + * The TRANSFORM ATTRIBUTE format is described in RFC section 3.3.5. + * + * @ingroup payloads + */ +struct transform_attribute_t { + /** + * The payload_t interface. + */ + payload_t payload_interface; + + /** + * @brief Returns the currently set value of the attribute. + * + * @warning Returned data are not copied. + * + * @param this calling transform_attribute_t object + * @return chunk_t pointing to the value + */ + chunk_t (*get_value_chunk) (transform_attribute_t *this); + + /** + * @brief Returns the currently set value of the attribute. + * + * @warning Returned data are not copied. + * + * @param this calling transform_attribute_t object + * @return value + */ + u_int16_t (*get_value) (transform_attribute_t *this); + + /** + * @brief Sets the value of the attribute. + * + * @warning Value is getting copied. + * + * @param this calling transform_attribute_t object + * @param value chunk_t pointing to the value to set + */ + void (*set_value_chunk) (transform_attribute_t *this, chunk_t value); + + /** + * @brief Sets the value of the attribute. + * + * @param this calling transform_attribute_t object + * @param value value to set + */ + void (*set_value) (transform_attribute_t *this, u_int16_t value); + + /** + * @brief Sets the type of the attribute. + * + * @param this calling transform_attribute_t object + * @param type type to set (most significant bit is set to zero) + */ + void (*set_attribute_type) (transform_attribute_t *this, u_int16_t type); + + /** + * @brief get the type of the attribute. + * + * @param this calling transform_attribute_t object + * @return type of the value + */ + u_int16_t (*get_attribute_type) (transform_attribute_t *this); + + /** + * @brief Clones an transform_attribute_t object. + * + * @param this transform_attribute_t object to clone + * @return cloned transform_attribute_t object + */ + transform_attribute_t * (*clone) (transform_attribute_t *this); + + /** + * @brief Destroys an transform_attribute_t object. + * + * @param this transform_attribute_t object to destroy + */ + void (*destroy) (transform_attribute_t *this); +}; + +/** + * @brief Creates an empty transform_attribute_t object. + * + * @return transform_attribute_t object + * + * @ingroup payloads + */ +transform_attribute_t *transform_attribute_create(void); + +/** + * @brief Creates an transform_attribute_t of type KEY_LENGTH. + * + * @param key_length key length in bytes + * @return transform_attribute_t object + * + * @ingroup payloads + */ +transform_attribute_t *transform_attribute_create_key_length(u_int16_t key_length); + + +#endif /*TRANSFORM_ATTRIBUTE_H_*/ diff --git a/src/charon/encoding/payloads/transform_substructure.c b/src/charon/encoding/payloads/transform_substructure.c new file mode 100644 index 000000000..350ad63e4 --- /dev/null +++ b/src/charon/encoding/payloads/transform_substructure.c @@ -0,0 +1,485 @@ +/** + * @file transform_substructure.h + * + * @brief Implementation of transform_substructure_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 + +#include "transform_substructure.h" + +#include +#include +#include +#include + + +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. + */ + transform_substructure_t public; + + /** + * Next payload type. + */ + u_int8_t next_payload; + + + /** + * Length of this payload. + */ + u_int16_t transform_length; + + + /** + * Type of the transform. + */ + u_int8_t transform_type; + + /** + * Transform ID. + */ + u_int16_t transform_id; + + /** + * Transforms Attributes are stored in a linked_list_t. + */ + linked_list_t *attributes; + + /** + * @brief Computes the length of this substructure. + * + * @param this calling private_transform_substructure_t object + */ + void (*compute_length) (private_transform_substructure_t *this); +}; + + +/** + * 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 }, + /* Length of the whole transform substructure*/ + { PAYLOAD_LENGTH, offsetof(private_transform_substructure_t, transform_length) }, + /* transform type is a number of 8 bit */ + { U_INT_8, offsetof(private_transform_substructure_t, transform_type) }, + /* Reserved Byte is skipped */ + { RESERVED_BYTE, 0 }, + /* tranform ID is a number of 8 bit */ + { U_INT_16, offsetof(private_transform_substructure_t, transform_id) }, + /* Attributes are stored in a transform attribute, + offset points to a linked_list_t pointer */ + { TRANSFORM_ATTRIBUTES, offsetof(private_transform_substructure_t, attributes) } +}; + +/* + 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 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! 0 (last) or 3 ! RESERVED ! Transform Length ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + !Transform Type ! RESERVED ! Transform ID ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! ! + ~ Transform Attributes ~ + ! ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ + + +/** + * Implementation of payload_t.verify. + */ +static status_t verify(private_transform_substructure_t *this) +{ + status_t status = SUCCESS; + iterator_t *iterator; + + if ((this->next_payload != NO_PAYLOAD) && (this->next_payload != 3)) + { + /* must be 0 or 3 */ + return FAILED; + } + + switch (this->transform_type) + { + case ENCRYPTION_ALGORITHM: + { + if ((this->transform_id < ENCR_DES_IV64) || (this->transform_id > ENCR_AES_CTR)) + { + return FAILED; + } + break; + } + case PSEUDO_RANDOM_FUNCTION: + { + if ((this->transform_id < PRF_HMAC_MD5) || (this->transform_id > PRF_AES128_CBC)) + { + return FAILED; + } + break; + } + case INTEGRITY_ALGORITHM: + { + if ((this->transform_id < AUTH_HMAC_MD5_96) || (this->transform_id > AUTH_AES_XCBC_96)) + { + return FAILED; + } + break; + } + case DIFFIE_HELLMAN_GROUP: + { + switch (this->transform_id) + { + case MODP_768_BIT: + case MODP_1024_BIT: + case MODP_1536_BIT: + case MODP_2048_BIT: + case MODP_3072_BIT: + case MODP_4096_BIT: + case MODP_6144_BIT: + case MODP_8192_BIT: + { + break; + } + default: + { + return FAILED; + } + } + + + break; + } + case EXTENDED_SEQUENCE_NUMBERS: + { + if ((this->transform_id != NO_EXT_SEQ_NUMBERS) && (this->transform_id != EXT_SEQ_NUMBERS)) + { + return FAILED; + } + break; + } + default: + { + /* not a supported transform type! */ + return FAILED; + } + } + iterator = this->attributes->create_iterator(this->attributes,TRUE); + + while(iterator->has_next(iterator)) + { + payload_t *current_attributes; + iterator->current(iterator,(void **)¤t_attributes); + + status = current_attributes->verify(current_attributes); + if (status != SUCCESS) + { + break; + } + } + + iterator->destroy(iterator); + + + /* 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) +{ + *rules = transform_substructure_encodings; + *rule_count = sizeof(transform_substructure_encodings) / sizeof(encoding_rule_t); +} + +/** + * Implementation of payload_t.get_type. + */ +static payload_type_t get_type(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) +{ + return (this->next_payload); +} + +/** + * Implementation of payload_t.get_length. + */ +static size_t get_length(private_transform_substructure_t *this) +{ + 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); + this->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) +{ +} + +/** + * Implementation of transform_substructure_t.set_transform_type. + */ +static void set_transform_type (private_transform_substructure_t *this,u_int8_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) +{ + 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) +{ + return this->transform_id; +} + +/** + * Implementation of private_transform_substructure_t.compute_length. + */ +static void compute_length (private_transform_substructure_t *this) +{ + iterator_t *iterator; + size_t length = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH; + iterator = this->attributes->create_iterator(this->attributes,TRUE); + while (iterator->has_next(iterator)) + { + payload_t * current_attribute; + iterator->current(iterator,(void **) ¤t_attribute); + length += current_attribute->get_length(current_attribute); + } + iterator->destroy(iterator); + + this->transform_length = length; +} + +/** + * Implementation of transform_substructure_t.clone. + */ +static transform_substructure_t *clone(private_transform_substructure_t *this) +{ + private_transform_substructure_t *new_clone; + iterator_t *attributes; + + new_clone = (private_transform_substructure_t *) transform_substructure_create(); + + new_clone->next_payload = this->next_payload; + new_clone->transform_type = this->transform_type; + new_clone->transform_id = this->transform_id; + + attributes = this->attributes->create_iterator(this->attributes,FALSE); + + while (attributes->has_next(attributes)) + { + transform_attribute_t *current_attribute; + transform_attribute_t *current_attribute_clone; + attributes->current(attributes,(void **) ¤t_attribute); + + current_attribute_clone = current_attribute->clone(current_attribute); + + new_clone->public.add_transform_attribute(&(new_clone->public),current_attribute_clone); + } + + attributes->destroy(attributes); + + return &(new_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) +{ + iterator_t *attributes; + + attributes = this->attributes->create_iterator(this->attributes,TRUE); + + while (attributes->has_next(attributes)) + { + transform_attribute_t *current_attribute; + attributes->current(attributes,(void **) ¤t_attribute); + + if (current_attribute->get_attribute_type(current_attribute) == KEY_LENGTH) + { + *key_length = current_attribute->get_value(current_attribute); + attributes->destroy(attributes); + return SUCCESS; + } + + } + attributes->destroy(attributes); + + return FAILED; +} + + +/** + * Implementation of transform_substructure_t.destroy and payload_t.destroy. + */ +static void destroy(private_transform_substructure_t *this) +{ + /* all proposals are getting destroyed */ + while (this->attributes->get_count(this->attributes) > 0) + { + transform_attribute_t *current_attribute; + this->attributes->remove_last(this->attributes,(void **)¤t_attribute); + current_attribute->destroy(current_attribute); + } + this->attributes->destroy(this->attributes); + + free(this); +} + +/* + * Described in header. + */ +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; + + /* private functions */ + this->compute_length = compute_length; + + /* 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)); +} + +/* + * 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_substructure_t *transform = transform_substructure_create(); + + transform->set_transform_type(transform,transform_type); + transform->set_transform_id(transform,transform_id); + + /* a keylength attribute is only created for AES encryption */ + if (transform_type == ENCRYPTION_ALGORITHM && + transform_id == ENCR_AES_CBC) + { + transform_attribute_t *attribute = transform_attribute_create_key_length(key_length); + transform->add_transform_attribute(transform,attribute); + } + + return transform; +} diff --git a/src/charon/encoding/payloads/transform_substructure.h b/src/charon/encoding/payloads/transform_substructure.h new file mode 100644 index 000000000..8aac55400 --- /dev/null +++ b/src/charon/encoding/payloads/transform_substructure.h @@ -0,0 +1,198 @@ +/** + * @file transform_substructure.h + * + * @brief Interface of transform_substructure_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef TRANSFORM_SUBSTRUCTURE_H_ +#define TRANSFORM_SUBSTRUCTURE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/** + * IKEv1 Value for a transform payload. + * + * @ingroup payloads + */ +#define TRANSFORM_TYPE_VALUE 3 + +/** + * Length of the transform substructure header in bytes. + * + * @ingroup payloads + */ +#define TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH 8 + + +typedef struct transform_substructure_t transform_substructure_t; + +/** + * @brief Class representing an IKEv2- TRANSFORM SUBSTRUCTURE. + * + * The TRANSFORM SUBSTRUCTURE format is described in RFC section 3.3.2. + * + * @ingroup payloads + */ +struct transform_substructure_t { + /** + * The payload_t interface. + */ + payload_t payload_interface; + + /** + * @brief Creates an iterator of stored transform_attribute_t objects. + * + * @warning The created iterator has to get destroyed by the caller! + * + * @warning When deleting an transform attribute using this iterator, + * the length of this transform substructure has to be refreshed + * by calling get_length()! + * + * @param this calling transform_substructure_t object + * @param[in] forward iterator direction (TRUE: front to end) + * @return created iterator_t object. + */ + iterator_t * (*create_transform_attribute_iterator) (transform_substructure_t *this, bool forward); + + /** + * @brief Adds a transform_attribute_t object to this object. + * + * @warning The added proposal_substructure_t object is + * getting destroyed in destroy function of transform_substructure_t. + * + * @param this calling transform_substructure_t object + * @param proposal transform_attribute_t object to add + */ + void (*add_transform_attribute) (transform_substructure_t *this,transform_attribute_t *attribute); + + /** + * @brief Sets the next_payload field of this substructure + * + * If this is the last transform, next payload field is set to 0, + * otherwise to 3 + * + * @param this calling transform_substructure_t object + * @param is_last When TRUE, next payload field is set to 0, otherwise to 3 + */ + void (*set_is_last_transform) (transform_substructure_t *this, bool is_last); + + /** + * @brief Checks if this is the last transform. + * + * @param this calling transform_substructure_t object + * @return TRUE if this is the last Transform, FALSE otherwise + */ + bool (*get_is_last_transform) (transform_substructure_t *this); + + /** + * @brief Sets transform type of the current transform substructure. + * + * @param this calling transform_substructure_t object + * @param type type value to set + */ + void (*set_transform_type) (transform_substructure_t *this,u_int8_t type); + + /** + * @brief get transform type of the current transform. + * + * @param this calling transform_substructure_t object + * @return Transform type of current transform substructure. + */ + u_int8_t (*get_transform_type) (transform_substructure_t *this); + + /** + * @brief Sets transform id of the current transform substructure. + * + * @param this calling transform_substructure_t object + * @param id transform id to set + */ + void (*set_transform_id) (transform_substructure_t *this,u_int16_t id); + + /** + * @brief get transform id of the current transform. + * + * @param this calling transform_substructure_t object + * @return Transform id of current transform substructure. + */ + u_int16_t (*get_transform_id) (transform_substructure_t *this); + + /** + * @brief get transform id of the current transform. + * + * @param this calling transform_substructure_t object + * @param key_length The key length is written to this location + * @return + * - SUCCESS if a key length attribute is contained + * - FAILED if no key length attribute is part of this + * transform or key length uses more then 16 bit! + */ + status_t (*get_key_length) (transform_substructure_t *this,u_int16_t *key_length); + + /** + * @brief Clones an transform_substructure_t object. + * + * @param this transform_substructure_t object to clone + * @return cloned transform_substructure_t object + */ + transform_substructure_t* (*clone) (transform_substructure_t *this); + + /** + * @brief Destroys an transform_substructure_t object. + * + * @param this transform_substructure_t object to destroy + */ + void (*destroy) (transform_substructure_t *this); +}; + +/** + * @brief Creates an empty transform_substructure_t object. + * + * @return created transform_substructure_t object + * + * @ingroup payloads + */ +transform_substructure_t *transform_substructure_create(void); + +/** + * @brief 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 + * + * @ingroup payloads + */ +transform_substructure_t *transform_substructure_create_type(transform_type_t transform_type, u_int16_t transform_id, u_int16_t key_length); + +#endif /*TRANSFORM_SUBSTRUCTURE_H_*/ diff --git a/src/charon/encoding/payloads/ts_payload.c b/src/charon/encoding/payloads/ts_payload.c new file mode 100644 index 000000000..58772e666 --- /dev/null +++ b/src/charon/encoding/payloads/ts_payload.c @@ -0,0 +1,365 @@ +/** + * @file ts_payload.c + * + * @brief Implementation of ts_payload_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 + +#include "ts_payload.h" + +#include +#include + +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. + */ + ts_payload_t public; + + /** + * TRUE if this TS payload is of type TSi, FALSE for TSr. + */ + bool is_initiator; + + /** + * Next payload type. + */ + u_int8_t next_payload; + + /** + * Critical flag. + */ + bool critical; + + /** + * Length of this payload. + */ + u_int16_t payload_length; + + /** + * Number of traffic selectors + */ + u_int8_t number_of_traffic_selectors; + + /** + * Contains the traffic selectors of type traffic_selector_substructure_t. + */ + linked_list_t *traffic_selectors; + + /** + * @brief Computes the length of this payload. + * + * @param this calling private_ts_payload_t object + */ + void (*compute_length) (private_ts_payload_t *this); +}; + +/** + * Encoding rules to parse or generate a TS payload + * + * 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) }, + /* 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 }, + /* Length of the whole payload*/ + { 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) }, + /* 3 reserved bytes */ + { RESERVED_BYTE, 0 }, + { RESERVED_BYTE, 0 }, + { RESERVED_BYTE, 0 }, + /* some ts data bytes, length is defined in PAYLOAD_LENGTH */ + { TRAFFIC_SELECTORS, offsetof(private_ts_payload_t, traffic_selectors) } +}; + +/* + 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! Next Payload !C! RESERVED ! Payload Length ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! Number of TSs ! RESERVED ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! ! + ~ ~ + ! ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ + +/** + * Implementation of payload_t.verify. + */ +static status_t verify(private_ts_payload_t *this) +{ + iterator_t *iterator; + status_t status = SUCCESS; + + if (this->number_of_traffic_selectors != (this->traffic_selectors->get_count(this->traffic_selectors))) + { + /* must be the same */ + return FAILED; + } + + iterator = this->traffic_selectors->create_iterator(this->traffic_selectors,TRUE); + while(iterator->has_next(iterator)) + { + payload_t *current_traffic_selector; + iterator->current(iterator,(void **)¤t_traffic_selector); + + status = current_traffic_selector->verify(current_traffic_selector); + if (status != SUCCESS) + { + break; + } + } + iterator->destroy(iterator); + + 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) +{ + *rules = ts_payload_encodings; + *rule_count = sizeof(ts_payload_encodings) / sizeof(encoding_rule_t); +} + +/** + * Implementation of payload_t.get_type. + */ +static payload_type_t get_payload_type(private_ts_payload_t *this) +{ + if (this->is_initiator) + { + return TRAFFIC_SELECTOR_INITIATOR; + } + else + { + return TRAFFIC_SELECTOR_RESPONDER; + } +} + +/** + * Implementation of payload_t.get_next_type. + */ +static payload_type_t get_next_type(private_ts_payload_t *this) +{ + 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) +{ + this->next_payload = type; +} + +/** + * Implementation of payload_t.get_length. + */ +static size_t get_length(private_ts_payload_t *this) +{ + this->compute_length(this); + return this->payload_length; +} + +/** + * Implementation of ts_payload_t.get_initiator. + */ +static bool get_initiator (private_ts_payload_t *this) +{ + return (this->is_initiator); +} + +/** + * Implementation of ts_payload_t.set_initiator. + */ +static void set_initiator (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) +{ + traffic_selector_t *ts; + iterator_t *iterator; + linked_list_t *ts_list = linked_list_create(); + + iterator = this->traffic_selectors->create_iterator(this->traffic_selectors, TRUE); + while (iterator->has_next(iterator)) + { + traffic_selector_substructure_t *ts_substructure; + iterator->current(iterator, (void**)&ts_substructure); + ts = ts_substructure->get_traffic_selector(ts_substructure); + ts_list->insert_last(ts_list, (void*)ts); + } + iterator->destroy(iterator); + + return ts_list; +} + +/** + * Implementation of private_ts_payload_t.compute_length. + */ +static void compute_length (private_ts_payload_t *this) +{ + iterator_t *iterator; + size_t ts_count = 0; + size_t length = TS_PAYLOAD_HEADER_LENGTH; + iterator = this->traffic_selectors->create_iterator(this->traffic_selectors,TRUE); + while (iterator->has_next(iterator)) + { + payload_t * current_traffic_selector; + iterator->current(iterator,(void **) ¤t_traffic_selector); + length += current_traffic_selector->get_length(current_traffic_selector); + ts_count++; + } + iterator->destroy(iterator); + + this->number_of_traffic_selectors= ts_count; + this->payload_length = length; + +} + + +/** + * Implementation of payload_t.destroy and ts_payload_t.destroy. + */ +static void destroy(private_ts_payload_t *this) +{ + while (this->traffic_selectors->get_count(this->traffic_selectors) > 0) + { + payload_t *current_traffic_selector; + + this->traffic_selectors->remove_last(this->traffic_selectors,(void **) ¤t_traffic_selector); + + current_traffic_selector->destroy(current_traffic_selector); + } + + this->traffic_selectors->destroy(this->traffic_selectors); + + free(this); +} + +/* + * Described in header + */ +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 functions */ + this->compute_length = compute_length; + + /* 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(); + + return &(this->public); +} + +/* + * Described in header + */ +ts_payload_t *ts_payload_create_from_traffic_selectors(bool is_initiator, linked_list_t *traffic_selectors) +{ + iterator_t *iterator; + traffic_selector_t *ts; + traffic_selector_substructure_t *ts_substructure; + 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->has_next(iterator)) + { + iterator->current(iterator, (void**)&ts); + ts_substructure = traffic_selector_substructure_create_from_traffic_selector(ts); + this->public.add_traffic_selector_substructure(&(this->public), ts_substructure); + } + iterator->destroy(iterator); + + return &(this->public); +} + diff --git a/src/charon/encoding/payloads/ts_payload.h b/src/charon/encoding/payloads/ts_payload.h new file mode 100644 index 000000000..775ff6134 --- /dev/null +++ b/src/charon/encoding/payloads/ts_payload.h @@ -0,0 +1,152 @@ +/** + * @file ts_payload.h + * + * @brief Interface of ts_payload_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + + +#ifndef TS_PAYLOAD_H_ +#define TS_PAYLOAD_H_ + +#include +#include +#include +#include +#include + +/** + * Length of a TS payload without the Traffic selectors. + * + * @ingroup payloads + */ +#define TS_PAYLOAD_HEADER_LENGTH 8 + + +typedef struct ts_payload_t ts_payload_t; + +/** + * @brief Class representing an IKEv2 TS payload. + * + * The TS payload format is described in RFC section 3.13. + * + * @b Constructors: + * - ts_payload_create() + * - ts_payload_create_from_traffic_selectors() + * + * @ingroup payloads + */ +struct ts_payload_t { + /** + * The payload_t interface. + */ + payload_t payload_interface; + + /** + * @brief Get the type of TSpayload (TSi or TSr). + * + * @param this calling id_payload_t object + * @return + * - TRUE if this payload is of type TSi + * - FALSE if this payload is of type TSr + */ + bool (*get_initiator) (ts_payload_t *this); + + /** + * @brief Set the type of TS payload (TSi or TSr). + * + * @param this calling id_payload_t object + * @param is_initiator + * - TRUE if this payload is of type TSi + * - FALSE if this payload is of type TSr + */ + void (*set_initiator) (ts_payload_t *this,bool is_initiator); + + /** + * @brief Adds a traffic_selector_substructure_t object to this object. + * + * @warning The added traffic_selector_substructure_t object is + * getting destroyed in destroy function of ts_payload_t. + * + * @param this calling ts_payload_t 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); + + /** + * @brief Creates an iterator of stored traffic_selector_substructure_t objects. + * + * @warning The created iterator has to get destroyed by the caller! + * + * @warning 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 this calling ts_payload_t object + * @param[in] 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); + + /** + * @brief Get a list of nested traffic selectors as traffic_selector_t. + * + * Resulting list and its traffic selectors must be destroyed after usage + * + * @param this calling ts_payload_t object + * @return list of traffic selectors + */ + linked_list_t *(*get_traffic_selectors) (ts_payload_t *this); + + /** + * @brief Destroys an ts_payload_t object. + * + * @param this ts_payload_t object to destroy + */ + void (*destroy) (ts_payload_t *this); +}; + +/** + * @brief 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 + * + * @ingroup payloads + */ +ts_payload_t *ts_payload_create(bool is_initiator); + +/** + * @brief 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 traffic_selectors list of traffic selectors to include + * @return ts_payload_t object + * + * @ingroup payloads + */ +ts_payload_t *ts_payload_create_from_traffic_selectors(bool is_initiator, linked_list_t *traffic_selectors); + + +#endif /* TS_PAYLOAD_H_ */ diff --git a/src/charon/encoding/payloads/unknown_payload.c b/src/charon/encoding/payloads/unknown_payload.c new file mode 100644 index 000000000..25bb37d59 --- /dev/null +++ b/src/charon/encoding/payloads/unknown_payload.c @@ -0,0 +1,207 @@ +/** + * @file unknown_payload.c + * + * @brief Implementation of unknown_payload_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 + +#include "unknown_payload.h" + + + +typedef struct private_unknown_payload_t private_unknown_payload_t; + +/** + * Private data of an unknown_payload_t object. + */ +struct private_unknown_payload_t { + + /** + * Public unknown_payload_t interface. + */ + unknown_payload_t public; + + /** + * Next payload type. + */ + u_int8_t next_payload; + + /** + * Critical flag. + */ + bool critical; + + /** + * Length of this payload. + */ + u_int16_t payload_length; + + /** + * The contained data. + */ + chunk_t data; +}; + +/** + * Encoding rules to parse an payload which is not further specified. + * + * The defined offsets are the positions in a object of type + * 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)}, + /* 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 }, + /* Length of the whole payload*/ + { PAYLOAD_LENGTH, offsetof(private_unknown_payload_t, payload_length)}, + /* some unknown data bytes, length is defined in PAYLOAD_LENGTH */ + { UNKNOWN_DATA, offsetof(private_unknown_payload_t, data) } +}; + +/* + 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! Next Payload !C! RESERVED ! Payload Length ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! ! + ~ Data of any type ~ + ! ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ + +/** + * Implementation of payload_t.verify. + */ +static status_t verify(private_unknown_payload_t *this) +{ + /* can't do any checks, so we assume its good */ + 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) +{ + *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) +{ + return UNKNOWN_PAYLOAD; +} + +/** + * Implementation of payload_t.get_next_type. + */ +static payload_type_t get_next_type(private_unknown_payload_t *this) +{ + 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) +{ + this->next_payload = type; +} + +/** + * Implementation of payload_t.get_length. + */ +static size_t get_length(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) +{ + return this->critical; +} + +/** + * Implementation of unknown_payload_t.get_data. + */ +static chunk_t get_data (private_unknown_payload_t *this) +{ + return (this->data); +} + +/** + * Implementation of payload_t.destroy and unknown_payload_t.destroy. + */ +static void destroy(private_unknown_payload_t *this) +{ + if (this->data.ptr != NULL) + { + chunk_free(&(this->data)); + } + + free(this); +} + +/* + * Described in header + */ +unknown_payload_t *unknown_payload_create() +{ + 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_INITIALIZER; + + return (&(this->public)); +} diff --git a/src/charon/encoding/payloads/unknown_payload.h b/src/charon/encoding/payloads/unknown_payload.h new file mode 100644 index 000000000..56cdd5677 --- /dev/null +++ b/src/charon/encoding/payloads/unknown_payload.h @@ -0,0 +1,95 @@ +/** + * @file unknown_payload.h + * + * @brief Interface of unknown_payload_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef UNKNOWN_PAYLOAD_H_ +#define UNKNOWN_PAYLOAD_H_ + +#include +#include + +/** + * Header length of the unknown payload. + * + * @ingroup payloads + */ +#define UNKNOWN_PAYLOAD_HEADER_LENGTH 4 + + +typedef struct unknown_payload_t unknown_payload_t; + +/** + * @brief Payload which can't be processed further. + * + * When the parser finds an unknown payload, he builds an instance of + * this class. This allows further processing of this payload, such as + * a check for the critical bit in the header. + * + * @b Constructors: + * - unknown_payload_create() + * + * @ingroup payloads + */ +struct unknown_payload_t { + + /** + * The payload_t interface. + */ + payload_t payload_interface; + + /** + * @brief Get the raw data of this payload, without + * the generic payload header. + * + * Returned data are NOT copied and must not be freed. + * + * @param this calling unknown_payload_t object + * @return data as chunk_t + */ + chunk_t (*get_data) (unknown_payload_t *this); + + /** + * @brief Get the critical flag. + * + * @param this calling unknown_payload_t object + * @return TRUE if payload is critical, FALSE if not + */ + bool (*is_critical) (unknown_payload_t *this); + + /** + * @brief Destroys an unknown_payload_t object. + * + * @param this unknown_payload_t object to destroy + */ + void (*destroy) (unknown_payload_t *this); +}; + +/** + * @brief Creates an empty unknown_payload_t object. + * + * @return unknown_payload_t object + * + * @ingroup payloads + */ +unknown_payload_t *unknown_payload_create(void); + + +#endif /* UNKNOWN_PAYLOAD_H_ */ diff --git a/src/charon/encoding/payloads/vendor_id_payload.c b/src/charon/encoding/payloads/vendor_id_payload.c new file mode 100644 index 000000000..436b82d79 --- /dev/null +++ b/src/charon/encoding/payloads/vendor_id_payload.c @@ -0,0 +1,227 @@ +/** + * @file vendor_id_payload.c + * + * @brief Implementation of vendor_id_payload_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 + +#include "vendor_id_payload.h" + + +typedef struct private_vendor_id_payload_t private_vendor_id_payload_t; + +/** + * Private data of an vendor_id_payload_t object. + * + */ +struct private_vendor_id_payload_t { + /** + * Public vendor_id_payload_t interface. + */ + vendor_id_payload_t public; + + /** + * Next payload type. + */ + u_int8_t next_payload; + + /** + * Critical flag. + */ + bool critical; + + /** + * Length of this payload. + */ + u_int16_t payload_length; + + /** + * The contained vendor_id data value. + */ + chunk_t vendor_id_data; +}; + +/** + * Encoding rules to parse or generate a VENDOR ID payload + * + * The defined offsets are the positions in a object of type + * 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) }, + /* 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 }, + /* 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, vendor_id_data) } +}; + +/* + 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! Next Payload !C! RESERVED ! Payload Length ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! Cert Encoding ! ! + +-+-+-+-+-+-+-+-+ ! + ~ Certificate Data ~ + ! ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ + +/** + * Implementation of payload_t.verify. + */ +static status_t verify(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) +{ + *rules = vendor_id_payload_encodings; + *rule_count = sizeof(vendor_id_payload_encodings) / sizeof(encoding_rule_t); +} + +/** + * Implementation of payload_t.get_type. + */ +static payload_type_t get_payload_type(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) +{ + 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) +{ + this->next_payload = type; +} + +/** + * Implementation of payload_t.get_length. + */ +static size_t get_length(private_vendor_id_payload_t *this) +{ + return this->payload_length; +} + +/** + * Implementation of vendor_id_payload_t.set_data. + */ +static void set_data (private_vendor_id_payload_t *this, chunk_t data) +{ + if (this->vendor_id_data.ptr != NULL) + { + chunk_free(&(this->vendor_id_data)); + } + this->vendor_id_data.ptr = clalloc(data.ptr,data.len); + this->vendor_id_data.len = data.len; + this->payload_length = VENDOR_ID_PAYLOAD_HEADER_LENGTH + this->vendor_id_data.len; +} + +/** + * Implementation of vendor_id_payload_t.get_data. + */ +static chunk_t get_data (private_vendor_id_payload_t *this) +{ + return (this->vendor_id_data); +} + +/** + * Implementation of vendor_id_payload_t.get_data_clone. + */ +static chunk_t get_data_clone (private_vendor_id_payload_t *this) +{ + chunk_t cloned_data; + if (this->vendor_id_data.ptr == NULL) + { + return (this->vendor_id_data); + } + cloned_data.ptr = clalloc(this->vendor_id_data.ptr,this->vendor_id_data.len); + cloned_data.len = this->vendor_id_data.len; + return cloned_data; +} + +/** + * Implementation of payload_t.destroy and vendor_id_payload_t.destroy. + */ +static void destroy(private_vendor_id_payload_t *this) +{ + if (this->vendor_id_data.ptr != NULL) + { + chunk_free(&(this->vendor_id_data)); + } + free(this); +} + +/* + * Described in header + */ +vendor_id_payload_t *vendor_id_payload_create() +{ + private_vendor_id_payload_t *this = malloc_thing(private_vendor_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 (*) (vendor_id_payload_t *)) destroy; + this->public.set_data = (void (*) (vendor_id_payload_t *,chunk_t)) set_data; + this->public.get_data_clone = (chunk_t (*) (vendor_id_payload_t *)) get_data_clone; + this->public.get_data = (chunk_t (*) (vendor_id_payload_t *)) get_data; + + /* private variables */ + this->critical = FALSE; + this->next_payload = NO_PAYLOAD; + this->payload_length = VENDOR_ID_PAYLOAD_HEADER_LENGTH; + this->vendor_id_data = CHUNK_INITIALIZER; + + return (&(this->public)); +} diff --git a/src/charon/encoding/payloads/vendor_id_payload.h b/src/charon/encoding/payloads/vendor_id_payload.h new file mode 100644 index 000000000..1e4fdb510 --- /dev/null +++ b/src/charon/encoding/payloads/vendor_id_payload.h @@ -0,0 +1,103 @@ +/** + * @file vendor_id_payload.h + * + * @brief Interface of vendor_id_payload_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef VENDOR_ID_PAYLOAD_H_ +#define VENDOR_ID_PAYLOAD_H_ + +#include +#include + +/** + * Length of a VENDOR ID payload without the VID data in bytes. + * + * @ingroup payloads + */ +#define VENDOR_ID_PAYLOAD_HEADER_LENGTH 4 + + +typedef struct vendor_id_payload_t vendor_id_payload_t; + +/** + * @brief Class representing an IKEv2 VENDOR ID payload. + * + * The VENDOR ID payload format is described in RFC section 3.12. + * + * @b Constructors: + * - vendor_id_payload_create() + * + * @ingroup payloads + */ +struct vendor_id_payload_t { + /** + * The payload_t interface. + */ + payload_t payload_interface; + + /** + * @brief Set the VID data. + * + * Data are getting cloned. + * + * @param this calling vendor_id_payload_t object + * @param data VID data as chunk_t + */ + void (*set_data) (vendor_id_payload_t *this, chunk_t data); + + /** + * @brief Get the VID data. + * + * Returned data are a copy of the internal one. + * + * @param this calling vendor_id_payload_t object + * @return VID data as chunk_t + */ + chunk_t (*get_data_clone) (vendor_id_payload_t *this); + + /** + * @brief Get the VID data. + * + * Returned data are NOT copied. + * + * @param this calling vendor_id_payload_t object + * @return VID data as chunk_t + */ + chunk_t (*get_data) (vendor_id_payload_t *this); + + /** + * @brief Destroys an vendor_id_payload_t object. + * + * @param this vendor_id_payload_t object to destroy + */ + void (*destroy) (vendor_id_payload_t *this); +}; + +/** + * @brief Creates an empty vendor_id_payload_t object. + * + * @return vendor_id_payload_t object + * + * @ingroup payloads + */ +vendor_id_payload_t *vendor_id_payload_create(void); + + +#endif /* VENDOR_ID_PAYLOAD_H_ */ diff --git a/src/charon/network/Makefile.network b/src/charon/network/Makefile.network new file mode 100644 index 000000000..fd99bd085 --- /dev/null +++ b/src/charon/network/Makefile.network @@ -0,0 +1,24 @@ +# Copyright (C) 2005 Jan Hutter, 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 . +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# + +NETWORK_DIR= $(CHARON_DIR)network/ + + +CHARON_OBJS+= $(BUILD_DIR)packet.o +$(BUILD_DIR)packet.o : $(NETWORK_DIR)packet.c $(NETWORK_DIR)packet.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)socket.o +$(BUILD_DIR)socket.o : $(NETWORK_DIR)socket.c $(NETWORK_DIR)socket.h + $(CC) $(CFLAGS) -c -o $@ $< \ No newline at end of file diff --git a/src/charon/network/packet.c b/src/charon/network/packet.c new file mode 100644 index 000000000..6aaeca190 --- /dev/null +++ b/src/charon/network/packet.c @@ -0,0 +1,189 @@ +/** + * @file packet.c + * + * @brief Implementation of packet_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + + +#include "packet.h" + + +typedef struct private_packet_t private_packet_t; + +/** + * Private data of an packet_t object. + */ +struct private_packet_t { + + /** + * Public part of a packet_t object. + */ + packet_t public; + + /** + * source address + */ + host_t *source; + + /** + * destination address + */ + host_t *destination; + + /** + * message data + */ + chunk_t data; +}; + +/** + * Implements packet_t.get_source + */ +static void set_source(private_packet_t *this, host_t *source) +{ + if (this->source) + { + this->source->destroy(this->source); + } + this->source = source; +} + +/** + * Implements packet_t.set_destination + */ +static void set_destination(private_packet_t *this, host_t *destination) +{ + if (this->destination) + { + this->destination->destroy(this->destination); + } + this->destination = destination; +} + +/** + * Implements packet_t.get_source + */ +static host_t *get_source(private_packet_t *this) +{ + return this->source; +} + +/** + * Implements packet_t.get_destination + */ +static host_t *get_destination(private_packet_t *this) +{ + return this->destination; +} + +/** + * Implements packet_t.get_data + */ +static chunk_t get_data(private_packet_t *this) +{ + return this->data; +} + +/** + * Implements packet_t.set_data + */ +static void set_data(private_packet_t *this, chunk_t data) +{ + free(this->data.ptr); + this->data = data; +} + +/** + * Implements packet_t.destroy. + */ +static void destroy(private_packet_t *this) +{ + if (this->source != NULL) + { + this->source->destroy(this->source); + } + if (this->destination != NULL) + { + this->destination->destroy(this->destination); + } + free(this->data.ptr); + free(this); +} + +/** + * Implements packet_t.clone. + */ +static packet_t *clone(private_packet_t *this) +{ + private_packet_t *other = (private_packet_t*)packet_create(); + + if (this->destination != NULL) + { + other->destination = this->destination->clone(this->destination); + } + else + { + other->destination = NULL; + } + + if (this->source != NULL) + { + other->source = this->source->clone(this->source); + } + else + { + other->source = NULL; + } + + /* only clone existing chunks :-) */ + if (this->data.ptr != NULL) + { + other->data.ptr = clalloc(this->data.ptr,this->data.len); + other->data.len = this->data.len; + } + else + { + other->data = CHUNK_INITIALIZER; + } + return &(other->public); +} + + +/* + * Documented in header + */ +packet_t *packet_create(void) +{ + private_packet_t *this = malloc_thing(private_packet_t); + + this->public.set_data = (void(*) (packet_t *,chunk_t)) set_data; + this->public.get_data = (chunk_t(*) (packet_t *)) get_data; + this->public.set_source = (void(*) (packet_t *,host_t*)) set_source; + this->public.get_source = (host_t*(*) (packet_t *)) get_source; + this->public.set_destination = (void(*) (packet_t *,host_t*)) set_destination; + this->public.get_destination = (host_t*(*) (packet_t *)) get_destination; + this->public.clone = (packet_t*(*) (packet_t *))clone; + this->public.destroy = (void(*) (packet_t *)) destroy; + + this->destination = NULL; + this->source = NULL; + this->data = CHUNK_INITIALIZER; + + return &(this->public); +} diff --git a/src/charon/network/packet.h b/src/charon/network/packet.h new file mode 100644 index 000000000..9510ecd87 --- /dev/null +++ b/src/charon/network/packet.h @@ -0,0 +1,135 @@ +/** + * @file packet.h + * + * @brief Interface of packet_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef PACKET_H_ +#define PACKET_H_ + + +#include +#include + + +typedef struct packet_t packet_t; + +/** + * @brief Abstraction of an UDP-Packet, contains data, sender and receiver. + * + * @b Constructors: + * - packet_create() + * + * @ingroup network + */ +struct packet_t { + + /** + * @brief Set the source address. + * + * Set host_t is now owned by packet_t, it will destroy + * it if necessary. + * + * @param this calling object + * @param source address to set as source + */ + void (*set_source) (packet_t *packet, host_t *source); + + /** + * @brief Set the destination address. + * + * Set host_t is now owned by packet_t, it will destroy + * it if necessary. + * + * @param this calling object + * @param source address to set as destination + */ + void (*set_destination) (packet_t *packet, host_t *destination); + + /** + * @brief Get the source address. + * + * Set host_t is still owned by packet_t, clone it + * if needed. + * + * @param this calling object + * @return source address + */ + host_t *(*get_source) (packet_t *packet); + + /** + * @brief Get the destination address. + * + * Set host_t is still owned by packet_t, clone it + * if needed. + * + * @param this calling object + * @return destination address + */ + host_t *(*get_destination) (packet_t *packet); + + /** + * @brief Get the data from the packet. + * + * The data pointed by the chunk is still owned + * by the packet. Clone it if needed. + * + * @param this calling object + * @return chunk containing the data + */ + chunk_t (*get_data) (packet_t *packet); + + /** + * @brief Set the data in the packet. + * + * Supplied chunk data is now owned by the + * packet. It will free it. + * + * @param this calling object + * @param data chunk with data to set + */ + void (*set_data) (packet_t *packet, chunk_t data); + + /** + * @brief Clones a packet_t object. + * + * @param packet calling object + * @param clone pointer to a packet_t object pointer where the new object is stored + */ + packet_t* (*clone) (packet_t *packet); + + /** + * @brief Destroy the packet, freeing contained data. + * + * @param packet packet to destroy + */ + void (*destroy) (packet_t *packet); +}; + +/** + * @brief create an empty packet + * + * @return packet_t object + * + * @ingroup network + */ +packet_t *packet_create(void); + + +#endif /*PACKET_H_*/ diff --git a/src/charon/network/socket.c b/src/charon/network/socket.c new file mode 100644 index 000000000..4193e6fd8 --- /dev/null +++ b/src/charon/network/socket.c @@ -0,0 +1,456 @@ +/** + * @file socket.c + * + * @brief Implementation of socket_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, Martin Willi + * Hochschule fuer Technik Rapperswil + * Copyright (C) 1998-2002 D. Hugh Redelmeier. + * Copyright (C) 1997 Angelos D. Keromytis. + * + * Some parts of interface lookup code from pluto. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "socket.h" + +#include +#include + + +#define IP_HEADER_LENGTH 20 +#define UDP_HEADER_LENGTH 8 + + +/** + * This filter code filters out all non-IKEv2 traffic on + * a SOCK_RAW IP_PROTP_UDP socket. Handling of other + * IKE versions is done in pluto. + */ +struct sock_filter ikev2_filter_code[] = +{ + /* Protocol must be UDP */ + BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 9), + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, IPPROTO_UDP, 0, 7), + /* Destination Port must be 500 */ + BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 22), + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 500, 0, 5), + /* IKE version must be 2.0 */ + BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 45), + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0x20, 0, 3), + /* packet length is length in IKEv2 header + ip header + udp header */ + BPF_STMT(BPF_LD+BPF_W+BPF_ABS, 52), + BPF_STMT(BPF_ALU+BPF_ADD+BPF_K, IP_HEADER_LENGTH + UDP_HEADER_LENGTH), + BPF_STMT(BPF_RET+BPF_A, 0), + /* packet doesn't match IKEv2, ignore */ + BPF_STMT(BPF_RET+BPF_K, 0), +}; + +/** + * Filter struct to use with setsockopt + */ +struct sock_fprog ikev2_filter = { + sizeof(ikev2_filter_code) / sizeof(struct sock_filter), + ikev2_filter_code +}; + + +typedef struct interface_t interface_t; + +/** + * An interface on which we listen. + */ +struct interface_t { + + /** + * Name of the interface + */ + char name[IFNAMSIZ]; + + /** + * Associated socket + */ + int socket_fd; + + /** + * Host with listening address + */ + host_t *address; +}; + +typedef struct private_socket_t private_socket_t; + +/** + * Private data of an socket_t object + */ +struct private_socket_t{ + /** + * public functions + */ + socket_t public; + + /** + * Master socket + */ + int master_fd; + + /** + * List of all socket to listen + */ + linked_list_t* interfaces; + + /** + * logger for this socket + */ + logger_t *logger; +}; + +/** + * implementation of socket_t.receive + */ +static status_t receiver(private_socket_t *this, packet_t **packet) +{ + char buffer[MAX_PACKET]; + chunk_t data; + packet_t *pkt = packet_create(); + host_t *source, *dest; + int bytes_read = 0; + + + while (bytes_read >= 0) + { + int max_fd = 1; + fd_set readfds; + iterator_t *iterator; + int oldstate; + interface_t *interface; + + /* build fd_set */ + FD_ZERO(&readfds); + iterator = this->interfaces->create_iterator(this->interfaces, TRUE); + while (iterator->has_next(iterator)) + { + iterator->current(iterator, (void**)&interface); + FD_SET(interface->socket_fd, &readfds); + if (interface->socket_fd > max_fd) + { + max_fd = interface->socket_fd + 1; + } + } + iterator->destroy(iterator); + + /* add packet destroy handler for cancellation, enable cancellation */ + pthread_cleanup_push((void(*)(void*))pkt->destroy, (void*)pkt); + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); + + this->logger->log(this->logger, CONTROL|LEVEL1, "waiting on sockets"); + bytes_read = select(max_fd, &readfds, NULL, NULL, NULL); + + /* reset cancellation, remove packet destroy handler (without executing) */ + pthread_setcancelstate(oldstate, NULL); + pthread_cleanup_pop(0); + + /* read on the first nonblocking socket */ + bytes_read = 0; + iterator = this->interfaces->create_iterator(this->interfaces, TRUE); + while (iterator->has_next(iterator)) + { + iterator->current(iterator, (void**)&interface); + if (FD_ISSET(interface->socket_fd, &readfds)) + { + /* do the read */ + bytes_read = recv(interface->socket_fd, buffer, MAX_PACKET, 0); + break; + } + } + iterator->destroy(iterator); + + if (bytes_read < 0) + { + this->logger->log(this->logger, ERROR, "error reading from socket: %s", strerror(errno)); + continue; + } + if (bytes_read > IP_HEADER_LENGTH + UDP_HEADER_LENGTH) + { + /* read source/dest from raw IP/UDP header */ + chunk_t source_chunk = {buffer + 12, 4}; + chunk_t dest_chunk = {buffer + 16, 4}; + u_int16_t source_port = ntohs(*(u_int16_t*)(buffer + 20)); + u_int16_t dest_port = ntohs(*(u_int16_t*)(buffer + 22)); + source = host_create_from_chunk(AF_INET, source_chunk, source_port); + dest = host_create_from_chunk(AF_INET, dest_chunk, dest_port); + pkt->set_source(pkt, source); + pkt->set_destination(pkt, dest); + break; + } + this->logger->log(this->logger, ERROR|LEVEL1, "too short packet received"); + } + + this->logger->log(this->logger, CONTROL, "received packet: from %s:%d to %s:%d", + source->get_address(source), source->get_port(source), + dest->get_address(dest), dest->get_port(dest)); + + /* fill in packet */ + data.len = bytes_read - IP_HEADER_LENGTH - UDP_HEADER_LENGTH; + data.ptr = malloc(data.len); + memcpy(data.ptr, buffer + IP_HEADER_LENGTH + UDP_HEADER_LENGTH, data.len); + pkt->set_data(pkt, data); + + /* return packet */ + *packet = pkt; + + return SUCCESS; +} + +/** + * implementation of socket_t.send + */ +status_t sender(private_socket_t *this, packet_t *packet) +{ + ssize_t bytes_sent; + chunk_t data; + host_t *src, *dst; + + src = packet->get_source(packet); + dst = packet->get_destination(packet); + data = packet->get_data(packet); + + this->logger->log(this->logger, CONTROL, "sending packet: from %s:%d to %s:%d", + src->get_address(src), src->get_port(src), + dst->get_address(dst), dst->get_port(dst)); + + /* send data */ + /* TODO: should we send via the interface we received the packet? */ + bytes_sent = sendto(this->master_fd, data.ptr, data.len, 0, + dst->get_sockaddr(dst), *(dst->get_sockaddr_len(dst))); + + if (bytes_sent != data.len) + { + this->logger->log(this->logger, ERROR, "error writing to socket: %s", strerror(errno)); + return FAILED; + } + return SUCCESS; +} + +/** + * Find all suitable interfaces, bind them and add them to the list + */ +static status_t build_interface_list(private_socket_t *this, u_int16_t port) +{ + int on = TRUE; + int i; + struct sockaddr_in addr; + struct ifconf ifconf; + struct ifreq buf[300]; + + /* master socket for querying socket for a specific interfaces */ + this->master_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (this->master_fd == -1) + { + this->logger->log(this->logger, ERROR, "could not open IPv4 master socket!"); + return FAILED; + } + + /* allow binding of multiplo sockets */ + if (setsockopt(this->master_fd, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on)) < 0) + { + this->logger->log(this->logger, ERROR, "unable to set SO_REUSEADDR on master socket!"); + return FAILED; + } + + /* bind the master socket */ + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_port = htons(port); + if (bind(this->master_fd,(struct sockaddr*)&addr, sizeof(addr)) < 0) + { + this->logger->log(this->logger, ERROR, "unable to bind master socket: %s!", strerror(errno)); + return FAILED; + } + + /* get all interfaces */ + ifconf.ifc_len = sizeof(buf); + ifconf.ifc_buf = (void*) buf; + memset(buf, 0, sizeof(buf)); + if (ioctl(this->master_fd, SIOCGIFCONF, &ifconf) == -1) + { + this->logger->log(this->logger, ERROR, "unable to get interfaces!"); + return FAILED; + } + + /* add every interesting interfaces to our interface list */ + for (i = 0; (i+1) * sizeof(*buf) <= (size_t)ifconf.ifc_len; i++) + { + struct sockaddr_in *current = (struct sockaddr_in*) &buf[i].ifr_addr; + struct ifreq auxinfo; + int skt; + interface_t *interface; + + if (current->sin_family != AF_INET) + { + /* ignore all but AF_INET interfaces */ + continue; + } + + /* get auxilary info about socket */ + memset(&auxinfo, 0, sizeof(auxinfo)); + memcpy(auxinfo.ifr_name, buf[i].ifr_name, IFNAMSIZ); + if (ioctl(this->master_fd, SIOCGIFFLAGS, &auxinfo) == -1) + { + this->logger->log(this->logger, ERROR, "unable to SIOCGIFFLAGS master socket!"); + continue; + } + if (!(auxinfo.ifr_flags & IFF_UP)) + { + /* ignore an interface that isn't up */ + continue; + } + if (current->sin_addr.s_addr == 0) + { + /* ignore unconfigured interfaces */ + continue; + } + + /* set up interface socket */ + skt = socket(AF_INET, SOCK_RAW, IPPROTO_UDP); + if (socket < 0) + { + this->logger->log(this->logger, ERROR, "unable to open interface socket!"); + continue; + } + if (setsockopt(skt, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on)) < 0) + { + this->logger->log(this->logger, ERROR, "unable to set SO_REUSEADDR on interface socket!"); + close(skt); + continue; + } + current->sin_port = htons(port); + current->sin_family = AF_INET; + if (bind(skt, (struct sockaddr*)current, sizeof(struct sockaddr_in)) < 0) + { + this->logger->log(this->logger, ERROR, "unable to bind interface socket!"); + close(skt); + continue; + } + + if (setsockopt(skt, SOL_SOCKET, SO_ATTACH_FILTER, &ikev2_filter, sizeof(ikev2_filter)) < 0) + { + this->logger->log(this->logger, ERROR, "unable to attack IKEv2 filter to interface socket!"); + close(skt); + continue; + } + + /* add socket with interface name to list */ + interface = malloc_thing(interface_t); + strncpy(interface->name, buf[i].ifr_name, IFNAMSIZ); + interface->socket_fd = skt; + interface->address = host_create_from_sockaddr((struct sockaddr*)current); + this->logger->log(this->logger, CONTROL, "listening on %s (%s)", + interface->name, interface->address->get_address(interface->address)); + this->interfaces->insert_last(this->interfaces, (void*)interface); + } + + if (this->interfaces->get_count(this->interfaces) == 0) + { + this->logger->log(this->logger, ERROR, "unable to find any usable interface!"); + return FAILED; + } + return SUCCESS; +} + +/** + * implementation of socket_t.is_listening_on + */ +static bool is_listening_on(private_socket_t *this, host_t *host) +{ + iterator_t *iterator; + + /* listening on 0.0.0.0 is always TRUE */ + if (host->is_default_route(host)) + { + return TRUE; + } + + /* compare host with all interfaces */ + iterator = this->interfaces->create_iterator(this->interfaces, TRUE); + while (iterator->has_next(iterator)) + { + interface_t *interface; + iterator->current(iterator, (void**)&interface); + if (host->equals(host, interface->address)) + { + iterator->destroy(iterator); + return TRUE; + } + } + iterator->destroy(iterator); + return FALSE; +} + +/** + * implementation of socket_t.destroy + */ +static void destroy(private_socket_t *this) +{ + interface_t *interface; + while (this->interfaces->remove_last(this->interfaces, (void**)&interface) == SUCCESS) + { + interface->address->destroy(interface->address); + close(interface->socket_fd); + free(interface); + } + this->interfaces->destroy(this->interfaces); + close(this->master_fd); + free(this); +} + +/* + * See header for description + */ +socket_t *socket_create(u_int16_t port) +{ + private_socket_t *this = malloc_thing(private_socket_t); + + /* public functions */ + this->public.send = (status_t(*)(socket_t*, packet_t*))sender; + this->public.receive = (status_t(*)(socket_t*, packet_t**))receiver; + this->public.is_listening_on = (bool (*)(socket_t*,host_t*))is_listening_on; + this->public.destroy = (void(*)(socket_t*)) destroy; + + this->logger = logger_manager->get_logger(logger_manager, SOCKET); + this->interfaces = linked_list_create(); + + if (build_interface_list(this, port) != SUCCESS) + { + this->interfaces->destroy(this->interfaces); + free(this); + charon->kill(charon, "could not bind any interface!"); + } + + return (socket_t*)this; +} diff --git a/src/charon/network/socket.h b/src/charon/network/socket.h new file mode 100644 index 000000000..498e7700a --- /dev/null +++ b/src/charon/network/socket.h @@ -0,0 +1,128 @@ +/** + * @file socket.h + * + * @brief Interface for socket_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef SOCKET_H_ +#define SOCKET_H_ + + +#include +#include + + +/** + * @brief Maximum size of a packet. + * + * 3000 Bytes should be sufficient, see IKEv2 RFC. + * + * @ingroup network + */ +#define MAX_PACKET 3000 + + +typedef struct socket_t socket_t; + +/** + * @brief Abstraction all sockets (currently IPv4 only). + * + * All available IPv4 sockets are bound and the receive function + * reads from them. To allow binding of other daemons (pluto) to + * UDP/500, this implementation uses RAW sockets. An installed + * "Linux socket filter" filters out all non-IKEv2 traffic and handles + * just IKEv2 messages. An other daemon (pluto) must handle all traffic + * seperatly, e.g. ignore IKEv2 traffic, since charon handles that. + * + * @b Constructors: + * - socket_create() + * + * @todo add IPv6 support + * + * @todo We currently use multiple sockets for historic reasons. With the + * new RAW socket mechanism, we could use just one socket and filter + * addresses in userspace (or via linux socket filter). This would allow + * realtime interface/address management in a easy way... + * + * @ingroup network + */ +struct socket_t { + /** + * @brief Receive a packet. + * + * Reads a packet from the socket and sets source/dest + * appropriately. + * + * @param sock socket_t object to work on + * @param packet pinter gets address from allocated packet_t + * @return + * - SUCCESS when packet successfully received + * - FAILED when unable to receive + */ + status_t (*receive) (socket_t *sock, packet_t **packet); + + /** + * @brief Send a packet. + * + * Sends a packet to the net using destination from the packet. + * Packet is sent using default routing mechanisms, thus the + * source address in packet is ignored. + * + * @param sock socket_t object to work on + * @param packet[out] packet_t to send + * @return + * - SUCCESS when packet successfully sent + * - FAILED when unable to send + */ + status_t (*send) (socket_t *sock, packet_t *packet); + + /** + * @brief Check if socket listens on an address. + * + * @param sock socket_t object to work on + * @param host address to check + * @return TRUE if listening on host, FALSE otherwise + */ + bool (*is_listening_on) (socket_t *sock, host_t *host); + + /** + * @brief Destroy sockets. + * + * close sockets and destroy socket_t object + * + * @param sock socket_t to destroy + */ + void (*destroy) (socket_t *sock); +}; + +/** + * @brief Create a socket_t, wich binds multiple sockets. + * + * currently creates one socket, listening on all addresses + * on "port". + * + * @param port port to bind socket to + * @return socket_t object + * + * @ingroup network + */ +socket_t *socket_create(u_int16_t port); + + +#endif /*SOCKET_H_*/ diff --git a/src/charon/queues/Makefile.queues b/src/charon/queues/Makefile.queues new file mode 100644 index 000000000..eeb012d2b --- /dev/null +++ b/src/charon/queues/Makefile.queues @@ -0,0 +1,30 @@ +# Copyright (C) 2005 Jan Hutter, 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 . +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# + +QUEUES_DIR= $(CHARON_DIR)queues/ + +CHARON_OBJS+= $(BUILD_DIR)event_queue.o +$(BUILD_DIR)event_queue.o : $(QUEUES_DIR)event_queue.c $(QUEUES_DIR)event_queue.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)job_queue.o +$(BUILD_DIR)job_queue.o : $(QUEUES_DIR)job_queue.c $(QUEUES_DIR)job_queue.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)send_queue.o +$(BUILD_DIR)send_queue.o : $(QUEUES_DIR)send_queue.c $(QUEUES_DIR)send_queue.h + $(CC) $(CFLAGS) -c -o $@ $< + + +include $(QUEUES_DIR)jobs/Makefile.jobs \ No newline at end of file diff --git a/src/charon/queues/event_queue.c b/src/charon/queues/event_queue.c new file mode 100644 index 000000000..ece9d1513 --- /dev/null +++ b/src/charon/queues/event_queue.c @@ -0,0 +1,349 @@ +/** + * @file event_queue.c + * + * @brief Implementation of event_queue_t + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 +#include + +#include "event_queue.h" + +#include +#include + + + +typedef struct event_t event_t; + +/** + * @brief Represents an event as it is stored in the event queue. + * + * A event consists of a event time and an assigned job object. + * + */ +struct event_t{ + /** + * Time to fire the event. + */ + timeval_t time; + + /** + * Every event has its assigned job. + */ + job_t * job; + + /** + * @brief Destroys a event_t object. + * + * @param event_t calling object + */ + void (*destroy) (event_t *event); +}; + + +/** + * implements event_t.destroy + */ +static void event_destroy(event_t *event) +{ + free(event); +} + +/** + * @brief Creates a event for a specific time + * + * @param time absolute time to fire the event + * @param job job to add to job-queue at specific time + * + * @returns created event_t object + */ +static event_t *event_create(timeval_t time, job_t *job) +{ + event_t *this = malloc_thing(event_t); + + this->destroy = event_destroy; + this->time = time; + this->job = job; + + return this; +} + + +typedef struct private_event_queue_t private_event_queue_t; + +/** + * Private Variables and Functions of event_queue_t class. + * + */ +struct private_event_queue_t { + /** + * Public part. + */ + event_queue_t public; + + /** + * The events are stored in a linked list of type linked_list_t. + */ + linked_list_t *list; + + /** + * Access to linked_list is locked through this mutex. + */ + pthread_mutex_t mutex; + + /** + * If the queue is empty or an event has not to be fired + * a thread has to wait. + * + * This condvar is used to wake up such a thread. + */ + pthread_cond_t condvar; +}; + +/** + * Returns the difference of to timeval structs in microseconds + * + * @param end_time end time + * @param start_time start time + * + * @warning this function is also defined in the tester class + * In later improvements, this function can be added to a general + * class type! + * + * @return difference in microseconds (end time - start time) + */ +static long time_difference(struct timeval *end_time, struct timeval *start_time) +{ + long seconds, microseconds; + + seconds = (end_time->tv_sec - start_time->tv_sec); + microseconds = (end_time->tv_usec - start_time->tv_usec); + return ((seconds * 1000000) + microseconds); +} + + +/** + * Implements event_queue_t.get_count + */ +static int get_count (private_event_queue_t *this) +{ + int count; + pthread_mutex_lock(&(this->mutex)); + count = this->list->get_count(this->list); + pthread_mutex_unlock(&(this->mutex)); + return count; +} + +/** + * Implements event_queue_t.get + */ +static job_t *get(private_event_queue_t *this) +{ + timespec_t timeout; + timeval_t current_time; + event_t * next_event; + job_t *job; + int oldstate; + + pthread_mutex_lock(&(this->mutex)); + + while (1) + { + while(this->list->get_count(this->list) == 0) + { + /* add mutex unlock handler for cancellation, enable cancellation */ + pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock, (void*)&(this->mutex)); + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); + + pthread_cond_wait( &(this->condvar), &(this->mutex)); + + /* reset cancellation, remove mutex-unlock handler (without executing) */ + pthread_setcancelstate(oldstate, NULL); + pthread_cleanup_pop(0); + } + + this->list->get_first(this->list,(void **) &next_event); + + gettimeofday(¤t_time,NULL); + long difference = time_difference(¤t_time,&(next_event->time)); + if (difference <= 0) + { + timeout.tv_sec = next_event->time.tv_sec; + timeout.tv_nsec = next_event->time.tv_usec * 1000; + + /* add mutex unlock handler for cancellation, enable cancellation */ + pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock, (void*)&(this->mutex)); + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); + + pthread_cond_timedwait( &(this->condvar), &(this->mutex),&timeout); + + /* reset cancellation, remove mutex-unlock handler (without executing) */ + pthread_setcancelstate(oldstate, NULL); + pthread_cleanup_pop(0); + } + else + { + /* event available */ + this->list->remove_first(this->list,(void **) &next_event); + + job = next_event->job; + + next_event->destroy(next_event); + break; + } + + } + pthread_cond_signal( &(this->condvar)); + + pthread_mutex_unlock(&(this->mutex)); + + return job; +} + +/** + * Implements function add_absolute of event_queue_t. + * See #event_queue_s.add_absolute for description. + */ +static void add_absolute(private_event_queue_t *this, job_t *job, timeval_t time) +{ + event_t *event = event_create(time,job); + event_t *current_event; + status_t status; + + pthread_mutex_lock(&(this->mutex)); + + /* while just used to break out */ + while(1) + { + if (this->list->get_count(this->list) == 0) + { + this->list->insert_first(this->list,event); + break; + } + + /* check last entry */ + this->list->get_last(this->list,(void **) ¤t_event); + + if (time_difference(&(event->time), &(current_event->time)) >= 0) + { + /* my event has to be fired after the last event in list */ + this->list->insert_last(this->list,event); + break; + } + + /* check first entry */ + this->list->get_first(this->list,(void **) ¤t_event); + + if (time_difference(&(event->time), &(current_event->time)) < 0) + { + /* my event has to be fired before the first event in list */ + this->list->insert_first(this->list,event); + break; + } + + iterator_t * iterator; + + iterator = this->list->create_iterator(this->list,TRUE); + + iterator->has_next(iterator); + /* first element has not to be checked (already done) */ + + while(iterator->has_next(iterator)) + { + status = iterator->current(iterator,(void **) ¤t_event); + + if (time_difference(&(event->time), &(current_event->time)) <= 0) + { + /* my event has to be fired before the current event in list */ + iterator->insert_before(iterator,event); + break; + } + } + iterator->destroy(iterator); + break; + } + + pthread_cond_signal( &(this->condvar)); + pthread_mutex_unlock(&(this->mutex)); +} + +/** + * Implements event_queue_t.add_relative. + */ +static void add_relative(event_queue_t *this, job_t *job, u_int32_t ms) +{ + timeval_t current_time; + timeval_t time; + int micros = ms * 1000; + + gettimeofday(¤t_time, NULL); + + time.tv_usec = ((current_time.tv_usec + micros) % 1000000); + time.tv_sec = current_time.tv_sec + ((current_time.tv_usec + micros)/ 1000000); + + this->add_absolute(this, job, time); +} + + +/** + * Implements event_queue_t.destroy. + */ +static void event_queue_destroy(private_event_queue_t *this) +{ + while (this->list->get_count(this->list) > 0) + { + event_t *event; + + if (this->list->remove_first(this->list,(void *) &event) != SUCCESS) + { + this->list->destroy(this->list); + break; + } + event->job->destroy_all(event->job); + event->destroy(event); + } + this->list->destroy(this->list); + + pthread_mutex_destroy(&(this->mutex)); + + pthread_cond_destroy(&(this->condvar)); + + free(this); +} + +/* + * Documented in header + */ +event_queue_t *event_queue_create() +{ + private_event_queue_t *this = malloc_thing(private_event_queue_t); + + this->public.get_count = (int (*) (event_queue_t *event_queue)) get_count; + this->public.get = (job_t *(*) (event_queue_t *event_queue)) get; + this->public.add_absolute = (void (*) (event_queue_t *event_queue, job_t *job, timeval_t time)) add_absolute; + this->public.add_relative = (void (*) (event_queue_t *event_queue, job_t *job, u_int32_t ms)) add_relative; + this->public.destroy = (void (*) (event_queue_t *event_queue)) event_queue_destroy; + + this->list = linked_list_create(); + pthread_mutex_init(&(this->mutex), NULL); + pthread_cond_init(&(this->condvar), NULL); + + return (&this->public); +} diff --git a/src/charon/queues/event_queue.h b/src/charon/queues/event_queue.h new file mode 100644 index 000000000..638887dac --- /dev/null +++ b/src/charon/queues/event_queue.h @@ -0,0 +1,117 @@ +/** + * @file event_queue.h + * + * @brief Interface of job_queue_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef EVENT_QUEUE_H_ +#define EVENT_QUEUE_H_ + +#include + +#include +#include + +typedef struct event_queue_t event_queue_t; + +/** + * @brief Event-Queue used to store timed events. + * + * Added events are sorted. The get method blocks until + * the time is elapsed to process the next event. The get + * method is called from the scheduler_t thread, which + * will add the jobs to to job_queue_t for further processing. + * + * Although the event-queue is based on a linked_list_t + * all access functions are thread-save implemented. + * + * @b Constructors: + * - event_queue_create() + * + * @ingroup queues + */ +struct event_queue_t { + + /** + * @brief Returns number of events in queue. + * + * @param event_queue calling object + * @return number of events in queue + */ + int (*get_count) (event_queue_t *event_queue); + + /** + * @brief Get the next job from the event-queue. + * + * If no event is pending, this function blocks until a job can be returned. + * + * @param event_queue calling object + * @param[out] job pointer to a job pointer where to job is returned to + * @return next job + */ + job_t *(*get) (event_queue_t *event_queue); + + /** + * @brief Adds a event to the queue, using a relative time. + * + * This function is non blocking and adds a job_t at a specific time to the list. + * The specific job object has to get destroyed by the thread which + * removes the job. + * + * @param event_queue calling object + * @param[in] job job to add to the queue (job is not copied) + * @param[in] time relative time, when the event has to get fired + */ + void (*add_relative) (event_queue_t *event_queue, job_t *job, u_int32_t ms); + + /** + * @brief Adds a event to the queue, using an absolute time. + * + * This function is non blocking and adds a job_t at a specific time to the list. + * The specific job object has to get destroyed by the thread which + * removes the job. + * + * @param event_queue calling object + * @param[in] job job to add to the queue (job is not copied) + * @param[in] absolute time time, when the event has to get fired + */ + void (*add_absolute) (event_queue_t *event_queue, job_t *job, timeval_t time); + + /** + * @brief Destroys a event_queue object. + * + * @warning The caller of this function has to make sure + * that no thread is going to add or get an event from the event_queue + * after calling this function. + * + * @param event_queue calling object + */ + void (*destroy) (event_queue_t *event_queue); +}; + +/** + * @brief Creates an empty event_queue. + * + * @returns event_queue_t object + * + * @ingroup queues + */ +event_queue_t *event_queue_create(void); + +#endif /*EVENT_QUEUE_H_*/ diff --git a/src/charon/queues/job_queue.c b/src/charon/queues/job_queue.c new file mode 100644 index 000000000..12a781c67 --- /dev/null +++ b/src/charon/queues/job_queue.c @@ -0,0 +1,153 @@ +/** + * @file job_queue.c + * + * @brief Implementation of job_queue_t + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 +#include + +#include "job_queue.h" + +#include + + +typedef struct private_job_queue_t private_job_queue_t; + +/** + * @brief Private Variables and Functions of job_queue class + * + */ +struct private_job_queue_t { + + /** + * public members + */ + job_queue_t public; + + /** + * The jobs are stored in a linked list + */ + linked_list_t *list; + + /** + * access to linked_list is locked through this mutex + */ + pthread_mutex_t mutex; + + /** + * If the queue is empty a thread has to wait + * This condvar is used to wake up such a thread + */ + pthread_cond_t condvar; +}; + + +/** + * implements job_queue_t.get_count + */ +static int get_count(private_job_queue_t *this) +{ + int count; + pthread_mutex_lock(&(this->mutex)); + count = this->list->get_count(this->list); + pthread_mutex_unlock(&(this->mutex)); + return count; +} + +/** + * implements job_queue_t.get + */ +static job_t *get(private_job_queue_t *this) +{ + int oldstate; + job_t *job; + pthread_mutex_lock(&(this->mutex)); + /* go to wait while no jobs available */ + while(this->list->get_count(this->list) == 0) + { + /* add mutex unlock handler for cancellation, enable cancellation */ + pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock, (void*)&(this->mutex)); + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); + + pthread_cond_wait( &(this->condvar), &(this->mutex)); + + /* reset cancellation, remove mutex-unlock handler (without executing) */ + pthread_setcancelstate(oldstate, NULL); + pthread_cleanup_pop(0); + } + this->list->remove_first(this->list,(void **) &job); + pthread_mutex_unlock(&(this->mutex)); + return job; +} + +/** + * implements function job_queue_t.add + */ +static void add(private_job_queue_t *this, job_t *job) +{ + pthread_mutex_lock(&(this->mutex)); + this->list->insert_last(this->list,job); + pthread_cond_signal( &(this->condvar)); + pthread_mutex_unlock(&(this->mutex)); +} + +/** + * implements job_queue_t.destroy + */ +static void job_queue_destroy (private_job_queue_t *this) +{ + while (this->list->get_count(this->list) > 0) + { + job_t *job; + if (this->list->remove_first(this->list,(void *) &job) != SUCCESS) + { + this->list->destroy(this->list); + break; + } + job->destroy_all(job); + } + this->list->destroy(this->list); + + pthread_mutex_destroy(&(this->mutex)); + + pthread_cond_destroy(&(this->condvar)); + + free(this); +} + +/* + * + * Documented in header + */ +job_queue_t *job_queue_create(void) +{ + private_job_queue_t *this = malloc_thing(private_job_queue_t); + + this->public.get_count = (int(*)(job_queue_t*))get_count; + this->public.get = (job_t*(*)(job_queue_t*))get; + this->public.add = (void(*)(job_queue_t*, job_t*))add; + this->public.destroy = (void(*)(job_queue_t*))job_queue_destroy; + + this->list = linked_list_create(); + pthread_mutex_init(&(this->mutex), NULL); + pthread_cond_init(&(this->condvar), NULL); + + return (&this->public); +} diff --git a/src/charon/queues/job_queue.h b/src/charon/queues/job_queue.h new file mode 100644 index 000000000..71cc5891e --- /dev/null +++ b/src/charon/queues/job_queue.h @@ -0,0 +1,99 @@ +/** + * @file job_queue.h + * + * @brief Interface of job_queue_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef JOB_QUEUE_H_ +#define JOB_QUEUE_H_ + +#include +#include + +typedef struct job_queue_t job_queue_t; + +/** + * @brief The job queue stores jobs, which will be processed by the thread_pool_t. + * + * Jobs are added from various sources, from the threads and + * from the event_queue_t. + * Although the job-queue is based on a linked_list_t + * all access functions are thread-save implemented. + * + * @b Constructors: + * - job_queue_create() + * + * @ingroup queues + */ +struct job_queue_t { + + /** + * @brief Returns number of jobs in queue. + * + * @param job_queue_t calling object + * @returns number of items in queue + */ + int (*get_count) (job_queue_t *job_queue); + + /** + * @brief Get the next job from the queue. + * + * If the queue is empty, this function blocks until a job can be returned. + * After using, the returned job has to get destroyed by the caller. + * + * @param job_queue_t calling object + * @param[out] job pointer to a job pointer where to job is returned to + * @return next job + */ + job_t *(*get) (job_queue_t *job_queue); + + /** + * @brief Adds a job to the queue. + * + * This function is non blocking and adds a job_t to the list. + * The specific job object has to get destroyed by the thread which + * removes the job. + * + * @param job_queue_t calling object + * @param job job to add to the queue (job is not copied) + */ + void (*add) (job_queue_t *job_queue, job_t *job); + + /** + * @brief Destroys a job_queue object. + * + * @warning The caller of this function has to make sure + * that no thread is going to add or get a job from the job_queue + * after calling this function. + * + * @param job_queue_t calling object + */ + void (*destroy) (job_queue_t *job_queue); +}; + +/** + * @brief Creates an empty job_queue. + * + * @return job_queue_t object + * + * @ingroup queues + */ +job_queue_t *job_queue_create(void); + +#endif /*JOB_QUEUE_H_*/ diff --git a/src/charon/queues/jobs/Makefile.jobs b/src/charon/queues/jobs/Makefile.jobs new file mode 100644 index 000000000..db89987bc --- /dev/null +++ b/src/charon/queues/jobs/Makefile.jobs @@ -0,0 +1,40 @@ +# Copyright (C) 2005 Jan Hutter, 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 . +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# + +JOBS_DIR= $(QUEUES_DIR)jobs/ + +CHARON_OBJS+= $(BUILD_DIR)delete_half_open_ike_sa_job.o +$(BUILD_DIR)delete_half_open_ike_sa_job.o : $(JOBS_DIR)delete_half_open_ike_sa_job.c $(JOBS_DIR)delete_half_open_ike_sa_job.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)delete_established_ike_sa_job.o +$(BUILD_DIR)delete_established_ike_sa_job.o : $(JOBS_DIR)delete_established_ike_sa_job.c $(JOBS_DIR)delete_established_ike_sa_job.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)incoming_packet_job.o +$(BUILD_DIR)incoming_packet_job.o : $(JOBS_DIR)incoming_packet_job.c $(JOBS_DIR)incoming_packet_job.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)initiate_ike_sa_job.o +$(BUILD_DIR)initiate_ike_sa_job.o : $(JOBS_DIR)initiate_ike_sa_job.c $(JOBS_DIR)initiate_ike_sa_job.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)retransmit_request_job.o +$(BUILD_DIR)retransmit_request_job.o : $(JOBS_DIR)retransmit_request_job.c $(JOBS_DIR)retransmit_request_job.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)job.o +$(BUILD_DIR)job.o : $(JOBS_DIR)job.c $(JOBS_DIR)job.h + $(CC) $(CFLAGS) -c -o $@ $< + \ No newline at end of file diff --git a/src/charon/queues/jobs/delete_established_ike_sa_job.c b/src/charon/queues/jobs/delete_established_ike_sa_job.c new file mode 100644 index 000000000..7251e2ca4 --- /dev/null +++ b/src/charon/queues/jobs/delete_established_ike_sa_job.c @@ -0,0 +1,90 @@ +/** + * @file delete_established_ike_sa_job.c + * + * @brief Implementation of delete_established_ike_sa_job_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 "delete_established_ike_sa_job.h" + + + +typedef struct private_delete_established_ike_sa_job_t private_delete_established_ike_sa_job_t; + +/** + * Private data of an delete_established_ike_sa_job_t object. + */ +struct private_delete_established_ike_sa_job_t { + /** + * Public delete_established_ike_sa_job_t interface. + */ + delete_established_ike_sa_job_t public; + + /** + * ID of the ike_sa to delete. + */ + ike_sa_id_t *ike_sa_id; +}; + +/** + * Implementation of job_t.get_type. + */ +static job_type_t get_type(private_delete_established_ike_sa_job_t *this) +{ + return DELETE_ESTABLISHED_IKE_SA; +} + +/** + * Implementation of delete_established_ike_sa_job_t.get_ike_sa_id + */ +static ike_sa_id_t *get_ike_sa_id(private_delete_established_ike_sa_job_t *this) +{ + return this->ike_sa_id; +} + +/** + * Implementation of job_t.destroy. + */ +static void destroy(private_delete_established_ike_sa_job_t *this) +{ + this->ike_sa_id->destroy(this->ike_sa_id); + free(this); +} + +/* + * Described in header + */ +delete_established_ike_sa_job_t *delete_established_ike_sa_job_create(ike_sa_id_t *ike_sa_id) +{ + private_delete_established_ike_sa_job_t *this = malloc_thing(private_delete_established_ike_sa_job_t); + + /* interface functions */ + this->public.job_interface.get_type = (job_type_t (*) (job_t *)) get_type; + /* same as destroy */ + this->public.job_interface.destroy_all = (void (*) (job_t *)) destroy; + this->public.job_interface.destroy = (void (*)(job_t*)) destroy; + + /* public functions */ + this->public.get_ike_sa_id = (ike_sa_id_t * (*)(delete_established_ike_sa_job_t *)) get_ike_sa_id; + this->public.destroy = (void (*)(delete_established_ike_sa_job_t *)) destroy; + + /* private variables */ + this->ike_sa_id = ike_sa_id->clone(ike_sa_id); + + return &(this->public); +} diff --git a/src/charon/queues/jobs/delete_established_ike_sa_job.h b/src/charon/queues/jobs/delete_established_ike_sa_job.h new file mode 100644 index 000000000..762dceae6 --- /dev/null +++ b/src/charon/queues/jobs/delete_established_ike_sa_job.h @@ -0,0 +1,78 @@ +/** + * @file delete_established_ike_sa_job.h + * + * @brief Interface of delete_established_ike_sa_job_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef DELETE_ESTABLISHED_IKE_SA_JOB_H_ +#define DELETE_ESTABLISHED_IKE_SA_JOB_H_ + +#include +#include +#include + + +typedef struct delete_established_ike_sa_job_t delete_established_ike_sa_job_t; + +/** + * @brief Class representing an DELETE_ESTABLISHED_IKE_SA Job. + * + * This job initiates the deletion of an IKE_SA. The SA + * to delete is specified via an ike_sa_id_t. + * + * @b Constructors: + * - delete_established_ike_sa_job_create() + * + * @ingroup jobs + */ +struct delete_established_ike_sa_job_t { + /** + * The job_t interface. + */ + job_t job_interface; + + /** + * @brief Returns the currently set ike_sa_id. + * + * @warning Returned object is not copied. + * + * @param this calling delete_established_ike_sa_job_t object + * @return ike_sa_id_t object + */ + ike_sa_id_t * (*get_ike_sa_id) (delete_established_ike_sa_job_t *this); + + /** + * @brief Destroys an delete_established_ike_sa_job_t object (including assigned data). + * + * @param this delete_established_ike_sa_job_t object to destroy + */ + void (*destroy) (delete_established_ike_sa_job_t *this); +}; + +/** + * @brief Creates a job of type DELETE_ESTABLISHED_IKE_SA. + * + * @param ike_sa_id id of the IKE_SA to delete + * @return delete_established_ike_sa_job_t object + * + * @ingroup jobs + */ +delete_established_ike_sa_job_t *delete_established_ike_sa_job_create(ike_sa_id_t *ike_sa_id); + +#endif /*DELETE_ESTABLISHED_IKE_SA_JOB_H_*/ diff --git a/src/charon/queues/jobs/delete_half_open_ike_sa_job.c b/src/charon/queues/jobs/delete_half_open_ike_sa_job.c new file mode 100644 index 000000000..610285e20 --- /dev/null +++ b/src/charon/queues/jobs/delete_half_open_ike_sa_job.c @@ -0,0 +1,90 @@ +/** + * @file delete_half_open_ike_sa_job.c + * + * @brief Implementation of delete_half_open_ike_sa_job_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 "delete_half_open_ike_sa_job.h" + + + +typedef struct private_delete_half_open_ike_sa_job_t private_delete_half_open_ike_sa_job_t; + +/** + * Private data of an delete_half_open_ike_sa_job_t Object + */ +struct private_delete_half_open_ike_sa_job_t { + /** + * public delete_half_open_ike_sa_job_t interface + */ + delete_half_open_ike_sa_job_t public; + + /** + * ID of the ike_sa to delete + */ + ike_sa_id_t *ike_sa_id; +}; + +/** + * Implements job_t.get_type. + */ +static job_type_t get_type(private_delete_half_open_ike_sa_job_t *this) +{ + return DELETE_HALF_OPEN_IKE_SA; +} + +/** + * Implements elete_ike_sa_job_t.get_ike_sa_id + */ +static ike_sa_id_t *get_ike_sa_id(private_delete_half_open_ike_sa_job_t *this) +{ + return this->ike_sa_id; +} + +/** + * Implements job_t.destroy. + */ +static void destroy(private_delete_half_open_ike_sa_job_t *this) +{ + this->ike_sa_id->destroy(this->ike_sa_id); + free(this); +} + +/* + * Described in header + */ +delete_half_open_ike_sa_job_t *delete_half_open_ike_sa_job_create(ike_sa_id_t *ike_sa_id) +{ + private_delete_half_open_ike_sa_job_t *this = malloc_thing(private_delete_half_open_ike_sa_job_t); + + /* interface functions */ + this->public.job_interface.get_type = (job_type_t (*) (job_t *)) get_type; + /* same as destroy */ + this->public.job_interface.destroy_all = (void (*) (job_t *)) destroy; + this->public.job_interface.destroy = (void (*)(job_t *)) destroy;; + + /* public functions */ + this->public.get_ike_sa_id = (ike_sa_id_t * (*)(delete_half_open_ike_sa_job_t *)) get_ike_sa_id; + this->public.destroy = (void (*)(delete_half_open_ike_sa_job_t *)) destroy; + + /* private variables */ + this->ike_sa_id = ike_sa_id->clone(ike_sa_id); + + return &(this->public); +} diff --git a/src/charon/queues/jobs/delete_half_open_ike_sa_job.h b/src/charon/queues/jobs/delete_half_open_ike_sa_job.h new file mode 100644 index 000000000..ea42be8f2 --- /dev/null +++ b/src/charon/queues/jobs/delete_half_open_ike_sa_job.h @@ -0,0 +1,79 @@ +/** + * @file delete_half_open_ike_sa_job.h + * + * @brief Interface of delete_half_open_ike_sa_job_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef DELETE_HALF_OPEN_IKE_SA_JOB_H_ +#define DELETE_HALF_OPEN_IKE_SA_JOB_H_ + +#include +#include +#include + + +typedef struct delete_half_open_ike_sa_job_t delete_half_open_ike_sa_job_t; + +/** + * @brief Class representing an DELETE_HALF_OPEN_IKE_SA Job. + * + * This job is responsible for deleting of half open IKE_SAs. A half + * open IKE_SA is every IKE_SA which hasn't reache the ike_sa_established + * state. + * + * @b Constructors: + * - delete_half_open_ike_sa_job_create() + * + * @ingroup jobs + */ +struct delete_half_open_ike_sa_job_t { + /** + * The job_t interface. + */ + job_t job_interface; + + /** + * @brief Returns the currently set ike_sa_id. + * + * @warning Returned object is not copied. + * + * @param this calling delete_half_open_ike_sa_job_t object + * @return ike_sa_id_t object + */ + ike_sa_id_t * (*get_ike_sa_id) (delete_half_open_ike_sa_job_t *this); + + /** + * @brief Destroys an delete_half_open_ike_sa_job_t object (including assigned data). + * + * @param this delete_half_open_ike_sa_job_t object to destroy + */ + void (*destroy) (delete_half_open_ike_sa_job_t *this); +}; + +/** + * @brief Creates a job of type DELETE_HALF_OPEN_IKE_SA. + * + * @param ike_sa_id id of the IKE_SA to delete + * @return created delete_half_open_ike_sa_job_t object + * + * @ingroup jobs + */ +delete_half_open_ike_sa_job_t *delete_half_open_ike_sa_job_create(ike_sa_id_t *ike_sa_id); + +#endif /*DELETE_HALF_OPEN_IKE_SA_JOB_H_*/ diff --git a/src/charon/queues/jobs/incoming_packet_job.c b/src/charon/queues/jobs/incoming_packet_job.c new file mode 100644 index 000000000..fc71f63ea --- /dev/null +++ b/src/charon/queues/jobs/incoming_packet_job.c @@ -0,0 +1,102 @@ +/** + * @file incoming_packet_job.h + * + * @brief Implementation of incoming_packet_job_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 "incoming_packet_job.h" + + + +typedef struct private_incoming_packet_job_t private_incoming_packet_job_t; + +/** + * Private data of an incoming_packet_job_t Object + */ +struct private_incoming_packet_job_t { + /** + * public incoming_packet_job_t interface + */ + incoming_packet_job_t public; + + /** + * Assigned packet + */ + packet_t *packet; +}; + +/** + * Implements job_t.get_type. + */ +static job_type_t get_type(private_incoming_packet_job_t *this) +{ + return INCOMING_PACKET; +} + +/** + * Implements incoming_packet_job_t.get_packet. + */ +static packet_t *get_packet(private_incoming_packet_job_t *this) +{ + return this->packet; +} + +/** + * Implements job_t.destroy_all. + */ +static void destroy_all(private_incoming_packet_job_t *this) +{ + if (this->packet != NULL) + { + this->packet->destroy(this->packet); + } + free(this); +} + +/** + * Implements job_t.destroy. + */ +static void destroy(job_t *job) +{ + private_incoming_packet_job_t *this = (private_incoming_packet_job_t *) job; + free(this); +} + +/* + * Described in header + */ +incoming_packet_job_t *incoming_packet_job_create(packet_t *packet) +{ + private_incoming_packet_job_t *this = malloc_thing(private_incoming_packet_job_t); + + /* interface functions */ + this->public.job_interface.get_type = (job_type_t (*) (job_t *)) get_type; + this->public.job_interface.destroy_all = (void (*) (job_t *)) destroy_all; + this->public.job_interface.destroy = destroy; + + /* public functions */ + this->public.get_packet = (packet_t * (*)(incoming_packet_job_t *)) get_packet; + this->public.destroy = (void (*)(incoming_packet_job_t *)) destroy; + + /* private variables */ + this->packet = packet; + + return &(this->public); +} diff --git a/src/charon/queues/jobs/incoming_packet_job.h b/src/charon/queues/jobs/incoming_packet_job.h new file mode 100644 index 000000000..e3fb5797e --- /dev/null +++ b/src/charon/queues/jobs/incoming_packet_job.h @@ -0,0 +1,78 @@ +/** + * @file incoming_packet_job.h + * + * @brief Interface of incoming_packet_job_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef INCOMING_PACKET_JOB_H_ +#define INCOMING_PACKET_JOB_H_ + +#include +#include +#include + + +typedef struct incoming_packet_job_t incoming_packet_job_t; + +/** + * @brief Class representing an INCOMING_PACKET Job. + * + * An incoming pack job is created from the receiver, which has + * read a packet to process from the socket. + * + * @b Constructors: + * - incoming_packet_job_create() + * + * @ingroup jobs + */ +struct incoming_packet_job_t { + /** + * implements job_t interface + */ + job_t job_interface; + + /** + * @brief Returns the assigned packet_t object + * + * @warning Returned packet is not cloned and has to get destroyed by the caller. + * + * @param this calling incoming_packet_job_t object + * @return assigned packet + */ + packet_t *(*get_packet) (incoming_packet_job_t *this); + + /** + * @brief Destroys an incoming_packet_job_t object. + * + * @param this incoming_packet_job_t object to destroy + */ + void (*destroy) (incoming_packet_job_t *this); +}; + +/** + * @brief Creates a job of type INCOMING_PACKET + * + * @param[in] packet packet to assign with this job + * @return created incoming_packet_job_t object + * + * @ingroup jobs + */ +incoming_packet_job_t *incoming_packet_job_create(packet_t *packet); + +#endif /*INCOMING_PACKET_JOB_H_*/ diff --git a/src/charon/queues/jobs/initiate_ike_sa_job.c b/src/charon/queues/jobs/initiate_ike_sa_job.c new file mode 100644 index 000000000..ac9ace36c --- /dev/null +++ b/src/charon/queues/jobs/initiate_ike_sa_job.c @@ -0,0 +1,101 @@ +/** + * @file initiate_ike_sa_job.c + * + * @brief Implementation of initiate_ike_sa_job_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 + +#include "initiate_ike_sa_job.h" + + + +typedef struct private_initiate_ike_sa_job_t private_initiate_ike_sa_job_t; + +/** + * Private data of an initiate_ike_sa_job_t Object + */ +struct private_initiate_ike_sa_job_t { + /** + * public initiate_ike_sa_job_t interface + */ + initiate_ike_sa_job_t public; + + /** + * associated connection object to initiate + */ + connection_t *connection; +}; + + +/** + * Implements initiate_ike_sa_job_t.get_type. + */ +static job_type_t get_type(private_initiate_ike_sa_job_t *this) +{ + return INITIATE_IKE_SA; +} + +/** + * Implements initiate_ike_sa_job_t.get_configuration_name. + */ +static connection_t *get_connection(private_initiate_ike_sa_job_t *this) +{ + return this->connection; +} + +/** + * Implements job_t.destroy. + */ +static void destroy_all(private_initiate_ike_sa_job_t *this) +{ + this->connection->destroy(this->connection); + free(this); +} + +/** + * Implements job_t.destroy. + */ +static void destroy(private_initiate_ike_sa_job_t *this) +{ + free(this); +} + +/* + * Described in header + */ +initiate_ike_sa_job_t *initiate_ike_sa_job_create(connection_t *connection) +{ + private_initiate_ike_sa_job_t *this = malloc_thing(private_initiate_ike_sa_job_t); + + /* interface functions */ + this->public.job_interface.get_type = (job_type_t (*) (job_t *)) get_type; + this->public.job_interface.destroy_all = (void (*) (job_t *)) destroy_all; + this->public.job_interface.destroy = (void (*) (job_t *)) destroy; + + /* public functions */ + this->public.get_connection = (connection_t* (*)(initiate_ike_sa_job_t *)) get_connection; + this->public.destroy = (void (*)(initiate_ike_sa_job_t *)) destroy; + + /* private variables */ + this->connection = connection; + + return &(this->public); +} diff --git a/src/charon/queues/jobs/initiate_ike_sa_job.h b/src/charon/queues/jobs/initiate_ike_sa_job.h new file mode 100644 index 000000000..cee31f07b --- /dev/null +++ b/src/charon/queues/jobs/initiate_ike_sa_job.h @@ -0,0 +1,75 @@ +/** + * @file initiate_ike_sa_job.h + * + * @brief Interface of initiate_ike_sa_job_t. + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef INITIATE_IKE_SA_JOB_H_ +#define INITIATE_IKE_SA_JOB_H_ + +#include +#include +#include + + +typedef struct initiate_ike_sa_job_t initiate_ike_sa_job_t; + +/** + * @brief Class representing an INITIATE_IKE_SA Job. + * + * This job is created if an IKE_SA should be iniated. This + * happens via a user request, or via the kernel interface. + * + * @b Constructors: + * - initiate_ike_sa_job_create() + * + * @ingroup jobs + */ +struct initiate_ike_sa_job_t { + /** + * implements job_t interface + */ + job_t job_interface; + + /** + * @brief Returns the connection_t to initialize + * + * @param this calling initiate_ike_sa_job_t object + * @return connection_t + */ + connection_t *(*get_connection) (initiate_ike_sa_job_t *this); + + /** + * @brief Destroys an initiate_ike_sa_job_t object. + * + * @param this initiate_ike_sa_job_t object to destroy + */ + void (*destroy) (initiate_ike_sa_job_t *this); +}; + +/** + * @brief Creates a job of type INITIATE_IKE_SA. + * + * @param connection connection_t to initializes + * @return initiate_ike_sa_job_t object + * + * @ingroup jobs + */ +initiate_ike_sa_job_t *initiate_ike_sa_job_create(connection_t *connection); + +#endif /*INITIATE_IKE_SA_JOB_H_*/ diff --git a/src/charon/queues/jobs/job.c b/src/charon/queues/jobs/job.c new file mode 100644 index 000000000..df739f9e5 --- /dev/null +++ b/src/charon/queues/jobs/job.c @@ -0,0 +1,34 @@ +/** + * @file job.c + * + * @brief Interface additions to job_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 "job.h" + + +mapping_t job_type_m[] = { + {INCOMING_PACKET, "INCOMING_PACKET"}, + {RETRANSMIT_REQUEST, "RETRANSMIT_REQUEST"}, + {INITIATE_IKE_SA, "INITIATE_IKE_SA"}, + {DELETE_HALF_OPEN_IKE_SA, "DELETE_HALF_OPEN_IKE_SA"}, + {DELETE_ESTABLISHED_IKE_SA, "DELETE_ESTABLISHED_IKE_SA"}, + {MAPPING_END, NULL} +}; diff --git a/src/charon/queues/jobs/job.h b/src/charon/queues/jobs/job.h new file mode 100644 index 000000000..eea4da09e --- /dev/null +++ b/src/charon/queues/jobs/job.h @@ -0,0 +1,120 @@ +/** + * @file job.h + * + * @brief Interface job_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef JOB_H_ +#define JOB_H_ + +#include +#include + + +typedef enum job_type_t job_type_t; + +/** + * @brief Definition of the various job types. + * + * @todo add more jobs, such as rekeying. + * + * @ingroup jobs + */ +enum job_type_t { + /** + * Process an incoming IKEv2-Message. + * + * Job is implemented in class type incoming_packet_job_t + */ + INCOMING_PACKET, + + /** + * Retransmit an IKEv2-Message. + */ + RETRANSMIT_REQUEST, + + /** + * Establish an ike sa as initiator. + * + * Job is implemented in class type initiate_ike_sa_job_t + */ + INITIATE_IKE_SA, + + /** + * Delete an ike sa which is still not established. + * + * Job is implemented in class type delete_half_open_ike_sa_job_t + */ + DELETE_HALF_OPEN_IKE_SA, + + /** + * Delete an ike sa which is established. + * + * Job is implemented in class type delete_established_ike_sa_job_t + */ + DELETE_ESTABLISHED_IKE_SA +}; + +/** + * string mappings for job_type_t + * + * @ingroup jobs + */ +extern mapping_t job_type_m[]; + + +typedef struct job_t job_t; + +/** + * @brief Job-Interface as it is stored in the job queue. + * + * A job consists of a job-type and one or more assigned values. + * + * @b Constructors: + * - None, use specific implementation of the interface. + * + * @ingroup jobs + */ +struct job_t { + + /** + * @brief get type of job. + * + * @param this calling object + * @return type of this job + */ + job_type_t (*get_type) (job_t *this); + + /** + * @brief Destroys a job_t object and all assigned data! + * + * @param job_t calling object + */ + void (*destroy_all) (job_t *job); + + /** + * @brief Destroys a job_t object + * + * @param job_t calling object + */ + void (*destroy) (job_t *job); +}; + + +#endif /*JOB_H_*/ diff --git a/src/charon/queues/jobs/retransmit_request_job.c b/src/charon/queues/jobs/retransmit_request_job.c new file mode 100644 index 000000000..e171df5bd --- /dev/null +++ b/src/charon/queues/jobs/retransmit_request_job.c @@ -0,0 +1,132 @@ +/** + * @file retransmit_request_job.c + * + * @brief Implementation of retransmit_request_job_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 "retransmit_request_job.h" + + + + +typedef struct private_retransmit_request_job_t private_retransmit_request_job_t; + +/** + * Private data of an retransmit_request_job_t Object. + */ +struct private_retransmit_request_job_t { + /** + * Public retransmit_request_job_t interface. + */ + retransmit_request_job_t public; + + /** + * Message ID of the request to resend. + */ + u_int32_t message_id; + + /** + * ID of the IKE_SA which the message belongs to. + */ + ike_sa_id_t *ike_sa_id; + + /** + * Number of times a request was retransmitted + */ + u_int32_t retransmit_count; +}; + + +/** + * Implements job_t.get_type. + */ +static job_type_t get_type(private_retransmit_request_job_t *this) +{ + return RETRANSMIT_REQUEST; +} + +/** + * Implements retransmit_request_job_t.get_ike_sa_id. + */ +static ike_sa_id_t *get_ike_sa_id(private_retransmit_request_job_t *this) +{ + return this->ike_sa_id; +} + +/** + * Implements retransmit_request_job_t.get_retransmit_count. + */ +static u_int32_t get_retransmit_count(private_retransmit_request_job_t *this) +{ + return this->retransmit_count; +} + +/** + * Implements retransmit_request_job_t.increase_retransmit_count. + */ +static void increase_retransmit_count(private_retransmit_request_job_t *this) +{ + this->retransmit_count++; +} + +/** + * Implements retransmit_request_job_t.get_message_id. + */ +static u_int32_t get_message_id(private_retransmit_request_job_t *this) +{ + return this->message_id; +} + + +/** + * Implements job_t.destroy. + */ +static void destroy(private_retransmit_request_job_t *this) +{ + this->ike_sa_id->destroy(this->ike_sa_id); + free(this); +} + +/* + * Described in header. + */ +retransmit_request_job_t *retransmit_request_job_create(u_int32_t message_id,ike_sa_id_t *ike_sa_id) +{ + private_retransmit_request_job_t *this = malloc_thing(private_retransmit_request_job_t); + + /* interface functions */ + this->public.job_interface.get_type = (job_type_t (*) (job_t *)) get_type; + /* same as destroy */ + this->public.job_interface.destroy_all = (void (*) (job_t *)) destroy; + this->public.job_interface.destroy = (void (*) (job_t *)) destroy; + + /* public functions */ + this->public.get_ike_sa_id = (ike_sa_id_t * (*)(retransmit_request_job_t *)) get_ike_sa_id; + this->public.get_message_id = (u_int32_t (*)(retransmit_request_job_t *)) get_message_id; + this->public.destroy = (void (*)(retransmit_request_job_t *)) destroy; + this->public.get_retransmit_count = (u_int32_t (*)(retransmit_request_job_t *)) get_retransmit_count; + this->public.increase_retransmit_count = (void (*)(retransmit_request_job_t *)) increase_retransmit_count; + + /* private variables */ + this->message_id = message_id; + this->retransmit_count = 0; + this->ike_sa_id = ike_sa_id->clone(ike_sa_id); + + return &(this->public); +} diff --git a/src/charon/queues/jobs/retransmit_request_job.h b/src/charon/queues/jobs/retransmit_request_job.h new file mode 100644 index 000000000..2349d3f5e --- /dev/null +++ b/src/charon/queues/jobs/retransmit_request_job.h @@ -0,0 +1,105 @@ +/** + * @file retransmit_request_job.h + * + * @brief Interface of retransmit_request_job_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef RESEND_MESSAGE_JOB_H_ +#define RESEND_MESSAGE_JOB_H_ + +#include +#include +#include + + +typedef struct retransmit_request_job_t retransmit_request_job_t; + +/** + * @brief Class representing an RETRANSMIT_REQUEST Job. + * + * This job is scheduled every time a request is sent over the + * wire. If the response to the request is not received at schedule + * time, the retransmission will be initiated. + * + * @b Constructors: + * - retransmit_request_job_create() + * + * @ingroup jobs + */ +struct retransmit_request_job_t { + /** + * The job_t interface. + */ + job_t job_interface; + + /** + * @brief Returns the retransmit count for a specific request. + * + * @param this calling retransmit_request_job_t object + * @return retransmit count of request + */ + u_int32_t (*get_retransmit_count) (retransmit_request_job_t *this); + + /** + * @brief Increases number of retransmitt attemps. + * + * @param this calling retransmit_request_job_t object + */ + void (*increase_retransmit_count) (retransmit_request_job_t *this); + + /** + * @brief Returns the message_id of the request to be resent + * + * @param this calling retransmit_request_job_t object + * @return message id of the request to resend + */ + u_int32_t (*get_message_id) (retransmit_request_job_t *this); + + /** + * @brief Returns the ike_sa_id_t object of the IKE_SA + * which the request belongs to + * + * @warning returned ike_sa_id_t object is getting destroyed in + * retransmit_request_job_t.destroy. + * + * @param this calling retransmit_request_job_t object + * @return ike_sa_id_t object to identify IKE_SA (gets NOT cloned) + */ + ike_sa_id_t *(*get_ike_sa_id) (retransmit_request_job_t *this); + + /** + * @brief Destroys an retransmit_request_job_t object. + * + * @param this retransmit_request_job_t object to destroy + */ + void (*destroy) (retransmit_request_job_t *this); +}; + +/** + * @brief Creates a job of type RETRANSMIT_REQUEST. + * + * @param message_id message_id of the request to resend + * @param ike_sa_id identification of the ike_sa as ike_sa_id_t object (gets cloned) + * @return retransmit_request_job_t object + * + * @ingroup jobs + */ +retransmit_request_job_t *retransmit_request_job_create(u_int32_t message_id,ike_sa_id_t *ike_sa_id); + +#endif /* RESEND_MESSAGE_JOB_H_ */ diff --git a/src/charon/queues/send_queue.c b/src/charon/queues/send_queue.c new file mode 100644 index 000000000..6a55d96ab --- /dev/null +++ b/src/charon/queues/send_queue.c @@ -0,0 +1,153 @@ +/** + * @file send_queue.c + * + * @brief Implementation of send_queue_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 + +#include "send_queue.h" + +#include + + +typedef struct private_send_queue_t private_send_queue_t; + +/** + * @brief Private Variables and Functions of send_queue class + * + */ +struct private_send_queue_t { + /** + * Public part of the send_queue_t object + */ + send_queue_t public; + + /** + * The packets are stored in a linked list + */ + linked_list_t *list; + + /** + * access to linked_list is locked through this mutex + */ + pthread_mutex_t mutex; + + /** + * If the queue is empty a thread has to wait + * This condvar is used to wake up such a thread + */ + pthread_cond_t condvar; +}; + + +/** + * implements send_queue_t.get_count + */ +static int get_count(private_send_queue_t *this) +{ + int count; + pthread_mutex_lock(&(this->mutex)); + count = this->list->get_count(this->list); + pthread_mutex_unlock(&(this->mutex)); + return count; +} + +/** + * implements send_queue_t.get + */ +static packet_t *get(private_send_queue_t *this) +{ + int oldstate; + packet_t *packet; + pthread_mutex_lock(&(this->mutex)); + /* go to wait while no packets available */ + + while(this->list->get_count(this->list) == 0) + { + /* add mutex unlock handler for cancellation, enable cancellation */ + pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock, (void*)&(this->mutex)); + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); + pthread_cond_wait( &(this->condvar), &(this->mutex)); + + /* reset cancellation, remove mutex-unlock handler (without executing) */ + pthread_setcancelstate(oldstate, NULL); + pthread_cleanup_pop(0); + } + this->list->remove_first(this->list,(void **)&packet); + pthread_mutex_unlock(&(this->mutex)); + return packet; +} + +/** + * implements send_queue_t.add + */ +static void add(private_send_queue_t *this, packet_t *packet) +{ + pthread_mutex_lock(&(this->mutex)); + this->list->insert_last(this->list,packet); + pthread_cond_signal( &(this->condvar)); + pthread_mutex_unlock(&(this->mutex)); +} + +/** + * implements send_queue_t.destroy + */ +static void destroy (private_send_queue_t *this) +{ + + /* destroy all packets in list before destroying list */ + while (this->list->get_count(this->list) > 0) + { + packet_t *packet; + if (this->list->remove_first(this->list,(void *) &packet) != SUCCESS) + { + this->list->destroy(this->list); + break; + } + packet->destroy(packet); + } + this->list->destroy(this->list); + + pthread_mutex_destroy(&(this->mutex)); + + pthread_cond_destroy(&(this->condvar)); + + free(this); +} + +/* + * + * Documented in header + */ +send_queue_t *send_queue_create(void) +{ + private_send_queue_t *this = malloc_thing(private_send_queue_t); + + this->public.get_count = (int(*)(send_queue_t*)) get_count; + this->public.get = (packet_t*(*)(send_queue_t*)) get; + this->public.add = (void(*)(send_queue_t*, packet_t*)) add; + this->public.destroy = (void(*)(send_queue_t*)) destroy; + + this->list = linked_list_create(); + pthread_mutex_init(&(this->mutex), NULL); + pthread_cond_init(&(this->condvar), NULL); + + return (&this->public); +} diff --git a/src/charon/queues/send_queue.h b/src/charon/queues/send_queue.h new file mode 100644 index 000000000..022a831fe --- /dev/null +++ b/src/charon/queues/send_queue.h @@ -0,0 +1,100 @@ +/** + * @file send_queue.h + * + * @brief Interface of send_queue_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef SEND_QUEUE_H_ +#define SEND_QUEUE_H_ + +#include +#include + + +typedef struct send_queue_t send_queue_t; + +/** + * @brief The send queue stores packet for the sender_t instance. + * + * The sender_t will send them consequently over the wire. + * Although the send-queue is based on a linked_list_t + * all access functions are thread-save implemented. + * + * @b Constructors: + * - send_queue_create() + * + * @ingroup queues + */ +struct send_queue_t { + + /** + * @brief returns number of packets in queue + * + * @param send_queue_t calling object + * @param[out] count integer pointer to store the count in + * @returns number of items in queue + */ + int (*get_count) (send_queue_t *send_queue); + + /** + * @brief get the next packet from the queue. + * + * If the queue is empty, this function blocks until a packet can be returned. + * + * After using, the returned packet has to get destroyed by the caller. + * + * @param send_queue_t calling object + * @return next packet from the queue + */ + packet_t *(*get) (send_queue_t *send_queue); + + /** + * @brief adds a packet to the queue. + * + * This function is non blocking and adds a packet_t to the list. + * The specific packet object has to get destroyed by the thread which + * removes the packet. + * + * @param send_queue_t calling object + * @param packet packet_t to add to the queue (packet is not copied) + */ + void (*add) (send_queue_t *send_queue, packet_t *packet); + + /** + * @brief destroys a send_queue object. + * + * @warning The caller of this function has to make sure + * that no thread is going to add or get a packet from the send_queue + * after calling this function. + * + * @param send_queue_t calling object + */ + void (*destroy) (send_queue_t *send_queue); +}; + +/** + * @brief Creates an empty send_queue_t. + * + * @return send_queue_t object + * + * @ingroup queues + */ +send_queue_t *send_queue_create(void); + +#endif /*SEND_QUEUE_H_*/ diff --git a/src/charon/sa/Makefile.sa b/src/charon/sa/Makefile.sa new file mode 100644 index 000000000..825c19959 --- /dev/null +++ b/src/charon/sa/Makefile.sa @@ -0,0 +1,37 @@ +# Copyright (C) 2005 Jan Hutter, 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 . +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# + +SA_DIR= $(CHARON_DIR)sa/ + +CHARON_OBJS+= $(BUILD_DIR)ike_sa_id.o +$(BUILD_DIR)ike_sa_id.o : $(SA_DIR)ike_sa_id.c $(SA_DIR)ike_sa_id.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)ike_sa_manager.o +$(BUILD_DIR)ike_sa_manager.o : $(SA_DIR)ike_sa_manager.c $(SA_DIR)ike_sa_manager.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)ike_sa.o +$(BUILD_DIR)ike_sa.o : $(SA_DIR)ike_sa.c $(SA_DIR)ike_sa.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)authenticator.o +$(BUILD_DIR)authenticator.o : $(SA_DIR)authenticator.c $(SA_DIR)authenticator.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)child_sa.o +$(BUILD_DIR)child_sa.o : $(SA_DIR)child_sa.c $(SA_DIR)child_sa.h + $(CC) $(CFLAGS) -c -o $@ $< + +include $(SA_DIR)states/Makefile.states \ No newline at end of file diff --git a/src/charon/sa/authenticator.c b/src/charon/sa/authenticator.c new file mode 100644 index 000000000..3aeb8795f --- /dev/null +++ b/src/charon/sa/authenticator.c @@ -0,0 +1,405 @@ +/** + * @file authenticator.c + * + * @brief Implementation of authenticator_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 + +#include "authenticator.h" + +#include + +/** + * Key pad for the AUTH method SHARED_KEY_MESSAGE_INTEGRITY_CODE. + */ +#define IKEV2_KEY_PAD "Key Pad for IKEv2" + + +typedef struct private_authenticator_t private_authenticator_t; + +/** + * Private data of an authenticator_t object. + */ +struct private_authenticator_t { + + /** + * Public authenticator_t interface. + */ + authenticator_t public; + + /** + * Assigned IKE_SA. Needed to get objects of type prf_t and logger_t. + */ + protected_ike_sa_t *ike_sa; + + /** + * PRF taken from the IKE_SA. + */ + prf_t *prf; + + /** + * A logger for. + * + * Using logger of IKE_SA. + */ + logger_t *logger; + + /** + * @brief Creates the octets which are signed (RSA) or MACed (shared secret) as described in section + * 2.15 of RFC. + * + * @param this calling object + * @param last_message the last message to include in created octets + * (either binary form of IKE_SA_INIT request or IKE_SA_INIT response) + * @param other_nonce Nonce data received from other peer + * @param my_id id_payload_t object representing an ID payload + * @param initiator Type of peer. TRUE, if it is original initiator, FALSE otherwise + * @return octets as described in section 2.15. Memory gets allocated and has to get + * destroyed by caller. + */ + chunk_t (*allocate_octets) (private_authenticator_t *this, + chunk_t last_message, + chunk_t other_nonce, + id_payload_t *my_id, + bool initiator); + + /** + * @brief Creates the AUTH data using auth method SHARED_KEY_MESSAGE_INTEGRITY_CODE. + * + * @param this calling object + * @param last_message the last message + * (either binary form of IKE_SA_INIT request or IKE_SA_INIT response) + * @param nonce Nonce data to include in auth data compution + * @param id_payload id_payload_t object representing an ID payload + * @param initiator Type of peer. TRUE, if it is original initiator, FALSE otherwise + * @param shared_secret shared secret as chunk_t. If shared secret is a string, + * the NULL termination is not included. + * @return AUTH data as dscribed in section 2.15 for + * AUTH method SHARED_KEY_MESSAGE_INTEGRITY_CODE. + * Memory gets allocated and has to get destroyed by caller. + */ + chunk_t (*build_preshared_secret_signature) (private_authenticator_t *this, + chunk_t last_message, + chunk_t nonce, + id_payload_t *id_payload, + bool initiator, + chunk_t preshared_secret); +}; + +/** + * Implementation of private_authenticator_t.allocate_octets. + */ +static chunk_t allocate_octets(private_authenticator_t *this, + chunk_t last_message, + chunk_t other_nonce, + id_payload_t *my_id, + bool initiator) +{ + prf_t *prf; + chunk_t id_chunk = my_id->get_data(my_id); + u_int8_t id_with_header[4 + id_chunk.len]; + /* + * IKEv2 for linux (http://sf.net/projects/ikev2/) + * is not compatible with IKEv2 Draft and so not compatible with this + * implementation, cause AUTH data are computed without + * ID type and the three reserved bytes. + */ + chunk_t id_with_header_chunk = {ptr:id_with_header, len: sizeof(id_with_header)}; + u_int8_t *current_pos; + chunk_t octets; + + id_with_header[0] = my_id->get_id_type(my_id); + id_with_header[1] = 0x00; + id_with_header[2] = 0x00; + id_with_header[3] = 0x00; + memcpy(id_with_header + 4,id_chunk.ptr,id_chunk.len); + + if (initiator) + { + prf = this->ike_sa->get_prf_auth_i(this->ike_sa); + } + else + { + prf = this->ike_sa->get_prf_auth_r(this->ike_sa); + } + + /* 4 bytes are id type and reserved fields of id payload */ + octets.len = last_message.len + other_nonce.len + prf->get_block_size(prf); + octets.ptr = malloc(octets.len); + current_pos = octets.ptr; + memcpy(current_pos,last_message.ptr,last_message.len); + current_pos += last_message.len; + memcpy(current_pos,other_nonce.ptr,other_nonce.len); + current_pos += other_nonce.len; + prf->get_bytes(prf, id_with_header_chunk, current_pos); + + this->logger->log_chunk(this->logger,RAW | LEVEL2, "Octets (Mesage + Nonce + prf(Sk_px,Idx)",octets); + return octets; +} + +/** + * Implementation of private_authenticator_t.build_preshared_secret_signature. + */ +static chunk_t build_preshared_secret_signature(private_authenticator_t *this, + chunk_t last_message, + chunk_t nonce, + id_payload_t *id_payload, + bool initiator, + chunk_t preshared_secret) +{ + chunk_t key_pad = {ptr: IKEV2_KEY_PAD, len:strlen(IKEV2_KEY_PAD)}; + u_int8_t key_buffer[this->prf->get_block_size(this->prf)]; + chunk_t key = {ptr: key_buffer, len: sizeof(key_buffer)}; + chunk_t auth_data; + + chunk_t octets = this->allocate_octets(this,last_message,nonce,id_payload,initiator); + + /* AUTH = prf(prf(Shared Secret,"Key Pad for IKEv2"), ) */ + this->prf->set_key(this->prf, preshared_secret); + this->prf->get_bytes(this->prf, key_pad, key_buffer); + this->prf->set_key(this->prf, key); + this->prf->allocate_bytes(this->prf, octets, &auth_data); + chunk_free(&octets); + this->logger->log_chunk(this->logger,RAW | LEVEL2, "Authenticated data",auth_data); + + return auth_data; +} + +/** + * Implementation of authenticator_t.verify_auth_data. + */ +static status_t verify_auth_data (private_authenticator_t *this, + auth_payload_t *auth_payload, + chunk_t last_received_packet, + chunk_t my_nonce, + id_payload_t *other_id_payload, + bool initiator) +{ + switch(auth_payload->get_auth_method(auth_payload)) + { + case SHARED_KEY_MESSAGE_INTEGRITY_CODE: + { + identification_t *other_id = other_id_payload->get_identification(other_id_payload); + chunk_t auth_data = auth_payload->get_data(auth_payload); + chunk_t preshared_secret; + status_t status; + + status = charon->credentials->get_shared_secret(charon->credentials, + other_id, + &preshared_secret); + if (status != SUCCESS) + { + this->logger->log(this->logger, ERROR|LEVEL1, "No shared secret found for %s", + other_id->get_string(other_id)); + other_id->destroy(other_id); + return status; + } + + chunk_t my_auth_data = this->build_preshared_secret_signature(this, + last_received_packet, + my_nonce, + other_id_payload, + initiator, + preshared_secret); + chunk_free(&preshared_secret); + + if (auth_data.len != my_auth_data.len) + { + chunk_free(&my_auth_data); + status = FAILED; + } + else if (memcmp(auth_data.ptr,my_auth_data.ptr, my_auth_data.len) == 0) + { + this->logger->log(this->logger, CONTROL, "Authentication of %s with preshared secret successful", + other_id->get_string(other_id)); + status = SUCCESS; + } + else + { + this->logger->log(this->logger, CONTROL, "Authentication of %s with preshared secret failed", + other_id->get_string(other_id)); + status = FAILED; + } + other_id->destroy(other_id); + chunk_free(&my_auth_data); + return status; + } + case RSA_DIGITAL_SIGNATURE: + { + identification_t *other_id = other_id_payload->get_identification(other_id_payload); + rsa_public_key_t *public_key; + status_t status; + chunk_t octets, auth_data; + + auth_data = auth_payload->get_data(auth_payload); + + public_key = charon->credentials->get_rsa_public_key(charon->credentials, + other_id); + if (public_key == NULL) + { + this->logger->log(this->logger, ERROR|LEVEL1, "No RSA public key found for %s", + other_id->get_string(other_id)); + other_id->destroy(other_id); + return NOT_FOUND; + } + + octets = this->allocate_octets(this,last_received_packet, my_nonce,other_id_payload, initiator); + + status = public_key->verify_emsa_pkcs1_signature(public_key, octets, auth_data); + if (status == SUCCESS) + { + this->logger->log(this->logger, CONTROL, "Authentication of %s with RSA successful", + other_id->get_string(other_id)); + } + else + { + this->logger->log(this->logger, CONTROL, "Authentication of %s with RSA failed", + other_id->get_string(other_id)); + } + + public_key->destroy(public_key); + other_id->destroy(other_id); + chunk_free(&octets); + return status; + } + default: + { + return NOT_SUPPORTED; + } + } +} + +/** + * Implementation of authenticator_t.compute_auth_data. + */ +static status_t compute_auth_data (private_authenticator_t *this, + auth_payload_t **auth_payload, + chunk_t last_sent_packet, + chunk_t other_nonce, + id_payload_t *my_id_payload, + bool initiator) +{ + connection_t *connection = this->ike_sa->get_connection(this->ike_sa); + + switch(connection->get_auth_method(connection)) + { + case SHARED_KEY_MESSAGE_INTEGRITY_CODE: + { + identification_t *my_id = my_id_payload->get_identification(my_id_payload); + chunk_t preshared_secret; + status_t status; + chunk_t auth_data; + + status = charon->credentials->get_shared_secret(charon->credentials, + my_id, + &preshared_secret); + + if (status != SUCCESS) + { + this->logger->log(this->logger, ERROR|LEVEL1, "No shared secret found for %s", + my_id->get_string(my_id)); + my_id->destroy(my_id); + return status; + } + my_id->destroy(my_id); + + auth_data = this->build_preshared_secret_signature(this, last_sent_packet, other_nonce, + my_id_payload, initiator, preshared_secret); + chunk_free(&preshared_secret); + *auth_payload = auth_payload_create(); + (*auth_payload)->set_auth_method(*auth_payload, SHARED_KEY_MESSAGE_INTEGRITY_CODE); + (*auth_payload)->set_data(*auth_payload, auth_data); + + chunk_free(&auth_data); + return SUCCESS; + } + case RSA_DIGITAL_SIGNATURE: + { + identification_t *my_id = my_id_payload->get_identification(my_id_payload); + rsa_private_key_t *private_key; + status_t status; + chunk_t octets, auth_data; + + private_key = charon->credentials->get_rsa_private_key(charon->credentials, my_id); + if (private_key == NULL) + { + this->logger->log(this->logger, ERROR|LEVEL1, "No RSA private key found for %s", + my_id->get_string(my_id)); + my_id->destroy(my_id); + return NOT_FOUND; + } + my_id->destroy(my_id); + + octets = this->allocate_octets(this,last_sent_packet,other_nonce,my_id_payload,initiator); + + status = private_key->build_emsa_pkcs1_signature(private_key, HASH_SHA1, octets, &auth_data); + chunk_free(&octets); + if (status != SUCCESS) + { + private_key->destroy(private_key); + return status; + } + + *auth_payload = auth_payload_create(); + (*auth_payload)->set_auth_method(*auth_payload, RSA_DIGITAL_SIGNATURE); + (*auth_payload)->set_data(*auth_payload, auth_data); + + private_key->destroy(private_key); + chunk_free(&auth_data); + return SUCCESS; + } + default: + { + return NOT_SUPPORTED; + } + } +} + +/** + * Implementation of authenticator_t.destroy. + */ +static void destroy (private_authenticator_t *this) +{ + free(this); +} + +/* + * Described in header. + */ +authenticator_t *authenticator_create(protected_ike_sa_t *ike_sa) +{ + private_authenticator_t *this = malloc_thing(private_authenticator_t); + + /* Public functions */ + this->public.destroy = (void(*)(authenticator_t*))destroy; + this->public.verify_auth_data = (status_t (*) (authenticator_t *,auth_payload_t *, chunk_t ,chunk_t ,id_payload_t *,bool)) verify_auth_data; + this->public.compute_auth_data = (status_t (*) (authenticator_t *,auth_payload_t **, chunk_t ,chunk_t ,id_payload_t *,bool)) compute_auth_data; + + /* private functions */ + this->allocate_octets = allocate_octets; + this->build_preshared_secret_signature = build_preshared_secret_signature; + + /* private data */ + this->ike_sa = ike_sa; + this->prf = this->ike_sa->get_prf(this->ike_sa); + this->logger = logger_manager->get_logger(logger_manager, IKE_SA); + + return &(this->public); +} diff --git a/src/charon/sa/authenticator.h b/src/charon/sa/authenticator.h new file mode 100644 index 000000000..b6bc317ac --- /dev/null +++ b/src/charon/sa/authenticator.h @@ -0,0 +1,138 @@ +/** + * @file authenticator.h + * + * @brief Interface of authenticator_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef AUTHENTICATOR_H_ +#define AUTHENTICATOR_H_ + +#include +#include +#include +#include +#include + + +typedef struct authenticator_t authenticator_t; + +/** + * @brief Class used to authenticate a peer. + * + * Currently the following two AUTH methods are supported: + * - SHARED_KEY_MESSAGE_INTEGRITY_CODE + * - RSA_DIGITAL_SIGNATURE + * + * This class retrieves needed data for specific AUTH methods (RSA keys, shared secrets, etc.) + * over an internal stored protected_ike_sa_t object or directly from the configuration_t over + * the daemon_t object "charon". + * + * @b Constructors: + * - authenticator_create() + * + * @ingroup sa + */ +struct authenticator_t { + + /** + * @brief Verify's given authentication data. + * + * To verify a received AUTH payload the following data must be provided: + * - the last received IKEv2 Message from the other peer in binary form + * - the nonce value sent to the other peer + * - the ID payload of the other peer + * + * @param this calling object + * @param last_received_packet binary representation of the last received IKEv2-Message + * @param my_nonce the sent nonce (without payload header) + * @param other_id_payload the ID payload received from other peer + * @param initiator type of other peer. TRUE, if it is original initiator, FALSE otherwise + * + * @todo Document RSA error status types + * + * @return + * - SUCCESS if verification successful + * - FAILED if verification failed + * - NOT_SUPPORTED if AUTH method not supported + * - NOT_FOUND if the data for specific AUTH method could not be found + * (e.g. shared secret, rsa key) + */ + status_t (*verify_auth_data) (authenticator_t *this, + auth_payload_t *auth_payload, + chunk_t last_received_packet, + chunk_t my_nonce, + id_payload_t *other_id_payload, + bool initiator); + + /** + * @brief Computes authentication data and creates specific AUTH payload. + * + * To create an AUTH payload, the following data must be provided: + * - the last sent IKEv2 Message in binary form + * - the nonce value received from the other peer + * - the ID payload of myself + * + * @param this calling object + * @param[out] auth_payload The object of typee auth_payload_t will be created at pointing location + * @param last_sent_packet binary representation of the last sent IKEv2-Message + * @param other_nonce the received nonce (without payload header) + * @param my_id_payload the ID payload going to send to other peer + * @param initiator type of myself. TRUE, if I'm original initiator, FALSE otherwise + * + * @todo Document RSA error status types + * + * @return + * - SUCCESS if authentication data could be computed + * - NOT_SUPPORTED if AUTH method not supported + * - NOT_FOUND if the data for AUTH method could not be found + */ + status_t (*compute_auth_data) (authenticator_t *this, + auth_payload_t **auth_payload, + chunk_t last_sent_packet, + chunk_t other_nonce, + id_payload_t *my_id_payload, + bool initiator); + + /** + * @brief Destroys a authenticator_t object. + * + * @param this calling object + */ + void (*destroy) (authenticator_t *this); +}; + +/** + * @brief Creates an authenticator object. + * + * @warning: The following functions of the assigned protected_ike_sa_t object + * must return a valid value: + * - protected_ike_sa_t.get_policy + * - protected_ike_sa_t.get_prf + * - protected_ike_sa_t.get_logger + * This preconditions are not given in IKE_SA states INITIATOR_INIT or RESPONDER_INIT! + * + * @param ike_sa object of type protected_ike_sa_t + * + * @return authenticator_t object + * + * @ingroup sa + */ +authenticator_t *authenticator_create(protected_ike_sa_t *ike_sa); + +#endif /* AUTHENTICATOR_H_ */ diff --git a/src/charon/sa/child_sa.c b/src/charon/sa/child_sa.c new file mode 100644 index 000000000..a678ea9b8 --- /dev/null +++ b/src/charon/sa/child_sa.c @@ -0,0 +1,590 @@ +/** + * @file child_sa.c + * + * @brief Implementation of child_sa_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 + +#include "child_sa.h" + +#include + + +typedef struct sa_policy_t sa_policy_t; + +/** + * Struct used to store information for a policy. This + * is needed since we must provide all this information + * for deleting a policy... + */ +struct sa_policy_t { + + /** + * Network on local side + */ + host_t *my_net; + + /** + * Network on remote side + */ + host_t *other_net; + + /** + * Number of bits for local network (subnet size) + */ + u_int8_t my_net_mask; + + /** + * Number of bits for remote network (subnet size) + */ + u_int8_t other_net_mask; + + /** + * Protocol for this policy, such as TCP/UDP/ICMP... + */ + int upper_proto; +}; + +typedef struct private_child_sa_t private_child_sa_t; + +/** + * Private data of a child_sa_t object. + */ +struct private_child_sa_t { + /** + * Public interface of child_sa_t. + */ + child_sa_t public; + + /** + * IP of this peer + */ + host_t *me; + + /** + * IP of other peer + */ + host_t *other; + + /** + * Local security parameter index for AH protocol, 0 if not used + */ + u_int32_t my_ah_spi; + + /** + * Local security parameter index for ESP protocol, 0 if not used + */ + u_int32_t my_esp_spi; + + /** + * Remote security parameter index for AH protocol, 0 if not used + */ + u_int32_t other_ah_spi; + + /** + * Remote security parameter index for ESP protocol, 0 if not used + */ + u_int32_t other_esp_spi; + + /** + * List containing policy_id_t objects + */ + linked_list_t *policies; + + /** + * reqid used for this child_sa + */ + u_int32_t reqid; + + /** + * CHILD_SAs own logger + */ + logger_t *logger; +}; + +/** + * Implements child_sa_t.alloc + */ +static status_t alloc(private_child_sa_t *this, linked_list_t *proposals) +{ + protocol_id_t protocols[2]; + iterator_t *iterator; + proposal_t *proposal; + status_t status; + u_int i; + + /* iterator through proposals */ + iterator = proposals->create_iterator(proposals, TRUE); + while(iterator->has_next(iterator)) + { + iterator->current(iterator, (void**)&proposal); + proposal->get_protocols(proposal, protocols); + + /* check all protocols */ + for (i = 0; i<2; i++) + { + switch (protocols[i]) + { + case PROTO_AH: + /* do we already have an spi for AH?*/ + if (this->my_ah_spi == 0) + { + /* nope, get one */ + status = charon->kernel_interface->get_spi( + charon->kernel_interface, + this->me, this->other, + PROTO_AH, FALSE, + &(this->my_ah_spi)); + } + /* update proposal */ + proposal->set_spi(proposal, PROTO_AH, (u_int64_t)this->my_ah_spi); + break; + case PROTO_ESP: + /* do we already have an spi for ESP?*/ + if (this->my_esp_spi == 0) + { + /* nope, get one */ + status = charon->kernel_interface->get_spi( + charon->kernel_interface, + this->me, this->other, + PROTO_ESP, FALSE, + &(this->my_esp_spi)); + } + /* update proposal */ + proposal->set_spi(proposal, PROTO_ESP, (u_int64_t)this->my_esp_spi); + break; + default: + break; + } + if (status != SUCCESS) + { + iterator->destroy(iterator); + return FAILED; + } + } + } + iterator->destroy(iterator); + return SUCCESS; +} + +static status_t install(private_child_sa_t *this, proposal_t *proposal, prf_plus_t *prf_plus, bool mine) +{ + protocol_id_t protocols[2]; + u_int32_t spi; + encryption_algorithm_t enc_algo; + integrity_algorithm_t int_algo; + chunk_t enc_key, int_key; + algorithm_t *algo; + crypter_t *crypter; + signer_t *signer; + size_t key_size; + host_t *src; + host_t *dst; + status_t status; + u_int i; + + /* we must assign the roles to correctly set up the SAs */ + if (mine) + { + src = this->me; + dst = this->other; + } + else + { + dst = this->me; + src = this->other; + } + + proposal->get_protocols(proposal, protocols); + /* derive keys in order as protocols appear */ + for (i = 0; i<2; i++) + { + if (protocols[i] != PROTO_NONE) + { + + /* now we have to decide which spi to use. Use self allocated, if "mine", + * or the one in the proposal, if not "mine" (others). */ + if (mine) + { + if (protocols[i] == PROTO_AH) + { + spi = this->my_ah_spi; + } + else + { + spi = this->my_esp_spi; + } + } + else /* use proposals spi */ + { + spi = proposal->get_spi(proposal, protocols[i]); + if (protocols[i] == PROTO_AH) + { + this->other_ah_spi = spi; + } + else + { + this->other_esp_spi = spi; + } + } + + /* derive encryption key first */ + if (proposal->get_algorithm(proposal, protocols[i], ENCRYPTION_ALGORITHM, &algo)) + { + enc_algo = algo->algorithm; + this->logger->log(this->logger, CONTROL|LEVEL1, "%s for %s: using %s %s, ", + mapping_find(protocol_id_m, protocols[i]), + mine ? "me" : "other", + mapping_find(transform_type_m, ENCRYPTION_ALGORITHM), + mapping_find(encryption_algorithm_m, enc_algo)); + + /* we must create a (unused) crypter, since its the only way to get the size + * of the key. This is not so nice, since charon must support all algorithms + * the kernel supports... + * TODO: build something of a encryption algorithm lookup function + */ + crypter = crypter_create(enc_algo, algo->key_size); + key_size = crypter->get_key_size(crypter); + crypter->destroy(crypter); + prf_plus->allocate_bytes(prf_plus, key_size, &enc_key); + this->logger->log_chunk(this->logger, PRIVATE, "key:", enc_key); + } + else + { + enc_algo = ENCR_UNDEFINED; + } + + /* derive integrity key */ + if (proposal->get_algorithm(proposal, protocols[i], INTEGRITY_ALGORITHM, &algo)) + { + int_algo = algo->algorithm; + this->logger->log(this->logger, CONTROL|LEVEL1, "%s for %s: using %s %s,", + mapping_find(protocol_id_m, protocols[i]), + mine ? "me" : "other", + mapping_find(transform_type_m, INTEGRITY_ALGORITHM), + mapping_find(integrity_algorithm_m, algo->algorithm)); + + signer = signer_create(int_algo); + key_size = signer->get_key_size(signer); + signer->destroy(signer); + prf_plus->allocate_bytes(prf_plus, key_size, &int_key); + this->logger->log_chunk(this->logger, PRIVATE, "key:", int_key); + } + else + { + int_algo = AUTH_UNDEFINED; + } + /* send keys down to kernel */ + this->logger->log(this->logger, CONTROL|LEVEL1, + "installing 0x%.8x for %s, src %s dst %s", + ntohl(spi), mapping_find(protocol_id_m, protocols[i]), + src->get_address(src), dst->get_address(dst)); + status = charon->kernel_interface->add_sa(charon->kernel_interface, + src, dst, + spi, protocols[i], + this->reqid, + enc_algo, enc_key, + int_algo, int_key, mine); + /* clean up for next round */ + if (enc_algo != ENCR_UNDEFINED) + { + chunk_free(&enc_key); + } + if (int_algo != AUTH_UNDEFINED) + { + chunk_free(&int_key); + } + + if (status != SUCCESS) + { + return FAILED; + } + + + } + } + return SUCCESS; +} + +static status_t add(private_child_sa_t *this, proposal_t *proposal, prf_plus_t *prf_plus) +{ + linked_list_t *list; + + /* install others (initiators) SAs*/ + if (install(this, proposal, prf_plus, FALSE) != SUCCESS) + { + return FAILED; + } + + /* get SPIs for our SAs */ + list = linked_list_create(); + list->insert_last(list, proposal); + if (alloc(this, list) != SUCCESS) + { + list->destroy(list); + return FAILED; + } + list->destroy(list); + + /* install our (responders) SAs */ + if (install(this, proposal, prf_plus, TRUE) != SUCCESS) + { + return FAILED; + } + + return SUCCESS; +} + +static status_t update(private_child_sa_t *this, proposal_t *proposal, prf_plus_t *prf_plus) +{ + /* install our (initator) SAs */ + if (install(this, proposal, prf_plus, TRUE) != SUCCESS) + { + return FAILED; + } + /* install his (responder) SAs */ + if (install(this, proposal, prf_plus, FALSE) != SUCCESS) + { + return FAILED; + } + + return SUCCESS; +} + +static status_t add_policies(private_child_sa_t *this, linked_list_t *my_ts_list, linked_list_t *other_ts_list) +{ + iterator_t *my_iter, *other_iter; + traffic_selector_t *my_ts, *other_ts; + + /* iterate over both lists */ + my_iter = my_ts_list->create_iterator(my_ts_list, TRUE); + other_iter = other_ts_list->create_iterator(other_ts_list, TRUE); + while (my_iter->has_next(my_iter)) + { + my_iter->current(my_iter, (void**)&my_ts); + other_iter->reset(other_iter); + while (other_iter->has_next(other_iter)) + { + /* set up policies for every entry in my_ts_list to every entry in other_ts_list */ + int family; + chunk_t from_addr; + u_int16_t from_port, to_port; + sa_policy_t *policy; + status_t status; + + other_iter->current(other_iter, (void**)&other_ts); + + /* only set up policies if protocol matches */ + if (my_ts->get_protocol(my_ts) != other_ts->get_protocol(other_ts)) + { + continue; + } + policy = malloc_thing(sa_policy_t); + policy->upper_proto = my_ts->get_protocol(my_ts); + + /* calculate net and ports for local side */ + family = my_ts->get_type(my_ts) == TS_IPV4_ADDR_RANGE ? AF_INET : AF_INET6; + from_addr = my_ts->get_from_address(my_ts); + from_port = my_ts->get_from_port(my_ts); + to_port = my_ts->get_to_port(my_ts); + from_port = (from_port != to_port) ? 0 : from_port; + policy->my_net = host_create_from_chunk(family, from_addr, from_port); + policy->my_net_mask = my_ts->get_netmask(my_ts); + chunk_free(&from_addr); + + /* calculate net and ports for remote side */ + family = other_ts->get_type(other_ts) == TS_IPV4_ADDR_RANGE ? AF_INET : AF_INET6; + from_addr = other_ts->get_from_address(other_ts); + from_port = other_ts->get_from_port(other_ts); + to_port = other_ts->get_to_port(other_ts); + from_port = (from_port != to_port) ? 0 : from_port; + policy->other_net = host_create_from_chunk(family, from_addr, from_port); + policy->other_net_mask = other_ts->get_netmask(other_ts); + chunk_free(&from_addr); + + /* install 3 policies: out, in and forward */ + status = charon->kernel_interface->add_policy(charon->kernel_interface, + this->me, this->other, + policy->my_net, policy->other_net, + policy->my_net_mask, policy->other_net_mask, + XFRM_POLICY_OUT, policy->upper_proto, + this->my_ah_spi, this->my_esp_spi, + this->reqid); + + status |= charon->kernel_interface->add_policy(charon->kernel_interface, + this->other, this->me, + policy->other_net, policy->my_net, + policy->other_net_mask, policy->my_net_mask, + XFRM_POLICY_IN, policy->upper_proto, + this->my_ah_spi, this->my_esp_spi, + this->reqid); + + status |= charon->kernel_interface->add_policy(charon->kernel_interface, + this->other, this->me, + policy->other_net, policy->my_net, + policy->other_net_mask, policy->my_net_mask, + XFRM_POLICY_FWD, policy->upper_proto, + this->my_ah_spi, this->my_esp_spi, + this->reqid); + + if (status != SUCCESS) + { + my_iter->destroy(my_iter); + other_iter->destroy(other_iter); + policy->my_net->destroy(policy->my_net); + policy->other_net->destroy(policy->other_net); + free(policy); + return status; + } + + /* add it to the policy list, since we want to know which policies we own */ + this->policies->insert_last(this->policies, policy); + } + } + + my_iter->destroy(my_iter); + other_iter->destroy(other_iter); + return SUCCESS; +} + +/** + * Implementation of child_sa_t.log_status. + */ +static void log_status(private_child_sa_t *this, logger_t *logger, char* name) +{ + iterator_t *iterator; + sa_policy_t *policy; + struct protoent *proto; + char proto_buf[8] = ""; + char *proto_name = proto_buf; + + if (logger == NULL) + { + logger = this->logger; + } + logger->log(logger, CONTROL|LEVEL1, "\"%s\": protected with ESP (0x%x/0x%x), AH (0x%x,0x%x):", + name, + htonl(this->my_esp_spi), htonl(this->other_esp_spi), + htonl(this->my_ah_spi), htonl(this->other_ah_spi)); + iterator = this->policies->create_iterator(this->policies, TRUE); + while (iterator->has_next(iterator)) + { + iterator->current(iterator, (void**)&policy); + if (policy->upper_proto) + { + proto = getprotobynumber(policy->upper_proto); + if (proto) + { + proto_name = proto->p_name; + } + else + { + snprintf(proto_buf, sizeof(proto_buf), "<%d>", policy->upper_proto); + } + } + logger->log(logger, CONTROL, "\"%s\": %s/%d==%s==%s/%d", + name, + policy->my_net->get_address(policy->my_net), policy->my_net_mask, + proto_name, + policy->other_net->get_address(policy->other_net), policy->other_net_mask); + } + iterator->destroy(iterator); +} + +/** + * Implementation of child_sa_t.destroy. + */ +static void destroy(private_child_sa_t *this) +{ + /* delete all policys in the kernel */ + sa_policy_t *policy; + while (this->policies->remove_last(this->policies, (void**)&policy) == SUCCESS) + { + charon->kernel_interface->del_policy(charon->kernel_interface, + this->me, this->other, + policy->my_net, policy->other_net, + policy->my_net_mask, policy->other_net_mask, + XFRM_POLICY_OUT, policy->upper_proto); + + charon->kernel_interface->del_policy(charon->kernel_interface, + this->other, this->me, + policy->other_net, policy->my_net, + policy->other_net_mask, policy->my_net_mask, + XFRM_POLICY_IN, policy->upper_proto); + + charon->kernel_interface->del_policy(charon->kernel_interface, + this->other, this->me, + policy->other_net, policy->my_net, + policy->other_net_mask, policy->my_net_mask, + XFRM_POLICY_FWD, policy->upper_proto); + + policy->my_net->destroy(policy->my_net); + policy->other_net->destroy(policy->other_net); + free(policy); + } + this->policies->destroy(this->policies); + + /* delete SAs in the kernel, if they are set up */ + if (this->my_ah_spi) + { + charon->kernel_interface->del_sa(charon->kernel_interface, + this->other, this->my_ah_spi, PROTO_AH); + charon->kernel_interface->del_sa(charon->kernel_interface, + this->me, this->other_ah_spi, PROTO_AH); + } + if (this->my_esp_spi) + { + charon->kernel_interface->del_sa(charon->kernel_interface, + this->other, this->my_esp_spi, PROTO_ESP); + charon->kernel_interface->del_sa(charon->kernel_interface, + this->me, this->other_esp_spi, PROTO_ESP); + } + free(this); +} + +/* + * Described in header. + */ +child_sa_t * child_sa_create(host_t *me, host_t* other) +{ + static u_int32_t reqid = 0xc0000000; + private_child_sa_t *this = malloc_thing(private_child_sa_t); + + /* public functions */ + this->public.alloc = (status_t(*)(child_sa_t*,linked_list_t*))alloc; + this->public.add = (status_t(*)(child_sa_t*,proposal_t*,prf_plus_t*))add; + this->public.update = (status_t(*)(child_sa_t*,proposal_t*,prf_plus_t*))update; + this->public.add_policies = (status_t (*)(child_sa_t*, linked_list_t*,linked_list_t*))add_policies; + this->public.log_status = (void (*)(child_sa_t*, logger_t*, char*))log_status; + this->public.destroy = (void(*)(child_sa_t*))destroy; + + /* private data */ + this->logger = logger_manager->get_logger(logger_manager, CHILD_SA); + this->me = me; + this->other = other; + this->my_ah_spi = 0; + this->my_esp_spi = 0; + this->other_ah_spi = 0; + this->other_esp_spi = 0; + this->reqid = reqid++; + this->policies = linked_list_create(); + + return (&this->public); +} diff --git a/src/charon/sa/child_sa.h b/src/charon/sa/child_sa.h new file mode 100644 index 000000000..6ccbff13f --- /dev/null +++ b/src/charon/sa/child_sa.h @@ -0,0 +1,149 @@ +/** + * @file child_sa.h + * + * @brief Interface of child_sa_t. + * + */ + +/* + * Copyright (C) 2005 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + + +#ifndef CHILD_SA_H_ +#define CHILD_SA_H_ + +#include +#include +#include +#include + +typedef struct child_sa_t child_sa_t; + +/** + * @brief Represents multiple IPsec SAs between two hosts. + * + * A child_sa_t contains multiple SAs. SAs for both + * directions are managed in one child_sa_t object, and + * if both AH and ESP is set up, both protocols are managed + * by one child_sa_t. This means we can have two or + * in the AH+ESP case four IPsec-SAs in one child_sa_t. + * + * The procedure for child sa setup is as follows: + * - A gets SPIs for a proposal via child_sa_t.alloc + * - A send the updated proposal to B + * - B selects a suitable proposal + * - B calls child_sa_t.add to add and update the selected proposal + * - B sends the updated proposal to A + * - A calls child_sa_t.update to update the already allocated SPIs with the chosen proposal + * + * Once SAs are set up, policies can be added using add_policies. + * + * + * @b Constructors: + * - child_sa_create() + * + * @ingroup sa + */ +struct child_sa_t { + + /** + * @brief Allocate SPIs for a given proposals. + * + * Since the kernel manages SPIs for us, we need + * to allocate them. If the proposal contains more + * than one protocol, for each protocol an SPI is + * allocated. SPIs are stored internally and written + * back to the proposal. + * + * @param this calling object + * @param proposal proposal for which SPIs are allocated + */ + status_t (*alloc)(child_sa_t *this, linked_list_t* proposals); + + /** + * @brief Install the kernel SAs for a proposal. + * + * Since the kernel manages SPIs for us, we need + * to allocate them. If the proposal contains more + * than one protocol, for each protocol an SPI is + * allocated. SPIs are stored internally and written + * back to the proposal. + * + * @param this calling object + * @param proposal proposal for which SPIs are allocated + * @param prf_plus key material to use for key derivation + */ + status_t (*add)(child_sa_t *this, proposal_t *proposal, prf_plus_t *prf_plus); + + /** + * @brief Install the kernel SAs for a proposal, if SPIs already allocated. + * + * This one updates the SAs in the kernel, which are + * allocated via alloc, with a selected proposals. + * + * @param this calling object + * @param proposal proposal for which SPIs are allocated + * @param prf_plus key material to use for key derivation + */ + status_t (*update)(child_sa_t *this, proposal_t *proposal, prf_plus_t *prf_plus); + + /** + * @brief Install the policies using some traffic selectors. + * + * Spplied lists of traffic_selector_t's specify the policies + * to use for this child sa. + * + * @param this calling object + * @param my_ts traffic selectors for local site + * @param other_ts traffic selectors for remote site + * @return SUCCESS or FAILED + */ + status_t (*add_policies) (child_sa_t *this, linked_list_t *my_ts_list, linked_list_t *other_ts_list); + + /** + * @brief Log the status of a child_sa to a logger. + * + * The status of ESP/AH SAs is logged with the supplied logger in + * a human readable form. + * Supplying NULL as logger uses the internal child_sa logger + * to do the logging. The name is only a log-prefix without further + * meaning. + * + * @param this calling object + * @param logger logger to use for logging + * @param name connection name + */ + void (*log_status) (child_sa_t *this, logger_t *logger, char *name); + + /** + * @brief Destroys a child_sa. + * + * @param this calling object + */ + void (*destroy) (child_sa_t *this); +}; + +/** + * @brief Constructor to create a new child_sa_t. + * + * @param me own address + * @param other remote address + * @return child_sa_t object + * + * @ingroup sa + */ +child_sa_t * child_sa_create(host_t *me, host_t *other); + +#endif /*CHILD_SA_H_*/ diff --git a/src/charon/sa/ike_sa.c b/src/charon/sa/ike_sa.c new file mode 100644 index 000000000..6322eb8e9 --- /dev/null +++ b/src/charon/sa/ike_sa.c @@ -0,0 +1,1199 @@ +/** + * @file ike_sa.c + * + * @brief Implementation of ike_sa_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 + +#include "ike_sa.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + + +typedef struct private_ike_sa_t private_ike_sa_t; + +/** + * Private data of an ike_sa_t object. + */ +struct private_ike_sa_t { + + /** + * Protected part of a ike_sa_t object. + */ + protected_ike_sa_t protected; + + /** + * Identifier for the current IKE_SA. + */ + ike_sa_id_t *ike_sa_id; + + /** + * Linked List containing the child sa's of the current IKE_SA. + */ + linked_list_t *child_sas; + + /** + * Current state of the IKE_SA represented as state_t object. + * + * A state object representates one of the following states and is processing + * messages in the specific state: + * - INITIATOR_INIT + * - RESPONDER_INIT + * - IKE_SA_INIT_REQUESTED + * - IKE_SA_INIT_RESPONDED + * - IKE_AUTH_REQUESTED + * -IKE_SA_ESTABLISHED + */ + state_t *current_state; + + /** + * INIT configuration, needed for the IKE_SA_INIT exchange. + * + * Gets set in states: + * - INITATOR_INIT + * - RESPONDER_INIT + * + * Available in states: + * - IKE_SA_INIT_REQUESTED + * - IKE_SA_INIT_RESPONDED + * - IKE_AUTH_REQUESTED + * -IKE_SA_ESTABLISHED + */ + connection_t *connection; + + /** + * SA configuration, needed for all other exchanges after IKE_SA_INIT exchange. + * + * Gets set in states: + * - IKE_SA_INIT_REQUESTED + * - IKE_SA_INIT_RESPONDED + * + * Available in states: + * - IKE_AUTH_REQUESTED + * -IKE_SA_ESTABLISHED + */ + policy_t *policy; + + /** + * This SA's source for random data. + * + * Is available in every state. + */ + randomizer_t *randomizer; + + /** + * The last responded message. + */ + message_t *last_responded_message; + + /** + * The ast requested message. + */ + message_t *last_requested_message; + + /** + * Crypter object for initiator. + */ + crypter_t *crypter_initiator; + + /** + * Crypter object for responder. + */ + crypter_t *crypter_responder; + + /** + * Signer object for initiator. + */ + signer_t *signer_initiator; + + /** + * Signer object for responder. + */ + signer_t *signer_responder; + + /** + * Multi purpose prf, set key, use it, forget it + */ + prf_t *prf; + + /** + * Prf function for derivating keymat child SAs + */ + prf_t *child_prf; + + /** + * PRF, with key set to pi_key, used for authentication + */ + prf_t *prf_auth_i; + + /** + * PRF, with key set to pr_key, used for authentication + */ + prf_t *prf_auth_r; + + /** + * Next message id to receive. + */ + u_int32_t message_id_in; + + /** + * Next message id to send. + */ + u_int32_t message_id_out; + + /** + * Last reply id which was successfully received. + */ + int32_t last_replied_message_id; + + /** + * A logger for this IKE_SA. + */ + logger_t *logger; + + /** + * Resends the last sent reply. + * + * @param this calling object + */ + status_t (*resend_last_reply) (private_ike_sa_t *this); +}; + +/** + * Implementation of ike_sa_t.process_message. + */ +static status_t process_message (private_ike_sa_t *this, message_t *message) +{ + u_int32_t message_id; + exchange_type_t exchange_type; + bool is_request; + + /* We must process each request or response from remote host */ + + /* Find out type of message (request or response) */ + is_request = message->get_request(message); + exchange_type = message->get_exchange_type(message); + + this->logger->log(this->logger, CONTROL|LEVEL1, "Process %s of exchange type %s", + (is_request) ? "request" : "response",mapping_find(exchange_type_m,exchange_type)); + + message_id = message->get_message_id(message); + + /* + * It has to be checked, if the message has to be resent cause of lost packets! + */ + if (is_request && (message_id == (this->message_id_in - 1))) + { + /* Message can be resent ! */ + this->logger->log(this->logger, CONTROL|LEVEL1, "Resent request detected. Send stored reply."); + return (this->resend_last_reply(this)); + } + + /* Now, the message id is checked for request AND reply */ + if (is_request) + { + /* In a request, the message has to be this->message_id_in (other case is already handled) */ + if (message_id != this->message_id_in) + { + this->logger->log(this->logger, ERROR | LEVEL1, + "Message request with message id %d received, but %d expected", + message_id,this->message_id_in); + return FAILED; + } + } + else + { + /* In a reply, the message has to be this->message_id_out -1 cause it is the reply to the last sent message*/ + if (message_id != (this->message_id_out - 1)) + { + this->logger->log(this->logger, ERROR | LEVEL1, + "Message reply with message id %d received, but %d expected", + message_id,this->message_id_in); + return FAILED; + } + } + + /* now the message is processed by the current state object. + * The specific state object is responsible to check if a message can be received in + * the state it represents. + * The current state is also responsible to change the state object to the next state + * by calling protected_ike_sa_t.set_new_state*/ + return this->current_state->process_message(this->current_state,message); +} + +/** + * Implementation of protected_ike_sa_t.build_message. + */ +static void build_message(private_ike_sa_t *this, exchange_type_t type, bool request, message_t **message) +{ + message_t *new_message; + host_t *me, *other; + + me = this->connection->get_my_host(this->connection); + other = this->connection->get_other_host(this->connection); + + this->logger->log(this->logger, CONTROL|LEVEL2, "Build empty message"); + new_message = message_create(); + new_message->set_source(new_message, me->clone(me)); + new_message->set_destination(new_message, other->clone(other)); + new_message->set_exchange_type(new_message, type); + new_message->set_request(new_message, request); + new_message->set_message_id(new_message, (request) ? this->message_id_out : this->message_id_in); + new_message->set_ike_sa_id(new_message, this->ike_sa_id); + + *message = new_message; +} + +/** + * Implementation of protected_ike_sa_t.initiate_connection. + */ +static status_t initiate_connection(private_ike_sa_t *this, connection_t *connection) +{ + initiator_init_t *current_state; + + /* Work is done in state object of type INITIATOR_INIT. All other states are not + * initial states and so don't have a initiate_connection function */ + + if (this->current_state->get_state(this->current_state) != INITIATOR_INIT) + { + return FAILED; + } + + current_state = (initiator_init_t *) this->current_state; + + return current_state->initiate_connection(current_state, connection); +} + +/** + * Implementation of ike_sa_t.send_delete_ike_sa_request. + */ +static void send_delete_ike_sa_request (private_ike_sa_t *this) +{ + message_t *informational_request; + delete_payload_t *delete_payload; + crypter_t *crypter; + signer_t *signer; + packet_t *packet; + status_t status; + + if (this->current_state->get_state(this->current_state) != IKE_SA_ESTABLISHED) + { + return; + } + + /* build empty INFORMATIONAL message */ + this->protected.build_message(&(this->protected), INFORMATIONAL, TRUE, &informational_request); + + delete_payload = delete_payload_create(); + delete_payload->set_protocol_id(delete_payload, PROTO_IKE); + + informational_request->add_payload(informational_request,(payload_t *)delete_payload); + + if (this->ike_sa_id->is_initiator(this->ike_sa_id)) + { + crypter = this->crypter_initiator; + signer = this->signer_initiator; + } + else + { + crypter = this->crypter_responder; + signer = this->signer_responder; + } + + status = informational_request->generate(informational_request, + crypter, + signer, &packet); + informational_request->destroy(informational_request); + if (status != SUCCESS) + { + this->logger->log(this->logger, ERROR, "Could not generate packet from message"); + return ; + } + + charon->send_queue->add(charon->send_queue,packet); +} + +/** + * Implementation of ike_sa_t.get_id. + */ +static ike_sa_id_t* get_id(private_ike_sa_t *this) +{ + return this->ike_sa_id; +} + +/** + * Implementation of ike_sa_t.get_my_host. + */ +static host_t* get_my_host(private_ike_sa_t *this) +{ + return this->connection->get_my_host(this->connection);; +} + +/** + * Implementation of ike_sa_t.get_other_host. + */ +static host_t* get_other_host(private_ike_sa_t *this) +{ + return this->connection->get_other_host(this->connection);; +} + +/** + * Implementation of ike_sa_t.get_my_id. + */ +static identification_t* get_my_id(private_ike_sa_t *this) +{ + return this->connection->get_my_id(this->connection);; +} + +/** + * Implementation of ike_sa_t.get_other_id. + */ +static identification_t* get_other_id(private_ike_sa_t *this) +{ + return this->connection->get_other_id(this->connection);; +} + +/** + * Implementation of private_ike_sa_t.resend_last_reply. + */ +static status_t resend_last_reply(private_ike_sa_t *this) +{ + packet_t *packet; + + this->logger->log(this->logger, CONTROL | LEVEL1, "Going to retransmit last reply"); + packet = this->last_responded_message->get_packet(this->last_responded_message); + charon->send_queue->add(charon->send_queue, packet); + + return SUCCESS; +} + +/** + * Implementation of ike_sa_t.retransmit_request. + */ +status_t retransmit_request (private_ike_sa_t *this, u_int32_t message_id) +{ + packet_t *packet; + + if (this->last_requested_message == NULL) + { + return NOT_FOUND; + } + + if (message_id == this->last_replied_message_id) + { + return NOT_FOUND; + } + + if ((this->last_requested_message->get_message_id(this->last_requested_message)) != message_id) + { + return NOT_FOUND; + } + + this->logger->log(this->logger, CONTROL | LEVEL1, "Going to retransmit message with id %d",message_id); + packet = this->last_requested_message->get_packet(this->last_requested_message); + charon->send_queue->add(charon->send_queue, packet); + + return SUCCESS; +} + +/** + * Implementation of protected_ike_sa_t.set_new_state. + */ +static void set_new_state (private_ike_sa_t *this, state_t *state) +{ + this->logger->log(this->logger, CONTROL, "statechange: %s => %s", + mapping_find(ike_sa_state_m,this->current_state->get_state(this->current_state)), + mapping_find(ike_sa_state_m,state->get_state(state))); + this->current_state = state; +} + +/** + * Implementation of protected_ike_sa_t.get_connection. + */ +static connection_t *get_connection (private_ike_sa_t *this) +{ + return this->connection; +} + +/** + * Implementation of protected_ike_sa_t.set_connection. + */ +static void set_connection (private_ike_sa_t *this,connection_t * connection) +{ + this->connection = connection; +} + +/** + * Implementation of protected_ike_sa_t.get_policy. + */ +static policy_t *get_policy (private_ike_sa_t *this) +{ + return this->policy; +} + +/** + * Implementation of protected_ike_sa_t.set_policy. + */ +static void set_policy (private_ike_sa_t *this,policy_t * policy) +{ + this->policy = policy; +} + +/** + * Implementation of protected_ike_sa_t.get_prf. + */ +static prf_t *get_prf (private_ike_sa_t *this) +{ + return this->prf; +} + +/** + * Implementation of protected_ike_sa_t.get_prf. + */ +static prf_t *get_child_prf (private_ike_sa_t *this) +{ + return this->child_prf; +} + +/** + * Implementation of protected_ike_sa_t.get_prf_auth_i. + */ +static prf_t *get_prf_auth_i (private_ike_sa_t *this) +{ + return this->prf_auth_i; +} + +/** + * Implementation of protected_ike_sa_t.get_prf_auth_r. + */ +static prf_t *get_prf_auth_r (private_ike_sa_t *this) +{ + return this->prf_auth_r; +} + + +/** + * Implementation of protected_ike_sa_t.build_transforms. + */ +static status_t build_transforms(private_ike_sa_t *this, proposal_t *proposal, diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r) +{ + chunk_t nonces, nonces_spis, skeyseed, key, secret; + u_int64_t spi_i, spi_r; + prf_plus_t *prf_plus; + algorithm_t *algo; + size_t key_size; + + /* + * Build the PRF+ instance for deriving keys + */ + if (this->prf != NULL) + { + this->prf->destroy(this->prf); + } + proposal->get_algorithm(proposal, PROTO_IKE, PSEUDO_RANDOM_FUNCTION, &algo); + if (algo == NULL) + { + this->logger->log(this->logger, ERROR|LEVEL2, "No PRF algoithm selected!?"); + return FAILED; + } + this->prf = prf_create(algo->algorithm); + if (this->prf == NULL) + { + this->logger->log(this->logger, ERROR|LEVEL1, + "PSEUDO_RANDOM_FUNCTION %s not supported!", + mapping_find(pseudo_random_function_m, algo->algorithm)); + return FAILED; + } + + /* concatenate nonces = nonce_i | nonce_r */ + nonces = chunk_alloc(nonce_i.len + nonce_r.len); + memcpy(nonces.ptr, nonce_i.ptr, nonce_i.len); + memcpy(nonces.ptr + nonce_i.len, nonce_r.ptr, nonce_r.len); + + /* concatenate prf_seed = nonce_i | nonce_r | spi_i | spi_r */ + nonces_spis = chunk_alloc(nonces.len + 16); + memcpy(nonces_spis.ptr, nonces.ptr, nonces.len); + spi_i = this->ike_sa_id->get_initiator_spi(this->ike_sa_id); + spi_r = this->ike_sa_id->get_responder_spi(this->ike_sa_id); + memcpy(nonces_spis.ptr + nonces.len, &spi_i, 8); + memcpy(nonces_spis.ptr + nonces.len + 8, &spi_r, 8); + + /* SKEYSEED = prf(Ni | Nr, g^ir) */ + dh->get_shared_secret(dh, &secret); + this->logger->log_chunk(this->logger, PRIVATE, "Shared Diffie Hellman secret", secret); + this->prf->set_key(this->prf, nonces); + this->prf->allocate_bytes(this->prf, secret, &skeyseed); + this->logger->log_chunk(this->logger, PRIVATE | LEVEL1, "SKEYSEED", skeyseed); + chunk_free(&secret); + + /* prf+ (SKEYSEED, Ni | Nr | SPIi | SPIr ) + * = SK_d | SK_ai | SK_ar | SK_ei | SK_er | SK_pi | SK_pr + * + * we use the prf directly for prf+ + */ + this->prf->set_key(this->prf, skeyseed); + prf_plus = prf_plus_create(this->prf, nonces_spis); + + /* clean up unused stuff */ + chunk_free(&nonces); + chunk_free(&nonces_spis); + chunk_free(&skeyseed); + + + /* + * We now can derive all of our key. We build the transforms + * directly. + */ + + + /* SK_d used for prf+ to derive keys for child SAs */ + this->child_prf = prf_create(algo->algorithm); + key_size = this->child_prf->get_key_size(this->child_prf); + prf_plus->allocate_bytes(prf_plus, key_size, &key); + this->logger->log_chunk(this->logger, PRIVATE, "Sk_d secret", key); + this->child_prf->set_key(this->child_prf, key); + chunk_free(&key); + + + /* SK_ai/SK_ar used for integrity protection */ + proposal->get_algorithm(proposal, PROTO_IKE, INTEGRITY_ALGORITHM, &algo); + if (algo == NULL) + { + this->logger->log(this->logger, ERROR|LEVEL2, "No integrity algoithm selected?!"); + return FAILED; + } + if (this->signer_initiator != NULL) + { + this->signer_initiator->destroy(this->signer_initiator); + } + if (this->signer_responder != NULL) + { + this->signer_responder->destroy(this->signer_responder); + } + + this->signer_initiator = signer_create(algo->algorithm); + this->signer_responder = signer_create(algo->algorithm); + if (this->signer_initiator == NULL || this->signer_responder == NULL) + { + this->logger->log(this->logger, ERROR|LEVEL1, + "INTEGRITY_ALGORITHM %s not supported!", + mapping_find(integrity_algorithm_m,algo->algorithm)); + return FAILED; + } + key_size = this->signer_initiator->get_key_size(this->signer_initiator); + + prf_plus->allocate_bytes(prf_plus, key_size, &key); + this->logger->log_chunk(this->logger, PRIVATE, "Sk_ai secret", key); + this->signer_initiator->set_key(this->signer_initiator, key); + chunk_free(&key); + + prf_plus->allocate_bytes(prf_plus, key_size, &key); + this->logger->log_chunk(this->logger, PRIVATE, "Sk_ar secret", key); + this->signer_responder->set_key(this->signer_responder, key); + chunk_free(&key); + + + /* SK_ei/SK_er used for encryption */ + proposal->get_algorithm(proposal, PROTO_IKE, ENCRYPTION_ALGORITHM, &algo); + if (algo == NULL) + { + this->logger->log(this->logger, ERROR|LEVEL2, "No encryption algoithm selected!?"); + return FAILED; + } + if (this->crypter_initiator != NULL) + { + this->crypter_initiator->destroy(this->crypter_initiator); + } + if (this->crypter_responder != NULL) + { + this->crypter_responder->destroy(this->crypter_responder); + } + + this->crypter_initiator = crypter_create(algo->algorithm, algo->key_size); + this->crypter_responder = crypter_create(algo->algorithm, algo->key_size); + if (this->crypter_initiator == NULL || this->crypter_responder == NULL) + { + this->logger->log(this->logger, ERROR|LEVEL1, + "ENCRYPTION_ALGORITHM %s (key size %d) not supported!", + mapping_find(encryption_algorithm_m, algo->algorithm), + algo->key_size); + return FAILED; + } + key_size = this->crypter_initiator->get_key_size(this->crypter_initiator); + + prf_plus->allocate_bytes(prf_plus, key_size, &key); + this->logger->log_chunk(this->logger, PRIVATE, "Sk_ei secret", key); + this->crypter_initiator->set_key(this->crypter_initiator, key); + chunk_free(&key); + + prf_plus->allocate_bytes(prf_plus, key_size, &key); + this->logger->log_chunk(this->logger, PRIVATE, "Sk_er secret", key); + this->crypter_responder->set_key(this->crypter_responder, key); + chunk_free(&key); + + /* SK_pi/SK_pr used for authentication */ + proposal->get_algorithm(proposal, PROTO_IKE, PSEUDO_RANDOM_FUNCTION, &algo); + if (this->prf_auth_i != NULL) + { + this->prf_auth_i->destroy(this->prf_auth_i); + } + if (this->prf_auth_r != NULL) + { + this->prf_auth_r->destroy(this->prf_auth_r); + } + + this->prf_auth_i = prf_create(algo->algorithm); + this->prf_auth_r = prf_create(algo->algorithm); + + key_size = this->prf_auth_i->get_key_size(this->prf_auth_i); + prf_plus->allocate_bytes(prf_plus, key_size, &key); + this->logger->log_chunk(this->logger, PRIVATE, "Sk_pi secret", key); + this->prf_auth_i->set_key(this->prf_auth_i, key); + chunk_free(&key); + + prf_plus->allocate_bytes(prf_plus, key_size, &key); + this->logger->log_chunk(this->logger, PRIVATE, "Sk_pr secret", key); + this->prf_auth_r->set_key(this->prf_auth_r, key); + chunk_free(&key); + + /* all done, prf_plus not needed anymore */ + prf_plus->destroy(prf_plus); + + return SUCCESS; +} + +/** + * Implementation of protected_ike_sa_t.get_randomizer. + */ +static randomizer_t *get_randomizer (private_ike_sa_t *this) +{ + return this->randomizer; +} + +/** + * Implementation of protected_ike_sa_t.get_crypter_initiator. + */ +static crypter_t *get_crypter_initiator (private_ike_sa_t *this) +{ + return this->crypter_initiator; +} + +/** + * Implementation of protected_ike_sa_t.get_signer_initiator. + */ +static signer_t *get_signer_initiator (private_ike_sa_t *this) +{ + return this->signer_initiator; +} + +/** + * Implementation of protected_ike_sa_t.get_crypter_responder. + */ +static crypter_t *get_crypter_responder(private_ike_sa_t *this) +{ + return this->crypter_responder; +} + +/** + * Implementation of protected_ike_sa_t.get_signer_responder. + */ +static signer_t *get_signer_responder (private_ike_sa_t *this) +{ + return this->signer_responder; +} + +/** + * Implementation of protected_ike_sa_t.send_request. + */ +static status_t send_request (private_ike_sa_t *this,message_t * message) +{ + retransmit_request_job_t *retransmit_job; + u_int32_t timeout; + crypter_t *crypter; + signer_t *signer; + packet_t *packet; + status_t status; + + if (message->get_message_id(message) != this->message_id_out) + { + this->logger->log(this->logger, ERROR, "Message could not be sent cause id (%d) was not as expected (%d)", + message->get_message_id(message),this->message_id_out); + return FAILED; + } + + /* generate packet */ + this->logger->log(this->logger, CONTROL|LEVEL2, "Generate packet from message"); + + if (this->ike_sa_id->is_initiator(this->ike_sa_id)) + { + crypter = this->crypter_initiator; + signer = this->signer_initiator; + } + else + { + crypter = this->crypter_responder; + signer =this->signer_responder; + } + + status = message->generate(message, crypter,signer, &packet); + if (status != SUCCESS) + { + this->logger->log(this->logger, ERROR, "Could not generate packet from message"); + return FAILED; + } + + this->logger->log(this->logger, CONTROL|LEVEL3, + "Add request packet with message id %d to global send queue", + this->message_id_out); + charon->send_queue->add(charon->send_queue, packet); + + if (this->last_requested_message != NULL) + { + /* destroy message */ + this->last_requested_message->destroy(this->last_requested_message); + } + + this->logger->log(this->logger, CONTROL|LEVEL3, "Replace last requested message with new one"); + this->last_requested_message = message; + + retransmit_job = retransmit_request_job_create(this->message_id_out,this->ike_sa_id); + + status = charon->configuration->get_retransmit_timeout (charon->configuration, + retransmit_job->get_retransmit_count(retransmit_job),&timeout); + + if (status != SUCCESS) + { + this->logger->log(this->logger, CONTROL|LEVEL2, "No retransmit job for message created!"); + retransmit_job->destroy(retransmit_job); + } + else + { + this->logger->log(this->logger, CONTROL|LEVEL2, "Request will be retransmitted in %d ms.",timeout); + charon->event_queue->add_relative(charon->event_queue,(job_t *) retransmit_job,timeout); + } + + /* message counter can now be increased */ + this->logger->log(this->logger, CONTROL|LEVEL3, + "Increase message counter for outgoing messages from %d", + this->message_id_out); + this->message_id_out++; + return SUCCESS; +} + +/** + * Implementation of protected_ike_sa_t.send_response. + */ +static status_t send_response (private_ike_sa_t *this,message_t * message) +{ + crypter_t *crypter; + signer_t *signer; + packet_t *packet; + status_t status; + + if (message->get_message_id(message) != this->message_id_in) + { + this->logger->log(this->logger, ERROR, "Message could not be sent cause id was not as expected"); + return FAILED; + } + + + if (this->ike_sa_id->is_initiator(this->ike_sa_id)) + { + crypter = this->crypter_initiator; + signer = this->signer_initiator; + } + else + { + crypter = this->crypter_responder; + signer =this->signer_responder; + } + + status = message->generate(message, crypter,signer, &packet); + if (status != SUCCESS) + { + this->logger->log(this->logger, ERROR, "Could not generate packet from message"); + return FAILED; + } + + this->logger->log(this->logger, CONTROL|LEVEL3, + "Add response packet with message id %d to global send queue", + this->message_id_in); + charon->send_queue->add(charon->send_queue, packet); + + if (this->last_responded_message != NULL) + { + /* destroy message */ + this->last_responded_message->destroy(this->last_responded_message); + } + + this->logger->log(this->logger, CONTROL|LEVEL3, "Replace last responded message with new one"); + this->last_responded_message = message; + + /* message counter can now be increased */ + this->logger->log(this->logger, CONTROL|LEVEL3, "Increase message counter for incoming messages"); + this->message_id_in++; + + return SUCCESS; +} + +/** + * Implementation of of private_responder_init_t.send_notify_reply. + */ +static void send_notify(private_ike_sa_t *this, exchange_type_t exchange_type, notify_message_type_t type, chunk_t data) +{ + notify_payload_t *payload; + message_t *response; + packet_t *packet; + status_t status; + + this->logger->log(this->logger, CONTROL|LEVEL2, "Going to build message with notify payload"); + /* set up the reply */ + this->protected.build_message(&(this->protected), exchange_type, FALSE, &response); + payload = notify_payload_create_from_protocol_and_type(PROTO_IKE, type); + if ((data.ptr != NULL) && (data.len > 0)) + { + this->logger->log(this->logger, CONTROL|LEVEL2, "Add Data to notify payload"); + payload->set_notification_data(payload,data); + } + + this->logger->log(this->logger, CONTROL|LEVEL2, "Add Notify payload to message"); + response->add_payload(response,(payload_t *) payload); + + /* generate packet */ + this->logger->log(this->logger, CONTROL|LEVEL2, "Generate packet from message"); + status = response->generate(response, this->crypter_responder, this->signer_responder, &packet); + if (status != SUCCESS) + { + this->logger->log(this->logger, ERROR|LEVEL1, "Could not generate notify message"); + response->destroy(response); + return; + } + + this->logger->log(this->logger, CONTROL|LEVEL2, "Add packet to global send queue"); + charon->send_queue->add(charon->send_queue, packet); + this->logger->log(this->logger, CONTROL|LEVEL2, "Destroy message"); + response->destroy(response); +} + +/** + * Implementation of protected_ike_sa_t.set_last_replied_message_id. + */ +static void set_last_replied_message_id (private_ike_sa_t *this,u_int32_t message_id) +{ + this->last_replied_message_id = message_id; +} + +/** + * Implementation of protected_ike_sa_t.get_last_responded_message. + */ +static message_t * get_last_responded_message (private_ike_sa_t *this) +{ + return this->last_responded_message; +} + +/** + * Implementation of protected_ike_sa_t.get_last_requested_message. + */ +static message_t * get_last_requested_message (private_ike_sa_t *this) +{ + return this->last_requested_message; +} + +/** + * Implementation of protected_ike_sa_t.get_state. + */ +static ike_sa_state_t get_state (private_ike_sa_t *this) +{ + return this->current_state->get_state(this->current_state); +} + +/** + * Implementation of protected_ike_sa_t.get_state. + */ +static void add_child_sa (private_ike_sa_t *this, child_sa_t *child_sa) +{ + this->child_sas->insert_last(this->child_sas, child_sa); +} + +/** + * Implementation of protected_ike_sa_t.reset_message_buffers. + */ +static void reset_message_buffers (private_ike_sa_t *this) +{ + this->logger->log(this->logger, CONTROL|LEVEL2, "Reset message counters and destroy stored messages"); + /* destroy stored requested message */ + if (this->last_requested_message != NULL) + { + this->last_requested_message->destroy(this->last_requested_message); + this->last_requested_message = NULL; + } + + /* destroy stored responded messages */ + if (this->last_responded_message != NULL) + { + this->last_responded_message->destroy(this->last_responded_message); + this->last_responded_message = NULL; + } + + this->message_id_out = 0; + this->message_id_in = 0; + this->last_replied_message_id = -1; +} + +/** + * Implementation of protected_ike_sa_t.log_status. + */ +static void log_status(private_ike_sa_t *this, logger_t *logger, char *name) +{ + iterator_t *iterator; + child_sa_t *child_sa; + + /* only log if name == NULL or name == connection_name */ + if (name) + { + if (strcmp(this->connection->get_name(this->connection), name) != 0) + { + return; + } + } + else + { + name = this->connection->get_name(this->connection); + } + + host_t *my_host = this->connection->get_my_host(this->connection); + host_t *other_host = this->connection->get_other_host(this->connection); + + identification_t *my_id = this->connection->get_my_id(this->connection); + identification_t *other_id = this->connection->get_other_id(this->connection); + + if (logger == NULL) + { + logger = this->logger; + } + logger->log(logger, CONTROL|LEVEL1, "\"%s\": IKE_SA in state %s, SPIs: 0x%.16llx 0x%.16llx", + name, + mapping_find(ike_sa_state_m, this->current_state->get_state(this->current_state)), + this->ike_sa_id->get_initiator_spi(this->ike_sa_id), + this->ike_sa_id->get_responder_spi(this->ike_sa_id)); + logger->log(logger, CONTROL, "\"%s\": %s[%s]...%s[%s]", + name, + my_host->get_address(my_host), + my_id->get_string(my_id), + other_host->get_address(other_host), + other_id->get_string(other_id)); + + iterator = this->child_sas->create_iterator(this->child_sas, TRUE); + while (iterator->has_next(iterator)) + { + iterator->current(iterator, (void**)&child_sa); + child_sa->log_status(child_sa, logger, name); + } + iterator->destroy(iterator); +} + +/** + * Implementation of protected_ike_sa_t.destroy. + */ +static void destroy (private_ike_sa_t *this) +{ + child_sa_t *child_sa; + + this->logger->log(this->logger, CONTROL|LEVEL2, "Going to destroy IKE SA %llu:%llu, role %s", + this->ike_sa_id->get_initiator_spi(this->ike_sa_id), + this->ike_sa_id->get_responder_spi(this->ike_sa_id), + this->ike_sa_id->is_initiator(this->ike_sa_id) ? "initiator" : "responder"); + + /* inform other peer of delete */ + send_delete_ike_sa_request(this); + while (this->child_sas->remove_last(this->child_sas, (void**)&child_sa) == SUCCESS) + { + child_sa->destroy(child_sa); + } + this->child_sas->destroy(this->child_sas); + + if (this->crypter_initiator) + { + this->crypter_initiator->destroy(this->crypter_initiator); + } + if (this->crypter_responder) + { + this->crypter_responder->destroy(this->crypter_responder); + } + if (this->signer_initiator) + { + this->signer_initiator->destroy(this->signer_initiator); + } + if (this->signer_responder) + { + this->signer_responder->destroy(this->signer_responder); + } + if (this->prf) + { + this->prf->destroy(this->prf); + } + if (this->child_prf) + { + this->child_prf->destroy(this->child_prf); + } + if (this->prf_auth_i) + { + this->prf_auth_i->destroy(this->prf_auth_i); + } + if (this->prf_auth_r) + { + this->prf_auth_r->destroy(this->prf_auth_r); + } + if (this->connection) + { + host_t *me, *other; + me = this->connection->get_my_host(this->connection); + other = this->connection->get_other_host(this->connection); + + this->logger->log(this->logger, AUDIT, "IKE_SA deleted between %s - %s", + me->get_address(me), other->get_address(other)); + this->connection->destroy(this->connection); + } + if (this->policy) + { + this->policy->destroy(this->policy); + } + if (this->last_requested_message) + { + this->last_requested_message->destroy(this->last_requested_message); + } + if (this->last_responded_message) + { + this->last_responded_message->destroy(this->last_responded_message); + } + this->ike_sa_id->destroy(this->ike_sa_id); + this->randomizer->destroy(this->randomizer); + this->current_state->destroy(this->current_state); + + free(this); +} + +/* + * Described in header. + */ +ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id) +{ + private_ike_sa_t *this = malloc_thing(private_ike_sa_t); + + /* Public functions */ + this->protected.public.process_message = (status_t(*)(ike_sa_t*, message_t*)) process_message; + this->protected.public.initiate_connection = (status_t(*)(ike_sa_t*,connection_t*)) initiate_connection; + this->protected.public.get_id = (ike_sa_id_t*(*)(ike_sa_t*)) get_id; + this->protected.public.get_my_host = (host_t*(*)(ike_sa_t*)) get_my_host; + this->protected.public.get_other_host = (host_t*(*)(ike_sa_t*)) get_other_host; + this->protected.public.get_my_id = (identification_t*(*)(ike_sa_t*)) get_my_id; + this->protected.public.get_other_id = (identification_t*(*)(ike_sa_t*)) get_other_id; + this->protected.public.get_connection = (connection_t*(*)(ike_sa_t*)) get_connection; + this->protected.public.retransmit_request = (status_t (*) (ike_sa_t *, u_int32_t)) retransmit_request; + this->protected.public.get_state = (ike_sa_state_t (*) (ike_sa_t *this)) get_state; + this->protected.public.send_delete_ike_sa_request = (void (*)(ike_sa_t*)) send_delete_ike_sa_request; + this->protected.public.log_status = (void (*) (ike_sa_t*,logger_t*,char*))log_status; + this->protected.public.destroy = (void(*)(ike_sa_t*))destroy; + + /* protected functions */ + this->protected.build_message = (void (*) (protected_ike_sa_t *, exchange_type_t , bool , message_t **)) build_message; + this->protected.get_prf = (prf_t *(*) (protected_ike_sa_t *)) get_prf; + this->protected.get_child_prf = (prf_t *(*) (protected_ike_sa_t *)) get_child_prf; + this->protected.get_prf_auth_i = (prf_t *(*) (protected_ike_sa_t *)) get_prf_auth_i; + this->protected.get_prf_auth_r = (prf_t *(*) (protected_ike_sa_t *)) get_prf_auth_r; + this->protected.add_child_sa = (void (*) (protected_ike_sa_t*,child_sa_t*)) add_child_sa; + this->protected.set_connection = (void (*) (protected_ike_sa_t *,connection_t *)) set_connection; + this->protected.get_connection = (connection_t *(*) (protected_ike_sa_t *)) get_connection; + this->protected.set_policy = (void (*) (protected_ike_sa_t *,policy_t *)) set_policy; + this->protected.get_policy = (policy_t *(*) (protected_ike_sa_t *)) get_policy; + this->protected.get_randomizer = (randomizer_t *(*) (protected_ike_sa_t *)) get_randomizer; + this->protected.send_request = (status_t (*) (protected_ike_sa_t *,message_t *)) send_request; + this->protected.send_response = (status_t (*) (protected_ike_sa_t *,message_t *)) send_response; + this->protected.send_notify = (void (*)(protected_ike_sa_t*,exchange_type_t,notify_message_type_t,chunk_t)) send_notify; + this->protected.build_transforms = (status_t (*) (protected_ike_sa_t *,proposal_t*,diffie_hellman_t*,chunk_t,chunk_t)) build_transforms; + this->protected.set_new_state = (void (*) (protected_ike_sa_t *,state_t *)) set_new_state; + this->protected.get_crypter_initiator = (crypter_t *(*) (protected_ike_sa_t *)) get_crypter_initiator; + this->protected.get_signer_initiator = (signer_t *(*) (protected_ike_sa_t *)) get_signer_initiator; + this->protected.get_crypter_responder = (crypter_t *(*) (protected_ike_sa_t *)) get_crypter_responder; + this->protected.get_signer_responder = (signer_t *(*) (protected_ike_sa_t *)) get_signer_responder; + this->protected.reset_message_buffers = (void (*) (protected_ike_sa_t *)) reset_message_buffers; + this->protected.get_last_responded_message = (message_t * (*) (protected_ike_sa_t *this)) get_last_responded_message; + this->protected.get_last_requested_message = (message_t * (*) (protected_ike_sa_t *this)) get_last_requested_message; + + this->protected.set_last_replied_message_id = (void (*) (protected_ike_sa_t *,u_int32_t)) set_last_replied_message_id; + + /* private functions */ + this->resend_last_reply = resend_last_reply; + + /* initialize private fields */ + this->logger = logger_manager->get_logger(logger_manager, IKE_SA); + + this->ike_sa_id = ike_sa_id->clone(ike_sa_id); + this->child_sas = linked_list_create(); + this->randomizer = randomizer_create(); + + this->last_requested_message = NULL; + this->last_responded_message = NULL; + this->message_id_out = 0; + this->message_id_in = 0; + this->last_replied_message_id = -1; + this->crypter_initiator = NULL; + this->crypter_responder = NULL; + this->signer_initiator = NULL; + this->signer_responder = NULL; + this->prf = NULL; + this->prf_auth_i = NULL; + this->prf_auth_r = NULL; + this->child_prf = NULL; + this->connection = NULL; + this->policy = NULL; + + /* at creation time, IKE_SA is in a initiator state */ + if (ike_sa_id->is_initiator(ike_sa_id)) + { + this->logger->log(this->logger, CONTROL | LEVEL2, "Create first state_t object of type INITIATOR_INIT"); + this->current_state = (state_t *) initiator_init_create(&(this->protected)); + } + else + { + this->logger->log(this->logger, CONTROL | LEVEL2, "Create first state_t object of type RESPONDER_INIT"); + this->current_state = (state_t *) responder_init_create(&(this->protected)); + } + return &(this->protected.public); +} diff --git a/src/charon/sa/ike_sa.h b/src/charon/sa/ike_sa.h new file mode 100644 index 000000000..c526c6347 --- /dev/null +++ b/src/charon/sa/ike_sa.h @@ -0,0 +1,462 @@ +/** + * @file ike_sa.h + * + * @brief Interface of ike_sa_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef IKE_SA_H_ +#define IKE_SA_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * Nonce size in bytes for nonces sending to other peer. + * + * @warning Nonce size MUST be between 16 and 256 bytes. + * + * @ingroup sa + */ +#define NONCE_SIZE 16 + + +typedef struct ike_sa_t ike_sa_t; + +/** + * @brief Class ike_sa_t representing an IKE_SA. + * + * An object of this type is managed by an ike_sa_manager_t object + * and represents an IKE_SA. Message processing is split up in different states. + * They will handle all related things for the state they represent. + * + * @b Constructors: + * - ike_sa_create() + * + * @ingroup sa + */ +struct ike_sa_t { + + /** + * @brief Processes a incoming IKEv2-Message of type message_t. + * + * @param this ike_sa_t object object + * @param[in] message message_t object to process + * @return + * - SUCCESS + * - FAILED + * - DELETE_ME if this IKE_SA MUST be deleted + */ + status_t (*process_message) (ike_sa_t *this,message_t *message); + + /** + * @brief Initiate a new connection with given connection_t object. + * + * The connection_t object is owned by the IKE_SA after the call, so + * do not modify or destroy it. + * + * @param this calling object + * @param connection connection to initiate + * @return + * - SUCCESS if initialization started + * - FAILED if in wrong state + * - DELETE_ME if initialization failed and IKE_SA MUST be deleted + */ + status_t (*initiate_connection) (ike_sa_t *this, connection_t *connection); + + /** + * @brief Retransmits a request. + * + * @param this calling object + * @param message_id ID of the request to retransmit + * @return + * - SUCCESS + * - NOT_FOUND if request doesn't have to be retransmited + */ + status_t (*retransmit_request) (ike_sa_t *this, u_int32_t message_id); + + /** + * @brief Sends a request to delete IKE_SA. + * + * Only supported in state IKE_SA_ESTABLISHED + * + * @param this calling object + */ + void (*send_delete_ike_sa_request) (ike_sa_t *this); + + /** + * @brief Get the id of the SA. + * + * Returned ike_sa_id_t object is not getting cloned! + * + * @param this calling object + * @return ike_sa's ike_sa_id_t + */ + ike_sa_id_t* (*get_id) (ike_sa_t *this); + + /** + * @brief Get local peer address of the IKE_SA. + * + * @param this calling object + * @return local host_t + */ + host_t* (*get_my_host) (ike_sa_t *this); + + /** + * @brief Get remote peer address of the IKE_SA. + * + * @param this calling object + * @return remote host_t + */ + host_t* (*get_other_host) (ike_sa_t *this); + + /** + * @brief Get own ID of the IKE_SA. + * + * @param this calling object + * @return local identification_t + */ + identification_t* (*get_my_id) (ike_sa_t *this); + + /** + * @brief Get remote ID the IKE_SA. + * + * @param this calling object + * @return remote identification_t + */ + identification_t* (*get_other_id) (ike_sa_t *this); + + /** + * @brief Get the connection of the IKE_SA. + * + * The internal used connection specification + * can be queried to get some data of an IKE_SA. + * The connection is still owned to the IKE_SA + * and must not be manipulated. + * + * @param this calling object + * @return connection_t + */ + connection_t* (*get_connection) (ike_sa_t *this); + + /** + * @brief Get the state of type of associated state object. + * + * @param this calling object + * @return state of IKE_SA + */ + ike_sa_state_t (*get_state) (ike_sa_t *this); + + /** + * @brief Log the status of a the ike sa to a logger. + * + * The status of the IKE SA and all child SAs is logged. + * Supplying NULL as logger uses the internal child_sa logger + * to do the logging. The log is only done if the supplied + * connection name is NULL or matches the connections name. + * + * @param this calling object + * @param logger logger to use for logging + * @param name name of the connection + */ + void (*log_status) (ike_sa_t *this, logger_t *logger, char *name); + + /** + * @brief Destroys a ike_sa_t object. + * + * @param this calling object + */ + void (*destroy) (ike_sa_t *this); +}; + + +typedef struct protected_ike_sa_t protected_ike_sa_t; + +/** + * @brief Protected functions of an ike_sa_t object. + * + * This members are only accessed out from + * the various state_t implementations. + * + * @ingroup sa + */ +struct protected_ike_sa_t { + + /** + * Public interface of an ike_sa_t object. + */ + ike_sa_t public; + + /** + * @brief Build an empty IKEv2-Message and fills in default informations. + * + * Depending on the type of message (request or response), the message id is + * either message_id_out or message_id_in. + * + * Used in state_t Implementation to build an empty IKEv2-Message. + * + * @param this calling object + * @param type exchange type of new message + * @param request TRUE, if message has to be a request + * @param message new message is stored at this location + */ + void (*build_message) (protected_ike_sa_t *this, exchange_type_t type, bool request, message_t **message); + + /** + * @brief Get the internal stored connection_t object. + * + * @param this calling object + * @return pointer to the internal stored connection_t object + */ + connection_t *(*get_connection) (protected_ike_sa_t *this); + + /** + * @brief Set the internal connection object. + * + * @param this calling object + * @param connection object of type connection_t + */ + void (*set_connection) (protected_ike_sa_t *this, connection_t *connection); + + /** + * @brief Get the internal stored policy object. + * + * @param this calling object + * @return pointer to the internal stored policy_t object + */ + policy_t *(*get_policy) (protected_ike_sa_t *this); + + /** + * @brief Set the internal policy_t object. + * + * @param this calling object + * @param policy object of type policy_t + */ + void (*set_policy) (protected_ike_sa_t *this,policy_t *policy); + + /** + * @brief Derive all keys and create the transforms for IKE communication. + * + * Keys are derived using the diffie hellman secret, nonces and internal + * stored SPIs. + * Allready existing objects get destroyed. + * + * @param this calling object + * @param proposal proposal which contains algorithms to use + * @param dh diffie hellman object with shared secret + * @param nonce_i initiators nonce + * @param nonce_r responders nonce + */ + status_t (*build_transforms) (protected_ike_sa_t *this, proposal_t* proposal, + diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r); + + /** + * @brief Send the next request message. + * + * Also the first retransmit job is created. + * + * Last stored requested message gets destroyed. Object gets not cloned! + * + * @param this calling object + * @param message pointer to the message which should be sent + * @return + * - SUCCESS + * - FAILED if message id is not next expected one + */ + status_t (*send_request) (protected_ike_sa_t *this,message_t * message); + + /** + * @brief Send the next response message. + * + * Last stored responded message gets destroyed. Object gets not cloned! + * + * @param this calling object + * @param message pointer to the message which should be sent + * return + * - SUCCESS + * - FAILED if message id is not next expected one + */ + status_t (*send_response) (protected_ike_sa_t *this,message_t * message); + + /** + * @brief Send a notify reply message. + * + * @param this calling object + * @param exchange_type type of exchange in which the notify should be wrapped + * @param type type of the notify message to send + * @param data notification data + */ + void (*send_notify) (protected_ike_sa_t *this, exchange_type_t exchange_type, notify_message_type_t type, chunk_t data); + + /** + * @brief Get the internal stored randomizer_t object. + * + * @param this calling object + * @return pointer to the internal randomizer_t object + */ + randomizer_t *(*get_randomizer) (protected_ike_sa_t *this); + + /** + * @brief Set the new state_t object of the IKE_SA object. + * + * The old state_t object gets not destroyed. It's the callers duty to + * make sure old state is destroyed (Normally the old state is the caller). + * + * @param this calling object + * @param state pointer to the new state_t object + */ + void (*set_new_state) (protected_ike_sa_t *this,state_t *state); + + /** + * @brief Set the last replied message id. + * + * @param this calling object + * @param message_id message id + */ + void (*set_last_replied_message_id) (protected_ike_sa_t *this,u_int32_t message_id); + + /** + * @brief Get the internal stored initiator crypter_t object. + * + * @param this calling object + * @return pointer to crypter_t object + */ + crypter_t *(*get_crypter_initiator) (protected_ike_sa_t *this); + + /** + * @brief Get the internal stored initiator signer_t object. + * + * @param this calling object + * @return pointer to signer_t object + */ + signer_t *(*get_signer_initiator) (protected_ike_sa_t *this); + + /** + * @brief Get the internal stored responder crypter_t object. + * + * @param this calling object + * @return pointer to crypter_t object + */ + crypter_t *(*get_crypter_responder) (protected_ike_sa_t *this); + + /** + * @brief Get the internal stored responder signer object. + * + * @param this calling object + * @return pointer to signer_t object + */ + signer_t *(*get_signer_responder) (protected_ike_sa_t *this); + + /** + * @brief Get the multi purpose prf. + * + * @param this calling object + * @return pointer to prf_t object + */ + prf_t *(*get_prf) (protected_ike_sa_t *this); + + /** + * @brief Get the prf-object, which is used to derive keys for child SAs. + * + * @param this calling object + * @return pointer to prf_t object + */ + prf_t *(*get_child_prf) (protected_ike_sa_t *this); + + /** + * @brief Get the prf used for authentication of initiator. + * + * @param this calling object + * @return pointer to prf_t object + */ + prf_t *(*get_prf_auth_i) (protected_ike_sa_t *this); + + /** + * @brief Get the prf used for authentication of responder. + * + * @param this calling object + * @return pointer to prf_t object + */ + prf_t *(*get_prf_auth_r) (protected_ike_sa_t *this); + + /** + * @brief Associates a child SA to this IKE SA + * + * @param this calling object + * @param child_sa child_sa to add + */ + void (*add_child_sa) (protected_ike_sa_t *this, child_sa_t *child_sa); + + /** + * @brief Get the last responded message. + * + * @param this calling object + * @return + * - last received as message_t object + * - NULL if no last request available + */ + message_t *(*get_last_responded_message) (protected_ike_sa_t *this); + + /** + * @brief Get the last requested message. + * + * @param this calling object + * @return + * - last sent as message_t object + * - NULL if no last request available + */ + message_t *(*get_last_requested_message) (protected_ike_sa_t *this); + + /** + * @brief Resets message counters and does destroy stored received and sent messages. + * + * @param this calling object + */ + void (*reset_message_buffers) (protected_ike_sa_t *this); +}; + + +/** + * @brief Creates an ike_sa_t object with a specific ID. + * + * @warning the Content of internal ike_sa_id_t object can change over time + * e.g. when a IKE_SA_INIT has been finished. + * + * @param[in] ike_sa_id ike_sa_id_t object to associate with new IKE_SA. + * The object is internal getting cloned + * and so has to be destroyed by the caller. + * @return ike_sa_t object + * + * @ingroup sa + */ +ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id); + +#endif /*IKE_SA_H_*/ diff --git a/src/charon/sa/ike_sa_id.c b/src/charon/sa/ike_sa_id.c new file mode 100644 index 000000000..bf3a05d11 --- /dev/null +++ b/src/charon/sa/ike_sa_id.c @@ -0,0 +1,185 @@ +/** + * @file ike_sa_id.c + * + * @brief Implementation of ike_sa_id_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 "ike_sa_id.h" + + + +typedef struct private_ike_sa_id_t private_ike_sa_id_t; + +/** + * Private data of an ike_sa_id_t object. + */ +struct private_ike_sa_id_t { + /** + * Public interface of ike_sa_id_t. + */ + ike_sa_id_t public; + + /** + * SPI of Initiator. + */ + u_int64_t initiator_spi; + + /** + * SPI of Responder. + */ + u_int64_t responder_spi; + + /** + * Role for specific IKE_SA. + */ + bool is_initiator_flag; +}; + +/** + * Implementation of ike_sa_id_t.set_responder_spi. + */ +static void set_responder_spi (private_ike_sa_id_t *this, u_int64_t responder_spi) +{ + this->responder_spi = responder_spi; +} + +/** + * Implementation of ike_sa_id_t.set_initiator_spi. + */ +static void set_initiator_spi(private_ike_sa_id_t *this, u_int64_t initiator_spi) +{ + this->initiator_spi = initiator_spi; +} + +/** + * Implementation of ike_sa_id_t.get_initiator_spi. + */ +static u_int64_t get_initiator_spi (private_ike_sa_id_t *this) +{ + return this->initiator_spi; +} + +/** + * Implementation of ike_sa_id_t.get_responder_spi. + */ +static u_int64_t get_responder_spi (private_ike_sa_id_t *this) +{ + return this->responder_spi; +} + +/** + * Implementation of ike_sa_id_t.equals. + */ +static bool equals (private_ike_sa_id_t *this, private_ike_sa_id_t *other) +{ + if (other == NULL) + { + return FALSE; + } + if ((this->is_initiator_flag == other->is_initiator_flag) && + (this->initiator_spi == other->initiator_spi) && + (this->responder_spi == other->responder_spi)) + { + /* private_ike_sa_id's are equal */ + return TRUE; + } + else + { + /* private_ike_sa_id's are not equal */ + return FALSE; + } +} + +/** + * Implementation of ike_sa_id_t.replace_values. + */ +static void replace_values(private_ike_sa_id_t *this, private_ike_sa_id_t *other) +{ + this->initiator_spi = other->initiator_spi; + this->responder_spi = other->responder_spi; + this->is_initiator_flag = other->is_initiator_flag; +} + +/** + * Implementation of ike_sa_id_t.is_initiator. + */ +static bool is_initiator(private_ike_sa_id_t *this) +{ + return this->is_initiator_flag; +} + +/** + * Implementation of ike_sa_id_t.switch_initiator. + */ +static bool switch_initiator(private_ike_sa_id_t *this) +{ + if (this->is_initiator_flag) + { + this->is_initiator_flag = FALSE; + } + else + { + this->is_initiator_flag = TRUE; + } + return this->is_initiator_flag; +} + +/** + * Implementation of ike_sa_id_t.clone. + */ +static ike_sa_id_t* clone(private_ike_sa_id_t *this) +{ + return ike_sa_id_create(this->initiator_spi, this->responder_spi, this->is_initiator_flag); +} + +/** + * Implementation of ike_sa_id_t.destroy. + */ +static void destroy(private_ike_sa_id_t *this) +{ + free(this); +} + +/* + * Described in header. + */ +ike_sa_id_t * ike_sa_id_create(u_int64_t initiator_spi, u_int64_t responder_spi, bool is_initiator_flag) +{ + private_ike_sa_id_t *this = malloc_thing(private_ike_sa_id_t); + + /* public functions */ + this->public.set_responder_spi = (void(*)(ike_sa_id_t*,u_int64_t)) set_responder_spi; + this->public.set_initiator_spi = (void(*)(ike_sa_id_t*,u_int64_t)) set_initiator_spi; + this->public.get_responder_spi = (u_int64_t(*)(ike_sa_id_t*)) get_responder_spi; + this->public.get_initiator_spi = (u_int64_t(*)(ike_sa_id_t*)) get_initiator_spi; + this->public.equals = (bool(*)(ike_sa_id_t*,ike_sa_id_t*)) equals; + this->public.replace_values = (void(*)(ike_sa_id_t*,ike_sa_id_t*)) replace_values; + this->public.is_initiator = (bool(*)(ike_sa_id_t*)) is_initiator; + this->public.switch_initiator = (bool(*)(ike_sa_id_t*)) switch_initiator; + this->public.clone = (ike_sa_id_t*(*)(ike_sa_id_t*)) clone; + this->public.destroy = (void(*)(ike_sa_id_t*))destroy; + + /* private data */ + this->initiator_spi = initiator_spi; + this->responder_spi = responder_spi; + this->is_initiator_flag = is_initiator_flag; + + return (&this->public); +} diff --git a/src/charon/sa/ike_sa_id.h b/src/charon/sa/ike_sa_id.h new file mode 100644 index 000000000..0f16f7637 --- /dev/null +++ b/src/charon/sa/ike_sa_id.h @@ -0,0 +1,146 @@ +/** + * @file ike_sa_id.h + * + * @brief Interface of ike_sa_id_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + + +#ifndef IKE_SA_ID_H_ +#define IKE_SA_ID_H_ + +#include + + +typedef struct ike_sa_id_t ike_sa_id_t; + +/** + * @brief An object of type ike_sa_id_t is used to identify an IKE_SA. + * + * An IKE_SA is identified by its initiator and responder spi's. + * Additionaly it contains the role of the actual running IKEv2-Daemon + * for the specific IKE_SA (original initiator or responder). + * + * @b Constructors: + * - ike_sa_id_create() + * + * @ingroup sa + */ +struct ike_sa_id_t { + + /** + * @brief Set the SPI of the responder. + * + * This function is called when a request or reply of a IKE_SA_INIT is received. + * + * @param this calling object + * @param responder_spi SPI of responder to set + */ + void (*set_responder_spi) (ike_sa_id_t *this, u_int64_t responder_spi); + + /** + * @brief Set the SPI of the initiator. + * + * @param this calling object + * @param initiator_spi SPI to set + */ + void (*set_initiator_spi) (ike_sa_id_t *this, u_int64_t initiator_spi); + + /** + * @brief Get the initiator SPI. + * + * @param this calling object + * @return SPI of the initiator + */ + u_int64_t (*get_initiator_spi) (ike_sa_id_t *this); + + /** + * @brief Get the responder SPI. + * + * @param this calling object + * @return SPI of the responder + */ + u_int64_t (*get_responder_spi) (ike_sa_id_t *this); + + /** + * @brief Check if two ike_sa_id_t objects are equal. + * + * Two ike_sa_id_t objects are equal if both SPI values and the role matches. + * + * @param this calling object + * @param other ike_sa_id_t object to check if equal + * @return TRUE if given ike_sa_id_t are equal, FALSE otherwise + */ + bool (*equals) (ike_sa_id_t *this, ike_sa_id_t *other); + + /** + * @brief Replace all values of a given ike_sa_id_t object with values. + * from another ike_sa_id_t object. + * + * After calling this function, both objects are equal. + * + * @param this calling object + * @param other ike_sa_id_t object from which values will be taken + */ + void (*replace_values) (ike_sa_id_t *this, ike_sa_id_t *other); + + /** + * @brief Get the initiator flag. + * + * @param this calling object + * @return TRUE if we are the original initator + */ + bool (*is_initiator) (ike_sa_id_t *this); + + /** + * @brief Switche the original initiator flag. + * + * @param this calling object + * @return TRUE if we are the original initator after switch, FALSE otherwise + */ + bool (*switch_initiator) (ike_sa_id_t *this); + + /** + * @brief Clones a given ike_sa_id_t object. + * + * @param this calling object + * @return cloned ike_sa_id_t object + */ + ike_sa_id_t *(*clone) (ike_sa_id_t *this); + + /** + * @brief Destroys an ike_sa_id_t object. + * + * @param this calling object + */ + void (*destroy) (ike_sa_id_t *this); +}; + +/** + * @brief Creates an ike_sa_id_t object with specific SPI's and defined role. + * + * @param initiator_spi initiators SPI + * @param responder_spi responders SPI + * @param is_initiaor TRUE if we are the original initiator + * @return ike_sa_id_t object + * + * @ingroup sa + */ +ike_sa_id_t * ike_sa_id_create(u_int64_t initiator_spi, u_int64_t responder_spi, bool is_initiaor); + +#endif /*IKE_SA_ID_H_*/ diff --git a/src/charon/sa/ike_sa_manager.c b/src/charon/sa/ike_sa_manager.c new file mode 100644 index 000000000..a65f41042 --- /dev/null +++ b/src/charon/sa/ike_sa_manager.c @@ -0,0 +1,843 @@ +/** + * @file ike_sa_manager.c + * + * @brief Implementation of ike_sa_mananger_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 +#include + +#include "ike_sa_manager.h" + +#include +#include +#include +#include +#include + +typedef struct ike_sa_entry_t ike_sa_entry_t; + +/** + * An entry in the linked list, contains IKE_SA, locking and lookup data. + */ +struct ike_sa_entry_t { + /** + * Destructor, also destroys associated ike_sa_t object. + */ + status_t (*destroy) (ike_sa_entry_t *this); + + /** + * Number of threads waiting for this ike_sa_t object. + */ + int waiting_threads; + + /** + * Condvar where threads can wait until ike_sa_t object is free for use again. + */ + pthread_cond_t condvar; + + /** + * Is this ike_sa currently checked out? + */ + bool checked_out; + + /** + * Does this SA drives out new threads? + */ + bool driveout_new_threads; + + /** + * Does this SA drives out waiting threads? + */ + bool driveout_waiting_threads; + + /** + * Identifiaction of an IKE_SA (SPIs). + */ + ike_sa_id_t *ike_sa_id; + + /** + * The contained ike_sa_t object. + */ + ike_sa_t *ike_sa; +}; + +/** + * Implementation of ike_sa_entry_t.destroy. + */ +static status_t ike_sa_entry_destroy(ike_sa_entry_t *this) +{ + /* also destroy IKE SA */ + this->ike_sa->destroy(this->ike_sa); + this->ike_sa_id->destroy(this->ike_sa_id); + free(this); + return SUCCESS; +} + +/** + * @brief Creates a new entry for the ike_sa_t list. + * + * This constructor additionaly creates a new and empty SA. + * + * @param ike_sa_id The associated ike_sa_id_t, will be cloned + * @return ike_sa_entry_t object + */ +static ike_sa_entry_t *ike_sa_entry_create(ike_sa_id_t *ike_sa_id) +{ + ike_sa_entry_t *this = malloc_thing(ike_sa_entry_t); + + /* destroy function */ + this->destroy = ike_sa_entry_destroy; + + this->waiting_threads = 0; + pthread_cond_init(&(this->condvar), NULL); + + /* we set checkout flag when we really give it out */ + this->checked_out = FALSE; + this->driveout_new_threads = FALSE; + this->driveout_waiting_threads = FALSE; + + /* ike_sa_id is always cloned */ + this->ike_sa_id = ike_sa_id->clone(ike_sa_id); + + /* create new ike_sa */ + this->ike_sa = ike_sa_create(ike_sa_id); + + return this; +} + + +typedef struct private_ike_sa_manager_t private_ike_sa_manager_t; + +/** + * Additional private members of ike_sa_manager_t. + */ +struct private_ike_sa_manager_t { + /** + * Public interface of ike_sa_manager_t. + */ + ike_sa_manager_t public; + + /** + * @brief Get next spi. + * + * We give out SPIs incremental starting at 1. + * + * @param this the ike_sa_manager + * @return the next spi + */ + u_int64_t (*get_next_spi) (private_ike_sa_manager_t *this); + + /** + * @brief Find the ike_sa_entry_t object in the list by SPIs. + * + * This function simply iterates over the linked list. A hash-table + * would be more efficient when storing a lot of IKE_SAs... + * + * @param this calling object + * @param ike_sa_id id of the ike_sa, containing SPIs + * @param[out] entry pointer to set to the found entry + * @return + * - SUCCESS when found, + * - NOT_FOUND when no such ike_sa_id in list + */ + status_t (*get_entry_by_id) (private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id, ike_sa_entry_t **entry); + + /** + * @brief Find the ike_sa_entry_t in the list by pointer to SA. + * + * This function simply iterates over the linked list. A hash-table + * would be more efficient when storing a lot of IKE_SAs... + * + * @param this calling object + * @param ike_sa pointer to the ike_sa + * @param[out] entry pointer to set to the found entry + * @return + * - SUCCESS when found, + * - NOT_FOUND when no such ike_sa_id in list + */ + status_t (*get_entry_by_sa) (private_ike_sa_manager_t *this, ike_sa_t *ike_sa, ike_sa_entry_t **entry); + + /** + * @brief Felete an entry from the linked list. + * + * @param this calling object + * @param entry entry to delete + * @return + * - SUCCESS when found, + * - NOT_FOUND when no such ike_sa_id in list + */ + status_t (*delete_entry) (private_ike_sa_manager_t *this, ike_sa_entry_t *entry); + + /** + * Lock for exclusivly accessing the manager. + */ + pthread_mutex_t mutex; + + /** + * Logger used for this IKE SA Manager. + */ + logger_t *logger; + + /** + * Linked list with entries for the ike_sa_t objects. + */ + linked_list_t *ike_sa_list; + + /** + * A randomizer, to get random SPIs for our side + */ + randomizer_t *randomizer; +}; + +/** + * Implementation of private_ike_sa_manager_t.get_entry_by_id. + */ +static status_t get_entry_by_id(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id, ike_sa_entry_t **entry) +{ + linked_list_t *list = this->ike_sa_list; + iterator_t *iterator; + status_t status; + + /* create iterator over list of ike_sa's */ + iterator = list->create_iterator(list, TRUE); + + /* default status */ + status = NOT_FOUND; + + while (iterator->has_next(iterator)) + { + ike_sa_entry_t *current; + + iterator->current(iterator, (void**)¤t); + if (current->ike_sa_id->get_responder_spi(current->ike_sa_id) == 0) + { + /* seems to be a half ready ike_sa */ + if ((current->ike_sa_id->get_initiator_spi(current->ike_sa_id) == ike_sa_id->get_initiator_spi(ike_sa_id)) + && (ike_sa_id->is_initiator(ike_sa_id) == current->ike_sa_id->is_initiator(current->ike_sa_id))) + { + this->logger->log(this->logger,CONTROL | LEVEL2,"Found entry by initiator spi %d",ike_sa_id->get_initiator_spi(ike_sa_id)); + *entry = current; + status = SUCCESS; + break; + } + } + else if (ike_sa_id->get_responder_spi(ike_sa_id) == 0) + { + if ((current->ike_sa_id->get_initiator_spi(current->ike_sa_id) == ike_sa_id->get_initiator_spi(ike_sa_id)) + && (ike_sa_id->is_initiator(ike_sa_id) == current->ike_sa_id->is_initiator(current->ike_sa_id))) + { + this->logger->log(this->logger,CONTROL | LEVEL2,"Found entry by initiator spi %d",ike_sa_id->get_initiator_spi(ike_sa_id)); + *entry = current; + status = SUCCESS; + break; + } + } + if (current->ike_sa_id->equals(current->ike_sa_id, ike_sa_id)) + { + this->logger->log(this->logger,CONTROL | LEVEL2,"Found entry by full ID"); + *entry = current; + status = SUCCESS; + break; + } + } + + iterator->destroy(iterator); + return status; +} + +/** + * Implementation of private_ike_sa_manager_t.get_entry_by_sa. + */ +static status_t get_entry_by_sa(private_ike_sa_manager_t *this, ike_sa_t *ike_sa, ike_sa_entry_t **entry) +{ + linked_list_t *list = this->ike_sa_list; + iterator_t *iterator; + status_t status; + + iterator = list->create_iterator(list, TRUE); + + /* default status */ + status = NOT_FOUND; + + while (iterator->has_next(iterator)) + { + ike_sa_entry_t *current; + iterator->current(iterator, (void**)¤t); + /* only pointers are compared */ + if (current->ike_sa == ike_sa) + { + this->logger->log(this->logger,CONTROL | LEVEL2,"Found entry by pointer"); + *entry = current; + status = SUCCESS; + break; + } + } + iterator->destroy(iterator); + + return status; +} + +/** + * Implementation of private_ike_sa_manager_s.delete_entry. + */ +static status_t delete_entry(private_ike_sa_manager_t *this, ike_sa_entry_t *entry) +{ + linked_list_t *list = this->ike_sa_list; + iterator_t *iterator; + status_t status; + + iterator = list->create_iterator(list, TRUE); + + status = NOT_FOUND; + + while (iterator->has_next(iterator)) + { + ike_sa_entry_t *current; + iterator->current(iterator, (void**)¤t); + if (current == entry) + { + this->logger->log(this->logger,CONTROL | LEVEL2,"Found entry by pointer. Going to delete it."); + iterator->remove(iterator); + entry->destroy(entry); + status = SUCCESS; + break; + } + } + iterator->destroy(iterator); + return status; +} + + +/** + * Implementation of private_ike_sa_manager_t.get_next_spi. + */ +static u_int64_t get_next_spi(private_ike_sa_manager_t *this) +{ + u_int64_t spi; + + this->randomizer->get_pseudo_random_bytes(this->randomizer, 8, (u_int8_t*)&spi); + + return spi; +} + +/** + * Implementation of of ike_sa_manager.create_and_checkout. + */ +static void create_and_checkout(private_ike_sa_manager_t *this,ike_sa_t **ike_sa) +{ + u_int64_t initiator_spi; + ike_sa_entry_t *new_ike_sa_entry; + ike_sa_id_t *new_ike_sa_id; + + initiator_spi = this->get_next_spi(this); + new_ike_sa_id = ike_sa_id_create(0, 0, TRUE); + new_ike_sa_id->set_initiator_spi(new_ike_sa_id, initiator_spi); + + /* create entry */ + new_ike_sa_entry = ike_sa_entry_create(new_ike_sa_id); + new_ike_sa_id->destroy(new_ike_sa_id); + + /* each access is locked */ + pthread_mutex_lock(&(this->mutex)); + + this->ike_sa_list->insert_last(this->ike_sa_list, new_ike_sa_entry); + + /* check ike_sa out */ + this->logger->log(this->logger,CONTROL | LEVEL1 ,"New IKE_SA created and added to list of known IKE_SA's"); + new_ike_sa_entry->checked_out = TRUE; + *ike_sa = new_ike_sa_entry->ike_sa; + + pthread_mutex_unlock(&(this->mutex)); +} + +/** + * Implementation of of ike_sa_manager.checkout. + */ +static status_t checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id, ike_sa_t **ike_sa) +{ + bool responder_spi_set; + bool initiator_spi_set; + bool original_initiator; + status_t retval; + + /* each access is locked */ + pthread_mutex_lock(&(this->mutex)); + + responder_spi_set = (FALSE != ike_sa_id->get_responder_spi(ike_sa_id)); + initiator_spi_set = (FALSE != ike_sa_id->get_initiator_spi(ike_sa_id)); + original_initiator = ike_sa_id->is_initiator(ike_sa_id); + + if ((initiator_spi_set && responder_spi_set) || + ((initiator_spi_set && !responder_spi_set) && (original_initiator))) + { + /* we SHOULD have an IKE_SA for these SPIs in the list, + * if not, we can't handle the request... + */ + ike_sa_entry_t *entry; + /* look for the entry */ + if (this->get_entry_by_id(this, ike_sa_id, &entry) == SUCCESS) + { + /* can we give this ike_sa out to new requesters?*/ + if (entry->driveout_new_threads) + { + this->logger->log(this->logger,CONTROL|LEVEL1,"Drive out new thread for existing IKE_SA"); + /* no we can't */ + retval = NOT_FOUND; + } + else + { + /* is this IKE_SA already checked out ?? + * are we welcome to get this SA ? */ + while (entry->checked_out && !entry->driveout_waiting_threads) + { + /* so wait until we can get it for us. + * we register us as waiting. + */ + entry->waiting_threads++; + pthread_cond_wait(&(entry->condvar), &(this->mutex)); + entry->waiting_threads--; + } + + /* hm, a deletion request forbids us to get this SA, go home */ + if (entry->driveout_waiting_threads) + { + /* we must signal here, others are interested that we leave */ + pthread_cond_signal(&(entry->condvar)); + this->logger->log(this->logger,CONTROL|LEVEL1,"Drive out waiting thread for existing IKE_SA"); + retval = NOT_FOUND; + } + else + { + this->logger->log(this->logger,CONTROL|LEVEL2,"IKE SA successfully checked out"); + /* ok, this IKE_SA is finally ours */ + entry->checked_out = TRUE; + *ike_sa = entry->ike_sa; + /* DON'T use return, we must unlock the mutex! */ + retval = SUCCESS; + } + } + } + else + { + this->logger->log(this->logger,ERROR | LEVEL1,"IKE SA not stored in known IKE_SA list"); + /* looks like there is no such IKE_SA, better luck next time... */ + /* DON'T use return, we must unlock the mutex! */ + retval = NOT_FOUND; + } + } + else if ((initiator_spi_set && !responder_spi_set) && (!original_initiator)) + { + /* an IKE_SA_INIT from an another endpoint, + * he is the initiator. + * For simplicity, we do NOT check for retransmitted + * IKE_SA_INIT-Requests here, so EVERY single IKE_SA_INIT- + * Request (even a retransmitted one) will result in a + * IKE_SA. This could be improved... + */ + u_int64_t responder_spi; + ike_sa_entry_t *new_ike_sa_entry; + + + /* set SPIs, we are the responder */ + responder_spi = this->get_next_spi(this); + + /* we also set arguments spi, so its still valid */ + ike_sa_id->set_responder_spi(ike_sa_id, responder_spi); + + /* create entry */ + new_ike_sa_entry = ike_sa_entry_create(ike_sa_id); + + this->ike_sa_list->insert_last(this->ike_sa_list, new_ike_sa_entry); + + /* check ike_sa out */ + this->logger->log(this->logger,CONTROL | LEVEL1 ,"IKE_SA added to list of known IKE_SA's"); + new_ike_sa_entry->checked_out = TRUE; + *ike_sa = new_ike_sa_entry->ike_sa; + + retval = CREATED; + } + else + { + /* responder set, initiator not: here is something seriously wrong! */ + this->logger->log(this->logger,ERROR | LEVEL1, "Invalid IKE_SA SPI's"); + /* DON'T use return, we must unlock the mutex! */ + retval = INVALID_ARG; + } + + pthread_mutex_unlock(&(this->mutex)); + /* OK, unlocked... */ + return retval; +} + +/** + * Implementation of of ike_sa_manager.checkout_by_hosts. + */ +static status_t checkout_by_hosts(private_ike_sa_manager_t *this, host_t *me, host_t *other, ike_sa_t **ike_sa) +{ + iterator_t *iterator; + ike_sa_id_t *ike_sa_id = NULL; + + pthread_mutex_lock(&(this->mutex)); + + iterator = this->ike_sa_list->create_iterator(this->ike_sa_list, TRUE); + while (iterator->has_next(iterator)) + { + ike_sa_entry_t *current; + host_t *sa_me, *sa_other; + + iterator->current(iterator, (void**)¤t); + sa_me = current->ike_sa->get_my_host(current->ike_sa); + sa_other = current->ike_sa->get_other_host(current->ike_sa); + + /* one end may be default/any, but not both */ + if (me->is_default_route(me)) + { + if (other->is_default_route(other)) + { + break; + } + if (other->equals(other, sa_other)) + { + /* other matches */ + ike_sa_id = current->ike_sa_id; + } + } + else if (other->is_default_route(other)) + { + if (me->equals(me, sa_me)) + { + /* ME matches */ + ike_sa_id = current->ike_sa_id; + } + } + else + { + if (me->equals(me, sa_me) && other->equals(other, sa_other)) + { + /* both matches */ + ike_sa_id = current->ike_sa_id; + } + } + } + iterator->destroy(iterator); + pthread_mutex_unlock(&(this->mutex)); + + if (ike_sa_id) + { + /* checkout is done in the checkout function, since its rather complex */ + return checkout(this, ike_sa_id, ike_sa); + } + return NOT_FOUND; +} + +/** + * Implementation of ike_sa_manager_t.get_ike_sa_list. + */ +linked_list_t *get_ike_sa_list(private_ike_sa_manager_t* this) +{ + linked_list_t *list; + iterator_t *iterator; + + pthread_mutex_lock(&(this->mutex)); + + list = linked_list_create(); + iterator = this->ike_sa_list->create_iterator(this->ike_sa_list, TRUE); + while (iterator->has_next(iterator)) + { + ike_sa_entry_t *entry; + iterator->current(iterator, (void**)&entry); + list->insert_last(list, (void*)entry->ike_sa_id->clone(entry->ike_sa_id)); + } + iterator->destroy(iterator); + + pthread_mutex_unlock(&(this->mutex)); + return list; +} + +/** + * Implementation of ike_sa_manager_t.get_ike_sa_list_by_name. + */ +linked_list_t *get_ike_sa_list_by_name(private_ike_sa_manager_t* this, const char *name) +{ + linked_list_t *list; + iterator_t *iterator; + + pthread_mutex_lock(&(this->mutex)); + + list = linked_list_create(); + iterator = this->ike_sa_list->create_iterator(this->ike_sa_list, TRUE); + while (iterator->has_next(iterator)) + { + ike_sa_entry_t *entry; + connection_t *connection; + + iterator->current(iterator, (void**)&entry); + connection = entry->ike_sa->get_connection(entry->ike_sa); + if (strcmp(name, connection->get_name(connection)) == 0) + { + list->insert_last(list, (void*)entry->ike_sa_id->clone(entry->ike_sa_id)); + } + } + iterator->destroy(iterator); + + pthread_mutex_unlock(&(this->mutex)); + return list; +} + +/** + * Implementation of ike_sa_manager_t.log_status. + */ +static void log_status(private_ike_sa_manager_t* this, logger_t* logger, char* name) +{ + iterator_t *iterator; + + pthread_mutex_lock(&(this->mutex)); + + iterator = this->ike_sa_list->create_iterator(this->ike_sa_list, TRUE); + while (iterator->has_next(iterator)) + { + ike_sa_entry_t *entry; + iterator->current(iterator, (void**)&entry); + entry->ike_sa->log_status(entry->ike_sa, logger, name); + } + iterator->destroy(iterator); + + pthread_mutex_unlock(&(this->mutex)); +} + +/** + * Implementation of ike_sa_manager_t.checkin. + */ +static status_t checkin(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. + * We can't search by SPI's since the MAY have changed (e.g. on reception + * of a IKE_SA_INIT response). Updating of the SPI MAY be necessary... + */ + status_t retval; + ike_sa_entry_t *entry; + + pthread_mutex_lock(&(this->mutex)); + + /* look for the entry */ + if (this->get_entry_by_sa(this, ike_sa, &entry) == SUCCESS) + { + /* ike_sa_id must be updated */ + entry->ike_sa_id->replace_values(entry->ike_sa_id, ike_sa->get_id(ike_sa)); + /* signal waiting threads */ + entry->checked_out = FALSE; + this->logger->log(this->logger,CONTROL | LEVEL1,"Checkin of IKE_SA successful."); + pthread_cond_signal(&(entry->condvar)); + retval = SUCCESS; + } + else + { + this->logger->log(this->logger,ERROR,"Fatal Error: Tried to checkin nonexisting IKE_SA"); + /* this SA is no more, this REALLY should not happen */ + retval = NOT_FOUND; + } + pthread_mutex_unlock(&(this->mutex)); + return retval; +} + + +/** + * Implementation of ike_sa_manager_t.checkin_and_delete. + */ +static status_t checkin_and_delete(private_ike_sa_manager_t *this, ike_sa_t *ike_sa) +{ + /* deletion is a bit complex, we must garant that no thread is waiting for + * this SA. + * We take this SA from the list, and start signaling while threads + * are in the condvar. + */ + ike_sa_entry_t *entry; + status_t retval; + + pthread_mutex_lock(&(this->mutex)); + + if (this->get_entry_by_sa(this, ike_sa, &entry) == SUCCESS) + { + /* mark it, so now new threads can acquire this SA */ + entry->driveout_new_threads = TRUE; + /* additionaly, drive out waiting threads */ + entry->driveout_waiting_threads = TRUE; + + /* wait until all workers have done their work */ + while (entry->waiting_threads > 0) + { + /* let the other threads do some work*/ + pthread_cond_signal(&(entry->condvar)); + /* and the nice thing, they will wake us again when their work is done */ + pthread_cond_wait(&(entry->condvar), &(this->mutex)); + } + /* ok, we are alone now, no threads waiting in the entry's condvar */ + this->delete_entry(this, entry); + this->logger->log(this->logger,CONTROL | LEVEL1,"Checkin and delete of IKE_SA successful"); + retval = SUCCESS; + } + else + { + this->logger->log(this->logger,ERROR,"Fatal Error: Tried to checkin and delete nonexisting IKE_SA"); + retval = NOT_FOUND; + } + + pthread_mutex_unlock(&(this->mutex)); + return retval; +} + +/** + * Implementation of ike_sa_manager_t.delete. + */ +static status_t delete(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id) +{ + /* deletion is a bit complex, we must garant that no thread is waiting for + * this SA. + * We take this SA from the list, and start signaling while threads + * are in the condvar. + */ + ike_sa_entry_t *entry; + status_t retval; + + pthread_mutex_lock(&(this->mutex)); + + if (this->get_entry_by_id(this, ike_sa_id, &entry) == SUCCESS) + { + /* mark it, so now new threads can acquire this SA */ + entry->driveout_new_threads = TRUE; + + /* wait until all workers have done their work */ + while (entry->waiting_threads) + { + /* wake up all */ + pthread_cond_signal(&(entry->condvar)); + /* and the nice thing, they will wake us again when their work is done */ + pthread_cond_wait(&(entry->condvar), &(this->mutex)); + } + /* ok, we are alone now, no threads waiting in the entry's condvar */ + this->delete_entry(this, entry); + this->logger->log(this->logger,CONTROL | LEVEL1,"Delete of IKE_SA successful"); + retval = SUCCESS; + } + else + { + this->logger->log(this->logger,ERROR,"Fatal Error: Tried to delete nonexisting IKE_SA"); + retval = NOT_FOUND; + } + + pthread_mutex_unlock(&(this->mutex)); + return retval; +} + +/** + * Implementation of ike_sa_manager_t.destroy. + */ +static void destroy(private_ike_sa_manager_t *this) +{ + /* destroy all list entries */ + linked_list_t *list = this->ike_sa_list; + iterator_t *iterator; + ike_sa_entry_t *entry; + + pthread_mutex_lock(&(this->mutex)); + + this->logger->log(this->logger,CONTROL | LEVEL1,"Going to destroy IKE_SA manager and all managed IKE_SA's"); + + /* Step 1: drive out all waiting threads */ + iterator = list->create_iterator(list, TRUE); + + this->logger->log(this->logger,CONTROL | LEVEL2,"Set driveout flags for all stored IKE_SA's"); + while (iterator->has_next(iterator)) + { + iterator->current(iterator, (void**)&entry); + /* do not accept new threads, drive out waiting threads */ + entry->driveout_new_threads = TRUE; + entry->driveout_waiting_threads = TRUE; + } + + this->logger->log(this->logger,CONTROL | LEVEL2,"Wait for all threads to leave IKE_SA's"); + /* Step 2: wait until all are gone */ + iterator->reset(iterator); + while (iterator->has_next(iterator)) + { + iterator->current(iterator, (void**)&entry); + while (entry->waiting_threads) + { + /* wake up all */ + pthread_cond_signal(&(entry->condvar)); + /* go sleeping until they are gone */ + pthread_cond_wait(&(entry->condvar), &(this->mutex)); + } + } + this->logger->log(this->logger,CONTROL | LEVEL2,"Delete all IKE_SA's"); + /* Step 3: delete all entries */ + iterator->destroy(iterator); + + while (list->get_count(list) > 0) + { + list->get_first(list, (void**)&entry); + this->delete_entry(this, entry); + } + list->destroy(list); + this->logger->log(this->logger,CONTROL | LEVEL2,"IKE_SA's deleted"); + pthread_mutex_unlock(&(this->mutex)); + + this->randomizer->destroy(this->randomizer); + + free(this); +} + +/* + * Described in header. + */ +ike_sa_manager_t *ike_sa_manager_create() +{ + private_ike_sa_manager_t *this = malloc_thing(private_ike_sa_manager_t); + + /* assign public functions */ + this->public.destroy = (void(*)(ike_sa_manager_t*))destroy; + this->public.create_and_checkout = (void(*)(ike_sa_manager_t*,ike_sa_t**))create_and_checkout; + this->public.checkout = (status_t(*)(ike_sa_manager_t*, ike_sa_id_t*,ike_sa_t**))checkout; + this->public.checkout_by_hosts = (status_t(*)(ike_sa_manager_t*,host_t*,host_t*,ike_sa_t**))checkout_by_hosts; + this->public.get_ike_sa_list = (linked_list_t*(*)(ike_sa_manager_t*))get_ike_sa_list; + this->public.get_ike_sa_list_by_name = (linked_list_t*(*)(ike_sa_manager_t*,const char*))get_ike_sa_list_by_name; + this->public.log_status = (void(*)(ike_sa_manager_t*,logger_t*,char*))log_status; + this->public.checkin = (status_t(*)(ike_sa_manager_t*,ike_sa_t*))checkin; + this->public.delete = (status_t(*)(ike_sa_manager_t*,ike_sa_id_t*))delete; + this->public.checkin_and_delete = (status_t(*)(ike_sa_manager_t*,ike_sa_t*))checkin_and_delete; + + /* initialize private functions */ + this->get_next_spi = get_next_spi; + this->get_entry_by_sa = get_entry_by_sa; + this->get_entry_by_id = get_entry_by_id; + this->delete_entry = delete_entry; + + /* initialize private variables */ + this->logger = logger_manager->get_logger(logger_manager, IKE_SA_MANAGER); + + this->ike_sa_list = linked_list_create(); + + pthread_mutex_init(&(this->mutex), NULL); + + this->randomizer = randomizer_create(); + + return (ike_sa_manager_t*)this; +} diff --git a/src/charon/sa/ike_sa_manager.h b/src/charon/sa/ike_sa_manager.h new file mode 100644 index 000000000..d4cd749dc --- /dev/null +++ b/src/charon/sa/ike_sa_manager.h @@ -0,0 +1,194 @@ +/** + * @file ike_sa_manager.h + * + * @brief Interface of ike_sa_manager_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef IKE_SA_MANAGER_H_ +#define IKE_SA_MANAGER_H_ + +#include +#include +#include + + +typedef struct ike_sa_manager_t ike_sa_manager_t; + +/** + * @brief The IKE_SA-Manager is responsible for managing all initiated and responded IKE_SA's. + * + * To avoid access from multiple threads, IKE_SAs must be checked out from + * the manager, and checked in after usage. + * The manager also handles deletion of SAs. + * + * @todo checking of double-checkouts from the same threads would be nice. + * This could be done by comparing thread-ids via pthread_self()... + * + * @todo Managing of ike_sa_t objects in a hash table instead of linked list. + * + * @b Constructors: + * - ike_sa_manager_create() + * + * @ingroup sa + */ +struct ike_sa_manager_t { + /** + * @brief Checkout an IKE_SA, create it when necesarry. + * + * Checks out a SA by its ID. An SA will be created, when: + * - Responder SPI is not set (when received an IKE_SA_INIT from initiator) + * Management of SPIs is the managers job, he will set it. + * This function blocks until SA is available for checkout. + * + * @warning checking out two times without checking in will + * result in a deadlock! + * + * @param this the manager object + * @param ike_sa_id[in/out] the SA identifier, will be updated + * @param ike_sa[out] checked out SA + * @returns + * - SUCCESS if checkout successful + * - NOT_FOUND when no such SA is available + * - CREATED if a new IKE_SA got created + */ + status_t (*checkout) (ike_sa_manager_t* this, ike_sa_id_t *sa_id, ike_sa_t **ike_sa); + + /** + * @brief Create and checkout an IKE_SA as original initator. + * + * Creates and checks out a SA as initiator. + * Management of SPIs is the managers job, he will set it. + * + * @param this the manager object + * @param ike_sa[out] checked out SA + */ + void (*create_and_checkout) (ike_sa_manager_t* this,ike_sa_t **ike_sa); + + /** + * @brief Check out an IKE_SA, defined be the two peers. + * + * Checking out an IKE_SA by their peer addresses may be necessary + * for kernel traps, status querying and so on... one of the hosts + * may be 0.0.0.0 (defaultroute/any), but not both. + * + * @param this the manager object + * @param me host on local side + * @param other host on remote side + * @param ike_sa[out] checked out SA + * @return + * - NOT_FOUND, if no such SA found + * - SUCCESS, if SA found and ike_sa set appropriatly + */ + status_t (*checkout_by_hosts) (ike_sa_manager_t* this, host_t *me, host_t *other, ike_sa_t **ike_sa); + + /** + * @brief Get a list of all IKE_SA SAs currently set up. + * + * The resulting list with all IDs must be destroyd by + * the caller. There is no guarantee an ike_sa with the + * corrensponding ID really exists, since it may be deleted + * in the meantime by another thread. + * + * @param this the manager object + * @return a list with ike_sa_id_t s + */ + linked_list_t *(*get_ike_sa_list) (ike_sa_manager_t* this); + + /** + * @brief Get a list of all IKE_SA SAs currently set up specified + * by the connections name. + * + * @param this the manager object + * @return a list with ike_sa_id_t s + */ + linked_list_t *(*get_ike_sa_list_by_name) (ike_sa_manager_t* this, const char *name); + + /** + * @brief Log the status of the IKE_SA's in the manager. + * + * A informational log is done to the supplied logger. If logger is + * NULL, an internal logger is used. If a name is supplied, + * only connections with the matching name will be logged. + * + * @param this the manager object + * @param logger logger to do the log, or NULL + * @param name name of a connection, or NULL + */ + void (*log_status) (ike_sa_manager_t* this, logger_t* logger, char* name); + + /** + * @brief Checkin the SA after usage. + * + * @warning the SA pointer MUST NOT be used after checkin! + * The SA must be checked out again! + * + * @param this the manager object + * @param ike_sa_id[in/out] the SA identifier, will be updated + * @param ike_sa[out] checked out SA + * @returns + * - SUCCESS if checked in + * - NOT_FOUND when not found (shouldn't happen!) + */ + status_t (*checkin) (ike_sa_manager_t* this, ike_sa_t *ike_sa); + + /** + * @brief Delete a SA, which was not checked out. + * + * @warning do not use this when the SA is already checked out, this will + * deadlock! + * + * @param this the manager object + * @param ike_sa_id[in/out] the SA identifier + * @returns + * - SUCCESS if found + * - NOT_FOUND when no such SA is available + */ + status_t (*delete) (ike_sa_manager_t* this, ike_sa_id_t *ike_sa_id); + + /** + * @brief Delete a checked out SA. + * + * @param this the manager object + * @param ike_sa SA to delete + * @returns + * - SUCCESS if found + * - NOT_FOUND when no such SA is available + */ + status_t (*checkin_and_delete) (ike_sa_manager_t* this, ike_sa_t *ike_sa); + + /** + * @brief Destroys the manager with all associated SAs. + * + * Threads will be driven out, so all SAs can be deleted cleanly. + * + * @param this the manager object + */ + void (*destroy) (ike_sa_manager_t *this); +}; + +/** + * @brief Create a manager. + * + * @returns ike_sa_manager_t object + * + * @ingroup sa + */ +ike_sa_manager_t *ike_sa_manager_create(void); + +#endif /*IKE_SA_MANAGER_H_*/ diff --git a/src/charon/sa/states/Makefile.states b/src/charon/sa/states/Makefile.states new file mode 100644 index 000000000..a258ebef0 --- /dev/null +++ b/src/charon/sa/states/Makefile.states @@ -0,0 +1,43 @@ +# Copyright (C) 2005 Jan Hutter, 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 . +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# + +STATES_DIR= $(SA_DIR)states/ + +CHARON_OBJS+= $(BUILD_DIR)ike_auth_requested.o +$(BUILD_DIR)ike_auth_requested.o : $(STATES_DIR)ike_auth_requested.c $(STATES_DIR)ike_auth_requested.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)ike_sa_established.o +$(BUILD_DIR)ike_sa_established.o : $(STATES_DIR)ike_sa_established.c $(STATES_DIR)ike_sa_established.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)ike_sa_init_requested.o +$(BUILD_DIR)ike_sa_init_requested.o : $(STATES_DIR)ike_sa_init_requested.c $(STATES_DIR)ike_sa_init_requested.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)ike_sa_init_responded.o +$(BUILD_DIR)ike_sa_init_responded.o : $(STATES_DIR)ike_sa_init_responded.c $(STATES_DIR)ike_sa_init_responded.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)initiator_init.o +$(BUILD_DIR)initiator_init.o : $(STATES_DIR)initiator_init.c $(STATES_DIR)initiator_init.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)responder_init.o +$(BUILD_DIR)responder_init.o : $(STATES_DIR)responder_init.c $(STATES_DIR)responder_init.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)state.o +$(BUILD_DIR)state.o : $(STATES_DIR)state.c $(STATES_DIR)state.h + $(CC) $(CFLAGS) -c -o $@ $< \ No newline at end of file diff --git a/src/charon/sa/states/ike_auth_requested.c b/src/charon/sa/states/ike_auth_requested.c new file mode 100644 index 000000000..3d49f440f --- /dev/null +++ b/src/charon/sa/states/ike_auth_requested.c @@ -0,0 +1,671 @@ +/** + * @file ike_auth_requested.c + * + * @brief Implementation of ike_auth_requested_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 + +#include "ike_auth_requested.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct private_ike_auth_requested_t private_ike_auth_requested_t; + +/** + * Private data of a ike_auth_requested_t object. + * + */ +struct private_ike_auth_requested_t { + /** + * Public interface of ike_auth_requested_t. + */ + ike_auth_requested_t public; + + /** + * Assigned IKE_SA. + */ + protected_ike_sa_t *ike_sa; + + /** + * SA config, just a copy of the one stored in the ike_sa. + */ + policy_t *policy; + + /** + * Received nonce from responder. + */ + chunk_t received_nonce; + + /** + * Sent nonce in IKE_SA_INIT request. + */ + chunk_t sent_nonce; + + /** + * IKE_SA_INIT-Request in binary form. + */ + chunk_t ike_sa_init_reply_data; + + /** + * Proposal to setup CHILD_SA + */ + proposal_t *proposal; + + /** + * Traffic selectors applicable at our site + */ + linked_list_t *my_ts; + + /** + * Traffic selectors applicable at remote site + */ + linked_list_t *other_ts; + + /** + * Child sa created in ike_sa_init_requested + */ + child_sa_t *child_sa; + + /** + * Assigned Logger. + * + * Is logger of ike_sa! + */ + logger_t *logger; + + /** + * Process the IDr payload (check if other id is valid) + * + * @param this calling object + * @param idr_payload ID payload of responder + * @return + * - SUCCESS + * - DELETE_ME + */ + status_t (*process_idr_payload) (private_ike_auth_requested_t *this, id_payload_t *idr_payload); + + /** + * Process the SA payload (check if selected proposals are valid, setup child sa) + * + * @param this calling object + * @param sa_payload SA payload of responder + * + * - SUCCESS + * - DELETE_ME + */ + status_t (*process_sa_payload) (private_ike_auth_requested_t *this, sa_payload_t *sa_payload); + + /** + * Process the AUTH payload (check authenticity of message) + * + * @param this calling object + * @param auth_payload AUTH payload of responder + * @param other_id_payload ID payload of responder + * + * - SUCCESS + * - DELETE_ME + */ + status_t (*process_auth_payload) (private_ike_auth_requested_t *this, auth_payload_t *auth_payload, id_payload_t *other_id_payload); + + /** + * Process the TS payload (check if selected traffic selectors are valid) + * + * @param this calling object + * @param ts_initiator TRUE if TS payload is TSi, FALSE for TSr + * @param ts_payload TS payload of responder + * + * - SUCCESS + * - DELETE_ME + */ + status_t (*process_ts_payload) (private_ike_auth_requested_t *this, bool ts_initiator, ts_payload_t *ts_payload); + + /** + * Process a notify payload + * + * @param this calling object + * @param notify_payload notify payload + * + * - SUCCESS + * - FAILED + * - DELETE_ME + */ + status_t (*process_notify_payload) (private_ike_auth_requested_t *this, notify_payload_t *notify_payload); + + /** + * Destroy function called internally of this class after state change to + * state IKE_SA_ESTABLISHED succeeded. + * + * This destroy function does not destroy objects which were passed to the new state. + * + * @param this calling object + */ + void (*destroy_after_state_change) (private_ike_auth_requested_t *this); +}; + + +/** + * Implements state_t.process_message + */ +static status_t process_message(private_ike_auth_requested_t *this, message_t *ike_auth_reply) +{ + ts_payload_t *tsi_payload = NULL, *tsr_payload = NULL; + id_payload_t *idr_payload = NULL; + auth_payload_t *auth_payload = NULL; + sa_payload_t *sa_payload = NULL; + iterator_t *payloads = NULL; + crypter_t *crypter = NULL; + signer_t *signer = NULL; + status_t status; + host_t *my_host, *other_host; + chunk_t seed; + prf_plus_t *prf_plus; + connection_t *connection; + + if (ike_auth_reply->get_exchange_type(ike_auth_reply) != IKE_AUTH) + { + this->logger->log(this->logger, ERROR | LEVEL1, "Message of type %s not supported in state ike_auth_requested", + mapping_find(exchange_type_m,ike_auth_reply->get_exchange_type(ike_auth_reply))); + return FAILED; + } + + if (ike_auth_reply->get_request(ike_auth_reply)) + { + this->logger->log(this->logger, ERROR | LEVEL1, "IKE_AUTH requests not allowed state ike_sa_init_responded"); + return FAILED; + } + + /* get signer for verification and crypter for decryption */ + signer = this->ike_sa->get_signer_responder(this->ike_sa); + crypter = this->ike_sa->get_crypter_responder(this->ike_sa); + + /* parse incoming message */ + status = ike_auth_reply->parse_body(ike_auth_reply, crypter, signer); + if (status != SUCCESS) + { + this->logger->log(this->logger, AUDIT, "IKE_AUTH reply decryption failed. Ignoring message"); + return status; + } + + this->policy = this->ike_sa->get_policy(this->ike_sa); + + /* we collect all payloads, which are processed later. Notify's are processed + * in place, since we don't know how may are there. + */ + payloads = ike_auth_reply->get_payload_iterator(ike_auth_reply); + while (payloads->has_next(payloads)) + { + payload_t *payload; + payloads->current(payloads, (void**)&payload); + + switch (payload->get_type(payload)) + { + case AUTHENTICATION: + { + auth_payload = (auth_payload_t*)payload; + break; + } + case ID_RESPONDER: + { + idr_payload = (id_payload_t*)payload; + break; + } + case SECURITY_ASSOCIATION: + { + sa_payload = (sa_payload_t*)payload; + break; + } + case TRAFFIC_SELECTOR_INITIATOR: + { + tsi_payload = (ts_payload_t*)payload; + break; + } + case TRAFFIC_SELECTOR_RESPONDER: + { + tsr_payload = (ts_payload_t*)payload; + break; + } + case NOTIFY: + { + notify_payload_t *notify_payload = (notify_payload_t *) payload; + /* handle the notify directly, abort if no further processing required */ + status = this->process_notify_payload(this, notify_payload); + if (status != SUCCESS) + { + payloads->destroy(payloads); + return status; + } + } + case CERTIFICATE: + { + /* TODO handle cert payloads */ + } + default: + { + this->logger->log(this->logger, ERROR|LEVEL1, "Ignoring Payload %s (%d)", + mapping_find(payload_type_m, payload->get_type(payload)), payload->get_type(payload)); + break; + } + } + } + /* iterator can be destroyed */ + payloads->destroy(payloads); + + /* check if we have all payloads */ + if (!(idr_payload && sa_payload && auth_payload && tsi_payload && tsr_payload)) + { + this->logger->log(this->logger, AUDIT, "IKE_AUTH reply did not contain all required payloads. Deleting IKE_SA"); + return DELETE_ME; + } + + /* process all payloads */ + status = this->process_idr_payload(this, idr_payload); + if (status != SUCCESS) + { + return status; + } + status = this->process_auth_payload(this, auth_payload,idr_payload); + if (status != SUCCESS) + { + return status; + } + status = this->process_sa_payload(this, sa_payload); + if (status != SUCCESS) + { + return status; + } + status = this->process_ts_payload(this, TRUE, tsi_payload); + if (status != SUCCESS) + { + return status; + } + status = this->process_ts_payload(this, FALSE, tsr_payload); + if (status != SUCCESS) + { + return status; + } + + /* install child SAs for AH and esp */ + if (!this->child_sa) + { + this->logger->log(this->logger, CONTROL, "No CHILD_SA requested, no CHILD_SA built"); + } + if (!this->proposal) + { + this->logger->log(this->logger, CONTROL, "Proposal negotiation failed, no CHILD_SA built"); + this->child_sa->destroy(this->child_sa); + this->child_sa = NULL; + } + else if (this->my_ts->get_count(this->my_ts) == 0 || this->other_ts->get_count(this->other_ts) == 0) + { + this->logger->log(this->logger, CONTROL, "Traffic selector negotiation failed, no CHILD_SA built"); + this->child_sa->destroy(this->child_sa); + this->child_sa = NULL; + } + else + { + seed = chunk_alloc(this->sent_nonce.len + this->received_nonce.len); + memcpy(seed.ptr, this->sent_nonce.ptr, this->sent_nonce.len); + memcpy(seed.ptr + this->sent_nonce.len, this->received_nonce.ptr, this->received_nonce.len); + prf_plus = prf_plus_create(this->ike_sa->get_child_prf(this->ike_sa), seed); + chunk_free(&seed); + + status = this->child_sa->update(this->child_sa, this->proposal, prf_plus); + prf_plus->destroy(prf_plus); + if (status != SUCCESS) + { + this->logger->log(this->logger, AUDIT, "Could not install CHILD_SA! Deleting IKE_SA"); + return DELETE_ME; + } + status = this->child_sa->add_policies(this->child_sa, this->my_ts, this->other_ts); + if (status != SUCCESS) + { + this->logger->log(this->logger, AUDIT, "Could not install CHILD_SA policy! Deleting IKE_SA"); + return DELETE_ME; + } + this->ike_sa->add_child_sa(this->ike_sa, this->child_sa); + } + + this->ike_sa->set_last_replied_message_id(this->ike_sa,ike_auth_reply->get_message_id(ike_auth_reply)); + + /* create new state */ + this->ike_sa->set_new_state(this->ike_sa, (state_t*)ike_sa_established_create(this->ike_sa)); + this->destroy_after_state_change(this); + + connection = this->ike_sa->get_connection(this->ike_sa); + my_host = connection->get_my_host(connection); + other_host = connection->get_other_host(connection); + this->logger->log(this->logger, AUDIT, "IKE_SA established between %s - %s", + my_host->get_address(my_host), other_host->get_address(other_host)); + + return SUCCESS; +} + +/** + * Implements private_ike_auth_requested_t.process_idr_payload + */ +static status_t process_idr_payload(private_ike_auth_requested_t *this, id_payload_t *idr_payload) +{ + identification_t *other_id, *configured_other_id; + connection_t *connection; + + other_id = idr_payload->get_identification(idr_payload); + configured_other_id = this->policy->get_other_id(this->policy); + + this->logger->log(this->logger, CONTROL|LEVEL1, "configured ID: %s, ID of responder: %s", + configured_other_id->get_string(configured_other_id), + other_id->get_string(other_id)); + + if (!other_id->belongs_to(other_id, configured_other_id)) + { + other_id->destroy(other_id); + this->logger->log(this->logger, AUDIT, "IKE_AUTH reply contained a not acceptable ID. Deleting IKE_SA"); + return DELETE_ME; + } + + connection = this->ike_sa->get_connection(this->ike_sa); + connection->update_other_id(connection, other_id->clone(other_id)); + + this->policy->update_other_id(this->policy, other_id); + return SUCCESS; +} + +/** + * Implements private_ike_auth_requested_t.process_sa_payload + */ +static status_t process_sa_payload(private_ike_auth_requested_t *this, sa_payload_t *sa_payload) +{ + proposal_t *proposal, *proposal_tmp; + linked_list_t *proposal_list; + + /* get his selected proposal */ + proposal_list = sa_payload->get_proposals(sa_payload); + /* check count of proposals */ + if (proposal_list->get_count(proposal_list) == 0) + { + /* no proposal? we accept this, but no child sa is built */ + this->logger->log(this->logger, AUDIT, "IKE_AUTH reply's SA_PAYLOAD didn't contain any proposals. No CHILD_SA created", + proposal_list->get_count(proposal_list)); + proposal_list->destroy(proposal_list); + return SUCCESS; + } + if (proposal_list->get_count(proposal_list) > 1) + { + this->logger->log(this->logger, AUDIT, "IKE_AUTH reply's SA_PAYLOAD contained %d proposal. Deleting IKE_SA", + proposal_list->get_count(proposal_list)); + while (proposal_list->remove_last(proposal_list, (void**)&proposal) == SUCCESS) + { + proposal->destroy(proposal); + } + proposal_list->destroy(proposal_list); + return DELETE_ME; + } + + /* we have to re-check here if other's selection is valid */ + proposal = this->policy->select_proposal(this->policy, proposal_list); + /* list not needed anymore */ + while (proposal_list->remove_last(proposal_list, (void**)&proposal_tmp) == SUCCESS) + { + proposal_tmp->destroy(proposal_tmp); + } + proposal_list->destroy(proposal_list); + /* got a match? */ + if (proposal == NULL) + { + this->logger->log(this->logger, AUDIT, "IKE_AUTH reply contained a not offered proposal. Deleting IKE_SA"); + return DELETE_ME; + } + + /* apply proposal */ + this->proposal = proposal; + + return SUCCESS; +} + +/** + * Implements private_ike_auth_requested_t.process_auth_payload + */ +static status_t process_auth_payload(private_ike_auth_requested_t *this, auth_payload_t *auth_payload, id_payload_t *other_id_payload) +{ + authenticator_t *authenticator; + status_t status; + + authenticator = authenticator_create(this->ike_sa); + status = authenticator->verify_auth_data(authenticator,auth_payload,this->ike_sa_init_reply_data,this->sent_nonce,other_id_payload,FALSE); + authenticator->destroy(authenticator); + if (status != SUCCESS) + { + this->logger->log(this->logger, AUDIT, "Verification of IKE_AUTH reply failed. Deleting IKE_SA"); + return DELETE_ME; + } + + this->logger->log(this->logger, CONTROL|LEVEL1, "AUTH data verified successfully"); + return SUCCESS; +} + +/** + * Implements private_ike_auth_requested_t.process_ts_payload + */ +static status_t process_ts_payload(private_ike_auth_requested_t *this, bool ts_initiator, ts_payload_t *ts_payload) +{ + linked_list_t *ts_received, *ts_selected; + traffic_selector_t *ts; + + /* get ts form payload */ + ts_received = ts_payload->get_traffic_selectors(ts_payload); + /* select ts depending on payload type */ + if (ts_initiator) + { + ts_selected = this->policy->select_my_traffic_selectors(this->policy, ts_received); + this->my_ts = ts_selected; + } + else + { + ts_selected = this->policy->select_other_traffic_selectors(this->policy, ts_received); + this->other_ts = ts_selected; + } + /* check if the responder selected valid proposals */ + if (ts_selected->get_count(ts_selected) != ts_received->get_count(ts_received)) + { + this->logger->log(this->logger, AUDIT, "IKE_AUTH reply contained not offered traffic selectors."); + } + + /* cleanup */ + while (ts_received->remove_last(ts_received, (void**)&ts) == SUCCESS) + { + ts->destroy(ts); + } + ts_received->destroy(ts_received); + + return SUCCESS; +} + +/** + * Implements private_ike_auth_requested_t.process_notify_payload + */ +static status_t process_notify_payload(private_ike_auth_requested_t *this, notify_payload_t *notify_payload) +{ + notify_message_type_t notify_message_type = notify_payload->get_notify_message_type(notify_payload); + + this->logger->log(this->logger, CONTROL|LEVEL1, "Process notify type %s", + mapping_find(notify_message_type_m, notify_message_type)); + + switch (notify_message_type) + { + case INVALID_SYNTAX: + { + this->logger->log(this->logger, AUDIT, "IKE_AUTH reply contained an INVALID_SYNTAX notify. Deleting IKE_SA"); + return DELETE_ME; + + } + case AUTHENTICATION_FAILED: + { + this->logger->log(this->logger, AUDIT, "IKE_AUTH reply contained an AUTHENTICATION_FAILED notify. Deleting IKE_SA"); + return DELETE_ME; + + } + case SINGLE_PAIR_REQUIRED: + { + this->logger->log(this->logger, AUDIT, "IKE_AUTH reply contained a SINGLE_PAIR_REQUIRED notify. Deleting IKE_SA"); + return DELETE_ME; + } + default: + { + /* + * - In case of unknown error: IKE_SA gets destroyed. + * - In case of unknown status: logging + */ + + if (notify_message_type < 16383) + { + this->logger->log(this->logger, AUDIT, "IKE_AUTH reply contained an unknown notify error (%d). Deleting IKE_SA", + notify_message_type); + return DELETE_ME; + + } + else + { + this->logger->log(this->logger, CONTROL, "IKE_AUTH reply contained an unknown notify (%d), ignored.", + notify_message_type); + return SUCCESS; + } + } + } +} + +/** + * Implements state_t.get_state + */ +static ike_sa_state_t get_state(private_ike_auth_requested_t *this) +{ + return IKE_AUTH_REQUESTED; +} + +/** + * Implements state_t.get_state + */ +static void destroy(private_ike_auth_requested_t *this) +{ + chunk_free(&(this->received_nonce)); + chunk_free(&(this->sent_nonce)); + chunk_free(&(this->ike_sa_init_reply_data)); + if (this->child_sa) + { + this->child_sa->destroy(this->child_sa); + } + if (this->my_ts) + { + traffic_selector_t *ts; + while (this->my_ts->remove_last(this->my_ts, (void**)&ts) == SUCCESS) + { + ts->destroy(ts); + } + this->my_ts->destroy(this->my_ts); + } + if (this->other_ts) + { + traffic_selector_t *ts; + while (this->other_ts->remove_last(this->other_ts, (void**)&ts) == SUCCESS) + { + ts->destroy(ts); + } + this->other_ts->destroy(this->other_ts); + } + if (this->proposal) + { + this->proposal->destroy(this->proposal); + } + free(this); +} +/** + * Implements protected_ike_sa_t.destroy_after_state_change + */ +static void destroy_after_state_change(private_ike_auth_requested_t *this) +{ + chunk_free(&(this->received_nonce)); + chunk_free(&(this->sent_nonce)); + chunk_free(&(this->ike_sa_init_reply_data)); + if (this->my_ts) + { + traffic_selector_t *ts; + while (this->my_ts->remove_last(this->my_ts, (void**)&ts) == SUCCESS) + { + ts->destroy(ts); + } + this->my_ts->destroy(this->my_ts); + } + if (this->other_ts) + { + traffic_selector_t *ts; + while (this->other_ts->remove_last(this->other_ts, (void**)&ts) == SUCCESS) + { + ts->destroy(ts); + } + this->other_ts->destroy(this->other_ts); + } + if (this->proposal) + { + this->proposal->destroy(this->proposal); + } + free(this); +} + +/* + * Described in header. + */ +ike_auth_requested_t *ike_auth_requested_create(protected_ike_sa_t *ike_sa,chunk_t sent_nonce,chunk_t received_nonce,chunk_t ike_sa_init_reply_data, child_sa_t *child_sa) +{ + private_ike_auth_requested_t *this = malloc_thing(private_ike_auth_requested_t); + + /* interface functions */ + this->public.state_interface.process_message = (status_t (*) (state_t *,message_t *)) process_message; + this->public.state_interface.get_state = (ike_sa_state_t (*) (state_t *)) get_state; + this->public.state_interface.destroy = (void (*) (state_t *)) destroy; + + /* private functions */ + this->process_idr_payload = process_idr_payload; + this->process_sa_payload = process_sa_payload; + this->process_auth_payload = process_auth_payload; + this->process_ts_payload = process_ts_payload; + this->process_notify_payload = process_notify_payload; + this->destroy_after_state_change = destroy_after_state_change; + + /* private data */ + this->ike_sa = ike_sa; + this->received_nonce = received_nonce; + this->sent_nonce = sent_nonce; + this->ike_sa_init_reply_data = ike_sa_init_reply_data; + this->logger = logger_manager->get_logger(logger_manager, IKE_SA); + this->my_ts = NULL; + this->other_ts = NULL; + this->proposal = NULL; + this->child_sa = child_sa; + + return &(this->public); +} diff --git a/src/charon/sa/states/ike_auth_requested.h b/src/charon/sa/states/ike_auth_requested.h new file mode 100644 index 000000000..a8eef014c --- /dev/null +++ b/src/charon/sa/states/ike_auth_requested.h @@ -0,0 +1,72 @@ +/** + * @file ike_auth_requested.h + * + * @brief Interface of ike_auth_requested_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef IKE_AUTH_REQUESTED_H_ +#define IKE_AUTH_REQUESTED_H_ + +#include +#include + + +typedef struct ike_auth_requested_t ike_auth_requested_t; + +/** + * @brief This class represents an IKE_SA, which has requested an IKE_AUTH. + * + * The state accpets IKE_AUTH responses. It proves the authenticity + * and sets up the first child sa. After that, it changes IKE_SA state to + * IKE_SA_ESTABLISHED. + * + * @ Constructors: + * - ike_auth_requested_create() + * + * @todo handle certificate payloads + * + * @ingroup states + */ +struct ike_auth_requested_t { + /** + * The state_t interface. + */ + state_t state_interface; + +}; + +/** + * Constructor of class ike_auth_requested_t + * + * @param ike_sa assigned ike_sa object + * @param sent_nonce Sent nonce value in IKE_SA_INIT request + * @param received_nonce Received nonce value in IKE_SA_INIT response + * @param ike_sa_init_reply_data binary representation of IKE_SA_INIT reply + * @param child_sa opened but not completed child_sa + * @return created ike_auth_requested_t object + * + * @ingroup states + */ +ike_auth_requested_t *ike_auth_requested_create(protected_ike_sa_t *ike_sa, + chunk_t sent_nonce, + chunk_t received_nonce, + chunk_t ike_sa_init_reply_data, + child_sa_t *child_sa); + +#endif /*IKE_AUTH_REQUESTED_H_*/ diff --git a/src/charon/sa/states/ike_sa_established.c b/src/charon/sa/states/ike_sa_established.c new file mode 100644 index 000000000..e91409f6a --- /dev/null +++ b/src/charon/sa/states/ike_sa_established.c @@ -0,0 +1,239 @@ +/** + * @file ike_sa_established.c + * + * @brief Implementation of ike_sa_established_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 "ike_sa_established.h" + +#include +#include + + +typedef struct private_ike_sa_established_t private_ike_sa_established_t; + +/** + * Private data of a ike_sa_established_t object. + */ +struct private_ike_sa_established_t { + /** + * methods of the state_t interface + */ + ike_sa_established_t public; + + /** + * Assigned IKE_SA. + */ + protected_ike_sa_t *ike_sa; + + /** + * Assigned logger. Use logger of IKE_SA. + */ + logger_t *logger; + + /** + * Process a notify payload + * + * @param this calling object + * @param notify_payload notify payload + * @param response response message of type INFORMATIONAL + * + * - SUCCESS + * - FAILED + * - DELETE_ME + */ + status_t (*process_notify_payload) (private_ike_sa_established_t *this, notify_payload_t *notify_payload,message_t *response); +}; + +/** + * Implements state_t.get_state + */ +static status_t process_message(private_ike_sa_established_t *this, message_t *message) +{ + delete_payload_t *delete_request = NULL; + ike_sa_id_t *ike_sa_id; + iterator_t *payloads; + message_t *response; + crypter_t *crypter; + signer_t *signer; + status_t status; + + if (message->get_exchange_type(message) != INFORMATIONAL) + { + this->logger->log(this->logger, ERROR | LEVEL1, "Message of type %s not supported in state ike_sa_established", + mapping_find(exchange_type_m,message->get_exchange_type(message))); + return FAILED; + } + + if (!message->get_request(message)) + { + this->logger->log(this->logger, ERROR | LEVEL1, "INFORMATIONAL responses not handled in state ike_sa_established"); + return FAILED; + } + + ike_sa_id = this->ike_sa->public.get_id(&(this->ike_sa->public)); + + /* get signer for verification and crypter for decryption */ + if (!ike_sa_id->is_initiator(ike_sa_id)) + { + crypter = this->ike_sa->get_crypter_initiator(this->ike_sa); + signer = this->ike_sa->get_signer_initiator(this->ike_sa); + } + else + { + crypter = this->ike_sa->get_crypter_responder(this->ike_sa); + signer = this->ike_sa->get_signer_responder(this->ike_sa); + } + + /* parse incoming message */ + status = message->parse_body(message, crypter, signer); + if (status != SUCCESS) + { + this->logger->log(this->logger, AUDIT, "INFORMATIONAL request decryption failed. Ignoring message"); + return status; + } + + /* build empty INFORMATIONAL message */ + this->ike_sa->build_message(this->ike_sa, INFORMATIONAL, FALSE, &response); + + payloads = message->get_payload_iterator(message); + + while (payloads->has_next(payloads)) + { + payload_t *payload; + payloads->current(payloads, (void**)&payload); + + switch (payload->get_type(payload)) + { + case NOTIFY: + { + notify_payload_t *notify_payload = (notify_payload_t *) payload; + /* handle the notify directly, abort if no further processing required */ + status = this->process_notify_payload(this, notify_payload,response); + if (status != SUCCESS) + { + payloads->destroy(payloads); + response->destroy(response); + return status; + } + } + case DELETE: + { + delete_request = (delete_payload_t *) payload; + break; + } + default: + { + this->logger->log(this->logger, ERROR|LEVEL1, "Ignoring Payload %s (%d)", + mapping_find(payload_type_m, payload->get_type(payload)), payload->get_type(payload)); + break; + } + } + } + /* iterator can be destroyed */ + payloads->destroy(payloads); + + if (delete_request) + { + if (delete_request->get_protocol_id(delete_request) == PROTO_IKE) + { + this->logger->log(this->logger, AUDIT, "DELETE request for IKE_SA received"); + response->destroy(response); + return DELETE_ME; + } + else + { + this->logger->log(this->logger, AUDIT, "DELETE request for CHILD_SA received. Ignored"); + response->destroy(response); + return SUCCESS; + } + } + + status = this->ike_sa->send_response(this->ike_sa, response); + /* message can now be sent (must not be destroyed) */ + if (status != SUCCESS) + { + this->logger->log(this->logger, AUDIT, "Unable to send INFORMATIONAL reply"); + response->destroy(response); + return FAILED; + } + + return SUCCESS; +} + +/** + * Implementation of private_ike_sa_established_t.process_notify_payload; + */ +static status_t process_notify_payload (private_ike_sa_established_t *this, notify_payload_t *notify_payload, message_t *response) +{ + notify_message_type_t notify_message_type = notify_payload->get_notify_message_type(notify_payload); + + this->logger->log(this->logger, CONTROL|LEVEL1, "Process notify type %s for protocol %s", + mapping_find(notify_message_type_m, notify_message_type), + mapping_find(protocol_id_m, notify_payload->get_protocol_id(notify_payload))); + + switch (notify_message_type) + { + default: + { + this->logger->log(this->logger, AUDIT, "INFORMATIONAL request contained an unknown notify (%d), ignored.", notify_message_type); + } + } + + + return SUCCESS; +} + +/** + * Implementation of state_t.get_state. + */ +static ike_sa_state_t get_state(private_ike_sa_established_t *this) +{ + return IKE_SA_ESTABLISHED; +} + +/** + * Implementation of state_t.get_state + */ +static void destroy(private_ike_sa_established_t *this) +{ + free(this); +} + +/* + * Described in header. + */ +ike_sa_established_t *ike_sa_established_create(protected_ike_sa_t *ike_sa) +{ + private_ike_sa_established_t *this = malloc_thing(private_ike_sa_established_t); + + /* interface functions */ + this->public.state_interface.process_message = (status_t (*) (state_t *,message_t *)) process_message; + this->public.state_interface.get_state = (ike_sa_state_t (*) (state_t *)) get_state; + this->public.state_interface.destroy = (void (*) (state_t *)) destroy; + + /* private functions */ + this->process_notify_payload = process_notify_payload; + + /* private data */ + this->ike_sa = ike_sa; + this->logger = logger_manager->get_logger(logger_manager, IKE_SA); + + return &(this->public); +} diff --git a/src/charon/sa/states/ike_sa_established.h b/src/charon/sa/states/ike_sa_established.h new file mode 100644 index 000000000..8477ad5bc --- /dev/null +++ b/src/charon/sa/states/ike_sa_established.h @@ -0,0 +1,64 @@ +/** + * @file ike_sa_established.h + * + * @brief Interface of ike_sa_established_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef IKE_SA_ESTABLISHED_H_ +#define IKE_SA_ESTABLISHED_H_ + +#include +#include + +typedef struct ike_sa_established_t ike_sa_established_t; + +/** + * @brief This class represents an the state of an established + * IKE_SA. + * + * @b Constructors: + * - ike_sa_established_create() + * + * @todo Implement handling of CREATE_CHILD_SA requests + * + * @todo Implement initialization of CREATE_CHILD_SA requests + * + * @todo Implement handling of any other message + * + * @ingroup states + */ +struct ike_sa_established_t { + /** + * methods of the state_t interface + */ + state_t state_interface; + +}; + +/** + * @brief Constructor of class ike_sa_established_t + * + * @param ike_sa assigned ike_sa + * @return created ike_sa_established_t object + * + * @ingroup states + */ +ike_sa_established_t *ike_sa_established_create(protected_ike_sa_t *ike_sa); + +#endif /*IKE_SA_ESTABLISHED_H_*/ diff --git a/src/charon/sa/states/ike_sa_init_requested.c b/src/charon/sa/states/ike_sa_init_requested.c new file mode 100644 index 000000000..311cdf0a0 --- /dev/null +++ b/src/charon/sa/states/ike_sa_init_requested.c @@ -0,0 +1,798 @@ +/** + * @file ike_sa_init_requested.c + * + * @brief Implementation of ike_sa_init_requested_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 "ike_sa_init_requested.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +typedef struct private_ike_sa_init_requested_t private_ike_sa_init_requested_t; + +/** + * Private data of a ike_sa_init_requested_t object. + * + */ +struct private_ike_sa_init_requested_t { + /** + * Public interface of an ike_sa_init_requested_t object. + */ + ike_sa_init_requested_t public; + + /** + * Assigned IKE_SA + */ + protected_ike_sa_t *ike_sa; + + /** + * Diffie Hellman object used to compute shared secret. + */ + diffie_hellman_t *diffie_hellman; + + /** + * Sent nonce value. + */ + chunk_t sent_nonce; + + /** + * Received nonce + */ + chunk_t received_nonce; + + /** + * Selected proposal + */ + proposal_t *proposal; + + /** + * Packet data of ike_sa_init request + */ + chunk_t ike_sa_init_request_data; + + /** + * Created child sa, if any + */ + child_sa_t *child_sa; + + /** + * Assigned logger + * + * Is logger of ike_sa! + */ + logger_t *logger; + + + /** + * Process NONCE payload of IKE_SA_INIT response. + * + * @param this calling object + * @param nonce_payload NONCE payload to process + * @return SUCCESS in any case + */ + status_t (*process_nonce_payload) (private_ike_sa_init_requested_t *this, nonce_payload_t *nonce_payload); + + /** + * Process SA payload of IKE_SA_INIT response. + * + * @param this calling object + * @param sa_payload SA payload to process + * @return + * - SUCCESS + * - FAILED + */ + status_t (*process_sa_payload) (private_ike_sa_init_requested_t *this, sa_payload_t *sa_payload); + + /** + * Process KE payload of IKE_SA_INIT response. + * + * @param this calling object + * @param sa_payload KE payload to process + * @return + * - SUCCESS + * - FAILED + */ + status_t (*process_ke_payload) (private_ike_sa_init_requested_t *this, ke_payload_t *ke_payload); + + /** + * Build ID payload for IKE_AUTH request. + * + * @param this calling object + * @param[out] id_payload buildet ID payload + * @param response created payload will be added to this message_t object + * @return + * - SUCCESS + * - FAILED + */ + status_t (*build_id_payload) (private_ike_sa_init_requested_t *this,id_payload_t **id_payload, message_t *response); + + /** + * Build IDr payload for IKE_AUTH request. + * + * Only built when the ID of the responder contains no wildcards. + * + * @param this calling object + * @param response created payload will be added to this message_t object + * @return + * - SUCCESS + * - FAILED + */ + status_t (*build_idr_payload) (private_ike_sa_init_requested_t *this, message_t *response); + + /** + * Build AUTH payload for IKE_AUTH request. + * + * @param this calling object + * @param my_id_payload buildet ID payload + * @param response created payload will be added to this message_t object + * @return + * - SUCCESS + * - FAILED + */ + status_t (*build_auth_payload) (private_ike_sa_init_requested_t *this,id_payload_t *my_id_payload, message_t *response); + + /** + * Build SA payload for IKE_AUTH request. + * + * @param this calling object + * @param response created payload will be added to this message_t object + * @return + * - SUCCESS + * - FAILED + */ + status_t (*build_sa_payload) (private_ike_sa_init_requested_t *this, message_t *response); + + /** + * Build TSi payload for IKE_AUTH request. + * + * @param this calling object + * @param response created payload will be added to this message_t object + * @return + * - SUCCESS + * - FAILED + */ + status_t (*build_tsi_payload) (private_ike_sa_init_requested_t *this, message_t *response); + + /** + * Build TSr payload for IKE_AUTH request. + * + * @param this calling object + * @param response created payload will be added to this message_t object + * @return + * - SUCCESS + * - FAILED + */ + status_t (*build_tsr_payload) (private_ike_sa_init_requested_t *this, message_t *response); + + /** + * Process a notify payload and react. + * + * @param this calling object + * @param notify_payload notify_payload to handle + */ + status_t (*process_notify_payload) (private_ike_sa_init_requested_t *this, notify_payload_t *notify_payload); + + /** + * Destroy function called internally of this class after state change to + * state IKE_AUTH_REQUESTED succeeded. + * + * This destroy function does not destroy objects which were passed to the new state. + * + * @param this calling object + */ + void (*destroy_after_state_change) (private_ike_sa_init_requested_t *this); +}; + +/** + * Implementation of state_t.process_message. + */ +static status_t process_message(private_ike_sa_init_requested_t *this, message_t *ike_sa_init_reply) +{ + ike_auth_requested_t *next_state; + chunk_t ike_sa_init_reply_data; + sa_payload_t *sa_payload = NULL; + ke_payload_t *ke_payload = NULL; + id_payload_t *id_payload = NULL; + nonce_payload_t *nonce_payload = NULL; + u_int64_t responder_spi; + ike_sa_id_t *ike_sa_id; + iterator_t *payloads; + host_t *me; + connection_t *connection; + policy_t *policy; + + message_t *request; + status_t status; + + /* + * In this state a reply message of type IKE_SA_INIT is expected: + * + * <-- HDR, SAr1, KEr, Nr, [CERTREQ] + * or + * <-- HDR, N + */ + + if (ike_sa_init_reply->get_exchange_type(ike_sa_init_reply) != IKE_SA_INIT) + { + this->logger->log(this->logger, ERROR | LEVEL1, "Message of type %s not supported in state ike_sa_init_requested", + mapping_find(exchange_type_m,ike_sa_init_reply->get_exchange_type(ike_sa_init_reply))); + return FAILED; + } + + if (ike_sa_init_reply->get_request(ike_sa_init_reply)) + { + this->logger->log(this->logger, ERROR | LEVEL1, "IKE_SA_INIT requests not allowed state ike_sa_init_responded"); + return FAILED; + } + + /* parse incoming message */ + status = ike_sa_init_reply->parse_body(ike_sa_init_reply, NULL, NULL); + if (status != SUCCESS) + { + this->logger->log(this->logger, ERROR | LEVEL1, "IKE_SA_INIT reply parsing faild. Ignoring message"); + return status; + } + + /* because we are original initiator we have to update the responder SPI to the new one */ + responder_spi = ike_sa_init_reply->get_responder_spi(ike_sa_init_reply); + if (responder_spi == 0) + { + this->logger->log(this->logger, ERROR | LEVEL1, "IKE_SA_INIT reply contained a SPI of zero"); + return FAILED; + } + ike_sa_id = this->ike_sa->public.get_id(&(this->ike_sa->public)); + ike_sa_id->set_responder_spi(ike_sa_id,responder_spi); + + /* Iterate over all payloads. + * + * The message is allready checked for the right payload types. + */ + payloads = ike_sa_init_reply->get_payload_iterator(ike_sa_init_reply); + while (payloads->has_next(payloads)) + { + payload_t *payload; + payloads->current(payloads, (void**)&payload); + + switch (payload->get_type(payload)) + { + case SECURITY_ASSOCIATION: + { + sa_payload = (sa_payload_t*)payload; + break; + } + case KEY_EXCHANGE: + { + ke_payload = (ke_payload_t*)payload; + break; + } + case NONCE: + { + nonce_payload = (nonce_payload_t*)payload; + break; + } + case NOTIFY: + { + notify_payload_t *notify_payload = (notify_payload_t *) payload; + + status = this->process_notify_payload(this, notify_payload); + if (status != SUCCESS) + { + payloads->destroy(payloads); + return status; + } + break; + } + default: + { + this->logger->log(this->logger, ERROR|LEVEL1, "Ignoring payload %s (%d)", + mapping_find(payload_type_m, payload->get_type(payload)), payload->get_type(payload)); + break; + } + + } + + } + payloads->destroy(payloads); + + if (!(nonce_payload && sa_payload && ke_payload)) + { + this->logger->log(this->logger, AUDIT, "IKE_SA_INIT reply did not contain all required payloads. Deleting IKE_SA"); + return DELETE_ME; + } + + status = this->process_nonce_payload (this,nonce_payload); + if (status != SUCCESS) + { + return status; + } + + status = this->process_sa_payload (this,sa_payload); + if (status != SUCCESS) + { + return status; + } + + status = this->process_ke_payload (this,ke_payload); + if (status != SUCCESS) + { + return status; + } + + /* derive all the keys used in the IKE_SA */ + status = this->ike_sa->build_transforms(this->ike_sa, this->proposal, this->diffie_hellman, this->sent_nonce, this->received_nonce); + if (status != SUCCESS) + { + this->logger->log(this->logger, AUDIT, "Transform objects could not be created from selected proposal. Deleting IKE_SA"); + return DELETE_ME; + } + + /* apply the address on wich we really received the packet */ + connection = this->ike_sa->get_connection(this->ike_sa); + me = ike_sa_init_reply->get_destination(ike_sa_init_reply); + connection->update_my_host(connection, me->clone(me)); + policy = this->ike_sa->get_policy(this->ike_sa); + policy->update_my_ts(policy, me); + + /* build empty message */ + this->ike_sa->build_message(this->ike_sa, IKE_AUTH, TRUE, &request); + + status = this->build_id_payload(this, &id_payload, request); + if (status != SUCCESS) + { + request->destroy(request); + return status; + } + status = this->build_idr_payload(this, request); + if (status != SUCCESS) + { + request->destroy(request); + return status; + } + status = this->build_auth_payload(this, (id_payload_t*)id_payload, request); + if (status != SUCCESS) + { + request->destroy(request); + return status; + } + status = this->build_sa_payload(this, request); + if (status != SUCCESS) + { + request->destroy(request); + return status; + } + status = this->build_tsi_payload(this, request); + if (status != SUCCESS) + { + request->destroy(request); + return status; + } + status = this->build_tsr_payload(this, request); + if (status != SUCCESS) + { + request->destroy(request); + return status; + } + + /* message can now be sent (must not be destroyed) */ + status = this->ike_sa->send_request(this->ike_sa, request); + if (status != SUCCESS) + { + this->logger->log(this->logger, AUDIT, "Unable to send IKE_AUTH request. Deleting IKE_SA"); + request->destroy(request); + return DELETE_ME; + } + + this->ike_sa->set_last_replied_message_id(this->ike_sa,ike_sa_init_reply->get_message_id(ike_sa_init_reply)); + + ike_sa_init_reply_data = ike_sa_init_reply->get_packet_data(ike_sa_init_reply); + + /* state can now be changed */ + next_state = ike_auth_requested_create(this->ike_sa, this->sent_nonce, this->received_nonce, + ike_sa_init_reply_data, this->child_sa); + this->ike_sa->set_new_state(this->ike_sa,(state_t *) next_state); + + this->destroy_after_state_change(this); + return SUCCESS; +} + + +/** + * Implementation of private_ike_sa_init_requested_t.process_nonce_payload. + */ +status_t process_nonce_payload (private_ike_sa_init_requested_t *this, nonce_payload_t *nonce_payload) +{ + free(this->received_nonce.ptr); + this->received_nonce = nonce_payload->get_nonce(nonce_payload); + return SUCCESS; +} + + +/** + * Implementation of private_ike_sa_init_requested_t.process_sa_payload. + */ +status_t process_sa_payload (private_ike_sa_init_requested_t *this, sa_payload_t *sa_payload) +{ + proposal_t *proposal; + linked_list_t *proposal_list; + connection_t *connection; + + connection = this->ike_sa->get_connection(this->ike_sa); + + /* get the list of selected proposals, the peer has to select only one proposal */ + proposal_list = sa_payload->get_proposals (sa_payload); + if (proposal_list->get_count(proposal_list) != 1) + { + this->logger->log(this->logger, AUDIT, "IKE_SA_INIT response did not contain a single proposal. Deleting IKE_SA"); + while (proposal_list->remove_last(proposal_list, (void**)&proposal) == SUCCESS) + { + proposal->destroy(proposal); + } + proposal_list->destroy(proposal_list); + return DELETE_ME; + } + + /* we have to re-check if the others selection is valid */ + this->proposal = connection->select_proposal(connection, proposal_list); + while (proposal_list->remove_last(proposal_list, (void**)&proposal) == SUCCESS) + { + proposal->destroy(proposal); + } + proposal_list->destroy(proposal_list); + + if (this->proposal == NULL) + { + this->logger->log(this->logger, AUDIT, "IKE_SA_INIT response contained selected proposal we did not offer. Deleting IKE_SA"); + return DELETE_ME; + } + + return SUCCESS; +} + +/** + * Implementation of private_ike_sa_init_requested_t.process_ke_payload. + */ +status_t process_ke_payload (private_ike_sa_init_requested_t *this, ke_payload_t *ke_payload) +{ + this->diffie_hellman->set_other_public_value(this->diffie_hellman, ke_payload->get_key_exchange_data(ke_payload)); + + return SUCCESS; +} + +/** + * Implementation of private_ike_sa_init_requested_t.build_id_payload. + */ +static status_t build_id_payload (private_ike_sa_init_requested_t *this,id_payload_t **id_payload, message_t *request) +{ + policy_t *policy; + id_payload_t *new_id_payload; + identification_t *identification; + + policy = this->ike_sa->get_policy(this->ike_sa); + identification = policy->get_my_id(policy); + new_id_payload = id_payload_create_from_identification(TRUE, identification); + + this->logger->log(this->logger, CONTROL|LEVEL2, "Add ID payload to message"); + request->add_payload(request,(payload_t *) new_id_payload); + + *id_payload = new_id_payload; + + return SUCCESS; +} + +/** + * Implementation of private_ike_sa_init_requested_t.build_idr_payload. + */ +static status_t build_idr_payload (private_ike_sa_init_requested_t *this, message_t *request) +{ + policy_t *policy; + id_payload_t *idr_payload; + identification_t *identification; + + policy = this->ike_sa->get_policy(this->ike_sa); + identification = policy->get_other_id(policy); + if (!identification->contains_wildcards(identification)) + { + idr_payload = id_payload_create_from_identification(FALSE, identification); + + this->logger->log(this->logger, CONTROL|LEVEL2, "Add IDr payload to message"); + request->add_payload(request,(payload_t *) idr_payload); + } + return SUCCESS; +} + +/** + * Implementation of private_ike_sa_init_requested_t.build_auth_payload. + */ +static status_t build_auth_payload (private_ike_sa_init_requested_t *this, id_payload_t *my_id_payload, message_t *request) +{ + authenticator_t *authenticator; + auth_payload_t *auth_payload; + status_t status; + + authenticator = authenticator_create(this->ike_sa); + status = authenticator->compute_auth_data(authenticator,&auth_payload,this->ike_sa_init_request_data,this->received_nonce,my_id_payload,TRUE); + authenticator->destroy(authenticator); + + if (status != SUCCESS) + { + this->logger->log(this->logger, AUDIT, "Could not generate AUTH data for IKE_AUTH request. Deleting IKE_SA"); + return DELETE_ME; + } + + this->logger->log(this->logger, CONTROL|LEVEL2, "Add AUTH payload to message"); + request->add_payload(request,(payload_t *) auth_payload); + + return SUCCESS; +} + +/** + * Implementation of private_ike_sa_init_requested_t.build_sa_payload. + */ +static status_t build_sa_payload (private_ike_sa_init_requested_t *this, message_t *request) +{ + linked_list_t *proposal_list; + sa_payload_t *sa_payload; + policy_t *policy; + connection_t *connection; + + /* get proposals form config, add to payload */ + policy = this->ike_sa->get_policy(this->ike_sa); + proposal_list = policy->get_proposals(policy); + /* build child sa */ + connection = this->ike_sa->get_connection(this->ike_sa); + this->child_sa = child_sa_create(connection->get_my_host(connection), + connection->get_other_host(connection)); + if (this->child_sa->alloc(this->child_sa, proposal_list) != SUCCESS) + { + this->logger->log(this->logger, AUDIT, "Could not install CHILD_SA! Deleting IKE_SA"); + return DELETE_ME; + } + + sa_payload = sa_payload_create_from_proposal_list(proposal_list); + + this->logger->log(this->logger, CONTROL|LEVEL2, "Add SA payload to message"); + request->add_payload(request,(payload_t *) sa_payload); + + return SUCCESS; +} + +/** + * Implementation of private_ike_sa_init_requested_t.build_tsi_payload. + */ +static status_t build_tsi_payload (private_ike_sa_init_requested_t *this, message_t *request) +{ + linked_list_t *ts_list; + ts_payload_t *ts_payload; + policy_t *policy; + + policy = this->ike_sa->get_policy(this->ike_sa); + ts_list = policy->get_my_traffic_selectors(policy); + ts_payload = ts_payload_create_from_traffic_selectors(TRUE, ts_list); + + this->logger->log(this->logger, CONTROL|LEVEL2, "Add TSi payload to message"); + request->add_payload(request,(payload_t *) ts_payload); + + return SUCCESS; +} + +/** + * Implementation of private_ike_sa_init_requested_t.build_tsr_payload. + */ +static status_t build_tsr_payload (private_ike_sa_init_requested_t *this, message_t *request) +{ + linked_list_t *ts_list; + ts_payload_t *ts_payload; + policy_t *policy; + + policy = this->ike_sa->get_policy(this->ike_sa); + ts_list = policy->get_other_traffic_selectors(policy); + ts_payload = ts_payload_create_from_traffic_selectors(FALSE, ts_list); + + this->logger->log(this->logger, CONTROL|LEVEL2, "Add TSr payload to message"); + request->add_payload(request,(payload_t *) ts_payload); + + return SUCCESS; +} + +/** + * Implementation of private_ike_sa_init_requested_t.process_notify_payload. + */ +static status_t process_notify_payload(private_ike_sa_init_requested_t *this, notify_payload_t *notify_payload) +{ + notify_message_type_t notify_message_type = notify_payload->get_notify_message_type(notify_payload); + + this->logger->log(this->logger, CONTROL|LEVEL1, "Process notify type %s", + mapping_find(notify_message_type_m, notify_message_type)); + + switch (notify_message_type) + { + case NO_PROPOSAL_CHOSEN: + { + this->logger->log(this->logger, AUDIT, "IKE_SA_INIT response contained a NO_PROPOSAL_CHOSEN notify. Deleting IKE_SA"); + return DELETE_ME; + } + case INVALID_MAJOR_VERSION: + { + this->logger->log(this->logger, AUDIT, "IKE_SA_INIT response contained a INVALID_MAJOR_VERSION notify. Deleting IKE_SA"); + return DELETE_ME; + } + case INVALID_KE_PAYLOAD: + { + initiator_init_t *initiator_init_state; + chunk_t notify_data; + diffie_hellman_group_t dh_group, old_dh_group; + connection_t *connection; + + connection = this->ike_sa->get_connection(this->ike_sa); + old_dh_group = connection->get_dh_group(connection); + notify_data = notify_payload->get_notification_data(notify_payload); + dh_group = ntohs(*((u_int16_t*)notify_data.ptr)); + + /* TODO: + * We are very restrictive here: If the other didn't accept + * our DH group, and we do not accept his offer, continuation + * is cancelled... + */ + + this->logger->log(this->logger, AUDIT, "Peer didn't accept %s, it requested %s!", + mapping_find(diffie_hellman_group_m, old_dh_group), + mapping_find(diffie_hellman_group_m, dh_group)); + /* check if we can accept this dh group */ + if (!connection->check_dh_group(connection, dh_group)) + { + this->logger->log(this->logger, AUDIT, + "Peer does only accept DH group %s, which we do not accept! Aborting", + mapping_find(diffie_hellman_group_m, dh_group)); + return DELETE_ME; + } + + /* Going to change state back to initiator_init_t */ + this->logger->log(this->logger, CONTROL|LEVEL2, "Create next state object"); + initiator_init_state = initiator_init_create(this->ike_sa); + + /* buffer of sent and received messages has to get reseted */ + this->ike_sa->reset_message_buffers(this->ike_sa); + + /* state can now be changed */ + this->ike_sa->set_new_state(this->ike_sa,(state_t *) initiator_init_state); + + /* state has NOW changed :-) */ + this->logger->log(this->logger, CONTROL|LEVEL2, "Destroy old sate object"); + this->logger->log(this->logger, CONTROL|LEVEL2, "Going to retry initialization of connection"); + + this->public.state_interface.destroy(&(this->public.state_interface)); + if (initiator_init_state->retry_initiate_connection (initiator_init_state, dh_group) != SUCCESS) + { + return DELETE_ME; + } + return FAILED; + } + default: + { + /* + * - In case of unknown error: IKE_SA gets destroyed. + * - In case of unknown status: logging + */ + if (notify_message_type < 16383) + { + this->logger->log(this->logger, AUDIT, "IKE_SA_INIT reply contained an unknown notify error (%d). Deleting IKE_SA", + notify_message_type); + return DELETE_ME; + } + else + { + this->logger->log(this->logger, CONTROL, "IKE_SA_INIT reply contained an unknown notify (%d), ignored.", + notify_message_type); + return SUCCESS; + } + } + } +} + +/** + * Implementation of state_t.get_state. + */ +static ike_sa_state_t get_state(private_ike_sa_init_requested_t *this) +{ + return IKE_SA_INIT_REQUESTED; +} + +/** + * Implementation of private_ike_sa_init_requested_t.destroy_after_state_change. + */ +static void destroy_after_state_change (private_ike_sa_init_requested_t *this) +{ + this->diffie_hellman->destroy(this->diffie_hellman); + chunk_free(&(this->ike_sa_init_request_data)); + if (this->proposal) + { + this->proposal->destroy(this->proposal); + } + free(this); +} + +/** + * Implementation state_t.destroy. + */ +static void destroy(private_ike_sa_init_requested_t *this) +{ + this->diffie_hellman->destroy(this->diffie_hellman); + free(this->sent_nonce.ptr); + free(this->received_nonce.ptr); + chunk_free(&(this->ike_sa_init_request_data)); + if (this->child_sa) + { + this->child_sa->destroy(this->child_sa); + } + if (this->proposal) + { + this->proposal->destroy(this->proposal); + } + free(this); +} + +/* + * Described in header. + */ +ike_sa_init_requested_t *ike_sa_init_requested_create(protected_ike_sa_t *ike_sa, diffie_hellman_t *diffie_hellman, chunk_t sent_nonce,chunk_t ike_sa_init_request_data) +{ + private_ike_sa_init_requested_t *this = malloc_thing(private_ike_sa_init_requested_t); + + /* interface functions */ + this->public.state_interface.process_message = (status_t (*) (state_t *,message_t *)) process_message; + this->public.state_interface.get_state = (ike_sa_state_t (*) (state_t *)) get_state; + this->public.state_interface.destroy = (void (*) (state_t *)) destroy; + + /* private functions */ + this->destroy_after_state_change = destroy_after_state_change; + this->process_nonce_payload = process_nonce_payload; + this->process_sa_payload = process_sa_payload; + this->process_ke_payload = process_ke_payload; + this->build_auth_payload = build_auth_payload; + this->build_tsi_payload = build_tsi_payload; + this->build_tsr_payload = build_tsr_payload; + this->build_id_payload = build_id_payload; + this->build_idr_payload = build_idr_payload; + this->build_sa_payload = build_sa_payload; + this->process_notify_payload = process_notify_payload; + + /* private data */ + this->ike_sa = ike_sa; + this->received_nonce = CHUNK_INITIALIZER; + this->logger = logger_manager->get_logger(logger_manager, IKE_SA); + this->diffie_hellman = diffie_hellman; + this->proposal = NULL; + this->sent_nonce = sent_nonce; + this->child_sa = NULL; + this->ike_sa_init_request_data = ike_sa_init_request_data; + + return &(this->public); +} diff --git a/src/charon/sa/states/ike_sa_init_requested.h b/src/charon/sa/states/ike_sa_init_requested.h new file mode 100644 index 000000000..0a43afad1 --- /dev/null +++ b/src/charon/sa/states/ike_sa_init_requested.h @@ -0,0 +1,68 @@ +/** + * @file ike_sa_init_requested.h + * + * @brief Interface of ike_sa_init_requestet_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + + +#ifndef IKE_SA_INIT_REQUESTED_H_ +#define IKE_SA_INIT_REQUESTED_H_ + +#include +#include +#include +#include + +typedef struct ike_sa_init_requested_t ike_sa_init_requested_t; + +/** + * @brief This class represents an IKE_SA state when + * requested an IKE_SA_INIT as initiator. + * + * @b Constructors: + * - ike_sa_init_requested_create() + * + * @todo Include valid child sa SPIs in proposal + * + * @ingroup states + */ +struct ike_sa_init_requested_t { + /** + * The state_t interface. + */ + state_t state_interface; +}; + +/** + * Constructor of class ike_sa_init_requested_t. + * + * @param ike_sa assigned ike_sa + * @param diffie_hellman diffie_hellman object use to retrieve shared secret + * @param sent_nonce Sent nonce value + * @param ike_sa_init_request_data the binary representation of the IKE_SA_INIT request message + * @return created ike_sa_init_request_t object + * + * @ingroup states + */ +ike_sa_init_requested_t *ike_sa_init_requested_create(protected_ike_sa_t *ike_sa, + diffie_hellman_t *diffie_hellman, + chunk_t sent_nonce, + chunk_t ike_sa_init_request_data); + +#endif /*IKE_SA_INIT_REQUESTED_H_*/ diff --git a/src/charon/sa/states/ike_sa_init_responded.c b/src/charon/sa/states/ike_sa_init_responded.c new file mode 100644 index 000000000..e40b0cf22 --- /dev/null +++ b/src/charon/sa/states/ike_sa_init_responded.c @@ -0,0 +1,695 @@ +/** + * @file ike_sa_init_responded.c + * + * @brief State of a IKE_SA after responding to an IKE_SA_INIT request + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 + +#include "ike_sa_init_responded.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +typedef struct private_ike_sa_init_responded_t private_ike_sa_init_responded_t; + +/** + * Private data of a ike_sa_init_responded_t object. + * + */ +struct private_ike_sa_init_responded_t { + /** + * Public interface of ike_sa_init_responded_t. + */ + ike_sa_init_responded_t public; + + /** + * Assigned IKE_SA. + */ + protected_ike_sa_t *ike_sa; + + /** + * Received nonce. + */ + chunk_t received_nonce; + + /** + * Sent nonce. + */ + chunk_t sent_nonce; + + /** + * Binary representation of the IKE_SA_INIT response. + */ + chunk_t ike_sa_init_response_data; + + /** + * Binary representation of the IKE_SA_INIT request. + */ + chunk_t ike_sa_init_request_data; + + /** + * SA config to use. + */ + policy_t *policy; + + /** + * CHILD_SA, if set up + */ + child_sa_t *child_sa; + + /** + * Traffic selectors applicable at our site + */ + linked_list_t *my_ts; + + /** + * Traffic selectors applicable at remote site + */ + linked_list_t *other_ts; + + /** + * Assigned logger. + * + * Is logger of ike_sa! + */ + logger_t *logger; + + /** + * Process received IDi and IDr payload and build IDr payload for IKE_AUTH response. + * + * @param this calling object + * @param request_idi ID payload representing initiator + * @param request_idr ID payload representing responder (May be zero) + * @param response The created IDr payload is added to this message_t object + * @param response_idr The created IDr payload is also written to this location + */ + status_t (*build_idr_payload) (private_ike_sa_init_responded_t *this, + id_payload_t *request_idi, + id_payload_t *request_idr, + message_t *response, + id_payload_t **response_idr); + + /** + * Process received SA payload and build SA payload for IKE_AUTH response. + * + * @param this calling object + * @param request SA payload received in IKE_AUTH request + * @param response The created SA payload is added to this message_t object + */ + status_t (*build_sa_payload) (private_ike_sa_init_responded_t *this, sa_payload_t *request, message_t *response); + + /** + * Process received AUTH payload and build AUTH payload for IKE_AUTH response. + * + * @param this calling object + * @param request AUTH payload received in IKE_AUTH request + * @param other_id_payload other ID payload needed to verify AUTH data + * @param my_id_payload my ID payload needed to compute AUTH data + * @param response The created AUTH payload is added to this message_t object + */ + status_t (*build_auth_payload) (private_ike_sa_init_responded_t *this, auth_payload_t *request,id_payload_t *other_id_payload,id_payload_t *my_id_payload, message_t* response); + + /** + * Process received TS payload and build TS payload for IKE_AUTH response. + * + * @param this calling object + * @param is_initiator type of TS payload. TRUE for TSi, FALSE for TSr + * @param request TS payload received in IKE_AUTH request + * @param response the created TS payload is added to this message_t object + */ + status_t (*build_ts_payload) (private_ike_sa_init_responded_t *this, bool ts_initiator, ts_payload_t *request, message_t *response); + + /** + * Sends a IKE_AUTH reply containing a notify payload. + * + * @param this calling object + * @param notify_payload payload to process + * @return + * - DELETE_ME if IKE_SA should be deleted + * - SUCCSS if processed successfull + */ + status_t (*process_notify_payload) (private_ike_sa_init_responded_t *this, notify_payload_t* notify_payload); + + /** + * Destroy function called internally of this class after state change to + * state IKE_SA_ESTABLISHED succeeded. + * + * This destroy function does not destroy objects which were passed to the new state. + * + * @param this calling object + */ + void (*destroy_after_state_change) (private_ike_sa_init_responded_t *this); +}; + +/** + * Implements state_t.get_state + */ +static status_t process_message(private_ike_sa_init_responded_t *this, message_t *request) +{ + id_payload_t *idi_request = NULL, *idr_request = NULL,*idr_response; + ts_payload_t *tsi_request = NULL, *tsr_request = NULL; + auth_payload_t *auth_request = NULL; + sa_payload_t *sa_request = NULL; + iterator_t *payloads; + message_t *response; + crypter_t *crypter; + signer_t *signer; + status_t status; + host_t *my_host, *other_host; + connection_t *connection; + + if (request->get_exchange_type(request) != IKE_AUTH) + { + this->logger->log(this->logger, ERROR | LEVEL1, "Message of type %s not supported in state ike_sa_init_responded", + mapping_find(exchange_type_m,request->get_exchange_type(request))); + return FAILED; + } + + if (!request->get_request(request)) + { + this->logger->log(this->logger, ERROR | LEVEL1, "IKE_AUTH responses not allowed state ike_sa_init_responded"); + return FAILED; + } + + /* get signer for verification and crypter for decryption */ + signer = this->ike_sa->get_signer_initiator(this->ike_sa); + crypter = this->ike_sa->get_crypter_initiator(this->ike_sa); + + status = request->parse_body(request, crypter, signer); + if (status != SUCCESS) + { + if (status == NOT_SUPPORTED) + { + this->logger->log(this->logger, ERROR | LEVEL1, "IKE_AUTH request contains unsupported payload with critical flag set." + "Deleting IKE_SA"); + this->ike_sa->send_notify(this->ike_sa, IKE_AUTH, UNSUPPORTED_CRITICAL_PAYLOAD, CHUNK_INITIALIZER); + return DELETE_ME; + } + else + { + this->logger->log(this->logger, AUDIT, "IKE_AUTH request decryption faild. Ignoring message"); + } + return status; + } + + /* iterate over incoming payloads. Message is verified, we can be sure there are the required payloads */ + payloads = request->get_payload_iterator(request); + while (payloads->has_next(payloads)) + { + payload_t *payload; + payloads->current(payloads, (void**)&payload); + + switch (payload->get_type(payload)) + { + case ID_INITIATOR: + { + idi_request = (id_payload_t*)payload; + break; + } + case AUTHENTICATION: + { + auth_request = (auth_payload_t*)payload; + break; + } + case ID_RESPONDER: + { + idr_request = (id_payload_t*)payload; + break; + } + case SECURITY_ASSOCIATION: + { + sa_request = (sa_payload_t*)payload; + break; + } + case TRAFFIC_SELECTOR_INITIATOR: + { + tsi_request = (ts_payload_t*)payload; + break; + } + case TRAFFIC_SELECTOR_RESPONDER: + { + tsr_request = (ts_payload_t*)payload; + break; + } + case NOTIFY: + { + notify_payload_t *notify_payload = (notify_payload_t *) payload; + status = this->process_notify_payload(this, notify_payload); + if (status != SUCCESS) + { + payloads->destroy(payloads); + return status; + } + } + case CERTIFICATE: + { + /* TODO handle cert payloads */ + } + case CERTIFICATE_REQUEST: + { + /* TODO handle certrequest payloads */ + } + default: + { + this->logger->log(this->logger, ERROR|LEVEL1, "Ignoring payload %s (%d)", + mapping_find(payload_type_m, payload->get_type(payload)), payload->get_type(payload)); + break; + } + } + } + /* iterator can be destroyed */ + payloads->destroy(payloads); + + /* check if we have all payloads */ + if (!(idi_request && sa_request && auth_request && tsi_request && tsr_request)) + { + this->logger->log(this->logger, AUDIT, "IKE_AUTH reply did not contain all required payloads. Deleting IKE_SA"); + return DELETE_ME; + } + + /* build response */ + this->ike_sa->build_message(this->ike_sa, IKE_AUTH, FALSE, &response); + + /* add payloads to it */ + status = this->build_idr_payload(this, idi_request, idr_request, response,&idr_response); + if (status != SUCCESS) + { + response->destroy(response); + return status; + } + status = this->build_auth_payload(this, auth_request,idi_request, idr_response,response); + if (status != SUCCESS) + { + response->destroy(response); + return status; + } + status = this->build_sa_payload(this, sa_request, response); + if (status != SUCCESS) + { + response->destroy(response); + return status; + } + status = this->build_ts_payload(this, TRUE, tsi_request, response); + if (status != SUCCESS) + { + response->destroy(response); + return status; + } + status = this->build_ts_payload(this, FALSE, tsr_request, response); + if (status != SUCCESS) + { + response->destroy(response); + return status; + } + + status = this->ike_sa->send_response(this->ike_sa, response); + /* message can now be sent (must not be destroyed) */ + if (status != SUCCESS) + { + this->logger->log(this->logger, AUDIT, "Unable to send IKE_AUTH reply. Deleting IKE_SA"); + response->destroy(response); + return DELETE_ME; + } + + /* install child SA policies */ + if (!this->child_sa) + { + this->logger->log(this->logger, CONTROL, "Proposal negotiation failed, no CHILD_SA built"); + } + else if (this->my_ts->get_count(this->my_ts) == 0 || this->other_ts->get_count(this->other_ts) == 0) + { + this->logger->log(this->logger, CONTROL, "Traffic selector negotiation failed, no CHILD_SA built"); + this->child_sa->destroy(this->child_sa); + this->child_sa = NULL; + } + else + { + status = this->child_sa->add_policies(this->child_sa, this->my_ts, this->other_ts); + if (status != SUCCESS) + { + this->logger->log(this->logger, AUDIT, "Could not install CHILD_SA policy! Deleting IKE_SA"); + return DELETE_ME; + } + this->ike_sa->add_child_sa(this->ike_sa, this->child_sa); + } + + /* create new state */ + this->ike_sa->set_new_state(this->ike_sa, (state_t*)ike_sa_established_create(this->ike_sa)); + this->destroy_after_state_change(this); + + connection = this->ike_sa->get_connection(this->ike_sa); + my_host = connection->get_my_host(connection); + other_host = connection->get_other_host(connection); + this->logger->log(this->logger, AUDIT, "IKE_SA established between %s - %s", + my_host->get_address(my_host), other_host->get_address(other_host)); + + return SUCCESS; +} + +/** + * Implementation of private_ike_sa_init_responded_t.build_idr_payload. + */ +static status_t build_idr_payload(private_ike_sa_init_responded_t *this, id_payload_t *request_idi, id_payload_t *request_idr, message_t *response,id_payload_t **response_idr) +{ + identification_t *other_id, *my_id = NULL; + connection_t *connection; + id_payload_t *idr_response; + + connection = this->ike_sa->get_connection(this->ike_sa); + + /* update adresses, as connection may contain wildcards, or wrong IDs */ + other_id = request_idi->get_identification(request_idi); + if (request_idr) + { + my_id = request_idr->get_identification(request_idr); + connection->update_my_id(connection, my_id); + } + else + { + my_id = connection->get_my_id(connection); + } + connection->update_other_id(connection, other_id); + + /* build new sa config */ + this->policy = charon->policies->get_policy(charon->policies, my_id, other_id); + if (this->policy == NULL) + { + this->logger->log(this->logger, AUDIT, "We don't have a policy for IDs %s - %s. Deleting IKE_SA", + my_id->get_string(my_id), other_id->get_string(other_id)); + return DELETE_ME; + } + + /* get my id from policy, which must contain a fully qualified valid id */ + my_id = this->policy->get_my_id(this->policy); + + /* update others traffic selectors with actually used address */ + this->policy->update_other_ts(this->policy, response->get_destination(response)); + + /* set policy in ike_sa for other states */ + this->ike_sa->set_policy(this->ike_sa, this->policy); + + /* build response */ + idr_response = id_payload_create_from_identification(FALSE, my_id); + response->add_payload(response, (payload_t*)idr_response); + *response_idr = idr_response; + + return SUCCESS; +} + +/** + * Implementation of private_ike_sa_init_responded_t.build_sa_payload. + */ +static status_t build_sa_payload(private_ike_sa_init_responded_t *this, sa_payload_t *request, message_t *response) +{ + proposal_t *proposal, *proposal_tmp; + linked_list_t *proposal_list; + sa_payload_t *sa_response; + chunk_t seed; + prf_plus_t *prf_plus; + status_t status; + connection_t *connection; + + /* get proposals from request */ + proposal_list = request->get_proposals(request); + if (proposal_list->get_count(proposal_list) == 0) + { + /* if the other side did not offer any proposals, we do not create child sa's */ + this->logger->log(this->logger, AUDIT, "IKE_AUH request did not contain any proposals. No CHILD_SA created"); + sa_response = sa_payload_create(); + response->add_payload(response, (payload_t*)sa_response); + proposal_list->destroy(proposal_list); + return SUCCESS; + } + + /* now select a proposal */ + this->logger->log(this->logger, CONTROL|LEVEL1, "Selecting proposals:"); + proposal = this->policy->select_proposal(this->policy, proposal_list); + /* list is not needed anymore */ + while (proposal_list->remove_last(proposal_list, (void**)&proposal_tmp) == SUCCESS) + { + proposal_tmp->destroy(proposal_tmp); + } + proposal_list->destroy(proposal_list); + /* do we have a proposal */ + if (proposal == NULL) + { + this->logger->log(this->logger, AUDIT, "IKE_AUTH request did not contain any proposals we accept. Deleting IKE_SA"); + this->ike_sa->send_notify(this->ike_sa, IKE_AUTH, NO_PROPOSAL_CHOSEN, CHUNK_INITIALIZER); + return DELETE_ME; + } + + /* set up child sa */ + seed = chunk_alloc(this->received_nonce.len + this->sent_nonce.len); + memcpy(seed.ptr, this->received_nonce.ptr, this->received_nonce.len); + memcpy(seed.ptr + this->received_nonce.len, this->sent_nonce.ptr, this->sent_nonce.len); + prf_plus = prf_plus_create(this->ike_sa->get_child_prf(this->ike_sa), seed); + chunk_free(&seed); + + connection = this->ike_sa->get_connection(this->ike_sa); + this->child_sa = child_sa_create(connection->get_my_host(connection), + connection->get_other_host(connection)); + + status = this->child_sa->add(this->child_sa, proposal, prf_plus); + prf_plus->destroy(prf_plus); + if (status != SUCCESS) + { + this->logger->log(this->logger, AUDIT, "Could not install CHILD_SA! Deleting IKE_SA"); + return DELETE_ME; + } + + /* create payload with selected propsal */ + sa_response = sa_payload_create_from_proposal(proposal); + response->add_payload(response, (payload_t*)sa_response); + proposal->destroy(proposal); + return SUCCESS; +} + +/** + * Implementation of private_ike_sa_init_responded_t.build_auth_payload. + */ +static status_t build_auth_payload(private_ike_sa_init_responded_t *this, auth_payload_t *auth_request,id_payload_t *other_id_payload,id_payload_t *my_id_payload, message_t* response) +{ + authenticator_t *authenticator; + auth_payload_t *auth_reply; + status_t status; + + authenticator = authenticator_create(this->ike_sa); + status = authenticator->verify_auth_data(authenticator,auth_request, this->ike_sa_init_request_data,this->sent_nonce,other_id_payload,TRUE); + + if (status != SUCCESS) + { + this->logger->log(this->logger, AUDIT, "IKE_AUTH request verification failed. Deleting IKE_SA"); + this->ike_sa->send_notify(this->ike_sa, IKE_AUTH, AUTHENTICATION_FAILED, CHUNK_INITIALIZER); + authenticator->destroy(authenticator); + return DELETE_ME; + } + + status = authenticator->compute_auth_data(authenticator,&auth_reply, this->ike_sa_init_response_data,this->received_nonce,my_id_payload,FALSE); + authenticator->destroy(authenticator); + if (status != SUCCESS) + { + this->logger->log(this->logger, AUDIT, "Unable to build authentication data for IKE_AUTH reply. Deleting IKE_SA"); + return DELETE_ME; + + } + + response->add_payload(response, (payload_t *)auth_reply); + return SUCCESS; +} + +/** + * Implementation of private_ike_sa_init_responded_t.build_ts_payload. + */ +static status_t build_ts_payload(private_ike_sa_init_responded_t *this, bool ts_initiator, ts_payload_t *request, message_t* response) +{ + linked_list_t *ts_received, *ts_selected; + traffic_selector_t *ts; + status_t status = SUCCESS; + ts_payload_t *ts_response; + + /* build a reply payload with selected traffic selectors */ + ts_received = request->get_traffic_selectors(request); + /* select ts depending on payload type */ + if (ts_initiator) + { + ts_selected = this->policy->select_other_traffic_selectors(this->policy, ts_received); + this->other_ts = ts_selected; + } + else + { + ts_selected = this->policy->select_my_traffic_selectors(this->policy, ts_received); + this->my_ts = ts_selected; + } + + ts_response = ts_payload_create_from_traffic_selectors(ts_initiator, ts_selected); + response->add_payload(response, (payload_t*)ts_response); + + /* cleanup */ + while (ts_received->remove_last(ts_received, (void**)&ts) == SUCCESS) + { + ts->destroy(ts); + } + ts_received->destroy(ts_received); + + return status; +} + +static status_t process_notify_payload(private_ike_sa_init_responded_t *this, notify_payload_t *notify_payload) +{ + notify_message_type_t notify_message_type = notify_payload->get_notify_message_type(notify_payload); + + this->logger->log(this->logger, CONTROL|LEVEL1, "Process notify type %s", + mapping_find(notify_message_type_m, notify_message_type)); + + switch (notify_message_type) + { + case SET_WINDOW_SIZE: + /* + * TODO Increase window size. + */ + case INITIAL_CONTACT: + /* + * TODO Delete existing IKE_SA's with other Identity. + */ + default: + { + this->logger->log(this->logger, AUDIT, "IKE_AUTH request contained an unknown notify (%d), ignored.", notify_message_type); + } + } + + return SUCCESS; +} + +/** + * Implementation of state_t.get_state. + */ +static ike_sa_state_t get_state(private_ike_sa_init_responded_t *this) +{ + return IKE_SA_INIT_RESPONDED; +} + +/** + * Implementation of state_t.destroy. + */ +static void destroy(private_ike_sa_init_responded_t *this) +{ + chunk_free(&(this->received_nonce)); + chunk_free(&(this->sent_nonce)); + chunk_free(&(this->ike_sa_init_response_data)); + chunk_free(&(this->ike_sa_init_request_data)); + if (this->my_ts) + { + traffic_selector_t *ts; + while (this->my_ts->remove_last(this->my_ts, (void**)&ts) == SUCCESS) + { + ts->destroy(ts); + } + this->my_ts->destroy(this->my_ts); + } + if (this->other_ts) + { + traffic_selector_t *ts; + while (this->other_ts->remove_last(this->other_ts, (void**)&ts) == SUCCESS) + { + ts->destroy(ts); + } + this->other_ts->destroy(this->other_ts); + } + if (this->child_sa) + { + this->child_sa->destroy(this->child_sa); + } + + free(this); +} +/** + * Implementation of private_ike_sa_init_responded.destroy_after_state_change. + */ +static void destroy_after_state_change(private_ike_sa_init_responded_t *this) +{ + chunk_free(&(this->received_nonce)); + chunk_free(&(this->sent_nonce)); + chunk_free(&(this->ike_sa_init_response_data)); + chunk_free(&(this->ike_sa_init_request_data)); + if (this->my_ts) + { + traffic_selector_t *ts; + while (this->my_ts->remove_last(this->my_ts, (void**)&ts) == SUCCESS) + { + ts->destroy(ts); + } + this->my_ts->destroy(this->my_ts); + } + if (this->other_ts) + { + traffic_selector_t *ts; + while (this->other_ts->remove_last(this->other_ts, (void**)&ts) == SUCCESS) + { + ts->destroy(ts); + } + this->other_ts->destroy(this->other_ts); + } + + free(this); +} + +/* + * Described in header. + */ +ike_sa_init_responded_t *ike_sa_init_responded_create(protected_ike_sa_t *ike_sa, chunk_t received_nonce, chunk_t sent_nonce,chunk_t ike_sa_init_request_data, chunk_t ike_sa_init_response_data) +{ + private_ike_sa_init_responded_t *this = malloc_thing(private_ike_sa_init_responded_t); + + /* interface functions */ + this->public.state_interface.process_message = (status_t (*) (state_t *,message_t *)) process_message; + this->public.state_interface.get_state = (ike_sa_state_t (*) (state_t *)) get_state; + this->public.state_interface.destroy = (void (*) (state_t *)) destroy; + + /* private functions */ + this->build_idr_payload = build_idr_payload; + this->build_sa_payload = build_sa_payload; + this->build_auth_payload = build_auth_payload; + this->build_ts_payload = build_ts_payload; + this->process_notify_payload = process_notify_payload; + this->destroy_after_state_change = destroy_after_state_change; + + /* private data */ + this->ike_sa = ike_sa; + this->received_nonce = received_nonce; + this->sent_nonce = sent_nonce; + this->ike_sa_init_response_data = ike_sa_init_response_data; + this->ike_sa_init_request_data = ike_sa_init_request_data; + this->my_ts = NULL; + this->other_ts = NULL; + this->child_sa = NULL; + this->logger = logger_manager->get_logger(logger_manager, IKE_SA); + + return &(this->public); +} diff --git a/src/charon/sa/states/ike_sa_init_responded.h b/src/charon/sa/states/ike_sa_init_responded.h new file mode 100644 index 000000000..43aecf26f --- /dev/null +++ b/src/charon/sa/states/ike_sa_init_responded.h @@ -0,0 +1,73 @@ +/** + * @file ike_sa_init_responded.h + * + * @brief Interface of ike_sa_init_responded_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef IKE_SA_INIT_RESPONDED_H_ +#define IKE_SA_INIT_RESPONDED_H_ + +#include +#include + +typedef struct ike_sa_init_responded_t ike_sa_init_responded_t; + +/** + * @brief This class represents an IKE_SA state when + * responded to an IKE_SA_INIT request. + * + * The state accpets IKE_AUTH requests. It proves the authenticity + * and sets up the first child sa. Then it sends back an IKE_AUTH + * reply and changes to the IKE_SA_ESTABLISHED state. + * + * @b Constructors: + * - ike_sa_init_response_data() + * + * @todo Implement handling of SET_WINDOW_SIZE notify + * + * @todo Implement handling of INITIAL_CONTACT notify + * + * @ingroup states + */ +struct ike_sa_init_responded_t { + /** + * The state_t interface. + */ + state_t state_interface; + +}; + +/** + * @brief Constructor of class ike_sa_init_responded_t + * + * @param ike_sa assigned IKE_SA + * @param received_nonce received nonce data in IKE_SA_INIT request + * @param sent_nonce sent nonce data in IKE_SA_INIT response + * @param ike_sa_init_request_data binary representation of received IKE_SA_INIT request + * @param ike_sa_init_response_data binary representation of sent IKE_SA_INIT response + * + * @ingroup states + */ +ike_sa_init_responded_t *ike_sa_init_responded_create(protected_ike_sa_t *ike_sa, + chunk_t received_nonce, + chunk_t sent_nonce, + chunk_t ike_sa_init_request_data, + chunk_t ike_sa_init_response_data); + +#endif /*IKE_SA_INIT_RESPONDED_H_*/ diff --git a/src/charon/sa/states/initiator_init.c b/src/charon/sa/states/initiator_init.c new file mode 100644 index 000000000..35d15235d --- /dev/null +++ b/src/charon/sa/states/initiator_init.c @@ -0,0 +1,360 @@ +/** + * @file initiator_init.c + * + * @brief Implementation of initiator_init_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 "initiator_init.h" + + +#include +#include +#include +#include +#include +#include +#include +#include + + +typedef struct private_initiator_init_t private_initiator_init_t; + +/** + * Private data of a initiator_init_t object.. + * + */ +struct private_initiator_init_t { + /** + * Methods of the state_t interface. + */ + initiator_init_t public; + + /** + * Assigned IKE_SA. + */ + protected_ike_sa_t *ike_sa; + + /** + * Diffie hellman object used to generate public DH value. + * This objet is passed to the next state of type IKE_SA_INIT_REQUESTED. + */ + diffie_hellman_t *diffie_hellman; + + /** + * Sent nonce. + * This nonce is passed to the next state of type IKE_SA_INIT_REQUESTED. + */ + chunk_t sent_nonce; + + /** + * Assigned logger. + * + * Is logger of ike_sa! + */ + logger_t *logger; + + /** + * Builds the SA payload for this state. + * + * @param this calling object + * @param request message_t object to add the SA payload + */ + void (*build_sa_payload) (private_initiator_init_t *this, message_t *request); + + /** + * Builds the KE payload for this state. + * + * @param this calling object + * @param request message_t object to add the KE payload + */ + void (*build_ke_payload) (private_initiator_init_t *this, message_t *request); + + /** + * Builds the NONCE payload for this state. + * + * @param this calling object + * @param request message_t object to add the NONCE payload + */ + status_t (*build_nonce_payload) (private_initiator_init_t *this,message_t *request); + + /** + * Destroy function called internally of this class after state change to state + * IKE_SA_INIT_REQUESTED succeeded. + * + * This destroy function does not destroy objects which were passed to the new state. + * + * @param this calling object + */ + void (*destroy_after_state_change) (private_initiator_init_t *this); +}; + +/** + * Implementation of initiator_init_t.initiate_connection. + */ +static status_t initiate_connection (private_initiator_init_t *this, connection_t *connection) +{ + policy_t *policy; + diffie_hellman_group_t dh_group; + host_t *my_host, *other_host; + identification_t *my_id, *other_id; + + my_host = connection->get_my_host(connection); + other_host = connection->get_other_host(connection); + my_id = connection->get_my_id(connection); + other_id = connection->get_other_id(connection); + + this->logger->log(this->logger, CONTROL, "Initiating connection between %s (%s) - %s (%s)", + my_id->get_string(my_id), my_host->get_address(my_host), + other_id->get_string(other_id), other_host->get_address(other_host)); + + this->ike_sa->set_connection(this->ike_sa, connection); + + /* get policy */ + policy = charon->policies->get_policy(charon->policies, my_id, other_id); + if (policy == NULL) + { + this->logger->log(this->logger, ERROR | LEVEL1, "Could not get a policy for '%s - %s', aborting", + my_id->get_string(my_id), other_id->get_string(other_id)); + return DELETE_ME; + } + this->ike_sa->set_policy(this->ike_sa,policy); + + /* we must guess now a DH group. For that we choose our most preferred group */ + dh_group = connection->get_dh_group(connection); + + /* next step is done in retry_initiate_connection */ + return this->public.retry_initiate_connection(&this->public, dh_group); +} + +/** + * Implementation of initiator_init_t.retry_initiate_connection. + */ +status_t retry_initiate_connection (private_initiator_init_t *this, diffie_hellman_group_t dh_group) +{ + ike_sa_init_requested_t *next_state; + chunk_t ike_sa_init_request_data; + connection_t *connection; + ike_sa_id_t *ike_sa_id; + message_t *message; + status_t status; + + if (dh_group == MODP_UNDEFINED) + { + this->logger->log(this->logger, AUDIT, "No DH group acceptable for initialization, Aborting"); + return DELETE_ME; + } + + connection = this->ike_sa->get_connection(this->ike_sa); + this->diffie_hellman = diffie_hellman_create(dh_group); + ike_sa_id = this->ike_sa->public.get_id(&(this->ike_sa->public)); + ike_sa_id->set_responder_spi(ike_sa_id,0); + + /* going to build message */ + this->logger->log(this->logger, CONTROL|LEVEL2, "Going to build message"); + this->ike_sa->build_message(this->ike_sa, IKE_SA_INIT, TRUE, &message); + + /* build SA payload */ + this->build_sa_payload(this, message); + + /* build KE payload */ + this->build_ke_payload(this, message); + + /* build Nonce payload */ + status = this->build_nonce_payload(this, message); + if (status != SUCCESS) + { + this->logger->log(this->logger, ERROR, "Building nonce payload failed. Aborting"); + message->destroy(message); + return DELETE_ME; + } + + /* message can now be sent (must not be destroyed) */ + status = this->ike_sa->send_request(this->ike_sa, message); + if (status != SUCCESS) + { + this->logger->log(this->logger, AUDIT, "Unable to initiate connection, could not send message. Aborting"); + message->destroy(message); + return DELETE_ME; + } + + message = this->ike_sa->get_last_requested_message(this->ike_sa); + + ike_sa_init_request_data = message->get_packet_data(message); + + /* state can now be changed */ + this->logger->log(this->logger, CONTROL|LEVEL2, "Create next state object"); + next_state = ike_sa_init_requested_create(this->ike_sa, this->diffie_hellman, this->sent_nonce,ike_sa_init_request_data); + this->ike_sa->set_new_state(this->ike_sa,(state_t *) next_state); + + this->logger->log(this->logger, CONTROL|LEVEL2, "Destroy old sate object"); + this->destroy_after_state_change(this); + return SUCCESS; +} + +/** + * Implementation of private_initiator_init_t.build_sa_payload. + */ +static void build_sa_payload(private_initiator_init_t *this, message_t *request) +{ + sa_payload_t* sa_payload; + linked_list_t *proposal_list; + connection_t *connection; + + this->logger->log(this->logger, CONTROL|LEVEL1, "Building SA payload"); + + connection = this->ike_sa->get_connection(this->ike_sa); + + proposal_list = connection->get_proposals(connection); + + sa_payload = sa_payload_create_from_proposal_list(proposal_list); + + this->logger->log(this->logger, CONTROL|LEVEL2, "Add SA payload to message"); + request->add_payload(request, (payload_t *) sa_payload); +} + +/** + * Implementation of private_initiator_init_t.build_ke_payload. + */ +static void build_ke_payload(private_initiator_init_t *this, message_t *request) +{ + ke_payload_t *ke_payload; + chunk_t key_data; + diffie_hellman_group_t dh_group; + + this->logger->log(this->logger, CONTROL|LEVEL1, "Building KE payload"); + + this->diffie_hellman->get_my_public_value(this->diffie_hellman,&key_data); + dh_group = this->diffie_hellman->get_dh_group(this->diffie_hellman); + + ke_payload = ke_payload_create(); + ke_payload->set_dh_group_number(ke_payload, dh_group); + ke_payload->set_key_exchange_data(ke_payload, key_data); + + chunk_free(&key_data); + + this->logger->log(this->logger, CONTROL|LEVEL2, "Add KE payload to message"); + request->add_payload(request, (payload_t *) ke_payload); +} + +/** + * Implementation of private_initiator_init_t.build_nonce_payload. + */ +static status_t build_nonce_payload(private_initiator_init_t *this, message_t *request) +{ + nonce_payload_t *nonce_payload; + randomizer_t *randomizer; + status_t status; + + this->logger->log(this->logger, CONTROL|LEVEL1, "Building NONCE payload"); + + this->logger->log(this->logger, CONTROL|LEVEL2, "Get pseudo random bytes for NONCE"); + randomizer = this->ike_sa->get_randomizer(this->ike_sa); + + status = randomizer->allocate_pseudo_random_bytes(randomizer, NONCE_SIZE, &(this->sent_nonce)); + if (status != SUCCESS) + { + return status; + } + + this->logger->log(this->logger, RAW|LEVEL2, "Initiator NONCE",&(this->sent_nonce)); + + nonce_payload = nonce_payload_create(); + + nonce_payload->set_nonce(nonce_payload, this->sent_nonce); + + this->logger->log(this->logger, CONTROL|LEVEL2, "Add NONCE payload to message"); + request->add_payload(request, (payload_t *) nonce_payload); + return SUCCESS; +} + +/** + * Implementation of state_t.process_message. + */ +static status_t process_message(private_initiator_init_t *this, message_t *message) +{ + this->logger->log(this->logger, ERROR, "In state INITIATOR_INIT, no message is processed"); + return FAILED; +} + +/** + * Implementation of state_t.get_state. + */ +static ike_sa_state_t get_state(private_initiator_init_t *this) +{ + return INITIATOR_INIT; +} + +/** + * Implementation of state_t.destroy. + */ +static void destroy(private_initiator_init_t *this) +{ + this->logger->log(this->logger, CONTROL | LEVEL3, "Going to destroy initiator_init_t state object"); + + /* destroy diffie hellman object */ + if (this->diffie_hellman != NULL) + { + this->diffie_hellman->destroy(this->diffie_hellman); + } + if (this->sent_nonce.ptr != NULL) + { + free(this->sent_nonce.ptr); + } + free(this); +} + +/** + * Implementation of private_initiator_init_t.destroy_after_state_change + */ +static void destroy_after_state_change (private_initiator_init_t *this) +{ + this->logger->log(this->logger, CONTROL | LEVEL3, "Going to destroy initiator_init_t state object"); + free(this); +} + +/* + * Described in header. + */ +initiator_init_t *initiator_init_create(protected_ike_sa_t *ike_sa) +{ + private_initiator_init_t *this = malloc_thing(private_initiator_init_t); + + /* interface functions */ + this->public.state_interface.process_message = (status_t (*) (state_t *,message_t *)) process_message; + this->public.state_interface.get_state = (ike_sa_state_t (*) (state_t *)) get_state; + this->public.state_interface.destroy = (void (*) (state_t *)) destroy; + + /* public functions */ + this->public.initiate_connection = (status_t (*)(initiator_init_t *, connection_t*)) initiate_connection; + this->public.retry_initiate_connection = (status_t (*)(initiator_init_t *, int )) retry_initiate_connection; + + /* private functions */ + this->destroy_after_state_change = destroy_after_state_change; + this->build_nonce_payload = build_nonce_payload; + this->build_sa_payload = build_sa_payload; + this->build_ke_payload = build_ke_payload; + + /* private data */ + this->ike_sa = ike_sa; + this->logger = logger_manager->get_logger(logger_manager, IKE_SA); + this->sent_nonce = CHUNK_INITIALIZER; + this->diffie_hellman = NULL; + + return &(this->public); +} diff --git a/src/charon/sa/states/initiator_init.h b/src/charon/sa/states/initiator_init.h new file mode 100644 index 000000000..6b4940a73 --- /dev/null +++ b/src/charon/sa/states/initiator_init.h @@ -0,0 +1,84 @@ +/** + * @file initiator_init.h + * + * @brief Interface of initiator_init_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + + +#ifndef INITIATOR_INIT_H_ +#define INITIATOR_INIT_H_ + +#include +#include + + +typedef struct initiator_init_t initiator_init_t; + +/** + * @brief This class represents an IKE_SA state when + * initializing a connection as initiator. + * + * @b Constructors: + * - initiator_init_create() + * + * @ingroup states + */ +struct initiator_init_t { + /** + * The state_t interface. + */ + state_t state_interface; + + /** + * Initiate a new connection with given connection_t object. + * + * @param this calling object + * @param connection connection to initiate + * @return + * - SUCCESS + * - DELETE_ME if something failed + */ + status_t (*initiate_connection) (initiator_init_t *this, connection_t *connection); + + /** + * Retry to initiate a new connection with a specific dh_group_priority. + * + * The dh_group_priority is starting at 1. + * + * @param this calling object + * @param dh_group_priority dh group priority to try with + * @return + * - SUCCESS + * - DELETE_ME if something failed (see log for error) + */ + status_t (*retry_initiate_connection) (initiator_init_t *this, int dh_group_priority); +}; + +/** + * @brief Constructor of class initiator_init_t. + * + * @param ike_sa assigned IKE_SA + * @return created initiator_init_t object + * + * @ingroup states + */ +initiator_init_t *initiator_init_create(protected_ike_sa_t *ike_sa); + + +#endif /*INITIATOR_INIT_H_*/ diff --git a/src/charon/sa/states/responder_init.c b/src/charon/sa/states/responder_init.c new file mode 100644 index 000000000..10acf645c --- /dev/null +++ b/src/charon/sa/states/responder_init.c @@ -0,0 +1,568 @@ +/** + * @file responder_init.c + * + * @brief Implementation of responder_init_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 "responder_init.h" + +#include +#include +#include +#include +#include +#include +#include +#include + + +typedef struct private_responder_init_t private_responder_init_t; + +/** + * Private data of a responder_init_t object. + * + */ +struct private_responder_init_t { + /** + * Methods of the state_t interface. + */ + responder_init_t public; + + /** + * Assigned IKE_SA. + */ + protected_ike_sa_t *ike_sa; + + /** + * Diffie Hellman object used to compute shared secret. + */ + diffie_hellman_t *diffie_hellman; + + /** + * Diffie Hellman group number from selected IKE proposal. + */ + u_int16_t dh_group_number; + + /** + * Priority used to get matching dh_group number. + */ + u_int16_t dh_group_priority; + + /** + * Sent nonce value. + * + * This value is passed to the next state of type IKE_SA_INIT_RESPONDED. + */ + chunk_t sent_nonce; + + /** + * Received nonce value + * + * This value is passed to the next state of type IKE_SA_INIT_RESPONDED. + */ + chunk_t received_nonce; + + /** + * Selected proposal + */ + proposal_t *proposal; + + /** + * Logger used to log data . + * + * Is logger of ike_sa! + */ + logger_t *logger; + + /** + * Handles received SA payload and builds the SA payload for the response. + * + * @param this calling object + * @param sa_request The received SA payload + * @param response the SA payload is added to this response message_t object. + * @return + * - DELETE_ME + * - SUCCESS + */ + status_t (*build_sa_payload) (private_responder_init_t *this,sa_payload_t *sa_request, message_t *response); + + /** + * Handles received KE payload and builds the KE payload for the response. + * + * @param this calling object + * @param ke_request The received KE payload + * @param response the KE payload is added to this response message_t object. + * - DELETE_ME + * - SUCCESS + */ + status_t (*build_ke_payload) (private_responder_init_t *this,ke_payload_t *ke_request, message_t *response); + + /** + * Handles received NONCE payload and builds the NONCE payload for the response. + * + * @param this calling object + * @param nonce_request The received NONCE payload + * @param response the NONCE payload is added to this response message_t object. + * - DELETE_ME + * - SUCCESS + */ + status_t (*build_nonce_payload) (private_responder_init_t *this,nonce_payload_t *nonce_request, message_t *response); + + /** + * Sends a IKE_SA_INIT reply containing a notify payload. + * + * @param this calling object + * @param notify_payload notify_payload to process + */ + status_t (*process_notify_payload) (private_responder_init_t *this, notify_payload_t *notify_payload); + + /** + * Destroy function called internally of this class after change + * to state IKE_SA_INIT_RESPONDED succeeded. + * + * This destroy function does not destroy objects which were passed to the new state. + * + * @param this calling object + */ + void (*destroy_after_state_change) (private_responder_init_t *this); + +}; + +/** + * Implementation of state_t.process_message. + */ +static status_t process_message(private_responder_init_t *this, message_t *message) +{ + ike_sa_init_responded_t *next_state; + chunk_t ike_sa_init_response_data; + chunk_t ike_sa_init_request_data; + sa_payload_t *sa_request = NULL; + ke_payload_t *ke_request = NULL; + nonce_payload_t *nonce_request = NULL; + host_t *source, *destination; + connection_t *connection; + iterator_t *payloads; + message_t *response; + status_t status; + + if (message->get_exchange_type(message) != IKE_SA_INIT) + { + this->logger->log(this->logger, ERROR | LEVEL1, "Message of type %s not supported in state responder_init",mapping_find(exchange_type_m,message->get_exchange_type(message))); + return DELETE_ME; + } + if (!message->get_request(message)) + { + this->logger->log(this->logger, ERROR | LEVEL1, "IKE_SA_INIT responses not allowed state ike_sa_init_responded"); + return DELETE_ME; + } + + /* this is the first message to process, so get host infos */ + source = message->get_source(message); + destination = message->get_destination(message); + + connection = charon->connections->get_connection_by_hosts(charon->connections, destination, source); + if (connection == NULL) + { + /* no configuration matches given hosts */ + this->logger->log(this->logger, AUDIT, "IKE_SA_INIT request does not match any available connection. Deleting IKE_SA"); + /* TODO: inform requestor */ + return DELETE_ME; + } + this->ike_sa->set_connection(this->ike_sa,connection); + + /* parse incoming message */ + status = message->parse_body(message, NULL, NULL); + if (status != SUCCESS) + { + if (status == NOT_SUPPORTED) + { + this->logger->log(this->logger, AUDIT, "IKE_SA_INIT request contains unsupported payload with critical flag set. " + "Deleting IKE_SA"); + this->ike_sa->send_notify(this->ike_sa, IKE_SA_INIT, UNSUPPORTED_CRITICAL_PAYLOAD, CHUNK_INITIALIZER); + } + else + { + this->logger->log(this->logger, AUDIT, "Unable to parse IKE_SA_INIT request. Deleting IKE_SA"); + } + return DELETE_ME; + } + + payloads = message->get_payload_iterator(message); + while (payloads->has_next(payloads)) + { + payload_t *payload; + + payloads->current(payloads, (void**)&payload); + + switch (payload->get_type(payload)) + { + case SECURITY_ASSOCIATION: + { + sa_request = (sa_payload_t*)payload; + break; + } + case KEY_EXCHANGE: + { + ke_request = (ke_payload_t*)payload; + break; + } + case NONCE: + { + nonce_request = (nonce_payload_t*)payload; + break; + } + case NOTIFY: + { + notify_payload_t *notify_payload = (notify_payload_t *) payload; + status = this->process_notify_payload(this, notify_payload); + if (status != SUCCESS) + { + payloads->destroy(payloads); + return status; + } + } + default: + { + this->logger->log(this->logger, ERROR|LEVEL1, "Ignoring payload %s (%d)", + mapping_find(payload_type_m, payload->get_type(payload)), payload->get_type(payload)); + break; + } + } + } + payloads->destroy(payloads); + + /* check if we have all payloads */ + if (!(sa_request && ke_request && nonce_request)) + { + this->logger->log(this->logger, AUDIT, "IKE_SA_INIT request did not contain all required payloads. Deleting IKE_SA"); + return DELETE_ME; + } + + this->ike_sa->build_message(this->ike_sa, IKE_SA_INIT, FALSE, &response); + + status = this->build_sa_payload(this, sa_request, response); + if (status != SUCCESS) + { + response->destroy(response); + return status; + } + + status = this->build_ke_payload(this, ke_request, response); + if (status != SUCCESS) + { + response->destroy(response); + return status; + } + + status = this->build_nonce_payload(this, nonce_request, response); + if (status != SUCCESS) + { + response->destroy(response); + return status; + } + + /* derive all the keys used in the IKE_SA */ + status = this->ike_sa->build_transforms(this->ike_sa, this->proposal, this->diffie_hellman, this->received_nonce, this->sent_nonce); + if (status != SUCCESS) + { + this->logger->log(this->logger, AUDIT, "Transform objects could not be created from selected proposal. Deleting IKE_SA"); + return DELETE_ME; + } + + /* message can now be sent (must not be destroyed) */ + status = this->ike_sa->send_response(this->ike_sa, response); + if (status != SUCCESS) + { + this->logger->log(this->logger, AUDIT, "Unable to send IKE_SA_INIT response. Deleting IKE_SA"); + response->destroy(response); + return DELETE_ME; + } + + /* state can now be changed */ + this->logger->log(this->logger, CONTROL|LEVEL2, "Create next state object of type IKE_SA_INIT_RESPONDED"); + + response = this->ike_sa->get_last_responded_message(this->ike_sa); + ike_sa_init_response_data = response->get_packet_data(response); + ike_sa_init_request_data = message->get_packet_data(message); + + next_state = ike_sa_init_responded_create(this->ike_sa, this->received_nonce, this->sent_nonce,ike_sa_init_request_data, + ike_sa_init_response_data); + + /* state can now be changed */ + this->ike_sa->set_new_state(this->ike_sa, (state_t *) next_state); + this->destroy_after_state_change(this); + + return SUCCESS; +} + +/** + * Implementation of private_initiator_init_t.build_sa_payload. + */ +static status_t build_sa_payload(private_responder_init_t *this,sa_payload_t *sa_request, message_t *response) +{ + proposal_t *proposal; + linked_list_t *proposal_list; + connection_t *connection; + sa_payload_t* sa_payload; + algorithm_t *algo; + + connection = this->ike_sa->get_connection(this->ike_sa); + + this->logger->log(this->logger, CONTROL | LEVEL2, "Process received SA payload"); + + /* get the list of suggested proposals */ + proposal_list = sa_request->get_proposals (sa_request); + + /* select proposal */ + this->proposal = connection->select_proposal(connection, proposal_list); + while(proposal_list->remove_last(proposal_list, (void**)&proposal) == SUCCESS) + { + proposal->destroy(proposal); + } + proposal_list->destroy(proposal_list); + if (this->proposal == NULL) + { + this->logger->log(this->logger, AUDIT, "IKE_SA_INIT request did not contain any acceptable proposals. Deleting IKE_SA"); + this->ike_sa->send_notify(this->ike_sa, IKE_SA_INIT, NO_PROPOSAL_CHOSEN, CHUNK_INITIALIZER); + return DELETE_ME; + } + /* get selected DH group to force policy, this is very restrictive!? */ + this->proposal->get_algorithm(this->proposal, PROTO_IKE, DIFFIE_HELLMAN_GROUP, &algo); + this->dh_group_number = algo->algorithm; + + this->logger->log(this->logger, CONTROL | LEVEL2, "SA Payload processed"); + + this->logger->log(this->logger, CONTROL|LEVEL2, "Building SA payload"); + sa_payload = sa_payload_create_from_proposal(this->proposal); + this->logger->log(this->logger, CONTROL|LEVEL2, "add SA payload to message"); + response->add_payload(response,(payload_t *) sa_payload); + + return SUCCESS; +} + +/** + * Implementation of private_initiator_init_t.build_ke_payload. + */ +static status_t build_ke_payload(private_responder_init_t *this,ke_payload_t *ke_request, message_t *response) +{ + diffie_hellman_group_t group; + ke_payload_t *ke_payload; + diffie_hellman_t *dh; + chunk_t key_data; + + this->logger->log(this->logger, CONTROL | LEVEL2, "Process received KE payload"); + group = ke_request->get_dh_group_number(ke_request); + + if (group == MODP_UNDEFINED) + { + this->logger->log(this->logger, AUDIT, "No diffie hellman group to select. Deleting IKE_SA"); + return DELETE_ME; + } + + if (this->dh_group_number != group) + { + u_int16_t accepted_group; + chunk_t accepted_group_chunk; + /* group not same as selected one + * Maybe key exchange payload is before SA payload */ + this->logger->log(this->logger, AUDIT, "IKE_SA_INIT request did not contain a acceptable diffie hellman group. Deleting IKE_SA"); + + accepted_group = htons(this->dh_group_number); + accepted_group_chunk.ptr = (u_int8_t*) &(accepted_group); + accepted_group_chunk.len = 2; + this->ike_sa->send_notify(this->ike_sa,IKE_SA_INIT,INVALID_KE_PAYLOAD,accepted_group_chunk); + return DELETE_ME; + } + + /* create diffie hellman object to handle DH exchange */ + dh = diffie_hellman_create(group); + if (dh == NULL) + { + this->logger->log(this->logger, AUDIT, "Could not generate DH object with group %d. Deleting IKE_SA", + mapping_find(diffie_hellman_group_m,group) ); + return DELETE_ME; + } + this->logger->log(this->logger, CONTROL | LEVEL2, "Set other DH public value"); + + dh->set_other_public_value(dh, ke_request->get_key_exchange_data(ke_request)); + + this->diffie_hellman = dh; + + this->logger->log(this->logger, CONTROL | LEVEL2, "KE Payload processed."); + + this->logger->log(this->logger, CONTROL|LEVEL2, "Building KE payload"); + this->diffie_hellman->get_my_public_value(this->diffie_hellman,&key_data); + + ke_payload = ke_payload_create(); + ke_payload->set_key_exchange_data(ke_payload,key_data); + ke_payload->set_dh_group_number(ke_payload, this->dh_group_number); + chunk_free(&key_data); + + this->logger->log(this->logger, CONTROL|LEVEL2, "Add KE payload to message"); + response->add_payload(response,(payload_t *) ke_payload); + + return SUCCESS; +} + +/** + * Implementation of private_responder_init_t.build_nonce_payload. + */ +static status_t build_nonce_payload(private_responder_init_t *this,nonce_payload_t *nonce_request, message_t *response) +{ + nonce_payload_t *nonce_payload; + randomizer_t *randomizer; + status_t status; + + this->logger->log(this->logger, CONTROL | LEVEL2, "Process received NONCE payload"); + free(this->received_nonce.ptr); + this->received_nonce = CHUNK_INITIALIZER; + + this->logger->log(this->logger, CONTROL | LEVEL2, "Get NONCE value and store it"); + this->received_nonce = nonce_request->get_nonce(nonce_request); + + this->logger->log(this->logger, CONTROL | LEVEL2, "Create new NONCE value."); + + randomizer = this->ike_sa->get_randomizer(this->ike_sa); + status = randomizer->allocate_pseudo_random_bytes(randomizer, NONCE_SIZE, &(this->sent_nonce)); + if (status != SUCCESS) + { + return status; + } + + this->logger->log(this->logger, CONTROL|LEVEL2, "Building NONCE payload"); + nonce_payload = nonce_payload_create(); + nonce_payload->set_nonce(nonce_payload, this->sent_nonce); + + this->logger->log(this->logger, CONTROL|LEVEL2, "Add NONCE payload to message"); + response->add_payload(response,(payload_t *) nonce_payload); + + return SUCCESS; +} + +/** + * Implementation of private_responder_init_t.process_notify_payload. + */ +static status_t process_notify_payload(private_responder_init_t *this, notify_payload_t *notify_payload) +{ + notify_message_type_t notify_message_type = notify_payload->get_notify_message_type(notify_payload); + + this->logger->log(this->logger, CONTROL|LEVEL1, "Process notify type %s", + mapping_find(notify_message_type_m, notify_message_type)); + + if (notify_payload->get_protocol_id(notify_payload) != PROTO_IKE) + { + this->logger->log(this->logger, ERROR | LEVEL1, "Notify reply not for IKE protocol."); + return FAILED; + } + switch (notify_message_type) + { + default: + { + this->logger->log(this->logger, CONTROL, "IKE_SA_INIT request contained a notify (%d), ignored.", + notify_message_type); + return SUCCESS; + } + } +} + +/** + * Implementation of state_t.get_state. + */ +static ike_sa_state_t get_state(private_responder_init_t *this) +{ + return RESPONDER_INIT; +} + +/** + * Implementation of state_t.destroy. + */ +static void destroy(private_responder_init_t *this) +{ + this->logger->log(this->logger, CONTROL | LEVEL1, "Going to destroy responder init state object"); + + this->logger->log(this->logger, CONTROL | LEVEL2, "Destroy sent nonce"); + chunk_free(&(this->sent_nonce)); + this->logger->log(this->logger, CONTROL | LEVEL2, "Destroy received nonce"); + chunk_free(&(this->received_nonce)); + + if (this->diffie_hellman != NULL) + { + this->logger->log(this->logger, CONTROL | LEVEL2, "Destroy diffie_hellman_t hellman object"); + this->diffie_hellman->destroy(this->diffie_hellman); + } + if (this->proposal) + { + this->proposal->destroy(this->proposal); + } + this->logger->log(this->logger, CONTROL | LEVEL2, "Destroy object"); + free(this); +} + +/** + * Implementation of private_responder_init_t.destroy_after_state_change + */ +static void destroy_after_state_change (private_responder_init_t *this) +{ + this->logger->log(this->logger, CONTROL | LEVEL1, "Going to destroy responder_init_t state object"); + + /* destroy diffie hellman object */ + if (this->diffie_hellman != NULL) + { + this->logger->log(this->logger, CONTROL | LEVEL2, "Destroy diffie_hellman_t object"); + this->diffie_hellman->destroy(this->diffie_hellman); + } + if (this->proposal) + { + this->proposal->destroy(this->proposal); + } + + this->logger->log(this->logger, CONTROL | LEVEL2, "Destroy object"); + free(this); +} + +/* + * Described in header. + */ +responder_init_t *responder_init_create(protected_ike_sa_t *ike_sa) +{ + private_responder_init_t *this = malloc_thing(private_responder_init_t); + + /* interface functions */ + this->public.state_interface.process_message = (status_t (*) (state_t *,message_t *)) process_message; + this->public.state_interface.get_state = (ike_sa_state_t (*) (state_t *)) get_state; + this->public.state_interface.destroy = (void (*) (state_t *)) destroy; + + /* private functions */ + this->build_sa_payload = build_sa_payload; + this->build_ke_payload = build_ke_payload; + this->build_nonce_payload = build_nonce_payload; + this->destroy_after_state_change = destroy_after_state_change; + this->process_notify_payload = process_notify_payload; + + /* private data */ + this->ike_sa = ike_sa; + this->logger = logger_manager->get_logger(logger_manager, IKE_SA); + this->sent_nonce = CHUNK_INITIALIZER; + this->received_nonce = CHUNK_INITIALIZER; + this->dh_group_number = MODP_UNDEFINED; + this->diffie_hellman = NULL; + this->proposal = NULL; + + return &(this->public); +} diff --git a/src/charon/sa/states/responder_init.h b/src/charon/sa/states/responder_init.h new file mode 100644 index 000000000..c8ba73ea3 --- /dev/null +++ b/src/charon/sa/states/responder_init.h @@ -0,0 +1,68 @@ +/** + * @file responder_init.h + * + * @brief Interface of responder_init_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef RESPONDER_INIT_H_ +#define RESPONDER_INIT_H_ + +#include +#include + + +typedef struct responder_init_t responder_init_t; + +/** + * @brief This class represents an IKE_SA state when + * initializing a connection as responder. + * + * @b Constructors: + * - responder_init_create() + * + * @ingroup states + */ +struct responder_init_t { + /** + * The state_t interface. + */ + state_t state_interface; +}; + +/** + * Constructor of class responder_init_t. + * + * The following functions of the assigned protected_ike_sa_t object are being called with + * valid values after successfully processing a received message and before changing + * to next state IKE_SA_INIT_RESPONDED: + * - protected_ike_sa_t.set_connection() + * - protected_ike_sa_t.set_my_host() + * - protected_ike_sa_t.set_other_host() + * - protected_ike_sa_t.compute_secrets() + * - protected_ike_sa_t.create_transforms_from_proposal() + * + * @param ike_sa assigned IKE_SA + * + * @return responder_init_t object + * + * @ingroup states + */ +responder_init_t *responder_init_create(protected_ike_sa_t *ike_sa); + +#endif /*RESPONDER_INIT_H_*/ diff --git a/src/charon/sa/states/state.c b/src/charon/sa/states/state.c new file mode 100644 index 000000000..595f5abbb --- /dev/null +++ b/src/charon/sa/states/state.c @@ -0,0 +1,37 @@ +/** + * @file state.c + * + * @brief Interface state_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 "state.h" + + +/** + * String mappings for ike_sa_state_t. + */ +mapping_t ike_sa_state_m[] = { + {INITIATOR_INIT, "INITIATOR_INIT"}, + {RESPONDER_INIT, "RESPONDER_INIT"}, + {IKE_SA_INIT_REQUESTED, "IKE_SA_INIT_REQUESTED"}, + {IKE_SA_INIT_RESPONDED, "IKE_SA_INIT_RESPONDED"}, + {IKE_AUTH_REQUESTED, "IKE_AUTH_REQUESTED"}, + {IKE_SA_ESTABLISHED, "IKE_SA_ESTABLISHED"}, + {MAPPING_END, NULL} +}; diff --git a/src/charon/sa/states/state.h b/src/charon/sa/states/state.h new file mode 100644 index 000000000..c93068d35 --- /dev/null +++ b/src/charon/sa/states/state.h @@ -0,0 +1,166 @@ +/** + * @file state.h + * + * @brief Interface state_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef STATE_H_ +#define STATE_H_ + +#include +#include +#include + +typedef enum ike_sa_state_t ike_sa_state_t; + +/** + * States in which a IKE_SA can be. + * + * @todo Support of more states (CHILD_SA_REQUESTED, etc...) + * + * @ingroup states + */ +enum ike_sa_state_t { + + /** + * @brief IKE_SA is in initial state as initiator and is going to initiate a new connection. + * + * Next state following this state is IKE_SA_INIT_REQUESTED. + * + * Implemented in class initiator_init_t. + */ + INITIATOR_INIT = 1, + + /** + * @brief IKE_SA is in initial state as responder and is going to respond to a initiated connection. + * + * Next state following this state is IKE_SA_INIT_RESPONDED. + * + * Implemented in class responder_init_t. + */ + RESPONDER_INIT = 2, + + /** + * @brief A IKE_SA_INIT request was sent. In this state a reply of type IKE_SA_INIT is expected. + * + * Two states are possible as next states: + * - IKE_AUTH_REQUESTED if IKE_SA_INIT reply could successfully processed and IKE_AUTH request could be sent. + * - INITIATOR_INIT if selected DH group was not the one selected by other peer. + * + * Implemented in class ike_sa_init_requested_t. + */ + IKE_SA_INIT_REQUESTED = 3, + + /** + * @brief A IKE_SA_INIT response was sent. In this state a request of type IKE_AUTH is expected. + * + * Next state following this state is IKE_SA_ESTABLISHED. + * + * Implemented in class ike_sa_init_responded_t. + */ + IKE_SA_INIT_RESPONDED = 4, + + /** + * @brief An IKE_AUTH request was sent after a successful IKE_SA_INIT-exchange. + * + * Next state following this state is IKE_SA_ESTABLISHED. + * + * Implemented in class ike_auth_requested_t. + */ + IKE_AUTH_REQUESTED = 5, + + /** + * @brief An IKE_AUTH exchange was successfuly handled either as initiator or responder. + * + * In this state, all the informations for an IKE_SA and one CHILD_SA are known. + * + * Implemented in class ike_sa_established_t. + */ + IKE_SA_ESTABLISHED = 6 +}; + + +/** + * String mappings for ike_sa_state_t. + */ +extern mapping_t ike_sa_state_m[]; + + +typedef struct state_t state_t; + +/** + * @brief This interface represents an IKE_SA state. + * + * A state_t object is responsible to handle incoming messages. + * + * It's the responsibility of the state_t object to parse the body of the message and to process each + * payload. + * + * Needed Configurations and transform objects can be retrieved over an internal stored protected_ike_sa_t object + * which is passed to a state_t object when creating it (see different constructors). + * + * The following states are supported and implemented: + * - INITIATOR_INIT: implemented in initiator_init_t + * - RESPONDER_INIT: implemented in responder_init_t + * - IKE_SA_INIT_REQUESTED: implemented in ike_sa_init_requested_t + * - IKE_SA_INIT_RESPONDED: implemented in ike_sa_init_responded_t + * - IKE_AUTH_REQUESTED: implemented in ike_auth_requested_t + * - IKE_SA_ESTABLISHED: implemented in ike_sa_established_t + * + * @b Constructors: + * - initiator_init_create() + * - responder_init_create() + * - ike_sa_init_requested_create() + * - ike_sa_init_responded_create() + * - ike_auth_requested_create() + * - ike_sa_established_create() + * + * @ingroup states + */ +struct state_t { + + /** + * @brief Processes a incoming IKEv2-Message of type message_t. + * + * @param this calling object + * @param[in] message message_t object to process + * @return + * - SUCCESSFUL + * - FAILED + * - DELETE_ME if belonging IKE_SA should be deleted + */ + status_t (*process_message) (state_t *this,message_t *message); + + /** + * @brief Get the current state representing by this state_t object. + * + * @param this calling object + * @return state + */ + ike_sa_state_t (*get_state) (state_t *this); + + /** + * @brief Destroys a state_t object. + * + * @param this calling object + */ + void (*destroy) (state_t *this); +}; + +#endif /*STATE_H_*/ diff --git a/src/charon/threads/Makefile.threads b/src/charon/threads/Makefile.threads new file mode 100644 index 000000000..949c1ad24 --- /dev/null +++ b/src/charon/threads/Makefile.threads @@ -0,0 +1,39 @@ +# Copyright (C) 2005 Jan Hutter, 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 . +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# + +THREADS_DIR= $(CHARON_DIR)threads/ + +CHARON_OBJS+= $(BUILD_DIR)receiver.o +$(BUILD_DIR)receiver.o : $(THREADS_DIR)receiver.c $(THREADS_DIR)receiver.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)scheduler.o +$(BUILD_DIR)scheduler.o : $(THREADS_DIR)scheduler.c $(THREADS_DIR)scheduler.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)sender.o +$(BUILD_DIR)sender.o : $(THREADS_DIR)sender.c $(THREADS_DIR)sender.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)thread_pool.o +$(BUILD_DIR)thread_pool.o : $(THREADS_DIR)thread_pool.c $(THREADS_DIR)thread_pool.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)kernel_interface.o +$(BUILD_DIR)kernel_interface.o :$(THREADS_DIR)kernel_interface.c $(THREADS_DIR)kernel_interface.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)stroke_interface.o +$(BUILD_DIR)stroke_interface.o :$(THREADS_DIR)stroke_interface.c $(THREADS_DIR)stroke_interface.h + $(CC) $(CFLAGS) -c -o $@ $< diff --git a/src/charon/threads/kernel_interface.c b/src/charon/threads/kernel_interface.c new file mode 100644 index 000000000..679cf69ee --- /dev/null +++ b/src/charon/threads/kernel_interface.c @@ -0,0 +1,729 @@ +/** + * @file kernel_interface.c + * + * @brief Implementation of kernel_interface_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, Martin Willi + * Hochschule fuer Technik Rapperswil + * Copyright (C) 2003 Herbert Xu. + * + * Contains modified parts from pluto. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 +#include +#include +#include +#include +#include +#include +#include + +#include "kernel_interface.h" + +#include +#include + + +#define KERNEL_ESP 50 +#define KERNEL_AH 51 + +#define SPD_PRIORITY 1024 + +#define XFRM_DATA_LENGTH 512 + + +typedef struct xfrm_data_t xfrm_data_t; + +/** + * Lenght/Type/data struct for userdata in xfrm + * We dont use the "I-don't-know-where-they-come-from"-structs + * used in the kernel. + */ +struct xfrm_data_t { + /** + * length of the data + */ + u_int16_t length; + + /** + * type of data + */ + u_int16_t type; + + /** + * and the data itself, for different purposes + */ + union { + /** algorithm */ + struct xfrm_algo algo; + /** policy tmpl */ + struct xfrm_user_tmpl tmpl[2]; + }; +}; + + +typedef struct netlink_message_t netlink_message_t; + +/** + * Representation of ANY netlink message used + */ +struct netlink_message_t { + + /** + * header of the netlink message + */ + struct nlmsghdr hdr; + + union { + /** error message */ + struct nlmsgerr e; + /** message for spi allocation */ + struct xfrm_userspi_info spi; + /** message for SA manipulation */ + struct xfrm_usersa_id sa_id; + /** message for SA installation */ + struct xfrm_usersa_info sa; + /** message for policy manipulation */ + struct xfrm_userpolicy_id policy_id; + /** message for policy installation */ + struct xfrm_userpolicy_info policy; + }; + u_int8_t data[XFRM_DATA_LENGTH]; +}; + + +typedef struct private_kernel_interface_t private_kernel_interface_t; + + /** + * @brief Private Variables and Functions of kernel_interface class. + * + */ +struct private_kernel_interface_t { + /** + * Public part of the kernel_interface_t object. + */ + kernel_interface_t public; + + /** + * Netlink communication socket. + */ + int socket; + + /** + * Process id of kernel thread + */ + pid_t pid; + + /** + * Sequence number for messages. + */ + u_int32_t seq; + + /** + * List of responded messages. + */ + linked_list_t *responses; + + /** + * Thread which receives messages. + */ + pthread_t thread; + + /** + * Mutex locks access to replies list. + */ + pthread_mutex_t mutex; + + /** + * Condvar allows signaling of threads waiting for a reply. + */ + pthread_cond_t condvar; + + /** + * Logger for XFRM stuff + */ + logger_t *logger; + + /** + * Function for the thread, receives messages. + */ + void (*receive_messages) (private_kernel_interface_t *this); + + /** + * Sends a netlink_message_t down to the kernel and wait for reply. + */ + status_t (*send_message) (private_kernel_interface_t *this, netlink_message_t *request, netlink_message_t **response); +}; + +/** + * In the kernel, algorithms are identified as strings, we use our + * mapping functions... + * Algorithms for encryption. + * TODO: Add missing algorithm strings + */ +mapping_t kernel_encryption_algs_m[] = { + {ENCR_DES_IV64, ""}, + {ENCR_DES, "des"}, + {ENCR_3DES, "des3_ede"}, + {ENCR_RC5, ""}, + {ENCR_IDEA, "idea"}, + {ENCR_CAST, "cast128"}, + {ENCR_BLOWFISH, "blowfish"}, + {ENCR_3IDEA, ""}, + {ENCR_DES_IV32, ""}, + {ENCR_NULL, ""}, + {ENCR_AES_CBC, "aes"}, + {ENCR_AES_CTR, ""}, + {MAPPING_END, NULL} +}; +/** + * In the kernel, algorithms are identified as strings, we use our + * mapping functions... + * Algorithms for integrity protection. + * TODO: Add missing algorithm strings + */ +mapping_t kernel_integrity_algs_m[] = { + {AUTH_HMAC_MD5_96, "md5"}, + {AUTH_HMAC_SHA1_96, "sha1"}, + {AUTH_DES_MAC, ""}, + {AUTH_KPDK_MD5, ""}, + {AUTH_AES_XCBC_96, ""}, + {MAPPING_END, NULL} +}; + + +/** + * Implementation of kernel_interface_t.get_spi. + */ +static status_t get_spi(private_kernel_interface_t *this, + host_t *src, host_t *dest, + protocol_id_t protocol, u_int32_t reqid, + u_int32_t *spi) +{ + netlink_message_t request, *response; + status_t status = SUCCESS; + + + this->logger->log(this->logger, CONTROL|LEVEL2, "getting spi"); + + memset(&request, 0, sizeof(request)); + request.hdr.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(request.spi))); + request.hdr.nlmsg_flags = NLM_F_REQUEST; + request.hdr.nlmsg_type = XFRM_MSG_ALLOCSPI; + request.spi.info.saddr = src->get_xfrm_addr(src); + request.spi.info.id.daddr = dest->get_xfrm_addr(dest); + request.spi.info.mode = TRUE; /* tunnel mode */ + request.spi.info.reqid = reqid; + request.spi.info.id.proto = (protocol == PROTO_ESP) ? KERNEL_ESP : KERNEL_AH; + request.spi.info.family = PF_INET; + request.spi.min = 0xc0000000; + request.spi.max = 0xcFFFFFFF; + + if (this->send_message(this, &request, &response) != SUCCESS) + { + this->logger->log(this->logger, ERROR, "netlink communication failed"); + return FAILED; + } + else if (response->hdr.nlmsg_type == NLMSG_ERROR) + { + this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_ALLOCSPI got an error: %s", + strerror(-response->e.error)); + status = FAILED; + } + else if (response->hdr.nlmsg_type != XFRM_MSG_NEWSA) + { + this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_ALLOCSPI got a unknown reply"); + status = FAILED; + } + else if (response->hdr.nlmsg_len < NLMSG_LENGTH(sizeof(response->sa))) + { + this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_ALLOCSPI got an invalid reply"); + status = FAILED; + } + else + { + *spi = response->sa.id.spi; + } + free(response); + + return status; +} + +/** + * Implementation of kernel_interface_t.add_sa. + */ +static status_t add_sa( private_kernel_interface_t *this, + host_t *me, + host_t *other, + u_int32_t spi, + int protocol, + u_int32_t reqid, + encryption_algorithm_t enc_alg, + chunk_t encryption_key, + integrity_algorithm_t int_alg, + chunk_t integrity_key, + bool replace) +{ + netlink_message_t request, *response; + memset(&request, 0, sizeof(request)); + status_t status = SUCCESS; + + this->logger->log(this->logger, CONTROL|LEVEL2, "adding SA"); + + request.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; + request.hdr.nlmsg_type = replace ? XFRM_MSG_UPDSA : XFRM_MSG_NEWSA; + + request.sa.saddr = me->get_xfrm_addr(me); + request.sa.id.daddr = other->get_xfrm_addr(other); + + request.sa.id.spi = spi; + request.sa.id.proto = (protocol == PROTO_ESP) ? KERNEL_ESP : KERNEL_AH; + request.sa.family = me->get_family(me); + request.sa.mode = TRUE; /* tunnel mode */ + request.sa.replay_window = 32; + request.sa.reqid = reqid; + request.sa.lft.soft_byte_limit = XFRM_INF; + request.sa.lft.soft_packet_limit = XFRM_INF; + request.sa.lft.hard_byte_limit = XFRM_INF; + request.sa.lft.hard_packet_limit = XFRM_INF; + + request.hdr.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(request.sa))); + + if (enc_alg != ENCR_UNDEFINED) + { + xfrm_data_t *data = (xfrm_data_t*)(((u_int8_t*)&request) + request.hdr.nlmsg_len); + + data->type = XFRMA_ALG_CRYPT; + data->length = 4 + sizeof(data->algo) + encryption_key.len; + data->algo.alg_key_len = encryption_key.len * 8; + request.hdr.nlmsg_len += data->length; + if (request.hdr.nlmsg_len > sizeof(request)) + { + return FAILED; + } + strcpy(data->algo.alg_name, mapping_find(kernel_encryption_algs_m, enc_alg)); + memcpy(data->algo.alg_key, encryption_key.ptr, encryption_key.len); + } + + if (int_alg != AUTH_UNDEFINED) + { + xfrm_data_t *data = (xfrm_data_t*)(((u_int8_t*)&request) + request.hdr.nlmsg_len); + + data->type = XFRMA_ALG_AUTH; + data->length = 4 + sizeof(data->algo) + integrity_key.len; + data->algo.alg_key_len = integrity_key.len * 8; + request.hdr.nlmsg_len += data->length; + if (request.hdr.nlmsg_len > sizeof(request)) + { + return FAILED; + } + strcpy(data->algo.alg_name, mapping_find(kernel_integrity_algs_m, int_alg)); + memcpy(data->algo.alg_key, integrity_key.ptr, integrity_key.len); + } + + /* TODO: add IPComp here*/ + + if (this->send_message(this, &request, &response) != SUCCESS) + { + this->logger->log(this->logger, ERROR, "netlink communication failed"); + return FAILED; + } + else if (response->hdr.nlmsg_type != NLMSG_ERROR) + { + this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_NEWSA not acknowledged"); + status = FAILED; + } + else if (response->e.error) + { + this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_NEWSA got error %s", + strerror(-response->e.error)); + status = FAILED; + } + + free(response); + return status; +} + +static status_t del_sa( private_kernel_interface_t *this, + host_t *dst, + u_int32_t spi, + protocol_id_t protocol) +{ + netlink_message_t request, *response; + memset(&request, 0, sizeof(request)); + status_t status = SUCCESS; + + this->logger->log(this->logger, CONTROL|LEVEL2, "deleting SA"); + + request.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; + request.hdr.nlmsg_type = XFRM_MSG_DELSA; + + request.sa_id.daddr = dst->get_xfrm_addr(dst); + + request.sa_id.spi = spi; + request.sa_id.proto = (protocol == PROTO_ESP) ? KERNEL_ESP : KERNEL_AH; + request.sa_id.family = dst->get_family(dst); + + request.hdr.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(request.sa_id))); + + if (this->send_message(this, &request, &response) != SUCCESS) + { + return FAILED; + } + else if (response->hdr.nlmsg_type != NLMSG_ERROR) + { + status = FAILED; + } + else if (response->e.error) + { + status = FAILED; + } + + free(response); + return status; +} + +/** + * Implementation of kernel_interface_t.add_policy. + */ +static status_t add_policy(private_kernel_interface_t *this, + host_t *me, host_t *other, + host_t *src, host_t *dst, + u_int8_t src_hostbits, u_int8_t dst_hostbits, + int direction, int upper_proto, + bool ah, bool esp, + u_int32_t reqid) +{ + netlink_message_t request, *response; + status_t status = SUCCESS; + + this->logger->log(this->logger, CONTROL|LEVEL2, "adding policy"); + + memset(&request, 0, sizeof(request)); + request.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; + + request.policy.sel.sport = htons(src->get_port(src)); + request.policy.sel.dport = htons(dst->get_port(dst)); + request.policy.sel.sport_mask = (request.policy.sel.sport) ? ~0 : 0; + request.policy.sel.dport_mask = (request.policy.sel.dport) ? ~0 : 0; + request.policy.sel.saddr = src->get_xfrm_addr(src); + request.policy.sel.daddr = dst->get_xfrm_addr(dst); + request.policy.sel.prefixlen_s = src_hostbits; + request.policy.sel.prefixlen_d = dst_hostbits; + request.policy.sel.proto = upper_proto; + request.policy.sel.family = src->get_family(src); + + request.hdr.nlmsg_type = XFRM_MSG_NEWPOLICY; + request.hdr.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(request.policy))); + + request.policy.dir = direction; + request.policy.priority = SPD_PRIORITY; + request.policy.action = XFRM_POLICY_ALLOW; + request.policy.share = XFRM_SHARE_ANY; + + request.policy.lft.soft_byte_limit = XFRM_INF; + request.policy.lft.soft_packet_limit = XFRM_INF; + request.policy.lft.hard_byte_limit = XFRM_INF; + request.policy.lft.hard_packet_limit = XFRM_INF; + + if (esp || ah) + { + xfrm_data_t *data; + int tmpl_pos = 0; + data = (xfrm_data_t*)(((u_int8_t*)&request) + request.hdr.nlmsg_len); + data->type = XFRMA_TMPL; + if (esp) + { + data->tmpl[tmpl_pos].reqid = reqid; + data->tmpl[tmpl_pos].id.proto = KERNEL_ESP; + data->tmpl[tmpl_pos].aalgos = data->tmpl[tmpl_pos].ealgos = data->tmpl[tmpl_pos].calgos = ~0; + data->tmpl[tmpl_pos].mode = TRUE; + + data->tmpl[tmpl_pos].saddr = me->get_xfrm_addr(me); + data->tmpl[tmpl_pos].id.daddr = me->get_xfrm_addr(other); + + tmpl_pos++; + } + if (ah) + { + data->tmpl[tmpl_pos].reqid = reqid; + data->tmpl[tmpl_pos].id.proto = KERNEL_AH; + data->tmpl[tmpl_pos].aalgos = data->tmpl[tmpl_pos].ealgos = data->tmpl[tmpl_pos].calgos = ~0; + data->tmpl[tmpl_pos].mode = TRUE; + + data->tmpl[tmpl_pos].saddr = me->get_xfrm_addr(me); + data->tmpl[tmpl_pos].id.daddr = other->get_xfrm_addr(other); + + tmpl_pos++; + } + data->length = 4 + sizeof(struct xfrm_user_tmpl) * tmpl_pos; + request.hdr.nlmsg_len += data->length; + } + + if (this->send_message(this, &request, &response) != SUCCESS) + { + this->logger->log(this->logger, ERROR, "netlink communication failed"); + return FAILED; + } + else if (response->hdr.nlmsg_type != NLMSG_ERROR) + { + this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_NEWPOLICY not acknowledged"); + status = FAILED; + } + else if (response->e.error) + { + this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_NEWPOLICY got error %s", + strerror(-response->e.error)); + status = FAILED; + } + + free(response); + return status; +} + +/** + * Implementation of kernel_interface_t.del_policy. + */ +static status_t del_policy(private_kernel_interface_t *this, + host_t *me, host_t *other, + host_t *src, host_t *dst, + u_int8_t src_hostbits, u_int8_t dst_hostbits, + int direction, int upper_proto) +{ + netlink_message_t request, *response; + status_t status = SUCCESS; + + + this->logger->log(this->logger, CONTROL|LEVEL2, "deleting policy"); + + memset(&request, 0, sizeof(request)); + request.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; + + request.policy_id.sel.sport = htons(src->get_port(src)); + request.policy_id.sel.dport = htons(dst->get_port(dst)); + request.policy_id.sel.sport_mask = (request.policy.sel.sport) ? ~0 : 0; + request.policy_id.sel.dport_mask = (request.policy.sel.dport) ? ~0 : 0; + request.policy_id.sel.saddr = src->get_xfrm_addr(src); + request.policy_id.sel.daddr = dst->get_xfrm_addr(dst); + request.policy_id.sel.prefixlen_s = src_hostbits; + request.policy_id.sel.prefixlen_d = dst_hostbits; + request.policy_id.sel.proto = upper_proto; + request.policy_id.sel.family = src->get_family(src); + + request.policy_id.dir = direction; + + request.hdr.nlmsg_type = XFRM_MSG_DELPOLICY; + request.hdr.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(request.policy_id))); + + if (this->send_message(this, &request, &response) != SUCCESS) + { + return FAILED; + } + else if (response->hdr.nlmsg_type != NLMSG_ERROR) + { + status = FAILED; + } + else if (response->e.error) + { + status = FAILED; + } + + free(response); + return status; +} + +/** + * Implementation of private_kernel_interface_t.send_message. + */ +static status_t send_message(private_kernel_interface_t *this, netlink_message_t *request, netlink_message_t **response) +{ + size_t length; + struct sockaddr_nl addr; + + request->hdr.nlmsg_seq = ++this->seq; + request->hdr.nlmsg_pid = this->pid; + + memset(&addr, 0, sizeof(struct sockaddr_nl)); + addr.nl_family = AF_NETLINK; + addr.nl_pid = 0; + addr.nl_groups = 0; + + length = sendto(this->socket,(void *)request, request->hdr.nlmsg_len, 0, (struct sockaddr *)&addr, sizeof(addr)); + + if (length < 0) + { + return FAILED; + } + else if (length != request->hdr.nlmsg_len) + { + return FAILED; + } + + pthread_mutex_lock(&(this->mutex)); + + while (TRUE) + { + iterator_t *iterator; + bool found = FALSE; + /* search list, break if found */ + iterator = this->responses->create_iterator(this->responses, TRUE); + while (iterator->has_next(iterator)) + { + netlink_message_t *listed_response; + iterator->current(iterator, (void**)&listed_response); + if (listed_response->hdr.nlmsg_seq == request->hdr.nlmsg_seq) + { + /* matches our request, this is the reply */ + *response = listed_response; + found = TRUE; + break; + } + } + iterator->destroy(iterator); + + if (found) + { + break; + } + /* TODO: we should time out, if something goes wrong!??? */ + pthread_cond_wait(&(this->condvar), &(this->mutex)); + } + + pthread_mutex_unlock(&(this->mutex)); + + return SUCCESS; +} + +/** + * Implementation of private_kernel_interface_t.receive_messages. + */ +static void receive_messages(private_kernel_interface_t *this) +{ + while(TRUE) + { + netlink_message_t response, *listed_response; + while (TRUE) + { + struct sockaddr_nl addr; + socklen_t addr_length; + size_t length; + + addr_length = sizeof(addr); + + response.hdr.nlmsg_type = XFRM_MSG_NEWSA; + length = recvfrom(this->socket, &response, sizeof(response), 0, (struct sockaddr*)&addr, &addr_length); + if (length < 0) + { + if (errno == EINTR) + { + /* interrupted, try again */ + continue; + } + charon->kill(charon, "receiving from netlink socket failed"); + } + if (!NLMSG_OK(&response.hdr, length)) + { + /* bad netlink message */ + continue; + } + if (addr.nl_pid != 0) + { + /* not from kernel. not interested, try another one */ + continue; + } + break; + } + + /* got a valid message. + * requests are handled on our own, + * responses are listed for the requesters + */ + if (response.hdr.nlmsg_flags & NLM_F_REQUEST) + { + /* handle request */ + } + else + { + /* add response to queue */ + listed_response = malloc(sizeof(response)); + memcpy(listed_response, &response, sizeof(response)); + + pthread_mutex_lock(&(this->mutex)); + this->responses->insert_last(this->responses, (void*)listed_response); + pthread_mutex_unlock(&(this->mutex)); + /* signal ALL waiting threads */ + pthread_cond_broadcast(&(this->condvar)); + } + /* get the next one */ + } +} + +/** + * Implementation of kernel_interface_t.destroy. + */ +static void destroy(private_kernel_interface_t *this) +{ + pthread_cancel(this->thread); + pthread_join(this->thread, NULL); + close(this->socket); + this->responses->destroy(this->responses); + free(this); +} + +/* + * Described in header. + */ +kernel_interface_t *kernel_interface_create() +{ + private_kernel_interface_t *this = malloc_thing(private_kernel_interface_t); + + /* public functions */ + this->public.get_spi = (status_t(*)(kernel_interface_t*,host_t*,host_t*,protocol_id_t,u_int32_t,u_int32_t*))get_spi; + this->public.add_sa = (status_t(*)(kernel_interface_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,encryption_algorithm_t,chunk_t,integrity_algorithm_t,chunk_t,bool))add_sa; + this->public.add_policy = (status_t(*)(kernel_interface_t*,host_t*, host_t*,host_t*,host_t*,u_int8_t,u_int8_t,int,int,bool,bool,u_int32_t))add_policy; + this->public.del_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t))del_sa; + this->public.del_policy = (status_t(*)(kernel_interface_t*,host_t*,host_t*,host_t*,host_t*,u_int8_t,u_int8_t,int,int))del_policy; + + this->public.destroy = (void(*)(kernel_interface_t*)) destroy; + + /* private members */ + this->receive_messages = receive_messages; + this->send_message = send_message; + this->pid = getpid(); + this->responses = linked_list_create(); + this->logger = logger_manager->get_logger(logger_manager, XFRM); + pthread_mutex_init(&(this->mutex),NULL); + pthread_cond_init(&(this->condvar),NULL); + this->seq = 0; + this->socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_XFRM); + if (this->socket <= 0) + { + this->responses->destroy(this->responses); + free(this); + charon->kill(charon, "Unable to create netlink socket"); + } + + if (pthread_create(&(this->thread), NULL, (void*(*)(void*))this->receive_messages, this) != 0) + { + this->responses->destroy(this->responses); + close(this->socket); + free(this); + charon->kill(charon, "Unable to create netlink thread"); + } + + return (&this->public); +} diff --git a/src/charon/threads/kernel_interface.h b/src/charon/threads/kernel_interface.h new file mode 100644 index 000000000..b3ca13faa --- /dev/null +++ b/src/charon/threads/kernel_interface.h @@ -0,0 +1,185 @@ +/** + * @file kernel_interface.h + * + * @brief Interface of kernel_interface_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef KERNEL_INTERFACE_H_ +#define KERNEL_INTERFACE_H_ + +#include + +#include +#include + +typedef struct kernel_interface_t kernel_interface_t; + +/** + * @brief Interface to the kernel. + * + * The kernel interface handles the communication with the kernel + * for SA and policy management. It allows setup of these, and provides + * further the handling of kernel events. + * + * @b Constructors: + * - kernel_interface_create() + * + * @ingroup threads + */ +struct kernel_interface_t { + + /** + * @brief Get a SPI from the kernel. + * + * @param this calling object + * @param src source address of SA + * @param dst destination address of SA + * @param protocol protocol for SA (ESP/AH) + * @param reqid unique ID for this SA + * @param[out] spi allocated spi + * @return + * - SUCCESS + * - FAILED if kernel comm failed + */ + status_t (*get_spi) (kernel_interface_t *this, + host_t *src, host_t *dst, + protocol_id_t protocol, + u_int32_t reqid, + u_int32_t *spi); + + /** + * @brief Add an SA to the SAD. + * + * add_sa() may update an already allocated + * SPI (via get_spi). In this case, the replace + * flag must be set. + * This function does install a single SA for a + * single protocol in one direction. + * + * @param this calling object + * @param src source address for this SA + * @param dst destination address for this SA + * @param spi SPI allocated by us or remote peer + * @param protocol protocol for this SA (ESP/AH) + * @param reqid unique ID for this SA + * @param enc_alg Algorithm to use for encryption (ESP only) + * @param enc_key Key to use for encryption + * @param int_alg Algorithm to use for integrity protection + * @param int_key Key for integrity protection + * @param replace Should an already installed SA be updated? + * @return + * - SUCCESS + * - FAILED if kernel comm failed + */ + status_t (*add_sa)(kernel_interface_t *this, + host_t *src, host_t *dst, + u_int32_t spi, + protocol_id_t protocol, + u_int32_t reqid, + encryption_algorithm_t enc_alg, + chunk_t enc_key, + integrity_algorithm_t int_alg, + chunk_t int_key, + bool replace); + /** + * @brief Delete a previusly installed SA from the SAD. + * + * @param this calling object + * @param dst destination address for this SA + * @param spi SPI allocated by us or remote peer + * @param protocol protocol for this SA (ESP/AH) + * @return + * - SUCCESS + * - FAILED if kernel comm failed + */ + status_t (*del_sa) (kernel_interface_t *this, + host_t *dst, + u_int32_t spi, + protocol_id_t protocol); + + /** + * @brief Add a policy to the SPD. + * + * A policy is always associated to an SA, so + * traffic applied to a policy. Traffic which + * matches a policy is handled by the SA with the same + * reqid. + * + * @param this calling object + * @param me address of local peer + * @param other address of remote peer + * @param src src address of traffic this policy applies + * @param dst dest address of traffic this policy applies + * @param src_hostbits subnetmask to use for src address + * @param dst_hostbits subnetmask to use for dst address + * @param direction direction of traffic, XFRM_POLICY_OUT, XFRM_POLICY_IN, XFRM_POLICY_FWD + * @param upper_proto upper layer protocol of traffic for this policy (TCP, UDP, ICMP, ...) + * @param ah protect traffic with AH? + * @param esp protect traffic with ESP? + * @param reqid uniqe ID of an SA to use to enforce policy + * @return + * - SUCCESS + * - FAILED if kernel comm failed + */ + status_t (*add_policy) (kernel_interface_t *this, + host_t *me, host_t *other, + host_t *src, host_t *dst, + u_int8_t src_hostbits, u_int8_t dst_hostbits, + int direction, int upper_proto, + bool ah, bool esp, + u_int32_t reqid); + + /** + * @brief Remove a policy from the SPD. + * + * @param this calling object + * @param me address of local peer + * @param other address of remote peer + * @param src src address of traffic this policy applies + * @param dst dest address of traffic this policy applies + * @param src_hostbits subnetmask to use for src address + * @param dst_hostbits subnetmask to use for dst address + * @param direction direction of traffic, XFRM_POLICY_OUT, XFRM_POLICY_IN, XFRM_POLICY_FWD + * @param upper_proto upper layer protocol of traffic for this policy (TCP, UDP, ICMP, ...) + * @return + * - SUCCESS + * - FAILED if kernel comm failed + */ + status_t (*del_policy) (kernel_interface_t *this, + host_t *me, host_t *other, + host_t *src, host_t *dst, + u_int8_t src_hostbits, u_int8_t dst_hostbits, + int direction, int upper_proto); + + /** + * @brief Destroys a kernel_interface object. + * + * @param kernel_interface_t calling object + */ + void (*destroy) (kernel_interface_t *kernel_interface); +}; + +/** + * @brief Creates an object of type kernel_interface_t. + * + * @ingroup threads + */ +kernel_interface_t *kernel_interface_create(void); + +#endif /*KERNEL_INTERFACE_H_*/ diff --git a/src/charon/threads/receiver.c b/src/charon/threads/receiver.c new file mode 100644 index 000000000..0cf8b7bde --- /dev/null +++ b/src/charon/threads/receiver.c @@ -0,0 +1,128 @@ +/** + * @file receiver.c + * + * @brief Implementation of receiver_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 +#include + +#include "receiver.h" + +#include +#include +#include +#include +#include +#include +#include + + +typedef struct private_receiver_t private_receiver_t; + +/** + * Private data of a receiver_t object. + */ +struct private_receiver_t { + /** + * Public part of a receiver_t object. + */ + receiver_t public; + + /** + * @brief Thread function started at creation of the receiver object. + * + * @param this calling object + */ + void (*receive_packets) (private_receiver_t *this); + + /** + * Assigned thread. + */ + pthread_t assigned_thread; + + /** + * A logger for the receiver_t object. + */ + logger_t *logger; +}; + +/** + * Implementation of receiver_t.receive_packets. + */ +static void receive_packets(private_receiver_t * this) +{ + packet_t * current_packet; + job_t *current_job; + + /* cancellation disabled by default */ + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); + + this->logger->log(this->logger, CONTROL, "Receiver thread running, thread_id %u", (int)pthread_self()); + + while (1) + { + while (charon->socket->receive(charon->socket,¤t_packet) == SUCCESS) + { + this->logger->log(this->logger, CONTROL | LEVEL1, "Creating job from packet"); + current_job = (job_t *) incoming_packet_job_create(current_packet); + + charon->job_queue->add(charon->job_queue,current_job); + + } + /* bad bad, rebuild the socket ? */ + this->logger->log(this->logger, ERROR, "Receiving from socket failed!"); + } +} + +/** + * Implementation of receiver_t.destroy. + */ +static void destroy(private_receiver_t *this) +{ + this->logger->log(this->logger, CONTROL | LEVEL1, "Going to terminate receiver thread"); + pthread_cancel(this->assigned_thread); + + pthread_join(this->assigned_thread, NULL); + this->logger->log(this->logger, CONTROL | LEVEL1, "Receiver thread terminated"); + + free(this); +} + +/* + * Described in header. + */ +receiver_t * receiver_create() +{ + private_receiver_t *this = malloc_thing(private_receiver_t); + + this->public.destroy = (void(*)(receiver_t*)) destroy; + this->receive_packets = receive_packets; + + this->logger = logger_manager->get_logger(logger_manager, RECEIVER); + + if (pthread_create(&(this->assigned_thread), NULL, (void*(*)(void*))this->receive_packets, this) != 0) + { + this->logger->log(this->logger, ERROR, "Receiver thread could not be started"); + free(this); + charon->kill(charon, "Unable to create receiver thread"); + } + + return &(this->public); +} diff --git a/src/charon/threads/receiver.h b/src/charon/threads/receiver.h new file mode 100644 index 000000000..1f9b644b1 --- /dev/null +++ b/src/charon/threads/receiver.h @@ -0,0 +1,67 @@ +/** + * @file receiver.h + * + * @brief Interface of receiver_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef RECEIVER_H_ +#define RECEIVER_H_ + +#include + + +typedef struct receiver_t receiver_t; + +/** + * @brief Receives packets from the socket and adds them to the job queue. + * + * The receiver starts a thread, wich reads on the blocking socket. If + * data is available, a packet_t object is created , wrapped + * in an incoming_packet_job_t and added to the job queue. + * + * @b Constructors: + * - receiver_create() + * + * @ingroup threads + */ +struct receiver_t { + + /** + * @brief Destroys a receiver_t object. + * + * @param receiver receiver object + */ + void (*destroy) (receiver_t *receiver); +}; + +/** + * @brief Create a receiver_t object. + * + * The receiver thread will start working, get data + * from the socket and add those packets to the job queue. + * + * @return + * - receiver_t object + * - NULL of thread could not be started + * + * @ingroup threads + */ +receiver_t * receiver_create(void); + +#endif /*RECEIVER_H_*/ diff --git a/src/charon/threads/scheduler.c b/src/charon/threads/scheduler.c new file mode 100644 index 000000000..47c5d6fb9 --- /dev/null +++ b/src/charon/threads/scheduler.c @@ -0,0 +1,124 @@ +/** + * @file scheduler.c + * + * @brief Implementation of scheduler_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 +#include + +#include "scheduler.h" + +#include +#include +#include +#include + + +typedef struct private_scheduler_t private_scheduler_t; + +/** + * Private data of a scheduler_t object. + */ +struct private_scheduler_t { + /** + * Public part of a scheduler_t object. + */ + scheduler_t public; + + /** + * @brief Get events from the event queue and add them to to job queue. + * + * Thread function started at creation of the scheduler object. + * + * @param this calling object + */ + void (*get_events) (private_scheduler_t *this); + + /** + * Assigned thread. + */ + pthread_t assigned_thread; + + /** + * A logger. + */ + logger_t *logger; +}; + +/** + * Implementation of private_scheduler_t.get_events. + */ +static void get_events(private_scheduler_t * this) +{ + job_t *current_job; + + /* cancellation disabled by default */ + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); + + this->logger->log(this->logger, CONTROL, "Scheduler thread running, thread_id %u", (int)pthread_self()); + + for (;;) + { + this->logger->log(this->logger, CONTROL|LEVEL2, "Waiting for next event..."); + /* get a job, this block until one is available */ + current_job = charon->event_queue->get(charon->event_queue); + /* queue the job in the job queue, workers will eat them */ + charon->job_queue->add(charon->job_queue, current_job); + this->logger->log(this->logger, CONTROL | LEVEL1, "Got event, added job %s to job-queue.", + mapping_find(job_type_m, current_job->get_type(current_job))); + } +} + +/** + * Implementation of scheduler_t.destroy. + */ +static void destroy(private_scheduler_t *this) +{ + this->logger->log(this->logger, CONTROL | LEVEL1, "Going to terminate scheduler thread"); + pthread_cancel(this->assigned_thread); + + pthread_join(this->assigned_thread, NULL); + this->logger->log(this->logger, CONTROL | LEVEL1, "Scheduler thread terminated"); + + free(this); +} + +/* + * Described in header. + */ +scheduler_t * scheduler_create() +{ + private_scheduler_t *this = malloc_thing(private_scheduler_t); + + this->public.destroy = (void(*)(scheduler_t*)) destroy; + this->get_events = get_events; + + this->logger = logger_manager->get_logger(logger_manager, SCHEDULER); + + if (pthread_create(&(this->assigned_thread), NULL, (void*(*)(void*))this->get_events, this) != 0) + { + /* thread could not be created */ + this->logger->log(this->logger, ERROR, "Scheduler thread could not be created!"); + free(this); + charon->kill(charon, "Unable to create scheduler thread"); + } + + return &(this->public); +} diff --git a/src/charon/threads/scheduler.h b/src/charon/threads/scheduler.h new file mode 100644 index 000000000..04d639d1b --- /dev/null +++ b/src/charon/threads/scheduler.h @@ -0,0 +1,67 @@ +/** + * @file scheduler.h + * + * @brief Interface of scheduler_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef SCHEDULER_H_ +#define SCHEDULER_H_ + +#include + +typedef struct scheduler_t scheduler_t; + +/** + * @brief The scheduler thread is responsible for timed events. + * + * The scheduler thread takes out jobs from the event-queue and adds them + * to the job-queue. + * + * Starts a thread which does the work, since event-queue is blocking. + * + * @b Constructors: + * - scheduler_create() + * + * @ingroup threads + */ +struct scheduler_t { + + /** + * @brief Destroys a scheduler object. + * + * @param scheduler calling object + */ + void (*destroy) (scheduler_t *scheduler); +}; + +/** + * @brief Create a scheduler with its associated thread. + * + * The thread will start to get jobs form the event queue + * and adds them to the job queue. + * + * @return + * - scheduler_t object + * - NULL if thread could not be started + * + * @ingroup threads + */ +scheduler_t * scheduler_create(void); + +#endif /*SCHEDULER_H_*/ diff --git a/src/charon/threads/sender.c b/src/charon/threads/sender.c new file mode 100644 index 000000000..42d11beb9 --- /dev/null +++ b/src/charon/threads/sender.c @@ -0,0 +1,126 @@ +/** + * @file sender.c + * + * @brief Implementation of sender_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 +#include + +#include "sender.h" + +#include +#include +#include +#include +#include + + +typedef struct private_sender_t private_sender_t; + +/** + * Private data of a sender_t object. + */ +struct private_sender_t { + /** + * Public part of a sender_t object. + */ + sender_t public; + + /** + * Assigned thread. + */ + pthread_t assigned_thread; + + /** + * @brief The thread function, sends out packets. + * + * @param this calling object + */ + void (*send_packets) (private_sender_t * this); + + /** + * A logger for this sender_t object. + */ + logger_t *logger; + +}; + +/** + * Implementation of private_sender_t.send_packets. + */ +static void send_packets(private_sender_t * this) +{ + packet_t * current_packet; + status_t status; + + /* cancellation disabled by default */ + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); + + this->logger->log(this->logger, CONTROL, "Sender thread running, thread_id %u", (int)pthread_self()); + + while (1) + { + current_packet = charon->send_queue->get(charon->send_queue); + this->logger->log(this->logger, CONTROL|LEVEL1, "Got a packet, sending it"); + status = charon->socket->send(charon->socket,current_packet); + if (status != SUCCESS) + { + this->logger->log(this->logger, ERROR, "Sending failed, socket returned %s", + mapping_find(status_m, status)); + } + current_packet->destroy(current_packet); + } +} + +/** + * Implementation of sender_t.destroy. + */ +static void destroy(private_sender_t *this) +{ + this->logger->log(this->logger, CONTROL | LEVEL1, "Going to terminate sender thread"); + pthread_cancel(this->assigned_thread); + + pthread_join(this->assigned_thread, NULL); + this->logger->log(this->logger, CONTROL | LEVEL1, "Sender thread terminated"); + + free(this); +} + +/* + * Described in header. + */ +sender_t * sender_create() +{ + private_sender_t *this = malloc_thing(private_sender_t); + + this->send_packets = send_packets; + this->public.destroy = (void(*)(sender_t*)) destroy; + + this->logger = logger_manager->get_logger(logger_manager, SENDER); + + if (pthread_create(&(this->assigned_thread), NULL, (void*(*)(void*))this->send_packets, this) != 0) + { + this->logger->log(this->logger, ERROR, "Sender thread could not be created"); + free(this); + charon->kill(charon, "Unable to create sender thread"); + } + + return &(this->public); +} diff --git a/src/charon/threads/sender.h b/src/charon/threads/sender.h new file mode 100644 index 000000000..2a41ccc66 --- /dev/null +++ b/src/charon/threads/sender.h @@ -0,0 +1,63 @@ +/** + * @file sender.h + * + * @brief Interface of sender_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef SENDER_H_ +#define SENDER_H_ + +#include + +typedef struct sender_t sender_t; + +/** + * @brief Thread responsible for sending packets over the socket. + * + * @b Constructors: + * - sender_create() + * + * @ingroup threads + */ +struct sender_t { + + /** + * @brief Destroys a sender object. + * + * @param sender calling object + */ + void (*destroy) (sender_t *sender); +}; + + +/** + * @brief Create the sender thread. + * + * The thread will start to work, getting packets + * from the send queue and sends them out. + * + * @return + * - sender_t object + * - NULL of thread could not be started + * + * @ingroup threads + */ +sender_t * sender_create(void); + +#endif /*SENDER_H_*/ diff --git a/src/charon/threads/stroke_interface.c b/src/charon/threads/stroke_interface.c new file mode 100755 index 000000000..a9c55673b --- /dev/null +++ b/src/charon/threads/stroke_interface.c @@ -0,0 +1,646 @@ +/** + * @file stroke.c + * + * @brief Implementation of stroke_t. + * + */ + +/* + * Copyright (C) 2006 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stroke_interface.h" + +#include +#include +#include +#include +#include + + +struct sockaddr_un socket_addr = { AF_UNIX, STROKE_SOCKET}; + + +typedef struct private_stroke_t private_stroke_t; + +/** + * Private data of an stroke_t object. + */ +struct private_stroke_t { + + /** + * Public part of stroke_t object. + */ + stroke_t public; + + /** + * Assigned logger_t object in charon. + */ + logger_t *logger; + + /** + * Logger which logs to stroke + */ + logger_t *stroke_logger; + + /** + * Unix socket to listen for strokes + */ + int socket; + + /** + * Thread which reads from the socket + */ + pthread_t assigned_thread; + + /** + * Read from the socket and handle stroke messages + */ + void (*stroke_receive) (private_stroke_t *this); +}; + +/** + * Helper function which corrects the string pointers + * in a stroke_msg_t. Strings in a stroke_msg sent over "wire" + * contains RELATIVE addresses (relative to the beginning of the + * stroke_msg). They must be corrected if they reach our address + * space... + */ +static void pop_string(stroke_msg_t *msg, char **string) +{ + /* check for sanity of string pointer and string */ + if (*string == NULL) + { + *string = ""; + } + else if (string < (char**)msg || + string > (char**)msg + sizeof(stroke_msg_t) || + *string < (char*)msg->buffer - (u_int)msg || + *string > (char*)(u_int)msg->length) + { + *string = "(invalid char* in stroke msg)"; + } + else + { + *string = (char*)msg + (u_int)*string; + } +} + +/** + * Add a connection to the configuration list + */ +static void stroke_add_conn(private_stroke_t *this, stroke_msg_t *msg) +{ + connection_t *connection; + policy_t *policy; + identification_t *my_id, *other_id; + host_t *my_host, *other_host, *my_subnet, *other_subnet; + proposal_t *proposal; + traffic_selector_t *my_ts, *other_ts; + x509_t *cert; + + pop_string(msg, &msg->add_conn.name); + pop_string(msg, &msg->add_conn.me.address); + pop_string(msg, &msg->add_conn.other.address); + pop_string(msg, &msg->add_conn.me.id); + pop_string(msg, &msg->add_conn.other.id); + pop_string(msg, &msg->add_conn.me.cert); + pop_string(msg, &msg->add_conn.other.cert); + pop_string(msg, &msg->add_conn.me.subnet); + pop_string(msg, &msg->add_conn.other.subnet); + + this->logger->log(this->logger, CONTROL, "received stroke: add connection \"%s\"", msg->add_conn.name); + + my_host = host_create(AF_INET, msg->add_conn.me.address, 500); + if (my_host == NULL) + { + this->stroke_logger->log(this->stroke_logger, ERROR, "invalid host: %s", msg->add_conn.me.address); + return; + } + other_host = host_create(AF_INET, msg->add_conn.other.address, 500); + if (other_host == NULL) + { + this->stroke_logger->log(this->stroke_logger, ERROR, "invalid host: %s", msg->add_conn.other.address); + my_host->destroy(my_host); + return; + } + my_id = identification_create_from_string(*msg->add_conn.me.id ? + msg->add_conn.me.id : msg->add_conn.me.address); + if (my_id == NULL) + { + this->stroke_logger->log(this->stroke_logger, ERROR, "invalid id: %s", msg->add_conn.me.id); + my_host->destroy(my_host); + other_host->destroy(other_host); + return; + } + other_id = identification_create_from_string(*msg->add_conn.other.id ? + msg->add_conn.other.id : msg->add_conn.other.address); + if (other_id == NULL) + { + my_host->destroy(my_host); + other_host->destroy(other_host); + my_id->destroy(my_id); + this->stroke_logger->log(this->stroke_logger, ERROR, "invalid id: %s", msg->add_conn.other.id); + return; + } + + my_subnet = host_create(AF_INET, *msg->add_conn.me.subnet ? msg->add_conn.me.subnet : msg->add_conn.me.address, 500); + if (my_subnet == NULL) + { + my_host->destroy(my_host); + other_host->destroy(other_host); + my_id->destroy(my_id); + other_id->destroy(other_id); + this->stroke_logger->log(this->stroke_logger, ERROR, "invalid subnet: %s", msg->add_conn.me.subnet); + return; + } + + other_subnet = host_create(AF_INET, *msg->add_conn.other.subnet ? msg->add_conn.other.subnet : msg->add_conn.other.address, 500); + if (other_subnet == NULL) + { + my_host->destroy(my_host); + other_host->destroy(other_host); + my_id->destroy(my_id); + other_id->destroy(other_id); + my_subnet->destroy(my_subnet); + this->stroke_logger->log(this->stroke_logger, ERROR, "invalid subnet: %s", msg->add_conn.me.subnet); + return; + } + + my_ts = traffic_selector_create_from_subnet(my_subnet, *msg->add_conn.me.subnet ? msg->add_conn.me.subnet_mask : 32); + my_subnet->destroy(my_subnet); + other_ts = traffic_selector_create_from_subnet(other_subnet, *msg->add_conn.other.subnet ? msg->add_conn.other.subnet_mask : 32); + other_subnet->destroy(other_subnet); + + if (charon->socket->is_listening_on(charon->socket, other_host)) + { + this->stroke_logger->log(this->stroke_logger, CONTROL|LEVEL1, "left is other host, switching"); + + host_t *tmp_host = my_host; + identification_t *tmp_id = my_id; + traffic_selector_t *tmp_ts = my_ts; + char *tmp_cert = msg->add_conn.me.cert; + + my_host = other_host; + other_host = tmp_host; + my_id = other_id; + other_id = tmp_id; + my_ts = other_ts; + other_ts = tmp_ts; + msg->add_conn.me.cert = msg->add_conn.other.cert; + msg->add_conn.other.cert = tmp_cert; + } + else if (charon->socket->is_listening_on(charon->socket, my_host)) + { + this->stroke_logger->log(this->stroke_logger, CONTROL|LEVEL1, "left is own host, not switching"); + } + else + { + this->stroke_logger->log(this->stroke_logger, ERROR, "left nor right host is our, aborting"); + + my_host->destroy(my_host); + other_host->destroy(other_host); + my_id->destroy(my_id); + other_id->destroy(other_id); + my_ts->destroy(my_ts); + other_ts->destroy(other_ts); + return; + } + + if (msg->add_conn.me.cert) + { + char file[128]; + snprintf(file, sizeof(file), "%s/%s", CERTIFICATE_DIR, msg->add_conn.me.cert); + cert = x509_create_from_file(file); + if (cert) + { + my_id->destroy(my_id); + my_id = cert->get_subject(cert); + my_id = my_id->clone(my_id); + cert->destroy(cert); + this->logger->log(this->logger, CONTROL, + "valid certificate with ID \"%s\"", + my_id->get_string(my_id)); + } + } + if (msg->add_conn.other.cert) + { + char file[128]; + snprintf(file, sizeof(file), "%s/%s", CERTIFICATE_DIR, msg->add_conn.other.cert); + cert = x509_create_from_file(file); + if (cert) + { + other_id->destroy(other_id); + other_id = cert->get_subject(cert); + other_id = other_id->clone(other_id); + cert->destroy(cert); + this->logger->log(this->logger, CONTROL, + "valid certificate with ID \"%s\"", + other_id->get_string(other_id)); + } + } + + connection = connection_create(msg->add_conn.name, + my_host, other_host, + my_id->clone(my_id), other_id->clone(other_id), + RSA_DIGITAL_SIGNATURE); + proposal = proposal_create(1); + proposal->add_algorithm(proposal, PROTO_IKE, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 16); + proposal->add_algorithm(proposal, PROTO_IKE, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0); + proposal->add_algorithm(proposal, PROTO_IKE, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0); + proposal->add_algorithm(proposal, PROTO_IKE, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_SHA1, 0); + proposal->add_algorithm(proposal, PROTO_IKE, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_MD5, 0); + proposal->add_algorithm(proposal, PROTO_IKE, DIFFIE_HELLMAN_GROUP, MODP_2048_BIT, 0); + proposal->add_algorithm(proposal, PROTO_IKE, DIFFIE_HELLMAN_GROUP, MODP_1536_BIT, 0); + proposal->add_algorithm(proposal, PROTO_IKE, DIFFIE_HELLMAN_GROUP, MODP_1024_BIT, 0); + proposal->add_algorithm(proposal, PROTO_IKE, DIFFIE_HELLMAN_GROUP, MODP_4096_BIT, 0); + proposal->add_algorithm(proposal, PROTO_IKE, DIFFIE_HELLMAN_GROUP, MODP_8192_BIT, 0); + connection->add_proposal(connection, proposal); + /* add to global connection list */ + charon->connections->add_connection(charon->connections, connection); + + policy = policy_create(my_id, other_id); + proposal = proposal_create(1); + proposal->add_algorithm(proposal, PROTO_ESP, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 16); + proposal->add_algorithm(proposal, PROTO_ESP, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0); + proposal->add_algorithm(proposal, PROTO_ESP, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0); + policy->add_proposal(policy, proposal); + policy->add_my_traffic_selector(policy, my_ts); + policy->add_other_traffic_selector(policy, other_ts); + /* add to global policy list */ + charon->policies->add_policy(charon->policies, policy); + + this->stroke_logger->log(this->stroke_logger, CONTROL|LEVEL1, "connection \"%s\" added", msg->add_conn.name); +} + +/** + * initiate a connection by name + */ +static void stroke_initiate(private_stroke_t *this, stroke_msg_t *msg) +{ + initiate_ike_sa_job_t *job; + connection_t *connection; + + pop_string(msg, &(msg->initiate.name)); + this->logger->log(this->logger, CONTROL, "received stroke: initiate \"%s\"", msg->initiate.name); + connection = charon->connections->get_connection_by_name(charon->connections, msg->initiate.name); + if (connection == NULL) + { + this->stroke_logger->log(this->stroke_logger, ERROR, "no connection named \"%s\"", msg->initiate.name); + } + else + { + job = initiate_ike_sa_job_create(connection); + charon->job_queue->add(charon->job_queue, (job_t*)job); + } +} + +/** + * terminate a connection by name + */ +static void stroke_terminate(private_stroke_t *this, stroke_msg_t *msg) +{ + linked_list_t *ike_sas; + iterator_t *iterator; + int instances = 0; + + pop_string(msg, &(msg->terminate.name)); + this->logger->log(this->logger, CONTROL, "received stroke: terminate \"%s\"", msg->terminate.name); + + ike_sas = charon->ike_sa_manager->get_ike_sa_list_by_name(charon->ike_sa_manager, msg->terminate.name); + + iterator = ike_sas->create_iterator(ike_sas, TRUE); + while (iterator->has_next(iterator)) + { + ike_sa_id_t *ike_sa_id; + iterator->current(iterator, (void**)&ike_sa_id); + charon->ike_sa_manager->delete(charon->ike_sa_manager, ike_sa_id); + ike_sa_id->destroy(ike_sa_id); + instances++; + } + iterator->destroy(iterator); + ike_sas->destroy(ike_sas); + this->stroke_logger->log(this->stroke_logger, CONTROL, "terminated %d instances of %s", instances, msg->terminate.name); +} + +/** + * show status of (established) connections + */ +static void stroke_status(private_stroke_t *this, stroke_msg_t *msg) +{ + if (msg->status.name) + { + pop_string(msg, &(msg->status.name)); + } + charon->ike_sa_manager->log_status(charon->ike_sa_manager, this->stroke_logger, msg->status.name); +} + +logger_context_t get_context(char *context) +{ + if (strcasecmp(context, "ALL") == 0) return ALL_LOGGERS; + else if (strcasecmp(context, "PARSR") == 0) return PARSER; + else if (strcasecmp(context, "GNRAT") == 0) return GENERATOR; + else if (strcasecmp(context, "IKESA") == 0) return IKE_SA; + else if (strcasecmp(context, "SAMGR") == 0) return IKE_SA_MANAGER; + else if (strcasecmp(context, "CHDSA") == 0) return CHILD_SA; + else if (strcasecmp(context, "MESSG") == 0) return MESSAGE; + else if (strcasecmp(context, "TPOOL") == 0) return THREAD_POOL; + else if (strcasecmp(context, "WORKR") == 0) return WORKER; + else if (strcasecmp(context, "SCHED") == 0) return SCHEDULER; + else if (strcasecmp(context, "SENDR") == 0) return SENDER; + else if (strcasecmp(context, "RECVR") == 0) return RECEIVER; + else if (strcasecmp(context, "SOCKT") == 0) return SOCKET; + else if (strcasecmp(context, "TESTR") == 0) return TESTER; + else if (strcasecmp(context, "DAEMN") == 0) return DAEMON; + else if (strcasecmp(context, "CONFG") == 0) return CONFIG; + else if (strcasecmp(context, "ENCPL") == 0) return ENCRYPTION_PAYLOAD; + else if (strcasecmp(context, "PAYLD") == 0) return PAYLOAD; + else return -2; +} + +/** + * set the type of logged messages in a context + */ +static void stroke_logtype(private_stroke_t *this, stroke_msg_t *msg) +{ + pop_string(msg, &(msg->logtype.context)); + pop_string(msg, &(msg->logtype.type)); + + this->logger->log(this->logger, CONTROL, "received stroke: logtype for %s", msg->logtype.context); + + log_level_t level; + logger_context_t context = get_context(msg->logtype.context); + if (context == -2) + { + this->stroke_logger->log(this->stroke_logger, ERROR, "invalid context (%s)!", msg->logtype.context); + return; + } + + if (strcasecmp(msg->logtype.type, "CONTROL") == 0) level = CONTROL; + else if (strcasecmp(msg->logtype.type, "ERROR") == 0) level = ERROR; + else if (strcasecmp(msg->logtype.type, "AUDIT") == 0) level = AUDIT; + else if (strcasecmp(msg->logtype.type, "RAW") == 0) level = RAW; + else if (strcasecmp(msg->logtype.type, "PRIVATE") == 0) level = PRIVATE; + else + { + this->stroke_logger->log(this->stroke_logger, ERROR, "invalid type (%s)!", msg->logtype.type); + return; + } + + if (msg->logtype.enable) + { + logger_manager->enable_log_level(logger_manager, context, level); + } + else + { + logger_manager->disable_log_level(logger_manager, context, level); + } +} + +/** + * set the verbosity of a logger + */ +static void stroke_loglevel(private_stroke_t *this, stroke_msg_t *msg) +{ + pop_string(msg, &(msg->loglevel.context)); + + this->logger->log(this->logger, CONTROL, "received stroke: loglevel for %s", msg->loglevel.context); + + log_level_t level; + logger_context_t context = get_context(msg->loglevel.context); + + if (context == -2) + { + this->stroke_logger->log(this->stroke_logger, ERROR, "invalid context (%s)!", msg->loglevel.context); + return; + } + + if (msg->loglevel.level == 0) + { + level = LEVEL0; + } + else if (msg->loglevel.level == 1) + { + level = LEVEL1; + } + else if (msg->loglevel.level == 2) + { + level = LEVEL2; + } + else if (msg->loglevel.level == 3) + { + level = LEVEL3; + } + else + { + this->stroke_logger->log(this->stroke_logger, ERROR, "invalid level (%d)!", msg->loglevel.level); + return; + } + + logger_manager->enable_log_level(logger_manager, context, level); +} + +/** + * Implementation of private_stroke_t.stroke_receive. + */ +static void stroke_receive(private_stroke_t *this) +{ + stroke_msg_t *msg; + u_int16_t msg_length; + struct sockaddr_un strokeaddr; + int strokeaddrlen = sizeof(strokeaddr); + ssize_t bytes_read; + int strokefd; + FILE *strokefile; + int oldstate; + + /* disable cancellation by default */ + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); + + while (1) + { + /* wait for connections, but allow thread to terminate */ + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); + strokefd = accept(this->socket, (struct sockaddr *)&strokeaddr, &strokeaddrlen); + pthread_setcancelstate(oldstate, NULL); + + if (strokefd < 0) + { + this->logger->log(this->logger, ERROR, "accepting stroke connection failed: %s", strerror(errno)); + continue; + } + + /* peek the length */ + bytes_read = recv(strokefd, &msg_length, sizeof(msg_length), MSG_PEEK); + if (bytes_read != sizeof(msg_length)) + { + this->logger->log(this->logger, ERROR, "reading lenght of stroke message failed"); + close(strokefd); + continue; + } + + /* read message */ + msg = malloc(msg_length); + bytes_read = recv(strokefd, msg, msg_length, 0); + if (bytes_read != msg_length) + { + this->logger->log(this->logger, ERROR, "reading stroke message failed: %s"); + close(strokefd); + continue; + } + + strokefile = fdopen(dup(strokefd), "w"); + if (strokefile == NULL) + { + this->logger->log(this->logger, ERROR, "opening stroke output channel failed:", strerror(errno)); + close(strokefd); + free(msg); + continue; + } + + /* setup a logger which writes status to the unix socket */ + this->stroke_logger = logger_create("-", CONTROL|ERROR, FALSE, strokefile); + + this->logger->log_bytes(this->logger, RAW, "stroke message", (void*)msg, msg_length); + + switch (msg->type) + { + case STR_INITIATE: + { + stroke_initiate(this, msg); + break; + } + case STR_TERMINATE: + { + stroke_terminate(this, msg); + break; + } + case STR_STATUS: + { + stroke_status(this, msg); + break; + } + case STR_STATUS_ALL: + { + this->stroke_logger->enable_level(this->stroke_logger, LEVEL1); + stroke_status(this, msg); + break; + } + case STR_ADD_CONN: + { + stroke_add_conn(this, msg); + break; + } + case STR_LOGTYPE: + { + stroke_logtype(this, msg); + break; + } + case STR_LOGLEVEL: + { + stroke_loglevel(this, msg); + break; + } + default: + this->logger->log(this->logger, ERROR, "received invalid stroke"); + } + this->stroke_logger->destroy(this->stroke_logger); + fclose(strokefile); + close(strokefd); + free(msg); + } +} + +/** + * Implementation of stroke_t.destroy. + */ +static void destroy(private_stroke_t *this) +{ + + pthread_cancel(this->assigned_thread); + pthread_join(this->assigned_thread, NULL); + + close(this->socket); + unlink(socket_addr.sun_path); + free(this); +} + + +/* + * Described in header-file + */ +stroke_t *stroke_create() +{ + private_stroke_t *this = malloc_thing(private_stroke_t); + mode_t old; + + /* public functions */ + this->public.destroy = (void (*)(stroke_t*))destroy; + + /* private functions */ + this->stroke_receive = stroke_receive; + + this->logger = logger_manager->get_logger(logger_manager, CONFIG); + + /* set up unix socket */ + this->socket = socket(AF_UNIX, SOCK_STREAM, 0); + if (this->socket == -1) + { + this->logger->log(this->logger, ERROR, "could not create whack socket"); + free(this); + return NULL; + } + + old = umask(~S_IRWXU); + if (bind(this->socket, (struct sockaddr *)&socket_addr, sizeof(socket_addr)) < 0) + { + this->logger->log(this->logger, ERROR, "could not bind stroke socket: %s", strerror(errno)); + close(this->socket); + free(this); + return NULL; + } + umask(old); + + if (listen(this->socket, 0) < 0) + { + this->logger->log(this->logger, ERROR, "could not listen on stroke socket: %s", strerror(errno)); + close(this->socket); + unlink(socket_addr.sun_path); + free(this); + return NULL; + } + + /* start a thread reading from the socket */ + if (pthread_create(&(this->assigned_thread), NULL, (void*(*)(void*))this->stroke_receive, this) != 0) + { + this->logger->log(this->logger, ERROR, "Could not spawn stroke thread"); + close(this->socket); + unlink(socket_addr.sun_path); + free(this); + return NULL; + } + + return (&this->public); +} diff --git a/src/charon/threads/stroke_interface.h b/src/charon/threads/stroke_interface.h new file mode 100644 index 000000000..16eb66533 --- /dev/null +++ b/src/charon/threads/stroke_interface.h @@ -0,0 +1,76 @@ +/** + * @file stroke.h + * + * @brief Interface of stroke_t. + * + */ + +/* + * Copyright (C) 2006 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef STROKE_INTERFACE_H_ +#define STROKE_INTERFACE_H_ + +#include +#include +#include + + +typedef struct stroke_t stroke_t; + +/** + * @brief Stroke is a configuration and control interface which + * allows other processes to modify charons behavior. + * + * stroke_t allows config manipulation (as whack in pluto). + * Messages of type stroke_msg_t's are sent over a unix socket + * (/var/run/charon.ctl). stroke_t implements the connections_t + * and the policies_t interface, which means it acts as a + * configuration backend for those too. stroke_t uses an own + * thread to read from the socket. + * + * @warning DO NOT cast stroke_t to any of the implemented interfaces! + * stroke_t implements multiple interfaces, so you must use + * stroke_t.interface_xy to access the specific interface! You have + * been warned... + * + * @todo Add clean thread cancellation + * + * @b Constructors: + * - stroke_create() + * + * @ingroup threads + */ +struct stroke_t { + + /** + * @brief Destroy a stroke_t instance. + * + * @param this stroke_t objec to destroy + */ + void (*destroy) (stroke_t *this); +}; + + +/** + * @brief Create the stroke interface and listen on the socket. + * + * @return stroke_t object + * + * @ingroup threads + */ +stroke_t *stroke_create(void); + +#endif /* STROKE_INTERFACE_H_ */ diff --git a/src/charon/threads/thread_pool.c b/src/charon/threads/thread_pool.c new file mode 100644 index 000000000..4482e795f --- /dev/null +++ b/src/charon/threads/thread_pool.c @@ -0,0 +1,623 @@ +/** + * @file thread_pool.c + * + * @brief Implementation of thread_pool_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT 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 +#include +#include +#include + +#include "thread_pool.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +typedef struct private_thread_pool_t private_thread_pool_t; + +/** + * @brief Private data of thread_pool_t class. + */ +struct private_thread_pool_t { + /** + * Public thread_pool_t interface. + */ + thread_pool_t public; + + /** + * @brief Main processing function for worker threads. + * + * Gets a job from the job queue and calls corresponding + * function for processing. + * + * @param this calling object + */ + void (*process_jobs) (private_thread_pool_t *this); + + /** + * @brief Process a INCOMING_PACKET job. + * + * @param this calling object + * @param job incoming_packet_job_t object + */ + void (*process_incoming_packet_job) (private_thread_pool_t *this, incoming_packet_job_t *job); + + /** + * @brief Process a INITIATE_IKE_SA job. + * + * @param this calling object + * @param job initiate_ike_sa_job_t object + */ + void (*process_initiate_ike_sa_job) (private_thread_pool_t *this, initiate_ike_sa_job_t *job); + + /** + * @brief Process a DELETE_HALF_OPEN_IKE_SA job. + * + * @param this calling object + * @param job delete__half_open_ike_sa_job_t object + */ + void (*process_delete_half_open_ike_sa_job) (private_thread_pool_t *this, delete_half_open_ike_sa_job_t *job); + + /** + * @brief Process a DELETE_ESTABLISHED_IKE_SA job. + * + * @param this calling object + * @param job delete_established_ike_sa_job_t object + */ + void (*process_delete_established_ike_sa_job) (private_thread_pool_t *this, delete_established_ike_sa_job_t *job); + + /** + * @brief Process a RETRANSMIT_REQUEST job. + * + * @param this calling object + * @param job retransmit_request_job_t object + */ + void (*process_retransmit_request_job) (private_thread_pool_t *this, retransmit_request_job_t *job); + + /** + * Creates a job of type DELETE_HALF_OPEN_IKE_SA. + * + * This job is used to delete IKE_SA's which are still in state INITIATOR_INIT, + * RESPONDER_INIT, IKE_AUTH_REQUESTED, IKE_INIT_REQUESTED or IKE_INIT_RESPONDED. + * + * @param ike_sa_id ID of IKE_SA to delete + * @param delay Delay in ms after a half open IKE_SA gets deleted! + */ + void (*create_delete_half_open_ike_sa_job) (private_thread_pool_t *this,ike_sa_id_t *ike_sa_id, u_int32_t delay); + + /** + * Number of running threads. + */ + size_t pool_size; + + /** + * Array of thread ids. + */ + pthread_t *threads; + + /** + * Logger of the thread pool. + */ + logger_t *pool_logger; + + /** + * Logger of the worker threads. + */ + logger_t *worker_logger; +} ; + +/** + * Implementation of private_thread_pool_t.process_jobs. + */ +static void process_jobs(private_thread_pool_t *this) +{ + job_t *job; + job_type_t job_type; + timeval_t start_time; + timeval_t end_time; + + /* cancellation disabled by default */ + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); + + this->worker_logger->log(this->worker_logger, CONTROL, "Worker thread running, thread_id: %u", (int)pthread_self()); + + for (;;) { + + job = charon->job_queue->get(charon->job_queue); + job_type = job->get_type(job); + this->worker_logger->log(this->worker_logger, CONTROL|LEVEL2, "Process job of type %s", + mapping_find(job_type_m,job_type)); + gettimeofday(&start_time,NULL); + switch (job_type) + { + case INCOMING_PACKET: + { + this->process_incoming_packet_job(this, (incoming_packet_job_t*)job); + job->destroy(job); + break; + } + case INITIATE_IKE_SA: + { + this->process_initiate_ike_sa_job(this, (initiate_ike_sa_job_t*)job); + job->destroy(job); + break; + } + case DELETE_HALF_OPEN_IKE_SA: + { + this->process_delete_half_open_ike_sa_job(this, (delete_half_open_ike_sa_job_t*)job); + job->destroy(job); + break; + } + case DELETE_ESTABLISHED_IKE_SA: + { + this->process_delete_established_ike_sa_job(this, (delete_established_ike_sa_job_t*)job); + job->destroy(job); + break; + } + case RETRANSMIT_REQUEST: + { + this->process_retransmit_request_job(this, (retransmit_request_job_t*)job); + break; + } + default: + { + this->worker_logger->log(this->worker_logger, ERROR, "Job of type %s not supported!", + mapping_find(job_type_m,job_type)); + job->destroy(job); + break; + } + } + gettimeofday(&end_time,NULL); + + this->worker_logger->log(this->worker_logger, CONTROL | LEVEL2, "Processed job of type %s in %d us", + mapping_find(job_type_m,job_type), + (((end_time.tv_sec - start_time.tv_sec) * 1000000) + (end_time.tv_usec - start_time.tv_usec))); + + + } +} + +/** + * Implementation of private_thread_pool_t.process_incoming_packet_job. + */ +static void process_incoming_packet_job(private_thread_pool_t *this, incoming_packet_job_t *job) +{ + packet_t *packet; + message_t *message; + ike_sa_t *ike_sa; + ike_sa_id_t *ike_sa_id; + status_t status; + + + packet = job->get_packet(job); + + message = message_create_from_packet(packet); + + status = message->parse_header(message); + if (status != SUCCESS) + { + this->worker_logger->log(this->worker_logger, ERROR, "Message header could not be verified!"); + message->destroy(message); + return; + } + + this->worker_logger->log(this->worker_logger, CONTROL|LEVEL2, "Message is a %s %s", + mapping_find(exchange_type_m, message->get_exchange_type(message)), + message->get_request(message) ? "request" : "reply"); + + if ((message->get_major_version(message) != IKE_MAJOR_VERSION) || + (message->get_minor_version(message) != IKE_MINOR_VERSION)) + { + this->worker_logger->log(this->worker_logger, ERROR | LEVEL2, "IKE version %d.%d not supported", + message->get_major_version(message), + message->get_minor_version(message)); + /* + * This check is not handled in state_t object of IKE_SA to increase speed. + */ + if ((message->get_exchange_type(message) == IKE_SA_INIT) && (message->get_request(message))) + { + message_t *response; + message->get_ike_sa_id(message, &ike_sa_id); + ike_sa_id->switch_initiator(ike_sa_id); + response = message_create_notify_reply(message->get_destination(message), + message->get_source(message), + IKE_SA_INIT, + FALSE,ike_sa_id,INVALID_MAJOR_VERSION); + message->destroy(message); + ike_sa_id->destroy(ike_sa_id); + status = response->generate(response, NULL, NULL, &packet); + if (status != SUCCESS) + { + this->worker_logger->log(this->worker_logger, ERROR, "Could not generate packet from message"); + response->destroy(response); + return; + } + this->worker_logger->log(this->worker_logger, ERROR, "Send notify reply of type INVALID_MAJOR_VERSION"); + charon->send_queue->add(charon->send_queue, packet); + response->destroy(response); + return; + } + message->destroy(message); + return; + } + + message->get_ike_sa_id(message, &ike_sa_id); + + ike_sa_id->switch_initiator(ike_sa_id); + + this->worker_logger->log(this->worker_logger, CONTROL|LEVEL3, "Checking out IKE SA %lld:%lld, role %s", + ike_sa_id->get_initiator_spi(ike_sa_id), + ike_sa_id->get_responder_spi(ike_sa_id), + ike_sa_id->is_initiator(ike_sa_id) ? "initiator" : "responder"); + + status = charon->ike_sa_manager->checkout(charon->ike_sa_manager,ike_sa_id, &ike_sa); + if ((status != SUCCESS) && (status != CREATED)) + { + this->worker_logger->log(this->worker_logger, ERROR, "IKE SA could not be checked out"); + ike_sa_id->destroy(ike_sa_id); + message->destroy(message); + + /* + * TODO send notify reply of type INVALID_IKE_SPI if SPI could not be found ? + */ + + return; + } + + if (status == CREATED) + { + this->worker_logger->log(this->worker_logger, CONTROL|LEVEL3, + "Create Job to delete half open IKE_SA."); + this->create_delete_half_open_ike_sa_job(this,ike_sa_id, + charon->configuration->get_half_open_ike_sa_timeout(charon->configuration)); + } + + status = ike_sa->process_message(ike_sa, message); + + this->worker_logger->log(this->worker_logger, CONTROL|LEVEL3, "%s IKE SA %lld:%lld, role %s", + (status == DELETE_ME) ? "Checkin and delete" : "Checkin", + ike_sa_id->get_initiator_spi(ike_sa_id), + ike_sa_id->get_responder_spi(ike_sa_id), + ike_sa_id->is_initiator(ike_sa_id) ? "initiator" : "responder"); + ike_sa_id->destroy(ike_sa_id); + + if (status == DELETE_ME) + { + status = charon->ike_sa_manager->checkin_and_delete(charon->ike_sa_manager, ike_sa); + } + else + { + status = charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + } + + if (status != SUCCESS) + { + this->worker_logger->log(this->worker_logger, ERROR, "Checkin of IKE SA failed!"); + } + message->destroy(message); +} + +/** + * Implementation of private_thread_pool_t.process_initiate_ike_sa_job. + */ +static void process_initiate_ike_sa_job(private_thread_pool_t *this, initiate_ike_sa_job_t *job) +{ + /* + * Initiatie an IKE_SA: + * - is defined by a name of a configuration + * - create an empty IKE_SA via manager + * - call initiate_connection on this sa + */ + ike_sa_t *ike_sa; + status_t status; + + + this->worker_logger->log(this->worker_logger, CONTROL|LEVEL2, "Creating and checking out IKE SA"); + charon->ike_sa_manager->create_and_checkout(charon->ike_sa_manager, &ike_sa); + + status = ike_sa->initiate_connection(ike_sa, job->get_connection(job)); + if (status != SUCCESS) + { + this->worker_logger->log(this->worker_logger, ERROR, "Initiation returned %s, going to delete IKE_SA.", + mapping_find(status_m, status)); + charon->ike_sa_manager->checkin_and_delete(charon->ike_sa_manager, ike_sa); + return; + } + + this->worker_logger->log(this->worker_logger, CONTROL|LEVEL3, "Create Job to delete half open IKE_SA."); + this->create_delete_half_open_ike_sa_job(this,ike_sa->get_id(ike_sa), + charon->configuration->get_half_open_ike_sa_timeout(charon->configuration)); + + this->worker_logger->log(this->worker_logger, CONTROL|LEVEL2, "Checking in IKE SA"); + status = charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + if (status != SUCCESS) + { + this->worker_logger->log(this->worker_logger, ERROR, "Could not checkin IKE_SA (%s)", + mapping_find(status_m, status)); + } +} + +/** + * Implementation of private_thread_pool_t.process_delete_ike_sa_job. + */ +static void process_delete_half_open_ike_sa_job(private_thread_pool_t *this, delete_half_open_ike_sa_job_t *job) +{ + ike_sa_id_t *ike_sa_id = job->get_ike_sa_id(job); + ike_sa_t *ike_sa; + status_t status; + status = charon->ike_sa_manager->checkout(charon->ike_sa_manager,ike_sa_id, &ike_sa); + if ((status != SUCCESS) && (status != CREATED)) + { + this->worker_logger->log(this->worker_logger, CONTROL | LEVEL3, "IKE SA seems to be allready deleted and so doesn't have to be deleted"); + return; + } + + + switch (ike_sa->get_state(ike_sa)) + { + case INITIATOR_INIT: + case RESPONDER_INIT: + case IKE_SA_INIT_REQUESTED: + case IKE_SA_INIT_RESPONDED: + case IKE_AUTH_REQUESTED: + { + /* IKE_SA is half open and gets deleted! */ + status = charon->ike_sa_manager->checkin_and_delete(charon->ike_sa_manager, ike_sa); + if (status != SUCCESS) + { + this->worker_logger->log(this->worker_logger, ERROR, "Could not checkin and delete checked out IKE_SA!"); + } + break; + } + default: + { + /* IKE_SA is established and so is not getting deleted! */ + status = charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + if (status != SUCCESS) + { + this->worker_logger->log(this->worker_logger, ERROR, "Could not checkin a checked out IKE_SA!"); + } + break; + } + } +} + +/** + * Implementation of private_thread_pool_t.process_delete_established_ike_sa_job. + */ +static void process_delete_established_ike_sa_job(private_thread_pool_t *this, delete_established_ike_sa_job_t *job) +{ + ike_sa_id_t *ike_sa_id = job->get_ike_sa_id(job); + ike_sa_t *ike_sa; + status_t status; + status = charon->ike_sa_manager->checkout(charon->ike_sa_manager,ike_sa_id, &ike_sa); + if ((status != SUCCESS) && (status != CREATED)) + { + this->worker_logger->log(this->worker_logger, CONTROL | LEVEL3, "IKE SA seems to be allready deleted and so doesn't have to be deleted"); + return; + } + + switch (ike_sa->get_state(ike_sa)) + { + case INITIATOR_INIT: + case RESPONDER_INIT: + case IKE_SA_INIT_REQUESTED: + case IKE_SA_INIT_RESPONDED: + case IKE_AUTH_REQUESTED: + { + break; + } + default: + { + this->worker_logger->log(this->worker_logger, CONTROL, "Send delete request for IKE_SA."); + ike_sa->send_delete_ike_sa_request(ike_sa); + break; + } + } + this->worker_logger->log(this->worker_logger, CONTROL, "Delete established IKE_SA."); + status = charon->ike_sa_manager->checkin_and_delete(charon->ike_sa_manager, ike_sa); + if (status != SUCCESS) + { + this->worker_logger->log(this->worker_logger, ERROR, "Could not checkin and delete checked out IKE_SA!"); + } +} + + +/** + * Implementation of private_thread_pool_t.process_retransmit_request_job. + */ +static void process_retransmit_request_job(private_thread_pool_t *this, retransmit_request_job_t *job) +{ + + ike_sa_id_t *ike_sa_id = job->get_ike_sa_id(job); + u_int32_t message_id = job->get_message_id(job); + bool stop_retransmitting = FALSE; + u_int32_t timeout; + ike_sa_t *ike_sa; + status_t status; + + this->worker_logger->log(this->worker_logger, CONTROL|LEVEL2, "Checking out IKE SA %lld:%lld, role %s", + ike_sa_id->get_initiator_spi(ike_sa_id), + ike_sa_id->get_responder_spi(ike_sa_id), + ike_sa_id->is_initiator(ike_sa_id) ? "initiator" : "responder"); + + status = charon->ike_sa_manager->checkout(charon->ike_sa_manager,ike_sa_id, &ike_sa); + if ((status != SUCCESS) && (status != CREATED)) + { + job->destroy(job); + this->worker_logger->log(this->worker_logger, ERROR, "IKE SA could not be checked out. Allready deleted?"); + return; + } + + status = ike_sa->retransmit_request(ike_sa, message_id); + + if (status != SUCCESS) + { + this->worker_logger->log(this->worker_logger, CONTROL | LEVEL3, "Message doesn't have to be retransmitted"); + stop_retransmitting = TRUE; + } + + this->worker_logger->log(this->worker_logger, CONTROL|LEVEL2, "Checkin IKE SA %lld:%lld, role %s", + ike_sa_id->get_initiator_spi(ike_sa_id), + ike_sa_id->get_responder_spi(ike_sa_id), + ike_sa_id->is_initiator(ike_sa_id) ? "initiator" : "responder"); + + status = charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + if (status != SUCCESS) + { + this->worker_logger->log(this->worker_logger, ERROR, "Checkin of IKE SA failed!"); + } + + if (stop_retransmitting) + { + job->destroy(job); + return; + } + + job->increase_retransmit_count(job); + status = charon->configuration->get_retransmit_timeout (charon->configuration,job->get_retransmit_count(job),&timeout); + if (status != SUCCESS) + { + this->worker_logger->log(this->worker_logger, CONTROL | LEVEL2, "Message will not be anymore retransmitted"); + job->destroy(job); + /* + * TODO delete IKE_SA ? + */ + return; + } + charon->event_queue->add_relative(charon->event_queue,(job_t *) job,timeout); +} + + + +/** + * Implementation of private_thread_pool_t.create_delete_half_open_ike_sa_job. + */ +static void create_delete_half_open_ike_sa_job(private_thread_pool_t *this,ike_sa_id_t *ike_sa_id, u_int32_t delay) +{ + job_t *delete_job; + + this->worker_logger->log(this->worker_logger, CONTROL | LEVEL2, "Going to create job to delete half open IKE_SA in %d ms", delay); + + delete_job = (job_t *) delete_half_open_ike_sa_job_create(ike_sa_id); + charon->event_queue->add_relative(charon->event_queue,delete_job, delay); +} + + +/** + * Implementation of thread_pool_t.get_pool_size. + */ +static size_t get_pool_size(private_thread_pool_t *this) +{ + return this->pool_size; +} + +/** + * Implementation of thread_pool_t.destroy. + */ +static void destroy(private_thread_pool_t *this) +{ + int current; + /* flag thread for termination */ + for (current = 0; current < this->pool_size; current++) { + this->pool_logger->log(this->pool_logger, CONTROL, "cancelling worker thread #%d", current+1); + pthread_cancel(this->threads[current]); + } + + /* wait for all threads */ + for (current = 0; current < this->pool_size; current++) { + if (pthread_join(this->threads[current], NULL) == 0) + { + this->pool_logger->log(this->pool_logger, CONTROL, "worker thread #%d terminated", current+1); + } + else + { + this->pool_logger->log(this->pool_logger, ERROR, "could not terminate worker thread #%d", current+1); + } + } + + /* free mem */ + free(this->threads); + free(this); +} + +/* + * Described in header. + */ +thread_pool_t *thread_pool_create(size_t pool_size) +{ + int current; + + private_thread_pool_t *this = malloc_thing(private_thread_pool_t); + + /* fill in public fields */ + this->public.destroy = (void(*)(thread_pool_t*))destroy; + this->public.get_pool_size = (size_t(*)(thread_pool_t*))get_pool_size; + + this->process_jobs = process_jobs; + this->process_initiate_ike_sa_job = process_initiate_ike_sa_job; + this->process_delete_half_open_ike_sa_job = process_delete_half_open_ike_sa_job; + this->process_delete_established_ike_sa_job = process_delete_established_ike_sa_job; + this->process_incoming_packet_job = process_incoming_packet_job; + this->process_retransmit_request_job = process_retransmit_request_job; + this->create_delete_half_open_ike_sa_job = create_delete_half_open_ike_sa_job; + + this->pool_size = pool_size; + + this->threads = malloc(sizeof(pthread_t) * pool_size); + + this->pool_logger = logger_manager->get_logger(logger_manager, THREAD_POOL); + + this->worker_logger = logger_manager->get_logger(logger_manager, WORKER); + + /* try to create as many threads as possible, up tu pool_size */ + for (current = 0; current < pool_size; current++) + { + if (pthread_create(&(this->threads[current]), NULL, (void*(*)(void*))this->process_jobs, this) == 0) + { + this->pool_logger->log(this->pool_logger, CONTROL, "Created worker thread #%d", current+1); + } + else + { + /* creation failed, is it the first one? */ + if (current == 0) + { + this->pool_logger->log(this->pool_logger, ERROR, "Could not create any thread"); + free(this->threads); + free(this); + return NULL; + } + /* not all threads could be created, but at least one :-/ */ + this->pool_logger->log(this->pool_logger, ERROR, "Could only create %d from requested %d threads!", current, pool_size); + + this->pool_size = current; + return (thread_pool_t*)this; + } + } + return (thread_pool_t*)this; +} diff --git a/src/charon/threads/thread_pool.h b/src/charon/threads/thread_pool.h new file mode 100644 index 000000000..b33be08e3 --- /dev/null +++ b/src/charon/threads/thread_pool.h @@ -0,0 +1,78 @@ +/** + * @file thread_pool.h + * + * @brief Interface of thread_pool_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef THREAD_POOL_H_ +#define THREAD_POOL_H_ + +#include + +#include + + +typedef struct thread_pool_t thread_pool_t; + +/** + * @brief A thread_pool consists of a pool of threads processing jobs from the job queue. + * + * Current implementation uses as many threads as specified in constructor. + * A more improved version would dynamically increase thread count if necessary. + * + * @b Constructors: + * - thread_pool_create() + * + * @todo Add support for dynamic thread handling + * + * @ingroup threads + */ +struct thread_pool_t { + /** + * @brief Return currently instanciated thread count. + * + * @param thread_pool calling object + * @return size of thread pool + */ + size_t (*get_pool_size) (thread_pool_t *thread_pool); + + /** + * @brief Destroy a thread_pool_t object. + * + * Sends cancellation request to all threads and AWAITS their termination. + * + * @param thread_pool calling object + */ + void (*destroy) (thread_pool_t *thread_pool); +}; + +/** + * @brief Create the thread pool using using pool_size of threads. + * + * @param pool_size desired pool size + * @return + * - thread_pool_t object if one ore more threads could be started, or + * - NULL if no threads could be created + * + * @ingroup threads + */ +thread_pool_t *thread_pool_create(size_t pool_size); + + +#endif /*THREAD_POOL_H_*/ -- cgit v1.2.3