diff options
Diffstat (limited to 'Source/charon/sa')
-rw-r--r-- | Source/charon/sa/child_sa.c | 90 | ||||
-rw-r--r-- | Source/charon/sa/child_sa.h | 84 | ||||
-rw-r--r-- | Source/charon/sa/states/ike_auth_requested.c | 160 | ||||
-rw-r--r-- | Source/charon/sa/states/ike_sa_init_requested.c | 30 | ||||
-rw-r--r-- | Source/charon/sa/states/ike_sa_init_responded.c | 162 |
5 files changed, 370 insertions, 156 deletions
diff --git a/Source/charon/sa/child_sa.c b/Source/charon/sa/child_sa.c index 6754e8022..d6e6ce60d 100644 --- a/Source/charon/sa/child_sa.c +++ b/Source/charon/sa/child_sa.c @@ -59,20 +59,16 @@ struct private_child_sa_t { u_int32_t esp_spi; /** + * reqid used for this child_sa + */ + u_int32_t reqid; + + /** * CHILD_SAs own logger */ logger_t *logger; }; - -/** - * Implementation of child_sa_t.get_spi. - */ -static u_int32_t get_spi(private_child_sa_t *this) -{ - return 0; -} - /** * Implements child_sa_t.alloc */ @@ -244,7 +240,8 @@ static status_t install(private_child_sa_t *this, proposal_t *proposal, prf_plus src->get_address(src), dst->get_address(dst)); status = charon->kernel_interface->add_sa(charon->kernel_interface, src, dst, - spi, protocols[i], FALSE, + spi, protocols[i], + this->reqid, enc_algo, enc_key, int_algo, int_key, mine); /* clean up for next round */ @@ -262,6 +259,7 @@ static status_t install(private_child_sa_t *this, proposal_t *proposal, prf_plus return FAILED; } + } } return SUCCESS; @@ -292,6 +290,7 @@ static status_t add(private_child_sa_t *this, proposal_t *proposal, prf_plus_t * { return FAILED; } + return SUCCESS; } @@ -307,6 +306,73 @@ static status_t update(private_child_sa_t *this, proposal_t *proposal, prf_plus_ { return FAILED; } + + return SUCCESS; +} + +static status_t add_policy(private_child_sa_t *this, linked_list_t *my_ts, linked_list_t *other_ts) +{ + traffic_selector_t *local_ts, *remote_ts; + host_t *my_net, *other_net; + u_int8_t my_mask, other_mask; + int family; + chunk_t from_addr, to_addr; + u_int16_t from_port, to_port; + + my_ts->get_first(my_ts, (void**)&local_ts); + other_ts->get_first(other_ts, (void**)&remote_ts); + + + family = local_ts->get_type(local_ts) == TS_IPV4_ADDR_RANGE ? AF_INET : AF_INET6; + from_addr = local_ts->get_from_address(local_ts); + //to_addr = local_ts->get_to_address(local_ts); + from_port = local_ts->get_from_port(local_ts); + to_port = local_ts->get_to_port(local_ts); + if (from_port != to_port) + { + from_port = 0; + } + my_net = host_create_from_chunk(family, from_addr, from_port); + allocator_free_chunk(&from_addr); + my_mask = 16; + + family = remote_ts->get_type(remote_ts) == TS_IPV4_ADDR_RANGE ? AF_INET : AF_INET6; + from_addr = remote_ts->get_from_address(remote_ts); + //to_addr = remote_ts->get_to_address(remote_ts); + from_port = remote_ts->get_from_port(remote_ts); + to_port = remote_ts->get_to_port(remote_ts); + if (from_port != to_port) + { + from_port = 0; + } + other_net = host_create_from_chunk(family, from_addr, from_port); + allocator_free_chunk(&from_addr); + other_mask = 16; + + charon->kernel_interface->add_policy(charon->kernel_interface, + this->me, this->other, + my_net, other_net, + my_mask, other_mask, + XFRM_POLICY_OUT, + 0, this->ah_spi, this->esp_spi, + this->reqid); + + charon->kernel_interface->add_policy(charon->kernel_interface, + this->me, this->other, + other_net, my_net, + other_mask, my_mask, + XFRM_POLICY_IN, + 0, this->ah_spi, this->esp_spi, + this->reqid); + + charon->kernel_interface->add_policy(charon->kernel_interface, + this->me, this->other, + other_net, my_net, + other_mask, my_mask, + XFRM_POLICY_FWD, + 0, this->ah_spi, this->esp_spi, + this->reqid); + return SUCCESS; } @@ -324,13 +390,14 @@ static void destroy(private_child_sa_t *this) */ child_sa_t * child_sa_create(host_t *me, host_t* other) { + static u_int32_t reqid = 123; 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.add_policy = (status_t (*)(child_sa_t*, linked_list_t*,linked_list_t*))add_policy; this->public.destroy = (void(*)(child_sa_t*))destroy; /* private data */ @@ -339,6 +406,7 @@ child_sa_t * child_sa_create(host_t *me, host_t* other) this->other = other; this->ah_spi = 0; this->esp_spi = 0; + this->reqid = reqid++; return (&this->public); } diff --git a/Source/charon/sa/child_sa.h b/Source/charon/sa/child_sa.h index 260c4f29c..4316f262a 100644 --- a/Source/charon/sa/child_sa.h +++ b/Source/charon/sa/child_sa.h @@ -6,7 +6,7 @@ */ /* - * Copyright (C) 2005 Jan Hutter, Martin Willi + * Copyright (C) 2005 Martin Willi * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -31,31 +31,84 @@ typedef struct child_sa_t child_sa_t; /** - * @brief Represents a CHILD_SA between to hosts. + * @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 * * * @b Constructors: - * - child_sa_create + * - child_sa_create() * * @ingroup sa */ struct child_sa_t { /** - * @brief Returns the SPI value of this CHILD_SA. + * @brief Allocate SPIs for a given proposals. * - * AH and ESP are using 4 byte SPI values. - * - * @param this calling object - * @return 4 Byte SPI value + * 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 */ - u_int32_t (*get_spi) (child_sa_t *this); - - 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_policy) (child_sa_t *this, linked_list_t *my_ts, linked_list_t *other_ts); + /** * @brief Destroys a child_sa. * @@ -65,11 +118,12 @@ struct child_sa_t { }; /** - * @brief Constructor to create a new CHILD_SA. + * @brief Constructor to create a new child_sa_t. * - * @param protocol_id protocol id (AH or ESP) of CHILD_SA - * @param prf_plus prf_plus_t object use to derive shared secrets + * @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); diff --git a/Source/charon/sa/states/ike_auth_requested.c b/Source/charon/sa/states/ike_auth_requested.c index 328971579..41dfb2ce8 100644 --- a/Source/charon/sa/states/ike_auth_requested.c +++ b/Source/charon/sa/states/ike_auth_requested.c @@ -73,6 +73,21 @@ struct private_ike_auth_requested_t { 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; @@ -168,6 +183,8 @@ static status_t process_message(private_ike_auth_requested_t *this, message_t *i signer_t *signer = NULL; status_t status; host_t *my_host, *other_host; + chunk_t seed; + prf_plus_t *prf_plus; if (ike_auth_reply->get_exchange_type(ike_auth_reply) != IKE_AUTH) { @@ -291,10 +308,46 @@ static status_t process_message(private_ike_auth_requested_t *this, message_t *i { 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"); + } + 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"); + } + else + { + seed = allocator_alloc_as_chunk(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); + allocator_free_chunk(&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_policy(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 */ - my_host = this->ike_sa->get_my_host(this->ike_sa); other_host = this->ike_sa->get_other_host(this->ike_sa); this->logger->log(this->logger, AUDIT, "IKE_SA established between %s - %s, authenticated peer with %s", @@ -343,8 +396,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; - chunk_t seed; - prf_plus_t *prf_plus; /* get his selected proposal */ proposal_list = sa_payload->get_proposals(sa_payload); @@ -383,28 +434,9 @@ static status_t process_sa_payload(private_ike_auth_requested_t *this, sa_payloa this->logger->log(this->logger, AUDIT, "IKE_AUTH reply contained a not offered proposal. Deleting IKE_SA"); return DELETE_ME; } - - /* install child SAs for AH and esp */ - seed = allocator_alloc_as_chunk(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); - allocator_free_chunk(&seed); - 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); + /* apply proposal */ + this->proposal = proposal; return SUCCESS; } @@ -435,41 +467,36 @@ static status_t process_auth_payload(private_ike_auth_requested_t *this, auth_pa */ static status_t process_ts_payload(private_ike_auth_requested_t *this, bool ts_initiator, ts_payload_t *ts_payload) { - traffic_selector_t **ts_received, **ts_selected; - size_t ts_received_count, ts_selected_count; - status_t status = SUCCESS; + linked_list_t *ts_received, *ts_selected; + traffic_selector_t *ts; /* get ts form payload */ - ts_received_count = ts_payload->get_traffic_selectors(ts_payload, &ts_received); + ts_received = ts_payload->get_traffic_selectors(ts_payload); /* select ts depending on payload type */ if (ts_initiator) { - ts_selected_count = this->sa_config->select_traffic_selectors_initiator(this->sa_config, ts_received, ts_received_count, &ts_selected); + ts_selected = this->sa_config->select_my_traffic_selectors(this->sa_config, ts_received); + this->my_ts = ts_selected; } else { - ts_selected_count = this->sa_config->select_traffic_selectors_responder(this->sa_config, ts_received, ts_received_count, &ts_selected); + ts_selected = this->sa_config->select_other_traffic_selectors(this->sa_config, ts_received); + this->other_ts = ts_selected; } /* check if the responder selected valid proposals */ - if (ts_selected_count != ts_received_count) + 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_count--) + while (ts_received->remove_last(ts_received, (void**)&ts) == SUCCESS) { - traffic_selector_t *ts = *ts_received + ts_received_count; ts->destroy(ts); } - allocator_free(ts_received); - while(ts_selected_count--) - { - traffic_selector_t *ts = *ts_selected + ts_selected_count; - ts->destroy(ts); - } - allocator_free(ts_selected); - return status; + ts_received->destroy(ts_received); + + return SUCCESS; } /** @@ -552,6 +579,28 @@ static void destroy(private_ike_auth_requested_t *this) { 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); + } allocator_free(this); } /** @@ -561,7 +610,29 @@ 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_chunk(&(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); + } allocator_free(this); } @@ -591,6 +662,9 @@ 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->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_sa_init_requested.c b/Source/charon/sa/states/ike_sa_init_requested.c index 55f38883f..7f80c3477 100644 --- a/Source/charon/sa/states/ike_sa_init_requested.c +++ b/Source/charon/sa/states/ike_sa_init_requested.c @@ -543,22 +543,13 @@ static status_t build_sa_payload (private_ike_sa_init_requested_t *this, message */ static status_t build_tsi_payload (private_ike_sa_init_requested_t *this, message_t *request) { - traffic_selector_t **traffic_selectors; - size_t traffic_selectors_count; + linked_list_t *ts_list; ts_payload_t *ts_payload; sa_config_t *sa_config; sa_config = this->ike_sa->get_sa_config(this->ike_sa); - traffic_selectors_count = sa_config->get_traffic_selectors_initiator(sa_config,&traffic_selectors); - ts_payload = ts_payload_create_from_traffic_selectors(TRUE,traffic_selectors, traffic_selectors_count); - - /* cleanup traffic selectors */ - while(traffic_selectors_count--) - { - traffic_selector_t *ts = *traffic_selectors + traffic_selectors_count; - ts->destroy(ts); - } - allocator_free(traffic_selectors); + ts_list = sa_config->get_my_traffic_selectors(sa_config); + 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); @@ -571,22 +562,13 @@ static status_t build_tsi_payload (private_ike_sa_init_requested_t *this, messag */ static status_t build_tsr_payload (private_ike_sa_init_requested_t *this, message_t *request) { - traffic_selector_t **traffic_selectors; - size_t traffic_selectors_count; + linked_list_t *ts_list; ts_payload_t *ts_payload; sa_config_t *sa_config; sa_config = this->ike_sa->get_sa_config(this->ike_sa); - traffic_selectors_count = sa_config->get_traffic_selectors_responder(sa_config,&traffic_selectors); - ts_payload = ts_payload_create_from_traffic_selectors(FALSE,traffic_selectors, traffic_selectors_count); - - /* cleanup traffic selectors */ - while(traffic_selectors_count--) - { - traffic_selector_t *ts = *traffic_selectors + traffic_selectors_count; - ts->destroy(ts); - } - allocator_free(traffic_selectors); + ts_list = sa_config->get_other_traffic_selectors(sa_config); + 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); diff --git a/Source/charon/sa/states/ike_sa_init_responded.c b/Source/charon/sa/states/ike_sa_init_responded.c index 70baa5143..87e1318f2 100644 --- a/Source/charon/sa/states/ike_sa_init_responded.c +++ b/Source/charon/sa/states/ike_sa_init_responded.c @@ -79,6 +79,21 @@ struct private_ike_sa_init_responded_t { sa_config_t *sa_config; /** + * Proposal selected for 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; + + /** * Assigned logger. * * Is logger of ike_sa! @@ -157,8 +172,11 @@ static status_t process_message(private_ike_sa_init_responded_t *this, message_t signer_t *signer; status_t status; host_t *my_host, *other_host; - - + chunk_t seed; + prf_plus_t *prf_plus; + child_sa_t *child_sa; + + 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", @@ -313,7 +331,44 @@ static status_t process_message(private_ike_sa_init_responded_t *this, message_t return DELETE_ME; } - /* create new state */my_host = this->ike_sa->get_my_host(this->ike_sa); + /* install child SAs for AH and esp */ + if (!this->proposal) + { + 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"); + } + else + { + seed = allocator_alloc_as_chunk(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); + allocator_free_chunk(&seed); + + child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa), + this->ike_sa->get_other_host(this->ike_sa)); + + status = child_sa->add(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 = child_sa->add_policy(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, child_sa); + } + + /* create new state */ + my_host = this->ike_sa->get_my_host(this->ike_sa); other_host = this->ike_sa->get_other_host(this->ike_sa); this->logger->log(this->logger, AUDIT, "IKE_SA established between %s - %s, authenticated peer with %s", my_host->get_address(my_host), other_host->get_address(other_host), @@ -390,11 +445,6 @@ static status_t build_sa_payload(private_ike_sa_init_responded_t *this, sa_paylo proposal_t *proposal, *proposal_tmp; linked_list_t *proposal_list; sa_payload_t *sa_response; - child_sa_t *child_sa; - prf_plus_t *prf_plus; - chunk_t seed; - - /* TODO: child sa stuff */ /* get proposals from request */ proposal_list = request->get_proposals(request); @@ -425,30 +475,12 @@ static status_t build_sa_payload(private_ike_sa_init_responded_t *this, sa_paylo return DELETE_ME; } - /* 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); - 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); - allocator_free_chunk(&seed); - - 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); + /* apply proposal */ + this->proposal = proposal; /* 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; } @@ -462,8 +494,6 @@ static status_t build_auth_payload(private_ike_sa_init_responded_t *this, auth_p 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) @@ -474,7 +504,6 @@ static status_t build_auth_payload(private_ike_sa_init_responded_t *this, auth_p 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) @@ -483,7 +512,7 @@ static status_t build_auth_payload(private_ike_sa_init_responded_t *this, auth_p return DELETE_ME; } - + response->add_payload(response, (payload_t *)auth_reply); return SUCCESS; } @@ -493,47 +522,35 @@ static status_t build_auth_payload(private_ike_sa_init_responded_t *this, auth_p */ static status_t build_ts_payload(private_ike_sa_init_responded_t *this, bool ts_initiator, ts_payload_t *request, message_t* response) { - traffic_selector_t **ts_received, **ts_selected; - size_t ts_received_count, ts_selected_count; + 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_count = request->get_traffic_selectors(request, &ts_received); + ts_received = request->get_traffic_selectors(request); /* select ts depending on payload type */ if (ts_initiator) { - ts_selected_count = this->sa_config->select_traffic_selectors_initiator(this->sa_config, ts_received, ts_received_count, &ts_selected); + ts_selected = this->sa_config->select_other_traffic_selectors(this->sa_config, ts_received); + this->other_ts = ts_selected; } else { - ts_selected_count = this->sa_config->select_traffic_selectors_responder(this->sa_config, ts_received, ts_received_count, &ts_selected); - } - if(ts_selected_count == 0) - { - this->logger->log(this->logger, AUDIT, "IKE_AUH request did not contain any traffic selectors."); - ts_response = ts_payload_create(ts_initiator); - response->add_payload(response, (payload_t*)ts_response); - } - else - { - ts_response = ts_payload_create_from_traffic_selectors(ts_initiator, ts_selected, ts_selected_count); - response->add_payload(response, (payload_t*)ts_response); + ts_selected = this->sa_config->select_my_traffic_selectors(this->sa_config, 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_count--) - { - traffic_selector_t *ts = *ts_received + ts_received_count; - ts->destroy(ts); - } - allocator_free(ts_received); - while(ts_selected_count--) + while (ts_received->remove_last(ts_received, (void**)&ts) == SUCCESS) { - traffic_selector_t *ts = *ts_selected + ts_selected_count; ts->destroy(ts); } - allocator_free(ts_selected); + ts_received->destroy(ts_received); + return status; } @@ -577,16 +594,32 @@ static ike_sa_state_t get_state(private_ike_sa_init_responded_t *this) */ static void destroy(private_ike_sa_init_responded_t *this) { - this->logger->log(this->logger, CONTROL | LEVEL3, "Going to destroy ike_sa_init_responded_t state object"); - - this->logger->log(this->logger, CONTROL | LEVEL3, "Destroy received nonce"); allocator_free_chunk(&(this->received_nonce)); - this->logger->log(this->logger, CONTROL | LEVEL3, "Destroy sent nonce"); allocator_free_chunk(&(this->sent_nonce)); - this->logger->log(this->logger, CONTROL | LEVEL3, "Destroy IKE_SA_INIT response octets"); allocator_free_chunk(&(this->ike_sa_init_response_data)); - this->logger->log(this->logger, CONTROL | LEVEL3, "Destroy IKE_SA_INIT request octets"); allocator_free_chunk(&(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->proposal) + { + this->proposal->destroy(this->proposal); + } allocator_free(this); } @@ -616,6 +649,9 @@ ike_sa_init_responded_t *ike_sa_init_responded_create(protected_ike_sa_t *ike_sa 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->proposal = NULL; this->logger = this->ike_sa->get_logger(this->ike_sa); return &(this->public); |