- added deletion of IKE_SA
authorJan Hutter <jhutter@hsr.ch>
Mon, 12 Dec 2005 14:14:52 +0000 (14:14 -0000)
committerJan Hutter <jhutter@hsr.ch>
Mon, 12 Dec 2005 14:14:52 +0000 (14:14 -0000)
Source/charon/config/configuration_manager.c
Source/charon/encoding/message.c
Source/charon/sa/ike_sa.c
Source/charon/sa/ike_sa.h
Source/charon/sa/states/ike_auth_requested.c
Source/charon/sa/states/ike_sa_established.c
Source/charon/threads/thread_pool.c

index f2c726d..4e9cdc5 100644 (file)
@@ -745,15 +745,19 @@ static status_t get_rsa_private_key(private_configuration_manager_t *this, ident
  */
 static status_t get_retransmit_timeout (private_configuration_manager_t *this, u_int32_t retransmit_count, u_int32_t *timeout)
 {
+       int new_timeout = this->first_retransmit_timeout, i;
        if ((retransmit_count > this->max_retransmit_count) && (this->max_retransmit_count != 0))
        {
                return FAILED;
        }
        
-       /**
-        * TODO implement a good retransmit policy
-        */
-       *timeout = this->first_retransmit_timeout * (retransmit_count + 1);
+
+       for (i = 0; i < retransmit_count; i++)
+       {
+               new_timeout *= 2;
+       }
+       
+       *timeout = new_timeout;
        
        return SUCCESS;
 }
index b67f06d..2aedf84 100644 (file)
@@ -165,6 +165,27 @@ static payload_rule_t ike_auth_r_payload_rules[] = {
        {CONFIGURATION,0,1,TRUE,FALSE},
 };
 
+
+/**
+ * Message rule for INFORMATIONAL from initiator.
+ */
+static payload_rule_t informational_i_payload_rules[] = {
+       {NOTIFY,0,MAX_NOTIFY_PAYLOADS,TRUE,FALSE},
+       {CONFIGURATION,0,1,TRUE,FALSE},
+       {DELETE,0,1,TRUE,FALSE},
+       
+};
+
+/**
+ * Message rule for INFORMATIONAL from responder.
+ */
+static payload_rule_t informational_r_payload_rules[] = {
+       {NOTIFY,0,MAX_NOTIFY_PAYLOADS,TRUE,FALSE},
+       {CONFIGURATION,0,1,TRUE,FALSE},
+       {DELETE,0,1,TRUE,FALSE},
+};
+
+
 /**
  * Message rules, defines allowed payloads.
  */
@@ -172,7 +193,9 @@ static message_rule_t message_rules[] = {
        {IKE_SA_INIT,TRUE,FALSE,(sizeof(ike_sa_init_i_payload_rules)/sizeof(payload_rule_t)),ike_sa_init_i_payload_rules},
        {IKE_SA_INIT,FALSE,FALSE,(sizeof(ike_sa_init_r_payload_rules)/sizeof(payload_rule_t)),ike_sa_init_r_payload_rules},
        {IKE_AUTH,TRUE,TRUE,(sizeof(ike_auth_i_payload_rules)/sizeof(payload_rule_t)),ike_auth_i_payload_rules},
-       {IKE_AUTH,FALSE,TRUE,(sizeof(ike_auth_r_payload_rules)/sizeof(payload_rule_t)),ike_auth_r_payload_rules}
+       {IKE_AUTH,FALSE,TRUE,(sizeof(ike_auth_r_payload_rules)/sizeof(payload_rule_t)),ike_auth_r_payload_rules},
+       {INFORMATIONAL,TRUE,TRUE,(sizeof(informational_i_payload_rules)/sizeof(payload_rule_t)),informational_i_payload_rules},
+       {INFORMATIONAL,FALSE,TRUE,(sizeof(informational_r_payload_rules)/sizeof(payload_rule_t)),informational_r_payload_rules}
 };
 
 
@@ -1042,6 +1065,8 @@ static status_t encrypt_payloads (private_message_t *this,crypter_t *crypter, si
                this->payloads->remove_first(this->payloads,&current_payload);
                all_payloads->insert_last(all_payloads,current_payload);
        }
+       
+       encryption_payload = encryption_payload_create();
 
        this->logger->log(this->logger, CONTROL | LEVEL2, "Check each payloads if they have to get encrypted");
        while (all_payloads->get_count(all_payloads) > 0)
@@ -1072,10 +1097,6 @@ static status_t encrypt_payloads (private_message_t *this,crypter_t *crypter, si
                
                if (to_encrypt)
                {
-                       if (encryption_payload == NULL)
-                       {
-                               encryption_payload = encryption_payload_create();
-                       }
                        this->logger->log(this->logger, CONTROL | LEVEL2, "Insert payload %s to encryption payload", 
                                                          mapping_find(payload_type_m,current_payload->get_type(current_payload)));
 
@@ -1090,15 +1111,12 @@ static status_t encrypt_payloads (private_message_t *this,crypter_t *crypter, si
        }
 
        status = SUCCESS;
-       if (encryption_payload != NULL)
-       {
-               this->logger->log(this->logger, CONTROL | LEVEL2, "Set transforms for encryption payload ");
-               encryption_payload->set_transforms(encryption_payload,crypter,signer);
-               this->logger->log(this->logger, CONTROL | LEVEL1, "Encrypt all payloads of encrypted payload");
-               status = encryption_payload->encrypt(encryption_payload);
-               this->logger->log(this->logger, CONTROL | LEVEL2, "Add encrypted payload to payload list");
-               this->public.add_payload(&(this->public), (payload_t*)encryption_payload);
-       }
+       this->logger->log(this->logger, CONTROL | LEVEL2, "Set transforms for encryption payload ");
+       encryption_payload->set_transforms(encryption_payload,crypter,signer);
+       this->logger->log(this->logger, CONTROL | LEVEL1, "Encrypt all payloads of encrypted payload");
+       status = encryption_payload->encrypt(encryption_payload);
+       this->logger->log(this->logger, CONTROL | LEVEL2, "Add encrypted payload to payload list");
+       this->public.add_payload(&(this->public), (payload_t*)encryption_payload);
        
        all_payloads->destroy(all_payloads);
        
index d87ebe0..bae5ea7 100644 (file)
@@ -35,6 +35,7 @@
 #include <encoding/payloads/sa_payload.h>
 #include <encoding/payloads/nonce_payload.h>
 #include <encoding/payloads/ke_payload.h>
+#include <encoding/payloads/delete_payload.h>
 #include <encoding/payloads/transform_substructure.h>
 #include <encoding/payloads/transform_attribute.h>
 #include <sa/states/initiator_init.h>
@@ -374,6 +375,36 @@ static status_t initialize_connection(private_ike_sa_t *this, char *name)
 }
 
 /**
+ * Implementation of ike_sa_t.send_delete_ike_sa_request.
+ */
+static void send_delete_ike_sa_request (private_ike_sa_t *this)
+{
+       message_t *informational_request;
+       delete_payload_t *delete_payload;
+       status_t status;
+       
+       if (this->current_state->get_state(this->current_state) != IKE_SA_ESTABLISHED)
+       {
+               return;
+       }
+       
+       /* build empty INFORMATIONAL message */
+       this->protected.build_message(&(this->protected), INFORMATIONAL, TRUE, &informational_request);
+       
+       delete_payload = delete_payload_create();
+       delete_payload->set_protocol_id(delete_payload,IKE);
+               
+       informational_request->add_payload(informational_request,(payload_t *)delete_payload);
+       
+       status = this->protected.send_request(&(this->protected), informational_request);
+       if (status != SUCCESS)
+       {
+               this->logger->log(this->logger, AUDIT, "Unable to send INFORMATIONAL DELETE request");
+               informational_request->destroy(informational_request);
+       }
+}
+
+/**
  * Implementation of protected_ike_sa_t.get_id.
  */
 static ike_sa_id_t* get_id(private_ike_sa_t *this)
@@ -868,7 +899,7 @@ static void send_notify(private_ike_sa_t *this, exchange_type_t exchange_type, n
        response->add_payload(response,(payload_t *) payload);
        
        /* generate packet */   
-       this->logger->log(this->logger, CONTROL|LEVEL2, "Gnerate packet from message");
+       this->logger->log(this->logger, CONTROL|LEVEL2, "Generate packet from message");
        status = response->generate(response, this->crypter_responder, this->signer_responder, &packet);
        if (status != SUCCESS)
        {
@@ -1069,6 +1100,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
        this->protected.public.get_id = (ike_sa_id_t*(*)(ike_sa_t*)) get_id;
        this->protected.public.retransmit_request = (status_t (*) (ike_sa_t *, u_int32_t)) retransmit_request;
        this->protected.public.get_state = (ike_sa_state_t (*) (ike_sa_t *this)) get_state;
+       this->protected.public.send_delete_ike_sa_request = (void (*)(ike_sa_t*)) send_delete_ike_sa_request;
        this->protected.public.destroy = (void(*)(ike_sa_t*))destroy;
        
        /* protected functions */
index 92da57c..2533836 100644 (file)
@@ -95,6 +95,15 @@ struct ike_sa_t {
         *                                              - NOT_FOUND if request doesn't have to be retransmited
         */
        status_t (*retransmit_request) (ike_sa_t *this, u_int32_t message_id);
+       
+       /**
+        * @brief Sends a request to delete IKE_SA.
+        * 
+        * Only supported in state IKE_SA_ESTABLISHED
+        * 
+        * @param this                  calling object
+        */
+       void (*send_delete_ike_sa_request) (ike_sa_t *this);
 
        /**
         * @brief Get the id of the SA.
index f2385fe..13d980b 100644 (file)
@@ -127,11 +127,11 @@ struct private_ike_auth_requested_t {
        /**
         * Process a notify payload
         * 
-        * @param this                  calling object
-        * @param ts_initiator  TRUE if TS payload is TSi, FALSE for TSr
-        * @param ts_payload    TS payload of responder
+        * @param this                          calling object
+        * @param notify_payload        notify payload
         *
         *                                              - SUCCESS
+        *                                              - FAILED
         *                                              - DELETE_ME
         */
        status_t (*process_notify_payload) (private_ike_auth_requested_t *this, notify_payload_t *notify_payload);
@@ -174,7 +174,7 @@ static status_t process_message(private_ike_auth_requested_t *this, message_t *i
        status = ike_auth_reply->parse_body(ike_auth_reply, crypter, signer);
        if (status != SUCCESS)
        {
-               this->logger->log(this->logger, AUDIT, "IKE_AUTH reply decryption faild. Ignoring message");
+               this->logger->log(this->logger, AUDIT, "IKE_AUTH reply decryption failed. Ignoring message");
                return status;
        }
        
index 99e9a72..b020fc9 100644 (file)
@@ -23,6 +23,7 @@
 #include "ike_sa_established.h"
 
 #include <utils/allocator.h>
+#include <encoding/payloads/delete_payload.h>
 
 
 typedef struct private_ike_sa_established_t private_ike_sa_established_t;
@@ -37,10 +38,36 @@ struct private_ike_sa_established_t {
        ike_sa_established_t public;
        
        /** 
-        * Assigned IKE_SA
+        * Assigned IKE_SA.
         */
        protected_ike_sa_t *ike_sa;
        
+       /** 
+        * Assigned logger. Use logger of IKE_SA.
+        */
+       logger_t *logger;
+       
+       /**
+        * Process received DELETE payload and build DELETE payload for INFORMATIONAL response.
+        * 
+        * @param this                  calling object
+        * @param request               DELETE payload received in INFORMATIONAL request
+        * @param response              The created DELETE payload is added to this message_t object
+        */
+       status_t (*build_delete_payload) (private_ike_sa_established_t *this, delete_payload_t *request, message_t *response);
+       
+       /**
+        * Process a notify payload
+        * 
+        * @param this                          calling object
+        * @param notify_payload        notify payload
+        * @param response                      response message of type INFORMATIONAL
+        *
+        *                                              - SUCCESS
+        *                                              - FAILED
+        *                                              - DELETE_ME
+        */
+       status_t (*process_notify_payload) (private_ike_sa_established_t *this, notify_payload_t *notify_payload,message_t *response);
 };
 
 /**
@@ -48,11 +75,155 @@ struct private_ike_sa_established_t {
  */
 static status_t process_message(private_ike_sa_established_t *this, message_t *message)
 {
+       delete_payload_t *delete_request = NULL;
+       iterator_t *payloads;
+       message_t *response;
+       crypter_t *crypter;
+       signer_t *signer;
+       status_t status;
+       
+       if (message->get_exchange_type(message) != INFORMATIONAL)
+       {
+               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)));
+               return FAILED;
+       }
+       
+       if (!message->get_request(message))
+       {
+               this->logger->log(this->logger, ERROR | LEVEL1, "INFORMATIONAL responses not handled in state ike_sa_established");
+               return FAILED;
+       }
+       
+       /* get signer for verification and crypter for decryption */
+       signer = this->ike_sa->get_signer_responder(this->ike_sa);
+       crypter = this->ike_sa->get_crypter_responder(this->ike_sa);
+       
+       /* parse incoming message */
+       status = message->parse_body(message, crypter, signer);
+       if (status != SUCCESS)
+       {
+               this->logger->log(this->logger, AUDIT, "INFORMATIONAL request decryption failed. Ignoring message");
+               return status;
+       }
+       
+       /* build empty INFORMATIONAL message */
+       this->ike_sa->build_message(this->ike_sa, INFORMATIONAL, FALSE, &response);
+       
+       payloads = message->get_payload_iterator(message);
+       
+       while (payloads->has_next(payloads))
+       {
+               payload_t *payload;
+               payloads->current(payloads, (void**)&payload);
+               
+               switch (payload->get_type(payload))
+               {
+                       case NOTIFY:
+                       {
+                               notify_payload_t *notify_payload = (notify_payload_t *) payload;
+                               /* handle the notify directly, abort if no further processing required */
+                               status = this->process_notify_payload(this, notify_payload,response);
+                               if (status != SUCCESS)
+                               {
+                                       payloads->destroy(payloads);
+                                       response->destroy(response);
+                                       return status;
+                               }
+                       }
+                       case DELETE:
+                       {
+                               delete_request = (delete_payload_t *) payload;
+                       }
+                       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)
+       {
+               status = this->build_delete_payload(this, delete_request, response);
+               if (status == DELETE_ME)
+               {
+                       status = this->ike_sa->send_response(this->ike_sa, response);
+                       if (status != SUCCESS)
+                       {
+                               this->logger->log(this->logger, AUDIT, "Unable to send INFORMATIONAL reply");
+                               response->destroy(response);
+                               return FAILED;
+                       }
+                       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 INFORMATIONAL reply");
+               response->destroy(response);
+               return FAILED;
+       }
+       
+       return SUCCESS;
+}
+
+/**
+ * Implementation of private_ike_sa_established_t.build_sa_payload;
+ */
+static status_t build_delete_payload (private_ike_sa_established_t *this, delete_payload_t *request, message_t *response_message)
+{
+       delete_payload_t *response;
+       if (request->get_protocol_id(request) == IKE)
+       {
+               this->logger->log(this->logger, AUDIT, "DELETE request for IKE_SA received. Create delete reply.");
+               
+               response = delete_payload_create();
+               response->set_protocol_id(response,IKE);
+               
+               response_message->add_payload(response_message,(payload_t *)response);
+               /* IKE_SA has to get deleted */
+               return DELETE_ME;
+       }
+
+       this->logger->log(this->logger, AUDIT, "DELETE payload for CHILD_SAs not supported and handled.");
+
        return SUCCESS;
 }
 
 /**
- * Implements state_t.get_state
+ * Implementation of private_ike_sa_established_t.process_notify_payload;
+ */
+static status_t process_notify_payload (private_ike_sa_established_t *this, notify_payload_t *notify_payload, message_t *response)
+{
+       notify_message_type_t notify_message_type = notify_payload->get_notify_message_type(notify_payload);
+       
+       this->logger->log(this->logger, CONTROL|LEVEL1, "Process notify type %s for protocol %s",
+                                         mapping_find(notify_message_type_m, notify_message_type),
+                                         mapping_find(protocol_id_m, notify_payload->get_protocol_id(notify_payload)));
+                                         
+       switch (notify_message_type)
+       {
+               default:
+               {
+                       this->logger->log(this->logger, AUDIT, "INFORMATIONAL request contained an unknown notify (%d), ignored.", notify_message_type);
+               }
+       }
+
+
+       return SUCCESS; 
+}
+
+/**
+ * Implementation of state_t.get_state.
  */
 static ike_sa_state_t get_state(private_ike_sa_established_t *this)
 {
@@ -60,7 +231,7 @@ static ike_sa_state_t get_state(private_ike_sa_established_t *this)
 }
 
 /**
- * Implements state_t.get_state
+ * Implementation of state_t.get_state
  */
 static void destroy(private_ike_sa_established_t *this)
 {
@@ -79,8 +250,13 @@ ike_sa_established_t *ike_sa_established_create(protected_ike_sa_t *ike_sa)
        this->public.state_interface.get_state = (ike_sa_state_t (*) (state_t *)) get_state;
        this->public.state_interface.destroy  = (void (*) (state_t *)) destroy;
        
+       /* private functions */
+       this->process_notify_payload = process_notify_payload;
+       this->build_delete_payload = build_delete_payload;
+       
        /* private data */
        this->ike_sa = ike_sa;
+       this->logger = ike_sa->get_logger(ike_sa);
        
        return &(this->public);
 }
index 2b0259e..ac926a3 100644 (file)
@@ -444,9 +444,8 @@ static void process_delete_established_ike_sa_job(private_thread_pool_t *this, d
                }
                default:
                {
-                       /*
-                        * TODO Send delete notify
-                        */
+                       this->worker_logger->log(this->worker_logger, CONTROL, "Send delete request for IKE_SA.");                      
+                       ike_sa->send_delete_ike_sa_request(ike_sa);
                        break;
                }
        }