From f2463f1bd6bb8dfa25cfabfc0d2d284fc084ee00 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Tue, 24 Jul 2012 12:21:25 +0200 Subject: [PATCH] Add a Unity attribute provider that adds Split-Includes for TS --- src/libcharon/plugins/unity/Makefile.am | 3 +- src/libcharon/plugins/unity/unity_plugin.c | 11 ++ src/libcharon/plugins/unity/unity_provider.c | 170 +++++++++++++++++++ src/libcharon/plugins/unity/unity_provider.h | 49 ++++++ 4 files changed, 232 insertions(+), 1 deletion(-) create mode 100644 src/libcharon/plugins/unity/unity_provider.c create mode 100644 src/libcharon/plugins/unity/unity_provider.h diff --git a/src/libcharon/plugins/unity/Makefile.am b/src/libcharon/plugins/unity/Makefile.am index 4c3cb887e..b23143fd6 100644 --- a/src/libcharon/plugins/unity/Makefile.am +++ b/src/libcharon/plugins/unity/Makefile.am @@ -13,6 +13,7 @@ endif libstrongswan_unity_la_SOURCES = \ unity_plugin.h unity_plugin.c \ unity_handler.h unity_handler.c \ - unity_narrow.h unity_narrow.c + unity_narrow.h unity_narrow.c \ + unity_provider.h unity_provider.c libstrongswan_unity_la_LDFLAGS = -module -avoid-version diff --git a/src/libcharon/plugins/unity/unity_plugin.c b/src/libcharon/plugins/unity/unity_plugin.c index 092dfed88..9e21bd9ed 100644 --- a/src/libcharon/plugins/unity/unity_plugin.c +++ b/src/libcharon/plugins/unity/unity_plugin.c @@ -16,6 +16,7 @@ #include "unity_plugin.h" #include "unity_handler.h" #include "unity_narrow.h" +#include "unity_provider.h" #include #include @@ -37,6 +38,11 @@ struct private_unity_plugin_t { */ unity_handler_t *handler; + /** + * Responder Unity configuration attribute provider + */ + unity_provider_t *provider; + /** * Traffic selector narrower, for Unity Split-Includes */ @@ -55,7 +61,10 @@ METHOD(plugin_t, destroy, void, charon->bus->remove_listener(charon->bus, &this->narrower->listener); this->narrower->destroy(this->narrower); hydra->attributes->remove_handler(hydra->attributes, &this->handler->handler); + hydra->attributes->remove_provider(hydra->attributes, + &this->provider->provider); this->handler->destroy(this->handler); + this->provider->destroy(this->provider); free(this); } @@ -75,8 +84,10 @@ plugin_t *unity_plugin_create() }, }, .handler = unity_handler_create(), + .provider = unity_provider_create(), ); hydra->attributes->add_handler(hydra->attributes, &this->handler->handler); + hydra->attributes->add_provider(hydra->attributes, &this->provider->provider); this->narrower = unity_narrow_create(this->handler), charon->bus->add_listener(charon->bus, &this->narrower->listener); diff --git a/src/libcharon/plugins/unity/unity_provider.c b/src/libcharon/plugins/unity/unity_provider.c new file mode 100644 index 000000000..753cd9839 --- /dev/null +++ b/src/libcharon/plugins/unity/unity_provider.c @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2012 Martin Willi + * Copyright (C) 2012 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "unity_provider.h" + +#include + +typedef struct private_unity_provider_t private_unity_provider_t; + +/** + * Private data of an unity_provider_t object. + */ +struct private_unity_provider_t { + + /** + * Public unity_provider_t interface. + */ + unity_provider_t public; +}; + +/** + * Attribute enumerator for traffic selector list + */ +typedef struct { + /** Implements enumerator_t */ + 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]; +} attribute_enumerator_t; + +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; + + while (TRUE) + { + if (this->list->remove_first(this->list, (void**)&ts) != SUCCESS) + { + return FALSE; + } + if (ts->get_type(ts) == TS_IPV4_ADDR_RANGE && + ts->to_subnet(ts, &net, &mask)) + { + ts->destroy(ts); + break; + } + ts->destroy(ts); + } + + memset(this->mask, 0, sizeof(this->mask)); + for (i = 0; i < sizeof(this->mask); i++) + { + if (mask < 8) + { + this->mask[i] = 0xFF << (8 - mask); + break; + } + this->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)); + + return TRUE; +} + +METHOD(enumerator_t, attribute_destroy, void, + attribute_enumerator_t *this) +{ + this->list->destroy_offset(this->list, offsetof(traffic_selector_t, destroy)); + free(this); +} + +METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*, + private_unity_provider_t *this, linked_list_t *pools, identification_t *id, + linked_list_t *vips) +{ + attribute_enumerator_t *attr_enum; + enumerator_t *enumerator; + linked_list_t *list, *current; + traffic_selector_t *ts; + ike_sa_t *ike_sa; + peer_cfg_t *peer_cfg; + child_cfg_t *child_cfg; + + ike_sa = charon->bus->get_sa(charon->bus); + if (!ike_sa || ike_sa->get_version(ike_sa) != IKEV1 || + !vips->get_count(vips)) + { + return NULL; + } + + list = linked_list_create(); + peer_cfg = ike_sa->get_peer_cfg(ike_sa); + enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg); + while (enumerator->enumerate(enumerator, &child_cfg)) + { + current = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL); + while (current->remove_first(current, (void**)&ts) == SUCCESS) + { + list->insert_last(list, ts); + } + current->destroy(current); + } + enumerator->destroy(enumerator); + + if (list->get_count(list) == 0) + { + list->destroy(list); + return NULL; + } + INIT(attr_enum, + .public = { + .enumerate = (void*)_attribute_enumerate, + .destroy = _attribute_destroy, + }, + .list = list, + ); + return &attr_enum->public; +} + +METHOD(unity_provider_t, destroy, void, + private_unity_provider_t *this) +{ + free(this); +} + +/** + * See header + */ +unity_provider_t *unity_provider_create() +{ + private_unity_provider_t *this; + + INIT(this, + .public = { + .provider = { + .acquire_address = (void*)return_null, + .release_address = (void*)return_false, + .create_attribute_enumerator = _create_attribute_enumerator, + }, + .destroy = _destroy, + }, + ); + + return &this->public; +} diff --git a/src/libcharon/plugins/unity/unity_provider.h b/src/libcharon/plugins/unity/unity_provider.h new file mode 100644 index 000000000..a25df5df0 --- /dev/null +++ b/src/libcharon/plugins/unity/unity_provider.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2012 Martin Willi + * Copyright (C) 2012 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup unity_provider unity_provider + * @{ @ingroup unity + */ + +#ifndef UNITY_PROVIDER_H_ +#define UNITY_PROVIDER_H_ + +typedef struct unity_provider_t unity_provider_t; + +#include + +/** + * Cisco Unity extension attribute provider. + */ +struct unity_provider_t { + + /** + * Implements attribute_provier_t interface. + */ + attribute_provider_t provider; + + /** + * Destroy a unity_provider_t. + */ + void (*destroy)(unity_provider_t *this); +}; + +/** + * Create a unity_provider instance. + */ +unity_provider_t *unity_provider_create(); + +#endif /** UNITY_PROVIDER_H_ @}*/