]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
traffic-selector-substructure: Add support for TS_SECLABEL
authorTobias Brunner <tobias@strongswan.org>
Mon, 10 Jan 2022 16:34:22 +0000 (17:34 +0100)
committerTobias Brunner <tobias@strongswan.org>
Thu, 14 Apr 2022 16:42:01 +0000 (18:42 +0200)
Changes how regular address range traffic selectors are parsed as the
IKE parser currently doesn't provide sub-type parsing.

Also removed a lot of unused method definitions.

src/libcharon/encoding/payloads/traffic_selector_substructure.c
src/libcharon/encoding/payloads/traffic_selector_substructure.h

index febf0c4106e26d096bcebb5b09bf603e03f78b6a..c4e5d2b1d7c5ce63cee3c908635a2be7564db1ff 100644 (file)
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  */
+/*
+ * Copyright (C) 2022 Tobias Brunner, codelabs GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
 
 #include "traffic_selector_substructure.h"
 
 #include <encoding/payloads/encodings.h>
-#include <collections/linked_list.h>
+#include <bio/bio_reader.h>
+#include <bio/bio_writer.h>
 
 typedef struct private_traffic_selector_substructure_t private_traffic_selector_substructure_t;
 
@@ -48,50 +70,32 @@ struct private_traffic_selector_substructure_t {
        uint16_t payload_length;
 
        /**
-        * Start port number.
-        */
-       uint16_t start_port;
-
-       /**
-        * End port number.
-        */
-       uint16_t end_port;
-
-       /**
-        * Starting address.
-        */
-       chunk_t starting_address;
-
-       /**
-        * Ending address.
+        * Port/address range or security label.
         */
-       chunk_t ending_address;
+       chunk_t ts_data;
 };
 
 /**
- * Encoding rules to parse or generate a TS payload
+ * Encoding rules to parse or generate a TS payload.
+ *
+ * Due to the generic nature of security labels, the actual structure of regular
+ * TS is not parsed with these rules.
  *
  * The defined offsets are the positions in a object of type
  * private_traffic_selector_substructure_t.
  */
 static encoding_rule_t encodings[] = {
        /* 1 Byte next ts type*/
-       { TS_TYPE,              offsetof(private_traffic_selector_substructure_t, ts_type)                      },
+       { U_INT_8,              offsetof(private_traffic_selector_substructure_t, ts_type)                      },
        /* 1 Byte IP protocol id*/
        { U_INT_8,              offsetof(private_traffic_selector_substructure_t, ip_protocol_id)       },
        /* Length of the whole payload*/
        { PAYLOAD_LENGTH,offsetof(private_traffic_selector_substructure_t, payload_length)      },
-       /* 2 Byte start port*/
-       { U_INT_16,             offsetof(private_traffic_selector_substructure_t, start_port)           },
-       /* 2 Byte end port*/
-       { U_INT_16,             offsetof(private_traffic_selector_substructure_t, end_port)                     },
-       /* starting address is either 4 or 16 byte */
-       { ADDRESS,              offsetof(private_traffic_selector_substructure_t, starting_address)     },
-       /* ending address is either 4 or 16 byte */
-       { ADDRESS,              offsetof(private_traffic_selector_substructure_t, ending_address)       }
+       /* traffic selector data, length is defined in PAYLOAD_LENGTH */
+       { CHUNK_DATA,   offsetof(private_traffic_selector_substructure_t, ts_data)                      },
 };
 
-/*
+/* Regular traffic selectors for address ranges:
                            1                   2                   3
        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -107,48 +111,91 @@ static encoding_rule_t encodings[] = {
       ~                         Ending Address*                       ~
       !                                                               !
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ * Security labels:
+                           1                   2                   3
+       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+      +---------------+---------------+-------------------------------+
+      |   TS Type     |    Reserved   |       Selector Length         |
+      +---------------+---------------+-------------------------------+
+      |                                                               |
+      ~                         Security Label*                       ~
+      |                                                               |
+      +---------------------------------------------------------------+
 */
 
-METHOD(payload_t, verify, status_t,
-       private_traffic_selector_substructure_t *this)
+/**
+ * Parse the data of a regular address range traffic selector.
+ */
+static bool parse_ts_data(private_traffic_selector_substructure_t *this,
+                                                 uint16_t *start_port, uint16_t *end_port,
+                                                 chunk_t *start_addr, chunk_t *end_addr)
 {
-       if (this->start_port > this->end_port)
+       bio_reader_t *reader;
+       int addr_len;
+
+       switch (this->ts_type)
        {
-               /* OPAQUE ports are the only exception */
-               if (this->start_port != 0xffff && this->end_port != 0)
-               {
-                       return FAILED;
-               }
+               case TS_IPV4_ADDR_RANGE:
+                       addr_len = 4;
+                       break;
+               case TS_IPV6_ADDR_RANGE:
+                       addr_len = 16;
+                       break;
+               default:
+                       return FALSE;
+       }
+
+       reader = bio_reader_create(this->ts_data);
+       if (!reader->read_uint16(reader, start_port) ||
+               !reader->read_uint16(reader, end_port) ||
+               !reader->read_data(reader, addr_len, start_addr) ||
+               !reader->read_data(reader, addr_len, end_addr) ||
+               reader->remaining(reader) > 0)
+       {
+               reader->destroy(reader);
+               return FALSE;
        }
+       reader->destroy(reader);
+       return TRUE;
+}
+
+METHOD(payload_t, verify, status_t,
+       private_traffic_selector_substructure_t *this)
+{
        switch (this->ts_type)
        {
                case TS_IPV4_ADDR_RANGE:
+               case TS_IPV6_ADDR_RANGE:
                {
-                       if ((this->starting_address.len != 4) ||
-                               (this->ending_address.len != 4))
+                       uint16_t start_port, end_port;
+                       chunk_t start_addr, end_addr;
+
+                       if (!parse_ts_data(this, &start_port, &end_port, &start_addr,
+                                                          &end_addr))
                        {
-                               /* ipv4 address must be 4 bytes long */
                                return FAILED;
                        }
+                       if (start_port > end_port)
+                       {
+                               /* OPAQUE ports are the only exception */
+                               if (start_port != 0xffff && end_port != 0)
+                               {
+                                       return FAILED;
+                               }
+                       }
                        break;
                }
-               case TS_IPV6_ADDR_RANGE:
-               {
-                       if ((this->starting_address.len != 16) ||
-                               (this->ending_address.len != 16))
+               case TS_SECLABEL:
+                       if (!this->ts_data.len)
                        {
-                               /* ipv6 address must be 16 bytes long */
                                return FAILED;
                        }
                        break;
-               }
                default:
-               {
-                       /* not supported ts type */
-                       return FAILED;
-               }
+                       /* unsupported TS type, just ignored later */
+                       break;
        }
-
        return SUCCESS;
 }
 
@@ -162,7 +209,7 @@ METHOD(payload_t, get_encoding_rules, int,
 METHOD(payload_t, get_header_length, int,
        private_traffic_selector_substructure_t *this)
 {
-       return 8;
+       return 4;
 }
 
 METHOD(payload_t, get_type, payload_type_t,
@@ -191,17 +238,32 @@ METHOD(payload_t, get_length, size_t,
 METHOD(traffic_selector_substructure_t, get_traffic_selector, traffic_selector_t*,
        private_traffic_selector_substructure_t *this)
 {
+       uint16_t start_port, end_port;
+       chunk_t start_addr, end_addr;
+
+       if (!parse_ts_data(this, &start_port, &end_port, &start_addr, &end_addr))
+       {
+               return NULL;
+       }
        return traffic_selector_create_from_bytes(
                                                                        this->ip_protocol_id, this->ts_type,
-                                                                       this->starting_address, this->start_port,
-                                                                       this->ending_address, this->end_port);
+                                                                       start_addr, start_port, end_addr, end_port);
+}
+
+METHOD(traffic_selector_substructure_t, get_sec_label, sec_label_t*,
+       private_traffic_selector_substructure_t *this)
+{
+       if (this->ts_type != TS_SECLABEL)
+       {
+               return NULL;
+       }
+       return sec_label_from_encoding(this->ts_data);
 }
 
 METHOD2(payload_t, traffic_selector_substructure_t, destroy, void,
        private_traffic_selector_substructure_t *this)
 {
-       free(this->starting_address.ptr);
-       free(this->ending_address.ptr);
+       free(this->ts_data.ptr);
        free(this);
 }
 
@@ -225,6 +287,7 @@ traffic_selector_substructure_t *traffic_selector_substructure_create()
                                .destroy = _destroy,
                        },
                        .get_traffic_selector = _get_traffic_selector,
+                       .get_sec_label = _get_sec_label,
                        .destroy = _destroy,
                },
                .payload_length = get_header_length(this),
@@ -241,16 +304,34 @@ traffic_selector_substructure_t *traffic_selector_substructure_create_from_traff
                                                                                                        traffic_selector_t *ts)
 {
        private_traffic_selector_substructure_t *this;
+       bio_writer_t *writer;
 
        this = (private_traffic_selector_substructure_t*)traffic_selector_substructure_create();
        this->ts_type = ts->get_type(ts);
        this->ip_protocol_id = ts->get_protocol(ts);
-       this->start_port = ts->get_from_port(ts);
-       this->end_port = ts->get_to_port(ts);
-       this->starting_address = chunk_clone(ts->get_from_address(ts));
-       this->ending_address = chunk_clone(ts->get_to_address(ts));
-       this->payload_length = get_header_length(this) +
-                                               this->ending_address.len + this->starting_address.len;
 
+       writer = bio_writer_create(this->ts_type == TS_IPV4_ADDR_RANGE ? 12 : 36);
+       writer->write_uint16(writer, ts->get_from_port(ts));
+       writer->write_uint16(writer, ts->get_to_port(ts));
+       writer->write_data(writer, ts->get_from_address(ts));
+       writer->write_data(writer, ts->get_to_address(ts));
+       this->ts_data = writer->extract_buf(writer);
+       this->payload_length += this->ts_data.len;
+       writer->destroy(writer);
+       return &this->public;
+}
+
+/*
+ * Described in header
+ */
+traffic_selector_substructure_t *traffic_selector_substructure_create_from_sec_label(
+                                                                                                       sec_label_t *label)
+{
+       private_traffic_selector_substructure_t *this;
+
+       this = (private_traffic_selector_substructure_t*)traffic_selector_substructure_create();
+       this->ts_type = TS_SECLABEL;
+       this->ts_data = chunk_clone(label->get_encoding(label));
+       this->payload_length += this->ts_data.len;
        return &this->public;
 }
index d9698f86f323ec8121977deacbfa8cbbc66be3a1..a22c7a9351b771689ac9337d8facb163a4fdb697 100644 (file)
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  */
+/*
+ * Copyright (C) 2022 Tobias Brunner, codelabs GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
 
 /**
  * @defgroup traffic_selector_substructure traffic_selector_substructure
@@ -27,6 +48,7 @@ typedef struct traffic_selector_substructure_t traffic_selector_substructure_t;
 #include <library.h>
 #include <networking/host.h>
 #include <selectors/traffic_selector.h>
+#include <selectors/sec_label.h>
 #include <encoding/payloads/payload.h>
 
 /**
@@ -35,88 +57,29 @@ typedef struct traffic_selector_substructure_t traffic_selector_substructure_t;
  * The TRAFFIC SELECTOR format is described in RFC section 3.13.1.
  */
 struct traffic_selector_substructure_t {
+
        /**
         * The payload_t interface.
         */
        payload_t payload_interface;
 
        /**
-        * Get the type of Traffic selector.
-        *
-        * @return                      type of traffic selector
-        *
-        */
-       ts_type_t (*get_ts_type) (traffic_selector_substructure_t *this);
-
-       /**
-        * Set the type of Traffic selector.
-        *
-        * @param ts_type       type of traffic selector
-        */
-       void (*set_ts_type) (traffic_selector_substructure_t *this,
-                                                ts_type_t ts_type);
-
-       /**
-        * Get the IP protocol ID of Traffic selector.
-        *
-        * @return                      type of traffic selector
-        *
-        */
-       uint8_t (*get_protocol_id) (traffic_selector_substructure_t *this);
-
-       /**
-        * Set the IP protocol ID of Traffic selector
-        *
-        * @param protocol_id   protocol ID of traffic selector
-        */
-       void (*set_protocol_id) (traffic_selector_substructure_t *this,
-                                                         uint8_t protocol_id);
-
-       /**
-        * Get the start port and address as host_t object.
-        *
-        * Returned host_t object has to get destroyed by the caller.
-        *
-        * @return                      start host as host_t object
-        *
-        */
-       host_t *(*get_start_host) (traffic_selector_substructure_t *this);
-
-       /**
-        * Set the start port and address as host_t object.
-        *
-        * @param start_host    start host as host_t object
-        */
-       void (*set_start_host) (traffic_selector_substructure_t *this,
-                                                       host_t *start_host);
-
-       /**
-        * Get the end port and address as host_t object.
-        *
-        * Returned host_t object has to get destroyed by the caller.
-        *
-        * @return                      end host as host_t object
+        * Get a traffic_selector_t from this substructure if possible.
         *
-        */
-       host_t *(*get_end_host) (traffic_selector_substructure_t *this);
-
-       /**
-        * Set the end port and address as host_t object.
+        * @warning the returned object must be destroyed after use
         *
-        * @param end_host      end host as host_t object
+        * @return                      contained traffic_selector_t (NULL if type mismatch)
         */
-       void (*set_end_host) (traffic_selector_substructure_t *this,
-                                                 host_t *end_host);
+       traffic_selector_t *(*get_traffic_selector)(traffic_selector_substructure_t *this);
 
        /**
-        * Get a traffic_selector_t from this substructure.
+        * Get a sec_label_t from this substructure if possible.
         *
-        * @warning traffic_selector_t must be destroyed after usage.
+        * @warning the returned object must be destroyed after use
         *
-        * @return                      contained traffic_selector_t
+        * @return                      contained sec_label_t (NULL if type mismatch)
         */
-       traffic_selector_t *(*get_traffic_selector) (
-                                                                               traffic_selector_substructure_t *this);
+       sec_label_t *(*get_sec_label)(traffic_selector_substructure_t *this);
 
        /**
         * Destroys an traffic_selector_substructure_t object.
@@ -134,13 +97,21 @@ struct traffic_selector_substructure_t {
 traffic_selector_substructure_t *traffic_selector_substructure_create(void);
 
 /**
- * Creates an initialized traffic selector substructure using
- * the values from a traffic_selector_t.
+ * Creates a traffic selector substructure based on a traffic_selector_t.
  *
- * @param traffic_selector     traffic_selector_t to use for initialization
+ * @param traffic_selector     data to use
  * @return                                     traffic_selector_substructure_t object
  */
 traffic_selector_substructure_t *traffic_selector_substructure_create_from_traffic_selector(
                                                                                traffic_selector_t *traffic_selector);
 
+/**
+ * Creates a traffic selector substructure based on a sec_label_t.
+ *
+ * @param label                                data to use
+ * @return                                     traffic_selector_substructure_t object
+ */
+traffic_selector_substructure_t *traffic_selector_substructure_create_from_sec_label(
+                                                                               sec_label_t *label);
+
 #endif /** TRAFFIC_SELECTOR_SUBSTRUCTURE_H_ @}*/