traffic-selector-substructure: Add support for TS_SECLABEL

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.
This commit is contained in:
Tobias Brunner
2022-04-14 18:42:01 +02:00
parent d71d181d28
commit a44de0b957
2 changed files with 189 additions and 137 deletions
@@ -14,11 +14,33 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details. * 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 "traffic_selector_substructure.h"
#include <encoding/payloads/encodings.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; 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; uint16_t payload_length;
/** /**
* Start port number. * Port/address range or security label.
*/ */
uint16_t start_port; chunk_t ts_data;
/**
* End port number.
*/
uint16_t end_port;
/**
* Starting address.
*/
chunk_t starting_address;
/**
* Ending address.
*/
chunk_t ending_address;
}; };
/** /**
* 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 * The defined offsets are the positions in a object of type
* private_traffic_selector_substructure_t. * private_traffic_selector_substructure_t.
*/ */
static encoding_rule_t encodings[] = { static encoding_rule_t encodings[] = {
/* 1 Byte next ts type*/ /* 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*/ /* 1 Byte IP protocol id*/
{ U_INT_8, offsetof(private_traffic_selector_substructure_t, ip_protocol_id) }, { U_INT_8, offsetof(private_traffic_selector_substructure_t, ip_protocol_id) },
/* Length of the whole payload*/ /* Length of the whole payload*/
{ PAYLOAD_LENGTH,offsetof(private_traffic_selector_substructure_t, payload_length) }, { PAYLOAD_LENGTH,offsetof(private_traffic_selector_substructure_t, payload_length) },
/* 2 Byte start port*/ /* traffic selector data, length is defined in PAYLOAD_LENGTH */
{ U_INT_16, offsetof(private_traffic_selector_substructure_t, start_port) }, { CHUNK_DATA, offsetof(private_traffic_selector_substructure_t, ts_data) },
/* 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) }
}; };
/* /* Regular traffic selectors for address ranges:
1 2 3 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 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* ~ ~ 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* ~
| |
+---------------------------------------------------------------+
*/ */
/**
* 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)
{
bio_reader_t *reader;
int addr_len;
switch (this->ts_type)
{
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, METHOD(payload_t, verify, status_t,
private_traffic_selector_substructure_t *this) private_traffic_selector_substructure_t *this)
{ {
if (this->start_port > this->end_port)
{
/* OPAQUE ports are the only exception */
if (this->start_port != 0xffff && this->end_port != 0)
{
return FAILED;
}
}
switch (this->ts_type) switch (this->ts_type)
{ {
case TS_IPV4_ADDR_RANGE: case TS_IPV4_ADDR_RANGE:
{
if ((this->starting_address.len != 4) ||
(this->ending_address.len != 4))
{
/* ipv4 address must be 4 bytes long */
return FAILED;
}
break;
}
case TS_IPV6_ADDR_RANGE: case TS_IPV6_ADDR_RANGE:
{ {
if ((this->starting_address.len != 16) || uint16_t start_port, end_port;
(this->ending_address.len != 16)) chunk_t start_addr, end_addr;
if (!parse_ts_data(this, &start_port, &end_port, &start_addr,
&end_addr))
{ {
/* ipv6 address must be 16 bytes long */
return FAILED; return FAILED;
} }
if (start_port > end_port)
{
/* OPAQUE ports are the only exception */
if (start_port != 0xffff && end_port != 0)
{
return FAILED;
}
}
break; break;
} }
case TS_SECLABEL:
if (!this->ts_data.len)
{
return FAILED;
}
break;
default: default:
{ /* unsupported TS type, just ignored later */
/* not supported ts type */ break;
return FAILED;
}
} }
return SUCCESS; return SUCCESS;
} }
@@ -162,7 +209,7 @@ METHOD(payload_t, get_encoding_rules, int,
METHOD(payload_t, get_header_length, int, METHOD(payload_t, get_header_length, int,
private_traffic_selector_substructure_t *this) private_traffic_selector_substructure_t *this)
{ {
return 8; return 4;
} }
METHOD(payload_t, get_type, payload_type_t, 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*, METHOD(traffic_selector_substructure_t, get_traffic_selector, traffic_selector_t*,
private_traffic_selector_substructure_t *this) 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( return traffic_selector_create_from_bytes(
this->ip_protocol_id, this->ts_type, this->ip_protocol_id, this->ts_type,
this->starting_address, this->start_port, start_addr, start_port, end_addr, end_port);
this->ending_address, this->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, METHOD2(payload_t, traffic_selector_substructure_t, destroy, void,
private_traffic_selector_substructure_t *this) private_traffic_selector_substructure_t *this)
{ {
free(this->starting_address.ptr); free(this->ts_data.ptr);
free(this->ending_address.ptr);
free(this); free(this);
} }
@@ -225,6 +287,7 @@ traffic_selector_substructure_t *traffic_selector_substructure_create()
.destroy = _destroy, .destroy = _destroy,
}, },
.get_traffic_selector = _get_traffic_selector, .get_traffic_selector = _get_traffic_selector,
.get_sec_label = _get_sec_label,
.destroy = _destroy, .destroy = _destroy,
}, },
.payload_length = get_header_length(this), .payload_length = get_header_length(this),
@@ -241,16 +304,34 @@ traffic_selector_substructure_t *traffic_selector_substructure_create_from_traff
traffic_selector_t *ts) traffic_selector_t *ts)
{ {
private_traffic_selector_substructure_t *this; private_traffic_selector_substructure_t *this;
bio_writer_t *writer;
this = (private_traffic_selector_substructure_t*)traffic_selector_substructure_create(); this = (private_traffic_selector_substructure_t*)traffic_selector_substructure_create();
this->ts_type = ts->get_type(ts); this->ts_type = ts->get_type(ts);
this->ip_protocol_id = ts->get_protocol(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; return &this->public;
} }
@@ -13,6 +13,27 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details. * 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 * @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 <library.h>
#include <networking/host.h> #include <networking/host.h>
#include <selectors/traffic_selector.h> #include <selectors/traffic_selector.h>
#include <selectors/sec_label.h>
#include <encoding/payloads/payload.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. * The TRAFFIC SELECTOR format is described in RFC section 3.13.1.
*/ */
struct traffic_selector_substructure_t { struct traffic_selector_substructure_t {
/** /**
* The payload_t interface. * The payload_t interface.
*/ */
payload_t payload_interface; payload_t payload_interface;
/** /**
* Get the type of Traffic selector. * Get a traffic_selector_t from this substructure if possible.
* *
* @return type of traffic selector * @warning the returned object must be destroyed after use
* *
* @return contained traffic_selector_t (NULL if type mismatch)
*/ */
ts_type_t (*get_ts_type) (traffic_selector_substructure_t *this); traffic_selector_t *(*get_traffic_selector)(traffic_selector_substructure_t *this);
/** /**
* Set the type of Traffic selector. * Get a sec_label_t from this substructure if possible.
* *
* @param ts_type type of traffic selector * @warning the returned object must be destroyed after use
*
* @return contained sec_label_t (NULL if type mismatch)
*/ */
void (*set_ts_type) (traffic_selector_substructure_t *this, sec_label_t *(*get_sec_label)(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
*
*/
host_t *(*get_end_host) (traffic_selector_substructure_t *this);
/**
* Set the end port and address as host_t object.
*
* @param end_host end host as host_t object
*/
void (*set_end_host) (traffic_selector_substructure_t *this,
host_t *end_host);
/**
* Get a traffic_selector_t from this substructure.
*
* @warning traffic_selector_t must be destroyed after usage.
*
* @return contained traffic_selector_t
*/
traffic_selector_t *(*get_traffic_selector) (
traffic_selector_substructure_t *this);
/** /**
* Destroys an traffic_selector_substructure_t object. * 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); traffic_selector_substructure_t *traffic_selector_substructure_create(void);
/** /**
* Creates an initialized traffic selector substructure using * Creates a traffic selector substructure based on a traffic_selector_t.
* the values from 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 * @return traffic_selector_substructure_t object
*/ */
traffic_selector_substructure_t *traffic_selector_substructure_create_from_traffic_selector( traffic_selector_substructure_t *traffic_selector_substructure_create_from_traffic_selector(
traffic_selector_t *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_ @}*/ #endif /** TRAFFIC_SELECTOR_SUBSTRUCTURE_H_ @}*/