Added support for IKEv1 IPComp proposals in proposal substructure.
authorTobias Brunner <tobias@strongswan.org>
Wed, 23 May 2012 16:44:48 +0000 (18:44 +0200)
committerTobias Brunner <tobias@strongswan.org>
Thu, 24 May 2012 13:32:27 +0000 (15:32 +0200)
src/libcharon/config/proposal.c
src/libcharon/config/proposal.h
src/libcharon/encoding/payloads/proposal_substructure.c
src/libcharon/encoding/payloads/proposal_substructure.h

index d3c60a4..edba0f7 100644 (file)
 #include <crypto/signers/signer.h>
 #include <crypto/proposal/proposal_keywords.h>
 
-ENUM(protocol_id_names, PROTO_NONE, PROTO_ESP,
+ENUM(protocol_id_names, PROTO_NONE, PROTO_IPCOMP,
        "PROTO_NONE",
        "IKE",
        "AH",
        "ESP",
+       "IPCOMP",
 );
 
 typedef struct private_proposal_t private_proposal_t;
index 8f54d7e..fc93933 100644 (file)
@@ -43,6 +43,7 @@ enum protocol_id_t {
        PROTO_IKE = 1,
        PROTO_AH = 2,
        PROTO_ESP = 3,
+       PROTO_IPCOMP = 4, /* IKEv1 only */
 };
 
 /**
index 64422ff..ba71820 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2012 Tobias Brunner
  * Copyright (C) 2005-2010 Martin Willi
  * Copyright (C) 2005 Jan Hutter
  * Hochschule fuer Technik Rapperswil
@@ -292,6 +293,15 @@ typedef enum {
        IKEV1_AUTH_HYBRID_RESP_DSS = 64224,
 } ikev1_auth_method_t;
 
+/**
+ * IKEv1 IPComp transform IDs
+ */
+typedef enum {
+       IKEV1_IPCOMP_OUI = 1,
+       IKEV1_IPCOMP_DEFLATE = 2,
+       IKEV1_IPCOMP_LZS = 3,
+} ikev1_ipcomp_transform_t;
+
 METHOD(payload_t, verify, status_t,
        private_proposal_substructure_t *this)
 {
@@ -314,12 +324,19 @@ METHOD(payload_t, verify, status_t,
 
        switch (this->protocol_id)
        {
+               case PROTO_IPCOMP:
+                       if (this->spi.len != 2)
+                       {
+                               DBG1(DBG_ENC, "invalid CPI length in IPCOMP proposal");
+                               return FAILED;
+                       }
+                       break;
                case PROTO_AH:
                case PROTO_ESP:
                        if (this->spi.len != 4)
                        {
                                DBG1(DBG_ENC, "invalid SPI length in %N proposal",
-                                                                 protocol_id_names, this->protocol_id);
+                                        protocol_id_names, this->protocol_id);
                                return FAILED;
                        }
                        break;
@@ -472,6 +489,35 @@ METHOD(proposal_substructure_t, get_spi, chunk_t,
        return this->spi;
 }
 
+METHOD(proposal_substructure_t, get_cpi, bool,
+       private_proposal_substructure_t *this, u_int16_t *cpi)
+{
+
+       transform_substructure_t *transform;
+       enumerator_t *enumerator;
+
+       if (this->protocol_id != PROTO_IPCOMP)
+       {
+               return FALSE;
+       }
+
+       enumerator = this->transforms->create_enumerator(this->transforms);
+       while (enumerator->enumerate(enumerator, &transform))
+       {
+               if (transform->get_transform_id(transform) == IKEV1_IPCOMP_DEFLATE)
+               {
+                       if (cpi)
+                       {
+                               *cpi = *((u_int16_t*)this->spi.ptr);
+                       }
+                       enumerator->destroy(enumerator);
+                       return TRUE;
+               }
+       }
+       enumerator->destroy(enumerator);
+       return FALSE;
+}
+
 /**
  * Add a transform to a proposal for IKEv2
  */
@@ -1115,6 +1161,7 @@ proposal_substructure_t *proposal_substructure_create(payload_type_t type)
                        .create_substructure_enumerator = _create_substructure_enumerator,
                        .set_spi = _set_spi,
                        .get_spi = _get_spi,
+                       .get_cpi = _get_cpi,
                        .get_lifetime = _get_lifetime,
                        .get_lifebytes = _get_lifebytes,
                        .get_auth_method = _get_auth_method,
@@ -1466,3 +1513,52 @@ proposal_substructure_t *proposal_substructure_create_from_proposals_v1(
 
        return &this->public;
 }
+
+/**
+ * See header.
+ */
+proposal_substructure_t *proposal_substructure_create_for_ipcomp_v1(
+                       u_int32_t lifetime, u_int64_t lifebytes, u_int16_t cpi,
+                       u_int8_t proposal_number)
+{
+       private_proposal_substructure_t *this;
+       transform_substructure_t *transform;
+
+
+       this = (private_proposal_substructure_t*)
+                                               proposal_substructure_create(PROPOSAL_SUBSTRUCTURE_V1);
+
+       /* we currently support DEFLATE only */
+       transform = transform_substructure_create_type(TRANSFORM_SUBSTRUCTURE_V1,
+                                                                                                  1, IKEV1_IPCOMP_DEFLATE);
+
+       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, lifetime));
+       }
+       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);
+
+       this->spi = chunk_clone(chunk_from_thing(cpi));
+       this->spi_size = this->spi.len;
+       this->protocol_id = PROTO_IPCOMP;
+       this->proposal_number = proposal_number;
+
+       compute_length(this);
+
+       return &this->public;
+}
\ No newline at end of file
index aefdf2f..720f979 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2012 Tobias Brunner
  * Copyright (C) 2005-2006 Martin Willi
  * Copyright (C) 2005 Jan Hutter
  * Hochschule fuer Technik Rapperswil
@@ -52,7 +53,7 @@ struct proposal_substructure_t {
        /**
         * get proposal number of current proposal.
         *
-        * @return                      proposal number of current proposal substructure.
+        * @return                      proposal number of current proposal substructure.
         */
        u_int8_t (*get_proposal_number) (proposal_substructure_t *this);
 
@@ -67,7 +68,7 @@ struct proposal_substructure_t {
        /**
         * get protocol id of current proposal.
         *
-        * @return                      protocol id of current proposal substructure.
+        * @return                      protocol id of current proposal substructure.
         */
        u_int8_t (*get_protocol_id) (proposal_substructure_t *this);
 
@@ -84,7 +85,7 @@ struct proposal_substructure_t {
        /**
         * Returns the currently set SPI of this proposal.
         *
-        * @return                      chunk_t pointing to the value
+        * @return                      chunk_t pointing to the value
         */
        chunk_t (*get_spi) (proposal_substructure_t *this);
 
@@ -98,6 +99,14 @@ struct proposal_substructure_t {
        void (*set_spi) (proposal_substructure_t *this, chunk_t spi);
 
        /**
+        * Gets the CPI of the current proposal (IKEv1 only).
+        *
+        * @param cpi           the CPI if a supported algorithm is proposed
+        * @return                      TRUE if a supported algorithm is proposed
+        */
+       bool (*get_cpi) (proposal_substructure_t *this, u_int16_t *cpi);
+
+       /**
         * Get proposals contained in a propsal_substructure_t.
         *
         * @param list          list to add created proposals to
@@ -158,7 +167,7 @@ proposal_substructure_t *proposal_substructure_create(payload_type_t type);
  * Creates an IKEv2 proposal_substructure_t from a proposal_t.
  *
  * @param proposal     proposal to build a substruct out of it
- * @return                     proposal_substructure_t PROPOSAL_SUBSTRUCTURE
+ * @return                     proposal_substructure_t PROPOSAL_SUBSTRUCTURE
  */
 proposal_substructure_t *proposal_substructure_create_from_proposal_v2(
                                                                                                                proposal_t *proposal);
@@ -171,9 +180,7 @@ proposal_substructure_t *proposal_substructure_create_from_proposal_v2(
  * @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
+ * @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,
@@ -188,10 +195,24 @@ proposal_substructure_t *proposal_substructure_create_from_proposal_v1(
  * @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
+ * @return                     IKEv1 proposal_substructure_t PROPOSAL_SUBSTRUCTURE_V1
  */
 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);
 
+/**
+ * Creates an IKEv1 proposal_substructure_t for IPComp with the given
+ * proposal_number (e.g. of a ESP proposal to bundle them).
+ *
+ * @param lifetime     lifetime in seconds
+ * @param lifebytes    lifebytes, in bytes
+ * @param cpi                          the CPI to be used
+ * @param proposal_number      the proposal number of the proposal to be linked
+ * @return                                     IKEv1 proposal_substructure_t PROPOSAL_SUBSTRUCTURE_V1
+ */
+proposal_substructure_t *proposal_substructure_create_for_ipcomp_v1(
+                       u_int32_t lifetime, u_int64_t lifebytes, u_int16_t cpi,
+                       u_int8_t proposal_number);
+
 #endif /** PROPOSAL_SUBSTRUCTURE_H_ @}*/