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:
@@ -12,7 +12,7 @@ sa/states/state.c sa/states/state.h sa/states/ike_sa_init_requested.c sa/states/
|
||||
sa/states/ike_sa_init_responded.c sa/states/ike_sa_established.c sa/states/ike_sa_established.h \
|
||||
sa/states/responder_init.c sa/states/responder_init.h sa/states/initiator_init.c sa/states/initiator_init.h \
|
||||
sa/states/ike_sa_init_responded.h sa/states/ike_auth_requested.c sa/states/ike_auth_requested.h \
|
||||
sa/states/delete_requested.h sa/states/delete_requested.c \
|
||||
sa/states/delete_ike_sa_requested.h sa/states/delete_ike_sa_requested.c \
|
||||
sa/states/create_child_sa_requested.c sa/states/create_child_sa_requested.h \
|
||||
sa/child_sa.c sa/child_sa.h sa/ike_sa.c sa/ike_sa.h sa/ike_sa_manager.c sa/ike_sa_manager.h \
|
||||
sa/ike_sa_id.c sa/ike_sa_id.h sa/authenticator.c sa/authenticator.h encoding/payloads/encryption_payload.c \
|
||||
|
||||
@@ -218,7 +218,7 @@ static status_t add_connection(private_local_connection_store_t *this, connectio
|
||||
void log_connections(private_local_connection_store_t *this, logger_t *logger, char *name)
|
||||
{
|
||||
iterator_t *iterator;
|
||||
connection_t *current, *found = NULL;
|
||||
connection_t *current;
|
||||
|
||||
if (logger == NULL)
|
||||
{
|
||||
|
||||
@@ -185,20 +185,19 @@ static void add_certificate(private_local_credential_store_t *this, x509_t *cert
|
||||
static void log_certificates(private_local_credential_store_t *this, logger_t *logger, bool utc)
|
||||
{
|
||||
iterator_t *iterator = this->certs->create_iterator(this->certs, TRUE);
|
||||
|
||||
|
||||
if (iterator->get_count(iterator))
|
||||
{
|
||||
logger->log(logger, CONTROL, "");
|
||||
logger->log(logger, CONTROL, "List of X.509 End Entity Certificates:");
|
||||
logger->log(logger, CONTROL, "");
|
||||
}
|
||||
|
||||
|
||||
while (iterator->has_next(iterator))
|
||||
{
|
||||
x509_t *cert;
|
||||
rsa_private_key_t *key;
|
||||
bool has_key;
|
||||
|
||||
|
||||
iterator->current(iterator, (void**)&cert);
|
||||
has_key = has_rsa_private_key(this, cert->get_public_key(cert));
|
||||
cert->log_certificate(cert, logger, utc, has_key);
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "local_policy_store.h"
|
||||
|
||||
#include <utils/linked_list.h>
|
||||
|
||||
@@ -20,6 +20,9 @@
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "policy.h"
|
||||
|
||||
#include <utils/linked_list.h>
|
||||
@@ -293,7 +296,8 @@ static void add_proposal(private_policy_t *this, proposal_t *proposal)
|
||||
*/
|
||||
static u_int32_t get_soft_lifetime(policy_t *this)
|
||||
{
|
||||
return 0; /*5 + random() % 5; */
|
||||
srandom(time(NULL));
|
||||
return 0; //5 + random() % 3;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -301,7 +305,7 @@ static u_int32_t get_soft_lifetime(policy_t *this)
|
||||
*/
|
||||
static u_int32_t get_hard_lifetime(policy_t *this)
|
||||
{
|
||||
return 0; /*20; */
|
||||
return 0; //9;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -258,7 +258,6 @@ static proposal_t *select_proposal(private_proposal_t *this, private_proposal_t
|
||||
u_int16_t algo;
|
||||
size_t key_size;
|
||||
bool add;
|
||||
u_int64_t spi;
|
||||
|
||||
/* check protocol */
|
||||
if (this->protocol != other->protocol)
|
||||
|
||||
@@ -61,7 +61,6 @@ static job_type_t get_type(private_delete_established_ike_sa_job_t *this)
|
||||
*/
|
||||
static status_t execute(private_delete_established_ike_sa_job_t *this)
|
||||
{
|
||||
ike_sa_t *ike_sa;
|
||||
status_t status;
|
||||
|
||||
status = charon->ike_sa_manager->delete(charon->ike_sa_manager, this->ike_sa_id);
|
||||
|
||||
@@ -76,7 +76,7 @@ static status_t execute(private_delete_half_open_ike_sa_job_t *this)
|
||||
case IKE_SA_INIT_REQUESTED:
|
||||
case IKE_SA_INIT_RESPONDED:
|
||||
case IKE_AUTH_REQUESTED:
|
||||
case DELETE_REQUESTED:
|
||||
case DELETE_IKE_SA_REQUESTED:
|
||||
{
|
||||
/* IKE_SA is half open and gets deleted! */
|
||||
status = charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa);
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "incoming_packet_job.h"
|
||||
|
||||
#include <daemon.h>
|
||||
#include <queues/jobs/delete_half_open_ike_sa_job.h>
|
||||
|
||||
typedef struct private_incoming_packet_job_t private_incoming_packet_job_t;
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "initiate_ike_sa_job.h"
|
||||
|
||||
#include <daemon.h>
|
||||
#include <queues/jobs/delete_half_open_ike_sa_job.h>
|
||||
|
||||
typedef struct private_initiate_ike_sa_job_t private_initiate_ike_sa_job_t;
|
||||
|
||||
|
||||
@@ -135,7 +135,6 @@ static status_t alloc(private_child_sa_t *this, linked_list_t *proposals)
|
||||
iterator_t *iterator;
|
||||
proposal_t *proposal;
|
||||
status_t status;
|
||||
u_int i;
|
||||
|
||||
/* iterator through proposals */
|
||||
iterator = proposals->create_iterator(proposals, TRUE);
|
||||
@@ -146,9 +145,9 @@ static status_t alloc(private_child_sa_t *this, linked_list_t *proposals)
|
||||
|
||||
status = charon->kernel_interface->get_spi(
|
||||
charon->kernel_interface,
|
||||
this->me.addr, this->other.addr,
|
||||
this->other.addr, this->me.addr,
|
||||
protocol, FALSE,
|
||||
&(this->me.spi));
|
||||
&this->me.spi);
|
||||
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
@@ -178,15 +177,15 @@ static status_t install(private_child_sa_t *this, proposal_t *proposal, prf_plus
|
||||
|
||||
/* we must assign the roles to correctly set up the SAs */
|
||||
if (mine)
|
||||
{
|
||||
src = this->me.addr;
|
||||
dst = this->other.addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
dst = this->me.addr;
|
||||
src = this->other.addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
src = this->me.addr;
|
||||
dst = this->other.addr;
|
||||
}
|
||||
|
||||
this->protocol = proposal->get_protocol(proposal);
|
||||
|
||||
|
||||
+20
-139
@@ -42,6 +42,7 @@
|
||||
#include <sa/states/initiator_init.h>
|
||||
#include <sa/states/responder_init.h>
|
||||
#include <sa/states/create_child_sa_requested.h>
|
||||
#include <sa/states/delete_ike_sa_requested.h>
|
||||
#include <queues/jobs/retransmit_request_job.h>
|
||||
#include <queues/jobs/delete_established_ike_sa_job.h>
|
||||
#include <queues/jobs/delete_half_open_ike_sa_job.h>
|
||||
@@ -664,7 +665,9 @@ static status_t send_response(private_ike_sa_t *this, message_t *message)
|
||||
|
||||
if (message->get_message_id(message) != this->message_id_in)
|
||||
{
|
||||
this->logger->log(this->logger, ERROR, "Message could not be sent cause id was not as expected");
|
||||
|
||||
this->logger->log(this->logger, ERROR, "Message could not be sent cause id (%d) was not as expected (%d)",
|
||||
message->get_message_id(message),this->message_id_in);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
@@ -778,80 +781,6 @@ static void add_child_sa(private_ike_sa_t *this, child_sa_t *child_sa)
|
||||
this->child_sas->insert_last(this->child_sas, child_sa);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process an informational request
|
||||
*/
|
||||
static status_t process_informational(private_ike_sa_t *this, message_t *request)
|
||||
{
|
||||
delete_payload_t *delete_request = NULL;
|
||||
message_t *response;
|
||||
iterator_t *payloads;
|
||||
state_t *old_state;
|
||||
|
||||
build_message(this, INFORMATIONAL, FALSE, &response);
|
||||
|
||||
payloads = request->get_payload_iterator(request);
|
||||
while (payloads->has_next(payloads))
|
||||
{
|
||||
payload_t *payload;
|
||||
payloads->current(payloads, (void**)&payload);
|
||||
|
||||
switch (payload->get_type(payload))
|
||||
{
|
||||
case DELETE:
|
||||
{
|
||||
delete_request = (delete_payload_t *) payload;
|
||||
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);
|
||||
|
||||
if (delete_request)
|
||||
{
|
||||
if (delete_request->get_protocol_id(delete_request) == PROTO_IKE)
|
||||
{
|
||||
this->logger->log(this->logger, CONTROL, "DELETE request for IKE_SA received");
|
||||
if (send_response(this, response) != SUCCESS)
|
||||
{
|
||||
/* something is seriously wrong, kill connection */
|
||||
this->logger->log(this->logger, AUDIT, "Unable to send reply. Deleting IKE_SA");
|
||||
response->destroy(response);
|
||||
}
|
||||
/* switch to delete_requested. This is not absolutly correct, but we
|
||||
* allow the clean destruction of an SA only in this state. */
|
||||
old_state = this->current_state;
|
||||
set_new_state(this, (state_t*)delete_requested_create(this));
|
||||
old_state->destroy(old_state);
|
||||
return DESTROY_ME;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->logger->log(this->logger, CONTROL, "DELETE request for CHILD_SA received. Ignored");
|
||||
response->destroy(response);
|
||||
return FAILED;
|
||||
}
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Process an informational request
|
||||
*/
|
||||
static status_t process_create_child_sa(private_ike_sa_t *this, message_t *request)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of ike_sa_t.process_message.
|
||||
*/
|
||||
@@ -860,9 +789,6 @@ static status_t process_message(private_ike_sa_t *this, message_t *message)
|
||||
u_int32_t message_id;
|
||||
exchange_type_t exchange_type;
|
||||
bool is_request;
|
||||
status_t status;
|
||||
crypter_t *crypter;
|
||||
signer_t *signer;
|
||||
|
||||
/* Find out type of message (request or response) */
|
||||
is_request = message->get_request(message);
|
||||
@@ -916,60 +842,13 @@ static status_t process_message(private_ike_sa_t *this, message_t *message)
|
||||
}
|
||||
}
|
||||
|
||||
if (this->current_state->get_state(this->current_state) == IKE_SA_ESTABLISHED)
|
||||
{
|
||||
if (is_request)
|
||||
{
|
||||
/* get signer for verification and crypter for decryption */
|
||||
if (!this->ike_sa_id->is_initiator(this->ike_sa_id))
|
||||
{
|
||||
crypter = this->crypter_initiator;
|
||||
signer = this->signer_initiator;
|
||||
}
|
||||
else
|
||||
{
|
||||
crypter = this->crypter_responder;
|
||||
signer = this->signer_responder;
|
||||
}
|
||||
|
||||
/* parse incoming message */
|
||||
status = message->parse_body(message, crypter, signer);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
this->logger->log(this->logger, AUDIT, "%s request decryption failed. Ignoring message",
|
||||
mapping_find(exchange_type_m, message->get_exchange_type(message)));
|
||||
return status;
|
||||
}
|
||||
switch (message->get_exchange_type(message))
|
||||
{
|
||||
case CREATE_CHILD_SA:
|
||||
return process_create_child_sa(this, message);
|
||||
case INFORMATIONAL:
|
||||
return process_informational(this, message);
|
||||
default:
|
||||
this->logger->log(this->logger, CONTROL,
|
||||
"Received a %s request, ignored",
|
||||
mapping_find(exchange_type_m, exchange_type));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this->logger->log(this->logger, ERROR|LEVEL1,
|
||||
"Received an unexpected %s response, ignored",
|
||||
mapping_find(exchange_type_m, exchange_type));
|
||||
}
|
||||
return FAILED;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* now the message is processed by the current state object.
|
||||
* The specific state object is responsible to check if a message can be received in
|
||||
* the state it represents.
|
||||
* The current state is also responsible to change the state object to the next state
|
||||
* by calling protected_ike_sa_t.set_new_state
|
||||
*/
|
||||
return this->current_state->process_message(this->current_state, message);
|
||||
}
|
||||
/* now the message is processed by the current state object.
|
||||
* The specific state object is responsible to check if a message can be received in
|
||||
* the state it represents.
|
||||
* The current state is also responsible to change the state object to the next state
|
||||
* by calling protected_ike_sa_t.set_new_state
|
||||
*/
|
||||
return this->current_state->process_message(this->current_state, message);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1033,8 +912,6 @@ static status_t rekey_child_sa(private_ike_sa_t *this, u_int32_t reqid)
|
||||
sa_payload_t *sa_payload;
|
||||
ts_payload_t *tsi_payload, *tsr_payload;
|
||||
nonce_payload_t *nonce_payload;
|
||||
policy_t *policy;
|
||||
randomizer_t *randomizer;
|
||||
linked_list_t *proposals;
|
||||
chunk_t nonce;
|
||||
linked_list_t *my_ts, *other_ts;
|
||||
@@ -1062,6 +939,11 @@ static status_t rekey_child_sa(private_ike_sa_t *this, u_int32_t reqid)
|
||||
request->add_payload(request, (payload_t*)notify);
|
||||
|
||||
proposals = this->policy->get_proposals(this->policy);
|
||||
child_sa = child_sa_create(this->connection->get_my_host(this->connection),
|
||||
this->connection->get_other_host(this->connection),
|
||||
this->policy->get_soft_lifetime(this->policy),
|
||||
this->policy->get_hard_lifetime(this->policy));
|
||||
child_sa->alloc(child_sa, proposals);
|
||||
sa_payload = sa_payload_create_from_proposal_list(proposals);
|
||||
request->add_payload(request, (payload_t*)sa_payload);
|
||||
|
||||
@@ -1076,7 +958,7 @@ static status_t rekey_child_sa(private_ike_sa_t *this, u_int32_t reqid)
|
||||
request->add_payload(request, (payload_t*)nonce_payload);
|
||||
|
||||
my_ts = this->policy->get_my_traffic_selectors(this->policy);
|
||||
other_ts = this->policy->get_my_traffic_selectors(this->policy);
|
||||
other_ts = this->policy->get_other_traffic_selectors(this->policy);
|
||||
tsi_payload = ts_payload_create_from_traffic_selectors(TRUE, my_ts);
|
||||
tsr_payload = ts_payload_create_from_traffic_selectors(FALSE, other_ts);
|
||||
request->add_payload(request, (payload_t*)tsi_payload);
|
||||
@@ -1085,7 +967,7 @@ static status_t rekey_child_sa(private_ike_sa_t *this, u_int32_t reqid)
|
||||
send_request(this, request);
|
||||
|
||||
old_state = this->current_state;
|
||||
set_new_state(this, (state_t*)create_child_sa_requested_create(&this->protected, nonce));
|
||||
set_new_state(this, (state_t*)create_child_sa_requested_create(&this->protected, child_sa, nonce));
|
||||
old_state->destroy(old_state);
|
||||
|
||||
return SUCCESS;
|
||||
@@ -1187,7 +1069,6 @@ static status_t delete_(private_ike_sa_t *this)
|
||||
|
||||
if (get_state(this) != IKE_SA_ESTABLISHED)
|
||||
{
|
||||
this->logger->log(this->logger, ERROR, "Closing a not established IKE SA not allowed, aborting!");
|
||||
return INVALID_STATE;
|
||||
}
|
||||
|
||||
@@ -1204,9 +1085,9 @@ static status_t delete_(private_ike_sa_t *this)
|
||||
informational_request->destroy(informational_request);
|
||||
}
|
||||
|
||||
/* transit to state delete_requested */
|
||||
/* transit to state delete_ike_sa_requested */
|
||||
old_state = this->current_state;
|
||||
set_new_state(this, (state_t*)delete_requested_create(this));
|
||||
set_new_state(this, (state_t*)delete_ike_sa_requested_create(&this->protected));
|
||||
old_state->destroy(old_state);
|
||||
|
||||
/* there is no guarantee that the other peer will acknowledge the delete,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#include <sa/states/state.h>
|
||||
#include <sa/ike_sa.h>
|
||||
#include <sa/child_sa.h>
|
||||
|
||||
typedef struct create_child_sa_requested_t create_child_sa_requested_t;
|
||||
|
||||
@@ -47,11 +48,12 @@ struct create_child_sa_requested_t {
|
||||
* @brief Constructor of class create_child_sa_requested_t
|
||||
*
|
||||
* @param ike_sa assigned ike_sa
|
||||
* @param child_sa newly created child sa to complete
|
||||
* @param nonce nonce sent at initialization
|
||||
* @return created create_child_sa_requested_t object
|
||||
*
|
||||
* @ingroup states
|
||||
*/
|
||||
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);
|
||||
|
||||
#endif /*CREATE_CHILD_SA_REQEUSTED_H_*/
|
||||
|
||||
+14
-14
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file delete_requested.c
|
||||
* @file delete_ike_sa_requested.c
|
||||
*
|
||||
* @brief Implementation of delete_requested_t.
|
||||
* @brief Implementation of delete_ike_sa_requested_t.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -20,22 +20,22 @@
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include "delete_requested.h"
|
||||
#include "delete_ike_sa_requested.h"
|
||||
|
||||
#include <daemon.h>
|
||||
|
||||
|
||||
typedef struct private_delete_requested_t private_delete_requested_t;
|
||||
typedef struct private_delete_ike_sa_requested_t private_delete_ike_sa_requested_t;
|
||||
|
||||
/**
|
||||
* Private data of a delete_requested_t object.
|
||||
* Private data of a delete_ike_sa_requested_t object.
|
||||
*/
|
||||
struct private_delete_requested_t {
|
||||
struct private_delete_ike_sa_requested_t {
|
||||
|
||||
/**
|
||||
* methods of the state_t interface
|
||||
*/
|
||||
delete_requested_t public;
|
||||
delete_ike_sa_requested_t public;
|
||||
|
||||
/**
|
||||
* Assigned IKE_SA.
|
||||
@@ -51,7 +51,7 @@ struct private_delete_requested_t {
|
||||
/**
|
||||
* Implements state_t.get_state
|
||||
*/
|
||||
static status_t process_message(private_delete_requested_t *this, message_t *message)
|
||||
static status_t process_message(private_delete_ike_sa_requested_t *this, message_t *message)
|
||||
{
|
||||
ike_sa_id_t *ike_sa_id;
|
||||
crypter_t *crypter;
|
||||
@@ -86,7 +86,7 @@ static status_t process_message(private_delete_requested_t *this, message_t *mes
|
||||
/* anything other than information is ignored. We can an will not handle
|
||||
* messages such as CREATE_CHILD_SA */
|
||||
this->logger->log(this->logger, ERROR | LEVEL1,
|
||||
"%s messages not supported in state delete_requested. Ignored",
|
||||
"%s messages not supported in state delete_ike_sa_requested. Ignored",
|
||||
mapping_find(exchange_type_m, message->get_exchange_type(message)));
|
||||
return FAILED;
|
||||
}
|
||||
@@ -130,15 +130,15 @@ static status_t process_message(private_delete_requested_t *this, message_t *mes
|
||||
/**
|
||||
* Implementation of state_t.get_state.
|
||||
*/
|
||||
static ike_sa_state_t get_state(private_delete_requested_t *this)
|
||||
static ike_sa_state_t get_state(private_delete_ike_sa_requested_t *this)
|
||||
{
|
||||
return DELETE_REQUESTED;
|
||||
return DELETE_IKE_SA_REQUESTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of state_t.get_state
|
||||
*/
|
||||
static void destroy(private_delete_requested_t *this)
|
||||
static void destroy(private_delete_ike_sa_requested_t *this)
|
||||
{
|
||||
free(this);
|
||||
}
|
||||
@@ -146,9 +146,9 @@ static void destroy(private_delete_requested_t *this)
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
delete_requested_t *delete_requested_create(protected_ike_sa_t *ike_sa)
|
||||
delete_ike_sa_requested_t *delete_ike_sa_requested_create(protected_ike_sa_t *ike_sa)
|
||||
{
|
||||
private_delete_requested_t *this = malloc_thing(private_delete_requested_t);
|
||||
private_delete_ike_sa_requested_t *this = malloc_thing(private_delete_ike_sa_requested_t);
|
||||
|
||||
/* interface functions */
|
||||
this->public.state_interface.process_message = (status_t (*) (state_t *,message_t *)) process_message;
|
||||
+11
-11
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file delete_requested.h
|
||||
* @file delete_ike_sa_requested.h
|
||||
*
|
||||
* @brief Interface of delete_requested_t.
|
||||
* @brief Interface of delete_ike_sa_requested_t.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -20,23 +20,23 @@
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#ifndef DELETE_REQUESTED_H_
|
||||
#define DELETE_REQUESTED_H_
|
||||
#ifndef DELETE_IKE_SA_REQUESTED_H_
|
||||
#define DELETE_IKE_SA_REQUESTED_H_
|
||||
|
||||
#include <sa/states/state.h>
|
||||
#include <sa/ike_sa.h>
|
||||
|
||||
typedef struct delete_requested_t delete_requested_t;
|
||||
typedef struct delete_ike_sa_requested_t delete_ike_sa_requested_t;
|
||||
|
||||
/**
|
||||
* @brief This class represents an the state of a half closed IKE_SA.
|
||||
*
|
||||
* @b Constructors:
|
||||
* - delete_requested_create()
|
||||
* - delete_ike_sa_requested_create()
|
||||
*
|
||||
* @ingroup states
|
||||
*/
|
||||
struct delete_requested_t {
|
||||
struct delete_ike_sa_requested_t {
|
||||
/**
|
||||
* methods of the state_t interface
|
||||
*/
|
||||
@@ -45,13 +45,13 @@ struct delete_requested_t {
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Constructor of class delete_requested_t
|
||||
* @brief Constructor of class delete_ike_sa_requested_t
|
||||
*
|
||||
* @param ike_sa assigned ike_sa
|
||||
* @return created delete_requested_t object
|
||||
* @return created delete_ike_sa_requested_t object
|
||||
*
|
||||
* @ingroup states
|
||||
*/
|
||||
delete_requested_t *delete_requested_create(protected_ike_sa_t *ike_sa);
|
||||
delete_ike_sa_requested_t *delete_ike_sa_requested_create(protected_ike_sa_t *ike_sa);
|
||||
|
||||
#endif /*DELETE_REQUESTED_H_*/
|
||||
#endif /*DELETE_IKE_SA_REQUESTED_H_*/
|
||||
@@ -379,7 +379,6 @@ static status_t process_message(private_ike_auth_requested_t *this, message_t *i
|
||||
static status_t process_idr_payload(private_ike_auth_requested_t *this, id_payload_t *idr_payload)
|
||||
{
|
||||
identification_t *other_id, *configured_other_id;
|
||||
connection_t *connection;
|
||||
|
||||
other_id = idr_payload->get_identification(idr_payload);
|
||||
configured_other_id = this->policy->get_other_id(this->policy);
|
||||
|
||||
@@ -19,11 +19,18 @@
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "ike_sa_established.h"
|
||||
|
||||
#include <daemon.h>
|
||||
#include <encoding/payloads/delete_payload.h>
|
||||
#include <encoding/payloads/sa_payload.h>
|
||||
#include <encoding/payloads/ts_payload.h>
|
||||
#include <encoding/payloads/nonce_payload.h>
|
||||
#include <sa/child_sa.h>
|
||||
#include <sa/states/delete_ike_sa_requested.h>
|
||||
|
||||
|
||||
typedef struct private_ike_sa_established_t private_ike_sa_established_t;
|
||||
@@ -42,19 +49,438 @@ struct private_ike_sa_established_t {
|
||||
*/
|
||||
protected_ike_sa_t *ike_sa;
|
||||
|
||||
/**
|
||||
* Nonce for a new child SA, chosen by initiator
|
||||
*/
|
||||
chunk_t nonce_i;
|
||||
|
||||
/**
|
||||
* Nonce for a new child SA, chosen by responder
|
||||
*/
|
||||
chunk_t nonce_r;
|
||||
|
||||
/**
|
||||
* Traffic selectors for a new child SA, responder side
|
||||
*/
|
||||
linked_list_t *my_ts;
|
||||
|
||||
/**
|
||||
* Traffic selectors for a new child SA, initiator side
|
||||
*/
|
||||
linked_list_t *other_ts;
|
||||
|
||||
/**
|
||||
* Newly set up child sa
|
||||
*/
|
||||
child_sa_t *child_sa;
|
||||
|
||||
/**
|
||||
* Assigned logger. Use logger of IKE_SA.
|
||||
*/
|
||||
logger_t *logger;
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementation of private_ike_sa_established_t.build_sa_payload.
|
||||
*/
|
||||
static status_t build_sa_payload(private_ike_sa_established_t *this, sa_payload_t *request, message_t *response)
|
||||
{
|
||||
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;
|
||||
connection_t *connection;
|
||||
policy_t *policy;
|
||||
|
||||
/* prepare reply */
|
||||
sa_response = sa_payload_create();
|
||||
|
||||
/* get proposals from request, and select one with ours */
|
||||
policy = this->ike_sa->get_policy(this->ike_sa);
|
||||
proposal_list = request->get_proposals(request);
|
||||
this->logger->log(this->logger, CONTROL|LEVEL1, "Selecting proposals:");
|
||||
proposal = policy->select_proposal(policy, proposal_list);
|
||||
/* list is not needed anymore */
|
||||
while (proposal_list->remove_last(proposal_list, (void**)&proposal_tmp) == SUCCESS)
|
||||
{
|
||||
proposal_tmp->destroy(proposal_tmp);
|
||||
}
|
||||
proposal_list->destroy(proposal_list);
|
||||
/* do we have a proposal? */
|
||||
if (proposal == NULL)
|
||||
{
|
||||
notify_payload_t *notify;
|
||||
this->logger->log(this->logger, AUDIT, "CREATE_CHILD_SA request did not contain any proposals we accept. "
|
||||
"Adding NO_PROPOSAL_CHOSEN notify");
|
||||
/* add NO_PROPOSAL_CHOSEN and an empty SA payload */
|
||||
notify = notify_payload_create_from_protocol_and_type(PROTO_IKE, NO_PROPOSAL_CHOSEN);
|
||||
response->add_payload(response, (payload_t*)notify);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* set up child sa */
|
||||
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);
|
||||
|
||||
policy = this->ike_sa->get_policy(this->ike_sa);
|
||||
connection = this->ike_sa->get_connection(this->ike_sa);
|
||||
this->child_sa = child_sa_create(connection->get_my_host(connection),
|
||||
connection->get_other_host(connection),
|
||||
policy->get_soft_lifetime(policy),
|
||||
policy->get_hard_lifetime(policy));
|
||||
|
||||
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!");
|
||||
sa_response->destroy(sa_response);
|
||||
proposal->destroy(proposal);
|
||||
return DESTROY_ME;
|
||||
}
|
||||
|
||||
/* add proposal to sa payload */
|
||||
sa_response->add_proposal(sa_response, proposal);
|
||||
proposal->destroy(proposal);
|
||||
}
|
||||
response->add_payload(response, (payload_t*)sa_response);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements state_t.get_state
|
||||
* Implementation of private_ike_sa_established_t.build_ts_payload.
|
||||
*/
|
||||
static status_t build_ts_payload(private_ike_sa_established_t *this, bool ts_initiator, ts_payload_t *request, message_t* response)
|
||||
{
|
||||
linked_list_t *ts_received, *ts_selected;
|
||||
traffic_selector_t *ts;
|
||||
status_t status = SUCCESS;
|
||||
ts_payload_t *ts_response;
|
||||
policy_t *policy;
|
||||
|
||||
policy = this->ike_sa->get_policy(this->ike_sa);
|
||||
|
||||
/* build a reply payload with selected traffic selectors */
|
||||
ts_received = request->get_traffic_selectors(request);
|
||||
/* select ts depending on payload type */
|
||||
if (ts_initiator)
|
||||
{
|
||||
ts_selected = policy->select_other_traffic_selectors(policy, ts_received);
|
||||
this->other_ts = ts_selected;
|
||||
}
|
||||
else
|
||||
{
|
||||
ts_selected = policy->select_my_traffic_selectors(policy, 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);
|
||||
|
||||
/* add notify if traffic selectors do not match */
|
||||
if (!ts_initiator &&
|
||||
(ts_selected->get_count(ts_selected) == 0 || this->other_ts->get_count(this->other_ts) == 0))
|
||||
{
|
||||
notify_payload_t *notify;
|
||||
|
||||
this->logger->log(this->logger, AUDIT, "IKE_AUTH request did not contain any traffic selectors we accept. "
|
||||
"Adding TS_UNACCEPTABLE notify");
|
||||
|
||||
notify = notify_payload_create_from_protocol_and_type(0, TS_UNACCEPTABLE);
|
||||
response->add_payload(response, (payload_t*)notify);
|
||||
}
|
||||
|
||||
/* cleanup */
|
||||
while (ts_received->remove_last(ts_received, (void**)&ts) == SUCCESS)
|
||||
{
|
||||
ts->destroy(ts);
|
||||
}
|
||||
ts_received->destroy(ts_received);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of private_ike_sa_established_t.build_nonce_payload.
|
||||
*/
|
||||
static status_t build_nonce_payload(private_ike_sa_established_t *this, nonce_payload_t *nonce_request, message_t *response)
|
||||
{
|
||||
nonce_payload_t *nonce_payload;
|
||||
randomizer_t *randomizer;
|
||||
status_t status;
|
||||
|
||||
this->nonce_i = nonce_request->get_nonce(nonce_request);
|
||||
|
||||
randomizer = this->ike_sa->get_randomizer(this->ike_sa);
|
||||
status = randomizer->allocate_pseudo_random_bytes(randomizer, NONCE_SIZE, &this->nonce_r);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
nonce_payload = nonce_payload_create();
|
||||
nonce_payload->set_nonce(nonce_payload, this->nonce_r);
|
||||
|
||||
response->add_payload(response,(payload_t *) nonce_payload);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a CREATE_CHILD_SA request
|
||||
*/
|
||||
static status_t process_create_child_sa(private_ike_sa_established_t *this, message_t *request, message_t *response)
|
||||
{
|
||||
ts_payload_t *tsi_request = NULL, *tsr_request = NULL;
|
||||
sa_payload_t *sa_request = NULL;
|
||||
nonce_payload_t *nonce_request = NULL;
|
||||
iterator_t *payloads;
|
||||
status_t status;
|
||||
|
||||
/* iterate over incoming payloads. Message is verified, we can be sure there are the required payloads */
|
||||
payloads = request->get_payload_iterator(request);
|
||||
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;
|
||||
}
|
||||
|
||||
/* build response */
|
||||
this->ike_sa->build_message(this->ike_sa, CREATE_CHILD_SA, FALSE, &response);
|
||||
|
||||
/* add payloads to it */
|
||||
status = build_nonce_payload(this, nonce_request, response);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
response->destroy(response);
|
||||
return status;
|
||||
}
|
||||
status = build_sa_payload(this, sa_request, response);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
response->destroy(response);
|
||||
return status;
|
||||
}
|
||||
status = build_ts_payload(this, TRUE, tsi_request, response);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
response->destroy(response);
|
||||
return status;
|
||||
}
|
||||
status = build_ts_payload(this, FALSE, tsr_request, response);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
response->destroy(response);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = this->ike_sa->send_response(this->ike_sa, response);
|
||||
/* message can now be sent (must not be destroyed) */
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
this->logger->log(this->logger, AUDIT, "Unable to send CREATE_CHILD_SA reply. Ignored");
|
||||
response->destroy(response);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
/* install child SA policies */
|
||||
if (!this->child_sa)
|
||||
{
|
||||
this->logger->log(this->logger, ERROR, "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, ERROR, "Traffic selector negotiation failed, no CHILD_SA built");
|
||||
this->child_sa->destroy(this->child_sa);
|
||||
this->child_sa = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
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!");
|
||||
}
|
||||
this->ike_sa->add_child_sa(this->ike_sa, this->child_sa);
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Process an informational request
|
||||
*/
|
||||
static status_t process_informational(private_ike_sa_established_t *this, message_t *request, message_t *response)
|
||||
{
|
||||
delete_payload_t *delete_request = NULL;
|
||||
iterator_t *payloads = request->get_payload_iterator(request);
|
||||
|
||||
while (payloads->has_next(payloads))
|
||||
{
|
||||
payload_t *payload;
|
||||
payloads->current(payloads, (void**)&payload);
|
||||
|
||||
switch (payload->get_type(payload))
|
||||
{
|
||||
case DELETE:
|
||||
{
|
||||
delete_request = (delete_payload_t *) payload;
|
||||
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);
|
||||
|
||||
if (delete_request)
|
||||
{
|
||||
if (delete_request->get_protocol_id(delete_request) == PROTO_IKE)
|
||||
{
|
||||
this->logger->log(this->logger, CONTROL, "DELETE request for IKE_SA received");
|
||||
/* switch to delete_ike_sa_requested. This is not absolutly correct, but we
|
||||
* allow the clean destruction of an SA only in this state. */
|
||||
this->ike_sa->set_new_state(this->ike_sa, (state_t*)delete_ike_sa_requested_create(this->ike_sa));
|
||||
this->public.state_interface.destroy(&(this->public.state_interface));
|
||||
return DESTROY_ME;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->logger->log(this->logger, CONTROL, "DELETE request for CHILD_SA received. Ignored");
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
if (this->ike_sa->send_response(this->ike_sa, response) != SUCCESS)
|
||||
{
|
||||
/* something is seriously wrong, kill connection */
|
||||
this->logger->log(this->logger, AUDIT, "Unable to send reply. Deleting IKE_SA");
|
||||
response->destroy(response);
|
||||
return DESTROY_ME;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements state_t.process_message
|
||||
*/
|
||||
static status_t process_message(private_ike_sa_established_t *this, message_t *message)
|
||||
{
|
||||
|
||||
ike_sa_id_t *ike_sa_id;
|
||||
message_t *response;
|
||||
crypter_t *crypter;
|
||||
signer_t *signer;
|
||||
status_t status;
|
||||
|
||||
/* only requests are allowed, responses are handled in other state */
|
||||
if (!message->get_request(message))
|
||||
{
|
||||
this->logger->log(this->logger, ERROR|LEVEL1,
|
||||
"Response not handled in state ike_sa_established");
|
||||
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 = message->parse_body(message, crypter, signer);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
this->logger->log(this->logger, AUDIT, "%s request decryption failed. Ignoring message",
|
||||
mapping_find(exchange_type_m, message->get_exchange_type(message)));
|
||||
return status;
|
||||
}
|
||||
|
||||
/* prepare a reply of the same type */
|
||||
this->ike_sa->build_message(this->ike_sa, message->get_exchange_type(message), FALSE, &response);
|
||||
|
||||
/* handle the different message types in their functions */
|
||||
switch (message->get_exchange_type(message))
|
||||
{
|
||||
case INFORMATIONAL:
|
||||
status = process_informational(this, message, response);
|
||||
break;
|
||||
case CREATE_CHILD_SA:
|
||||
status = process_create_child_sa(this, message, response);
|
||||
break;
|
||||
default:
|
||||
this->logger->log(this->logger, ERROR | LEVEL1,
|
||||
"Message of type %s not supported in state ike_sa_established",
|
||||
mapping_find(exchange_type_m, message->get_exchange_type(message)));
|
||||
status = NOT_SUPPORTED;
|
||||
}
|
||||
/* clean up private members */
|
||||
chunk_free(&this->nonce_i);
|
||||
chunk_free(&this->nonce_r);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -88,6 +514,8 @@ ike_sa_established_t *ike_sa_established_create(protected_ike_sa_t *ike_sa)
|
||||
/* private data */
|
||||
this->ike_sa = ike_sa;
|
||||
this->logger = logger_manager->get_logger(logger_manager, IKE_SA);
|
||||
this->nonce_i = CHUNK_INITIALIZER;
|
||||
this->nonce_r = CHUNK_INITIALIZER;
|
||||
|
||||
return &(this->public);
|
||||
}
|
||||
|
||||
@@ -33,7 +33,8 @@ mapping_t ike_sa_state_m[] = {
|
||||
{IKE_SA_INIT_RESPONDED, "IKE_SA_INIT_RESPONDED"},
|
||||
{IKE_AUTH_REQUESTED, "IKE_AUTH_REQUESTED"},
|
||||
{IKE_SA_ESTABLISHED, "IKE_SA_ESTABLISHED"},
|
||||
{DELETE_REQUESTED, "DELETE_REQUESTED"},
|
||||
{DELETE_IKE_SA_REQUESTED, "DELETE_IKE_SA_REQUESTED"},
|
||||
{CREATE_CHILD_SA_REQUESTED, "CREATE_CHILD_SA_REQUESTED"},
|
||||
{DELETE_CHILD_SA_REQUESTED, "DELETE_CHILD_SA_REQUESTED"},
|
||||
{MAPPING_END, NULL}
|
||||
};
|
||||
|
||||
@@ -96,6 +96,20 @@ enum ike_sa_state_t {
|
||||
*/
|
||||
IKE_SA_ESTABLISHED,
|
||||
|
||||
/**
|
||||
* @brief A rekeying/create CHILD_SA request was sent.
|
||||
*
|
||||
* Implemented in class create_child_sa_requested.
|
||||
*/
|
||||
CREATE_CHILD_SA_REQUESTED,
|
||||
|
||||
/**
|
||||
* @brief A delete CHILD_SA request was sent.
|
||||
*
|
||||
* Implemented in class delete_child_sa_requested.
|
||||
*/
|
||||
DELETE_CHILD_SA_REQUESTED,
|
||||
|
||||
/**
|
||||
* @brief An IKE SA has sent a DELETE IKE_SA to the other peer.
|
||||
*
|
||||
@@ -105,9 +119,7 @@ enum ike_sa_state_t {
|
||||
*
|
||||
* Implemented in class delete_requested.
|
||||
*/
|
||||
DELETE_REQUESTED,
|
||||
|
||||
CREATE_CHILD_SA_REQUESTED,
|
||||
DELETE_IKE_SA_REQUESTED,
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ $(top_srcdir)/src/charon/connection.o $(top_srcdir)/src/charon/local_connection_
|
||||
$(top_srcdir)/src/charon/local_policy_store.o $(top_srcdir)/src/charon/local_credential_store.o $(top_srcdir)/src/charon/traffic_selector.o \
|
||||
$(top_srcdir)/src/charon/proposal.o $(top_srcdir)/src/charon/configuration.o $(top_srcdir)/src/charon/state.o $(top_srcdir)/src/charon/ike_sa_init_requested.o \
|
||||
$(top_srcdir)/src/charon/ike_sa_init_responded.o $(top_srcdir)/src/charon/ike_sa_established.o $(top_srcdir)/src/charon/responder_init.o \
|
||||
$(top_srcdir)/src/charon/initiator_init.o $(top_srcdir)/src/charon/ike_auth_requested.o $(top_srcdir)/src/charon/delete_requested.o \
|
||||
$(top_srcdir)/src/charon/initiator_init.o $(top_srcdir)/src/charon/ike_auth_requested.o $(top_srcdir)/src/charon/delete_ike_sa_requested.o \
|
||||
$(top_srcdir)/src/charon/child_sa.o $(top_srcdir)/src/charon/ike_sa.o $(top_srcdir)/src/charon/ike_sa_manager.o $(top_srcdir)/src/charon/ike_sa_id.o \
|
||||
$(top_srcdir)/src/charon/authenticator.o $(top_srcdir)/src/charon/encryption_payload.o $(top_srcdir)/src/charon/cert_payload.o \
|
||||
$(top_srcdir)/src/charon/traffic_selector_substructure.o $(top_srcdir)/src/charon/transform_attribute.o $(top_srcdir)/src/charon/configuration_attribute.o \
|
||||
|
||||
@@ -695,7 +695,7 @@ void test_generator_with_notify_payload(protected_tester_t *tester)
|
||||
notify_payload_t *notify_payload;
|
||||
logger_t *logger;
|
||||
chunk_t generated_data;
|
||||
chunk_t spi,notification_data;
|
||||
chunk_t notification_data;
|
||||
|
||||
logger = logger_manager->get_logger(logger_manager,TESTER);
|
||||
|
||||
@@ -710,7 +710,7 @@ void test_generator_with_notify_payload(protected_tester_t *tester)
|
||||
|
||||
notify_payload->set_protocol_id(notify_payload,255);
|
||||
notify_payload->set_notify_message_type(notify_payload,63333); /* Hex F765 */
|
||||
notify_payload->set_spi(notify_payload, 0x3132333435);
|
||||
notify_payload->set_spi(notify_payload, 0x3132333435ll);
|
||||
notify_payload->set_notification_data(notify_payload,notification_data);
|
||||
|
||||
generator->generate_payload(generator,(payload_t *)notify_payload);
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include "kernel_interface_test.h"
|
||||
|
||||
#include <daemon.h>
|
||||
|
||||
@@ -360,7 +360,7 @@ static status_t add_sa( private_kernel_interface_t *this,
|
||||
}
|
||||
else if (response->e.error)
|
||||
{
|
||||
this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_NEWSA got error %s",
|
||||
this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_NEWSA received error: %s",
|
||||
strerror(-response->e.error));
|
||||
status = FAILED;
|
||||
}
|
||||
@@ -438,9 +438,8 @@ static status_t add_policy(private_kernel_interface_t *this,
|
||||
request.policy.sel.proto = upper_proto;
|
||||
request.policy.sel.family = src->get_family(src);
|
||||
|
||||
request.hdr.nlmsg_type = XFRM_MSG_NEWPOLICY;
|
||||
request.hdr.nlmsg_type = XFRM_MSG_UPDPOLICY;
|
||||
request.hdr.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(request.policy)));
|
||||
|
||||
request.policy.dir = direction;
|
||||
request.policy.priority = SPD_PRIORITY;
|
||||
request.policy.action = XFRM_POLICY_ALLOW;
|
||||
@@ -502,7 +501,7 @@ static status_t add_policy(private_kernel_interface_t *this,
|
||||
}
|
||||
else if (response->e.error)
|
||||
{
|
||||
this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_NEWPOLICY got error %s",
|
||||
this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_NEWPOLICY received error: %s",
|
||||
strerror(-response->e.error));
|
||||
status = FAILED;
|
||||
}
|
||||
|
||||
@@ -470,7 +470,7 @@ static void stroke_status(private_stroke_t *this, stroke_msg_t *msg)
|
||||
*/
|
||||
static void stroke_list(private_stroke_t *this, stroke_msg_t *msg, bool utc)
|
||||
{
|
||||
if (msg->type = STR_LIST_CERTS)
|
||||
if (msg->type == STR_LIST_CERTS)
|
||||
{
|
||||
charon->credentials->log_certificates(charon->credentials, this->stroke_logger, utc);
|
||||
charon->credentials->log_ca_certificates(charon->credentials, this->stroke_logger, utc);
|
||||
|
||||
Reference in New Issue
Block a user