- handle IKE_SA setup without a piggy-packed CHILD_SA
authorMartin Willi <martin@strongswan.org>
Wed, 24 May 2006 09:05:21 +0000 (09:05 -0000)
committerMartin Willi <martin@strongswan.org>
Wed, 24 May 2006 09:05:21 +0000 (09:05 -0000)
  more IKEv2 conform

src/charon/doc/Todo-list.txt
src/charon/encoding/payloads/notify_payload.c
src/charon/encoding/payloads/notify_payload.h
src/charon/encoding/payloads/sa_payload.c
src/charon/sa/states/ike_auth_requested.c
src/charon/sa/states/ike_sa_init_responded.c
src/charon/threads/stroke_interface.c

index 7bff26d..2398acc 100644 (file)
   - certificate exchange
 
 + Apply -W's from Makefile.program to charon
-- do ipsec status via starter
++ do ipsec status via starter
 - add more output to to up/down, somehow...
 
-- stroke status should show configured connections
-- stroke loglevel update
++ stroke status should show configured connections
++ stroke loglevel update
 - stroke argument parsing via getopts/gperf?
 
 - implement 3DES to load encrypted pem files
-- ipsec.secrets parsing
++ ipsec.secrets parsing
 
 - trapping
-- delete notify, when to send?
++ proper delete messages
 - notifys on connection setup failure
 - create child sa message/rekeying
 
-- new build environment (autotools?)
++ new build environment (autotools?)
index 43d0c53..a4062cf 100644 (file)
@@ -44,7 +44,7 @@ mapping_t notify_message_type_m[] = {
        {NO_ADDITIONAL_SAS, "NO_ADDITIONAL_SAS"},
        {INTERNAL_ADDRESS_FAILURE, "INTERNAL_ADDRESS_FAILURE"},
        {FAILED_CP_REQUIRED, "FAILED_CP_REQUIRED"},
-       {TS_UACCEPTABLE, "TS_UACCEPTABLE"},
+       {TS_UNACCEPTABLE, "TS_UNACCEPTABLE"},
        {INVALID_SELECTORS, "INVALID_SELECTORS"},
        {INITIAL_CONTACT, "INITIAL_CONTACT"},
        {SET_WINDOW_SIZE, "SET_WINDOW_SIZE"},
index 4c9383e..ab86a6d 100644 (file)
@@ -60,7 +60,7 @@ enum notify_message_type_t {
        NO_ADDITIONAL_SAS = 35,
        INTERNAL_ADDRESS_FAILURE = 36,
        FAILED_CP_REQUIRED = 37,
-       TS_UACCEPTABLE = 38,
+       TS_UNACCEPTABLE = 38,
        INVALID_SELECTORS = 39,
        
        INITIAL_CONTACT = 16384,
index 81b4e67..345264b 100644 (file)
@@ -341,6 +341,7 @@ sa_payload_t *sa_payload_create()
        /* public functions */
        this->public.create_proposal_substructure_iterator = (iterator_t* (*) (sa_payload_t *,bool)) create_proposal_substructure_iterator;
        this->public.add_proposal_substructure = (void (*) (sa_payload_t *,proposal_substructure_t *)) add_proposal_substructure;
+       this->public.add_proposal = (void (*) (sa_payload_t*,proposal_t*))add_proposal;
        this->public.get_proposals = (linked_list_t* (*) (sa_payload_t *)) get_proposals;
        this->public.destroy = (void (*) (sa_payload_t *)) destroy;
        
index 069f165..45e40be 100644 (file)
@@ -521,19 +521,33 @@ static status_t process_notify_payload(private_ike_auth_requested_t *this, notif
                case INVALID_SYNTAX:
                {
                        this->logger->log(this->logger, AUDIT, "IKE_AUTH reply contained an INVALID_SYNTAX notify. Deleting IKE_SA");
-                       return DESTROY_ME;      
+                       return DESTROY_ME;
                        
                }
                case AUTHENTICATION_FAILED:
                {
                        this->logger->log(this->logger, AUDIT, "IKE_AUTH reply contained an AUTHENTICATION_FAILED notify. Deleting IKE_SA");
-                       return DESTROY_ME;      
+                       return DESTROY_ME;
                        
                }
                case SINGLE_PAIR_REQUIRED:
                {
                        this->logger->log(this->logger, AUDIT, "IKE_AUTH reply contained a SINGLE_PAIR_REQUIRED notify. Deleting IKE_SA");
-                       return DESTROY_ME;              
+                       return DESTROY_ME;
+               }
+               case TS_UNACCEPTABLE:
+               {
+                       /* TODO: We currently check only the replied TS payloads, which should be empty. Should
+                       * we interpret the notify additionaly? */
+                       this->logger->log(this->logger, CONTROL, "IKE_AUTH reply contained a TS_UNACCEPTABLE notify. Ignored");
+                       return SUCCESS;
+               }
+               case NO_PROPOSAL_CHOSEN:
+               {
+                       /* TODO: We currently check only the replied SA payload, which should be empty. Should
+                        * we interpret the notify additionaly? */
+                       this->logger->log(this->logger, CONTROL, "IKE_AUTH reply contained a NO_PROPOSAL_CHOSEN notify. Ignored");
+                       return SUCCESS;
                }
                default:
                {
index 3a37924..249f058 100644 (file)
@@ -436,19 +436,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 +449,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 DESTROY_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 DESTROY_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;
 }
 
@@ -550,6 +550,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)
        {
index 9d9fb36..b8e5ba9 100755 (executable)
@@ -332,6 +332,8 @@ static void stroke_initiate(private_stroke_t *this, stroke_msg_t *msg)
        /* only initiate if it is an IKEv2 connection, ignore IKEv1 */
        else if (connection->is_ikev2(connection))
        {
+               this->stroke_logger->log(this->stroke_logger, CONTROL, "initiating connection \"%s\" (see log)...", msg->initiate.name);
+       
                job = initiate_ike_sa_job_create(connection);
                charon->job_queue->add(charon->job_queue, (job_t*)job);
        }