diff options
Diffstat (limited to 'Source/charon/sa')
26 files changed, 0 insertions, 8314 deletions
diff --git a/Source/charon/sa/Makefile.sa b/Source/charon/sa/Makefile.sa deleted file mode 100644 index 825c19959..000000000 --- a/Source/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 <http://www.fsf.org/copyleft/gpl.txt>. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT 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/Source/charon/sa/authenticator.c b/Source/charon/sa/authenticator.c deleted file mode 100644 index 3aeb8795f..000000000 --- a/Source/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 <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include <string.h> - -#include "authenticator.h" - -#include <daemon.h> - -/** - * 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"), <msg octets>) */ - 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/Source/charon/sa/authenticator.h b/Source/charon/sa/authenticator.h deleted file mode 100644 index b6bc317ac..000000000 --- a/Source/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 <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 <types.h> -#include <sa/ike_sa.h> -#include <network/packet.h> -#include <encoding/payloads/auth_payload.h> -#include <encoding/payloads/id_payload.h> - - -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/Source/charon/sa/child_sa.c b/Source/charon/sa/child_sa.c deleted file mode 100644 index a678ea9b8..000000000 --- a/Source/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 <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include <netdb.h> - -#include "child_sa.h" - -#include <daemon.h> - - -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/Source/charon/sa/child_sa.h b/Source/charon/sa/child_sa.h deleted file mode 100644 index 6ccbff13f..000000000 --- a/Source/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 <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 <types.h> -#include <crypto/prf_plus.h> -#include <encoding/payloads/proposal_substructure.h> -#include <utils/logger.h> - -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/Source/charon/sa/ike_sa.c b/Source/charon/sa/ike_sa.c deleted file mode 100644 index 6322eb8e9..000000000 --- a/Source/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 <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ -#include <string.h> - -#include "ike_sa.h" - -#include <types.h> -#include <daemon.h> -#include <definitions.h> -#include <utils/linked_list.h> -#include <utils/logger_manager.h> -#include <utils/randomizer.h> -#include <crypto/diffie_hellman.h> -#include <crypto/prf_plus.h> -#include <crypto/crypters/crypter.h> -#include <encoding/payloads/sa_payload.h> -#include <encoding/payloads/nonce_payload.h> -#include <encoding/payloads/ke_payload.h> -#include <encoding/payloads/delete_payload.h> -#include <encoding/payloads/transform_substructure.h> -#include <encoding/payloads/transform_attribute.h> -#include <sa/states/initiator_init.h> -#include <sa/states/responder_init.h> -#include <queues/jobs/retransmit_request_job.h> -#include <queues/jobs/delete_established_ike_sa_job.h> - - - - -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/Source/charon/sa/ike_sa.h b/Source/charon/sa/ike_sa.h deleted file mode 100644 index c526c6347..000000000 --- a/Source/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 <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 <types.h> -#include <encoding/message.h> -#include <encoding/payloads/proposal_substructure.h> -#include <sa/ike_sa_id.h> -#include <sa/child_sa.h> -#include <sa/states/state.h> -#include <config/configuration.h> -#include <utils/logger.h> -#include <utils/randomizer.h> -#include <crypto/prfs/prf.h> -#include <crypto/crypters/crypter.h> -#include <crypto/signers/signer.h> -#include <config/connections/connection.h> -#include <config/policies/policy.h> -#include <utils/logger.h> - -/** - * 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/Source/charon/sa/ike_sa_id.c b/Source/charon/sa/ike_sa_id.c deleted file mode 100644 index bf3a05d11..000000000 --- a/Source/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 <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY 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/Source/charon/sa/ike_sa_id.h b/Source/charon/sa/ike_sa_id.h deleted file mode 100644 index 0f16f7637..000000000 --- a/Source/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 <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 <types.h> - - -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/Source/charon/sa/ike_sa_manager.c b/Source/charon/sa/ike_sa_manager.c deleted file mode 100644 index 01f3f5ad2..000000000 --- a/Source/charon/sa/ike_sa_manager.c +++ /dev/null @@ -1,812 +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 <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include <pthread.h> -#include <string.h> - -#include "ike_sa_manager.h" - -#include <daemon.h> -#include <sa/ike_sa_id.h> -#include <utils/logger.h> -#include <utils/logger_manager.h> -#include <utils/linked_list.h> - -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; - - /** - * Next SPI, needed for incremental creation of SPIs. - */ - u_int64_t next_spi; -}; - -/** - * 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) -{ - this->next_spi++; - if (this->next_spi == 0) { - /* TODO handle overflow, - * delete all SAs or so - */ - } - return this->next_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.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)); - - 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.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->next_spi = 0; - - return (ike_sa_manager_t*)this; -} diff --git a/Source/charon/sa/ike_sa_manager.h b/Source/charon/sa/ike_sa_manager.h deleted file mode 100644 index e2235b4b6..000000000 --- a/Source/charon/sa/ike_sa_manager.h +++ /dev/null @@ -1,185 +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 <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 <types.h> -#include <sa/ike_sa.h> -#include <utils/logger.h> - - -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 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(); - -#endif /*IKE_SA_MANAGER_H_*/ diff --git a/Source/charon/sa/states/Makefile.states b/Source/charon/sa/states/Makefile.states deleted file mode 100644 index a258ebef0..000000000 --- a/Source/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 <http://www.fsf.org/copyleft/gpl.txt>. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT 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/Source/charon/sa/states/ike_auth_requested.c b/Source/charon/sa/states/ike_auth_requested.c deleted file mode 100644 index 3d49f440f..000000000 --- a/Source/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 <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include <string.h> - -#include "ike_auth_requested.h" - -#include <daemon.h> -#include <encoding/payloads/ts_payload.h> -#include <encoding/payloads/sa_payload.h> -#include <encoding/payloads/id_payload.h> -#include <encoding/payloads/auth_payload.h> -#include <encoding/payloads/notify_payload.h> -#include <crypto/signers/signer.h> -#include <crypto/crypters/crypter.h> -#include <sa/states/ike_sa_established.h> -#include <sa/authenticator.h> -#include <sa/child_sa.h> - -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/Source/charon/sa/states/ike_auth_requested.h b/Source/charon/sa/states/ike_auth_requested.h deleted file mode 100644 index a8eef014c..000000000 --- a/Source/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 <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 <sa/states/state.h> -#include <sa/ike_sa.h> - - -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/Source/charon/sa/states/ike_sa_established.c b/Source/charon/sa/states/ike_sa_established.c deleted file mode 100644 index e91409f6a..000000000 --- a/Source/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 <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY 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 <daemon.h> -#include <encoding/payloads/delete_payload.h> - - -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/Source/charon/sa/states/ike_sa_established.h b/Source/charon/sa/states/ike_sa_established.h deleted file mode 100644 index 8477ad5bc..000000000 --- a/Source/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 <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 <sa/states/state.h> -#include <sa/ike_sa.h> - -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/Source/charon/sa/states/ike_sa_init_requested.c b/Source/charon/sa/states/ike_sa_init_requested.c deleted file mode 100644 index 311cdf0a0..000000000 --- a/Source/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 <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY 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 <daemon.h> -#include <encoding/payloads/sa_payload.h> -#include <encoding/payloads/ke_payload.h> -#include <encoding/payloads/nonce_payload.h> -#include <encoding/payloads/notify_payload.h> -#include <encoding/payloads/id_payload.h> -#include <encoding/payloads/auth_payload.h> -#include <encoding/payloads/ts_payload.h> -#include <crypto/diffie_hellman.h> -#include <sa/states/ike_auth_requested.h> -#include <sa/states/initiator_init.h> -#include <sa/authenticator.h> - - -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/Source/charon/sa/states/ike_sa_init_requested.h b/Source/charon/sa/states/ike_sa_init_requested.h deleted file mode 100644 index 0a43afad1..000000000 --- a/Source/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 <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 <types.h> -#include <sa/ike_sa.h> -#include <sa/states/state.h> -#include <crypto/diffie_hellman.h> - -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/Source/charon/sa/states/ike_sa_init_responded.c b/Source/charon/sa/states/ike_sa_init_responded.c deleted file mode 100644 index e40b0cf22..000000000 --- a/Source/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 <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include <string.h> - -#include "ike_sa_init_responded.h" - -#include <daemon.h> -#include <sa/authenticator.h> -#include <sa/child_sa.h> -#include <encoding/payloads/ts_payload.h> -#include <encoding/payloads/sa_payload.h> -#include <encoding/payloads/id_payload.h> -#include <encoding/payloads/auth_payload.h> -#include <encoding/payloads/notify_payload.h> -#include <crypto/signers/signer.h> -#include <crypto/crypters/crypter.h> -#include <sa/states/ike_sa_established.h> - - -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/Source/charon/sa/states/ike_sa_init_responded.h b/Source/charon/sa/states/ike_sa_init_responded.h deleted file mode 100644 index 43aecf26f..000000000 --- a/Source/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 <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 <sa/ike_sa.h> -#include <sa/states/state.h> - -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/Source/charon/sa/states/initiator_init.c b/Source/charon/sa/states/initiator_init.c deleted file mode 100644 index 35d15235d..000000000 --- a/Source/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 <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY 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 <daemon.h> -#include <sa/states/state.h> -#include <sa/states/ike_sa_init_requested.h> -#include <queues/jobs/retransmit_request_job.h> -#include <crypto/diffie_hellman.h> -#include <encoding/payloads/sa_payload.h> -#include <encoding/payloads/ke_payload.h> -#include <encoding/payloads/nonce_payload.h> - - -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/Source/charon/sa/states/initiator_init.h b/Source/charon/sa/states/initiator_init.h deleted file mode 100644 index 6b4940a73..000000000 --- a/Source/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 <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 <sa/ike_sa.h> -#include <sa/states/state.h> - - -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/Source/charon/sa/states/responder_init.c b/Source/charon/sa/states/responder_init.c deleted file mode 100644 index 10acf645c..000000000 --- a/Source/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 <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY 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 <daemon.h> -#include <sa/states/state.h> -#include <sa/states/ike_sa_init_responded.h> -#include <encoding/payloads/sa_payload.h> -#include <encoding/payloads/ke_payload.h> -#include <encoding/payloads/nonce_payload.h> -#include <encoding/payloads/notify_payload.h> -#include <crypto/diffie_hellman.h> - - -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/Source/charon/sa/states/responder_init.h b/Source/charon/sa/states/responder_init.h deleted file mode 100644 index c8ba73ea3..000000000 --- a/Source/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 <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 <sa/ike_sa.h> -#include <sa/states/state.h> - - -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/Source/charon/sa/states/state.c b/Source/charon/sa/states/state.c deleted file mode 100644 index 595f5abbb..000000000 --- a/Source/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 <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY 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/Source/charon/sa/states/state.h b/Source/charon/sa/states/state.h deleted file mode 100644 index c93068d35..000000000 --- a/Source/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 <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT 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 <definitions.h> -#include <types.h> -#include <encoding/message.h> - -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_*/ |