Store proposal number in proposal_t to reuse it in the selected proposal
authorMartin Willi <martin@revosec.ch>
Thu, 28 Oct 2010 12:40:54 +0000 (14:40 +0200)
committerMartin Willi <martin@revosec.ch>
Thu, 28 Oct 2010 13:08:14 +0000 (15:08 +0200)
According to RFC 5996 3.3.1, we MUST reuse the proposal number of
the selected proposal in the SA payload reply.

src/libcharon/config/proposal.c
src/libcharon/config/proposal.h
src/libcharon/encoding/payloads/proposal_substructure.c
src/libcharon/encoding/payloads/sa_payload.c
src/libcharon/plugins/ha/ha_dispatcher.c

index 6a29b41..5b82945 100644 (file)
@@ -87,6 +87,11 @@ struct private_proposal_t {
         * senders SPI
         */
        u_int64_t spi;
+
+       /**
+        * Proposal number
+        */
+       u_int number;
 };
 
 /**
@@ -311,7 +316,7 @@ METHOD(proposal_t, select_proposal, proposal_t*,
                return NULL;
        }
 
-       selected = proposal_create(this->protocol);
+       selected = proposal_create(this->protocol, other->number);
 
        /* select encryption algorithm */
        if (select_algo(this->encryption_algos, other->encryption_algos, private,
@@ -473,6 +478,12 @@ static bool algo_list_equals(linked_list_t *l1, linked_list_t *l2)
        return equals;
 }
 
+METHOD(proposal_t, get_number, u_int,
+       private_proposal_t *this)
+{
+       return this->number;
+}
+
 METHOD(proposal_t, equals, bool,
        private_proposal_t *this, proposal_t *other_pub)
 {
@@ -493,8 +504,9 @@ METHOD(proposal_t, equals, bool,
 METHOD(proposal_t, clone_, proposal_t*,
        private_proposal_t *this)
 {
-       private_proposal_t *clone = (private_proposal_t*)proposal_create(this->protocol);
+       private_proposal_t *clone;
 
+       clone = (private_proposal_t*)proposal_create(this->protocol, 0);
        clone_algo_list(this->encryption_algos, clone->encryption_algos);
        clone_algo_list(this->integrity_algos, clone->integrity_algos);
        clone_algo_list(this->prf_algos, clone->prf_algos);
@@ -502,6 +514,7 @@ METHOD(proposal_t, clone_, proposal_t*,
        clone_algo_list(this->esns, clone->esns);
 
        clone->spi = this->spi;
+       clone->number = this->number;
 
        return &clone->public;
 }
@@ -685,7 +698,7 @@ METHOD(proposal_t, destroy, void,
 /*
  * Describtion in header-file
  */
-proposal_t *proposal_create(protocol_id_t protocol)
+proposal_t *proposal_create(protocol_id_t protocol, u_int number)
 {
        private_proposal_t *this;
 
@@ -700,11 +713,13 @@ proposal_t *proposal_create(protocol_id_t protocol)
                        .get_protocol = _get_protocol,
                        .set_spi = _set_spi,
                        .get_spi = _get_spi,
+                       .get_number = _get_number,
                        .equals = _equals,
                        .clone = _clone_,
                        .destroy = _destroy,
                },
                .protocol = protocol,
+               .number = number,
                .encryption_algos = linked_list_create(),
                .integrity_algos = linked_list_create(),
                .prf_algos = linked_list_create(),
@@ -837,7 +852,7 @@ static void proposal_add_supported_ike(private_proposal_t *this)
  */
 proposal_t *proposal_create_default(protocol_id_t protocol)
 {
-       private_proposal_t *this = (private_proposal_t*)proposal_create(protocol);
+       private_proposal_t *this = (private_proposal_t*)proposal_create(protocol, 0);
 
        switch (protocol)
        {
@@ -872,7 +887,7 @@ proposal_t *proposal_create_default(protocol_id_t protocol)
  */
 proposal_t *proposal_create_from_string(protocol_id_t protocol, const char *algs)
 {
-       private_proposal_t *this = (private_proposal_t*)proposal_create(protocol);
+       private_proposal_t *this = (private_proposal_t*)proposal_create(protocol, 0);
        chunk_t string = {(void*)algs, strlen(algs)};
        chunk_t alg;
        status_t status = SUCCESS;
index 30f63b8..97af5b6 100644 (file)
@@ -161,6 +161,13 @@ struct proposal_t {
        void (*set_spi) (proposal_t *this, u_int64_t spi);
 
        /**
+        * Get the proposal number, as encoded in SA payload
+        *
+        * @return                              proposal number
+        */
+       u_int (*get_number)(proposal_t *this);
+
+       /**
         * Check for the eqality of two proposals.
         *
         * @param other                 other proposal to check for equality
@@ -185,9 +192,10 @@ struct proposal_t {
  * Create a child proposal for AH, ESP or IKE.
  *
  * @param protocol                     protocol, such as PROTO_ESP
+ * @param number                       proposal number, as encoded in SA payload
  * @return                                     proposal_t object
  */
-proposal_t *proposal_create(protocol_id_t protocol);
+proposal_t *proposal_create(protocol_id_t protocol, u_int number);
 
 /**
  * Create a default proposal if nothing further specified.
index a683d72..985b032 100644 (file)
@@ -309,7 +309,7 @@ METHOD(proposal_substructure_t, get_proposal, proposal_t*,
        proposal_t *proposal;
        u_int64_t spi;
 
-       proposal = proposal_create(this->protocol_id);
+       proposal = proposal_create(this->protocol_id, this->proposal_number);
 
        enumerator = this->transforms->create_enumerator(this->transforms);
        while (enumerator->enumerate(enumerator, &transform))
@@ -498,7 +498,7 @@ proposal_substructure_t *proposal_substructure_create_from_proposal(
                default:
                        break;
        }
-       this->proposal_number = 0;
+       this->proposal_number = proposal->get_number(proposal);
        this->protocol_id = proposal->get_protocol(proposal);
 
        return &this->public;
index 5689c80..4fbd4ca 100644 (file)
@@ -204,8 +204,15 @@ METHOD(sa_payload_t, add_proposal, void,
                last->set_is_last_proposal(last, FALSE);
        }
        substruct->set_is_last_proposal(substruct, TRUE);
-       substruct->set_proposal_number(substruct, count + 1);
-       this->proposals->insert_last(this->proposals, proposal);
+       if (proposal->get_number(proposal))
+       {       /* use the selected proposals number, if any */
+               substruct->set_proposal_number(substruct, proposal->get_number(proposal));
+       }
+       else
+       {
+               substruct->set_proposal_number(substruct, count + 1);
+       }
+       this->proposals->insert_last(this->proposals, substruct);
        compute_length(this);
 }
 
index 4f9496f..b46a221 100644 (file)
@@ -136,7 +136,7 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message
                diffie_hellman_t dh = { .get_shared_secret = get_shared_secret,
                                                                .destroy = (void*)&secret };
 
-               proposal = proposal_create(PROTO_IKE);
+               proposal = proposal_create(PROTO_IKE, 0);
                keymat = ike_sa->get_keymat(ike_sa);
                if (integ)
                {
@@ -549,7 +549,7 @@ static void process_child_add(private_ha_dispatcher_t *this,
        child_sa->set_protocol(child_sa, PROTO_ESP);
        child_sa->set_ipcomp(child_sa, ipcomp);
 
-       proposal = proposal_create(PROTO_ESP);
+       proposal = proposal_create(PROTO_ESP, 0);
        if (integ)
        {
                proposal->add_algorithm(proposal, INTEGRITY_ALGORITHM, integ, 0);