Parse proposal substructure with multiple IKEv1 transforms to multiple proposals
authorMartin Willi <martin@revosec.ch>
Tue, 22 Nov 2011 16:04:07 +0000 (17:04 +0100)
committerMartin Willi <martin@revosec.ch>
Tue, 20 Mar 2012 16:30:49 +0000 (17:30 +0100)
src/libcharon/encoding/payloads/proposal_substructure.c
src/libcharon/encoding/payloads/proposal_substructure.h
src/libcharon/encoding/payloads/sa_payload.c

index a1c58af..66fa899 100644 (file)
@@ -650,18 +650,35 @@ static void add_to_proposal_v1_esp(proposal_t *proposal,
                                                        transform->get_transform_id(transform), key_length);
 }
 
-METHOD(proposal_substructure_t, get_proposal, proposal_t*,
-       private_proposal_substructure_t *this)
+METHOD(proposal_substructure_t, get_proposals, void,
+       private_proposal_substructure_t *this, linked_list_t *proposals)
 {
        transform_substructure_t *transform;
        enumerator_t *enumerator;
-       proposal_t *proposal;
+       proposal_t *proposal = NULL;
+       u_int64_t spi = 0;
 
-       proposal = proposal_create(this->protocol_id, this->proposal_number);
+       switch (this->spi.len)
+       {
+               case 4:
+                       spi =  *((u_int32_t*)this->spi.ptr);
+                       break;
+               case 8:
+                       spi = *((u_int64_t*)this->spi.ptr);
+                       break;
+               default:
+                       break;
+       }
 
        enumerator = this->transforms->create_enumerator(this->transforms);
        while (enumerator->enumerate(enumerator, &transform))
        {
+               if (!proposal)
+               {
+                       proposal = proposal_create(this->protocol_id, this->proposal_number);
+                       proposal->set_spi(proposal, spi);
+                       proposals->insert_last(proposals, proposal);
+               }
                if (this->type == PROPOSAL_SUBSTRUCTURE)
                {
                        add_to_proposal_v2(proposal, transform);
@@ -679,27 +696,11 @@ METHOD(proposal_substructure_t, get_proposal, proposal_t*,
                                default:
                                        break;
                        }
-                       /* TODO-IKEv1: We currently accept the first set of transforms
-                        * in a substructure only. We need to return multiple proposals,
-                        * but this messes up proposal numbering, as we don't support
-                        * transform numbering. */
-                       break;
+                       /* create a new proposal for each transform in IKEv1 */
+                       proposal = NULL;
                }
        }
        enumerator->destroy(enumerator);
-
-       switch (this->spi.len)
-       {
-               case 4:
-                       proposal->set_spi(proposal, *((u_int32_t*)this->spi.ptr));
-                       break;
-               case 8:
-                       proposal->set_spi(proposal, *((u_int64_t*)this->spi.ptr));
-                       break;
-               default:
-                       break;
-       }
-       return proposal;
 }
 
 METHOD(proposal_substructure_t, create_substructure_enumerator, enumerator_t*,
@@ -741,7 +742,7 @@ proposal_substructure_t *proposal_substructure_create(payload_type_t type)
                        .set_protocol_id = _set_protocol_id,
                        .get_protocol_id = _get_protocol_id,
                        .set_is_last_proposal = _set_is_last_proposal,
-                       .get_proposal = _get_proposal,
+                       .get_proposals = _get_proposals,
                        .create_substructure_enumerator = _create_substructure_enumerator,
                        .set_spi = _set_spi,
                        .get_spi = _get_spi,
index 79a6ca2..496a352 100644 (file)
@@ -96,11 +96,11 @@ struct proposal_substructure_t {
        void (*set_spi) (proposal_substructure_t *this, chunk_t spi);
 
        /**
-        * Get a proposal_t from the propsal_substructure_t.
+        * Get proposals contained in a propsal_substructure_t.
         *
-        * @return                      proposal_t
+        * @param list          list to add created proposals to
         */
-       proposal_t * (*get_proposal) (proposal_substructure_t *this);
+       void (*get_proposals) (proposal_substructure_t *this, linked_list_t *list);
 
        /**
         * Create an enumerator over transform substructures.
index becc424..05695fc 100644 (file)
@@ -297,8 +297,8 @@ METHOD(sa_payload_t, get_proposals, linked_list_t*,
        int ignore_struct_number = 0;
        enumerator_t *enumerator;
        proposal_substructure_t *substruct;
-       linked_list_t *list;
        proposal_t *proposal;
+       linked_list_t *list;
 
        if (this->type == SECURITY_ASSOCIATION_V1)
        {       /* IKEv1 proposals start with 0 */
@@ -320,18 +320,16 @@ METHOD(sa_payload_t, get_proposals, linked_list_t*,
                        if (ignore_struct_number < struct_number)
                        {
                                /* remove an already added, if first of series */
-                               list->remove_last(list, (void**)&proposal);
-                               proposal->destroy(proposal);
+                               if (list->remove_last(list, (void**)&proposal) == SUCCESS)
+                               {
+                                       proposal->destroy(proposal);
+                               }
                                ignore_struct_number = struct_number;
                        }
                        continue;
                }
                struct_number++;
-               proposal = substruct->get_proposal(substruct);
-               if (proposal)
-               {
-                       list->insert_last(list, proposal);
-               }
+               substruct->get_proposals(substruct, list);
        }
        enumerator->destroy(enumerator);
        return list;