- some logging improvements and cosmetics
[strongswan.git] / src / charon / sa / states / ike_sa_init_responded.c
index e40b0cf..17d9e9d 100644 (file)
@@ -152,7 +152,7 @@ struct private_ike_sa_init_responded_t {
         * @param this          calling object
         * @param notify_payload payload to process
         * @return
-        *                                      - DELETE_ME if IKE_SA should be deleted
+        *                                      - DESTROY_ME if IKE_SA should be deleted
         *                                      - SUCCSS if processed successfull
         */
        status_t (*process_notify_payload) (private_ike_sa_init_responded_t *this, notify_payload_t* notify_payload);
@@ -183,6 +183,7 @@ 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;
+       identification_t *my_id, *other_id;
        connection_t *connection;
        
        if (request->get_exchange_type(request) != IKE_AUTH)
@@ -207,14 +208,14 @@ static status_t process_message(private_ike_sa_init_responded_t *this, message_t
        {
                if (status == NOT_SUPPORTED)
                {
-                       this->logger->log(this->logger, ERROR | LEVEL1, "IKE_AUTH request contains unsupported payload with critical flag set."
+                       this->logger->log(this->logger, ERROR | LEVEL1, "IKE_AUTH request contains unsupported payload with critical flag set. "
                                                                                                                        "Deleting IKE_SA");
                        this->ike_sa->send_notify(this->ike_sa, IKE_AUTH, UNSUPPORTED_CRITICAL_PAYLOAD, CHUNK_INITIALIZER);
-                       return DELETE_ME;
+                       return DESTROY_ME;
                }
                else
                {
-                       this->logger->log(this->logger, AUDIT, "IKE_AUTH request decryption faild. Ignoring message");
+                       this->logger->log(this->logger, AUDIT, "IKE_AUTH request decryption failed. Ignoring message");
                }
                return status;
        }
@@ -291,14 +292,14 @@ static status_t process_message(private_ike_sa_init_responded_t *this, message_t
        if (!(idi_request && sa_request && auth_request && tsi_request && tsr_request))
        {
                this->logger->log(this->logger, AUDIT, "IKE_AUTH reply did not contain all required payloads. Deleting IKE_SA");
-               return DELETE_ME;
+               return DESTROY_ME;
        }
                
        /* build response */
        this->ike_sa->build_message(this->ike_sa, IKE_AUTH, FALSE, &response);
        
        /* add payloads to it */
-       status = this->build_idr_payload(this, idi_request, idr_request, response,&idr_response);
+       status = this->build_idr_payload(this, idi_request, idr_request, response, &idr_response);
        if (status != SUCCESS)
        {
                response->destroy(response);
@@ -335,7 +336,7 @@ static status_t process_message(private_ike_sa_init_responded_t *this, message_t
        {
                this->logger->log(this->logger, AUDIT, "Unable to send IKE_AUTH reply. Deleting IKE_SA");
                response->destroy(response);
-               return DELETE_ME;
+               return DESTROY_ME;
        }
        
        /* install child SA policies */
@@ -355,20 +356,23 @@ static status_t process_message(private_ike_sa_init_responded_t *this, message_t
                if (status != SUCCESS)
                {
                        this->logger->log(this->logger, AUDIT, "Could not install CHILD_SA policy! Deleting IKE_SA");
-                       return DELETE_ME;
+                       return DESTROY_ME;
                }
                this->ike_sa->add_child_sa(this->ike_sa, this->child_sa);
        }
        
-       /* create new state */                                          
+       /* create new state */
        this->ike_sa->set_new_state(this->ike_sa, (state_t*)ike_sa_established_create(this->ike_sa));
        this->destroy_after_state_change(this);
        
        connection = this->ike_sa->get_connection(this->ike_sa);
        my_host = connection->get_my_host(connection);
        other_host = connection->get_other_host(connection);
-       this->logger->log(this->logger, AUDIT, "IKE_SA established between %s - %s", 
-                                         my_host->get_address(my_host), other_host->get_address(other_host));
+       my_id = connection->get_my_id(connection);
+       other_id = connection->get_other_id(connection);
+       this->logger->log(this->logger, AUDIT, "IKE_SA established %s[%s]...%s[%s]", 
+                                         my_host->get_address(my_host), my_id->get_string(my_id),
+                                         other_host->get_address(other_host), other_id->get_string(other_id));
 
        return SUCCESS;
 }
@@ -403,7 +407,7 @@ static status_t build_idr_payload(private_ike_sa_init_responded_t *this, id_payl
        {
                this->logger->log(this->logger, AUDIT, "We don't have a policy for IDs %s - %s. Deleting IKE_SA", 
                                                  my_id->get_string(my_id), other_id->get_string(other_id));
-               return DELETE_ME;
+               return DESTROY_ME;
        }
        
        /* get my id from policy, which must contain a fully qualified valid id */
@@ -436,19 +440,11 @@ static status_t build_sa_payload(private_ike_sa_init_responded_t *this, sa_paylo
        status_t status;
        connection_t *connection;
        
-       /* get proposals from request */
+       /* prepare reply */
+       sa_response = sa_payload_create();
+       
+       /* get proposals from request, and select one with ours */
        proposal_list = request->get_proposals(request);
-       if (proposal_list->get_count(proposal_list) == 0)
-       {
-               /* if the other side did not offer any proposals, we do not create child sa's */
-               this->logger->log(this->logger, AUDIT, "IKE_AUH request did not contain any proposals. No CHILD_SA created");
-               sa_response = sa_payload_create();
-               response->add_payload(response, (payload_t*)sa_response);
-               proposal_list->destroy(proposal_list);
-               return SUCCESS;
-       }
-
-       /* now select a proposal */
        this->logger->log(this->logger, CONTROL|LEVEL1, "Selecting proposals:");
        proposal = this->policy->select_proposal(this->policy, proposal_list);
        /* list is not needed anymore */
@@ -457,37 +453,45 @@ static status_t build_sa_payload(private_ike_sa_init_responded_t *this, sa_paylo
                proposal_tmp->destroy(proposal_tmp);
        }
        proposal_list->destroy(proposal_list);
-       /* do we have a proposal */
+       /* do we have a proposal? */
        if (proposal == NULL)
        {
-               this->logger->log(this->logger, AUDIT, "IKE_AUTH request did not contain any proposals we accept. Deleting IKE_SA");
-               this->ike_sa->send_notify(this->ike_sa, IKE_AUTH, NO_PROPOSAL_CHOSEN, CHUNK_INITIALIZER);
-               return DELETE_ME;       
+               notify_payload_t *notify;
+               this->logger->log(this->logger, AUDIT, "IKE_AUTH request did not contain any proposals we accept. "
+                                                                                          "Adding NO_PROPOSAL_CHOSEN notify");
+               /* add NO_PROPOSAL_CHOSEN and an empty SA payload */
+               notify = notify_payload_create_from_protocol_and_type(PROTO_IKE, NO_PROPOSAL_CHOSEN);
+               response->add_payload(response, (payload_t*)notify);
        }
-       
-       /* set up child sa */
-       seed = chunk_alloc(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);
-       chunk_free(&seed);
-       
-       connection = this->ike_sa->get_connection(this->ike_sa);
-       this->child_sa = child_sa_create(connection->get_my_host(connection),
-                                                                        connection->get_other_host(connection));
-               
-       status = this->child_sa->add(this->child_sa, proposal, prf_plus);
-       prf_plus->destroy(prf_plus);
-       if (status != SUCCESS)
+       else
        {
-               this->logger->log(this->logger, AUDIT, "Could not install CHILD_SA! Deleting IKE_SA");
-               return DELETE_ME;
+               /* set up child sa */
+               seed = chunk_alloc(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);
+               chunk_free(&seed);
+               
+               connection = this->ike_sa->get_connection(this->ike_sa);
+               this->child_sa = child_sa_create(connection->get_my_host(connection),
+                                                                               connection->get_other_host(connection));
+               
+               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");
+                       /* TODO: how do we handle this cleanly? */
+                       sa_response->destroy(sa_response);
+                       proposal->destroy(proposal);
+                       return DESTROY_ME;
+               }
+               
+               /* add proposal to sa payload */
+               sa_response->add_proposal(sa_response, proposal);
+               proposal->destroy(proposal);
        }
-       
-       /* 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;
 }
 
@@ -508,7 +512,7 @@ static status_t build_auth_payload(private_ike_sa_init_responded_t *this, auth_p
                this->logger->log(this->logger, AUDIT, "IKE_AUTH request verification failed. Deleting IKE_SA");
                this->ike_sa->send_notify(this->ike_sa, IKE_AUTH, AUTHENTICATION_FAILED, CHUNK_INITIALIZER);
                authenticator->destroy(authenticator);
-               return DELETE_ME;
+               return DESTROY_ME;
        }
                
        status = authenticator->compute_auth_data(authenticator,&auth_reply, this->ike_sa_init_response_data,this->received_nonce,my_id_payload,FALSE);
@@ -516,8 +520,7 @@ static status_t build_auth_payload(private_ike_sa_init_responded_t *this, auth_p
        if (status != SUCCESS)
        {
                this->logger->log(this->logger, AUDIT, "Unable to build authentication data for IKE_AUTH reply. Deleting IKE_SA");
-               return DELETE_ME;
-               
+               return DESTROY_ME;
        }
        
        response->add_payload(response, (payload_t *)auth_reply);
@@ -551,6 +554,19 @@ static status_t build_ts_payload(private_ike_sa_init_responded_t *this, bool ts_
        ts_response = ts_payload_create_from_traffic_selectors(ts_initiator, ts_selected);
        response->add_payload(response, (payload_t*)ts_response);
        
+       /* add notify if traffic selectors do not match */
+       if (!ts_initiator &&
+               (ts_selected->get_count(ts_selected) == 0 || this->other_ts->get_count(this->other_ts) == 0))
+       {
+               notify_payload_t *notify;
+               
+               this->logger->log(this->logger, AUDIT, "IKE_AUTH request did not contain any traffic selectors we accept. "
+                                                                                          "Adding TS_UNACCEPTABLE notify");
+               
+               notify = notify_payload_create_from_protocol_and_type(0, TS_UNACCEPTABLE);
+               response->add_payload(response, (payload_t*)notify);
+       }
+       
        /* cleanup */
        while (ts_received->remove_last(ts_received, (void**)&ts) == SUCCESS)
        {