- fixed policy setup bug
authorMartin Willi <martin@strongswan.org>
Thu, 23 Feb 2006 16:22:12 +0000 (16:22 -0000)
committerMartin Willi <martin@strongswan.org>
Thu, 23 Feb 2006 16:22:12 +0000 (16:22 -0000)
Source/charon/sa/child_sa.c
Source/charon/sa/states/ike_auth_requested.c
Source/charon/sa/states/ike_sa_init_responded.c

index d6e6ce6..2808cff 100644 (file)
@@ -310,6 +310,32 @@ static status_t update(private_child_sa_t *this, proposal_t *proposal, prf_plus_
        return SUCCESS;
 }
 
+static u_int8_t get_mask(chunk_t start, chunk_t end)
+{
+       int byte, bit, mask = 0;
+       
+       if (start.len != end.len)
+       {
+               return 0;
+       }
+       for (byte = 0; byte < start.len; byte++)
+       {
+               for (bit = 7; bit >= 0; bit--)
+               {
+                       if ((*(start.ptr + byte) | (1<<bit)) ==
+                               (*(end.ptr + byte) | (1<<bit)))
+                       {
+                               mask++;
+                       }
+                       else
+                       {
+                               return mask;
+                       }
+               }
+       }
+       return start.len * 8;
+}
+
 static status_t add_policy(private_child_sa_t *this, linked_list_t *my_ts, linked_list_t *other_ts)
 {
        traffic_selector_t *local_ts, *remote_ts;
@@ -318,14 +344,14 @@ static status_t add_policy(private_child_sa_t *this, linked_list_t *my_ts, linke
        int family;
        chunk_t from_addr, to_addr;
        u_int16_t from_port, to_port;
+       status_t status;
        
        my_ts->get_first(my_ts, (void**)&local_ts);
        other_ts->get_first(other_ts, (void**)&remote_ts);
-       
                
        family = local_ts->get_type(local_ts) == TS_IPV4_ADDR_RANGE ? AF_INET : AF_INET6;
        from_addr = local_ts->get_from_address(local_ts);
-       //to_addr = local_ts->get_to_address(local_ts);
+       to_addr = local_ts->get_to_address(local_ts);
        from_port = local_ts->get_from_port(local_ts);
        to_port = local_ts->get_to_port(local_ts);
        if (from_port != to_port)
@@ -333,12 +359,13 @@ static status_t add_policy(private_child_sa_t *this, linked_list_t *my_ts, linke
                from_port = 0;
        }
        my_net = host_create_from_chunk(family, from_addr, from_port);
+       my_mask = get_mask(from_addr, to_addr);
        allocator_free_chunk(&from_addr);
-       my_mask = 16;
+       allocator_free_chunk(&to_addr);
        
        family = remote_ts->get_type(remote_ts) == TS_IPV4_ADDR_RANGE ? AF_INET : AF_INET6;
        from_addr = remote_ts->get_from_address(remote_ts);
-       //to_addr = remote_ts->get_to_address(remote_ts);
+       to_addr = remote_ts->get_to_address(remote_ts);
        from_port = remote_ts->get_from_port(remote_ts);
        to_port = remote_ts->get_to_port(remote_ts);
        if (from_port != to_port)
@@ -346,10 +373,11 @@ static status_t add_policy(private_child_sa_t *this, linked_list_t *my_ts, linke
                from_port = 0;
        }
        other_net = host_create_from_chunk(family, from_addr, from_port);
+       other_mask = get_mask(from_addr, to_addr);
        allocator_free_chunk(&from_addr);
-       other_mask = 16;
+       allocator_free_chunk(&to_addr);
        
-       charon->kernel_interface->add_policy(charon->kernel_interface,
+       status = charon->kernel_interface->add_policy(charon->kernel_interface,
                                                                                this->me, this->other,
                                                                                my_net, other_net,
                                                                                my_mask, other_mask,
@@ -357,23 +385,23 @@ static status_t add_policy(private_child_sa_t *this, linked_list_t *my_ts, linke
                                                                                0, this->ah_spi, this->esp_spi,
                                                                                this->reqid);
        
-       charon->kernel_interface->add_policy(charon->kernel_interface,
-                                                                                this->me, this->other,
+       status |= charon->kernel_interface->add_policy(charon->kernel_interface,
+                                                                                this->other, this->me,
                                                                                 other_net, my_net,
                                                                                 other_mask, my_mask,
                                                                                 XFRM_POLICY_IN,
                                                                                 0, this->ah_spi, this->esp_spi,
                                                                                 this->reqid);
        
-       charon->kernel_interface->add_policy(charon->kernel_interface,
-                                                                                this->me, this->other,
+       status |= charon->kernel_interface->add_policy(charon->kernel_interface,
+                                                                                this->other, this->me,
                                                                                 other_net, my_net,
                                                                                 other_mask, my_mask,
                                                                                 XFRM_POLICY_FWD,
                                                                                 0, this->ah_spi, this->esp_spi,
                                                                                 this->reqid);
        
-       return SUCCESS;
+       return status;
 }
 
 /**
index 41dfb2c..35e4c24 100644 (file)
@@ -288,12 +288,12 @@ static status_t process_message(private_ike_auth_requested_t *this, message_t *i
        {
                return status;
        }
-       status = this->process_sa_payload(this, sa_payload);
+       status = this->process_auth_payload(this, auth_payload,idr_payload);
        if (status != SUCCESS)
        {
                return status;
        }
-       status = this->process_auth_payload(this, auth_payload,idr_payload);
+       status = this->process_sa_payload(this, sa_payload);
        if (status != SUCCESS)
        {
                return status;
index 87e1318..da0b0a7 100644 (file)
@@ -79,9 +79,9 @@ struct private_ike_sa_init_responded_t {
        sa_config_t *sa_config;
        
        /**
-        * Proposal selected for CHILD_SA
+        * CHILD_SA, if set up
         */
-       proposal_t *proposal;
+       child_sa_t *child_sa;
        
        /**
         * Traffic selectors applicable at our site
@@ -155,6 +155,16 @@ struct private_ike_sa_init_responded_t {
         *                                      - SUCCSS if processed successfull
         */
        status_t (*process_notify_payload) (private_ike_sa_init_responded_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_sa_init_responded_t *this);
 };
 
 /**
@@ -172,9 +182,6 @@ static status_t process_message(private_ike_sa_init_responded_t *this, message_t
        signer_t *signer;
        status_t status;
        host_t *my_host, *other_host;
-       chunk_t seed;
-       prf_plus_t *prf_plus;
-       child_sa_t *child_sa;
        
        
        if (request->get_exchange_type(request) != IKE_AUTH)
@@ -297,13 +304,13 @@ static status_t process_message(private_ike_sa_init_responded_t *this, message_t
                response->destroy(response);
                return status;
        }
-       status = this->build_sa_payload(this, sa_request, response);
+       status = this->build_auth_payload(this, auth_request,idi_request, idr_response,response);
        if (status != SUCCESS)
        {
                response->destroy(response);
                return status;
        }
-       status = this->build_auth_payload(this, auth_request,idi_request, idr_response,response);
+       status = this->build_sa_payload(this, sa_request, response);
        if (status != SUCCESS)
        {
                response->destroy(response);
@@ -331,8 +338,8 @@ static status_t process_message(private_ike_sa_init_responded_t *this, message_t
                return DELETE_ME;
        }
        
-       /* install child SAs for AH and esp */
-       if (!this->proposal)
+       /* install child SA policies */
+       if (!this->child_sa)
        {
                this->logger->log(this->logger, CONTROL, "Proposal negotiation failed, no CHILD_SA built");
        }
@@ -342,29 +349,13 @@ static status_t process_message(private_ike_sa_init_responded_t *this, message_t
        }
        else
        {
-               seed = allocator_alloc_as_chunk(this->received_nonce.len + this->sent_nonce.len);
-               memcpy(seed.ptr, this->received_nonce.ptr, this->received_nonce.len);
-               memcpy(seed.ptr + this->received_nonce.len, this->sent_nonce.ptr, this->sent_nonce.len);
-               prf_plus = prf_plus_create(this->ike_sa->get_child_prf(this->ike_sa), seed);
-               allocator_free_chunk(&seed);
-               
-               child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa),
-                                                               this->ike_sa->get_other_host(this->ike_sa));
-               
-               status = child_sa->add(child_sa, this->proposal, prf_plus);
-               prf_plus->destroy(prf_plus);
-               if (status != SUCCESS)
-               {
-                       this->logger->log(this->logger, AUDIT, "Could not install CHILD_SA! Deleting IKE_SA");
-                       return DELETE_ME;
-               }
-               status = child_sa->add_policy(child_sa, this->my_ts, this->other_ts);
+               status = this->child_sa->add_policy(this->child_sa, this->my_ts, this->other_ts);
                if (status != SUCCESS)
                {
                        this->logger->log(this->logger, AUDIT, "Could not install CHILD_SA policy! Deleting IKE_SA");
                        return DELETE_ME;
                }
-               this->ike_sa->add_child_sa(this->ike_sa, child_sa);
+               this->ike_sa->add_child_sa(this->ike_sa, this->child_sa);
        }
        
        /* create new state */
@@ -376,7 +367,7 @@ static status_t process_message(private_ike_sa_init_responded_t *this, message_t
                                                
        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;
 }
@@ -445,6 +436,9 @@ static status_t build_sa_payload(private_ike_sa_init_responded_t *this, sa_paylo
        proposal_t *proposal, *proposal_tmp;
        linked_list_t *proposal_list;
        sa_payload_t *sa_response;
+       chunk_t seed;
+       prf_plus_t *prf_plus;
+       status_t status;
        
        /* get proposals from request */
        proposal_list = request->get_proposals(request);
@@ -475,12 +469,28 @@ static status_t build_sa_payload(private_ike_sa_init_responded_t *this, sa_paylo
                return DELETE_ME;       
        }
        
-       /* apply proposal */
-       this->proposal = proposal;
+       /* set up child sa */
+       seed = allocator_alloc_as_chunk(this->received_nonce.len + this->sent_nonce.len);
+       memcpy(seed.ptr, this->received_nonce.ptr, this->received_nonce.len);
+       memcpy(seed.ptr + this->received_nonce.len, this->sent_nonce.ptr, this->sent_nonce.len);
+       prf_plus = prf_plus_create(this->ike_sa->get_child_prf(this->ike_sa), seed);
+       allocator_free_chunk(&seed);
+               
+       this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa),
+                                                                        this->ike_sa->get_other_host(this->ike_sa));
+               
+       status = this->child_sa->add(this->child_sa, proposal, prf_plus);
+       prf_plus->destroy(prf_plus);
+       if (status != SUCCESS)
+       {
+               this->logger->log(this->logger, AUDIT, "Could not install CHILD_SA! Deleting IKE_SA");
+               return DELETE_ME;
+       }
        
        /* create payload with selected propsal */
        sa_response = sa_payload_create_from_proposal(proposal);
        response->add_payload(response, (payload_t*)sa_response);
+       proposal->destroy(proposal);
        return SUCCESS;
 }
 
@@ -590,7 +600,7 @@ static ike_sa_state_t get_state(private_ike_sa_init_responded_t *this)
 }
 
 /**
- * Implementation of state_t.get_state.
+ * Implementation of state_t.destroy.
  */
 static void destroy(private_ike_sa_init_responded_t *this)
 {
@@ -616,9 +626,39 @@ static void destroy(private_ike_sa_init_responded_t *this)
                }
                this->other_ts->destroy(this->other_ts);
        }
-       if (this->proposal)
+       if (this->child_sa)
        {
-               this->proposal->destroy(this->proposal);
+               this->child_sa->destroy(this->child_sa);
+       }
+
+       allocator_free(this);
+}
+/**
+ * Implementation of private_ike_sa_init_responded.destroy_after_state_change.
+ */
+static void destroy_after_state_change(private_ike_sa_init_responded_t *this)
+{
+       allocator_free_chunk(&(this->received_nonce));
+       allocator_free_chunk(&(this->sent_nonce));
+       allocator_free_chunk(&(this->ike_sa_init_response_data));
+       allocator_free_chunk(&(this->ike_sa_init_request_data));
+       if (this->my_ts)
+       {
+               traffic_selector_t *ts;
+               while (this->my_ts->remove_last(this->my_ts, (void**)&ts) == SUCCESS)
+               {
+                       ts->destroy(ts);
+               }
+               this->my_ts->destroy(this->my_ts);
+       }
+       if (this->other_ts)
+       {
+               traffic_selector_t *ts;
+               while (this->other_ts->remove_last(this->other_ts, (void**)&ts) == SUCCESS)
+               {
+                       ts->destroy(ts);
+               }
+               this->other_ts->destroy(this->other_ts);
        }
 
        allocator_free(this);
@@ -642,6 +682,7 @@ ike_sa_init_responded_t *ike_sa_init_responded_create(protected_ike_sa_t *ike_sa
        this->build_auth_payload = build_auth_payload;
        this->build_ts_payload = build_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;
@@ -651,7 +692,7 @@ ike_sa_init_responded_t *ike_sa_init_responded_create(protected_ike_sa_t *ike_sa
        this->ike_sa_init_request_data = ike_sa_init_request_data;
        this->my_ts = NULL;
        this->other_ts = NULL;
-       this->proposal = NULL;
+       this->child_sa = NULL;
        this->logger = this->ike_sa->get_logger(this->ike_sa);
        
        return &(this->public);