From: Tobias Brunner Date: Mon, 10 Jan 2022 16:34:22 +0000 (+0100) Subject: traffic-selector-substructure: Add support for TS_SECLABEL X-Git-Tag: 5.9.6rc1~3^2~31 X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=a44de0b9578f28919fbdde80dff3e8b9a2164827;p=thirdparty%2Fstrongswan.git 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. --- diff --git a/src/libcharon/encoding/payloads/traffic_selector_substructure.c b/src/libcharon/encoding/payloads/traffic_selector_substructure.c index febf0c4106..c4e5d2b1d7 100644 --- a/src/libcharon/encoding/payloads/traffic_selector_substructure.c +++ b/src/libcharon/encoding/payloads/traffic_selector_substructure.c @@ -14,11 +14,33 @@ * 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 -#include +#include +#include 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; } diff --git a/src/libcharon/encoding/payloads/traffic_selector_substructure.h b/src/libcharon/encoding/payloads/traffic_selector_substructure.h index d9698f86f3..a22c7a9351 100644 --- a/src/libcharon/encoding/payloads/traffic_selector_substructure.h +++ b/src/libcharon/encoding/payloads/traffic_selector_substructure.h @@ -13,6 +13,27 @@ * 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 #include #include +#include #include /** @@ -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_ @}*/