Encode multiple IKEv1 proposals in a single transform substructure
authorMartin Willi <martin@revosec.ch>
Tue, 22 Nov 2011 15:47:17 +0000 (16:47 +0100)
committerMartin Willi <martin@revosec.ch>
Tue, 20 Mar 2012 16:30:48 +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 0555cba..a1c58af 100644 (file)
@@ -760,14 +760,14 @@ proposal_substructure_t *proposal_substructure_create(payload_type_t type)
  * Add an IKEv1 IKE proposal to the substructure
  */
 static void set_from_proposal_v1_ike(private_proposal_substructure_t *this,
-                                                                        proposal_t *proposal)
+                                                                        proposal_t *proposal, int number)
 {
        transform_substructure_t *transform;
        u_int16_t alg, key_size;
        enumerator_t *enumerator;
 
        transform = transform_substructure_create_type(TRANSFORM_SUBSTRUCTURE_V1,
-                                                                                                  0, IKEV1_TRANSID_KEY_IKE);
+                                                                                               number, IKEV1_TRANSID_KEY_IKE);
 
        enumerator = proposal->create_enumerator(proposal, ENCRYPTION_ALGORITHM);
        if (enumerator->enumerate(enumerator, &alg, &key_size))
@@ -829,7 +829,7 @@ static void set_from_proposal_v1_ike(private_proposal_substructure_t *this,
  * Add an IKEv1 ESP proposal to the substructure
  */
 static void set_from_proposal_v1_esp(private_proposal_substructure_t *this,
-                                                                        proposal_t *proposal)
+                                                                        proposal_t *proposal, int number)
 {
        transform_substructure_t *transform = NULL;
        u_int16_t alg, key_size;
@@ -839,7 +839,7 @@ static void set_from_proposal_v1_esp(private_proposal_substructure_t *this,
        if (enumerator->enumerate(enumerator, &alg, &key_size))
        {
                transform = transform_substructure_create_type(TRANSFORM_SUBSTRUCTURE_V1,
-                                                                                                  0, alg);
+                                                                                                  number, alg);
                if (key_size)
                {
                        transform->add_transform_attribute(transform,
@@ -968,10 +968,10 @@ proposal_substructure_t *proposal_substructure_create_from_proposal(
                switch (proposal->get_protocol(proposal))
                {
                        case PROTO_IKE:
-                               set_from_proposal_v1_ike(this, proposal);
+                               set_from_proposal_v1_ike(this, proposal, 0);
                                break;
                        case PROTO_ESP:
-                               set_from_proposal_v1_esp(this, proposal);
+                               set_from_proposal_v1_esp(this, proposal, 0);
                                break;
                        default:
                                break;
@@ -1003,3 +1003,43 @@ proposal_substructure_t *proposal_substructure_create_from_proposal(
 
        return &this->public;
 }
+
+/**
+ * See header.
+ */
+proposal_substructure_t *proposal_substructure_create_from_proposals(
+                                                                                                       linked_list_t *proposals)
+{
+       private_proposal_substructure_t *this = NULL;
+       enumerator_t *enumerator;
+       proposal_t *proposal;
+       int number = 0;
+
+       enumerator = proposals->create_enumerator(proposals);
+       while (enumerator->enumerate(enumerator, &proposal))
+       {
+               if (!this)
+               {
+                       this = (private_proposal_substructure_t*)
+                                               proposal_substructure_create_from_proposal(
+                                                                               PROPOSAL_SUBSTRUCTURE_V1, proposal);
+               }
+               else
+               {
+                       switch (proposal->get_protocol(proposal))
+                       {
+                               case PROTO_IKE:
+                                       set_from_proposal_v1_ike(this, proposal, ++number);
+                                       break;
+                               case PROTO_ESP:
+                                       set_from_proposal_v1_esp(this, proposal, ++number);
+                                       break;
+                               default:
+                                       break;
+                       }
+               }
+       }
+       enumerator->destroy(enumerator);
+
+       return &this->public;
+}
index 72bbdd6..79a6ca2 100644 (file)
@@ -127,10 +127,19 @@ proposal_substructure_t *proposal_substructure_create(payload_type_t type);
  * Creates a proposal_substructure_t from a proposal_t.
  *
  * @param type         PROPOSAL_SUBSTRUCTURE or PROPOSAL_SUBSTRUCTURE_V1
- * @param proposal             proposal to build a substruct out of it
- * @return                             proposal_substructure_t object
+ * @param proposal     proposal to build a substruct out of it
+ * @return                     proposal_substructure_t object
  */
 proposal_substructure_t *proposal_substructure_create_from_proposal(
                                                                        payload_type_t type, proposal_t *proposal);
 
+/**
+ * Creates a proposal_substructure_t from a list of proposal_t (IKEv1 only).
+ *
+ * @param proposal     proposal to build a substruct out of it
+ * @return                     IKEv1 proposal_substructure_t PROPOSAL_SUBSTRUCTURE_V1
+ */
+proposal_substructure_t *proposal_substructure_create_from_proposals(
+                                                                       linked_list_t *proposals);
+
 #endif /** PROPOSAL_SUBSTRUCTURE_H_ @}*/
index 8995841..becc424 100644 (file)
@@ -398,13 +398,25 @@ sa_payload_t *sa_payload_create_from_proposal_list(payload_type_t type,
        proposal_t *proposal;
 
        this = (private_sa_payload_t*)sa_payload_create(type);
-       enumerator = proposals->create_enumerator(proposals);
-       while (enumerator->enumerate(enumerator, &proposal))
+       if (type == SECURITY_ASSOCIATION)
        {
-               add_proposal(this, proposal);
+               enumerator = proposals->create_enumerator(proposals);
+               while (enumerator->enumerate(enumerator, &proposal))
+               {
+                       add_proposal(this, proposal);
+               }
+               enumerator->destroy(enumerator);
+       }
+       else
+       {       /* IKEv1 encodes multiple proposals in a single substructure
+                * TODO-IKEv1: Encode ESP+AH proposals in two different substructs */
+               proposal_substructure_t *substruct;
+
+               substruct = proposal_substructure_create_from_proposals(proposals);
+               substruct->set_is_last_proposal(substruct, TRUE);
+               this->proposals->insert_last(this->proposals, substruct);
+               compute_length(this);
        }
-       enumerator->destroy(enumerator);
-
        return &this->public;
 }