diff options
author | Martin Willi <martin@revosec.ch> | 2012-09-18 17:22:30 +0200 |
---|---|---|
committer | Martin Willi <martin@revosec.ch> | 2012-09-18 17:22:47 +0200 |
commit | a69bc12a3ac16835f28b333dcf0e5b43aab77f45 (patch) | |
tree | f39db3ce8fd2293a7f662cc111b2fba39643a56b /src/libcharon/plugins/unity | |
parent | 56ea95195acbb432ee7ab2f03883725408789e97 (diff) | |
parent | 995a9c8a0a00d52b2e5008433f22485b2f1bcf01 (diff) | |
download | strongswan-a69bc12a3ac16835f28b333dcf0e5b43aab77f45.tar.bz2 strongswan-a69bc12a3ac16835f28b333dcf0e5b43aab77f45.tar.xz |
Merge branch 'unity'
Add Cisco Unity extension support implemented in a dedicated plugin.
Diffstat (limited to 'src/libcharon/plugins/unity')
-rw-r--r-- | src/libcharon/plugins/unity/Makefile.am | 19 | ||||
-rw-r--r-- | src/libcharon/plugins/unity/unity_handler.c | 433 | ||||
-rw-r--r-- | src/libcharon/plugins/unity/unity_handler.h | 58 | ||||
-rw-r--r-- | src/libcharon/plugins/unity/unity_narrow.c | 171 | ||||
-rw-r--r-- | src/libcharon/plugins/unity/unity_narrow.h | 51 | ||||
-rw-r--r-- | src/libcharon/plugins/unity/unity_plugin.c | 96 | ||||
-rw-r--r-- | src/libcharon/plugins/unity/unity_plugin.h | 42 | ||||
-rw-r--r-- | src/libcharon/plugins/unity/unity_provider.c | 175 | ||||
-rw-r--r-- | src/libcharon/plugins/unity/unity_provider.h | 49 |
9 files changed, 1094 insertions, 0 deletions
diff --git a/src/libcharon/plugins/unity/Makefile.am b/src/libcharon/plugins/unity/Makefile.am new file mode 100644 index 000000000..b23143fd6 --- /dev/null +++ b/src/libcharon/plugins/unity/Makefile.am @@ -0,0 +1,19 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon + +AM_CFLAGS = -rdynamic + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-unity.la +else +plugin_LTLIBRARIES = libstrongswan-unity.la +endif + +libstrongswan_unity_la_SOURCES = \ + unity_plugin.h unity_plugin.c \ + unity_handler.h unity_handler.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_handler.c b/src/libcharon/plugins/unity/unity_handler.c new file mode 100644 index 000000000..b2aeba605 --- /dev/null +++ b/src/libcharon/plugins/unity/unity_handler.c @@ -0,0 +1,433 @@ +/* + * 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 <http://www.fsf.org/copyleft/gpl.txt>. + * + * 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_handler.h" + +#include <daemon.h> +#include <threading/mutex.h> +#include <utils/linked_list.h> +#include <processing/jobs/callback_job.h> + +typedef struct private_unity_handler_t private_unity_handler_t; + +/** + * Private data of an unity_handler_t object. + */ +struct private_unity_handler_t { + + /** + * Public unity_handler_t interface. + */ + unity_handler_t public; + + /** + * List of subnets to include, as entry_t + */ + linked_list_t *include; + + /** + * Mutex for concurrent access to lists + */ + mutex_t *mutex; +}; + +/** + * Traffic selector entry for networks to include under a given IKE_SA + */ +typedef struct { + /** associated IKE_SA, unique ID */ + u_int32_t sa; + /** traffic selector to include/exclude */ + traffic_selector_t *ts; +} entry_t; + +/** + * Clean up an entry + */ +static void entry_destroy(entry_t *this) +{ + this->ts->destroy(this->ts); + free(this); +} + +/** + * Create a traffic selector from a unity subnet definition + */ +static traffic_selector_t *create_ts(chunk_t subnet) +{ + chunk_t net, mask; + int i; + + if (subnet.len != 8) + { + return NULL; + } + net = chunk_create(subnet.ptr, 4); + mask = chunk_clonea(chunk_skip(subnet, 4)); + for (i = 0; i < net.len; i++) + { + mask.ptr[i] = (mask.ptr[i] ^ 0xFF) | net.ptr[i]; + } + return traffic_selector_create_from_bytes(0, TS_IPV4_ADDR_RANGE, + net, 0, mask, 65535); +} + +/** + * Store a subnet to include in tunnels under this IKE_SA + */ +static bool add_include(private_unity_handler_t *this, chunk_t subnet) +{ + traffic_selector_t *ts; + ike_sa_t *ike_sa; + entry_t *entry; + + ike_sa = charon->bus->get_sa(charon->bus); + if (!ike_sa) + { + return FALSE; + } + ts = create_ts(subnet); + if (!ts) + { + return FALSE; + } + INIT(entry, + .sa = ike_sa->get_unique_id(ike_sa), + .ts = ts, + ); + + this->mutex->lock(this->mutex); + this->include->insert_last(this->include, entry); + this->mutex->unlock(this->mutex); + return TRUE; +} + +/** + * Rempve a subnet from the inclusion list for this IKE_SA + */ +static bool remove_include(private_unity_handler_t *this, chunk_t subnet) +{ + enumerator_t *enumerator; + traffic_selector_t *ts; + ike_sa_t *ike_sa; + entry_t *entry; + + ike_sa = charon->bus->get_sa(charon->bus); + if (!ike_sa) + { + return FALSE; + } + ts = create_ts(subnet); + if (!ts) + { + return FALSE; + } + + this->mutex->lock(this->mutex); + enumerator = this->include->create_enumerator(this->include); + while (enumerator->enumerate(enumerator, &entry)) + { + if (entry->sa == ike_sa->get_unique_id(ike_sa) && + ts->equals(ts, entry->ts)) + { + this->include->remove_at(this->include, enumerator); + entry_destroy(entry); + break; + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); + ts->destroy(ts); + return TRUE; +} + +/** + * Create a unique shunt name for a bypass policy + */ +static void create_shunt_name(ike_sa_t *ike_sa, traffic_selector_t *ts, + char *buf, size_t len) +{ + snprintf(buf, len, "Unity (%s[%u]: %R)", ike_sa->get_name(ike_sa), + ike_sa->get_unique_id(ike_sa), ts); +} + +/** + * Install entry as a shunt policy + */ +static job_requeue_t add_exclude_async(entry_t *entry) +{ + enumerator_t *enumerator; + child_cfg_t *child_cfg; + lifetime_cfg_t lft = {}; + ike_sa_t *ike_sa; + char name[128]; + host_t *host; + bool has_vip = FALSE; + + ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager, + entry->sa, FALSE); + if (ike_sa) + { + create_shunt_name(ike_sa, entry->ts, name, sizeof(name)); + + child_cfg = child_cfg_create(name, &lft, NULL, TRUE, MODE_PASS, + ACTION_NONE, ACTION_NONE, ACTION_NONE, + FALSE, 0, 0, NULL, NULL, FALSE); + child_cfg->add_traffic_selector(child_cfg, FALSE, + entry->ts->clone(entry->ts)); + enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, TRUE); + while (enumerator->enumerate(enumerator, &host)) + { + has_vip = TRUE; + child_cfg->add_traffic_selector(child_cfg, TRUE, + traffic_selector_create_from_subnet(host->clone(host), 32, 0, 0)); + } + enumerator->destroy(enumerator); + + if (!has_vip) + { + host = ike_sa->get_my_host(ike_sa); + child_cfg->add_traffic_selector(child_cfg, TRUE, + traffic_selector_create_from_subnet(host->clone(host), 32, 0, 0)); + } + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + + charon->shunts->install(charon->shunts, child_cfg); + child_cfg->destroy(child_cfg); + + DBG1(DBG_IKE, "installed %N bypass policy for %R", + configuration_attribute_type_names, UNITY_LOCAL_LAN, entry->ts); + } + return JOB_REQUEUE_NONE; +} + +/** + * Add a bypass policy for a given subnet + */ +static bool add_exclude(private_unity_handler_t *this, chunk_t subnet) +{ + traffic_selector_t *ts; + ike_sa_t *ike_sa; + entry_t *entry; + + ike_sa = charon->bus->get_sa(charon->bus); + if (!ike_sa) + { + return FALSE; + } + ts = create_ts(subnet); + if (!ts) + { + return FALSE; + } + INIT(entry, + .sa = ike_sa->get_unique_id(ike_sa), + .ts = ts, + ); + + /* we can't install the shunt policy yet, as we don't know the virtual IP. + * Defer installation using an async callback. */ + lib->processor->queue_job(lib->processor, (job_t*) + callback_job_create((void*)add_exclude_async, entry, + (void*)entry_destroy, NULL)); + return TRUE; +} + +/** + * Remove a bypass policy for a given subnet + */ +static bool remove_exclude(private_unity_handler_t *this, chunk_t subnet) +{ + traffic_selector_t *ts; + ike_sa_t *ike_sa; + char name[128]; + + ike_sa = charon->bus->get_sa(charon->bus); + if (!ike_sa) + { + return FALSE; + } + ts = create_ts(subnet); + if (!ts) + { + return FALSE; + } + create_shunt_name(ike_sa, ts, name, sizeof(name)); + DBG1(DBG_IKE, "uninstalling %N bypass policy for %R", + configuration_attribute_type_names, UNITY_LOCAL_LAN, ts); + ts->destroy(ts); + return charon->shunts->uninstall(charon->shunts, name); +} + +METHOD(attribute_handler_t, handle, bool, + private_unity_handler_t *this, identification_t *id, + configuration_attribute_type_t type, chunk_t data) +{ + switch (type) + { + case UNITY_SPLIT_INCLUDE: + return add_include(this, data); + case UNITY_LOCAL_LAN: + return add_exclude(this, data); + default: + return FALSE; + } +} + +METHOD(attribute_handler_t, release, void, + private_unity_handler_t *this, identification_t *server, + configuration_attribute_type_t type, chunk_t data) +{ + switch (type) + { + case UNITY_SPLIT_INCLUDE: + remove_include(this, data); + break; + case UNITY_LOCAL_LAN: + remove_exclude(this, data); + break; + default: + break; + } +} + +/** + * Configuration attributes to request + */ +static configuration_attribute_type_t attributes[] = { + UNITY_SPLIT_INCLUDE, + UNITY_LOCAL_LAN, +}; + +/** + * Attribute enumerator implementation + */ +typedef struct { + /** implements enumerator_t */ + enumerator_t public; + /** position in attributes[] */ + int i; +} attribute_enumerator_t; + +METHOD(enumerator_t, enumerate_attributes, bool, + attribute_enumerator_t *this, configuration_attribute_type_t *type, + chunk_t *data) +{ + if (this->i < countof(attributes)) + { + *type = attributes[this->i++]; + *data = chunk_empty; + return TRUE; + } + return FALSE; +} + +METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t *, + unity_handler_t *this, identification_t *id, linked_list_t *vips) +{ + attribute_enumerator_t *enumerator; + ike_sa_t *ike_sa; + + ike_sa = charon->bus->get_sa(charon->bus); + if (!ike_sa || ike_sa->get_version(ike_sa) != IKEV1 || + !ike_sa->supports_extension(ike_sa, EXT_CISCO_UNITY)) + { + return enumerator_create_empty(); + } + INIT(enumerator, + .public = { + .enumerate = (void*)_enumerate_attributes, + .destroy = (void*)free, + }, + ); + return &enumerator->public; +} + +typedef struct { + /** mutex to unlock */ + mutex_t *mutex; + /** IKE_SA ID to filter for */ + u_int32_t id; +} include_filter_t; + +/** + * Include enumerator filter function + */ +static bool include_filter(include_filter_t *data, + entry_t **entry, traffic_selector_t **ts) +{ + if ((*entry)->sa == data->id) + { + *ts = (*entry)->ts; + return TRUE; + } + return FALSE; +} + +/** + * Destroy include filter data, unlock mutex + */ +static void destroy_filter(include_filter_t *data) +{ + data->mutex->unlock(data->mutex); + free(data); +} + +METHOD(unity_handler_t, create_include_enumerator, enumerator_t*, + private_unity_handler_t *this, u_int32_t id) +{ + include_filter_t *data; + + INIT(data, + .mutex = this->mutex, + .id = id, + ); + data->mutex->lock(data->mutex); + return enumerator_create_filter( + this->include->create_enumerator(this->include), + (void*)include_filter, data, (void*)destroy_filter); +} + +METHOD(unity_handler_t, destroy, void, + private_unity_handler_t *this) +{ + this->include->destroy(this->include); + this->mutex->destroy(this->mutex); + free(this); +} + +/** + * See header + */ +unity_handler_t *unity_handler_create() +{ + private_unity_handler_t *this; + + INIT(this, + .public = { + .handler = { + .handle = _handle, + .release = _release, + .create_attribute_enumerator = _create_attribute_enumerator, + }, + .create_include_enumerator = _create_include_enumerator, + .destroy = _destroy, + }, + .include = linked_list_create(), + .mutex = mutex_create(MUTEX_TYPE_DEFAULT), + ); + + return &this->public; +} diff --git a/src/libcharon/plugins/unity/unity_handler.h b/src/libcharon/plugins/unity/unity_handler.h new file mode 100644 index 000000000..8656fd372 --- /dev/null +++ b/src/libcharon/plugins/unity/unity_handler.h @@ -0,0 +1,58 @@ +/* + * 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 <http://www.fsf.org/copyleft/gpl.txt>. + * + * 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_handler unity_handler + * @{ @ingroup unity + */ + +#ifndef UNITY_HANDLER_H_ +#define UNITY_HANDLER_H_ + +#include <attributes/attribute_handler.h> + +typedef struct unity_handler_t unity_handler_t; + +/** + * Cisco Unity attribute handling. + */ +struct unity_handler_t { + + /** + * Implements attribute_handler_t. + */ + attribute_handler_t handler; + + /** + * Create an enumerator over Split-Include attributes received for an IKE_SA. + * + * @param id IKE_SA unique ID to get Split-Includes for + * @return enumerator over traffic_selector_t* + */ + enumerator_t* (*create_include_enumerator)(unity_handler_t *this, + u_int32_t id); + + /** + * Destroy a unity_handler_t. + */ + void (*destroy)(unity_handler_t *this); +}; + +/** + * Create a unity_handler instance. + */ +unity_handler_t *unity_handler_create(); + +#endif /** UNITY_HANDLER_H_ @}*/ diff --git a/src/libcharon/plugins/unity/unity_narrow.c b/src/libcharon/plugins/unity/unity_narrow.c new file mode 100644 index 000000000..56de0028f --- /dev/null +++ b/src/libcharon/plugins/unity/unity_narrow.c @@ -0,0 +1,171 @@ +/* + * 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 <http://www.fsf.org/copyleft/gpl.txt>. + * + * 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_narrow.h" + +#include <daemon.h> + +typedef struct private_unity_narrow_t private_unity_narrow_t; + +/** + * Private data of an unity_narrow_t object. + */ +struct private_unity_narrow_t { + + /** + * Public unity_narrow_t interface. + */ + unity_narrow_t public; + + /** + * Unity attribute handler + */ + unity_handler_t *handler; +}; + +/** + * Narrow TS as initiator to Unity Split-Include/Local-LAN + */ +static void narrow_initiator(private_unity_narrow_t *this, ike_sa_t *ike_sa, + child_cfg_t *cfg, linked_list_t *remote) +{ + traffic_selector_t *current, *orig = NULL; + linked_list_t *received, *selected; + enumerator_t *enumerator; + + enumerator = this->handler->create_include_enumerator(this->handler, + ike_sa->get_unique_id(ike_sa)); + while (enumerator->enumerate(enumerator, ¤t)) + { + if (orig == NULL) + { /* got one, replace original TS */ + if (remote->remove_first(remote, (void**)&orig) != SUCCESS) + { + break; + } + } + /* narrow received Unity TS with the child configuration */ + received = linked_list_create(); + received->insert_last(received, current); + selected = cfg->get_traffic_selectors(cfg, FALSE, received, NULL); + while (selected->remove_first(selected, (void**)¤t) == SUCCESS) + { + remote->insert_last(remote, current); + } + selected->destroy(selected); + received->destroy(received); + } + enumerator->destroy(enumerator); + if (orig) + { + DBG1(DBG_CFG, "narrowed CHILD_SA to %N %#R", + configuration_attribute_type_names, + UNITY_SPLIT_INCLUDE, remote); + orig->destroy(orig); + } +} + +/** + * As initiator, bump up TS to 0.0.0.0/0 for on-the-wire bits + */ +static void narrow_initiator_pre(linked_list_t *list) +{ + traffic_selector_t *ts; + + while (list->remove_first(list, (void**)&ts) == SUCCESS) + { + ts->destroy(ts); + } + ts = traffic_selector_create_from_string(0, TS_IPV4_ADDR_RANGE, + "0.0.0.0", 0, + "255.255.255.255", 65535); + if (ts) + { + list->insert_last(list, ts); + } +} + +/** + * As responder, narrow down TS to configuration for installation + */ +static void narrow_responder_post(child_cfg_t *child_cfg, linked_list_t *local) +{ + traffic_selector_t *ts; + linked_list_t *configured; + + while (local->remove_first(local, (void**)&ts) == SUCCESS) + { + ts->destroy(ts); + } + configured = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL); + + while (configured->remove_first(configured, (void**)&ts) == SUCCESS) + { + local->insert_last(local, ts); + } + configured->destroy(configured); +} + +METHOD(listener_t, narrow, bool, + private_unity_narrow_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa, + narrow_hook_t type, linked_list_t *local, linked_list_t *remote) +{ + if (ike_sa->get_version(ike_sa) == IKEV1 && + ike_sa->supports_extension(ike_sa, EXT_CISCO_UNITY)) + { + switch (type) + { + case NARROW_INITIATOR_PRE_AUTH: + narrow_initiator_pre(remote); + break; + case NARROW_INITIATOR_POST_AUTH: + narrow_initiator(this, ike_sa, + child_sa->get_config(child_sa), remote); + break; + case NARROW_RESPONDER_POST: + narrow_responder_post(child_sa->get_config(child_sa), local); + break; + default: + break; + } + } + return TRUE; +} + +METHOD(unity_narrow_t, destroy, void, + private_unity_narrow_t *this) +{ + free(this); +} + +/** + * See header + */ +unity_narrow_t *unity_narrow_create(unity_handler_t *handler) +{ + private_unity_narrow_t *this; + + INIT(this, + .public = { + .listener = { + .narrow = _narrow, + }, + .destroy = _destroy, + }, + .handler = handler, + ); + + return &this->public; +} diff --git a/src/libcharon/plugins/unity/unity_narrow.h b/src/libcharon/plugins/unity/unity_narrow.h new file mode 100644 index 000000000..5e0968518 --- /dev/null +++ b/src/libcharon/plugins/unity/unity_narrow.h @@ -0,0 +1,51 @@ +/* + * 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 <http://www.fsf.org/copyleft/gpl.txt>. + * + * 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_narrow unity_narrow + * @{ @ingroup unity + */ + +#ifndef UNITY_NARROW_H_ +#define UNITY_NARROW_H_ + +#include <bus/listeners/listener.h> + +#include "unity_handler.h" + +typedef struct unity_narrow_t unity_narrow_t; + +/** + * Listener that narrows Quick Modes to the Unity Split-Include subnets. + */ +struct unity_narrow_t { + + /** + * Implements listener_t. + */ + listener_t listener; + + /** + * Destroy a unity_narrow_t. + */ + void (*destroy)(unity_narrow_t *this); +}; + +/** + * Create a unity_narrow instance. + */ +unity_narrow_t *unity_narrow_create(unity_handler_t *handler); + +#endif /** UNITY_NARROW_H_ @}*/ diff --git a/src/libcharon/plugins/unity/unity_plugin.c b/src/libcharon/plugins/unity/unity_plugin.c new file mode 100644 index 000000000..9e21bd9ed --- /dev/null +++ b/src/libcharon/plugins/unity/unity_plugin.c @@ -0,0 +1,96 @@ +/* + * 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 <http://www.fsf.org/copyleft/gpl.txt>. + * + * 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_plugin.h" +#include "unity_handler.h" +#include "unity_narrow.h" +#include "unity_provider.h" + +#include <daemon.h> +#include <hydra.h> + +typedef struct private_unity_plugin_t private_unity_plugin_t; + +/** + * private data of unity_plugin + */ +struct private_unity_plugin_t { + + /** + * public functions + */ + unity_plugin_t public; + + /** + * Handler for UNITY configuration attributes + */ + unity_handler_t *handler; + + /** + * Responder Unity configuration attribute provider + */ + unity_provider_t *provider; + + /** + * Traffic selector narrower, for Unity Split-Includes + */ + unity_narrow_t *narrower; +}; + +METHOD(plugin_t, get_name, char*, + private_unity_plugin_t *this) +{ + return "unity"; +} + +METHOD(plugin_t, destroy, void, + private_unity_plugin_t *this) +{ + 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); +} + +/* + * see header file + */ +plugin_t *unity_plugin_create() +{ + private_unity_plugin_t *this; + + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, + .destroy = _destroy, + }, + }, + .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); + + return &this->public.plugin; +} diff --git a/src/libcharon/plugins/unity/unity_plugin.h b/src/libcharon/plugins/unity/unity_plugin.h new file mode 100644 index 000000000..0d407b561 --- /dev/null +++ b/src/libcharon/plugins/unity/unity_plugin.h @@ -0,0 +1,42 @@ +/* + * 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 <http://www.fsf.org/copyleft/gpl.txt>. + * + * 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 unity + * @ingroup cplugins + * + * @defgroup unity_plugin unity_plugin + * @{ @ingroup unity + */ + +#ifndef UNITY_PLUGIN_H_ +#define UNITY_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct unity_plugin_t unity_plugin_t; + +/** + * IKEv1 Cisco Unity extension support. + */ +struct unity_plugin_t { + + /** + * Implements plugin_t. interface. + */ + plugin_t plugin; +}; + +#endif /** UNITY_PLUGIN_H_ @}*/ diff --git a/src/libcharon/plugins/unity/unity_provider.c b/src/libcharon/plugins/unity/unity_provider.c new file mode 100644 index 000000000..c7feb090c --- /dev/null +++ b/src/libcharon/plugins/unity/unity_provider.c @@ -0,0 +1,175 @@ +/* + * 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 <http://www.fsf.org/copyleft/gpl.txt>. + * + * 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 <daemon.h> + +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 || + !ike_sa->supports_extension(ike_sa, EXT_CISCO_UNITY) || + !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; + } + DBG1(DBG_CFG, "sending %N: %#R", + configuration_attribute_type_names, UNITY_SPLIT_INCLUDE, list); + + 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 <http://www.fsf.org/copyleft/gpl.txt>. + * + * 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 <attributes/attribute_provider.h> + +/** + * 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_ @}*/ |