diff options
-rw-r--r-- | Source/charon/ike_sa.c | 321 | ||||
-rw-r--r-- | Source/charon/ike_sa.h | 2 |
2 files changed, 309 insertions, 14 deletions
diff --git a/Source/charon/ike_sa.c b/Source/charon/ike_sa.c index b0aa70971..c398ec0a2 100644 --- a/Source/charon/ike_sa.c +++ b/Source/charon/ike_sa.c @@ -24,8 +24,16 @@ #include "ike_sa.h" #include "types.h" +#include "globals.h" #include "utils/allocator.h" #include "utils/linked_list.h" +#include "utils/logger_manager.h" +#include "utils/randomizer.h" +#include "payloads/sa_payload.h" +#include "payloads/nonce_payload.h" +#include "payloads/ke_payload.h" +#include "payloads/transform_substructure.h" +#include "payloads/transform_attribute.h" /** @@ -33,7 +41,7 @@ */ typedef enum ike_sa_state_e ike_sa_state_t; -enum ike_sa_state_e{ +enum ike_sa_state_e { /** * IKE_SA is is not in a state @@ -76,7 +84,10 @@ struct private_ike_sa_s { * Public part of a ike_sa_t object */ ike_sa_t public; - + + status_t (*build_sa_payload) (private_ike_sa_t *this, sa_payload_t **payload); + status_t (*build_nonce_payload) (private_ike_sa_t *this, nonce_payload_t **payload); + status_t (*build_ke_payload) (private_ike_sa_t *this, ke_payload_t **payload); /* Private values */ /** @@ -93,6 +104,23 @@ struct private_ike_sa_s { * Current state of the IKE_SA */ ike_sa_state_t current_state; + + /** + * is this IKE_SA the original initiator of this IKE_SA + */ + bool original_initiator; + + /** + * this SA's source for random data + */ + randomizer_t *randomizer; + + linked_list_t *sent_messages; + + /** + * a logger for this IKE_SA + */ + logger_t *logger; }; /** @@ -107,12 +135,72 @@ static status_t process_message (private_ike_sa_t *this, message_t *message) /** * @brief implements function process_configuration of private_ike_sa_t */ -static status_t process_configuration (private_ike_sa_t *this,configuration_t *configuration) +static status_t initialize_connection(private_ike_sa_t *this, configuration_t *configuration) { - /* - * @TODO Add configuration processing here - */ - return SUCCESS; + message_t *message; + payload_t *payload; + packet_t *packet; + status_t status; + + this->logger->log(this->logger, CONTROL, "initializing connection"); + + this->original_initiator = TRUE; + + message = message_create(); + + if (message == NULL) + { + return OUT_OF_RES; + } + + + message->set_exchange_type(message, IKE_SA_INIT); + message->set_original_initiator(message, this->original_initiator); + message->set_message_id(message, 0); + message->set_ike_sa_id(message, this->ike_sa_id); + message->set_request(message, TRUE); + + status = this->build_sa_payload(this, (sa_payload_t**)&payload); + if (status != SUCCESS) + { + message->destroy(message); + return status; + } + payload->set_next_type(payload, KEY_EXCHANGE); + message->add_payload(message, payload); + + status = this->build_ke_payload(this, (ke_payload_t**)&payload); + if (status != SUCCESS) + { + message->destroy(message); + return status; + } + payload->set_next_type(payload, NONCE); + message->add_payload(message, payload); + + status = this->build_nonce_payload(this, (nonce_payload_t**)&payload); + if (status != SUCCESS) + { + message->destroy(message); + return status; + } + payload->set_next_type(payload, NO_PAYLOAD); + message->add_payload(message, payload); + + status = message->generate(message, &packet); + if (status != SUCCESS) + { + message->destroy(message); + return status; + } + + global_send_queue->add(global_send_queue, packet); + + + message->destroy(message); + + + return OUT_OF_RES; } /** @@ -124,18 +212,203 @@ static ike_sa_id_t* get_id(private_ike_sa_t *this) } /** - * @brief implements function destroy of private_ike_sa_t + * implements private_ike_sa_t.build_sa_payload */ -static status_t destroy (private_ike_sa_t *this) +static status_t build_sa_payload(private_ike_sa_t *this, sa_payload_t **payload) { - if (this == NULL) + sa_payload_t *sa_payload; + proposal_substructure_t *proposal; + transform_substructure_t *transform; + transform_attribute_t *attribute; + + + this->logger->log(this->logger, CONTROL_MORE, "building sa payload"); + + sa_payload = sa_payload_create(); + if (sa_payload == NULL) { - return FAILED; + return OUT_OF_RES; } + + do + { /* no loop, just to break */ + proposal = proposal_substructure_create(); + if (proposal == NULL) + { + break; + } + sa_payload->add_proposal_substructure(sa_payload, proposal); + + /* + * Encryption Algorithm + */ + transform = transform_substructure_create(); + if (transform == NULL) + { + break; + } + proposal->add_transform_substructure(proposal, transform); + transform->set_is_last_transform(transform, FALSE); + transform->set_transform_type(transform, ENCRYPTION_ALGORITHM); + transform->set_transform_id(transform, ENCR_AES_CBC); + + attribute = transform_attribute_create(); + if (attribute == NULL) + { + break; + } + transform->add_transform_attribute(transform, attribute); + attribute->set_attribute_type(attribute, KEY_LENGTH); + attribute->set_value(attribute, 16); + + /* + * Pseudo-random Function + */ + transform = transform_substructure_create(); + if (transform == NULL) + { + break; + } + proposal->add_transform_substructure(proposal, transform); + transform->set_is_last_transform(transform, FALSE); + transform->set_transform_type(transform, PSEUDO_RANDOM_FUNCTION); + transform->set_transform_id(transform, PRF_HMAC_SHA1); + + attribute = transform_attribute_create(); + if (attribute == NULL) + { + break; + } + transform->add_transform_attribute(transform, attribute); + attribute->set_attribute_type(attribute, KEY_LENGTH); + attribute->set_value(attribute, 16); + + + /* + * Integrity Algorithm + */ + transform = transform_substructure_create(); + if (transform == NULL) + { + break; + } + proposal->add_transform_substructure(proposal, transform); + transform->set_is_last_transform(transform, FALSE); + transform->set_transform_type(transform, INTEGRITIY_ALGORITHM); + transform->set_transform_id(transform, AUTH_HMAC_SHA1_96); + + attribute = transform_attribute_create(); + if (attribute == NULL) + { + break; + } + transform->add_transform_attribute(transform, attribute); + attribute->set_attribute_type(attribute, KEY_LENGTH); + attribute->set_value(attribute, 16); + + + /* + * Diffie-Hellman Group + */ + transform = transform_substructure_create(); + if (transform == NULL) + { + break; + } + proposal->add_transform_substructure(proposal, transform); + transform->set_is_last_transform(transform, FALSE); + transform->set_transform_type(transform, DIFFIE_HELLMAN_GROUP); + transform->set_transform_id(transform, MODP_1024_BIT); + + *payload = sa_payload; + + return SUCCESS; + + } while(FALSE); + + return OUT_OF_RES; +} - this->ike_sa_id->destroy(this->ike_sa_id); +/** + * implements private_ike_sa_t.build_ke_payload + */ +static status_t build_ke_payload(private_ike_sa_t *this, ke_payload_t **payload) +{ + ke_payload_t *ke_payload; + chunk_t key_data; + + + this->logger->log(this->logger, CONTROL_MORE, "building ke payload"); + + key_data.ptr = "12345"; + key_data.len = strlen("12345"); + + + ke_payload = ke_payload_create(); + if (ke_payload == NULL) + { + return OUT_OF_RES; + } + ke_payload->set_dh_group_number(ke_payload, MODP_1024_BIT); + if (ke_payload->set_key_exchange_data(ke_payload, key_data) != SUCCESS) + { + ke_payload->destroy(ke_payload); + return OUT_OF_RES; + } + *payload = ke_payload; + return SUCCESS; +} + +/** + * implements private_ike_sa_t.build_nonce_payload + */ +static status_t build_nonce_payload(private_ike_sa_t *this, nonce_payload_t **payload) +{ + nonce_payload_t *nonce_payload; + chunk_t nonce; + + this->logger->log(this->logger, CONTROL_MORE, "building nonce payload"); + + if (this->randomizer->allocate_pseudo_random_bytes(this->randomizer, 16, &nonce) != SUCCESS) + { + return OUT_OF_RES; + } + + nonce_payload = nonce_payload_create(); + if (nonce_payload == NULL) + { + return OUT_OF_RES; + } + + nonce_payload->set_nonce(nonce_payload, nonce); + + *payload = nonce_payload; + + return SUCCESS; +} + +/** + * @brief implements function destroy of private_ike_sa_t + */ +static status_t destroy (private_ike_sa_t *this) +{ + linked_list_iterator_t *iterator; + this->child_sas->create_iterator(this->child_sas, &iterator, TRUE); + while (iterator->has_next(iterator)) + { + payload_t *payload; + iterator->current(iterator, (void**)&payload); + payload->destroy(payload); + } + iterator->destroy(iterator); this->child_sas->destroy(this->child_sas); + + this->ike_sa_id->destroy(this->ike_sa_id); + + this->randomizer->destroy(this->randomizer); + + global_logger_manager->destroy_logger(global_logger_manager, this->logger); allocator_free(this); @@ -156,9 +429,14 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id) /* Public functions */ this->public.process_message = (status_t(*)(ike_sa_t*, message_t*)) process_message; - this->public.process_configuration = (status_t(*)(ike_sa_t*, configuration_t*)) process_configuration; + this->public.initialize_connection = (status_t(*)(ike_sa_t*, configuration_t*)) initialize_connection; this->public.get_id = (ike_sa_id_t*(*)(ike_sa_t*)) get_id; this->public.destroy = (status_t(*)(ike_sa_t*))destroy; + + this->build_sa_payload = build_sa_payload; + this->build_ke_payload = build_ke_payload; + this->build_nonce_payload = build_nonce_payload; + /* initialize private fields */ @@ -175,6 +453,23 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id) allocator_free(this); return NULL; } + + this->randomizer = randomizer_create(); + if (this->randomizer == NULL) + { + this->child_sas->destroy(this->child_sas); + this->ike_sa_id->destroy(this->ike_sa_id); + allocator_free(this); + } + + this->logger = global_logger_manager->create_logger(global_logger_manager, IKE_SA, NULL); + if (this->logger == NULL) + { + this->randomizer->destroy(this->randomizer); + this->child_sas->destroy(this->child_sas); + this->ike_sa_id->destroy(this->ike_sa_id); + allocator_free(this); + } /* at creation time, IKE_SA isn't in a specific state */ this->current_state = NO_STATE; diff --git a/Source/charon/ike_sa.h b/Source/charon/ike_sa.h index b35601714..d9b3943ea 100644 --- a/Source/charon/ike_sa.h +++ b/Source/charon/ike_sa.h @@ -55,7 +55,7 @@ struct ike_sa_s { * @param[in] message message_t object to process * @return SUCCESSFUL if succeeded, FAILED otherwise */ - status_t (*process_configuration) (ike_sa_t *this,configuration_t *configuration); + status_t (*initialize_connection) (ike_sa_t *this,configuration_t *configuration); /** * @brief Get the id of the SA |