From 685579d6d870230afd2cdde90c5d95adf816b811 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 15 Nov 2013 14:54:42 +0100 Subject: unity: Send UNITY_SPLIT_INCLUDE attributes with proper padding The additional 6 bytes are not actually padding but are parsed by the Cisco client as protocol and src and dst ports (each two bytes but strangely only the first two in network order). --- src/libcharon/plugins/unity/unity_provider.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/libcharon/plugins/unity/unity_provider.c b/src/libcharon/plugins/unity/unity_provider.c index ac6f93d69..30b20349c 100644 --- a/src/libcharon/plugins/unity/unity_provider.c +++ b/src/libcharon/plugins/unity/unity_provider.c @@ -38,10 +38,15 @@ typedef struct { enumerator_t public; /** list of traffic selectors to enumerate */ linked_list_t *list; - /** currently enumerating subnet */ - u_char subnet[4]; - /** currently enumerating subnet mask */ - u_char mask[4]; + /** currently enumerating attribute data */ + struct __attribute__((packed)) { + u_char net[4]; + u_char mask[4]; + /* the Cisco client parses this as protocol, src and dst port, the first + * two in network order the last in host order - no other clients seem + * to support these fields so we don't use them either */ + u_char padding[6]; + } attr; } attribute_enumerator_t; METHOD(enumerator_t, attribute_enumerate, bool, @@ -65,23 +70,23 @@ METHOD(enumerator_t, attribute_enumerate, bool, } ts->destroy(ts); } + memcpy(this->attr.net, net->get_address(net).ptr, sizeof(this->attr.net)); + net->destroy(net); - memset(this->mask, 0, sizeof(this->mask)); - for (i = 0; i < sizeof(this->mask); i++) + memset(this->attr.mask, 0, sizeof(this->attr.mask)); + for (i = 0; i < sizeof(this->attr.mask); i++) { if (mask < 8) { - this->mask[i] = 0xFF << (8 - mask); + this->attr.mask[i] = 0xFF << (8 - mask); break; } - this->mask[i] = 0xFF; + this->attr.mask[i] = 0xFF; mask -= 8; } - memcpy(this->subnet, net->get_address(net).ptr, sizeof(this->subnet)); - net->destroy(net); *type = UNITY_SPLIT_INCLUDE; - *attr = chunk_create(this->subnet, sizeof(this->subnet) + sizeof(this->mask)); + *attr = chunk_create(this->attr.net, sizeof(this->attr)); return TRUE; } -- cgit v1.2.3 From f8262aa1a624d2dcdc79cc6e1229ab9c31189f46 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 15 Nov 2013 15:15:19 +0100 Subject: unity: Change local TS to 0.0.0.0/0 as responder Cisco clients and Shrew expect a remote TS of 0.0.0.0/0 if Unity is used, otherwise Quick Mode fails. --- src/libcharon/plugins/unity/unity_narrow.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/libcharon/plugins/unity/unity_narrow.c b/src/libcharon/plugins/unity/unity_narrow.c index edff51a08..9f72a80da 100644 --- a/src/libcharon/plugins/unity/unity_narrow.c +++ b/src/libcharon/plugins/unity/unity_narrow.c @@ -97,9 +97,9 @@ static void narrow_initiator(private_unity_narrow_t *this, ike_sa_t *ike_sa, } /** - * As initiator, bump up TS to 0.0.0.0/0 for on-the-wire bits + * As initiator and responder, bump up TS to 0.0.0.0/0 for on-the-wire bits */ -static void narrow_initiator_pre(linked_list_t *list) +static void narrow_pre(linked_list_t *list, char *side) { traffic_selector_t *ts; @@ -112,7 +112,7 @@ static void narrow_initiator_pre(linked_list_t *list) "255.255.255.255", 65535); if (ts) { - DBG2(DBG_CFG, "changing proposed traffic selectors for other:"); + DBG2(DBG_CFG, "changing proposed traffic selectors for %s:", side); DBG2(DBG_CFG, " %R", ts); list->insert_last(list, ts); } @@ -149,12 +149,15 @@ METHOD(listener_t, narrow, bool, switch (type) { case NARROW_INITIATOR_PRE_AUTH: - narrow_initiator_pre(remote); + narrow_pre(remote, "other"); break; case NARROW_INITIATOR_POST_AUTH: narrow_initiator(this, ike_sa, child_sa->get_config(child_sa), remote); break; + case NARROW_RESPONDER: + narrow_pre(local, "us"); + break; case NARROW_RESPONDER_POST: narrow_responder_post(child_sa->get_config(child_sa), local); break; -- cgit v1.2.3 From 21c18f536d97448ce5036707d421b14ba8040877 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 15 Nov 2013 16:45:59 +0100 Subject: unity: Send all traffic selectors in a single UNITY_SPLIT_INCLUDE attribute Cisco clients only handle the first such attribute. --- src/libcharon/plugins/unity/unity_provider.c | 82 ++++++++++++++++------------ 1 file changed, 47 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/libcharon/plugins/unity/unity_provider.c b/src/libcharon/plugins/unity/unity_provider.c index 30b20349c..86f81fcfb 100644 --- a/src/libcharon/plugins/unity/unity_provider.c +++ b/src/libcharon/plugins/unity/unity_provider.c @@ -1,4 +1,7 @@ /* + * Copyright (C) 2013 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * * Copyright (C) 2012 Martin Willi * Copyright (C) 2012 revosec AG * @@ -16,6 +19,7 @@ #include "unity_provider.h" #include +#include typedef struct private_unity_provider_t private_unity_provider_t; @@ -31,63 +35,70 @@ struct private_unity_provider_t { }; /** - * Attribute enumerator for traffic selector list + * Attribute enumerator for UNITY_SPLIT_INCLUDE attribute */ typedef struct { /** Implements enumerator_t */ enumerator_t public; /** list of traffic selectors to enumerate */ linked_list_t *list; - /** currently enumerating attribute data */ - struct __attribute__((packed)) { - u_char net[4]; - u_char mask[4]; - /* the Cisco client parses this as protocol, src and dst port, the first - * two in network order the last in host order - no other clients seem - * to support these fields so we don't use them either */ - u_char padding[6]; - } attr; + /** attribute value */ + chunk_t attr; } attribute_enumerator_t; +/** + * Append data from the given traffic selector to the attribute data + */ +static void append_ts(bio_writer_t *writer, traffic_selector_t *ts) +{ + host_t *net, *mask; + chunk_t padding; + u_int8_t bits; + + if (!ts->to_subnet(ts, &net, &bits)) + { + return; + } + mask = host_create_netmask(AF_INET, bits); + if (!mask) + { + net->destroy(net); + return; + } + writer->write_data(writer, net->get_address(net)); + writer->write_data(writer, mask->get_address(mask)); + /* the Cisco client parses the "padding" as protocol, src and dst port, the + * first two in network order the last in host order - no other clients seem + * to support these fields so we don't use them either */ + padding = writer->skip(writer, 6); + memset(padding.ptr, 0, padding.len); + mask->destroy(mask); + net->destroy(net); +} + METHOD(enumerator_t, attribute_enumerate, bool, attribute_enumerator_t *this, configuration_attribute_type_t *type, chunk_t *attr) { traffic_selector_t *ts; - u_int8_t i, mask; - host_t *net; + bio_writer_t *writer; - while (TRUE) + if (this->list->get_count(this->list) == 0) { - if (this->list->remove_first(this->list, (void**)&ts) != SUCCESS) - { - return FALSE; - } - if (ts->to_subnet(ts, &net, &mask)) - { - ts->destroy(ts); - break; - } - ts->destroy(ts); + return FALSE; } - memcpy(this->attr.net, net->get_address(net).ptr, sizeof(this->attr.net)); - net->destroy(net); - memset(this->attr.mask, 0, sizeof(this->attr.mask)); - for (i = 0; i < sizeof(this->attr.mask); i++) + writer = bio_writer_create(14); + while (this->list->remove_first(this->list, (void**)&ts) == SUCCESS) { - if (mask < 8) - { - this->attr.mask[i] = 0xFF << (8 - mask); - break; - } - this->attr.mask[i] = 0xFF; - mask -= 8; + append_ts(writer, ts); + ts->destroy(ts); } *type = UNITY_SPLIT_INCLUDE; - *attr = chunk_create(this->attr.net, sizeof(this->attr)); + *attr = this->attr = writer->extract_buf(writer); + writer->destroy(writer); return TRUE; } @@ -95,6 +106,7 @@ METHOD(enumerator_t, attribute_destroy, void, attribute_enumerator_t *this) { this->list->destroy_offset(this->list, offsetof(traffic_selector_t, destroy)); + chunk_free(&this->attr); free(this); } -- cgit v1.2.3