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 \
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)
{
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);
* for more details.
*/
+#include <string.h>
+
#include "local_policy_store.h"
#include <utils/linked_list.h>
* for more details.
*/
+#include <time.h>
+#include <string.h>
+
#include "policy.h"
#include <utils/linked_list.h>
*/
static u_int32_t get_soft_lifetime(policy_t *this)
{
- return 0; /*5 + random() % 5; */
+ srandom(time(NULL));
+ return 0; //5 + random() % 3;
}
/**
*/
static u_int32_t get_hard_lifetime(policy_t *this)
{
- return 0; /*20; */
+ return 0; //9;
}
/**
u_int16_t algo;
size_t key_size;
bool add;
- u_int64_t spi;
/* check protocol */
if (this->protocol != other->protocol)
*/
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);
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);
#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;
#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;
iterator_t *iterator;
proposal_t *proposal;
status_t status;
- u_int i;
/* iterator through proposals */
iterator = proposals->create_iterator(proposals, TRUE);
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)
{
/* 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);
#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>
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;
}
}
/**
- * 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.
*/
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);
}
}
- 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);
}
/**
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;
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);
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);
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;
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;
}
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,
* 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>
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.
*
* Is logger of ike_sa!
};
/**
- * 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;
}
/**
/*
* 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);
/* 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);
#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;
* @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_*/
--- /dev/null
+/**
+ * @file delete_ike_sa_requested.c
+ *
+ * @brief Implementation of delete_ike_sa_requested_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2006 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "delete_ike_sa_requested.h"
+
+#include <daemon.h>
+
+
+typedef struct private_delete_ike_sa_requested_t private_delete_ike_sa_requested_t;
+
+/**
+ * Private data of a delete_ike_sa_requested_t object.
+ */
+struct private_delete_ike_sa_requested_t {
+
+ /**
+ * methods of the state_t interface
+ */
+ delete_ike_sa_requested_t public;
+
+ /**
+ * Assigned IKE_SA.
+ */
+ protected_ike_sa_t *ike_sa;
+
+ /**
+ * Assigned logger. Use logger of IKE_SA.
+ */
+ logger_t *logger;
+};
+
+/**
+ * Implements state_t.get_state
+ */
+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;
+ signer_t *signer;
+ status_t status;
+
+ /* Notation as follows:
+ * Mx{D} means: Message, with message ID "x", containing a Delete payload
+ *
+ * The clarifcation Document says in 5.8, that a IKE_SA delete should not
+ * be acknowledged with the same delete. This only makes sense for CHILD_SAs,
+ * as they are paired. IKE_SAs are not, there is only one for both ends.
+ *
+ * Normal case:
+ * ----------------
+ * Mx{D} -->
+ * <-- Mx{}
+ * Delete request is sent, and we wait for the acknowledge.
+ *
+ * Special case 1:
+ * ---------------
+ * Mx{D} -->
+ * <-- My{D}
+ * My{} -->
+ * <-- Mx{}
+ * Both initate a delete at the same time. We ack the delete, but wait for
+ * our delete to be acknowledged.
+ */
+
+ if (message->get_exchange_type(message) != INFORMATIONAL)
+ {
+ /* 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_ike_sa_requested. Ignored",
+ mapping_find(exchange_type_m, message->get_exchange_type(message)));
+ return FAILED;
+ }
+
+ if (message->get_request(message))
+ {
+ /* if it is a request, not a reply to our delete request, we
+ * just acknowledge this. We stay in our state, as the other peer
+ * has to ACK our request.
+ */
+ message_t *acknowledge;
+ this->ike_sa->build_message(this->ike_sa, INFORMATIONAL, FALSE, &acknowledge);
+ return this->ike_sa->send_response(this->ike_sa, acknowledge);
+ }
+
+ /* 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, check if it's proper signed */
+ status = message->parse_body(message, crypter, signer);
+ if (status != SUCCESS)
+ {
+ this->logger->log(this->logger, AUDIT, "INFORMATIONAL message decryption failed. Ignoring message");
+ return status;
+ }
+
+ /* ok, he knows about the deletion, destroy this IKE SA */
+ return DESTROY_ME;
+}
+
+/**
+ * Implementation of state_t.get_state.
+ */
+static ike_sa_state_t get_state(private_delete_ike_sa_requested_t *this)
+{
+ return DELETE_IKE_SA_REQUESTED;
+}
+
+/**
+ * Implementation of state_t.get_state
+ */
+static void destroy(private_delete_ike_sa_requested_t *this)
+{
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+delete_ike_sa_requested_t *delete_ike_sa_requested_create(protected_ike_sa_t *ike_sa)
+{
+ 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;
+ this->public.state_interface.get_state = (ike_sa_state_t (*) (state_t *)) get_state;
+ this->public.state_interface.destroy = (void (*) (state_t *)) destroy;
+
+ /* private data */
+ this->ike_sa = ike_sa;
+ this->logger = logger_manager->get_logger(logger_manager, IKE_SA);
+
+ return &(this->public);
+}
--- /dev/null
+/**
+ * @file delete_ike_sa_requested.h
+ *
+ * @brief Interface of delete_ike_sa_requested_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2006 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#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_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_ike_sa_requested_create()
+ *
+ * @ingroup states
+ */
+struct delete_ike_sa_requested_t {
+ /**
+ * methods of the state_t interface
+ */
+ state_t state_interface;
+
+};
+
+/**
+ * @brief Constructor of class delete_ike_sa_requested_t
+ *
+ * @param ike_sa assigned ike_sa
+ * @return created delete_ike_sa_requested_t object
+ *
+ * @ingroup states
+ */
+delete_ike_sa_requested_t *delete_ike_sa_requested_create(protected_ike_sa_t *ike_sa);
+
+#endif /*DELETE_IKE_SA_REQUESTED_H_*/
+++ /dev/null
-/**
- * @file delete_requested.c
- *
- * @brief Implementation of delete_requested_t.
- *
- */
-
-/*
- * Copyright (C) 2006 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include "delete_requested.h"
-
-#include <daemon.h>
-
-
-typedef struct private_delete_requested_t private_delete_requested_t;
-
-/**
- * Private data of a delete_requested_t object.
- */
-struct private_delete_requested_t {
-
- /**
- * methods of the state_t interface
- */
- delete_requested_t public;
-
- /**
- * Assigned IKE_SA.
- */
- protected_ike_sa_t *ike_sa;
-
- /**
- * Assigned logger. Use logger of IKE_SA.
- */
- logger_t *logger;
-};
-
-/**
- * Implements state_t.get_state
- */
-static status_t process_message(private_delete_requested_t *this, message_t *message)
-{
- ike_sa_id_t *ike_sa_id;
- crypter_t *crypter;
- signer_t *signer;
- status_t status;
-
- /* Notation as follows:
- * Mx{D} means: Message, with message ID "x", containing a Delete payload
- *
- * The clarifcation Document says in 5.8, that a IKE_SA delete should not
- * be acknowledged with the same delete. This only makes sense for CHILD_SAs,
- * as they are paired. IKE_SAs are not, there is only one for both ends.
- *
- * Normal case:
- * ----------------
- * Mx{D} -->
- * <-- Mx{}
- * Delete request is sent, and we wait for the acknowledge.
- *
- * Special case 1:
- * ---------------
- * Mx{D} -->
- * <-- My{D}
- * My{} -->
- * <-- Mx{}
- * Both initate a delete at the same time. We ack the delete, but wait for
- * our delete to be acknowledged.
- */
-
- if (message->get_exchange_type(message) != INFORMATIONAL)
- {
- /* 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",
- mapping_find(exchange_type_m, message->get_exchange_type(message)));
- return FAILED;
- }
-
- if (message->get_request(message))
- {
- /* if it is a request, not a reply to our delete request, we
- * just acknowledge this. We stay in our state, as the other peer
- * has to ACK our request.
- */
- message_t *acknowledge;
- this->ike_sa->build_message(this->ike_sa, INFORMATIONAL, FALSE, &acknowledge);
- return this->ike_sa->send_response(this->ike_sa, acknowledge);
- }
-
- /* 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, check if it's proper signed */
- status = message->parse_body(message, crypter, signer);
- if (status != SUCCESS)
- {
- this->logger->log(this->logger, AUDIT, "INFORMATIONAL message decryption failed. Ignoring message");
- return status;
- }
-
- /* ok, he knows about the deletion, destroy this IKE SA */
- return DESTROY_ME;
-}
-
-/**
- * Implementation of state_t.get_state.
- */
-static ike_sa_state_t get_state(private_delete_requested_t *this)
-{
- return DELETE_REQUESTED;
-}
-
-/**
- * Implementation of state_t.get_state
- */
-static void destroy(private_delete_requested_t *this)
-{
- free(this);
-}
-
-/*
- * Described in header.
- */
-delete_requested_t *delete_requested_create(protected_ike_sa_t *ike_sa)
-{
- private_delete_requested_t *this = malloc_thing(private_delete_requested_t);
-
- /* interface functions */
- this->public.state_interface.process_message = (status_t (*) (state_t *,message_t *)) process_message;
- this->public.state_interface.get_state = (ike_sa_state_t (*) (state_t *)) get_state;
- this->public.state_interface.destroy = (void (*) (state_t *)) destroy;
-
- /* private data */
- this->ike_sa = ike_sa;
- this->logger = logger_manager->get_logger(logger_manager, IKE_SA);
-
- return &(this->public);
-}
+++ /dev/null
-/**
- * @file delete_requested.h
- *
- * @brief Interface of delete_requested_t.
- *
- */
-
-/*
- * Copyright (C) 2006 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#ifndef DELETE_REQUESTED_H_
-#define DELETE_REQUESTED_H_
-
-#include <sa/states/state.h>
-#include <sa/ike_sa.h>
-
-typedef struct delete_requested_t delete_requested_t;
-
-/**
- * @brief This class represents an the state of a half closed IKE_SA.
- *
- * @b Constructors:
- * - delete_requested_create()
- *
- * @ingroup states
- */
-struct delete_requested_t {
- /**
- * methods of the state_t interface
- */
- state_t state_interface;
-
-};
-
-/**
- * @brief Constructor of class delete_requested_t
- *
- * @param ike_sa assigned ike_sa
- * @return created delete_requested_t object
- *
- * @ingroup states
- */
-delete_requested_t *delete_requested_create(protected_ike_sa_t *ike_sa);
-
-#endif /*DELETE_REQUESTED_H_*/
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);
* 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;
*/
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 process_message(private_ike_sa_established_t *this, message_t *message)
+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;
}
/**
/* 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);
}
{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}
};
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.
*
* After a call to ike_sa.close(), the IKE_SA sends a delete message
*
* Implemented in class delete_requested.
*/
- DELETE_REQUESTED,
-
- CREATE_CHILD_SA_REQUESTED,
+ DELETE_IKE_SA_REQUESTED,
};
$(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 \
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);
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);
* for more details.
*/
-
+#include <unistd.h>
+
#include "kernel_interface_test.h"
#include <daemon.h>
}
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;
}
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;
}
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;
}
*/
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);