aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMartin Willi <martin@strongswan.org>2006-06-08 14:20:05 +0000
committerMartin Willi <martin@strongswan.org>2006-06-08 14:20:05 +0000
commit5238c9afefb7783b639e154ae882cec1f8651c70 (patch)
treefa47ce291a4dcbb696b39311de7542db17a4ddfe /src
parentc0d63ac9db44ae1b0161b7398bb61385a6f4ac88 (diff)
downloadstrongswan-5238c9afefb7783b639e154ae882cec1f8651c70.tar.bz2
strongswan-5238c9afefb7783b639e154ae882cec1f8651c70.tar.xz
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
Diffstat (limited to 'src')
-rw-r--r--src/charon/Makefile.am2
-rw-r--r--src/charon/config/connections/local_connection_store.c2
-rw-r--r--src/charon/config/credentials/local_credential_store.c7
-rw-r--r--src/charon/config/policies/local_policy_store.c2
-rw-r--r--src/charon/config/policies/policy.c8
-rw-r--r--src/charon/config/proposal.c1
-rw-r--r--src/charon/queues/jobs/delete_established_ike_sa_job.c1
-rw-r--r--src/charon/queues/jobs/delete_half_open_ike_sa_job.c2
-rw-r--r--src/charon/queues/jobs/incoming_packet_job.c1
-rw-r--r--src/charon/queues/jobs/initiate_ike_sa_job.c1
-rw-r--r--src/charon/sa/child_sa.c17
-rw-r--r--src/charon/sa/ike_sa.c159
-rw-r--r--src/charon/sa/states/create_child_sa_requested.c304
-rw-r--r--src/charon/sa/states/create_child_sa_requested.h4
-rw-r--r--src/charon/sa/states/delete_ike_sa_requested.c (renamed from src/charon/sa/states/delete_requested.c)28
-rw-r--r--src/charon/sa/states/delete_ike_sa_requested.h (renamed from src/charon/sa/states/delete_requested.h)22
-rw-r--r--src/charon/sa/states/ike_auth_requested.c1
-rw-r--r--src/charon/sa/states/ike_sa_established.c434
-rw-r--r--src/charon/sa/states/state.c3
-rw-r--r--src/charon/sa/states/state.h18
-rw-r--r--src/charon/testing/Makefile.am2
-rw-r--r--src/charon/testing/generator_test.c4
-rw-r--r--src/charon/testing/kernel_interface_test.c3
-rw-r--r--src/charon/threads/kernel_interface.c7
-rwxr-xr-xsrc/charon/threads/stroke_interface.c2
25 files changed, 829 insertions, 206 deletions
diff --git a/src/charon/Makefile.am b/src/charon/Makefile.am
index a94a6dce4..93546c987 100644
--- a/src/charon/Makefile.am
+++ b/src/charon/Makefile.am
@@ -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 \
diff --git a/src/charon/config/connections/local_connection_store.c b/src/charon/config/connections/local_connection_store.c
index fa3bd555d..af0ee0879 100644
--- a/src/charon/config/connections/local_connection_store.c
+++ b/src/charon/config/connections/local_connection_store.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)
{
diff --git a/src/charon/config/credentials/local_credential_store.c b/src/charon/config/credentials/local_credential_store.c
index 4ab32fe62..09eac6aaa 100644
--- a/src/charon/config/credentials/local_credential_store.c
+++ b/src/charon/config/credentials/local_credential_store.c
@@ -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);
diff --git a/src/charon/config/policies/local_policy_store.c b/src/charon/config/policies/local_policy_store.c
index 764843526..8ba65d24e 100644
--- a/src/charon/config/policies/local_policy_store.c
+++ b/src/charon/config/policies/local_policy_store.c
@@ -20,6 +20,8 @@
* for more details.
*/
+#include <string.h>
+
#include "local_policy_store.h"
#include <utils/linked_list.h>
diff --git a/src/charon/config/policies/policy.c b/src/charon/config/policies/policy.c
index ac30afe74..3e5837714 100644
--- a/src/charon/config/policies/policy.c
+++ b/src/charon/config/policies/policy.c
@@ -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;
}
/**
diff --git a/src/charon/config/proposal.c b/src/charon/config/proposal.c
index 09fa150db..0e12e6bf6 100644
--- a/src/charon/config/proposal.c
+++ b/src/charon/config/proposal.c
@@ -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)
diff --git a/src/charon/queues/jobs/delete_established_ike_sa_job.c b/src/charon/queues/jobs/delete_established_ike_sa_job.c
index 78f5c9ed1..515340da9 100644
--- a/src/charon/queues/jobs/delete_established_ike_sa_job.c
+++ b/src/charon/queues/jobs/delete_established_ike_sa_job.c
@@ -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);
diff --git a/src/charon/queues/jobs/delete_half_open_ike_sa_job.c b/src/charon/queues/jobs/delete_half_open_ike_sa_job.c
index 5de3cb222..c81783446 100644
--- a/src/charon/queues/jobs/delete_half_open_ike_sa_job.c
+++ b/src/charon/queues/jobs/delete_half_open_ike_sa_job.c
@@ -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);
diff --git a/src/charon/queues/jobs/incoming_packet_job.c b/src/charon/queues/jobs/incoming_packet_job.c
index 834b14bb2..6043b03ca 100644
--- a/src/charon/queues/jobs/incoming_packet_job.c
+++ b/src/charon/queues/jobs/incoming_packet_job.c
@@ -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;
diff --git a/src/charon/queues/jobs/initiate_ike_sa_job.c b/src/charon/queues/jobs/initiate_ike_sa_job.c
index fa8513659..16e440768 100644
--- a/src/charon/queues/jobs/initiate_ike_sa_job.c
+++ b/src/charon/queues/jobs/initiate_ike_sa_job.c
@@ -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;
diff --git a/src/charon/sa/child_sa.c b/src/charon/sa/child_sa.c
index 2321e4696..87fcea0cb 100644
--- a/src/charon/sa/child_sa.c
+++ b/src/charon/sa/child_sa.c
@@ -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);
diff --git a/src/charon/sa/ike_sa.c b/src/charon/sa/ike_sa.c
index 363e2264d..bc1871317 100644
--- a/src/charon/sa/ike_sa.c
+++ b/src/charon/sa/ike_sa.c
@@ -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;
}
@@ -779,80 +782,6 @@ static void add_child_sa(private_ike_sa_t *this, child_sa_t *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.
*/
static status_t process_message(private_ike_sa_t *this, message_t *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,
diff --git a/src/charon/sa/states/create_child_sa_requested.c b/src/charon/sa/states/create_child_sa_requested.c
index 2ff37983b..cb5313966 100644
--- a/src/charon/sa/states/create_child_sa_requested.c
+++ b/src/charon/sa/states/create_child_sa_requested.c
@@ -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>
@@ -57,6 +61,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.
*
* Is logger of ike_sa!
@@ -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);
diff --git a/src/charon/sa/states/create_child_sa_requested.h b/src/charon/sa/states/create_child_sa_requested.h
index f6f8f011d..ced6273b0 100644
--- a/src/charon/sa/states/create_child_sa_requested.h
+++ b/src/charon/sa/states/create_child_sa_requested.h
@@ -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_*/
diff --git a/src/charon/sa/states/delete_requested.c b/src/charon/sa/states/delete_ike_sa_requested.c
index ff6ec1d48..36e9c2fb2 100644
--- a/src/charon/sa/states/delete_requested.c
+++ b/src/charon/sa/states/delete_ike_sa_requested.c
@@ -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;
diff --git a/src/charon/sa/states/delete_requested.h b/src/charon/sa/states/delete_ike_sa_requested.h
index a4c6daba0..a010a0f5b 100644
--- a/src/charon/sa/states/delete_requested.h
+++ b/src/charon/sa/states/delete_ike_sa_requested.h
@@ -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_*/
diff --git a/src/charon/sa/states/ike_auth_requested.c b/src/charon/sa/states/ike_auth_requested.c
index 5e5fcda19..1cbec5b52 100644
--- a/src/charon/sa/states/ike_auth_requested.c
+++ b/src/charon/sa/states/ike_auth_requested.c
@@ -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);
diff --git a/src/charon/sa/states/ike_sa_established.c b/src/charon/sa/states/ike_sa_established.c
index acbbb3781..d408988d0 100644
--- a/src/charon/sa/states/ike_sa_established.c
+++ b/src/charon/sa/states/ike_sa_established.c
@@ -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 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;
}
/**
@@ -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);
}
diff --git a/src/charon/sa/states/state.c b/src/charon/sa/states/state.c
index b91c6cfe1..e79d33e03 100644
--- a/src/charon/sa/states/state.c
+++ b/src/charon/sa/states/state.c
@@ -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}
};
diff --git a/src/charon/sa/states/state.h b/src/charon/sa/states/state.h
index 77193e7cf..e1cd490fa 100644
--- a/src/charon/sa/states/state.h
+++ b/src/charon/sa/states/state.h
@@ -97,6 +97,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.
*
* After a call to ike_sa.close(), the IKE_SA sends a delete message
@@ -105,9 +119,7 @@ enum ike_sa_state_t {
*
* Implemented in class delete_requested.
*/
- DELETE_REQUESTED,
-
- CREATE_CHILD_SA_REQUESTED,
+ DELETE_IKE_SA_REQUESTED,
};
diff --git a/src/charon/testing/Makefile.am b/src/charon/testing/Makefile.am
index e34b8291a..6648fbb92 100644
--- a/src/charon/testing/Makefile.am
+++ b/src/charon/testing/Makefile.am
@@ -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 \
diff --git a/src/charon/testing/generator_test.c b/src/charon/testing/generator_test.c
index 8ce7cf5b7..38f4c364b 100644
--- a/src/charon/testing/generator_test.c
+++ b/src/charon/testing/generator_test.c
@@ -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);
diff --git a/src/charon/testing/kernel_interface_test.c b/src/charon/testing/kernel_interface_test.c
index cf01b0297..29b3dc34e 100644
--- a/src/charon/testing/kernel_interface_test.c
+++ b/src/charon/testing/kernel_interface_test.c
@@ -20,7 +20,8 @@
* for more details.
*/
-
+#include <unistd.h>
+
#include "kernel_interface_test.h"
#include <daemon.h>
diff --git a/src/charon/threads/kernel_interface.c b/src/charon/threads/kernel_interface.c
index f0844ee5f..41dee48a6 100644
--- a/src/charon/threads/kernel_interface.c
+++ b/src/charon/threads/kernel_interface.c
@@ -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;
}
diff --git a/src/charon/threads/stroke_interface.c b/src/charon/threads/stroke_interface.c
index 00d3d3b27..a0e0112b4 100755
--- a/src/charon/threads/stroke_interface.c
+++ b/src/charon/threads/stroke_interface.c
@@ -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);