- installing of child sa works
authorMartin Willi <martin@strongswan.org>
Thu, 16 Feb 2006 09:55:07 +0000 (09:55 -0000)
committerMartin Willi <martin@strongswan.org>
Thu, 16 Feb 2006 09:55:07 +0000 (09:55 -0000)
- need correct IP adresses to actually use IPsec

23 files changed:
Source/charon/config/configuration_manager.c
Source/charon/config/proposal.c
Source/charon/encoding/generator.c
Source/charon/encoding/payloads/encryption_payload.c
Source/charon/encoding/payloads/proposal_substructure.c
Source/charon/encoding/payloads/transform_substructure.c
Source/charon/sa/child_sa.c
Source/charon/sa/child_sa.h
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_auth_requested.h
Source/charon/sa/states/ike_sa_init_requested.c
Source/charon/sa/states/ike_sa_init_responded.c
Source/charon/testcases/Makefile.testcases
Source/charon/testcases/child_sa_test.c [new file with mode: 0644]
Source/charon/testcases/child_sa_test.h [new file with mode: 0644]
Source/charon/testcases/init_config_test.c
Source/charon/testcases/kernel_interface_test.c
Source/charon/testcases/testcases.c
Source/charon/threads/kernel_interface.c
Source/charon/threads/kernel_interface.h
Source/charon/utils/logger_manager.c

index adbd0dd..07eaf53 100644 (file)
@@ -285,10 +285,8 @@ static void load_default_config (private_configuration_manager_t *this)
        /* IKE proposals for alice */
        proposal = proposal_create(1);
        proposal->add_algorithm(proposal, IKE, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 16);
-       POS;
-       proposal->add_algorithm(proposal, IKE, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 16);
-       POS;
-       proposal->add_algorithm(proposal, IKE, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_MD5, 16);
+       proposal->add_algorithm(proposal, IKE, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0);
+       proposal->add_algorithm(proposal, IKE, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_MD5, 0);
        proposal->add_algorithm(proposal, IKE, DIFFIE_HELLMAN_GROUP, MODP_1024_BIT, 0);
        proposal->add_algorithm(proposal, IKE, DIFFIE_HELLMAN_GROUP, MODP_2048_BIT, 0);
        init_config_a->add_proposal(init_config_a, proposal);
@@ -296,8 +294,8 @@ static void load_default_config (private_configuration_manager_t *this)
        /* IKE proposals for bob */
        proposal = proposal_create(1);
        proposal->add_algorithm(proposal, IKE, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 16);
-       proposal->add_algorithm(proposal, IKE, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 16);
-       proposal->add_algorithm(proposal, IKE, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_MD5, 16);
+       proposal->add_algorithm(proposal, IKE, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0);
+       proposal->add_algorithm(proposal, IKE, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_MD5, 0);
        proposal->add_algorithm(proposal, IKE, DIFFIE_HELLMAN_GROUP, MODP_2048_BIT, 0);
        init_config_b->add_proposal(init_config_b, proposal);
        
@@ -322,16 +320,17 @@ static void load_default_config (private_configuration_manager_t *this)
        /* child proposal for alice */
        proposal = proposal_create(1);
        
-       proposal->add_algorithm(proposal, AH, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 20);
-       proposal->add_algorithm(proposal, AH, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 20);
-       proposal->add_algorithm(proposal, AH, DIFFIE_HELLMAN_GROUP, MODP_1024_BIT, 0);
-       proposal->add_algorithm(proposal, AH, DIFFIE_HELLMAN_GROUP, MODP_2048_BIT, 0);
-       proposal->add_algorithm(proposal, AH, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0);
+//     proposal->add_algorithm(proposal, AH, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0);
+//     proposal->add_algorithm(proposal, AH, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0);
+//     proposal->add_algorithm(proposal, AH, DIFFIE_HELLMAN_GROUP, MODP_1024_BIT, 0);
+//     proposal->add_algorithm(proposal, AH, DIFFIE_HELLMAN_GROUP, MODP_2048_BIT, 0);
+//     proposal->add_algorithm(proposal, AH, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0);
 
        proposal->add_algorithm(proposal, ESP, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 16);
-       proposal->add_algorithm(proposal, ESP, ENCRYPTION_ALGORITHM, ENCR_3DES, 32);
-       proposal->add_algorithm(proposal, ESP, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 20);
-       proposal->add_algorithm(proposal, ESP, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 20);
+       proposal->add_algorithm(proposal, ESP, ENCRYPTION_ALGORITHM, ENCR_3DES, 0);
+       proposal->add_algorithm(proposal, ESP, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0);
+       proposal->add_algorithm(proposal, ESP, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0);
+       proposal->add_algorithm(proposal, ESP, DIFFIE_HELLMAN_GROUP, MODP_2048_BIT, 0);
        proposal->add_algorithm(proposal, ESP, DIFFIE_HELLMAN_GROUP, MODP_1024_BIT, 0);
        proposal->add_algorithm(proposal, ESP, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0);
        
@@ -340,12 +339,14 @@ static void load_default_config (private_configuration_manager_t *this)
        /* child proposal for bob */
        proposal = proposal_create(1);
        
-       proposal->add_algorithm(proposal, AH, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 20);
-       proposal->add_algorithm(proposal, AH, DIFFIE_HELLMAN_GROUP, MODP_1024_BIT, 0);
-       proposal->add_algorithm(proposal, AH, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0);
+//     proposal->add_algorithm(proposal, AH, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0);
+//     proposal->add_algorithm(proposal, AH, INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0);
+//     proposal->add_algorithm(proposal, AH, INTEGRITY_ALGORITHM, AUTH_DES_MAC, 0);
+//     proposal->add_algorithm(proposal, AH, DIFFIE_HELLMAN_GROUP, MODP_1024_BIT, 0);
+//     proposal->add_algorithm(proposal, AH, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0);
 
        proposal->add_algorithm(proposal, ESP, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 16);
-       proposal->add_algorithm(proposal, ESP, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 20);
+       proposal->add_algorithm(proposal, ESP, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0);
        proposal->add_algorithm(proposal, ESP, DIFFIE_HELLMAN_GROUP, MODP_1024_BIT, 0);
        proposal->add_algorithm(proposal, ESP, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0);
        
index 528cf98..a547583 100644 (file)
@@ -339,6 +339,7 @@ static proposal_t *select_proposal(private_proposal_t *this, private_proposal_t
        protocol_proposal_t *this_prop, *other_prop;
        protocol_id_t proto;
        bool add;
+       u_int64_t spi;
        
        /* empty proposal? no match */
        if (this->protocol_proposals->get_count(this->protocol_proposals) == 0 ||
@@ -443,6 +444,19 @@ static proposal_t *select_proposal(private_proposal_t *this, private_proposal_t
                }
        }
        iterator->destroy(iterator);
+       
+       /* apply spis from "other" */
+       spi = other->public.get_spi(&(other->public), AH);
+       if (spi)
+       {
+               selected->set_spi(selected, AH, spi);
+       }
+       spi = other->public.get_spi(&(other->public), ESP);
+       if (spi)
+       {
+               selected->set_spi(selected, ESP, spi);
+       }
+       
        /* everything matched, return new proposal */
        return selected;
 }
@@ -487,7 +501,7 @@ static void set_spi(private_proposal_t *this, protocol_id_t proto, u_int64_t spi
        protocol_proposal_t *proto_proposal = get_protocol_proposal(this, proto, FALSE);
        if (proto_proposal)
        {
-               if (proto == IKE)
+               if (proto == AH || proto == ESP)
                {
                        *((u_int32_t*)proto_proposal->spi.ptr) = (u_int32_t)spi;
                }
@@ -495,7 +509,6 @@ static void set_spi(private_proposal_t *this, protocol_id_t proto, u_int64_t spi
                {
                        *((u_int64_t*)proto_proposal->spi.ptr) = spi;
                }
-               
        }
 }
 
@@ -507,7 +520,7 @@ static u_int64_t get_spi(private_proposal_t *this, protocol_id_t proto)
        protocol_proposal_t *proto_proposal = get_protocol_proposal(this, proto, FALSE);
        if (proto_proposal)
        {
-               if (proto == IKE)
+               if (proto == AH || proto == ESP)
                {
                        return (u_int64_t)*((u_int32_t*)proto_proposal->spi.ptr);
                }
index a036b8e..ff72190 100644 (file)
@@ -341,7 +341,7 @@ static void generate_u_int_type (private_generator_t *this,encoding_type_t int_t
                                u_int8_t low_val = *(this->out_position) & 0x0F;
                                /* highval is set, low_val is not changed */
                                *(this->out_position) = high_val | low_val;
-                               this->logger->log(this->logger, RAW|LEVEL2, "   => 0x%x", *(this->out_position));
+                               this->logger->log(this->logger, RAW|LEVEL2, "   => %d", *(this->out_position));
                                /* write position is not changed, just bit position is moved */
                                this->current_bit = 4;
                        }
@@ -352,7 +352,7 @@ static void generate_u_int_type (private_generator_t *this,encoding_type_t int_t
                                /* lowval of current byte in buffer has to be set to the new value*/
                                u_int low_val = *((u_int8_t *)(this->data_struct + offset)) & 0x0F;
                                *(this->out_position) = high_val | low_val;
-                               this->logger->log(this->logger, RAW|LEVEL2, "   => 0x%x", *(this->out_position));
+                               this->logger->log(this->logger, RAW|LEVEL2, "   => %d", *(this->out_position));
                                this->out_position++;
                                this->current_bit = 0;
 
@@ -370,7 +370,7 @@ static void generate_u_int_type (private_generator_t *this,encoding_type_t int_t
                {
                        /* 8 bit values are written as they are */
                        *this->out_position = *((u_int8_t *)(this->data_struct + offset));
-                       this->logger->log(this->logger, RAW|LEVEL2, "   => 0x%x", *(this->out_position));
+                       this->logger->log(this->logger, RAW|LEVEL2, "   => %d", *(this->out_position));
                        this->out_position++;
                        break;
 
@@ -392,7 +392,7 @@ static void generate_u_int_type (private_generator_t *this,encoding_type_t int_t
                        int16_val = int16_val & 0xFF7F;
                        
                        int16_val = int16_val | attribute_format_flag;
-                       this->logger->log(this->logger, RAW|LEVEL2, "   => 0x%x", int16_val);
+                       this->logger->log(this->logger, RAW|LEVEL2, "   => %d", int16_val);
                        /* write bytes to buffer (set bit is overwritten)*/                             
                        this->write_bytes_to_buffer(this,&int16_val,sizeof(u_int16_t));
                        this->current_bit = 0;
@@ -516,7 +516,7 @@ static void generate_flag (private_generator_t *this,u_int32_t offset)
        *(this->out_position) = *(this->out_position) | flag;
        
        
-       this->logger->log(this->logger, RAW|LEVEL2, "   => 0x0%x", *(this->out_position));
+       this->logger->log(this->logger, RAW|LEVEL2, "   => %d", *(this->out_position));
 
        this->current_bit++;
        if (this->current_bit >= 8)
@@ -1017,6 +1017,8 @@ static void generate_payload (private_generator_t *this,payload_t *payload)
                                return;
                }
        }
+       this->logger->log(this->logger, CONTROL|LEVEL2, "generating %s payload finished.", 
+                                         mapping_find(payload_type_m, payload_type));
        this->logger->log_bytes(this->logger, RAW|LEVEL3, "generated data for this payload",
                                                        payload_start, this->out_position-payload_start);
 }
index bd720ea..8cbf556 100644 (file)
@@ -289,6 +289,7 @@ static status_t encrypt(private_encryption_payload_t *this)
        this->generate(this);
        
        this->logger->log(this->logger, CONTROL|LEVEL2, "encrypting payloads");
+       this->logger->log_chunk(this->logger, RAW|LEVEL2, "data to encrypt", &this->decrypted);
        
        /* build padding */
        block_size = this->crypter->get_block_size(this->crypter);
@@ -307,6 +308,8 @@ static status_t encrypt(private_encryption_payload_t *this)
        iv.len = block_size;
        randomizer->allocate_pseudo_random_bytes(randomizer, iv.len, &iv);
        randomizer->destroy(randomizer);
+       
+       this->logger->log_chunk(this->logger, RAW|LEVEL2, "data before encryption with padding", &to_crypt);
                
        /* encrypt to_crypt chunk */
        allocator_free(this->encrypted.ptr);
@@ -319,6 +322,8 @@ static status_t encrypt(private_encryption_payload_t *this)
                allocator_free(iv.ptr);
                return status;
        }
+       this->logger->log_chunk(this->logger, RAW|LEVEL2, "data after encryption", &result);
+       
        
        /* build encrypted result with iv and signature */
        this->encrypted.len = iv.len + result.len + this->signer->get_block_size(this->signer);
@@ -331,6 +336,8 @@ static status_t encrypt(private_encryption_payload_t *this)
        
        allocator_free(result.ptr);
        allocator_free(iv.ptr);
+       this->logger->log_chunk(this->logger, RAW|LEVEL2, "data after encryption with IV and (invalid) signature", &this->encrypted);
+       
        return SUCCESS;
 }
 
@@ -345,6 +352,8 @@ static status_t decrypt(private_encryption_payload_t *this)
        
        
        this->logger->log(this->logger, CONTROL|LEVEL2, "decrypting encryption payload");
+       this->logger->log_chunk(this->logger, RAW|LEVEL2, "data before decryption with IV and (invalid) signature", &this->encrypted);
+       
        
        if (this->signer == NULL || this->crypter == NULL)
        {
@@ -373,12 +382,16 @@ static status_t decrypt(private_encryption_payload_t *this)
        /* free previus data, if any */
        allocator_free(this->decrypted.ptr);
        
+       this->logger->log_chunk(this->logger, RAW|LEVEL2, "data before decryption", &concatenated);
+       
        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");
                return FAILED;
        }
+       this->logger->log_chunk(this->logger, RAW|LEVEL2, "data after decryption with padding", &this->decrypted);
+       
        
        /* get padding length, sits just bevore signature */
        padding_length = *(this->decrypted.ptr + this->decrypted.len - 1);
@@ -396,6 +409,7 @@ static status_t decrypt(private_encryption_payload_t *this)
        
        /* free padding */
        this->decrypted.ptr = allocator_realloc(this->decrypted.ptr, this->decrypted.len);
+       this->logger->log_chunk(this->logger, RAW|LEVEL2, "data after decryption without padding", &this->decrypted);
        this->logger->log(this->logger, CONTROL|LEVEL2, "decryption successful, trying to parse content");
        return (this->parse(this));
 }
index 2cf96fb..922dde4 100644 (file)
@@ -226,6 +226,7 @@ static void set_next_type(private_proposal_substructure_t *this,payload_type_t t
  */
 static size_t get_length(private_proposal_substructure_t *this)
 {
+       this->compute_length(this);
        return this->proposal_length;
 }
 
@@ -384,9 +385,8 @@ static void compute_length (private_proposal_substructure_t *this)
        iterator->destroy(iterator);
        
        length += this->spi.len;
-       this->transforms_count= transforms_count;
-       this->proposal_length = length; 
-
+       this->transforms_count = transforms_count;
+       this->proposal_length = length;
 }
 
 /**
@@ -411,8 +411,8 @@ static size_t get_spi_size (private_proposal_substructure_t *this)
 void add_to_proposal(private_proposal_substructure_t *this, proposal_t *proposal)
 {
        iterator_t *iterator = this->transforms->create_iterator(this->transforms, TRUE);
+       u_int32_t spi;
        
-       proposal->set_spi(proposal, this->protocol_id, *((u_int32_t*)this->spi.ptr));
        
        while (iterator->has_next(iterator))
        {
@@ -430,6 +430,10 @@ void add_to_proposal(private_proposal_substructure_t *this, proposal_t *proposal
                proposal->add_algorithm(proposal, this->protocol_id, transform_type, transform_id, key_length);
        }
        iterator->destroy(iterator);
+       
+       spi = *((u_int32_t*)this->spi.ptr);
+       
+       proposal->set_spi(proposal, this->protocol_id, spi);
 }
 
 /**
@@ -561,14 +565,6 @@ proposal_substructure_t *proposal_substructure_create_from_proposal(proposal_t *
        algorithm_t *algo;
        transform_substructure_t *transform;
        
-       /* take over general infos */
-       this->spi_size = proto == IKE ? 8 : 4;
-       this->spi.len = this->spi_size;
-       this->spi.ptr = allocator_alloc(this->spi_size);
-       *((u_int32_t*)this->spi.ptr) = proposal->get_spi(proposal, proto);
-       this->proposal_number = proposal->get_number(proposal);
-       this->protocol_id = proto;
-       
        /* encryption algorithm is only availble in ESP */
        iterator = proposal->create_algorithm_iterator(proposal, proto, ENCRYPTION_ALGORITHM);
        while (iterator->has_next(iterator))
@@ -623,5 +619,13 @@ proposal_substructure_t *proposal_substructure_create_from_proposal(proposal_t *
        }
        iterator->destroy(iterator);
        
+       /* take over general infos */
+       this->spi_size = proto == IKE ? 8 : 4;
+       this->spi.len = this->spi_size;
+       this->spi.ptr = allocator_alloc(this->spi_size);
+       *((u_int32_t*)this->spi.ptr) = proposal->get_spi(proposal, proto);
+       this->proposal_number = proposal->get_number(proposal);
+       this->protocol_id = proto;
+       
        return &(this->public);
 }
index e2f368f..9b0bbf4 100644 (file)
@@ -343,7 +343,6 @@ static void compute_length (private_transform_substructure_t *this)
        iterator->destroy(iterator);
        
        this->transform_length = length;
-               
 }
 
 /**
@@ -476,20 +475,13 @@ transform_substructure_t *transform_substructure_create_type(transform_type_t tr
        transform->set_transform_type(transform,transform_type);
        transform->set_transform_id(transform,transform_id);
        
-       switch (transform_type)
+       /* a keylength attribute is only created for AES encryption */
+       if (transform_type == ENCRYPTION_ALGORITHM &&
+               transform_id == ENCR_AES_CBC)
        {
-               case ENCRYPTION_ALGORITHM:
-               case PSEUDO_RANDOM_FUNCTION:
-               case INTEGRITY_ALGORITHM:
-               {
-                       transform_attribute_t *attribute = transform_attribute_create_key_length(key_length);
-                       transform->add_transform_attribute(transform,attribute);
-                       break;
-               }
-               default:
-               {
-                       /* no keylength attribute is created */
-               }
-       }       
+               transform_attribute_t *attribute = transform_attribute_create_key_length(key_length);
+               transform->add_transform_attribute(transform,attribute);                
+       }
+
        return transform;
 }
index 2c46243..6754e80 100644 (file)
@@ -39,14 +39,29 @@ struct private_child_sa_t {
        child_sa_t public;
        
        /**
-        * CHILD_SAs own logger
+        * IP of this peer
         */
-       logger_t *logger;
+       host_t *me;
        
        /**
-        * Protocols used in this SA
+        * IP of other peer
         */
-       protocol_id_t protocols[2];
+       host_t *other;
+       
+       /**
+        * Security parameter index for AH protocol, 0 if not used
+        */
+       u_int32_t ah_spi;
+       
+       /**
+        * Security parameter index for ESP protocol, 0 if not used
+        */
+       u_int32_t esp_spi;
+       
+       /**
+        * CHILD_SAs own logger
+        */
+       logger_t *logger;
 };
 
 
@@ -59,65 +74,271 @@ static u_int32_t get_spi(private_child_sa_t *this)
 }
 
 /**
- * Implementation of child_sa_t.destroy.
+ * Implements child_sa_t.alloc
  */
-static void destroy(private_child_sa_t *this)
+static status_t alloc(private_child_sa_t *this, linked_list_t *proposals)
 {
-       charon->logger_manager->destroy_logger(charon->logger_manager, this->logger);
-       allocator_free(this);
+       protocol_id_t protocols[2];
+       iterator_t *iterator;
+       proposal_t *proposal;
+       status_t status;
+       u_int i;
+       
+       /* iterator through proposals */
+       iterator = proposals->create_iterator(proposals, TRUE);
+       while(iterator->has_next(iterator))
+       {
+               iterator->current(iterator, (void**)&proposal);
+               proposal->get_protocols(proposal, protocols);
+       
+               /* check all protocols */
+               for (i = 0; i<2; i++)
+               {
+                       switch (protocols[i])
+                       {
+                               case AH:
+                                       /* do we already have an spi for AH?*/
+                                       if (this->ah_spi == 0)
+                                       {
+                                               /* nope, get one */
+                                               status = charon->kernel_interface->get_spi(
+                                                                                       charon->kernel_interface,
+                                                                                       this->me, this->other,
+                                                                                       AH, FALSE,
+                                                                                       &(this->ah_spi));
+                                       }
+                                       /* update proposal */
+                                       proposal->set_spi(proposal, AH, (u_int64_t)this->ah_spi);
+                                       break;
+                               case ESP:
+                                       /* do we already have an spi for ESP?*/
+                                       if (this->esp_spi == 0)
+                                       {
+                                               /* nope, get one */
+                                               status = charon->kernel_interface->get_spi(
+                                                                                       charon->kernel_interface,
+                                                                                       this->me, this->other,
+                                                                                       ESP, FALSE,
+                                                                                       &(this->esp_spi));
+                                       }
+                                       /* update proposal */
+                                       proposal->set_spi(proposal, ESP, (u_int64_t)this->esp_spi);
+                                       break;
+                               default:
+                                       break;
+                       }
+                       if (status != SUCCESS)
+                       {
+                               iterator->destroy(iterator);
+                               return FAILED;
+                       }
+               }
+       }
+       iterator->destroy(iterator);
+       return SUCCESS;
 }
 
-/*
- * Described in header.
- */
-child_sa_t * child_sa_create(proposal_t *proposal, prf_plus_t *prf_plus)
+static status_t install(private_child_sa_t *this, proposal_t *proposal, prf_plus_t *prf_plus, bool mine)
 {
-       private_child_sa_t *this = allocator_alloc_thing(private_child_sa_t);
+       protocol_id_t protocols[2];
+       u_int32_t spi;
+       encryption_algorithm_t enc_algo;
+       integrity_algorithm_t int_algo;
+       chunk_t enc_key, int_key;
+       algorithm_t *algo;
+       crypter_t *crypter;
+       signer_t *signer;
+       size_t key_size;
+       host_t *src;
+       host_t *dst;
+       status_t status;
        u_int i;
-
-       /* public functions */
-       this->public.get_spi = (u_int32_t(*)(child_sa_t*))get_spi;
-       this->public.destroy = (void(*)(child_sa_t*))destroy;
-
-       /* private data */
-       this->logger = charon->logger_manager->create_logger(charon->logger_manager, CHILD_SA, NULL);
-       proposal->get_protocols(proposal, this->protocols);
        
-       /* derive keys */
+       /* we must assign the roles to correctly set up the SAs */
+       if (mine)
+       {
+               src = this->me;
+               dst = this->other;
+       }
+       else
+       {
+               dst = this->me;
+               src = this->other;
+       }
+       
+       proposal->get_protocols(proposal, protocols);
+       /* derive keys in order as protocols appear */
        for (i = 0; i<2; i++)
        {
-               if (this->protocols[i] != UNDEFINED_PROTOCOL_ID)
+               if (protocols[i] != UNDEFINED_PROTOCOL_ID)
                {
-                       algorithm_t *algo;
-                       chunk_t key;
                        
-                       /* get encryption key */
-                       if (proposal->get_algorithm(proposal, this->protocols[i], ENCRYPTION_ALGORITHM, &algo))
+                       /* now we have to decide which spi to use. Use self allocated, if "mine",
+                        * or the one in the proposal, if not "mine" (others). */
+                       if (mine)
+                       {
+                               if (protocols[i] == AH)
+                               {
+                                       spi = this->ah_spi;
+                               }
+                               else
+                               {
+                                       spi = this->esp_spi;
+                               }
+                       }
+                       else /* use proposals spi */
+                       {
+                               spi = proposal->get_spi(proposal, protocols[i]);
+                       }
+                       
+                       /* derive encryption key first */
+                       if (proposal->get_algorithm(proposal, protocols[i], ENCRYPTION_ALGORITHM, &algo))
                        {
-                               this->logger->log(this->logger, CONTROL|LEVEL1, "%s: using %s %s, ",
-                                                                 mapping_find(protocol_id_m, this->protocols[i]),
+                               enc_algo = algo->algorithm;
+                               this->logger->log(this->logger, CONTROL|LEVEL1, "%s for %s: using %s %s, ",
+                                                                 mapping_find(protocol_id_m, protocols[i]),
+                                                                 mine ? "me" : "other",
                                                                  mapping_find(transform_type_m, ENCRYPTION_ALGORITHM),
-                                                                 mapping_find(encryption_algorithm_m, algo->algorithm));
+                                                                 mapping_find(encryption_algorithm_m, enc_algo));
                                
-                               prf_plus->allocate_bytes(prf_plus, algo->key_size, &key);
-                               this->logger->log_chunk(this->logger, PRIVATE, "key:", &key);
-                               allocator_free_chunk(&key);
+                               /* we must create a (unused) crypter, since its the only way to get the size
+                                * of the key. This is not so nice, since charon must support all algorithms
+                                * the kernel supports...
+                                * TODO: build something of a encryption algorithm lookup function 
+                                */
+                               crypter = crypter_create(enc_algo, algo->key_size);
+                               key_size = crypter->get_key_size(crypter);
+                               crypter->destroy(crypter);
+                               prf_plus->allocate_bytes(prf_plus, key_size, &enc_key);
+                               this->logger->log_chunk(this->logger, PRIVATE, "key:", &enc_key);
+                       }
+                       else
+                       {
+                               enc_algo = ENCR_UNDEFINED;
                        }
                        
-                       /* get integrity key */
-                       if (proposal->get_algorithm(proposal, this->protocols[i], INTEGRITY_ALGORITHM, &algo))
+                       /* derive integrity key */
+                       if (proposal->get_algorithm(proposal, protocols[i], INTEGRITY_ALGORITHM, &algo))
                        {
-                               this->logger->log(this->logger, CONTROL|LEVEL1, "%s: using %s %s,",
-                                                                 mapping_find(protocol_id_m, this->protocols[i]),
+                               int_algo = algo->algorithm;
+                               this->logger->log(this->logger, CONTROL|LEVEL1, "%s for %s: using %s %s,",
+                                                                 mapping_find(protocol_id_m, protocols[i]),
+                                                                 mine ? "me" : "other",
                                                                  mapping_find(transform_type_m, INTEGRITY_ALGORITHM),
                                                                  mapping_find(integrity_algorithm_m, algo->algorithm));
                                
-                               prf_plus->allocate_bytes(prf_plus, algo->key_size, &key);
-                               this->logger->log_chunk(this->logger, PRIVATE, "key:", &key);
-                               allocator_free_chunk(&key);
+                               signer = signer_create(int_algo);
+                               key_size = signer->get_key_size(signer);
+                               signer->destroy(signer);
+                               prf_plus->allocate_bytes(prf_plus, key_size, &int_key);
+                               this->logger->log_chunk(this->logger, PRIVATE, "key:", &int_key);
+                       }
+                       else
+                       {
+                               int_algo = AUTH_UNDEFINED;
+                       }
+                       /* send keys down to kernel */
+                       this->logger->log(this->logger, CONTROL|LEVEL1, 
+                                                         "installing 0x%.8x for %s, src %s dst %s",
+                                                         ntohl(spi), mapping_find(protocol_id_m, protocols[i]), 
+                                                         src->get_address(src), dst->get_address(dst));
+                       status = charon->kernel_interface->add_sa(charon->kernel_interface,
+                                                                                                         src, dst,
+                                                                                                         spi, protocols[i], FALSE,
+                                                                                                         enc_algo, enc_key,
+                                                                                                         int_algo, int_key, mine);
+                       /* clean up for next round */
+                       if (enc_algo != ENCR_UNDEFINED)
+                       {
+                               allocator_free_chunk(&enc_key);
                        }
+                       if (int_algo != AUTH_UNDEFINED)
+                       {
+                               allocator_free_chunk(&int_key);
+                       }
+                       
+                       if (status != SUCCESS)
+                       {
+                               return FAILED;
+                       }
+                       
                }
        }
+       return SUCCESS;
+}
+
+static status_t add(private_child_sa_t *this, proposal_t *proposal, prf_plus_t *prf_plus)
+{
+       linked_list_t *list;
+       
+       /* install others (initiators) SAs*/
+       if (install(this, proposal, prf_plus, FALSE) != SUCCESS)
+       {
+               return FAILED;
+       }
+       
+       /* get SPIs for our SAs */
+       list = linked_list_create();
+       list->insert_last(list, proposal);
+       if (alloc(this, list) != SUCCESS)
+       {
+               list->destroy(list);
+               return FAILED;
+       }
+       list->destroy(list);
+       
+       /* install our (responders) SAs */
+       if (install(this, proposal, prf_plus, TRUE) != SUCCESS)
+       {
+               return FAILED;
+       }
+       return SUCCESS;
+}
+
+static status_t update(private_child_sa_t *this, proposal_t *proposal, prf_plus_t *prf_plus)
+{
+       /* install our (initator) SAs */
+       if (install(this, proposal, prf_plus, TRUE) != SUCCESS)
+       {
+               return FAILED;
+       }
+       /* install his (responder) SAs */
+       if (install(this, proposal, prf_plus, FALSE) != SUCCESS)
+       {
+               return FAILED;
+       }
+       return SUCCESS;
+}
+
+/**
+ * Implementation of child_sa_t.destroy.
+ */
+static void destroy(private_child_sa_t *this)
+{
+       charon->logger_manager->destroy_logger(charon->logger_manager, this->logger);
+       allocator_free(this);
+}
+
+/*
+ * Described in header.
+ */
+child_sa_t * child_sa_create(host_t *me, host_t* other)
+{
+       private_child_sa_t *this = allocator_alloc_thing(private_child_sa_t);
+
+       /* public functions */
+       this->public.get_spi = (u_int32_t(*)(child_sa_t*))get_spi;
+       this->public.alloc = (status_t(*)(child_sa_t*,linked_list_t*))alloc;
+       this->public.add = (status_t(*)(child_sa_t*,proposal_t*,prf_plus_t*))add;
+       this->public.update = (status_t(*)(child_sa_t*,proposal_t*,prf_plus_t*))update;
+       this->public.destroy = (void(*)(child_sa_t*))destroy;
+
+       /* private data */
+       this->logger = charon->logger_manager->create_logger(charon->logger_manager, CHILD_SA, NULL);
+       this->me = me;
+       this->other = other;
+       this->ah_spi = 0;
+       this->esp_spi = 0;
        
        return (&this->public);
 }
index bde032b..260c4f2 100644 (file)
@@ -50,6 +50,11 @@ struct child_sa_t {
         * @return                      4 Byte SPI value
         */
        u_int32_t (*get_spi) (child_sa_t *this);
+       
+       
+       status_t (*alloc)(child_sa_t *this, linked_list_t* proposals);
+       status_t (*add)(child_sa_t *this, proposal_t *proposal, prf_plus_t *prf_plus);
+       status_t (*update)(child_sa_t *this, proposal_t *proposal, prf_plus_t *prf_plus);
 
        /**
         * @brief Destroys a child_sa.
@@ -67,6 +72,6 @@ struct child_sa_t {
  * @return                             child_sa_t object
  * @ingroup sa
  */
-child_sa_t * child_sa_create(proposal_t *proposal, prf_plus_t *prf_plus);
+child_sa_t * child_sa_create(host_t *me, host_t *other);
 
 #endif /*_CHILD_SA_H_*/
index ac617fa..55c03ef 100644 (file)
@@ -417,7 +417,7 @@ status_t retransmit_request (private_ike_sa_t *this, u_int32_t message_id)
  */
 static void set_new_state (private_ike_sa_t *this, state_t *state)
 {
-       this->logger->log(this->logger, CONTROL, "Change current state %s to %s",
+       this->logger->log(this->logger, CONTROL, "statechange: %s => %s",
                                          mapping_find(ike_sa_state_m,this->current_state->get_state(this->current_state)),
                                          mapping_find(ike_sa_state_m,state->get_state(state)));
        this->current_state = state;
@@ -964,6 +964,14 @@ static ike_sa_state_t get_state (private_ike_sa_t *this)
 }
 
 /**
+ * Implementation of protected_ike_sa_t.get_state.
+ */
+static void add_child_sa (private_ike_sa_t *this, child_sa_t *child_sa)
+{
+       this->child_sas->insert_last(this->child_sas, child_sa);
+}
+
+/**
  * Implementation of protected_ike_sa_t.reset_message_buffers.
  */
 static void reset_message_buffers (private_ike_sa_t *this)
@@ -1008,21 +1016,17 @@ static void create_delete_established_ike_sa_job (private_ike_sa_t *this,u_int32
  */
 static void destroy (private_ike_sa_t *this)
 {
+       child_sa_t *child_sa;
+       
        this->logger->log(this->logger, CONTROL|LEVEL2, "Going to destroy IKE SA %llu:%llu, role %s", 
                                          this->ike_sa_id->get_initiator_spi(this->ike_sa_id),
                                          this->ike_sa_id->get_responder_spi(this->ike_sa_id),
                                          this->ike_sa_id->is_initiator(this->ike_sa_id) ? "initiator" : "responder");
 
        /* destroy child sa's */
-       this->logger->log(this->logger, CONTROL | LEVEL3, "Destroy all child_sa's");
-       while (this->child_sas->get_count(this->child_sas) > 0)
+       while (this->child_sas->remove_last(this->child_sas, (void**)&child_sa) == SUCCESS)
        {
-               void *child_sa;
-               if (this->child_sas->remove_first(this->child_sas, &child_sa) != SUCCESS)
-               {
-                       break;
-               }
-               /* destroy child sa */
+               child_sa->destroy(child_sa);
        }
        this->child_sas->destroy(this->child_sas);
        
@@ -1134,7 +1138,8 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
        this->protected.get_child_prf = (prf_t *(*) (protected_ike_sa_t *)) get_child_prf;
        this->protected.get_prf_auth_i = (prf_t *(*) (protected_ike_sa_t *)) get_prf_auth_i;
        this->protected.get_prf_auth_r = (prf_t *(*) (protected_ike_sa_t *)) get_prf_auth_r;
-       this->protected.get_logger = (logger_t *(*) (protected_ike_sa_t *)) get_logger;         
+       this->protected.add_child_sa = (void (*) (protected_ike_sa_t*,child_sa_t*)) add_child_sa;
+       this->protected.get_logger = (logger_t *(*) (protected_ike_sa_t *)) get_logger;
        this->protected.set_init_config = (void (*) (protected_ike_sa_t *,init_config_t *)) set_init_config;
        this->protected.get_init_config = (init_config_t *(*) (protected_ike_sa_t *)) get_init_config;
        this->protected.set_sa_config = (void (*) (protected_ike_sa_t *,sa_config_t *)) set_sa_config;
index f5591a0..b15a8ea 100644 (file)
 #include <encoding/message.h>
 #include <encoding/payloads/proposal_substructure.h>
 #include <sa/ike_sa_id.h>
+#include <sa/child_sa.h>
+#include <sa/states/state.h>
 #include <config/configuration_manager.h>
 #include <utils/logger.h>
 #include <utils/randomizer.h>
-#include <sa/states/state.h>
 #include <transforms/prfs/prf.h>
 #include <transforms/crypters/crypter.h>
 #include <transforms/signers/signer.h>
@@ -388,6 +389,14 @@ struct protected_ike_sa_t {
        prf_t *(*get_prf_auth_r) (protected_ike_sa_t *this);
        
        /**
+        * @brief Associates a child SA to this IKE SA
+        * 
+        * @param this                          calling object
+        * @param child_sa                      child_sa to add
+        */
+       void (*add_child_sa) (protected_ike_sa_t *this, child_sa_t *child_sa);
+       
+       /**
         * @brief Get the last responded message.
         *  
         * @param this                          calling object
index e655931..3289715 100644 (file)
@@ -71,6 +71,11 @@ struct private_ike_auth_requested_t {
         * IKE_SA_INIT-Request in binary form.
         */
        chunk_t ike_sa_init_reply_data;
+       
+       /**
+        * Child sa created in ike_sa_init_requested
+        */
+       child_sa_t *child_sa;
         
        /**
         * Assigned Logger.
@@ -136,6 +141,16 @@ struct private_ike_auth_requested_t {
         *                                              - DELETE_ME
         */
        status_t (*process_notify_payload) (private_ike_auth_requested_t *this, notify_payload_t *notify_payload);
+       
+       /**
+        * Destroy function called internally of this class after state change to 
+        * state IKE_SA_ESTABLISHED succeeded. 
+        * 
+        * This destroy function does not destroy objects which were passed to the new state.
+        * 
+        * @param this          calling object
+        */
+       void (*destroy_after_state_change) (private_ike_auth_requested_t *this);
 };
 
 
@@ -288,7 +303,7 @@ static status_t process_message(private_ike_auth_requested_t *this, message_t *i
                                                
        this->ike_sa->create_delete_established_ike_sa_job(this->ike_sa,this->sa_config->get_ike_sa_lifetime(this->sa_config));
        this->ike_sa->set_new_state(this->ike_sa, (state_t*)ike_sa_established_create(this->ike_sa));
-       this->public.state_interface.destroy(&(this->public.state_interface));
+       this->destroy_after_state_change(this);
        return SUCCESS;
 }
 
@@ -328,7 +343,6 @@ static status_t process_sa_payload(private_ike_auth_requested_t *this, sa_payloa
 {
        proposal_t *proposal, *proposal_tmp;
        linked_list_t *proposal_list;
-       child_sa_t *child_sa;
        chunk_t seed;
        prf_plus_t *prf_plus;
        
@@ -377,10 +391,19 @@ static status_t process_sa_payload(private_ike_auth_requested_t *this, sa_payloa
        prf_plus = prf_plus_create(this->ike_sa->get_child_prf(this->ike_sa), seed);
        allocator_free_chunk(&seed);
        
-       child_sa = child_sa_create(proposal, prf_plus);
-       prf_plus->destroy(prf_plus);
-       child_sa->destroy(child_sa);
+       if (this->child_sa)
+       {
+               if (this->child_sa->update(this->child_sa, proposal, prf_plus) != SUCCESS)
+               {
+                       this->logger->log(this->logger, AUDIT, "Could not install CHILD_SA! Deleting IKE_SA");
+                       prf_plus->destroy(prf_plus);
+                       proposal->destroy(proposal);
+                       return DELETE_ME;
+               }
+               this->ike_sa->add_child_sa(this->ike_sa, this->child_sa);
+       }
        
+       prf_plus->destroy(prf_plus);
        proposal->destroy(proposal);
        
        return SUCCESS;
@@ -524,6 +547,20 @@ static void destroy(private_ike_auth_requested_t *this)
 {
        allocator_free_chunk(&(this->received_nonce));
        allocator_free_chunk(&(this->sent_nonce));
+       allocator_free_chunk(&(this->ike_sa_init_reply_data));
+       if (this->child_sa)
+       {
+               this->child_sa->destroy(this->child_sa);
+       }
+       allocator_free(this);
+}
+/**
+ * Implements protected_ike_sa_t.destroy_after_state_change
+ */
+static void destroy_after_state_change(private_ike_auth_requested_t *this)
+{
+       allocator_free_chunk(&(this->received_nonce));
+       allocator_free_chunk(&(this->sent_nonce));
        allocator_free_chunk(&(this->ike_sa_init_reply_data));  
        allocator_free(this);
 }
@@ -531,7 +568,7 @@ static void destroy(private_ike_auth_requested_t *this)
 /* 
  * Described in header.
  */
-ike_auth_requested_t *ike_auth_requested_create(protected_ike_sa_t *ike_sa,chunk_t sent_nonce,chunk_t received_nonce,chunk_t ike_sa_init_reply_data)
+ike_auth_requested_t *ike_auth_requested_create(protected_ike_sa_t *ike_sa,chunk_t sent_nonce,chunk_t received_nonce,chunk_t ike_sa_init_reply_data, child_sa_t *child_sa)
 {
        private_ike_auth_requested_t *this = allocator_alloc_thing(private_ike_auth_requested_t);
 
@@ -541,12 +578,12 @@ ike_auth_requested_t *ike_auth_requested_create(protected_ike_sa_t *ike_sa,chunk
        this->public.state_interface.destroy  = (void (*) (state_t *)) destroy;
        
        /* private functions */
-       
        this->process_idr_payload = process_idr_payload;
        this->process_sa_payload = process_sa_payload;
        this->process_auth_payload = process_auth_payload;
        this->process_ts_payload = process_ts_payload;
        this->process_notify_payload = process_notify_payload;
+       this->destroy_after_state_change = destroy_after_state_change;
        
        /* private data */
        this->ike_sa = ike_sa;
@@ -554,6 +591,7 @@ ike_auth_requested_t *ike_auth_requested_create(protected_ike_sa_t *ike_sa,chunk
        this->sent_nonce = sent_nonce;
        this->ike_sa_init_reply_data = ike_sa_init_reply_data;
        this->logger = this->ike_sa->get_logger(this->ike_sa);
+       this->child_sa = child_sa;
        
        return &(this->public);
 }
index 34b9488..a8eef01 100644 (file)
@@ -41,8 +41,6 @@ typedef struct ike_auth_requested_t ike_auth_requested_t;
  * 
  * @todo handle certificate payloads
  * 
- * @todo setup child SAs, if requested
- * 
  * @ingroup states
  */
 struct ike_auth_requested_t {
@@ -60,6 +58,7 @@ struct ike_auth_requested_t {
  * @param sent_nonce                           Sent nonce value in IKE_SA_INIT request
  * @param received_nonce                       Received nonce value in IKE_SA_INIT response
  * @param ike_sa_init_reply_data       binary representation of IKE_SA_INIT reply 
+ * @param child_sa                                     opened but not completed child_sa
  * @return                                                     created ike_auth_requested_t object
  * 
  * @ingroup states
@@ -67,6 +66,7 @@ struct ike_auth_requested_t {
 ike_auth_requested_t *ike_auth_requested_create(protected_ike_sa_t *ike_sa,
                                                                                                chunk_t sent_nonce,
                                                                                                chunk_t received_nonce,
-                                                                                               chunk_t ike_sa_init_reply_data);
+                                                                                               chunk_t ike_sa_init_reply_data,
+                                                                                               child_sa_t *child_sa);
 
 #endif /*IKE_AUTH_REQUESTED_H_*/
index 327eb2d..55f3888 100644 (file)
@@ -80,6 +80,11 @@ struct private_ike_sa_init_requested_t {
        chunk_t ike_sa_init_request_data;
        
        /**
+        * Created child sa, if any
+        */
+       child_sa_t *child_sa;
+       
+       /**
         * Assigned logger
         * 
         * Is logger of ike_sa!
@@ -187,8 +192,6 @@ struct private_ike_sa_init_requested_t {
         * Destroy function called internally of this class after state change to 
         * state IKE_AUTH_REQUESTED succeeded. 
         * 
-        * In case of state change to INITIATOR_INIT the default destroy function gets called.
-        * 
         * This destroy function does not destroy objects which were passed to the new state.
         * 
         * @param this          calling object
@@ -383,7 +386,8 @@ static status_t process_message(private_ike_sa_init_requested_t *this, message_t
        ike_sa_init_reply_data = ike_sa_init_reply->get_packet_data(ike_sa_init_reply);
 
        /* state can now be changed */
-       next_state = ike_auth_requested_create(this->ike_sa,this->sent_nonce,this->received_nonce,ike_sa_init_reply_data);
+       next_state = ike_auth_requested_create(this->ike_sa, this->sent_nonce, this->received_nonce,
+                                                                                  ike_sa_init_reply_data, this->child_sa);
        this->ike_sa->set_new_state(this->ike_sa,(state_t *) next_state);
 
        this->destroy_after_state_change(this);
@@ -512,10 +516,22 @@ static status_t build_sa_payload (private_ike_sa_init_requested_t *this, message
        /* get proposals form config, add to payload */
        sa_config = this->ike_sa->get_sa_config(this->ike_sa);
        proposal_list = sa_config->get_proposals(sa_config);
+       /* build child sa */
+       this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa),
+                                                                        this->ike_sa->get_other_host(this->ike_sa));
+       if (this->child_sa->alloc(this->child_sa, proposal_list) != SUCCESS)
+       {
+               this->logger->log(this->logger, AUDIT, "Could not install CHILD_SA! Deleting IKE_SA");
+               return DELETE_ME;
+       }
+       
+       /* TODO:
+        * Huston, we've got a problem here. Since SPIs are stored in
+        * the proposal, and these proposals are shared across configs,
+        * there may be some threading issues... fix it!
+        */
        sa_payload = sa_payload_create_from_proposal_list(proposal_list);
 
-       /* TODO child sa stuff */
-
        this->logger->log(this->logger, CONTROL|LEVEL2, "Add SA payload to message");
        request->add_payload(request,(payload_t *) sa_payload);
        
@@ -705,6 +721,10 @@ static void destroy(private_ike_sa_init_requested_t *this)
        allocator_free(this->sent_nonce.ptr);
        allocator_free(this->received_nonce.ptr);
        allocator_free_chunk(&(this->ike_sa_init_request_data));
+       if (this->child_sa)
+       {
+               this->child_sa->destroy(this->child_sa);
+       }
        if (this->proposal)
        {
                this->proposal->destroy(this->proposal);
@@ -743,6 +763,7 @@ ike_sa_init_requested_t *ike_sa_init_requested_create(protected_ike_sa_t *ike_sa
        this->diffie_hellman = diffie_hellman;
        this->proposal = NULL;
        this->sent_nonce = sent_nonce;
+       this->child_sa = NULL;
        this->ike_sa_init_request_data = ike_sa_init_request_data;
        
        return &(this->public);
index 536041d..70baa51 100644 (file)
@@ -425,10 +425,6 @@ static status_t build_sa_payload(private_ike_sa_init_responded_t *this, sa_paylo
                return DELETE_ME;       
        }
        
-       /* create payload with selected propsal */
-       sa_response = sa_payload_create_from_proposal(proposal);
-       response->add_payload(response, (payload_t*)sa_response);
-       
        /* install child SAs for AH and esp */
        seed = allocator_alloc_as_chunk(this->received_nonce.len + this->sent_nonce.len);
        memcpy(seed.ptr, this->received_nonce.ptr, this->received_nonce.len);
@@ -436,10 +432,22 @@ static status_t build_sa_payload(private_ike_sa_init_responded_t *this, sa_paylo
        prf_plus = prf_plus_create(this->ike_sa->get_child_prf(this->ike_sa), seed);
        allocator_free_chunk(&seed);
        
-       child_sa = child_sa_create(proposal, prf_plus);
-       prf_plus->destroy(prf_plus);
-       child_sa->destroy(child_sa);
+       child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa),
+                                                          this->ike_sa->get_other_host(this->ike_sa));
+       if (child_sa->add(child_sa, proposal, prf_plus) != SUCCESS)
+       {
+               this->logger->log(this->logger, AUDIT, "Could not install CHILD_SA! Deleting IKE_SA");
+               prf_plus->destroy(prf_plus);
+               proposal->destroy(proposal);
+               return DELETE_ME;
+       }
+       this->ike_sa->add_child_sa(this->ike_sa, child_sa);
+       
+       /* create payload with selected propsal */
+       sa_response = sa_payload_create_from_proposal(proposal);
+       response->add_payload(response, (payload_t*)sa_response);
        
+       prf_plus->destroy(prf_plus);
        proposal->destroy(proposal);    
        return SUCCESS;
 }
index a459e32..e21b5c2 100644 (file)
@@ -127,4 +127,8 @@ $(BUILD_DIR)rsa_test.o :                    $(TESTCASES_DIR)rsa_test.c $(TESTCASES_DIR)rsa_test.h
 TEST_OBJS+= $(BUILD_DIR)kernel_interface_test.o
 $(BUILD_DIR)kernel_interface_test.o :  $(TESTCASES_DIR)kernel_interface_test.c $(TESTCASES_DIR)kernel_interface_test.h
                                                                        $(CC) $(CFLAGS) -c -o $@ $<
+
+TEST_OBJS+= $(BUILD_DIR)child_sa_test.o
+$(BUILD_DIR)child_sa_test.o :          $(TESTCASES_DIR)child_sa_test.c $(TESTCASES_DIR)child_sa_test.h
+                                                                       $(CC) $(CFLAGS) -c -o $@ $<
                                                                        
\ No newline at end of file
diff --git a/Source/charon/testcases/child_sa_test.c b/Source/charon/testcases/child_sa_test.c
new file mode 100644 (file)
index 0000000..09b49b7
--- /dev/null
@@ -0,0 +1,102 @@
+/**
+ * @file child_sa_test.c
+ *
+ * @brief Tests for the child_sa_t class.
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "child_sa_test.h"
+
+#include <daemon.h>
+#include <sa/child_sa.h>
+#include <utils/allocator.h>
+#include <utils/logger.h>
+
+
+/**
+ * Described in header.
+ */
+void test_child_sa(protected_tester_t *tester)
+{
+       proposal_t *proposal1, *proposal2;
+       linked_list_t *list;
+       host_t *local_me, *remote_me;
+       host_t *local_other, *remote_other;
+       child_sa_t *local_sa, *remote_sa;
+       prf_plus_t *local_prf_plus, *remote_prf_plus;
+       prf_t *local_prf, *remote_prf;
+       u_int8_t key_buffer[] = {0x01,0x02,0x03,0x04};
+       chunk_t key = {key_buffer, sizeof(key_buffer)};
+       status_t status;
+       
+       /* setup test data */
+       local_me = host_create(AF_INET, "192.168.0.1", 0);
+       local_other = host_create(AF_INET, "192.168.0.2", 0);
+       remote_me = host_create(AF_INET, "192.168.0.3", 0);
+       remote_other = host_create(AF_INET, "192.168.0.4", 0);
+       
+       local_sa = child_sa_create(local_me, local_other);
+       remote_sa = child_sa_create(remote_me, remote_other);
+       
+       proposal1 = proposal_create(1);
+       proposal1->add_algorithm(proposal1, ESP, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 16);
+       
+       proposal2 = proposal_create(2);
+       proposal2->add_algorithm(proposal2, AH, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0);
+       
+       list = linked_list_create();
+       list->insert_last(list, proposal1);
+       list->insert_last(list, proposal2);
+       
+       local_prf = prf_create(PRF_HMAC_SHA1);
+       remote_prf = prf_create(PRF_HMAC_SHA1);
+       local_prf->set_key(local_prf, key);
+       remote_prf->set_key(remote_prf, key);
+       local_prf_plus = prf_plus_create(local_prf, key);
+       remote_prf_plus = prf_plus_create(remote_prf, key);
+       
+       /* 
+        * local plays initiator 
+        ***********************
+       */
+       status = local_sa->alloc(local_sa, list);
+       tester->assert_true(tester, status == SUCCESS, "spi allocation");
+       
+       status = remote_sa->add(remote_sa, proposal1, remote_prf_plus);
+       tester->assert_true(tester, status == SUCCESS, "sa add");
+       
+       status = local_sa->update(local_sa, proposal1, local_prf_plus);
+       tester->assert_true(tester, status == SUCCESS, "sa update");
+       
+       /* cleanup */
+       proposal1->destroy(proposal1);
+       proposal2->destroy(proposal2);
+       list->destroy(list);
+       local_prf->destroy(local_prf);
+       local_prf_plus->destroy(local_prf_plus);
+       remote_prf->destroy(remote_prf);
+       remote_prf_plus->destroy(remote_prf_plus);
+       local_sa->destroy(local_sa);
+       remote_sa->destroy(remote_sa);
+       local_me->destroy(local_me);
+       local_other->destroy(local_other);
+       remote_me->destroy(remote_me);
+       remote_other->destroy(remote_other);
+       
+       
+}
diff --git a/Source/charon/testcases/child_sa_test.h b/Source/charon/testcases/child_sa_test.h
new file mode 100644 (file)
index 0000000..00e4db1
--- /dev/null
@@ -0,0 +1,42 @@
+/**
+ * @file child_sa_test.h
+ *
+ * @brief Tests for the child_sa_t class.
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+
+#ifndef CHILD_SA_TEST_H_
+#define CHILD_SA_TEST_H_
+
+#include <utils/tester.h>
+
+/**
+ * @brief Test function used to test the child_sa_t functionality.
+ *
+ * @param tester associated protected_tester_t object
+ * 
+ * @ingroup testcases
+ */
+void test_child_sa(protected_tester_t *tester);
+
+#endif //CHILD_SA_TEST_H_
+
+
+
+
index 5e4506a..d75b00e 100644 (file)
@@ -32,9 +32,9 @@
 void test_init_config(protected_tester_t *tester)
 {
        init_config_t *init_config = init_config_create("192.168.0.1","192.168.0.2",500,500);
-       proposal_t *prop1, *prop2, *prop3, *prop4, *selected_one;
+       proposal_t *prop1, *prop2, *prop3, *prop4;//, *selected_one;
        linked_list_t *list;
-       status_t status;
+       //status_t status;
 
        prop1 = proposal_create(1);
        prop1->add_algorithm(prop1, IKE, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 20);
index 2f26c80..8eb2d5f 100644 (file)
@@ -65,10 +65,10 @@ void test_kernel_interface(protected_tester_t *tester)
 
 
 
-       //status = kernel_interface->get_spi(kernel_interface, me, other, 50, TRUE, &spi);
-       //tester->assert_true(tester, status == SUCCESS, "spi get");
+       status = kernel_interface->get_spi(kernel_interface, me, other, 50, FALSE, &spi);
+       tester->assert_true(tester, status == SUCCESS, "spi get");
 
-       status = kernel_interface->add_sa(kernel_interface, me, other, spi, 50, TRUE, ENCR_AES_CBC, enc_key,AUTH_HMAC_MD5_96,inc_key,TRUE);     
+       status = kernel_interface->add_sa(kernel_interface, me, other, spi, 50, FALSE, ENCR_AES_CBC, enc_key,AUTH_UNDEFINED,inc_key,TRUE);      
        tester->assert_true(tester, status == SUCCESS, "build sa");
        
 
index af539cb..8c391ca 100644 (file)
@@ -61,6 +61,7 @@
 #include <testcases/proposal_test.h>
 #include <testcases/rsa_test.h>
 #include <testcases/kernel_interface_test.h>
+#include <testcases/child_sa_test.h>
 
 /* output for test messages */
 extern FILE * stderr;
@@ -126,6 +127,7 @@ test_t sa_config_test = {test_sa_config, "sa_config_t test"};
 test_t proposal_test = {test_proposal, "proposal_t test"};
 test_t rsa_test = {test_rsa, "RSA private/public key test"};
 test_t kernel_interface_test = {test_kernel_interface, "Kernel Interface"};
+test_t child_sa_test = {test_child_sa, "Child SA"};
 
 
 daemon_t* charon;
@@ -138,6 +140,7 @@ static void daemon_kill(daemon_t *this, char* none)
        this->job_queue->destroy(this->job_queue);
        this->event_queue->destroy(this->event_queue);
        this->send_queue->destroy(this->send_queue);
+       this->kernel_interface->destroy(this->kernel_interface);
        //this->configuration_manager->destroy(this->configuration_manager);
        allocator_free(charon);
 }
@@ -160,6 +163,7 @@ daemon_t *daemon_create()
        charon->job_queue = job_queue_create();
        charon->event_queue = event_queue_create();
        charon->send_queue = send_queue_create();
+       charon->kernel_interface = kernel_interface_create();
        //charon->configuration_manager = configuration_manager_create(RETRANSMIT_TIMEOUT,MAX_RETRANSMIT_COUNT,HALF_OPEN_IKE_SA_TIMEOUT);
        charon->sender = NULL;
        charon->receiver = NULL;
@@ -237,6 +241,8 @@ int main()
                &rsa_test,
                NULL
        };
+       /* get rid of compiler warning ;-) */
+       *all_tests = *all_tests;
        
        /* allocator needs initialization */
        allocator_init();
@@ -244,13 +250,14 @@ int main()
        daemon_create();
  
        charon->logger_manager->disable_logger_level(charon->logger_manager,TESTER,FULL);
+       charon->logger_manager->enable_logger_level(charon->logger_manager,CHILD_SA,FULL);
        /* charon->logger_manager->enable_logger_level(charon->logger_manager,TESTER,RAW); */
        
        tester_t *tester = tester_create(test_output, FALSE);
        
 
-       tester->perform_tests(tester,all_tests);
-       //tester->perform_test(tester,&kernel_interface_test);
+       //tester->perform_tests(tester,all_tests);
+       tester->perform_test(tester,&child_sa_test);
        
        
        tester->destroy(tester);
index 4fba85c..f5273e1 100644 (file)
 #include <utils/linked_list.h>
 
 
+#define KERNEL_ESP 50
+#define KERNEL_AH 51
+
+
 typedef struct netlink_message_t netlink_message_t;
 
 /**
@@ -83,48 +87,48 @@ struct private_kernel_interface_t {
        /**
         * Public part of the kernel_interface_t object.
         */
-       kernel_interface_t public;
-       
-       /**
-        * Netlink communication socket.
-        */
-       int socket;
-
+       kernel_interface_t public;
+       
+       /**
+        * Netlink communication socket.
+        */
+       int socket;
+       
        pid_t pid;
-       /**
-        * Sequence number for messages.
-        */
-       u_int32_t seq;
-       
-       /** 
-        * List of responded messages.
-        */
-       linked_list_t *responses;
-       
-       /**
-        * Thread which receives messages.
-        */
-       pthread_t thread;
-       
-       /**
-        * Mutex locks access to replies list.
-        */
-       pthread_mutex_t mutex;
-       
-       /**
-        * Condvar allows signaling of threads waiting for a reply.
-        */
-       pthread_cond_t condvar;
-       
-       /**
-        * Function for the thread, receives messages.
-        */
-       void (*receive_messages) (private_kernel_interface_t *this);
-       
-       /**
-        * Sends a netlink_message_t down to the kernel and wait for reply.
-        */
-       status_t (*send_message) (private_kernel_interface_t *this, netlink_message_t *request, netlink_message_t **response);
+       /**
+        * Sequence number for messages.
+        */
+       u_int32_t seq;
+       
+       /** 
+        * List of responded messages.
+        */
+       linked_list_t *responses;
+       
+       /**
+        * Thread which receives messages.
+        */
+       pthread_t thread;
+       
+       /**
+        * Mutex locks access to replies list.
+        */
+       pthread_mutex_t mutex;
+       
+       /**
+        * Condvar allows signaling of threads waiting for a reply.
+        */
+       pthread_cond_t condvar;
+       
+       /**
+        * Function for the thread, receives messages.
+        */
+       void (*receive_messages) (private_kernel_interface_t *this);
+       
+       /**
+        * Sends a netlink_message_t down to the kernel and wait for reply.
+        */
+       status_t (*send_message) (private_kernel_interface_t *this, netlink_message_t *request, netlink_message_t **response);
 };
 
 mapping_t kernel_encryption_algs_m[] = {
@@ -157,41 +161,42 @@ static status_t get_spi(private_kernel_interface_t *this, host_t *src, host_t *d
 {
        netlink_message_t request, *response;
        
-    memset(&request, 0, sizeof(request));
-    request.hdr.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(request.spi)));
-    request.hdr.nlmsg_flags = NLM_F_REQUEST;
-    request.hdr.nlmsg_type = XFRM_MSG_ALLOCSPI;
+       memset(&request, 0, sizeof(request));
+       request.hdr.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(request.spi)));
+       request.hdr.nlmsg_flags = NLM_F_REQUEST;
+       request.hdr.nlmsg_type = XFRM_MSG_ALLOCSPI;
        request.spi.info.saddr = src->get_xfrm_addr(src);
        request.spi.info.id.daddr = dest->get_xfrm_addr(dest);
-    request.spi.info.mode = tunnel_mode;
-    request.spi.info.id.proto = protocol;
-    request.spi.info.family = PF_INET;
-    request.spi.min = 100;
-    request.spi.max = 200;
-
-       if (this->send_message(this, &request, &response) != SUCCESS)
-       {
-               return FAILED;
-       }
-    
-    if (response->hdr.nlmsg_type == NLMSG_ERROR)
-    {
-       return FAILED;
-    }
-    
-    if (response->hdr.nlmsg_type != XFRM_MSG_NEWSA)
-    {
-       return FAILED;
-    }
-    else if (response->hdr.nlmsg_len < NLMSG_LENGTH(sizeof(response->sa)))
-    {
+       request.spi.info.mode = tunnel_mode;
+       /* TODO: this should be done with getprotobyname() */
+       request.spi.info.id.proto = (protocol == ESP) ? KERNEL_ESP : KERNEL_AH;
+       request.spi.info.family = PF_INET;
+       request.spi.min = 100;
+       request.spi.max = 200;
+       
+       if (this->send_message(this, &request, &response) != SUCCESS)
+       {
                return FAILED;
-    }
+       }
+       
+       if (response->hdr.nlmsg_type == NLMSG_ERROR)
+       {
+               return FAILED;
+       }
+       
+       if (response->hdr.nlmsg_type != XFRM_MSG_NEWSA)
+       {
+               return FAILED;
+       }
+       else if (response->hdr.nlmsg_len < NLMSG_LENGTH(sizeof(response->sa)))
+       {
+               return FAILED;
+       }
        
        *spi = response->sa.id.spi;
        allocator_free(response);
-
-    return SUCCESS;
+       
+       return SUCCESS;
 }
 
 static status_t add_sa(        private_kernel_interface_t *this,
@@ -206,45 +211,46 @@ static status_t add_sa(   private_kernel_interface_t *this,
                                                chunk_t integrity_key,
                                                bool replace)
 {
-    netlink_message_t request, *response;
-       POS;
-    memset(&request, 0, sizeof(request));
-    
-    request.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
-    request.hdr.nlmsg_type = replace ? XFRM_MSG_UPDSA : XFRM_MSG_NEWSA;
-
-    request.sa.saddr = me->get_xfrm_addr(me);
-    request.sa.id.daddr = other->get_xfrm_addr(other);
-
-    request.sa.id.spi = spi;
-    request.sa.id.proto = protocol;
-    request.sa.family = me->get_family(me);
-    request.sa.mode = tunnel_mode;
-    request.sa.replay_window = 0; //sa->replay_window; ???
-    request.sa.reqid = 0; //sa->reqid; ???
-    request.sa.lft.soft_byte_limit = XFRM_INF;
-    request.sa.lft.soft_packet_limit = XFRM_INF;
-    request.sa.lft.hard_byte_limit = XFRM_INF;
-    request.sa.lft.hard_packet_limit = XFRM_INF;
-
-    request.hdr.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(request.sa)));
-
-    if (enc_alg != ENCR_UNDEFINED)
-    {
+       netlink_message_t request, *response;
+       memset(&request, 0, sizeof(request));
+       
+       
+       request.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+       request.hdr.nlmsg_type = replace ? XFRM_MSG_UPDSA : XFRM_MSG_NEWSA;
+       
+       request.sa.saddr = me->get_xfrm_addr(me);
+       request.sa.id.daddr = other->get_xfrm_addr(other);
+       
+       request.sa.id.spi = spi;
+       /* TODO: this should be done with getprotobyname() */
+       request.sa.id.proto = (protocol == ESP) ? KERNEL_ESP : KERNEL_AH;
+       request.sa.family = me->get_family(me);
+       request.sa.mode = tunnel_mode;
+       request.sa.replay_window = 0; //sa->replay_window; ???
+       request.sa.reqid = 0; //sa->reqid; ???
+       request.sa.lft.soft_byte_limit = XFRM_INF;
+       request.sa.lft.soft_packet_limit = XFRM_INF;
+       request.sa.lft.hard_byte_limit = XFRM_INF;
+       request.sa.lft.hard_packet_limit = XFRM_INF;
+       
+       request.hdr.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(request.sa)));
+       
+       if (enc_alg != ENCR_UNDEFINED)
+       {
                netlink_algo_t *nla = (netlink_algo_t*)(((u_int8_t*)&request) + request.hdr.nlmsg_len);
-       
-       nla->type = XFRMA_ALG_CRYPT;
+               
+               nla->type = XFRMA_ALG_CRYPT;
                nla->length = sizeof(netlink_algo_t) + encryption_key.len;
                nla->algo.alg_key_len = encryption_key.len * 8;
                
                strcpy(nla->algo.alg_name, mapping_find(kernel_encryption_algs_m, enc_alg));
                memcpy(nla->algo.alg_key, encryption_key.ptr, encryption_key.len);
-
+       
                request.hdr.nlmsg_len += nla->length;
-    }
-
-    if (int_alg != AUTH_UNDEFINED)
-    {
+       }
+       
+       if (int_alg != AUTH_UNDEFINED)
+       {
                netlink_algo_t *nla = (netlink_algo_t*)(((u_int8_t*)&request) + request.hdr.nlmsg_len);
                
                nla->type = XFRMA_ALG_AUTH;
@@ -252,20 +258,20 @@ static status_t add_sa(   private_kernel_interface_t *this,
                nla->algo.alg_key_len = integrity_key.len * 8;
                strcpy(nla->algo.alg_name, mapping_find(kernel_integrity_algs_m, int_alg));
                memcpy(nla->algo.alg_key, integrity_key.ptr, integrity_key.len);
-
+       
                request.hdr.nlmsg_len += nla->length;
-    }
-    
-       /* add IPComp */
-    
-    if (this->send_message(this, &request, &response) != SUCCESS)
-    {
-       allocator_free(response);
-       return FAILED;  
-    }
-       
-    allocator_free(response);
-    return SUCCESS;
+       }
+       
+       /* add IPComp here*/
+       
+       if (this->send_message(this, &request, &response) != SUCCESS)
+       {
+               allocator_free(response);
+               return FAILED;  
+       }
+       
+       allocator_free(response);
+       return SUCCESS;
 }
 
 
@@ -276,7 +282,7 @@ static status_t send_message(private_kernel_interface_t *this, netlink_message_t
        
        request->hdr.nlmsg_seq = ++this->seq;
        request->hdr.nlmsg_pid = this->pid;
-
+       
        memset(&addr, 0, sizeof(struct sockaddr_nl));
        addr.nl_family = AF_NETLINK;
        addr.nl_pid = 0;
@@ -308,17 +314,17 @@ static status_t send_message(private_kernel_interface_t *this, netlink_message_t
                        if (listed_response->hdr.nlmsg_seq == request->hdr.nlmsg_seq)
                        {
                                /* matches our request, this is the reply */
-                               *response = listed_response;
-                               found = TRUE;
-                               break;
-                       }
-               }
-               iterator->destroy(iterator);
-               
-               if (found)
-               {
-                       break;  
-               }
+                               *response = listed_response;
+                               found = TRUE;
+                               break;
+                       }
+               }
+               iterator->destroy(iterator);
+               
+               if (found)
+               {
+                       break;
+               }
                /* we should time out, if something goes wrong */
                pthread_cond_wait(&(this->condvar), &(this->mutex));
        }
@@ -330,16 +336,16 @@ static status_t send_message(private_kernel_interface_t *this, netlink_message_t
 
 
 static void receive_messages(private_kernel_interface_t *this)
-{      
+{
        while(TRUE) 
        {
                netlink_message_t response, *listed_response;
                while (TRUE)
                {
-               struct sockaddr_nl addr;
+                       struct sockaddr_nl addr;
                        socklen_t addr_length;
                        size_t length;
-       
+                       
                        addr_length = sizeof(addr);
                        
                        response.hdr.nlmsg_type = XFRM_MSG_NEWSA;
@@ -347,11 +353,11 @@ static void receive_messages(private_kernel_interface_t *this)
                        if (length < 0)
                        {
                                if (errno == EINTR)
-                       {
-                               /* interrupted, try again */
+                               {
+                                       /* interrupted, try again */
                                        continue;
-                       }
-                       charon->kill(charon, "receiving from netlink socket failed");
+                               }
+                               charon->kill(charon, "receiving from netlink socket failed");
                        }
                        if (!NLMSG_OK(&response.hdr, length))
                        {
@@ -361,7 +367,7 @@ static void receive_messages(private_kernel_interface_t *this)
                        if (addr.nl_pid != 0)
                        {
                                /* not from kernel. not interested, try another one */
-                           continue;
+                               continue;
                        }
                        break;
                }
index eeebbcd..7f57a04 100644 (file)
@@ -54,8 +54,8 @@ struct kernel_interface_t {
         * @todo Cleanup method params
         */
        status_t (*add_sa)(kernel_interface_t *this,
-                               host_t *me,
-                               host_t *other,
+                               host_t *src,
+                               host_t *dst,
                                u_int32_t spi,
                                int protocol,
                                bool tunnel_mode,
index 0360241..fb832ef 100644 (file)
@@ -175,11 +175,10 @@ static logger_t *create_logger(private_logger_manager_t *this, logger_context_t
                        log_thread_ids = TRUE;
                        break;
                case IKE_SA:
-                       logger_level |= LEVEL1;
                        log_thread_ids = TRUE;
                        break;
                case CHILD_SA:
-                       logger_level |= LEVEL1|PRIVATE;
+                       logger_level |= LEVEL1;
                        log_thread_ids = TRUE;
                        break;
                case CONFIGURATION_MANAGER: