fixed compile warnings when using -Wall
authorMartin Willi <martin@strongswan.org>
Thu, 8 Jun 2006 14:20:05 +0000 (14:20 -0000)
committerMartin Willi <martin@strongswan.org>
Thu, 8 Jun 2006 14:20:05 +0000 (14:20 -0000)
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

27 files changed:
src/charon/Makefile.am
src/charon/config/connections/local_connection_store.c
src/charon/config/credentials/local_credential_store.c
src/charon/config/policies/local_policy_store.c
src/charon/config/policies/policy.c
src/charon/config/proposal.c
src/charon/queues/jobs/delete_established_ike_sa_job.c
src/charon/queues/jobs/delete_half_open_ike_sa_job.c
src/charon/queues/jobs/incoming_packet_job.c
src/charon/queues/jobs/initiate_ike_sa_job.c
src/charon/sa/child_sa.c
src/charon/sa/ike_sa.c
src/charon/sa/states/create_child_sa_requested.c
src/charon/sa/states/create_child_sa_requested.h
src/charon/sa/states/delete_ike_sa_requested.c [new file with mode: 0644]
src/charon/sa/states/delete_ike_sa_requested.h [new file with mode: 0644]
src/charon/sa/states/delete_requested.c [deleted file]
src/charon/sa/states/delete_requested.h [deleted file]
src/charon/sa/states/ike_auth_requested.c
src/charon/sa/states/ike_sa_established.c
src/charon/sa/states/state.c
src/charon/sa/states/state.h
src/charon/testing/Makefile.am
src/charon/testing/generator_test.c
src/charon/testing/kernel_interface_test.c
src/charon/threads/kernel_interface.c
src/charon/threads/stroke_interface.c

index a94a6dc..93546c9 100644 (file)
@@ -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 \
index fa3bd55..af0ee08 100644 (file)
@@ -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)
        {
index 4ab32fe..09eac6a 100644 (file)
@@ -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);
index 7648435..8ba65d2 100644 (file)
@@ -20,6 +20,8 @@
  * for more details.
  */
 
+#include <string.h>
+
 #include "local_policy_store.h"
 
 #include <utils/linked_list.h>
index ac30afe..3e58377 100644 (file)
@@ -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;
 }
 
 /**
index 09fa150..0e12e6b 100644 (file)
@@ -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)
index 78f5c9e..515340d 100644 (file)
@@ -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);
index 5de3cb2..c817834 100644 (file)
@@ -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);
index 834b14b..6043b03 100644 (file)
@@ -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;
 
index fa85136..16e4407 100644 (file)
@@ -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;
 
index 2321e46..87fcea0 100644 (file)
@@ -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);
        
index 363e226..bc18713 100644 (file)
@@ -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,
index 2ff3798..cb53139 100644 (file)
  * 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);
index f6f8f01..ced6273 100644 (file)
@@ -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_ike_sa_requested.c b/src/charon/sa/states/delete_ike_sa_requested.c
new file mode 100644 (file)
index 0000000..36e9c2f
--- /dev/null
@@ -0,0 +1,163 @@
+/**
+ * @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);
+}
diff --git a/src/charon/sa/states/delete_ike_sa_requested.h b/src/charon/sa/states/delete_ike_sa_requested.h
new file mode 100644 (file)
index 0000000..a010a0f
--- /dev/null
@@ -0,0 +1,57 @@
+/**
+ * @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_*/
diff --git a/src/charon/sa/states/delete_requested.c b/src/charon/sa/states/delete_requested.c
deleted file mode 100644 (file)
index ff6ec1d..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-/**
- * @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);
-}
diff --git a/src/charon/sa/states/delete_requested.h b/src/charon/sa/states/delete_requested.h
deleted file mode 100644 (file)
index a4c6dab..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/**
- * @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_*/
index 5e5fcda..1cbec5b 100644 (file)
@@ -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);
index acbbb37..d408988 100644 (file)
  * 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);
 }
index b91c6cf..e79d33e 100644 (file)
@@ -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}
 };
index 77193e7..e1cd490 100644 (file)
@@ -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,
 };
 
 
index e34b829..6648fbb 100644 (file)
@@ -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 \
index 8ce7cf5..38f4c36 100644 (file)
@@ -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);
index cf01b02..29b3dc3 100644 (file)
@@ -20,7 +20,8 @@
  * for more details.
  */
 
+#include <unistd.h>
+
 #include "kernel_interface_test.h"
 
 #include <daemon.h>
index f0844ee..41dee48 100644 (file)
@@ -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;
        }
index 00d3d3b..a0e0112 100755 (executable)
@@ -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);