- baschtel
authorMartin Willi <martin@strongswan.org>
Fri, 18 Nov 2005 16:29:14 +0000 (16:29 -0000)
committerMartin Willi <martin@strongswan.org>
Fri, 18 Nov 2005 16:29:14 +0000 (16:29 -0000)
- works initiating, results in shared secret

Source/charon/configuration_manager.c
Source/charon/daemon.c
Source/charon/generator.c
Source/charon/ike_sa.c
Source/charon/ike_sa_id.c
Source/charon/ike_sa_manager.c
Source/charon/message.c
Source/charon/socket.c

index a0510bf..b7ffbc0 100644 (file)
@@ -108,6 +108,9 @@ static status_t get_proposals_for_host(private_configuration_manager_t *this, ho
                return OUT_OF_RES;
        }
        
+       proposal->set_proposal_number(proposal, 1);
+       proposal->set_protocol_id(proposal, 1);
+       
        /* 
         * Encryption Algorithm 
         */
@@ -123,7 +126,6 @@ static status_t get_proposals_for_host(private_configuration_manager_t *this, ho
                proposal->destroy(proposal);
                return OUT_OF_RES;
        }
-       transform->set_is_last_transform(transform, FALSE);
        transform->set_transform_type(transform, ENCRYPTION_ALGORITHM);
        transform->set_transform_id(transform, ENCR_AES_CBC);
        
@@ -157,9 +159,8 @@ static status_t get_proposals_for_host(private_configuration_manager_t *this, ho
                proposal->destroy(proposal);
                return OUT_OF_RES;
        }
-       transform->set_is_last_transform(transform, FALSE);
        transform->set_transform_type(transform, PSEUDO_RANDOM_FUNCTION);
-       transform->set_transform_id(transform, PRF_HMAC_SHA1);
+       transform->set_transform_id(transform, PRF_HMAC_MD5);
        
        attribute = transform_attribute_create();
        if (attribute == NULL)
@@ -192,9 +193,8 @@ static status_t get_proposals_for_host(private_configuration_manager_t *this, ho
                proposal->destroy(proposal);
                return OUT_OF_RES;
        }
-       transform->set_is_last_transform(transform, FALSE);
        transform->set_transform_type(transform, INTEGRITIY_ALGORITHM);
-       transform->set_transform_id(transform, AUTH_HMAC_SHA1_96);
+       transform->set_transform_id(transform, AUTH_HMAC_MD5_96);
        
        attribute = transform_attribute_create();
        if (attribute == NULL)
@@ -209,7 +209,7 @@ static status_t get_proposals_for_host(private_configuration_manager_t *this, ho
                return OUT_OF_RES;
        }
        attribute->set_attribute_type(attribute, KEY_LENGTH);
-       attribute->set_value(attribute, 12);
+       attribute->set_value(attribute, 16);
        
        
     /* 
@@ -227,7 +227,6 @@ static status_t get_proposals_for_host(private_configuration_manager_t *this, ho
                proposal->destroy(proposal);
                return OUT_OF_RES;
        }
-       transform->set_is_last_transform(transform, FALSE);
        transform->set_transform_type(transform, DIFFIE_HELLMAN_GROUP);
        transform->set_transform_id(transform, MODP_1024_BIT);
        
@@ -238,9 +237,148 @@ static status_t get_proposals_for_host(private_configuration_manager_t *this, ho
        
 static status_t select_proposals_for_host(private_configuration_manager_t *this, host_t *host, linked_list_iterator_t *in, linked_list_iterator_t *out)
 {
+       /* use a default proposal:
+        * - ENCR_AES_CBC 128Bit
+        * - PRF_HMAC_SHA1 128Bit
+        * - AUTH_HMAC_SHA1_96 96Bit
+        * - MODP_1024_BIT
+        */
+       proposal_substructure_t *proposal;
+       transform_substructure_t *transform;
+       transform_attribute_t *attribute;
+       status_t status;
+       
+       proposal = proposal_substructure_create();
+       if (proposal == NULL)
+       {
+               return OUT_OF_RES;
+       }
        
+       proposal->set_proposal_number(proposal, 1);
+       proposal->set_protocol_id(proposal, 1);
        
-       return FAILED;
+       /* 
+        * Encryption Algorithm 
+        */
+       transform = transform_substructure_create();
+       if (transform == NULL)
+       {
+               proposal->destroy(proposal);
+               return OUT_OF_RES;
+       }
+       status = proposal->add_transform_substructure(proposal, transform);
+       if (status != SUCCESS)
+       {
+               proposal->destroy(proposal);
+               return OUT_OF_RES;
+       }
+       transform->set_transform_type(transform, ENCRYPTION_ALGORITHM);
+       transform->set_transform_id(transform, ENCR_AES_CBC);
+       
+       attribute = transform_attribute_create();
+       if (attribute == NULL)
+       {
+               proposal->destroy(proposal);
+               return OUT_OF_RES;
+       }
+       status = transform->add_transform_attribute(transform, attribute);
+       if (status != SUCCESS)
+       {
+               proposal->destroy(proposal);
+               return OUT_OF_RES;
+       }
+       attribute->set_attribute_type(attribute, KEY_LENGTH);
+       attribute->set_value(attribute, 16);
+       
+       /* 
+        * Pseudo-random Function
+        */
+       transform = transform_substructure_create();
+       if (transform == NULL)
+       {
+               proposal->destroy(proposal);
+               return OUT_OF_RES;
+       }
+       status = proposal->add_transform_substructure(proposal, transform);
+       if (status != SUCCESS)
+       {
+               proposal->destroy(proposal);
+               return OUT_OF_RES;
+       }
+       transform->set_transform_type(transform, PSEUDO_RANDOM_FUNCTION);
+       transform->set_transform_id(transform, PRF_HMAC_MD5);
+       
+       attribute = transform_attribute_create();
+       if (attribute == NULL)
+       {               
+               proposal->destroy(proposal);
+               return OUT_OF_RES;
+       }
+       status = transform->add_transform_attribute(transform, attribute);
+       if (status != SUCCESS)
+       {
+               proposal->destroy(proposal);
+               return OUT_OF_RES;
+       }
+       attribute->set_attribute_type(attribute, KEY_LENGTH);
+       attribute->set_value(attribute, 16);
+
+       
+       /* 
+        * Integrity Algorithm 
+        */
+       transform = transform_substructure_create();
+       if (transform == NULL)
+       {
+               proposal->destroy(proposal);
+               return OUT_OF_RES;
+       }
+       status = proposal->add_transform_substructure(proposal, transform);
+       if (status != SUCCESS)
+       {
+               proposal->destroy(proposal);
+               return OUT_OF_RES;
+       }
+       transform->set_transform_type(transform, INTEGRITIY_ALGORITHM);
+       transform->set_transform_id(transform, AUTH_HMAC_MD5_96);
+       
+       attribute = transform_attribute_create();
+       if (attribute == NULL)
+       {               
+               proposal->destroy(proposal);
+               return OUT_OF_RES;
+       }
+       status = transform->add_transform_attribute(transform, attribute);
+       if (status != SUCCESS)
+       {
+               proposal->destroy(proposal);
+               return OUT_OF_RES;
+       }
+       attribute->set_attribute_type(attribute, KEY_LENGTH);
+       attribute->set_value(attribute, 16);
+       
+       
+    /* 
+     * Diffie-Hellman Group 
+     */
+       transform = transform_substructure_create();
+       if (transform == NULL)
+       {
+               proposal->destroy(proposal);
+               return OUT_OF_RES;
+       }
+       status = proposal->add_transform_substructure(proposal, transform);
+       if (status != SUCCESS)
+       {
+               proposal->destroy(proposal);
+               return OUT_OF_RES;
+       }
+       transform->set_transform_type(transform, DIFFIE_HELLMAN_GROUP);
+       transform->set_transform_id(transform, MODP_1024_BIT);
+       
+       out->insert_after(out, (void*)proposal);
+       
+       return SUCCESS;
 }
 
 static status_t is_dh_group_allowed_for_host(private_configuration_manager_t *this, host_t *host, diffie_hellman_group_t group, bool *allowed)
index c30459e..7de66a8 100644 (file)
@@ -145,7 +145,7 @@ int main()
        {
                initiate_ike_sa_job_t *initiate_job;
                
-               initiate_job = initiate_ike_sa_job_create("pinflb30");
+               initiate_job = initiate_ike_sa_job_create("pinflb31");
                global_event_queue->add_relative(global_event_queue, (job_t*)initiate_job, i * 1000);
                
        }
index 92afae6..ec781b8 100644 (file)
@@ -994,7 +994,8 @@ static status_t generate_payload (private_generator_t *this,payload_t *payload)
                                }
                                else
                                {
-                                       status = this->write_bytes_to_buffer(this,(this->data_struct + rules[i].offset),2);
+                                       status = this->generate_u_int_type(this,U_INT_16,rules[i].offset);
+//                                     status = this->write_bytes_to_buffer(this,(this->data_struct + rules[i].offset),2);
                                }
                                break;
                        }                               
index 8c56672..7828157 100644 (file)
@@ -174,6 +174,11 @@ struct private_ike_sa_s {
                 * Priority used get matching dh_group number
                 */
                u_int16_t dh_group_priority;
+               
+               /**
+                * selected proposals
+                */
+               linked_list_t *proposals;
                /**
                 * 
                 */
@@ -438,67 +443,165 @@ static status_t transto_ike_sa_init_requested(private_ike_sa_t *this, char *name
        return SUCCESS;
 }
 
-static status_t transto_ike_sa_init_responded(private_ike_sa_t *this, message_t *message)
+static status_t transto_ike_sa_init_responded(private_ike_sa_t *this, message_t *request)
 {
        status_t status;
        linked_list_iterator_t *payloads;
-       message_t *respond;
+       message_t *response;
+       host_t *source, *destination;
        
-       status = message->parse_body(message);
+       /* this is the first message we process, so copy host infos */
+       request->get_source(request, &source);
+       request->get_destination(request, &destination);
+       /* we need to clone them, since we destroy the message later */
+       destination->clone(destination, &(this->me.host));
+       source->clone(source, &(this->other.host));
+       
+       /* parse incoming message */
+       status = request->parse_body(request);
        if (status != SUCCESS)
        {
+               this->logger->log(this->logger, ERROR, "Could not parse body");
                return status;  
        }
-       
-
-       
-       
-       
-       status = message->get_payload_iterator(message, &payloads);
+       /* iterate over incoming payloads */
+       status = request->get_payload_iterator(request, &payloads);
        if (status != SUCCESS)
        {
-               respond->destroy(respond);
+               request->destroy(request);
                return status;  
        }
        while (payloads->has_next(payloads))
        {
                payload_t *payload;
-               payloads->current(payloads, (void**)payload);
+               payloads->current(payloads, (void**)&payload);
+               
+               this->logger->log(this->logger, CONTROL|MORE, "Processing payload %s", mapping_find(payload_type_m, payload->get_type(payload)));
                switch (payload->get_type(payload))
                {
                        case SECURITY_ASSOCIATION:
                        {
-                               sa_payload_t *sa_payload;
-                               linked_list_iterator_t *proposals;
+                               sa_payload_t *sa_payload = (sa_payload_t*)payload;
+                               linked_list_iterator_t *suggested_proposals, *accepted_proposals;
+                               /* create a list for accepted proposals */
+                               if (this->ike_sa_init_data.proposals == NULL) {
+                                       this->ike_sa_init_data.proposals = linked_list_create();
+                               }
+                               else
+                               {
+                                       /** @todo destroy list contents */      
+                               }
+                               if (this->ike_sa_init_data.proposals == NULL)
+                               {
+                                       payloads->destroy(payloads);
+                                       return OUT_OF_RES;      
+                               }
+                               status = this->ike_sa_init_data.proposals->create_iterator(this->ike_sa_init_data.proposals, &accepted_proposals, FALSE);
+                               if (status != SUCCESS)
+                               {
+                                       payloads->destroy(payloads);
+                                       return status;  
+                               }
+                               
+                               /* get the list of suggested proposals */ 
+                               status = sa_payload->create_proposal_substructure_iterator(sa_payload, &suggested_proposals, TRUE);
+                               if (status != SUCCESS)
+                               {       
+                                       accepted_proposals->destroy(accepted_proposals);
+                                       payloads->destroy(payloads);
+                                       return status;
+                               }
                                
-                               sa_payload = (sa_payload_t*)payload;
-                               status = sa_payload->create_proposal_substructure_iterator(sa_payload, &proposals, TRUE);
+                               /* now let the configuration-manager select a subset of the proposals */
+                               status = global_configuration_manager->select_proposals_for_host(global_configuration_manager,
+                                                                       this->other.host, suggested_proposals, accepted_proposals);
                                if (status != SUCCESS)
                                {
+                                       suggested_proposals->destroy(suggested_proposals);
+                                       accepted_proposals->destroy(accepted_proposals);
                                        payloads->destroy(payloads);
                                        return status;
                                }
-                               //global_configuration_manager->select_proposals_for_host
+                                                                       
+                               suggested_proposals->destroy(suggested_proposals);
+                               accepted_proposals->destroy(accepted_proposals);
                                
+                               /* ok, we have what we need for sa_payload */
                                break;
                        }
                        case KEY_EXCHANGE:
                        {
+                               ke_payload_t *ke_payload = (ke_payload_t*)payload;
+                               diffie_hellman_t *dh;
+                               diffie_hellman_group_t group;
+                               bool allowed_group;
+                               
+                               group = ke_payload->get_dh_group_number(ke_payload);
+                               
+                               status = global_configuration_manager->is_dh_group_allowed_for_host(global_configuration_manager,
+                                                               this->other.host, group, &allowed_group);
+                               if (status != SUCCESS)
+                               {
+                                       payloads->destroy(payloads);
+                                       return status;
+                               }
+                               if (!allowed_group)
+                               {
+                                       /** @todo info reply */ 
+                               }
+                               
+                               dh = diffie_hellman_create(group);
+                               if (dh == NULL)
+                               {
+                                       payloads->destroy(payloads);
+                                       return OUT_OF_RES;
+                               }
+                               
+                               status = dh->set_other_public_value(dh, ke_payload->get_key_exchange_data(ke_payload));
+                               if (status != SUCCESS)
+                               {
+                                       dh->destroy(dh);
+                                       payloads->destroy(payloads);
+                                       return OUT_OF_RES;
+                               }
+                               /** @todo destroy if there is already one */
+                               this->ike_sa_init_data.diffie_hellman = dh;
                                break;
                        }
                        case NONCE:
                        {
+                               nonce_payload_t *nonce_payload = (nonce_payload_t*)payload;
+                               chunk_t nonce;
+                               
+                               nonce_payload->get_nonce(nonce_payload, &nonce);
+                               /** @todo free if there is already one */
+                               this->ike_sa_init_data.received_nonce.ptr = allocator_clone_bytes(nonce.ptr, nonce.len);
+                               this->ike_sa_init_data.received_nonce.len = nonce.len;
+                               if (this->ike_sa_init_data.received_nonce.ptr == NULL)
+                               {
+                                       payloads->destroy(payloads);
+                                       return OUT_OF_RES;
+                               }
                                break;
                        }
                        default:
                        {
-                               
+                               /** @todo handle */
                        }
                                
                }
                        
        }
+       payloads->destroy(payloads);
        
+       printf("done.\n");
+
+       /* set up the reply */
+       status = this->build_message(this, IKE_SA_INIT, FALSE, &response);
+       if (status != SUCCESS)
+       {
+               return status;  
+       }
        
        
        
@@ -520,9 +623,146 @@ static status_t transto_ike_sa_init_responded(private_ike_sa_t *this, message_t
        return SUCCESS;
 }
 
-static status_t transto_ike_auth_requested(private_ike_sa_t *this, message_t *message)
-{
-       return SUCCESS;
+static status_t transto_ike_auth_requested(private_ike_sa_t *this, message_t *response)
+{      
+       status_t status;
+       linked_list_iterator_t *payloads;
+
+       
+       /* parse incoming message */
+       status = response->parse_body(response);
+       if (status != SUCCESS)
+       {
+               this->logger->log(this->logger, ERROR, "Could not parse body");
+               return status;  
+       }
+       /* iterate over incoming payloads */
+       status = response->get_payload_iterator(response, &payloads);
+       if (status != SUCCESS)
+       {
+               response->destroy(response);
+               return status;  
+       }
+       while (payloads->has_next(payloads))
+       {
+               payload_t *payload;
+               payloads->current(payloads, (void**)&payload);
+               
+               this->logger->log(this->logger, CONTROL|MORE, "Processing payload %s", mapping_find(payload_type_m, payload->get_type(payload)));
+               switch (payload->get_type(payload))
+               {
+//                     case SECURITY_ASSOCIATION:
+//                     {
+//                             sa_payload_t *sa_payload = (sa_payload_t*)payload;
+//                             linked_list_iterator_t *suggested_proposals, *accepted_proposals;
+//                             /* create a list for accepted proposals */
+//                             if (this->ike_sa_init_data.proposals == NULL) {
+//                                     this->ike_sa_init_data.proposals = linked_list_create();
+//                             }
+//                             else
+//                             {
+//                                     /** @todo destroy list contents */      
+//                             }
+//                             if (this->ike_sa_init_data.proposals == NULL)
+//                             {
+//                                     payloads->destroy(payloads);
+//                                     return OUT_OF_RES;      
+//                             }
+//                             status = this->ike_sa_init_data.proposals->create_iterator(this->ike_sa_init_data.proposals, &accepted_proposals, FALSE);
+//                             if (status != SUCCESS)
+//                             {
+//                                     payloads->destroy(payloads);
+//                                     return status;  
+//                             }
+//                             
+//                             /* get the list of suggested proposals */ 
+//                             status = sa_payload->create_proposal_substructure_iterator(sa_payload, &suggested_proposals, TRUE);
+//                             if (status != SUCCESS)
+//                             {       
+//                                     accepted_proposals->destroy(accepted_proposals);
+//                                     payloads->destroy(payloads);
+//                                     return status;
+//                             }
+//                             
+//                             /* now let the configuration-manager select a subset of the proposals */
+//                             status = global_configuration_manager->select_proposals_for_host(global_configuration_manager,
+//                                                                     this->other.host, suggested_proposals, accepted_proposals);
+//                             if (status != SUCCESS)
+//                             {
+//                                     suggested_proposals->destroy(suggested_proposals);
+//                                     accepted_proposals->destroy(accepted_proposals);
+//                                     payloads->destroy(payloads);
+//                                     return status;
+//                             }
+//                                                                     
+//                             suggested_proposals->destroy(suggested_proposals);
+//                             accepted_proposals->destroy(accepted_proposals);
+//                             
+//                             /* ok, we have what we need for sa_payload */
+//                             break;
+//                     }
+                       case KEY_EXCHANGE:
+                       {
+                               ke_payload_t *ke_payload = (ke_payload_t*)payload;
+                               diffie_hellman_t *dh;
+                               chunk_t shared_secret;
+                               
+                               dh = this->ike_sa_init_data.diffie_hellman;
+                               
+                               
+
+                               
+                               status = dh->set_other_public_value(dh, ke_payload->get_key_exchange_data(ke_payload));
+                               if (status != SUCCESS)
+                               {
+                                       dh->destroy(dh);
+                                       payloads->destroy(payloads);
+                                       return OUT_OF_RES;
+                               }
+                               
+                               status = dh->get_shared_secret(dh, &shared_secret);
+                               
+                               this->logger->log_chunk(this->logger, RAW, "Shared secret", &shared_secret);
+                               
+                               break;
+                       }
+                       case NONCE:
+                       {
+                               nonce_payload_t *nonce_payload = (nonce_payload_t*)payload;
+                               chunk_t nonce;
+                               
+                               nonce_payload->get_nonce(nonce_payload, &nonce);
+                               /** @todo free if there is already one */
+                               this->ike_sa_init_data.received_nonce.ptr = allocator_clone_bytes(nonce.ptr, nonce.len);
+                               this->ike_sa_init_data.received_nonce.len = nonce.len;
+                               if (this->ike_sa_init_data.received_nonce.ptr == NULL)
+                               {
+                                       payloads->destroy(payloads);
+                                       return OUT_OF_RES;
+                               }
+                               break;
+                       }
+                       default:
+                       {
+                               /** @todo handle */
+                       }
+                               
+               }
+                       
+       }
+       payloads->destroy(payloads);
+       
+       printf("done.\n");
+
+       /* set up the reply */
+       status = this->build_message(this, IKE_SA_INIT, FALSE, &response);
+       if (status != SUCCESS)
+       {
+               return status;  
+       }
+       
+       
+       
 }
 
 /**
@@ -806,6 +1046,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
        this->ike_sa_init_data.sent_nonce.ptr = NULL;
        this->ike_sa_init_data.received_nonce.len = 0;
        this->ike_sa_init_data.received_nonce.ptr = NULL;
+       this->ike_sa_init_data.proposals = NULL;
        this->message_id_out = 0;
        this->message_id_in = 0;
 
index 1453dae..8e8f5b8 100644 (file)
@@ -148,7 +148,15 @@ static bool is_initiator(private_ike_sa_id_t *this)
  */
 static bool switch_initiator(private_ike_sa_id_t *this)
 {
-       return (this->is_initiator_flag = !this->is_initiator_flag);
+       if (this->is_initiator_flag)
+       {
+               this->is_initiator_flag = FALSE;
+       }
+       else
+       {
+               this->is_initiator_flag = TRUE; 
+       }
+       return this->is_initiator_flag;
 }
 
 
index 3cbd072..a3011b3 100644 (file)
@@ -214,11 +214,20 @@ static status_t get_entry_by_id(private_ike_sa_manager_t *this, ike_sa_id_t *ike
        /* default status */
        status = NOT_FOUND;
        
+       
        while (iterator->has_next(iterator))
        {
                ike_sa_entry_t *current;
                bool are_equal = FALSE;
                iterator->current(iterator, (void**)&current);
+               if (current->ike_sa_id->get_responder_spi(current->ike_sa_id) == 0) {
+                       if (current->ike_sa_id->get_initiator_spi(current->ike_sa_id) == ike_sa_id->get_initiator_spi(ike_sa_id))
+                       {
+                               *entry = current;
+                               status = SUCCESS;
+                               break;
+                       }
+               }
                current->ike_sa_id->equals(current->ike_sa_id, ike_sa_id, &are_equal);
                if (are_equal)
                {
index c0618c8..0e67109 100644 (file)
@@ -369,7 +369,8 @@ static exchange_type_t get_request (private_message_t *this)
 static status_t add_payload(private_message_t *this, payload_t *payload)
 {
        payload_t *last_payload;
-       if (this->payloads->get_last(this->payloads,(void **) &last_payload) != SUCCESS)
+       if ((this->payloads->get_count(this->payloads) > 0) &&
+           (this->payloads->get_last(this->payloads,(void **) &last_payload) != SUCCESS))
        {
                return OUT_OF_RES;      
        }
@@ -583,18 +584,23 @@ static status_t parse_header (private_message_t *this)
  */
 static status_t parse_body (private_message_t *this)
 {
-       status_t status;
+       status_t status = SUCCESS;
        int i;
        payload_type_t current_payload_type = this->first_payload;
        supported_payload_entry_t *supported_payloads;
        size_t supported_payloads_count;
        
+                       
        if (this->get_supported_payloads (this,&supported_payloads,&supported_payloads_count) != SUCCESS)
        {
+               this->logger->log(this->logger, ERROR, "could not get supported payloads");
                /* message type is not supported */
                return FAILED;
        }
        
+       
+       this->logger->log(this->logger, ERROR, "first payload %s", mapping_find(payload_type_m, current_payload_type));
+       
        while (current_payload_type != NO_PAYLOAD)
        {
                payload_t *current_payload;
index b98d045..1dab620 100644 (file)
@@ -61,6 +61,7 @@ status_t receiver(private_socket_t *this, packet_t **packet)
        pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
        
        pkt->source = host_create(AF_INET, "0.0.0.0", 0);
+       pkt->destination = host_create(AF_INET, "0.0.0.0", 0);
 
        /* do the read */
        pkt->data.len = recvfrom(this->socket_fd, buffer, MAX_PACKET, 0,