aboutsummaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/charon/sa/child_sa.c50
-rw-r--r--Source/charon/sa/states/ike_auth_requested.c4
-rw-r--r--Source/charon/sa/states/ike_sa_init_responded.c109
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);