diff options
Diffstat (limited to 'Source')
-rw-r--r-- | Source/charon/sa/child_sa.c | 50 | ||||
-rw-r--r-- | Source/charon/sa/states/ike_auth_requested.c | 4 | ||||
-rw-r--r-- | Source/charon/sa/states/ike_sa_init_responded.c | 109 |
3 files changed, 116 insertions, 47 deletions
diff --git a/Source/charon/sa/child_sa.c b/Source/charon/sa/child_sa.c index d6e6ce60d..2808cff7f 100644 --- a/Source/charon/sa/child_sa.c +++ b/Source/charon/sa/child_sa.c @@ -310,6 +310,32 @@ static status_t update(private_child_sa_t *this, proposal_t *proposal, prf_plus_ return SUCCESS; } +static u_int8_t get_mask(chunk_t start, chunk_t end) +{ + int byte, bit, mask = 0; + + if (start.len != end.len) + { + return 0; + } + for (byte = 0; byte < start.len; byte++) + { + for (bit = 7; bit >= 0; bit--) + { + if ((*(start.ptr + byte) | (1<<bit)) == + (*(end.ptr + byte) | (1<<bit))) + { + mask++; + } + else + { + return mask; + } + } + } + return start.len * 8; +} + 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; @@ -318,14 +344,14 @@ static status_t add_policy(private_child_sa_t *this, linked_list_t *my_ts, linke int family; chunk_t from_addr, to_addr; u_int16_t from_port, to_port; + status_t status; 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); + 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) @@ -333,12 +359,13 @@ static status_t add_policy(private_child_sa_t *this, linked_list_t *my_ts, linke from_port = 0; } my_net = host_create_from_chunk(family, from_addr, from_port); + my_mask = get_mask(from_addr, to_addr); allocator_free_chunk(&from_addr); - my_mask = 16; + allocator_free_chunk(&to_addr); 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); + 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) @@ -346,10 +373,11 @@ static status_t add_policy(private_child_sa_t *this, linked_list_t *my_ts, linke from_port = 0; } other_net = host_create_from_chunk(family, from_addr, from_port); + other_mask = get_mask(from_addr, to_addr); allocator_free_chunk(&from_addr); - other_mask = 16; + allocator_free_chunk(&to_addr); - charon->kernel_interface->add_policy(charon->kernel_interface, + status = charon->kernel_interface->add_policy(charon->kernel_interface, this->me, this->other, my_net, other_net, my_mask, other_mask, @@ -357,23 +385,23 @@ static status_t add_policy(private_child_sa_t *this, linked_list_t *my_ts, linke 0, this->ah_spi, this->esp_spi, this->reqid); - charon->kernel_interface->add_policy(charon->kernel_interface, - this->me, this->other, + status |= charon->kernel_interface->add_policy(charon->kernel_interface, + this->other, this->me, 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, + status |= charon->kernel_interface->add_policy(charon->kernel_interface, + this->other, this->me, other_net, my_net, other_mask, my_mask, XFRM_POLICY_FWD, 0, this->ah_spi, this->esp_spi, this->reqid); - return SUCCESS; + return status; } /** diff --git a/Source/charon/sa/states/ike_auth_requested.c b/Source/charon/sa/states/ike_auth_requested.c index 41dfb2ce8..35e4c24ff 100644 --- a/Source/charon/sa/states/ike_auth_requested.c +++ b/Source/charon/sa/states/ike_auth_requested.c @@ -288,12 +288,12 @@ static status_t process_message(private_ike_auth_requested_t *this, message_t *i { return status; } - status = this->process_sa_payload(this, sa_payload); + status = this->process_auth_payload(this, auth_payload,idr_payload); if (status != SUCCESS) { return status; } - status = this->process_auth_payload(this, auth_payload,idr_payload); + status = this->process_sa_payload(this, sa_payload); if (status != SUCCESS) { return status; diff --git a/Source/charon/sa/states/ike_sa_init_responded.c b/Source/charon/sa/states/ike_sa_init_responded.c index 87e1318f2..da0b0a7f6 100644 --- a/Source/charon/sa/states/ike_sa_init_responded.c +++ b/Source/charon/sa/states/ike_sa_init_responded.c @@ -79,9 +79,9 @@ struct private_ike_sa_init_responded_t { sa_config_t *sa_config; /** - * Proposal selected for CHILD_SA + * CHILD_SA, if set up */ - proposal_t *proposal; + child_sa_t *child_sa; /** * Traffic selectors applicable at our site @@ -155,6 +155,16 @@ struct private_ike_sa_init_responded_t { * - 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); }; /** @@ -172,9 +182,6 @@ 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) @@ -297,13 +304,13 @@ static status_t process_message(private_ike_sa_init_responded_t *this, message_t response->destroy(response); return status; } - status = this->build_sa_payload(this, sa_request, response); + status = this->build_auth_payload(this, auth_request,idi_request, idr_response,response); if (status != SUCCESS) { response->destroy(response); return status; } - status = this->build_auth_payload(this, auth_request,idi_request, idr_response,response); + status = this->build_sa_payload(this, sa_request, response); if (status != SUCCESS) { response->destroy(response); @@ -331,8 +338,8 @@ static status_t process_message(private_ike_sa_init_responded_t *this, message_t return DELETE_ME; } - /* install child SAs for AH and esp */ - if (!this->proposal) + /* install child SA policies */ + if (!this->child_sa) { this->logger->log(this->logger, CONTROL, "Proposal negotiation failed, no CHILD_SA built"); } @@ -342,29 +349,13 @@ static status_t process_message(private_ike_sa_init_responded_t *this, message_t } 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); + 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, child_sa); + this->ike_sa->add_child_sa(this->ike_sa, this->child_sa); } /* create new state */ @@ -376,7 +367,7 @@ static status_t process_message(private_ike_sa_init_responded_t *this, message_t 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; } @@ -445,6 +436,9 @@ 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; + chunk_t seed; + prf_plus_t *prf_plus; + status_t status; /* get proposals from request */ proposal_list = request->get_proposals(request); @@ -475,12 +469,28 @@ static status_t build_sa_payload(private_ike_sa_init_responded_t *this, sa_paylo return DELETE_ME; } - /* apply proposal */ - this->proposal = proposal; + /* set up child sa */ + 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); + + this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa), + this->ike_sa->get_other_host(this->ike_sa)); + + 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; } @@ -590,7 +600,7 @@ static ike_sa_state_t get_state(private_ike_sa_init_responded_t *this) } /** - * Implementation of state_t.get_state. + * Implementation of state_t.destroy. */ static void destroy(private_ike_sa_init_responded_t *this) { @@ -616,9 +626,39 @@ static void destroy(private_ike_sa_init_responded_t *this) } this->other_ts->destroy(this->other_ts); } - if (this->proposal) + if (this->child_sa) { - this->proposal->destroy(this->proposal); + this->child_sa->destroy(this->child_sa); + } + + allocator_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) +{ + allocator_free_chunk(&(this->received_nonce)); + allocator_free_chunk(&(this->sent_nonce)); + allocator_free_chunk(&(this->ike_sa_init_response_data)); + 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); } allocator_free(this); @@ -642,6 +682,7 @@ ike_sa_init_responded_t *ike_sa_init_responded_create(protected_ike_sa_t *ike_sa 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; @@ -651,7 +692,7 @@ ike_sa_init_responded_t *ike_sa_init_responded_create(protected_ike_sa_t *ike_sa this->ike_sa_init_request_data = ike_sa_init_request_data; this->my_ts = NULL; this->other_ts = NULL; - this->proposal = NULL; + this->child_sa = NULL; this->logger = this->ike_sa->get_logger(this->ike_sa); return &(this->public); |