fixed compile warnings when using -Wall
further CHILD_SA rekeying work done: creation of a new CHILD_SA on a expire from a kernel works delete of old CHILD_SA still missing some issues when both initiate rekeing
This commit is contained in:
@@ -20,9 +20,13 @@
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "create_child_sa_requested.h"
|
||||
|
||||
#include <sa/child_sa.h>
|
||||
#include <sa/states/delete_ike_sa_requested.h>
|
||||
#include <sa/states/ike_sa_established.h>
|
||||
#include <encoding/payloads/ts_payload.h>
|
||||
#include <encoding/payloads/sa_payload.h>
|
||||
#include <encoding/payloads/nonce_payload.h>
|
||||
@@ -56,6 +60,31 @@ struct private_create_child_sa_requested_t {
|
||||
*/
|
||||
chunk_t nonce_r;
|
||||
|
||||
/**
|
||||
* Policy to use for new child_sa
|
||||
*/
|
||||
policy_t *policy;
|
||||
|
||||
/**
|
||||
* Proposal negotiated
|
||||
*/
|
||||
proposal_t *proposal;
|
||||
|
||||
/**
|
||||
* Negotiated list of traffic selectors for local site
|
||||
*/
|
||||
linked_list_t *my_ts;
|
||||
|
||||
/**
|
||||
* Negotiated list of traffic selectors for remote site
|
||||
*/
|
||||
linked_list_t *other_ts;
|
||||
|
||||
/**
|
||||
* Child SA to create
|
||||
*/
|
||||
child_sa_t *child_sa;
|
||||
|
||||
/**
|
||||
* Assigned logger.
|
||||
*
|
||||
@@ -65,11 +94,277 @@ struct private_create_child_sa_requested_t {
|
||||
};
|
||||
|
||||
/**
|
||||
* Implements state_t.get_state
|
||||
* Implementation of private_create_child_sa_requested_t.process_sa_payload.
|
||||
*/
|
||||
static status_t process_message(private_create_child_sa_requested_t *this, message_t *request)
|
||||
static status_t process_sa_payload(private_create_child_sa_requested_t *this, sa_payload_t *sa_payload)
|
||||
{
|
||||
this->logger->log(this->logger, ERROR, "NOT IMPLEMENTED");
|
||||
proposal_t *proposal, *proposal_tmp;
|
||||
linked_list_t *proposal_list;
|
||||
|
||||
/* get his selected proposal */
|
||||
proposal_list = sa_payload->get_proposals(sa_payload);
|
||||
/* check count of proposals */
|
||||
if (proposal_list->get_count(proposal_list) == 0)
|
||||
{
|
||||
/* no proposal? we accept this, but no child sa is built */
|
||||
this->logger->log(this->logger, AUDIT, "CREATE_CHILD_SA reply contained no proposals. CHILD_SA not created");
|
||||
proposal_list->destroy(proposal_list);
|
||||
return FAILED;
|
||||
}
|
||||
if (proposal_list->get_count(proposal_list) > 1)
|
||||
{
|
||||
this->logger->log(this->logger, AUDIT, "CREATE_CHILD_SA reply contained %d proposals. Aborting",
|
||||
proposal_list->get_count(proposal_list));
|
||||
while (proposal_list->remove_last(proposal_list, (void**)&proposal) == SUCCESS)
|
||||
{
|
||||
proposal->destroy(proposal);
|
||||
}
|
||||
proposal_list->destroy(proposal_list);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
/* we have to re-check here if other's selection is valid */
|
||||
proposal = this->policy->select_proposal(this->policy, proposal_list);
|
||||
/* list not needed anymore */
|
||||
while (proposal_list->remove_last(proposal_list, (void**)&proposal_tmp) == SUCCESS)
|
||||
{
|
||||
proposal_tmp->destroy(proposal_tmp);
|
||||
}
|
||||
proposal_list->destroy(proposal_list);
|
||||
/* got a match? */
|
||||
if (proposal == NULL)
|
||||
{
|
||||
this->logger->log(this->logger, AUDIT, "CREATE_CHILD_SA reply contained a not offered proposal. Aborting");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
/* apply proposal */
|
||||
this->proposal = proposal;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of private_create_child_sa_requested_t.process_ts_payload.
|
||||
*/
|
||||
static status_t process_ts_payload(private_create_child_sa_requested_t *this, bool ts_initiator, ts_payload_t *ts_payload)
|
||||
{
|
||||
linked_list_t *ts_received, *ts_selected;
|
||||
traffic_selector_t *ts;
|
||||
|
||||
/* get ts form payload */
|
||||
ts_received = ts_payload->get_traffic_selectors(ts_payload);
|
||||
/* select ts depending on payload type */
|
||||
if (ts_initiator)
|
||||
{
|
||||
ts_selected = this->policy->select_my_traffic_selectors(this->policy, ts_received);
|
||||
this->my_ts = ts_selected;
|
||||
}
|
||||
else
|
||||
{
|
||||
ts_selected = this->policy->select_other_traffic_selectors(this->policy, ts_received);
|
||||
this->other_ts = ts_selected;
|
||||
}
|
||||
/* check if the responder selected valid proposals */
|
||||
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->remove_last(ts_received, (void**)&ts) == SUCCESS)
|
||||
{
|
||||
ts->destroy(ts);
|
||||
}
|
||||
ts_received->destroy(ts_received);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of private_create_child_sa_requested_t.process_nonce_payload.
|
||||
*/
|
||||
static status_t process_nonce_payload(private_create_child_sa_requested_t *this, nonce_payload_t *nonce_request)
|
||||
{
|
||||
this->nonce_r = nonce_request->get_nonce(nonce_request);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a CREATE_CHILD_SA response
|
||||
*/
|
||||
static status_t process_message(private_create_child_sa_requested_t *this, message_t *response)
|
||||
{
|
||||
ts_payload_t *tsi_request = NULL, *tsr_request = NULL;
|
||||
sa_payload_t *sa_request = NULL;
|
||||
nonce_payload_t *nonce_request = NULL;
|
||||
ike_sa_id_t *ike_sa_id;
|
||||
iterator_t *payloads;
|
||||
crypter_t *crypter;
|
||||
signer_t *signer;
|
||||
status_t status;
|
||||
chunk_t seed;
|
||||
prf_plus_t *prf_plus;
|
||||
|
||||
this->policy = this->ike_sa->get_policy(this->ike_sa);
|
||||
if (response->get_exchange_type(response) != CREATE_CHILD_SA)
|
||||
{
|
||||
this->logger->log(this->logger, ERROR | LEVEL1, "Message of type %s not supported in state create_child_sa_requested",
|
||||
mapping_find(exchange_type_m, response->get_exchange_type(response)));
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
if (response->get_request(response))
|
||||
{
|
||||
this->logger->log(this->logger, ERROR | LEVEL1, "CREATE_CHILD_SA requests not allowed state create_child_sa_requested");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
/* get signer for verification and crypter for decryption */
|
||||
ike_sa_id = this->ike_sa->public.get_id(&this->ike_sa->public);
|
||||
if (!ike_sa_id->is_initiator(ike_sa_id))
|
||||
{
|
||||
crypter = this->ike_sa->get_crypter_initiator(this->ike_sa);
|
||||
signer = this->ike_sa->get_signer_initiator(this->ike_sa);
|
||||
}
|
||||
else
|
||||
{
|
||||
crypter = this->ike_sa->get_crypter_responder(this->ike_sa);
|
||||
signer = this->ike_sa->get_signer_responder(this->ike_sa);
|
||||
}
|
||||
|
||||
/* parse incoming message */
|
||||
status = response->parse_body(response, crypter, signer);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
this->logger->log(this->logger, AUDIT, "CREATE_CHILD_SA r decryption failed. Ignoring message");
|
||||
return status;
|
||||
}
|
||||
|
||||
/* iterate over incoming payloads. Message is verified, we can be sure there are the required payloads */
|
||||
payloads = response->get_payload_iterator(response);
|
||||
while (payloads->has_next(payloads))
|
||||
{
|
||||
payload_t *payload;
|
||||
payloads->current(payloads, (void**)&payload);
|
||||
|
||||
switch (payload->get_type(payload))
|
||||
{
|
||||
case SECURITY_ASSOCIATION:
|
||||
{
|
||||
sa_request = (sa_payload_t*)payload;
|
||||
break;
|
||||
}
|
||||
case TRAFFIC_SELECTOR_INITIATOR:
|
||||
{
|
||||
tsi_request = (ts_payload_t*)payload;
|
||||
break;
|
||||
}
|
||||
case TRAFFIC_SELECTOR_RESPONDER:
|
||||
{
|
||||
tsr_request = (ts_payload_t*)payload;
|
||||
break;
|
||||
}
|
||||
case NONCE:
|
||||
{
|
||||
nonce_request = (nonce_payload_t*)payload;
|
||||
break;
|
||||
}
|
||||
case NOTIFY:
|
||||
{
|
||||
/* TODO: handle notifys */
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
this->logger->log(this->logger, ERROR|LEVEL1, "Ignoring payload %s (%d)",
|
||||
mapping_find(payload_type_m, payload->get_type(payload)), payload->get_type(payload));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* iterator can be destroyed */
|
||||
payloads->destroy(payloads);
|
||||
|
||||
/* check if we have all payloads */
|
||||
if (!(sa_request && nonce_request && tsi_request && tsr_request))
|
||||
{
|
||||
this->logger->log(this->logger, AUDIT, "CREATE_CHILD_SA request did not contain all required payloads. Ignored");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
/* add payloads to it */
|
||||
status = process_nonce_payload(this, nonce_request);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
response->destroy(response);
|
||||
return status;
|
||||
}
|
||||
status = process_sa_payload(this, sa_request);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
response->destroy(response);
|
||||
return status;
|
||||
}
|
||||
status = process_ts_payload(this, TRUE, tsi_request);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
response->destroy(response);
|
||||
return status;
|
||||
}
|
||||
status = process_ts_payload(this, FALSE, tsr_request);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
response->destroy(response);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* install child SAs for AH and esp */
|
||||
if (!this->proposal)
|
||||
{
|
||||
this->logger->log(this->logger, CONTROL, "Proposal negotiation failed, no CHILD_SA built");
|
||||
this->child_sa->destroy(this->child_sa);
|
||||
this->child_sa = NULL;
|
||||
}
|
||||
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");
|
||||
this->child_sa->destroy(this->child_sa);
|
||||
this->child_sa = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
seed = chunk_alloc(this->nonce_i.len + this->nonce_r.len);
|
||||
memcpy(seed.ptr, this->nonce_i.ptr, this->nonce_i.len);
|
||||
memcpy(seed.ptr + this->nonce_i.len, this->nonce_r.ptr, this->nonce_r.len);
|
||||
prf_plus = prf_plus_create(this->ike_sa->get_child_prf(this->ike_sa), seed);
|
||||
|
||||
this->logger->log_chunk(this->logger, CONTROL, "Seed", seed);
|
||||
chunk_free(&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 DESTROY_ME;
|
||||
}
|
||||
status = this->child_sa->add_policies(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 DESTROY_ME;
|
||||
}
|
||||
this->ike_sa->add_child_sa(this->ike_sa, this->child_sa);
|
||||
}
|
||||
|
||||
this->ike_sa->set_last_replied_message_id(this->ike_sa, response->get_message_id(response));
|
||||
|
||||
/* create new state */
|
||||
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);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,7 +388,7 @@ static void destroy(private_create_child_sa_requested_t *this)
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
create_child_sa_requested_t *create_child_sa_requested_create(protected_ike_sa_t *ike_sa, chunk_t nonce_i)
|
||||
create_child_sa_requested_t *create_child_sa_requested_create(protected_ike_sa_t *ike_sa, child_sa_t *child_sa, chunk_t nonce_i)
|
||||
{
|
||||
private_create_child_sa_requested_t *this = malloc_thing(private_create_child_sa_requested_t);
|
||||
|
||||
@@ -104,6 +399,7 @@ create_child_sa_requested_t *create_child_sa_requested_create(protected_ike_sa_t
|
||||
|
||||
/* private data */
|
||||
this->ike_sa = ike_sa;
|
||||
this->child_sa = child_sa;
|
||||
this->nonce_i = nonce_i;
|
||||
this->nonce_r = CHUNK_INITIALIZER;
|
||||
this->logger = logger_manager->get_logger(logger_manager, IKE_SA);
|
||||
|
||||
Reference in New Issue
Block a user