diff options
Diffstat (limited to 'Source/charon/sa')
-rw-r--r-- | Source/charon/sa/child_sa.c | 301 | ||||
-rw-r--r-- | Source/charon/sa/child_sa.h | 7 | ||||
-rw-r--r-- | Source/charon/sa/ike_sa.c | 25 | ||||
-rw-r--r-- | Source/charon/sa/ike_sa.h | 11 | ||||
-rw-r--r-- | Source/charon/sa/states/ike_auth_requested.c | 52 | ||||
-rw-r--r-- | Source/charon/sa/states/ike_auth_requested.h | 6 | ||||
-rw-r--r-- | Source/charon/sa/states/ike_sa_init_requested.c | 31 | ||||
-rw-r--r-- | Source/charon/sa/states/ike_sa_init_responded.c | 22 |
8 files changed, 381 insertions, 74 deletions
diff --git a/Source/charon/sa/child_sa.c b/Source/charon/sa/child_sa.c index 2c4624310..6754e8022 100644 --- a/Source/charon/sa/child_sa.c +++ b/Source/charon/sa/child_sa.c @@ -39,14 +39,29 @@ struct private_child_sa_t { child_sa_t public; /** - * CHILD_SAs own logger + * IP of this peer */ - logger_t *logger; + host_t *me; /** - * Protocols used in this SA + * IP of other peer */ - protocol_id_t protocols[2]; + host_t *other; + + /** + * Security parameter index for AH protocol, 0 if not used + */ + u_int32_t ah_spi; + + /** + * Security parameter index for ESP protocol, 0 if not used + */ + u_int32_t esp_spi; + + /** + * CHILD_SAs own logger + */ + logger_t *logger; }; @@ -59,65 +74,271 @@ static u_int32_t get_spi(private_child_sa_t *this) } /** - * Implementation of child_sa_t.destroy. + * Implements child_sa_t.alloc */ -static void destroy(private_child_sa_t *this) +static status_t alloc(private_child_sa_t *this, linked_list_t *proposals) { - charon->logger_manager->destroy_logger(charon->logger_manager, this->logger); - allocator_free(this); + 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 AH: + /* do we already have an spi for AH?*/ + if (this->ah_spi == 0) + { + /* nope, get one */ + status = charon->kernel_interface->get_spi( + charon->kernel_interface, + this->me, this->other, + AH, FALSE, + &(this->ah_spi)); + } + /* update proposal */ + proposal->set_spi(proposal, AH, (u_int64_t)this->ah_spi); + break; + case ESP: + /* do we already have an spi for ESP?*/ + if (this->esp_spi == 0) + { + /* nope, get one */ + status = charon->kernel_interface->get_spi( + charon->kernel_interface, + this->me, this->other, + ESP, FALSE, + &(this->esp_spi)); + } + /* update proposal */ + proposal->set_spi(proposal, ESP, (u_int64_t)this->esp_spi); + break; + default: + break; + } + if (status != SUCCESS) + { + iterator->destroy(iterator); + return FAILED; + } + } + } + iterator->destroy(iterator); + return SUCCESS; } -/* - * Described in header. - */ -child_sa_t * child_sa_create(proposal_t *proposal, prf_plus_t *prf_plus) +static status_t install(private_child_sa_t *this, proposal_t *proposal, prf_plus_t *prf_plus, bool mine) { - private_child_sa_t *this = allocator_alloc_thing(private_child_sa_t); + 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; - - /* public functions */ - this->public.get_spi = (u_int32_t(*)(child_sa_t*))get_spi; - this->public.destroy = (void(*)(child_sa_t*))destroy; - - /* private data */ - this->logger = charon->logger_manager->create_logger(charon->logger_manager, CHILD_SA, NULL); - proposal->get_protocols(proposal, this->protocols); - /* derive keys */ + /* 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 (this->protocols[i] != UNDEFINED_PROTOCOL_ID) + if (protocols[i] != UNDEFINED_PROTOCOL_ID) { - algorithm_t *algo; - chunk_t key; - /* get encryption key */ - if (proposal->get_algorithm(proposal, this->protocols[i], ENCRYPTION_ALGORITHM, &algo)) + /* 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] == AH) + { + spi = this->ah_spi; + } + else + { + spi = this->esp_spi; + } + } + else /* use proposals spi */ + { + spi = proposal->get_spi(proposal, protocols[i]); + } + + /* derive encryption key first */ + if (proposal->get_algorithm(proposal, protocols[i], ENCRYPTION_ALGORITHM, &algo)) { - this->logger->log(this->logger, CONTROL|LEVEL1, "%s: using %s %s, ", - mapping_find(protocol_id_m, this->protocols[i]), + 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, algo->algorithm)); + mapping_find(encryption_algorithm_m, enc_algo)); - prf_plus->allocate_bytes(prf_plus, algo->key_size, &key); - this->logger->log_chunk(this->logger, PRIVATE, "key:", &key); - allocator_free_chunk(&key); + /* 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; } - /* get integrity key */ - if (proposal->get_algorithm(proposal, this->protocols[i], INTEGRITY_ALGORITHM, &algo)) + /* derive integrity key */ + if (proposal->get_algorithm(proposal, protocols[i], INTEGRITY_ALGORITHM, &algo)) { - this->logger->log(this->logger, CONTROL|LEVEL1, "%s: using %s %s,", - mapping_find(protocol_id_m, this->protocols[i]), + 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)); - prf_plus->allocate_bytes(prf_plus, algo->key_size, &key); - this->logger->log_chunk(this->logger, PRIVATE, "key:", &key); - allocator_free_chunk(&key); + 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], FALSE, + enc_algo, enc_key, + int_algo, int_key, mine); + /* clean up for next round */ + if (enc_algo != ENCR_UNDEFINED) + { + allocator_free_chunk(&enc_key); } + if (int_algo != AUTH_UNDEFINED) + { + allocator_free_chunk(&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; +} + +/** + * Implementation of child_sa_t.destroy. + */ +static void destroy(private_child_sa_t *this) +{ + charon->logger_manager->destroy_logger(charon->logger_manager, this->logger); + allocator_free(this); +} + +/* + * Described in header. + */ +child_sa_t * child_sa_create(host_t *me, host_t* other) +{ + private_child_sa_t *this = allocator_alloc_thing(private_child_sa_t); + + /* public functions */ + this->public.get_spi = (u_int32_t(*)(child_sa_t*))get_spi; + 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.destroy = (void(*)(child_sa_t*))destroy; + + /* private data */ + this->logger = charon->logger_manager->create_logger(charon->logger_manager, CHILD_SA, NULL); + this->me = me; + this->other = other; + this->ah_spi = 0; + this->esp_spi = 0; return (&this->public); } diff --git a/Source/charon/sa/child_sa.h b/Source/charon/sa/child_sa.h index bde032b74..260c4f29c 100644 --- a/Source/charon/sa/child_sa.h +++ b/Source/charon/sa/child_sa.h @@ -50,6 +50,11 @@ struct child_sa_t { * @return 4 Byte SPI value */ u_int32_t (*get_spi) (child_sa_t *this); + + + status_t (*alloc)(child_sa_t *this, linked_list_t* proposals); + status_t (*add)(child_sa_t *this, proposal_t *proposal, prf_plus_t *prf_plus); + status_t (*update)(child_sa_t *this, proposal_t *proposal, prf_plus_t *prf_plus); /** * @brief Destroys a child_sa. @@ -67,6 +72,6 @@ struct child_sa_t { * @return child_sa_t object * @ingroup sa */ -child_sa_t * child_sa_create(proposal_t *proposal, prf_plus_t *prf_plus); +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 index ac617faef..55c03ef92 100644 --- a/Source/charon/sa/ike_sa.c +++ b/Source/charon/sa/ike_sa.c @@ -417,7 +417,7 @@ status_t retransmit_request (private_ike_sa_t *this, u_int32_t message_id) */ static void set_new_state (private_ike_sa_t *this, state_t *state) { - this->logger->log(this->logger, CONTROL, "Change current state %s to %s", + 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; @@ -964,6 +964,14 @@ static ike_sa_state_t get_state (private_ike_sa_t *this) } /** + * 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) @@ -1008,21 +1016,17 @@ static void create_delete_established_ike_sa_job (private_ike_sa_t *this,u_int32 */ 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"); /* destroy child sa's */ - this->logger->log(this->logger, CONTROL | LEVEL3, "Destroy all child_sa's"); - while (this->child_sas->get_count(this->child_sas) > 0) + while (this->child_sas->remove_last(this->child_sas, (void**)&child_sa) == SUCCESS) { - void *child_sa; - if (this->child_sas->remove_first(this->child_sas, &child_sa) != SUCCESS) - { - break; - } - /* destroy child sa */ + child_sa->destroy(child_sa); } this->child_sas->destroy(this->child_sas); @@ -1134,7 +1138,8 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id) 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.get_logger = (logger_t *(*) (protected_ike_sa_t *)) get_logger; + this->protected.add_child_sa = (void (*) (protected_ike_sa_t*,child_sa_t*)) add_child_sa; + this->protected.get_logger = (logger_t *(*) (protected_ike_sa_t *)) get_logger; this->protected.set_init_config = (void (*) (protected_ike_sa_t *,init_config_t *)) set_init_config; this->protected.get_init_config = (init_config_t *(*) (protected_ike_sa_t *)) get_init_config; this->protected.set_sa_config = (void (*) (protected_ike_sa_t *,sa_config_t *)) set_sa_config; diff --git a/Source/charon/sa/ike_sa.h b/Source/charon/sa/ike_sa.h index f5591a00b..b15a8eaab 100644 --- a/Source/charon/sa/ike_sa.h +++ b/Source/charon/sa/ike_sa.h @@ -27,10 +27,11 @@ #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_manager.h> #include <utils/logger.h> #include <utils/randomizer.h> -#include <sa/states/state.h> #include <transforms/prfs/prf.h> #include <transforms/crypters/crypter.h> #include <transforms/signers/signer.h> @@ -388,6 +389,14 @@ struct protected_ike_sa_t { 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 diff --git a/Source/charon/sa/states/ike_auth_requested.c b/Source/charon/sa/states/ike_auth_requested.c index e6559319c..328971579 100644 --- a/Source/charon/sa/states/ike_auth_requested.c +++ b/Source/charon/sa/states/ike_auth_requested.c @@ -71,6 +71,11 @@ struct private_ike_auth_requested_t { * IKE_SA_INIT-Request in binary form. */ chunk_t ike_sa_init_reply_data; + + /** + * Child sa created in ike_sa_init_requested + */ + child_sa_t *child_sa; /** * Assigned Logger. @@ -136,6 +141,16 @@ struct private_ike_auth_requested_t { * - 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); }; @@ -288,7 +303,7 @@ static status_t process_message(private_ike_auth_requested_t *this, message_t *i this->ike_sa->create_delete_established_ike_sa_job(this->ike_sa,this->sa_config->get_ike_sa_lifetime(this->sa_config)); this->ike_sa->set_new_state(this->ike_sa, (state_t*)ike_sa_established_create(this->ike_sa)); - this->public.state_interface.destroy(&(this->public.state_interface)); + this->destroy_after_state_change(this); return SUCCESS; } @@ -328,7 +343,6 @@ static status_t process_sa_payload(private_ike_auth_requested_t *this, sa_payloa { proposal_t *proposal, *proposal_tmp; linked_list_t *proposal_list; - child_sa_t *child_sa; chunk_t seed; prf_plus_t *prf_plus; @@ -377,10 +391,19 @@ static status_t process_sa_payload(private_ike_auth_requested_t *this, sa_payloa prf_plus = prf_plus_create(this->ike_sa->get_child_prf(this->ike_sa), seed); allocator_free_chunk(&seed); - child_sa = child_sa_create(proposal, prf_plus); - prf_plus->destroy(prf_plus); - child_sa->destroy(child_sa); + if (this->child_sa) + { + if (this->child_sa->update(this->child_sa, proposal, prf_plus) != SUCCESS) + { + this->logger->log(this->logger, AUDIT, "Could not install CHILD_SA! Deleting IKE_SA"); + prf_plus->destroy(prf_plus); + proposal->destroy(proposal); + return DELETE_ME; + } + this->ike_sa->add_child_sa(this->ike_sa, this->child_sa); + } + prf_plus->destroy(prf_plus); proposal->destroy(proposal); return SUCCESS; @@ -524,6 +547,20 @@ static void destroy(private_ike_auth_requested_t *this) { allocator_free_chunk(&(this->received_nonce)); allocator_free_chunk(&(this->sent_nonce)); + allocator_free_chunk(&(this->ike_sa_init_reply_data)); + if (this->child_sa) + { + this->child_sa->destroy(this->child_sa); + } + allocator_free(this); +} +/** + * Implements protected_ike_sa_t.destroy_after_state_change + */ +static void destroy_after_state_change(private_ike_auth_requested_t *this) +{ + allocator_free_chunk(&(this->received_nonce)); + allocator_free_chunk(&(this->sent_nonce)); allocator_free_chunk(&(this->ike_sa_init_reply_data)); allocator_free(this); } @@ -531,7 +568,7 @@ static void destroy(private_ike_auth_requested_t *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) +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 = allocator_alloc_thing(private_ike_auth_requested_t); @@ -541,12 +578,12 @@ ike_auth_requested_t *ike_auth_requested_create(protected_ike_sa_t *ike_sa,chunk 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; @@ -554,6 +591,7 @@ ike_auth_requested_t *ike_auth_requested_create(protected_ike_sa_t *ike_sa,chunk this->sent_nonce = sent_nonce; this->ike_sa_init_reply_data = ike_sa_init_reply_data; this->logger = this->ike_sa->get_logger(this->ike_sa); + 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 index 34b948856..a8eef014c 100644 --- a/Source/charon/sa/states/ike_auth_requested.h +++ b/Source/charon/sa/states/ike_auth_requested.h @@ -41,8 +41,6 @@ typedef struct ike_auth_requested_t ike_auth_requested_t; * * @todo handle certificate payloads * - * @todo setup child SAs, if requested - * * @ingroup states */ struct ike_auth_requested_t { @@ -60,6 +58,7 @@ struct ike_auth_requested_t { * @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 @@ -67,6 +66,7 @@ struct ike_auth_requested_t { 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); + 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_init_requested.c b/Source/charon/sa/states/ike_sa_init_requested.c index 327eb2d7c..55f38883f 100644 --- a/Source/charon/sa/states/ike_sa_init_requested.c +++ b/Source/charon/sa/states/ike_sa_init_requested.c @@ -80,6 +80,11 @@ struct private_ike_sa_init_requested_t { chunk_t ike_sa_init_request_data; /** + * Created child sa, if any + */ + child_sa_t *child_sa; + + /** * Assigned logger * * Is logger of ike_sa! @@ -187,8 +192,6 @@ struct private_ike_sa_init_requested_t { * Destroy function called internally of this class after state change to * state IKE_AUTH_REQUESTED succeeded. * - * In case of state change to INITIATOR_INIT the default destroy function gets called. - * * This destroy function does not destroy objects which were passed to the new state. * * @param this calling object @@ -383,7 +386,8 @@ static status_t process_message(private_ike_sa_init_requested_t *this, message_t 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); + 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); @@ -512,10 +516,22 @@ static status_t build_sa_payload (private_ike_sa_init_requested_t *this, message /* get proposals form config, add to payload */ sa_config = this->ike_sa->get_sa_config(this->ike_sa); proposal_list = sa_config->get_proposals(sa_config); + /* build child sa */ + this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa), + this->ike_sa->get_other_host(this->ike_sa)); + 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; + } + + /* TODO: + * Huston, we've got a problem here. Since SPIs are stored in + * the proposal, and these proposals are shared across configs, + * there may be some threading issues... fix it! + */ sa_payload = sa_payload_create_from_proposal_list(proposal_list); - /* TODO child sa stuff */ - this->logger->log(this->logger, CONTROL|LEVEL2, "Add SA payload to message"); request->add_payload(request,(payload_t *) sa_payload); @@ -705,6 +721,10 @@ static void destroy(private_ike_sa_init_requested_t *this) allocator_free(this->sent_nonce.ptr); allocator_free(this->received_nonce.ptr); allocator_free_chunk(&(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); @@ -743,6 +763,7 @@ ike_sa_init_requested_t *ike_sa_init_requested_create(protected_ike_sa_t *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_responded.c b/Source/charon/sa/states/ike_sa_init_responded.c index 536041d0d..70baa5143 100644 --- a/Source/charon/sa/states/ike_sa_init_responded.c +++ b/Source/charon/sa/states/ike_sa_init_responded.c @@ -425,10 +425,6 @@ static status_t build_sa_payload(private_ike_sa_init_responded_t *this, sa_paylo return DELETE_ME; } - /* create payload with selected propsal */ - sa_response = sa_payload_create_from_proposal(proposal); - response->add_payload(response, (payload_t*)sa_response); - /* install child SAs for AH and esp */ seed = allocator_alloc_as_chunk(this->received_nonce.len + this->sent_nonce.len); memcpy(seed.ptr, this->received_nonce.ptr, this->received_nonce.len); @@ -436,10 +432,22 @@ static status_t build_sa_payload(private_ike_sa_init_responded_t *this, sa_paylo prf_plus = prf_plus_create(this->ike_sa->get_child_prf(this->ike_sa), seed); allocator_free_chunk(&seed); - child_sa = child_sa_create(proposal, prf_plus); - prf_plus->destroy(prf_plus); - child_sa->destroy(child_sa); + child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa), + this->ike_sa->get_other_host(this->ike_sa)); + if (child_sa->add(child_sa, proposal, prf_plus) != SUCCESS) + { + this->logger->log(this->logger, AUDIT, "Could not install CHILD_SA! Deleting IKE_SA"); + prf_plus->destroy(prf_plus); + proposal->destroy(proposal); + return DELETE_ME; + } + this->ike_sa->add_child_sa(this->ike_sa, child_sa); + + /* create payload with selected propsal */ + sa_response = sa_payload_create_from_proposal(proposal); + response->add_payload(response, (payload_t*)sa_response); + prf_plus->destroy(prf_plus); proposal->destroy(proposal); return SUCCESS; } |