]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
- added notify message handling to ike_sa_init_requested_t and
authorJan Hutter <jhutter@hsr.ch>
Fri, 2 Dec 2005 11:38:56 +0000 (11:38 -0000)
committerJan Hutter <jhutter@hsr.ch>
Fri, 2 Dec 2005 11:38:56 +0000 (11:38 -0000)
responder_init_t

Source/charon/encoding/message.c
Source/charon/encoding/payloads/notify_payload.c
Source/charon/encoding/payloads/notify_payload.h
Source/charon/encoding/payloads/proposal_substructure.c
Source/charon/encoding/payloads/proposal_substructure.h
Source/charon/sa/ike_sa.c
Source/charon/sa/ike_sa.h
Source/charon/sa/states/ike_sa_init_requested.c
Source/charon/sa/states/initiator_init.c
Source/charon/sa/states/responder_init.c
Source/charon/threads/thread_pool.c

index d3b92f3f150aa279aae8c6b8ee6ea37e6d1d9241..bf33c50674707ffd9a00f124d27c77aeb4f24d6b 100644 (file)
@@ -63,6 +63,11 @@ struct supported_payload_entry_t {
          * TRUE if payload has to get encrypted
          */
         bool encrypted;
+        
+        /**
+         * Verifying can stop after checking this payload.
+         */
+        bool can_be_last;
 };
 
 typedef struct message_rule_t message_rule_t;
@@ -104,9 +109,9 @@ struct message_rule_t {
  */
 static supported_payload_entry_t supported_ike_sa_init_i_payloads[] =
 {
-       {SECURITY_ASSOCIATION,1,1,FALSE},
-       {KEY_EXCHANGE,1,1,FALSE},
-       {NONCE,1,1,FALSE},
+       {SECURITY_ASSOCIATION,1,1,FALSE,FALSE},
+       {KEY_EXCHANGE,1,1,FALSE,FALSE},
+       {NONCE,1,1,FALSE,FALSE},
 };
 
 /**
@@ -114,9 +119,10 @@ static supported_payload_entry_t supported_ike_sa_init_i_payloads[] =
  */
 static supported_payload_entry_t supported_ike_sa_init_r_payloads[] =
 {
-       {SECURITY_ASSOCIATION,1,1,FALSE},
-       {KEY_EXCHANGE,1,1,FALSE},
-       {NONCE,1,1,FALSE},
+       {NOTIFY,0,1,FALSE,TRUE},
+       {SECURITY_ASSOCIATION,1,1,FALSE,FALSE},
+       {KEY_EXCHANGE,1,1,FALSE,FALSE},
+       {NONCE,1,1,FALSE,FALSE},
 };
 
 /**
@@ -124,14 +130,14 @@ static supported_payload_entry_t supported_ike_sa_init_r_payloads[] =
  */
 static supported_payload_entry_t supported_ike_auth_i_payloads[] =
 {
-       {ID_INITIATOR,1,1,TRUE},
-       {CERTIFICATE,0,1,TRUE},
-       {CERTIFICATE_REQUEST,0,1,TRUE},
-       {ID_RESPONDER,0,1,TRUE},
-       {AUTHENTICATION,1,1,TRUE},
-       {SECURITY_ASSOCIATION,1,1,TRUE},
-       {TRAFFIC_SELECTOR_INITIATOR,1,1,TRUE},
-       {TRAFFIC_SELECTOR_RESPONDER,1,1,TRUE},
+       {ID_INITIATOR,1,1,TRUE,FALSE},
+       {CERTIFICATE,0,1,TRUE,FALSE},
+       {CERTIFICATE_REQUEST,0,1,TRUE,FALSE},
+       {ID_RESPONDER,0,1,TRUE,FALSE},
+       {AUTHENTICATION,1,1,TRUE,FALSE},
+       {SECURITY_ASSOCIATION,1,1,TRUE,FALSE},
+       {TRAFFIC_SELECTOR_INITIATOR,1,1,TRUE,FALSE},
+       {TRAFFIC_SELECTOR_RESPONDER,1,1,TRUE,FALSE},
 };
 
 /**
@@ -139,12 +145,12 @@ static supported_payload_entry_t supported_ike_auth_i_payloads[] =
  */
 static supported_payload_entry_t supported_ike_auth_r_payloads[] =
 {
-       {CERTIFICATE,0,1,TRUE},
-       {ID_RESPONDER,0,1,TRUE},
-       {AUTHENTICATION,1,1,TRUE},
-       {SECURITY_ASSOCIATION,1,1,TRUE},
-       {TRAFFIC_SELECTOR_INITIATOR,1,1,TRUE},
-       {TRAFFIC_SELECTOR_RESPONDER,1,1,TRUE},
+       {CERTIFICATE,0,1,TRUE,FALSE},
+       {ID_RESPONDER,0,1,TRUE,FALSE},
+       {AUTHENTICATION,1,1,TRUE,FALSE},
+       {SECURITY_ASSOCIATION,1,1,TRUE,FALSE},
+       {TRAFFIC_SELECTOR_INITIATOR,1,1,TRUE,FALSE},
+       {TRAFFIC_SELECTOR_RESPONDER,1,1,TRUE,FALSE},
 };
 
 /**
@@ -749,6 +755,7 @@ static status_t verify(private_message_t *this)
        status_t status;
        iterator_t *iterator;
        message_rule_t *message_rule;
+       size_t total_found_payloads = 0;
        
        this->logger->log(this->logger, CONTROL|MORE, "Verifying message structure");
        
@@ -759,7 +766,7 @@ static status_t verify(private_message_t *this)
                                                  mapping_find(exchange_type_m,this->exchange_type));
                return status;
        }
-       
+
        iterator = this->payloads->create_iterator(this->payloads,TRUE);
        /* check for payloads with wrong count*/
        for (i = 0; i < message_rule->supported_payloads_count;i++)
@@ -776,6 +783,7 @@ static status_t verify(private_message_t *this)
                        if (current_payload->get_type(current_payload) == message_rule->supported_payloads[i].payload_type)
                        {
                                found_payloads++;
+                               total_found_payloads++;
                                this->logger->log(this->logger, CONTROL | MOST, "Found payload of type %s",
                                                          mapping_find(payload_type_m,message_rule->supported_payloads[i].payload_type));
 
@@ -798,6 +806,11 @@ static status_t verify(private_message_t *this)
                        iterator->destroy(iterator);
                        return NOT_SUPPORTED;
                }
+               if ((message_rule->supported_payloads[i].can_be_last) && (this->payloads->get_count(this->payloads) == total_found_payloads))
+               {
+                       iterator->destroy(iterator);
+                       return SUCCESS; 
+               }
        }
        iterator->destroy(iterator);
        
index 31e02d2d6350f359b2552bc1b8d93d21d26ff757..3bbc44df0dd2ed383d05624461e96562d5119e74 100644 (file)
 #include <encoding/payloads/encodings.h>
 #include <utils/allocator.h>
 
+/** 
+ * String mappings for notify_message_type_t.
+ */
+mapping_t notify_message_type_m[] = {
+       {UNSUPPORTED_CRITICAL_PAYLOAD, "UNSUPPORTED_CRITICAL_PAYLOAD"},
+       {INVALID_IKE_SPI, "INVALID_IKE_SPI"},
+       {INVALID_MAJOR_VERSION, "INVALID_MAJOR_VERSION"},
+       {INVALID_SYNTAX, "INVALID_SYNTAX"},
+       {INVALID_MESSAGE_ID, "MODP_2048_BIT"},
+       {INVALID_SPI, "INVALID_SPI"},
+       {NO_PROPOSAL_CHOSEN, "NO_PROPOSAL_CHOSEN"},
+       {INVALID_KE_PAYLOAD, "INVALID_KE_PAYLOAD"},
+       {AUTHENTICATION_FAILED, "AUTHENTICATION_FAILED"},
+       {SINGLE_PAIR_REQUIRED, "SINGLE_PAIR_REQUIRED"},
+       {NO_ADDITIONAL_SAS, "NO_ADDITIONAL_SAS"},
+       {INTERNAL_ADDRESS_FAILURE, "INTERNAL_ADDRESS_FAILURE"},
+       {FAILED_CP_REQUIRED, "FAILED_CP_REQUIRED"},
+       {TS_UACCEPTABLE, "TS_UACCEPTABLE"},
+       {INVALID_SELECTORS, "INVALID_SELECTORS"},
+       {MAPPING_END, NULL}
+};
 
 typedef struct private_notify_payload_t private_notify_payload_t;
 
@@ -176,7 +197,7 @@ static void get_encoding_rules(private_notify_payload_t *this, encoding_rule_t *
  */
 static payload_type_t get_type(private_notify_payload_t *this)
 {
-       return KEY_EXCHANGE;
+       return NOTIFY;
 }
 
 /**
@@ -378,3 +399,15 @@ notify_payload_t *notify_payload_create()
        return (&(this->public));
 }
 
+/*
+ * Described in header.
+ */
+notify_payload_t *notify_payload_create_from_protocol_and_type(protocol_id_t protocol_id, notify_message_type_t notify_message_type)
+{
+       notify_payload_t *notify = notify_payload_create();
+
+       notify->set_notify_message_type(notify,notify_message_type);
+       notify->set_protocol_id(notify,protocol_id);
+       
+       return notify;
+}
index 19dd14ef01d6e7c669d65e8d7cb2281232f2a322..e877e07c7b9a9b3a3a0737ca4235dd87f6265bd1 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <types.h>
 #include <encoding/payloads/payload.h>
+#include <encoding/payloads/proposal_substructure.h>
 #include <utils/linked_list.h>
 
 /**
  */
 #define NOTIFY_PAYLOAD_HEADER_LENGTH 8
 
+typedef enum notify_message_type_t notify_message_type_t;
+
+
+/** 
+ * @brief Notify message types.
+ * 
+ * Ssee IKEv2 draft 3.10.1.
+ * 
+ * @ingroup payloads
+ */
+enum notify_message_type_t {
+       UNSUPPORTED_CRITICAL_PAYLOAD = 1,
+       INVALID_IKE_SPI = 4,
+       INVALID_MAJOR_VERSION = 5,
+       INVALID_SYNTAX = 7,
+       INVALID_MESSAGE_ID = 9,
+       INVALID_SPI = 11,
+       NO_PROPOSAL_CHOSEN = 14,
+       INVALID_KE_PAYLOAD = 17,
+       AUTHENTICATION_FAILED = 24,
+       SINGLE_PAIR_REQUIRED = 34,
+       NO_ADDITIONAL_SAS = 35,
+       INTERNAL_ADDRESS_FAILURE = 36,
+       FAILED_CP_REQUIRED = 37,
+       TS_UACCEPTABLE = 38,
+       INVALID_SELECTORS = 39
+};
+
+/** 
+ * String mappings for notify_message_type_t.
+ */
+extern mapping_t notify_message_type_m[];
+
+
+
 typedef struct notify_payload_t notify_payload_t;
 
 /**
@@ -147,5 +183,16 @@ struct notify_payload_t {
  */
 notify_payload_t *notify_payload_create();
 
+/**
+ * @brief Creates an notify_payload_t object of specific type for specific protocol id.
+ * 
+ * @param protocol_id                  protocol id (IKE, AH or ESP)
+ * @param notify_message_type  notify type (see notify_message_type_t)
+ * @return                                             created notify_payload_t object
+ * 
+ * @ingroup payloads
+ */
+notify_payload_t *notify_payload_create_from_protocol_and_type(protocol_id_t protocol_id, notify_message_type_t notify_message_type);
+
 
 #endif /*NOTIFY_PAYLOAD_H_*/
index 05b375ef926db33e9dfe06ccd4dac2ed9d57ce1e..e207e77e8ab1b54cfe1d2e6ebb6fd40294c20e59 100644 (file)
 #include <utils/allocator.h>
 #include <utils/linked_list.h>
 
+/** 
+ * String mappings for protocol_id_t.
+ */
+mapping_t protocol_id_m[] = {
+       {UNDEFINED_PROTOCOL_ID, "UNDEFINED_PROTOCOL_ID"},
+       {IKE, "IKE"},
+       {AH, "AH"},
+       {ESP, "ESP"},
+       {MAPPING_END, NULL}
+};
+
+
 typedef struct private_proposal_substructure_t private_proposal_substructure_t;
 
 /**
index a2015fbfed5817a0ae3c37ab37eb46411d6d8b4b..736987fc86cf705f93718e38fc791e005ba7784a 100644 (file)
@@ -56,7 +56,12 @@ enum protocol_id_t {
        IKE = 1,
        AH = 2,
        ESP = 3,
-};         
+};
+
+/** 
+ * String mappings for protocol_id_t.
+ */
+extern mapping_t protocol_id_m[];
 
 typedef struct proposal_substructure_t proposal_substructure_t;
 
index 1ab5d2fe00e191f94e46538bbb45043cac8ccb57..9acd8914a95daf77858db2d392220c211b3e7879 100644 (file)
@@ -665,9 +665,32 @@ static status_t set_last_responded_message (private_ike_sa_t *this,message_t * m
        return SUCCESS;
 }
 
+/**
+ * Implementation of protected_ike_sa_t.destroy.
+ */
+static void reset_message_buffers (private_ike_sa_t *this)
+{
+       this->logger->log(this->logger, CONTROL|MOST, "Reset message counters and destroy stored messages");
+       /* destroy stored requested message */
+       if (this->last_requested_message != NULL)
+       {
+               this->last_requested_message->destroy(this->last_requested_message);
+               this->last_requested_message = NULL;
+       }
+       
+       /* destroy stored responded messages */
+       if (this->last_responded_message != NULL)
+       {
+               this->last_responded_message->destroy(this->last_responded_message);
+               this->last_responded_message = NULL;
+       }
+       
+       this->message_id_out = 0;
+       this->message_id_in = 0;
+}
 
 /**
- * Implements protected_ike_sa_t.destroy.
+ * Implementation of protected_ike_sa_t.destroy.
  */
 static void destroy (private_ike_sa_t *this)
 {
@@ -792,6 +815,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
        this->protected.set_new_state = (void (*) (protected_ike_sa_t *,state_t *)) set_new_state;
        this->protected.get_crypter_initiator = (crypter_t *(*) (protected_ike_sa_t *)) get_crypter_initiator;
        this->protected.get_signer_initiator = (signer_t *(*) (protected_ike_sa_t *)) get_signer_initiator;     
+       this->protected.reset_message_buffers = (void (*) (protected_ike_sa_t *)) reset_message_buffers;
 
        /* private functions */
        this->resend_last_reply = resend_last_reply;
index a5cf637d7a3dc76fe30d86f54cf9f0409aa27813..6fd6f0e8d943ccb0a2d37275a4aa5e27c743767b 100644 (file)
@@ -283,6 +283,12 @@ struct protected_ike_sa_t {
         */
        signer_t *(*get_signer_initiator) (protected_ike_sa_t *this);
 
+       /**
+        * Resets message id counters and does destroy stored received and sent messages.
+        * 
+        * @param this                          calling object
+        */     
+       void (*reset_message_buffers) (protected_ike_sa_t *this);
 };
 
 
index 756b6b9aa4ad0b48b000b0d54dd934267dbb6ed4..aa12cd1b190272cf7a024eb78d3b2724ab1344fa 100644 (file)
 #include <encoding/payloads/sa_payload.h>
 #include <encoding/payloads/ke_payload.h>
 #include <encoding/payloads/nonce_payload.h>
+#include <encoding/payloads/notify_payload.h>
 #include <encoding/payloads/id_payload.h>
 #include <encoding/payloads/auth_payload.h>
 #include <encoding/payloads/ts_payload.h>
 #include <transforms/diffie_hellman.h>
 #include <sa/states/ike_auth_requested.h>
+#include <sa/states/initiator_init.h>
 
 
 typedef struct private_ike_sa_init_requested_t private_ike_sa_init_requested_t;
@@ -218,6 +220,70 @@ static status_t process_message(private_ike_sa_init_requested_t *this, message_t
                this->logger->log(this->logger, CONTROL|MORE, "Processing payload %s", mapping_find(payload_type_m, payload->get_type(payload)));
                switch (payload->get_type(payload))
                {
+                       case NOTIFY:
+                       {
+                               notify_payload_t *notify_payload = (notify_payload_t *) payload;
+                               
+                               
+                               this->logger->log(this->logger, CONTROL|MORE, "Process notify type %s for protocol %s",
+                                                                 mapping_find(notify_message_type_m, notify_payload->get_notify_message_type(notify_payload)),
+                                                                 mapping_find(protocol_id_m, notify_payload->get_protocol_id(notify_payload)));
+                                                                 
+                               if (notify_payload->get_protocol_id(notify_payload) != IKE)
+                               {
+                                       this->logger->log(this->logger, ERROR | MORE, "Notify reply not for IKE protocol.");
+                                       payloads->destroy(payloads);
+                                       return FAILED;  
+                               }
+                               switch (notify_payload->get_notify_message_type(notify_payload))
+                               {
+                                       case NO_PROPOSAL_CHOSEN:
+                                       {
+                                               this->logger->log(this->logger, ERROR, "Peer didn't choose a proposal!!!");
+                                               payloads->destroy(payloads);
+                                               return DELETE_ME;
+                                       }
+                                       case INVALID_KE_PAYLOAD:
+                                       {
+                                               initiator_init_t *initiator_init_state;
+                                               u_int16_t new_dh_group_priority;
+                                               
+                                               this->logger->log(this->logger, ERROR, "Selected DH group is not the one in the proposal selected by the responder!");
+                                               payloads->destroy(payloads);                                            
+                                               /* Going to change state back to initiator_init_t */
+                                               this->logger->log(this->logger, CONTROL|MOST, "Create next state object");
+                                               initiator_init_state = initiator_init_create(this->ike_sa);
+
+                                               /* buffer of sent and received messages has to get reseted */
+                                               this->ike_sa->reset_message_buffers(this->ike_sa);
+
+                                               /* state can now be changed */ 
+                                               this->ike_sa->set_new_state(this->ike_sa,(state_t *) initiator_init_state);
+
+                                               /* state has NOW changed :-) */
+                                               this->logger->log(this->logger, CONTROL|MORE, "Changed state of IKE_SA from %s to %s", mapping_find(ike_sa_state_m,INITIATOR_INIT),mapping_find(ike_sa_state_m,IKE_SA_INIT_REQUESTED) );
+
+                                               this->logger->log(this->logger, CONTROL|MOST, "Destroy old sate object");
+                                               this->logger->log(this->logger, CONTROL|MOST, "Going to retry initialization of connection");
+                                               new_dh_group_priority = this->dh_group_priority + 1;
+                                               
+                                               this->public.state_interface.destroy(&(this->public.state_interface));
+                                               return (initiator_init_state->retry_initiate_connection (initiator_init_state,new_dh_group_priority));
+                                       }
+                                       default:
+                                       {
+                                               /*
+                                                * If an unrecognized Notify type is received, the IKE_SA gets destroyed.
+                                                * 
+                                                */
+                                               
+                                               this->logger->log(this->logger, ERROR, "Notify type %s not recognized in state ike_sa_init_requested.",
+                                                                                 mapping_find(notify_message_type_m,notify_payload->get_notify_message_type(notify_payload)));
+                                               payloads->destroy(payloads);
+                                               return DELETE_ME;       
+                                       }
+                               }
+                       
                        /**
                         * TODO check for notify of type 
                         * 
@@ -225,7 +291,7 @@ static status_t process_message(private_ike_sa_init_requested_t *this, message_t
                         * 
                         * call destroy after state change not destroy_after_state_change!!!
                         */
-                       
+                       }
                        case SECURITY_ASSOCIATION:
                        {
                                sa_payload_t *sa_payload = (sa_payload_t*)payload;
index 445d507159d896a9cff47338543438e3cdfc5091..7c63a4587e64f52d5e09d41edaac46bfc355a2a5 100644 (file)
@@ -140,7 +140,7 @@ static status_t initiate_connection (private_initiator_init_t *this, char *name)
        if (status != SUCCESS)
        {       
                this->logger->log(this->logger, ERROR | MORE, "Could not retrieve INIT configuration informations for %s",name);
-               return INVALID_ARG;
+               return DELETE_ME;
        }
        
        this->ike_sa->set_init_config(this->ike_sa,init_config);
@@ -150,7 +150,7 @@ static status_t initiate_connection (private_initiator_init_t *this, char *name)
        if (status != SUCCESS)
        {       
                this->logger->log(this->logger, ERROR | MORE, "Could not retrieve SA configuration informations for %s",name);
-               return INVALID_ARG;
+               return DELETE_ME;
        }
        
        this->ike_sa->set_sa_config(this->ike_sa,sa_config);
@@ -163,7 +163,7 @@ static status_t initiate_connection (private_initiator_init_t *this, char *name)
        if (this->dh_group_number == MODP_UNDEFINED)
        {
                this->logger->log(this->logger, ERROR | MORE, "Diffie hellman group could not be  retrieved with priority %d", this->dh_group_priority);
-               return INVALID_ARG;
+               return DELETE_ME;
        }
        
        /* next step is done in retry_initiate_connection */
@@ -181,14 +181,20 @@ status_t retry_initiate_connection (private_initiator_init_t *this, int dh_group
        message_t *message;
        packet_t *packet;
        status_t status;
+       ike_sa_id_t *ike_sa_id;
+       
+       this->dh_group_priority = dh_group_priority;
                
        init_config = this->ike_sa->get_init_config(this->ike_sa);
        
+       ike_sa_id = this->ike_sa->public.get_id(&(this->ike_sa->public));
+       ike_sa_id->set_responder_spi(ike_sa_id,0);
+       
        this->dh_group_number = init_config->get_dh_group_number(init_config,dh_group_priority);
        if (this->dh_group_number == MODP_UNDEFINED)
        {
-               this->logger->log(this->logger, ERROR | MORE, "Diffie hellman group could not be retrieved with priority %d", this->dh_group_priority);
-               return INVALID_ARG;
+               this->logger->log(this->logger, ERROR | MORE, "Diffie hellman group could not be retrieved with priority %d", dh_group_priority);
+               return DELETE_ME;
        }
        
        this->diffie_hellman = diffie_hellman_create(this->dh_group_number);
@@ -208,7 +214,7 @@ status_t retry_initiate_connection (private_initiator_init_t *this, int dh_group
        {
                this->logger->log(this->logger, ERROR, "could not generate packet from message");
                message->destroy(message);
-               return status;
+               return DELETE_ME;
        }
        
        this->logger->log(this->logger, CONTROL|MOST, "Add packet to global send queue");
@@ -216,7 +222,7 @@ status_t retry_initiate_connection (private_initiator_init_t *this, int dh_group
 
        /* state can now be changed */
        this->logger->log(this->logger, CONTROL|MOST, "Create next state object");
-       next_state = ike_sa_init_requested_create(this->ike_sa, this->dh_group_number, this->diffie_hellman, this->sent_nonce);
+       next_state = ike_sa_init_requested_create(this->ike_sa, this->dh_group_priority, this->diffie_hellman, this->sent_nonce);
 
        /* last message can now be set */
        status = this->ike_sa->set_last_requested_message(this->ike_sa, message);
@@ -226,7 +232,7 @@ status_t retry_initiate_connection (private_initiator_init_t *this, int dh_group
                this->logger->log(this->logger, ERROR, "Could not set last requested message");
                (next_state->state_interface).destroy(&(next_state->state_interface));
                message->destroy(message);
-               return status;
+               return DELETE_ME;
        }
 
        /* state can now be changed */ 
@@ -332,9 +338,8 @@ static void build_nonce_payload(private_initiator_init_t *this, payload_t **payl
 /**
  * Implements state_t.get_state
  */
-static status_t process_message(private_initiator_init_t *this, message_t *message, state_t **new_state)
+static status_t process_message(private_initiator_init_t *this, message_t *message)
 {
-       *new_state = (state_t *) this;
        this->logger->log(this->logger, ERROR|MORE, "In state INITIATOR_INIT no message is processed");
        return FAILED;
 }
index 6734d68c4a37324b43072f79c2541ac0856baaa6..ee9584e2c8814696ed974feeabebe789b2e05b4b 100644 (file)
@@ -29,6 +29,7 @@
 #include <encoding/payloads/sa_payload.h>
 #include <encoding/payloads/ke_payload.h>
 #include <encoding/payloads/nonce_payload.h>
+#include <encoding/payloads/notify_payload.h>
 #include <transforms/diffie_hellman.h>
 
 
@@ -136,6 +137,16 @@ struct private_responder_init_t {
         * @param this          calling object
         */
        void (*destroy_after_state_change) (private_responder_init_t *this);
+       
+       /**
+        * Sends a IKE_SA_INIT reply with a notify payload.
+        * 
+        * @param this          calling object
+        * @param type          type of notify message
+        * @param data          data of notify message
+        */
+       void (*send_notify_reply) (private_responder_init_t *this,notify_message_type_t type, chunk_t data);
+
 };
 
 /**
@@ -230,6 +241,7 @@ static status_t process_message(private_responder_init_t *this, message_t *messa
                                {
                                        this->logger->log(this->logger, ERROR | MORE, "No proposal of suggested proposals selected");
                                        payloads->destroy(payloads);
+                                       this->send_notify_reply(this,NO_PROPOSAL_CHOSEN,CHUNK_INITIALIZER);                     
                                        return DELETE_ME;
                                }
                                
@@ -263,11 +275,18 @@ static status_t process_message(private_responder_init_t *this, message_t *messa
                                }
                                if (this->dh_group_number != group)
                                {
-                                       /* group not same as selected one */
+                                       u_int16_t accepted_group;
+                                       chunk_t accepted_group_chunk;
+                                       /* group not same as selected one 
+                                        * Maybe key exchange payload is before SA payload */
+                                       this->logger->log(this->logger, ERROR | MORE, "Diffie hellman group not as in selected proposal!");
+                                       payloads->destroy(payloads);
                                        
-                                       /**
-                                        * TODO send notify reply
-                                        */
+                                       accepted_group = htons(this->dh_group_number);
+                                       accepted_group_chunk.ptr = (u_int8_t*) &(accepted_group);
+                                       accepted_group_chunk.len = 2;
+                                       this->send_notify_reply(this,INVALID_KE_PAYLOAD,accepted_group_chunk);
+                                       return DELETE_ME;
                                }
                                
                                /* create diffie hellman object to handle DH exchange */
@@ -452,6 +471,44 @@ static ike_sa_state_t get_state(private_responder_init_t *this)
        return RESPONDER_INIT;
 }
 
+/**
+ * Implementation of private_initiator_init_t.send_notify_reply.
+ */
+static void send_notify_reply (private_responder_init_t *this,notify_message_type_t type, chunk_t data)
+{
+       notify_payload_t *payload;
+       message_t *response;
+       packet_t *packet;
+       status_t status;
+       
+       this->logger->log(this->logger, CONTROL|MOST, "Going to build message with notify payload");
+       /* set up the reply */
+       this->ike_sa->build_message(this->ike_sa, IKE_SA_INIT, FALSE, &response);
+       payload = notify_payload_create_from_protocol_and_type(IKE,type);
+       if ((data.ptr != NULL) && (data.len > 0))
+       {
+               this->logger->log(this->logger, CONTROL|MOST, "Add Data to notify payload");
+               payload->set_notification_data(payload,data);
+       }
+       
+       this->logger->log(this->logger, CONTROL|MOST, "Add Notify payload to message");
+       response->add_payload(response,(payload_t *) payload);
+       
+       /* generate packet */   
+       this->logger->log(this->logger, CONTROL|MOST, "Gnerate packet from message");
+       status = response->generate(response, NULL, NULL, &packet);
+       if (status != SUCCESS)
+       {
+               this->logger->log(this->logger, ERROR, "Could not generate packet from message");
+               return;
+       }
+       
+       this->logger->log(this->logger, CONTROL|MOST, "Add packet to global send queue");
+       charon->send_queue->add(charon->send_queue, packet);
+       this->logger->log(this->logger, CONTROL|MOST, "Destroy message");
+       response->destroy(response);
+}
+
 /**
  * Implements state_t.get_state
  */
@@ -509,12 +566,14 @@ responder_init_t *responder_init_create(protected_ike_sa_t *ike_sa)
        this->build_ke_payload = build_ke_payload;
        this->build_nonce_payload = build_nonce_payload;
        this->destroy_after_state_change = destroy_after_state_change;
+       this->send_notify_reply = send_notify_reply;
        
        /* private data */
        this->ike_sa = ike_sa;
        this->logger = this->ike_sa->get_logger(this->ike_sa);
        this->sent_nonce = CHUNK_INITIALIZER;
        this->received_nonce = CHUNK_INITIALIZER;
+       this->dh_group_number = MODP_UNDEFINED;
 
        return &(this->public);
 }
index 661d0fdb7aaa143d707f87434d4b5eb41b2a119e..f6f5278f54618807d9d2c2f0cc29d7840470ba49 100644 (file)
@@ -182,7 +182,9 @@ static void process_incoming_packet_job(private_thread_pool_t *this, incoming_pa
                this->worker_logger->log(this->worker_logger, ERROR, "IKE version %d.%d not supported", 
                                                                 message->get_major_version(message),
                                                                 message->get_minor_version(message));  
-               /* Todo send notify */
+               /*
+                * TODO send notify reply of type INVALID_MAJOR_VERSION
+                */
        }
                                
        message->get_ike_sa_id(message, &ike_sa_id);
@@ -200,16 +202,22 @@ static void process_incoming_packet_job(private_thread_pool_t *this, incoming_pa
                this->worker_logger->log(this->worker_logger, ERROR, "IKE SA could not be checked out");
                ike_sa_id->destroy(ike_sa_id);  
                message->destroy(message);
+
+               /*
+                * TODO send notify reply of type INVALID_IKE_SPI if SPI could not be found
+                */
+
                return;
        }
                                
        status = ike_sa->process_message(ike_sa, message);                              
-       if (status != SUCCESS)
+       if ((status != SUCCESS) && (status != DELETE_ME))
        {
                this->worker_logger->log(this->worker_logger, ERROR, "message could not be processed by IKE SA");
        }
                                
-       this->worker_logger->log(this->worker_logger, CONTROL|MOST, "checking in IKE SA %lld:%lld, role %s", 
+       this->worker_logger->log(this->worker_logger, CONTROL|MOST, "%s IKE SA %lld:%lld, role %s", 
+                                                        (status == DELETE_ME) ? "Checkin and delete" : "Checkin",
                                                         ike_sa_id->get_initiator_spi(ike_sa_id),
                                                         ike_sa_id->get_responder_spi(ike_sa_id),
                                                         ike_sa_id->is_initiator(ike_sa_id) ? "initiator" : "responder");