Implemented encoding of additional IKEv1 proposal attributes
authorMartin Willi <martin@revosec.ch>
Thu, 24 Nov 2011 11:52:11 +0000 (12:52 +0100)
committerMartin Willi <martin@revosec.ch>
Tue, 20 Mar 2012 16:30:53 +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
src/libcharon/encoding/payloads/transform_attribute.c
src/libcharon/encoding/payloads/transform_attribute.h

index 924f5cb..11d684f 100644 (file)
@@ -573,6 +573,41 @@ static u_int16_t get_ikev1_from_alg(transform_type_t type, u_int16_t value)
 }
 
 /**
+ * Get IKEv1 authentication attribute from auth_method_t
+ */
+static u_int16_t get_ikev1_auth(auth_method_t method)
+{
+       switch (method)
+       {
+               case AUTH_RSA:
+                       return IKEV1_AUTH_RSA_SIG;
+               case AUTH_DSS:
+                       return IKEV1_AUTH_DSS_SIG;
+               default:
+                       /* TODO-IKEv1: Handle XAUTH methods */
+                       /* TODO-IKEv1: Handle ECDSA methods */
+               case AUTH_PSK:
+                       return IKEV1_AUTH_PSK;
+       }
+}
+
+/**
+ * Get IKEv1 encapsulation mode
+ */
+static u_int16_t get_ikev1_mode(ipsec_mode_t mode, bool udp)
+{
+       switch (mode)
+       {
+               case MODE_TUNNEL:
+                       return udp ? IKEV1_ENCAP_UDP_TUNNEL : IKEV1_ENCAP_TUNNEL;
+               case MODE_TRANSPORT:
+                       return udp ? IKEV1_ENCAP_UDP_TRANSPORT : IKEV1_ENCAP_TRANSPORT;
+               default:
+                       return IKEV1_ENCAP_TUNNEL;
+       }
+}
+
+/**
  * Add an IKE transform to a proposal for IKEv1
  */
 static void add_to_proposal_v1_ike(proposal_t *proposal,
@@ -771,7 +806,8 @@ 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, int number)
+                                                                        proposal_t *proposal, u_int32_t lifetime,
+                                                                        auth_method_t method, int number)
 {
        transform_substructure_t *transform;
        u_int16_t alg, key_size;
@@ -822,23 +858,15 @@ static void set_from_proposal_v1_ike(private_proposal_substructure_t *this,
        }
        enumerator->destroy(enumerator);
 
-       /* TODO-IKEv1: Add lifetime, non-fixed auth-method and other attributes */
-       if(1) /* TODO-IKEv1: Change to 0 if XAUTH is desired. */
-       {
        transform->add_transform_attribute(transform,
                transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
-                                                       TATTR_PH1_AUTH_METHOD, IKEV1_AUTH_PSK));
-       }else{
-       transform->add_transform_attribute(transform,
-               transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
-                                                       TATTR_PH1_AUTH_METHOD, IKEV1_AUTH_XAUTH_INIT_PSK));
-       }
+                                                       TATTR_PH1_AUTH_METHOD, get_ikev1_auth(method)));
        transform->add_transform_attribute(transform,
                transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
                                                        TATTR_PH1_LIFE_TYPE, IKEV1_LIFE_TYPE_SECONDS));
        transform->add_transform_attribute(transform,
                transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
-                                                       TATTR_PH1_LIFE_DURATION, 10800));
+                                                       TATTR_PH1_LIFE_DURATION, lifetime));
 
        add_transform_substructure(this, transform);
 }
@@ -847,7 +875,8 @@ 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, int number)
+                               proposal_t *proposal, u_int32_t lifetime, u_int64_t lifebytes,
+                               ipsec_mode_t mode, bool udp, int number)
 {
        transform_substructure_t *transform = NULL;
        u_int16_t alg, key_size;
@@ -884,16 +913,27 @@ static void set_from_proposal_v1_esp(private_proposal_substructure_t *this,
        }
        enumerator->destroy(enumerator);
 
-       /* TODO-IKEv1: Add lifetime and other attributes, ESN */
-       transform->add_transform_attribute(transform,
-               transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
-                                                       TATTR_PH2_ENCAP_MODE, IKEV1_ENCAP_TUNNEL));
        transform->add_transform_attribute(transform,
                transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+                                                       TATTR_PH2_ENCAP_MODE, get_ikev1_mode(mode, udp)));
+       if (lifetime)
+       {
+               transform->add_transform_attribute(transform,
+                       transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
                                                        TATTR_PH2_SA_LIFE_TYPE, IKEV1_LIFE_TYPE_SECONDS));
-       transform->add_transform_attribute(transform,
-               transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
-                                                       TATTR_PH2_SA_LIFE_DURATION, 3600));
+               transform->add_transform_attribute(transform,
+                       transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+                                                       TATTR_PH2_SA_LIFE_DURATION, lifetime));
+       }
+       else if (lifebytes)
+       {
+               transform->add_transform_attribute(transform,
+                       transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+                                                       TATTR_PH2_SA_LIFE_TYPE, IKEV1_LIFE_TYPE_KILOBYTES));
+               transform->add_transform_attribute(transform,
+                       transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+                                                       TATTR_PH2_SA_LIFE_DURATION, lifebytes / 1000));
+       }
 
        add_transform_substructure(this, transform);
 }
@@ -965,36 +1005,14 @@ static void set_from_proposal_v2(private_proposal_substructure_t *this,
        enumerator->destroy(enumerator);
 }
 
-/*
- * Described in header.
+/**
+ * Set SPI and other data from proposal, compute length
  */
-proposal_substructure_t *proposal_substructure_create_from_proposal(
-                                                                       payload_type_t type, proposal_t *proposal)
+static void set_data(private_proposal_substructure_t *this, proposal_t *proposal)
 {
-       private_proposal_substructure_t *this;
        u_int64_t spi64;
        u_int32_t spi32;
 
-       this = (private_proposal_substructure_t*)proposal_substructure_create(type);
-
-       if (type == PROPOSAL_SUBSTRUCTURE)
-       {
-               set_from_proposal_v2(this, proposal);
-       }
-       else
-       {
-               switch (proposal->get_protocol(proposal))
-               {
-                       case PROTO_IKE:
-                               set_from_proposal_v1_ike(this, proposal, 0);
-                               break;
-                       case PROTO_ESP:
-                               set_from_proposal_v1_esp(this, proposal, 0);
-                               break;
-                       default:
-                               break;
-               }
-       }
        /* add SPI, if necessary */
        switch (proposal->get_protocol(proposal))
        {
@@ -1018,6 +1036,48 @@ proposal_substructure_t *proposal_substructure_create_from_proposal(
        this->proposal_number = proposal->get_number(proposal);
        this->protocol_id = proposal->get_protocol(proposal);
        compute_length(this);
+}
+
+/*
+ * Described in header.
+ */
+proposal_substructure_t *proposal_substructure_create_from_proposal_v2(
+                                                                                                               proposal_t *proposal)
+{
+       private_proposal_substructure_t *this;
+
+       this = (private_proposal_substructure_t*)
+                                                       proposal_substructure_create(SECURITY_ASSOCIATION);
+       set_from_proposal_v2(this, proposal);
+       set_data(this, proposal);
+
+       return &this->public;
+}
+
+/**
+ * See header.
+ */
+proposal_substructure_t *proposal_substructure_create_from_proposal_v1(
+                       proposal_t *proposal,  u_int32_t lifetime, u_int64_t lifebytes,
+                       auth_method_t auth, ipsec_mode_t mode, bool udp)
+{
+       private_proposal_substructure_t *this;
+
+       this = (private_proposal_substructure_t*)
+                                               proposal_substructure_create(PROPOSAL_SUBSTRUCTURE_V1);
+       switch (proposal->get_protocol(proposal))
+       {
+               case PROTO_IKE:
+                       set_from_proposal_v1_ike(this, proposal, lifetime, auth, 0);
+                       break;
+               case PROTO_ESP:
+                       set_from_proposal_v1_esp(this, proposal, lifetime,
+                                                                        lifebytes, mode, udp, 0);
+                       break;
+               default:
+                       break;
+       }
+       set_data(this, proposal);
 
        return &this->public;
 }
@@ -1025,8 +1085,9 @@ proposal_substructure_t *proposal_substructure_create_from_proposal(
 /**
  * See header.
  */
-proposal_substructure_t *proposal_substructure_create_from_proposals(
-                                                                                                       linked_list_t *proposals)
+proposal_substructure_t *proposal_substructure_create_from_proposals_v1(
+                       linked_list_t *proposals, u_int32_t lifetime, u_int64_t lifebytes,
+                       auth_method_t auth, ipsec_mode_t mode, bool udp)
 {
        private_proposal_substructure_t *this = NULL;
        enumerator_t *enumerator;
@@ -1039,18 +1100,20 @@ proposal_substructure_t *proposal_substructure_create_from_proposals(
                if (!this)
                {
                        this = (private_proposal_substructure_t*)
-                                               proposal_substructure_create_from_proposal(
-                                                                               PROPOSAL_SUBSTRUCTURE_V1, proposal);
+                                               proposal_substructure_create_from_proposal_v1(
+                                                               proposal, lifetime, lifebytes, auth, mode, udp);
                }
                else
                {
                        switch (proposal->get_protocol(proposal))
                        {
                                case PROTO_IKE:
-                                       set_from_proposal_v1_ike(this, proposal, ++number);
+                                       set_from_proposal_v1_ike(this, proposal, lifetime,
+                                                                                        auth, ++number);
                                        break;
                                case PROTO_ESP:
-                                       set_from_proposal_v1_esp(this, proposal, ++number);
+                                       set_from_proposal_v1_esp(this, proposal, lifetime,
+                                                                                        lifebytes, mode, udp, ++number);
                                        break;
                                default:
                                        break;
index 496a352..de06f91 100644 (file)
@@ -29,6 +29,8 @@ typedef struct proposal_substructure_t proposal_substructure_t;
 #include <encoding/payloads/transform_substructure.h>
 #include <config/proposal.h>
 #include <utils/linked_list.h>
+#include <kernel/kernel_ipsec.h>
+#include <sa/authenticators/authenticator.h>
 
 /**
  * Class representing an IKEv1/IKEv2 proposal substructure.
@@ -124,22 +126,43 @@ struct proposal_substructure_t {
 proposal_substructure_t *proposal_substructure_create(payload_type_t type);
 
 /**
- * Creates a proposal_substructure_t from a proposal_t.
+ * Creates an IKEv2 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
+ * @return                     proposal_substructure_t PROPOSAL_SUBSTRUCTURE
  */
-proposal_substructure_t *proposal_substructure_create_from_proposal(
-                                                                       payload_type_t type, proposal_t *proposal);
-
+proposal_substructure_t *proposal_substructure_create_from_proposal_v2(
+                                                                                                               proposal_t *proposal);
 /**
- * Creates a proposal_substructure_t from a list of proposal_t (IKEv1 only).
+ * Creates an IKEv1 proposal_substructure_t from a proposal_t.
  *
  * @param proposal     proposal to build a substruct out of it
+ * @param lifetime     lifetime in seconds
+ * @param lifebytes    lifebytes, in bytes
+ * @param auth         authentication method to use, or AUTH_NONE
+ * @param mode         IPsec encapsulation mode, TRANSPORT or TUNNEL
+ * @param udp          TRUE to use UDP encapsulation
+ *
+ *
+ * @return                     proposal_substructure_t object PROPOSAL_SUBSTRUCTURE_V1
+ */
+proposal_substructure_t *proposal_substructure_create_from_proposal_v1(
+                       proposal_t *proposal,  u_int32_t lifetime, u_int64_t lifebytes,
+                       auth_method_t auth, ipsec_mode_t mode, bool udp);
+
+/**
+ * Creates an IKEv1 proposal_substructure_t from a list of proposal_t.
+ *
+ * @param proposals    list of proposal_t to encode in a substructure
+ * @param lifetime     lifetime in seconds
+ * @param lifebytes    lifebytes, in bytes
+ * @param auth         authentication method to use, or AUTH_NONE
+ * @param mode         IPsec encapsulation mode, TRANSPORT or TUNNEL
+ * @param udp          TRUE to use UDP encapsulation
  * @return                     IKEv1 proposal_substructure_t PROPOSAL_SUBSTRUCTURE_V1
  */
-proposal_substructure_t *proposal_substructure_create_from_proposals(
-                                                                       linked_list_t *proposals);
+proposal_substructure_t *proposal_substructure_create_from_proposals_v1(
+                       linked_list_t *proposals, u_int32_t lifetime, u_int64_t lifebytes,
+                       auth_method_t auth, ipsec_mode_t mode, bool udp);
 
 #endif /** PROPOSAL_SUBSTRUCTURE_H_ @}*/
index 385517b..5f739c9 100644 (file)
@@ -259,17 +259,12 @@ METHOD(payload_t, get_length, size_t,
 /**
  * Create a transform substructure from a proposal, add to payload
  */
-static void add_proposal(private_sa_payload_t *this, proposal_t *proposal)
+static void add_proposal_v2(private_sa_payload_t *this, proposal_t *proposal)
 {
        proposal_substructure_t *substruct, *last;
-       payload_type_t subtype = PROPOSAL_SUBSTRUCTURE;
        u_int count;
 
-       if (this->type == SECURITY_ASSOCIATION_V1)
-       {
-               subtype = PROPOSAL_SUBSTRUCTURE_V1;
-       }
-       substruct = proposal_substructure_create_from_proposal(subtype, proposal);
+       substruct = proposal_substructure_create_from_proposal_v2(proposal);
        count = this->proposals->get_count(this->proposals);
        if (count > 0)
        {
@@ -417,53 +412,6 @@ sa_payload_t *sa_payload_create(payload_type_t type)
 /*
  * Described in header.
  */
-sa_payload_t *sa_payload_create_from_proposal_list(payload_type_t type,
-                                                                                                  linked_list_t *proposals)
-{
-       private_sa_payload_t *this;
-       enumerator_t *enumerator;
-       proposal_t *proposal;
-
-       this = (private_sa_payload_t*)sa_payload_create(type);
-       if (type == SECURITY_ASSOCIATION)
-       {
-               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);
-       }
-       return &this->public;
-}
-
-/*
- * Described in header.
- */
-sa_payload_t *sa_payload_create_from_proposal(payload_type_t type,
-                                                                                         proposal_t *proposal)
-{
-       private_sa_payload_t *this;
-
-       this = (private_sa_payload_t*)sa_payload_create(type);
-       add_proposal(this, proposal);
-
-       return &this->public;
-}
-
-/*
- * Described in header.
- */
 sa_payload_t *sa_payload_create_from_proposals_v2(linked_list_t *proposals)
 {
        private_sa_payload_t *this;
@@ -474,7 +422,7 @@ sa_payload_t *sa_payload_create_from_proposals_v2(linked_list_t *proposals)
        enumerator = proposals->create_enumerator(proposals);
        while (enumerator->enumerate(enumerator, &proposal))
        {
-               add_proposal(this, proposal);
+               add_proposal_v2(this, proposal);
        }
        enumerator->destroy(enumerator);
 
@@ -489,7 +437,7 @@ sa_payload_t *sa_payload_create_from_proposal_v2(proposal_t *proposal)
        private_sa_payload_t *this;
 
        this = (private_sa_payload_t*)sa_payload_create(SECURITY_ASSOCIATION);
-       add_proposal(this, proposal);
+       add_proposal_v2(this, proposal);
 
        return &this->public;
 
@@ -505,11 +453,12 @@ sa_payload_t *sa_payload_create_from_proposals_v1(linked_list_t *proposals,
        proposal_substructure_t *substruct;
        private_sa_payload_t *this;
 
-       this = (private_sa_payload_t*)sa_payload_create(SECURITY_ASSOCIATION);
+       this = (private_sa_payload_t*)sa_payload_create(SECURITY_ASSOCIATION_V1);
 
        /* IKEv1 encodes multiple proposals in a single substructure
         * TODO-IKEv1: Encode ESP+AH proposals in two different substructs */
-       substruct = proposal_substructure_create_from_proposals(proposals);
+       substruct = proposal_substructure_create_from_proposals_v1(proposals,
+                                                                               lifetime, lifebytes, auth, mode, udp);
        substruct->set_is_last_proposal(substruct, TRUE);
        this->proposals->insert_last(this->proposals, substruct);
        compute_length(this);
@@ -529,8 +478,8 @@ sa_payload_t *sa_payload_create_from_proposal_v1(proposal_t *proposal,
 
        this = (private_sa_payload_t*)sa_payload_create(SECURITY_ASSOCIATION_V1);
 
-       substruct = proposal_substructure_create_from_proposal(
-                                                                                       PROPOSAL_SUBSTRUCTURE_V1, proposal);
+       substruct = proposal_substructure_create_from_proposal_v1(proposal,
+                                                                               lifetime, lifebytes, auth, mode, udp);
        substruct->set_is_last_proposal(substruct, TRUE);
        this->proposals->insert_last(this->proposals, substruct);
        compute_length(this);
index 474362f..7e8a9c7 100644 (file)
@@ -290,13 +290,28 @@ transform_attribute_t *transform_attribute_create(payload_type_t type)
  * Described in header.
  */
 transform_attribute_t *transform_attribute_create_value(payload_type_t type,
-                                                       transform_attribute_type_t kind, u_int16_t value)
+                                                       transform_attribute_type_t kind, u_int64_t value)
 {
        transform_attribute_t *attribute;
 
        attribute = transform_attribute_create(type);
        attribute->set_attribute_type(attribute, kind);
-       attribute->set_value(attribute, value);
 
+       if (value <= UINT16_MAX)
+       {
+               attribute->set_value(attribute, value);
+       }
+       else if (value <= UINT32_MAX)
+       {
+               u_int32_t val32;
+
+               val32 = htonl(value);
+               attribute->set_value_chunk(attribute, chunk_from_thing(val32));
+       }
+       else
+       {
+               value = htobe64(value);
+               attribute->set_value_chunk(attribute, chunk_from_thing(value));
+       }
        return attribute;
 }
index eedb3be..52e5d84 100644 (file)
@@ -163,7 +163,7 @@ struct transform_attribute_t {
 transform_attribute_t *transform_attribute_create(payload_type_t type);
 
 /**
- * Creates a two byte value attribute for a given attribute kind.
+ * Creates a two byte value or a larger attribute for a given attribute kind.
  *
  * @param type                 TRANSFORM_ATTRIBUTE or TRANSFORM_ATTRIBUTE_V1
  * @param kind                 attribute kind
@@ -171,6 +171,6 @@ transform_attribute_t *transform_attribute_create(payload_type_t type);
  * @return                             transform_attribute_t object
  */
 transform_attribute_t *transform_attribute_create_value(payload_type_t type,
-                                                       transform_attribute_type_t kind, u_int16_t value);
+                                                       transform_attribute_type_t kind, u_int64_t value);
 
 #endif /** TRANSFORM_ATTRIBUTE_H_ @}*/