Merge branch 'unity'

Add Cisco Unity extension support implemented in a dedicated plugin.
This commit is contained in:
Martin Willi
2012-09-18 17:22:47 +02:00
25 changed files with 1234 additions and 7 deletions
+7
View File
@@ -23,6 +23,13 @@ strongswan-5.0.1
PAM directly anymore, but can use any XAuth backend to verify credentials,
including xauth-pam.
- The new unity plugin brings support for some parts of the IKEv1 Cisco Unity
Extension. As client, charon narrows traffic selectors to the received
Split-Include attributes and automatically installs IPsec bypass policies
for received Local-LAN attributes. As server, charon sends Split-Include
attributes for leftsubnet definitions containing multiple subnets to Unity-
aware clients.
- An EAP-Nak payload is returned by clients if the gateway requests an EAP
method that the client does not support. Clients can also request a specific
EAP method by configuring that method with leftauth.
+4
View File
@@ -206,6 +206,7 @@ ARG_ENABL_SET([ctr], [enables the Counter Mode wrapper crypto plugin.
ARG_ENABL_SET([ccm], [enables the CCM AEAD wrapper crypto plugin.])
ARG_ENABL_SET([gcm], [enables the GCM AEAD wrapper crypto plugin.])
ARG_ENABL_SET([addrblock], [enables RFC 3779 address block constraint support.])
ARG_ENABL_SET([unity], [enables Cisco Unity extension plugin.])
ARG_ENABL_SET([uci], [enable OpenWRT UCI configuration plugin.])
ARG_ENABL_SET([android], [enable Android specific plugin.])
ARG_ENABL_SET([android-log], [enable Android specific logger plugin.])
@@ -953,6 +954,7 @@ ADD_PLUGIN([radattr], [c charon])
ADD_PLUGIN([maemo], [c charon])
ADD_PLUGIN([uci], [c charon])
ADD_PLUGIN([addrblock], [c charon])
ADD_PLUGIN([unity], [c charon])
ADD_PLUGIN([unit-tester], [c charon])
AC_SUBST(charon_plugins)
@@ -1078,6 +1080,7 @@ AM_CONDITIONAL(USE_SOCKET_DEFAULT, test x$socket_default = xtrue)
AM_CONDITIONAL(USE_SOCKET_DYNAMIC, test x$socket_dynamic = xtrue)
AM_CONDITIONAL(USE_FARP, test x$farp = xtrue)
AM_CONDITIONAL(USE_ADDRBLOCK, test x$addrblock = xtrue)
AM_CONDITIONAL(USE_UNITY, test x$unity = xtrue)
dnl hydra plugins
dnl =============
@@ -1257,6 +1260,7 @@ AC_OUTPUT(
src/libcharon/plugins/medsrv/Makefile
src/libcharon/plugins/medcli/Makefile
src/libcharon/plugins/addrblock/Makefile
src/libcharon/plugins/unity/Makefile
src/libcharon/plugins/uci/Makefile
src/libcharon/plugins/ha/Makefile
src/libcharon/plugins/whitelist/Makefile
+3 -2
View File
@@ -756,8 +756,9 @@ signifying that the left end of the connection goes to the left participant
only. Configured subnets of the peers may differ, the protocol narrows it to
the greatest common subnet. In IKEv1, this may lead to problems with other
implementations, make sure to configure identical subnets in such
configurations. IKEv2 supports multiple subnets separated by commas, IKEv1 only
interprets the first subnet of such a definition.
configurations. IKEv2 supports multiple subnets separated by commas. IKEv1 only
interprets the first subnet of such a definition, unless the Cisco Unity
extension plugin is enabled.
.TP
.BR leftupdown " = <path>"
what ``updown'' script to run to adjust routing and/or firewalling
+7
View File
@@ -533,6 +533,13 @@ if MONOLITHIC
endif
endif
if USE_UNITY
SUBDIRS += plugins/unity
if MONOLITHIC
libcharon_la_LIBADD += plugins/unity/libstrongswan-unity.la
endif
endif
if USE_UNIT_TESTS
SUBDIRS += plugins/unit_tester
if MONOLITHIC
+19
View File
@@ -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
+433
View File
@@ -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;
}
@@ -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_ @}*/
+171
View File
@@ -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, &current))
{
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**)&current) == 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;
}
@@ -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_ @}*/
@@ -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;
}
@@ -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_ @}*/
@@ -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;
}
@@ -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_ @}*/
@@ -460,11 +460,6 @@ static traffic_selector_t* select_ts(private_quick_mode_t *this, bool local,
hosts->destroy(hosts);
if (list->get_first(list, (void**)&ts) == SUCCESS)
{
if (this->initiator && list->get_count(list) > 1)
{
DBG1(DBG_IKE, "configuration has more than one %s traffic selector,"
" using first only", local ? "local" : "remote");
}
ts = ts->clone(ts);
}
else
+5
View File
@@ -392,6 +392,11 @@ then
echo -n " --enable-cisco-quirks" >> $INSTALLSHELL
fi
if [ "$USE_UNITY" = "yes" ]
then
echo -n " --enable-unity" >> $INSTALLSHELL
fi
echo "" >> $INSTALLSHELL
echo "make -j" >> $INSTALLSHELL
echo "make install" >> $INSTALLSHELL
+1
View File
@@ -87,6 +87,7 @@ USE_XAUTH_EAP="yes"
USE_PKCS8="yes"
USE_IFMAP="no"
USE_CISCO_QUIRKS="no"
USE_UNITY="yes"
# Gentoo linux root filesystem
ROOTFS=$UMLTESTDIR/gentoo-fs-20111212.tar.bz2
@@ -0,0 +1,6 @@
The roadwarrior <b>carol</b> sets up a connection to gateway <b>moon</b>.
The authentication is based on <b>X.509 certificates</b>. <b>carol</b>
requests a virtual IP using <b>leftsourceip=%config</b> and indicates
support for the Cisco Unity extension. Gateway <b>moon</b> responds with
two Split-Include subnets configured in the <b>leftsubnet</b> definition and a
global Local-LAN exclude option defined in strongswan.conf.
@@ -0,0 +1,8 @@
carol::ipsec status 2> /dev/null::home.*ESTABLISHED.*[email protected].*moon.strongswan.org::YES
moon:: ipsec status 2> /dev/null::rw\[1]: ESTABLISHED.*moon.strongswan.org.*[email protected]::YES
carol::ipsec status 2> /dev/null::10.2.1.1/32 === 192.168.0.0/24 PASS::YES
carol::ipsec status 2> /dev/null::home.*10.2.1.1/32 === 10.1.0.0/16 10.2.1.0/24::YES
moon:: ipsec status 2> /dev/null::rw[{]1}.*10.1.0.0/16 10.2.1.0/24 === 10.2.1.1/32::YES
carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_seq=1::YES
moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP::YES
moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES
@@ -0,0 +1,20 @@
# /etc/ipsec.conf - strongSwan IPsec configuration file
config setup
conn %default
ikelifetime=60m
keylife=20m
rekeymargin=3m
keyingtries=1
keyexchange=ikev1
conn home
left=PH_IP_CAROL
leftcert=carolCert.pem
[email protected]
leftsourceip=%config
right=PH_IP_MOON
[email protected]
rightsubnet=0.0.0.0/0
auto=add
@@ -0,0 +1,14 @@
# /etc/strongswan.conf - strongSwan configuration file
charon {
load = curl test-vectors aes des sha1 sha2 md5 pem pkcs1 pkcs8 gmp random nonce x509 revocation hmac xcbc ctr ccm gcm stroke kernel-netlink socket-default unity
cisco_unity = yes
}
libstrongswan {
dh_exponent_ansi_x9_42 = no
integrity_test = yes
crypto_test {
on_add = yes
}
}
@@ -0,0 +1,19 @@
# /etc/ipsec.conf - strongSwan IPsec configuration file
config setup
conn %default
ikelifetime=60m
keylife=20m
rekeymargin=3m
keyingtries=1
keyexchange=ikev1
conn rw
left=PH_IP_MOON
leftcert=moonCert.pem
[email protected]
leftsubnet=10.1.0.0/16,10.2.1.0/24
right=%any
rightsourceip=10.2.1.0/24
auto=add
@@ -0,0 +1,19 @@
# /etc/strongswan.conf - strongSwan configuration file
charon {
load = curl test-vectors aes des sha1 sha2 md5 pem pkcs1 pkcs8 gmp random nonce x509 revocation hmac xcbc ctr ccm gcm stroke kernel-netlink socket-default attr unity
cisco_unity = yes
plugins {
attr {
split-exclude = 192.168.0.0/24
}
}
}
libstrongswan {
dh_exponent_ansi_x9_42 = no
integrity_test = yes
crypto_test {
on_add = yes
}
}
@@ -0,0 +1,2 @@
moon::ipsec stop
carol::ipsec stop
@@ -0,0 +1,4 @@
moon::ipsec start
carol::ipsec start
carol::sleep 1
carol::ipsec up home
@@ -0,0 +1,21 @@
#!/bin/bash
#
# This configuration file provides information on the
# UML instances used for this test
# All UML instances that are required for this test
#
UMLHOSTS="alice moon carol winnetou"
# Corresponding block diagram
#
DIAGRAM="a-m-c.png"
# UML instances on which tcpdump is to be started
#
TCPDUMPHOSTS="moon"
# UML instances on which IPsec is started
# Used for IPsec logging purposes
#
IPSECHOSTS="moon carol"