- proposal setup implementation begun
This commit is contained in:
+79
-11
@@ -58,21 +58,17 @@ 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);
|
||||
}
|
||||
|
||||
+69
-15
@@ -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);
|
||||
|
||||
@@ -72,6 +72,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
|
||||
*/
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -78,6 +78,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.
|
||||
*
|
||||
@@ -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--)
|
||||
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);
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user