added support for "ike" and "esp" keywords
authorMartin Willi <martin@strongswan.org>
Thu, 15 Jun 2006 11:09:11 +0000 (11:09 -0000)
committerMartin Willi <martin@strongswan.org>
Thu, 15 Jun 2006 11:09:11 +0000 (11:09 -0000)
fixed bugs in proposal code
algorithm selection for charon works now with ipsec.conf
a lot of other fixes

17 files changed:
src/charon/config/connections/connection.c
src/charon/config/proposal.c
src/charon/config/proposal.h
src/charon/encoding/message.c
src/charon/encoding/payloads/encryption_payload.c
src/charon/encoding/payloads/notify_payload.c
src/charon/encoding/payloads/notify_payload.h
src/charon/encoding/payloads/sa_payload.c
src/charon/sa/ike_sa.c
src/charon/sa/states/ike_sa_established.c
src/charon/sa/states/responder_init.c
src/charon/testing/proposal_test.c
src/charon/testing/testcases.c
src/charon/threads/kernel_interface.c
src/charon/threads/stroke_interface.c
src/stroke/stroke.c
src/stroke/stroke.h

index 9a90f76..a938d8b 100644 (file)
@@ -200,20 +200,20 @@ static diffie_hellman_group_t get_dh_group(private_connection_t *this)
        iterator_t *iterator;
        proposal_t *proposal;
        algorithm_t *algo;
+       diffie_hellman_group_t dh_group = MODP_NONE;
        
        iterator = this->proposals->create_iterator(this->proposals, TRUE);
        while (iterator->has_next(iterator))
        {
                iterator->current(iterator, (void**)&proposal);
-               proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &algo);
-               if (algo)
+               if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &algo))
                {
-                       iterator->destroy(iterator);
-                       return algo->algorithm;
+                       dh_group = algo->algorithm;
+                       break;
                }
        }
        iterator->destroy(iterator);
-       return MODP_NONE;
+       return dh_group;
 }
 
 /**
index ef2ec94..3eb0815 100644 (file)
 #include <utils/linked_list.h>
 #include <utils/identification.h>
 #include <utils/logger.h>
+#include <utils/lexparser.h>
+#include <crypto/prfs/prf.h>
+#include <crypto/crypters/crypter.h>
+#include <crypto/signers/signer.h>
 
 
 /** 
@@ -115,8 +119,9 @@ struct private_proposal_t {
  */
 static void add_algo(linked_list_t *list, u_int8_t algo, size_t key_size)
 {
-       algorithm_t *algo_key = malloc_thing(algorithm_t);
+       algorithm_t *algo_key;
        
+       algo_key = malloc_thing(algorithm_t);
        algo_key->algorithm = algo;
        algo_key->key_size = key_size;
        list->insert_last(list, (void*)algo_key);
@@ -414,6 +419,83 @@ static void free_algo_list(linked_list_t *list)
        list->destroy(list);
 }
 
+static status_t add_string_algo(private_proposal_t *this, chunk_t alg)
+{
+       if (strncmp(alg.ptr, "aes128", alg.len) == 0)
+       {
+               add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128);
+       }
+       else if (strncmp(alg.ptr, "aes192", alg.len) == 0)
+       {
+               add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 192);
+       }
+       else if (strncmp(alg.ptr, "aes256", alg.len) == 0)
+       {
+               add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 256);
+       }
+       else if (strncmp(alg.ptr, "3des", alg.len) == 0)
+       {
+               add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_3DES, 0);
+       }
+       /* blowfish only uses some predefined key sizes yet */
+       else if (strncmp(alg.ptr, "blowfish128", alg.len) == 0)
+       {
+               add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 128);
+       }
+       else if (strncmp(alg.ptr, "blowfish192", alg.len) == 0)
+       {
+               add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 192);
+       }
+       else if (strncmp(alg.ptr, "blowfish256", alg.len) == 0)
+       {
+               add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 256);
+       }
+       else if (strncmp(alg.ptr, "sha", alg.len) == 0 ||
+                        strncmp(alg.ptr, "sha1", alg.len) == 0)
+       {
+               /* sha means we use SHA for both, PRF and AUTH */
+               add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0);
+               if (this->protocol == PROTO_IKE)
+               {
+                       add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_SHA1, 0);
+               }
+       }
+       else if (strncmp(alg.ptr, "md5", alg.len) == 0)
+       {
+               /* same for MD5 */
+               add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0);
+               if (this->protocol == PROTO_IKE)
+               {
+                       add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_MD5, 0);
+               }
+       }
+       else if (strncmp(alg.ptr, "modp1024", alg.len) == 0)
+       {
+               add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_1024_BIT, 0);
+       }
+       else if (strncmp(alg.ptr, "modp1536", alg.len) == 0)
+       {
+               add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_1536_BIT, 0);
+       }
+       else if (strncmp(alg.ptr, "modp2048", alg.len) == 0)
+       {
+               add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_2048_BIT, 0);
+       }
+       else if (strncmp(alg.ptr, "modp4096", alg.len) == 0)
+       {
+               add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_4096_BIT, 0);
+       }
+       else if (strncmp(alg.ptr, "modp8192", alg.len) == 0)
+       {
+               add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_8192_BIT, 0);
+       }
+       else
+       {
+               return FAILED;
+       }
+       return SUCCESS;
+}
+
 /**
  * Implements proposal_t.destroy.
  */
@@ -455,3 +537,77 @@ proposal_t *proposal_create(protocol_id_t protocol)
        
        return &this->public;
 }
+
+/*
+ * Describtion in header-file
+ */
+proposal_t *proposal_create_default(protocol_id_t protocol)
+{
+       private_proposal_t *this = (private_proposal_t*)proposal_create(protocol);
+       
+       switch (protocol)
+       {
+               case PROTO_IKE:
+                       add_algorithm(this, ENCRYPTION_ALGORITHM,   ENCR_AES_CBC,    128);
+                       add_algorithm(this, INTEGRITY_ALGORITHM,    AUTH_HMAC_SHA1_96, 0);
+                       add_algorithm(this, INTEGRITY_ALGORITHM,    AUTH_HMAC_MD5_96,  0);
+                       add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_SHA1,     0);
+                       add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_MD5,      0);
+                       add_algorithm(this, DIFFIE_HELLMAN_GROUP,   MODP_2048_BIT,     0);
+                       add_algorithm(this, DIFFIE_HELLMAN_GROUP,   MODP_1536_BIT,     0);
+                       add_algorithm(this, DIFFIE_HELLMAN_GROUP,   MODP_1024_BIT,     0);
+                       add_algorithm(this, DIFFIE_HELLMAN_GROUP,   MODP_4096_BIT,     0);
+                       add_algorithm(this, DIFFIE_HELLMAN_GROUP,   MODP_8192_BIT,     0);
+                       break;
+               case PROTO_ESP:
+                       add_algorithm(this, ENCRYPTION_ALGORITHM,   ENCR_AES_CBC,    128);
+                       add_algorithm(this, ENCRYPTION_ALGORITHM,   ENCR_AES_CBC,    192);
+                       add_algorithm(this, ENCRYPTION_ALGORITHM,   ENCR_AES_CBC,    256);
+                       add_algorithm(this, ENCRYPTION_ALGORITHM,   ENCR_3DES,         0);
+                       add_algorithm(this, ENCRYPTION_ALGORITHM,   ENCR_BLOWFISH,   256);
+                       add_algorithm(this, INTEGRITY_ALGORITHM,    AUTH_HMAC_SHA1_96, 0);
+                       add_algorithm(this, INTEGRITY_ALGORITHM,    AUTH_HMAC_MD5_96,  0);
+                       break;
+               case PROTO_AH:
+                       add_algorithm(this, INTEGRITY_ALGORITHM,    AUTH_HMAC_SHA1_96, 0);
+                       add_algorithm(this, INTEGRITY_ALGORITHM,    AUTH_HMAC_MD5_96,  0);
+                       break;
+       }
+       
+       return &this->public;
+}
+
+/*
+ * Describtion in header-file
+ */
+proposal_t *proposal_create_from_string(protocol_id_t protocol, const char *algs)
+{
+       private_proposal_t *this = (private_proposal_t*)proposal_create(protocol);
+       chunk_t string = {(void*)algs, strlen(algs)};
+       chunk_t alg;
+       status_t status = SUCCESS;
+       
+       eat_whitespace(&string);
+       if (string.len < 1)
+       {
+               destroy(this);
+               return NULL;
+       }
+       
+       /* get all tokens, separated by '-' */
+       while (extract_token(&alg, '-', &string))
+       {
+               status |= add_string_algo(this, alg);
+       }
+       if (string.len)
+       {
+               status |= add_string_algo(this, string);
+       }
+       if (status != SUCCESS)
+       {
+               destroy(this);
+               return NULL;
+       }
+       
+       return &this->public;
+}
index 9cb8f04..ab58ed3 100644 (file)
@@ -1,6 +1,6 @@
 /**
  * @file proposal.h
- * 
+ *
  * @brief Interface of proposal_t.
  *
  */
@@ -232,12 +232,39 @@ struct proposal_t {
 
 /**
  * @brief Create a child proposal for AH, ESP or IKE.
- * 
+ *
  * @param protocol                     protocol, such as PROTO_ESP
  * @return                                     proposal_t object
- * 
+ *
  * @ingroup config
  */
 proposal_t *proposal_create(protocol_id_t protocol);
 
+/**
+ * @brief Create a default proposal if nothing further specified.
+ *
+ * @param protocol                     protocol, such as PROTO_ESP
+ * @return                                     proposal_t object
+ *
+ * @ingroup config
+ */
+proposal_t *proposal_create_default(protocol_id_t protocol);
+
+/**
+ * @brief Create a proposal from a string identifying the algorithms.
+ *
+ * The string is in the same form as a in the ipsec.conf file.
+ * E.g.:       aes128-sha2_256-modp2048
+ *          3des-md5
+ * An additional '!' at the end of the string forces this proposal,
+ * without it the peer may choose another algorithm we support.
+ *
+ * @param protocol                     protocol, such as PROTO_ESP
+ * @param algs                         algorithms as string
+ * @return                                     proposal_t object
+ * 
+ * @ingroup config
+ */
+proposal_t *proposal_create_from_string(protocol_id_t protocol, const char *algs);
+
 #endif /* PROPOSAL_H_ */
index 0629fb7..ece2909 100644 (file)
@@ -966,7 +966,7 @@ static status_t decrypt_payloads(private_message_t *this,crypter_t *crypter, sig
                        if (payload_number != this->payloads->get_count(this->payloads))
                        {
                                /* encrypted payload is not last one */
-                               this->logger->log(this->logger, ERROR | LEVEL1, "encrypted payload is not last payload");
+                               this->logger->log(this->logger, ERROR, "encrypted payload is not last payload");
                                iterator->destroy(iterator);
                                return FAILED;
                        }
@@ -976,7 +976,7 @@ static status_t decrypt_payloads(private_message_t *this,crypter_t *crypter, sig
                        status = encryption_payload->verify_signature(encryption_payload, this->packet->get_data(this->packet));
                        if (status != SUCCESS)
                        {
-                               this->logger->log(this->logger, ERROR | LEVEL1, "encryption payload signature invalid");
+                               this->logger->log(this->logger, ERROR, "encryption payload signature invalid");
                                iterator->destroy(iterator);
                                return status;
                        }
@@ -984,7 +984,7 @@ static status_t decrypt_payloads(private_message_t *this,crypter_t *crypter, sig
                        status = encryption_payload->decrypt(encryption_payload);
                        if (status != SUCCESS)
                        {
-                               this->logger->log(this->logger, ERROR | LEVEL1
+                               this->logger->log(this->logger, ERROR, 
                                                                  "encrypted payload could not be decrypted and parsed: %s", 
                                                                  mapping_find(status_m, status));
                                iterator->destroy(iterator);
@@ -1045,7 +1045,7 @@ static status_t decrypt_payloads(private_message_t *this,crypter_t *crypter, sig
                        if (status != SUCCESS)
                        {
                                /* payload is not allowed */
-                               this->logger->log(this->logger, ERROR | LEVEL1, "payload type %s not allowed",
+                               this->logger->log(this->logger, ERROR, "payload type %s not allowed",
                                                                  mapping_find(payload_type_m,current_payload_type));
                                iterator->destroy(iterator);
                                return status;
@@ -1055,7 +1055,7 @@ static status_t decrypt_payloads(private_message_t *this,crypter_t *crypter, sig
                        if (payload_rule->encrypted != current_payload_was_encrypted)
                        {
                                /* payload was not encrypted, but should have been. or vice-versa */
-                               this->logger->log(this->logger, ERROR | LEVEL1, "payload type %s should be %s!", 
+                               this->logger->log(this->logger, ERROR, "payload type %s should be %s!", 
                                                                        mapping_find(payload_type_m,current_payload_type),
                                                                        (payload_rule->encrypted) ? "encrypted" : "not encrypted");
                                iterator->destroy(iterator);
@@ -1276,7 +1276,7 @@ message_t *message_create_notify_reply(host_t *source, host_t *destination, exch
        message->set_message_id(message,0);
        message->set_ike_sa_id(message, ike_sa_id);
        
-       payload = notify_payload_create_from_protocol_and_type(PROTO_IKE, notify_type);
+       payload = notify_payload_create_from_protocol_and_type(PROTO_NONE, notify_type);
        message->add_payload(message,(payload_t *) payload);
        
        return message;
index 358f371..20d733e 100644 (file)
@@ -385,7 +385,7 @@ static status_t decrypt(private_encryption_payload_t *this)
         */
        if (concatenated.len < iv.len)
        {
-               this->logger->log(this->logger, ERROR|LEVEL1, "could not decrypt, invalid input");
+               this->logger->log(this->logger, ERROR, "could not decrypt, invalid input");
                return FAILED;
        }
        
@@ -397,7 +397,7 @@ static status_t decrypt(private_encryption_payload_t *this)
        status = this->crypter->decrypt(this->crypter, concatenated, iv, &(this->decrypted));
        if (status != SUCCESS)
        {
-               this->logger->log(this->logger, ERROR|LEVEL1, "could not decrypt, decryption failed");
+               this->logger->log(this->logger, ERROR, "could not decrypt, decryption failed");
                return FAILED;
        }
        this->logger->log_chunk(this->logger, RAW|LEVEL2, "data after decryption with padding", this->decrypted);
@@ -412,7 +412,7 @@ static status_t decrypt(private_encryption_payload_t *this)
        /* check size again */
        if (padding_length > concatenated.len || this->decrypted.len < 0)
        {
-               this->logger->log(this->logger, ERROR|LEVEL1, "decryption failed, invalid padding length found. Invalid key?");
+               this->logger->log(this->logger, ERROR, "decryption failed, invalid padding length found. Invalid key?");
                /* decryption failed :-/ */
                return FAILED;
        }
@@ -575,7 +575,7 @@ static status_t parse(private_encryption_payload_t *this)
                status = current_payload->verify(current_payload);
                if (status != SUCCESS)
                {
-                       this->logger->log(this->logger, ERROR|LEVEL1, "%s verification failed: %s", 
+                       this->logger->log(this->logger, ERROR, "%s verification failed: %s", 
                                                                mapping_find(payload_type_m,current_payload->get_type(current_payload)),
                                                                mapping_find(status_m, status));
                        current_payload->destroy(current_payload);
index a09e337..575b4e5 100644 (file)
@@ -175,25 +175,24 @@ static status_t verify(private_notify_payload_t *this)
 {
        switch (this->protocol_id)
        {
+               case PROTO_NONE:
                case PROTO_IKE:
-                       if (this->spi.len != 8)
-                       {
-                               return FAILED;
-                       }
                        break;
                case PROTO_AH:
                case PROTO_ESP:
                        if (this->spi.len != 4)
                        {
+                               this->logger->log(this->logger, ERROR, "Invalid SPI size for %s", 
+                                                                 mapping_find(protocol_id_m, this->protocol_id));
                                return FAILED;
                        }
                        break;
                default:
+                       this->logger->log(this->logger, ERROR, "Unknown protocol (%d)", this->protocol_id);
                        return FAILED;
        }
-               
-       /* TODO: Check all kinds of notify */
        
+       /* TODO: Check all kinds of notify */
        if (this->notify_message_type == INVALID_KE_PAYLOAD)
        {
                /* check notification data */
@@ -316,12 +315,10 @@ static void set_notify_message_type(private_notify_payload_t *this, u_int16_t no
 /**
  * Implementation of notify_payload_t.get_spi.
  */
-static u_int64_t get_spi(private_notify_payload_t *this)
+static u_int32_t get_spi(private_notify_payload_t *this)
 {
        switch (this->protocol_id)
        {
-               case PROTO_IKE:
-                       return *((u_int64_t*)this->spi.ptr);
                case PROTO_AH:
                case PROTO_ESP:
                        return *((u_int32_t*)this->spi.ptr);
@@ -333,15 +330,11 @@ static u_int64_t get_spi(private_notify_payload_t *this)
 /**
  * Implementation of notify_payload_t.set_spi.
  */
-static void set_spi(private_notify_payload_t *this, u_int64_t spi)
+static void set_spi(private_notify_payload_t *this, u_int32_t spi)
 {
        chunk_free(&this->spi);
        switch (this->protocol_id)
        {
-               case PROTO_IKE:
-                       this->spi = chunk_alloc(8);
-                       *((u_int64_t*)this->spi.ptr) = spi;
-                       break;
                case PROTO_AH:
                case PROTO_ESP:
                        this->spi = chunk_alloc(4);
@@ -422,8 +415,8 @@ notify_payload_t *notify_payload_create()
        this->public.set_protocol_id  = (void (*) (notify_payload_t *,u_int8_t)) set_protocol_id;
        this->public.get_notify_message_type = (notify_message_type_t (*) (notify_payload_t *)) get_notify_message_type;
        this->public.set_notify_message_type = (void (*) (notify_payload_t *,notify_message_type_t)) set_notify_message_type;
-       this->public.get_spi = (u_int64_t (*) (notify_payload_t *)) get_spi;
-       this->public.set_spi = (void (*) (notify_payload_t *,u_int64_t)) set_spi;
+       this->public.get_spi = (u_int32_t (*) (notify_payload_t *)) get_spi;
+       this->public.set_spi = (void (*) (notify_payload_t *,u_int32_t)) set_spi;
        this->public.get_notification_data = (chunk_t (*) (notify_payload_t *)) get_notification_data;
        this->public.set_notification_data = (void (*) (notify_payload_t *,chunk_t)) set_notification_data;
        this->public.destroy = (void (*) (notify_payload_t *)) destroy;
index ef425f3..e154936 100644 (file)
@@ -131,19 +131,23 @@ struct notify_payload_t {
 
        /**
         * @brief Returns the currently set spi of this payload.
+        * 
+        * This is only valid for notifys with protocol AH|ESP
         *
         * @param this  calling notify_payload_t object
         * @return              SPI value
         */
-       u_int64_t (*get_spi) (notify_payload_t *this);
+       u_int32_t (*get_spi) (notify_payload_t *this);
        
        /**
         * @brief Sets the spi of this payload.
         * 
+        * This is only valid for notifys with protocol AH|ESP
+        * 
         * @param this  calling notify_payload_t object
         * @param spi   SPI value
         */
-       void (*set_spi) (notify_payload_t *this, u_int64_t spi);
+       void (*set_spi) (notify_payload_t *this, u_int32_t spi);
 
        /**
         * @brief Returns the currently set notification data of payload.
index a54e406..0c752b8 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <encoding/payloads/encodings.h>
 #include <utils/linked_list.h>
+#include <utils/logger_manager.h>
 
 
 typedef struct private_sa_payload_t private_sa_payload_t;
@@ -61,6 +62,11 @@ struct private_sa_payload_t {
        linked_list_t * proposals;
        
        /**
+        * Logger for error handling
+        */
+       logger_t *logger;
+       
+       /**
         * @brief Computes the length of this payload.
         *
         * @param this  calling private_sa_payload_t object
@@ -112,7 +118,7 @@ encoding_rule_t sa_payload_encodings[] = {
  */
 static status_t verify(private_sa_payload_t *this)
 {
-       int proposal_number = 1;
+       int expected_number = 1, current_number;
        status_t status = SUCCESS;
        iterator_t *iterator;
        bool first = TRUE;
@@ -124,25 +130,28 @@ static status_t verify(private_sa_payload_t *this)
        {
                proposal_substructure_t *current_proposal;
                iterator->current(iterator,(void **)&current_proposal);
-               if (current_proposal->get_proposal_number(current_proposal) > proposal_number)
+               current_number = current_proposal->get_proposal_number(current_proposal);
+               if (current_number > expected_number)
                {
                        if (first) 
                        {
-                               /* first number must be 1 */
+                               this->logger->log(this->logger, ERROR, "first proposal is not proposal #1");
                                status = FAILED;
                                break;
                        }
                        
-                       if (current_proposal->get_proposal_number(current_proposal) != (proposal_number + 1))
+                       if (current_number != (expected_number + 1))
                        {
-                               /* must be only one more then previous proposal */
+                               this->logger->log(this->logger, ERROR, "proposal number is %d, excepted %d or %d",
+                                                                 current_number, expected_number, expected_number + 1);
                                status = FAILED;
                                break;
                        }
                }
-               else if (current_proposal->get_proposal_number(current_proposal) < proposal_number)
+               else if (current_number < expected_number)
                {
                        /* must not be smaller then proceeding one */
+                       this->logger->log(this->logger, ERROR, "proposal number smaller than that of previous proposal");
                        status = FAILED;
                        break;
                }
@@ -150,9 +159,11 @@ static status_t verify(private_sa_payload_t *this)
                status = current_proposal->payload_interface.verify(&(current_proposal->payload_interface));
                if (status != SUCCESS)
                {
+                       this->logger->log(this->logger, ERROR, "proposal substructure verification failed");
                        break;
                }
                first = FALSE;
+               expected_number = current_number;
        }
        
        iterator->destroy(iterator);
@@ -358,6 +369,7 @@ sa_payload_t *sa_payload_create()
        this->critical = FALSE;
        this->next_payload = NO_PAYLOAD;
        this->payload_length = SA_PAYLOAD_HEADER_LENGTH;
+       this->logger = logger_manager->get_logger(logger_manager, PARSER);
 
        this->proposals = linked_list_create();
        return &this->public;
index b4a123d..4bffae9 100644 (file)
@@ -368,8 +368,7 @@ static status_t build_transforms(private_ike_sa_t *this, proposal_t *proposal, d
        {
                this->prf->destroy(this->prf);
        }
-       proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &algo);
-       if (algo == NULL)
+       if (!proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &algo))
        {
                this->logger->log(this->logger, ERROR|LEVEL2, "No PRF algoithm selected!?");
                return FAILED;
@@ -434,8 +433,7 @@ static status_t build_transforms(private_ike_sa_t *this, proposal_t *proposal, d
        
        
        /* SK_ai/SK_ar used for integrity protection */
-       proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &algo);
-       if (algo == NULL)
+       if (!proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &algo))
        {
                this->logger->log(this->logger, ERROR|LEVEL2, "No integrity algoithm selected?!");
                return FAILED;
@@ -472,8 +470,7 @@ static status_t build_transforms(private_ike_sa_t *this, proposal_t *proposal, d
        
        
        /* SK_ei/SK_er used for encryption */
-       proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &algo);
-       if (algo == NULL)
+       if (!proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &algo))
        {
                this->logger->log(this->logger, ERROR|LEVEL2, "No encryption algoithm selected!?");
                return FAILED;
@@ -510,7 +507,6 @@ static status_t build_transforms(private_ike_sa_t *this, proposal_t *proposal, d
        chunk_free(&key);
        
        /* SK_pi/SK_pr used for authentication */
-       proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &algo);
        if (this->prf_auth_i != NULL)
        {
                this->prf_auth_i->destroy(this->prf_auth_i);
@@ -520,6 +516,7 @@ static status_t build_transforms(private_ike_sa_t *this, proposal_t *proposal, d
                this->prf_auth_r->destroy(this->prf_auth_r);
        }
        
+       proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &algo);
        this->prf_auth_i = prf_create(algo->algorithm);
        this->prf_auth_r = prf_create(algo->algorithm);
        
@@ -724,7 +721,7 @@ static void send_notify(private_ike_sa_t *this, exchange_type_t exchange_type, n
        this->logger->log(this->logger, CONTROL|LEVEL2, "Going to build message with notify payload");
        /* set up the reply */
        build_message(this, exchange_type, FALSE, &response);
-       payload = notify_payload_create_from_protocol_and_type(PROTO_IKE, type);
+       payload = notify_payload_create_from_protocol_and_type(PROTO_NONE, type);
        if ((data.ptr != NULL) && (data.len > 0))
        {
                this->logger->log(this->logger, CONTROL|LEVEL2, "Add Data to notify payload");
index 46c1810..51ac972 100644 (file)
@@ -133,6 +133,8 @@ static status_t build_sa_payload(private_ike_sa_established_t *this, sa_payload_
                prf_plus = prf_plus_create(this->ike_sa->get_child_prf(this->ike_sa), seed);
                this->logger->log_chunk(this->logger, RAW|LEVEL2, "Rekey seed", seed);
                chunk_free(&seed);
+               chunk_free(&this->nonce_i);
+               chunk_free(&this->nonce_r);
                
                policy = this->ike_sa->get_policy(this->ike_sa);
                connection = this->ike_sa->get_connection(this->ike_sa);
@@ -226,20 +228,19 @@ static status_t build_nonce_payload(private_ike_sa_established_t *this, nonce_pa
        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);
        
+       this->nonce_i = nonce_request->get_nonce(nonce_request);
+       
        return SUCCESS;
 }
 
@@ -431,6 +432,7 @@ static status_t process_informational(private_ike_sa_established_t *this, messag
                         * 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));
+                       this->ike_sa->send_response(this->ike_sa, response);
                        return DESTROY_ME;
                }
                else
@@ -523,9 +525,6 @@ static status_t process_message(private_ike_sa_established_t *this, message_t *m
                                                          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;
 }
 
@@ -542,6 +541,8 @@ static ike_sa_state_t get_state(private_ike_sa_established_t *this)
  */
 static void destroy(private_ike_sa_established_t *this)
 {
+       chunk_free(&this->nonce_i);
+       chunk_free(&this->nonce_r);
        free(this);
 }
 
index 3f95229..809dd6e 100644 (file)
@@ -344,8 +344,10 @@ static status_t build_sa_payload(private_responder_init_t *this,sa_payload_t *sa
                return DESTROY_ME;
        }
        /* get selected DH group to force policy, this is very restrictive!? */
-       this->proposal->get_algorithm(this->proposal, DIFFIE_HELLMAN_GROUP, &algo);
-       this->dh_group_number = algo->algorithm;
+       if (this->proposal->get_algorithm(this->proposal, DIFFIE_HELLMAN_GROUP, &algo))
+       {
+               this->dh_group_number = algo->algorithm;
+       }
        
        this->logger->log(this->logger, CONTROL | LEVEL2, "SA Payload processed");
        
index 7adad91..d25573e 100644 (file)
  */
 void test_proposal(protected_tester_t *tester)
 {
-       proposal_t *proposal1, *proposal2, *proposal3;
+       proposal_t *proposal1, *proposal2, *proposal3, *proposal4;
        iterator_t *iterator;
        algorithm_t *algo;
        bool result;
 
        proposal1 = proposal_create(PROTO_ESP);
        proposal1->add_algorithm(proposal1, ENCRYPTION_ALGORITHM, ENCR_3DES, 0);
-       proposal1->add_algorithm(proposal1, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 32);
-       proposal1->add_algorithm(proposal1, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 16);
+       proposal1->add_algorithm(proposal1, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 256);
+       proposal1->add_algorithm(proposal1, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128);
        proposal1->add_algorithm(proposal1, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 0);
        proposal1->add_algorithm(proposal1, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0);
        proposal1->add_algorithm(proposal1, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0);
@@ -49,8 +49,9 @@ void test_proposal(protected_tester_t *tester)
        
        proposal2 = proposal_create(PROTO_ESP);
        proposal2->add_algorithm(proposal2, ENCRYPTION_ALGORITHM, ENCR_3IDEA, 0);
-       proposal2->add_algorithm(proposal2, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 0);
+       proposal2->add_algorithm(proposal2, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128);
        proposal2->add_algorithm(proposal2, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0);
+       proposal2->add_algorithm(proposal2, DIFFIE_HELLMAN_GROUP, MODP_1024_BIT, 0);
        
        /* ah and esp prop */
        proposal3 = proposal1->select(proposal1, proposal2);
@@ -60,13 +61,12 @@ void test_proposal(protected_tester_t *tester)
                result = proposal3->get_algorithm(proposal3, ENCRYPTION_ALGORITHM, &algo);
                tester->assert_true(tester, result, "encryption algo select");
                tester->assert_true(tester, algo->algorithm == ENCR_AES_CBC, "encryption algo");
-               tester->assert_true(tester, algo->key_size == 16, "encryption keylen");
+               tester->assert_true(tester, algo->key_size == 128, "encryption keylen");
                
                
                result = proposal3->get_algorithm(proposal3, INTEGRITY_ALGORITHM, &algo);
                tester->assert_true(tester, result, "integrity algo select");
                tester->assert_true(tester, algo->algorithm == AUTH_HMAC_MD5_96, "integrity algo");
-               tester->assert_true(tester, algo->key_size == 16, "integrity keylen");
                
                iterator = proposal3->create_algorithm_iterator(proposal3, INTEGRITY_ALGORITHM);
                tester->assert_false(tester, iterator == NULL, "integrity algo select");
@@ -74,7 +74,6 @@ void test_proposal(protected_tester_t *tester)
                {
                        iterator->current(iterator, (void**)&algo);
                        tester->assert_true(tester, algo->algorithm == AUTH_HMAC_MD5_96, "integrity algo");
-                       tester->assert_true(tester, algo->key_size == 16, "integrity keylen");
                }
                iterator->destroy(iterator);
                proposal3->destroy(proposal3);
@@ -82,5 +81,25 @@ void test_proposal(protected_tester_t *tester)
        
        proposal1->destroy(proposal1);
        proposal2->destroy(proposal2);
+       
+       /* from string tests */
+       
+       proposal1 = proposal_create_from_string(PROTO_ESP, "3des-md5!");
+       proposal2 = proposal_create_from_string(PROTO_ESP, "3des-md5-modp1024!");
+       proposal3 = proposal_create_from_string(PROTO_ESP, "aes256-sha1");
+       
+       proposal4 = proposal1->select(proposal1, proposal2);
+       tester->assert_true(tester, proposal4 == NULL, "from string 1");
+       
+       proposal4 = proposal1->select(proposal1, proposal3);
+       tester->assert_true(tester, proposal4 != NULL, "from string 2");
+       
+       result = proposal4->get_algorithm(proposal4, ENCRYPTION_ALGORITHM, &algo);
+       tester->assert_true(tester, result, "from string 3");
+       tester->assert_true(tester, algo->algorithm == ENCR_3DES, "from string 4");
+       result = proposal4->get_algorithm(proposal4, INTEGRITY_ALGORITHM, &algo);
+       tester->assert_true(tester, result, "from string 5");
+       tester->assert_true(tester, algo->algorithm == AUTH_HMAC_MD5_96, "from string 6");
+       
        return;
 }
index 2c8c04a..c4a4ad9 100644 (file)
@@ -252,7 +252,7 @@ int main()
        tester_t *tester = tester_create(test_output, FALSE);
        
        //tester->perform_tests(tester,all_tests);
-       tester->perform_test(tester,&kernel_interface_test);
+       tester->perform_test(tester,&proposal_test);
        
        
        tester->destroy(tester);
index 617e324..6416073 100644 (file)
@@ -302,6 +302,7 @@ static status_t get_spi(private_kernel_interface_t *this,
        else
        {
                *spi = response->sa.id.spi;
+               this->logger->log(this->logger, CONTROL|LEVEL1, "SPI is 0x%x", *spi);
        }
        free(response);
        
index a98d476..67ed97c 100755 (executable)
@@ -179,7 +179,9 @@ static void stroke_add_conn(private_stroke_t *this, stroke_msg_t *msg)
        pop_string(msg, &msg->add_conn.other.cert);
        pop_string(msg, &msg->add_conn.me.ca);
        pop_string(msg, &msg->add_conn.other.ca);
-                               
+       pop_string(msg, &msg->add_conn.algorithms.ike);
+       pop_string(msg, &msg->add_conn.algorithms.esp);
+       
        this->logger->log(this->logger, CONTROL, "received stroke: add connection \"%s\"", msg->add_conn.name);
                                
        my_host = msg->add_conn.me.address?
@@ -343,18 +345,91 @@ static void stroke_add_conn(private_stroke_t *this, stroke_msg_t *msg)
        connection = connection_create(msg->add_conn.name, msg->add_conn.ikev2,
                                                                   my_host, other_host,
                                                                   RSA_DIGITAL_SIGNATURE);
-       proposal = proposal_create(PROTO_IKE);
-       proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128);
-       proposal->add_algorithm(proposal, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0);
-       proposal->add_algorithm(proposal, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0);
-       proposal->add_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_SHA1, 0);
-       proposal->add_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_MD5, 0);
-       proposal->add_algorithm(proposal, DIFFIE_HELLMAN_GROUP, MODP_2048_BIT, 0);
-       proposal->add_algorithm(proposal, DIFFIE_HELLMAN_GROUP, MODP_1536_BIT, 0);
-       proposal->add_algorithm(proposal, DIFFIE_HELLMAN_GROUP, MODP_1024_BIT, 0);
-       proposal->add_algorithm(proposal, DIFFIE_HELLMAN_GROUP, MODP_4096_BIT, 0);
-       proposal->add_algorithm(proposal, DIFFIE_HELLMAN_GROUP, MODP_8192_BIT, 0);
-       connection->add_proposal(connection, proposal);
+       if (msg->add_conn.algorithms.ike)
+       {
+               char *proposal_string;
+               char *strict = msg->add_conn.algorithms.ike + strlen(msg->add_conn.algorithms.ike) - 1;
+               if (*strict == '!')
+               {
+                       *strict = '\0';
+               }
+               else
+               {
+                       strict = NULL;
+               }
+               while ((proposal_string = strsep(&msg->add_conn.algorithms.ike, ",")))
+               {
+                       proposal = proposal_create_from_string(PROTO_IKE, proposal_string);
+                       if (proposal == NULL)
+                       {
+                               this->logger->log(this->logger, ERROR, "invalid IKE proposal string: %s", msg->add_conn.algorithms.esp);
+                               my_id->destroy(my_id);
+                               other_id->destroy(other_id);
+                               my_ts->destroy(my_ts);
+                               other_ts->destroy(other_ts);
+                               my_ca->destroy(my_ca);
+                               other_ca->destroy(other_ca);
+                               connection->destroy(connection);
+                               return;
+                       }
+                       connection->add_proposal(connection, proposal);
+               }
+               if (!strict)
+               {
+                       proposal = proposal_create_default(PROTO_IKE);
+                       connection->add_proposal(connection, proposal);
+               }
+       }
+       else
+       {
+               proposal = proposal_create_default(PROTO_IKE);
+               connection->add_proposal(connection, proposal);
+       }
+       
+       policy = policy_create(msg->add_conn.name, my_id, other_id,
+                                                  msg->add_conn.rekey.ipsec_lifetime,
+                                                  msg->add_conn.rekey.ipsec_lifetime - msg->add_conn.rekey.margin,
+                                                  msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100);
+       policy->add_my_traffic_selector(policy, my_ts);
+       policy->add_other_traffic_selector(policy, other_ts);
+       policy->add_authorities(policy, my_ca, other_ca);
+       
+       if (msg->add_conn.algorithms.esp)
+       {
+               char *proposal_string;
+               char *strict = msg->add_conn.algorithms.esp + strlen(msg->add_conn.algorithms.esp) - 1;
+               if (*strict == '!')
+               {
+                       *strict = '\0';
+               }
+               else
+               {
+                       strict = NULL;
+               }
+               
+               while ((proposal_string = strsep(&msg->add_conn.algorithms.esp, ",")))
+               {
+                       proposal = proposal_create_from_string(PROTO_ESP, proposal_string);
+                       if (proposal == NULL)
+                       {
+                               this->logger->log(this->logger, ERROR, "invalid ESP proposal string: %s", msg->add_conn.algorithms.esp);
+                               policy->destroy(policy);
+                               connection->destroy(connection);
+                               return;
+                       }
+                       policy->add_proposal(policy, proposal);
+               }
+               if (!strict)
+               {
+                       proposal = proposal_create_default(PROTO_ESP);
+                       policy->add_proposal(policy, proposal);
+               }
+       }
+       else
+       {
+               proposal = proposal_create_default(PROTO_ESP);
+               policy->add_proposal(policy, proposal);
+       }
        
        /* add to global connection list */
        charon->connections->add_connection(charon->connections, connection);
@@ -364,23 +439,6 @@ static void stroke_add_conn(private_stroke_t *this, stroke_msg_t *msg)
                                          my_id->get_string(my_id),
                                          other_host->get_address(other_host),
                                          other_id->get_string(other_id));
-       
-       policy = policy_create(msg->add_conn.name, my_id, other_id,
-                                                  msg->add_conn.rekey.ipsec_lifetime,
-                                                  msg->add_conn.rekey.ipsec_lifetime - msg->add_conn.rekey.margin,
-                                                  msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100);
-       proposal = proposal_create(PROTO_ESP);
-       proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128);
-       proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 256);
-       proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, ENCR_3DES, 0);
-       proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 256);
-       proposal->add_algorithm(proposal, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0);
-       proposal->add_algorithm(proposal, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0);
-       policy->add_proposal(policy, proposal);
-       policy->add_my_traffic_selector(policy, my_ts);
-       policy->add_other_traffic_selector(policy, other_ts);
-       policy->add_authorities(policy, my_ca, other_ca);
-
        /* add to global policy list */
        charon->policies->add_policy(charon->policies, policy);
 }
index b8b0cc0..7d9e674 100644 (file)
@@ -113,6 +113,9 @@ static int add_connection(char *name,
        msg.add_conn.rekey.tries = 0;
        msg.add_conn.rekey.fuzz = 0;
        
+       msg.add_conn.algorithms.ike = NULL;
+       msg.add_conn.algorithms.esp = NULL;
+       
        msg.add_conn.me.id = push_string(&msg, my_id);
        msg.add_conn.me.address = push_string(&msg, my_addr);
        msg.add_conn.me.subnet = push_string(&msg, my_net);
index 0544ca8..64a538b 100644 (file)
@@ -96,6 +96,10 @@ struct stroke_msg_t {
                        char *name;
                        bool ikev2;
                        struct {
+                               char *ike;
+                               char *esp;
+                       } algorithms;
+                       struct {
                                time_t ipsec_lifetime;
                                time_t ike_lifetime;
                                time_t margin;