diff options
author | Tobias Brunner <tobias@strongswan.org> | 2013-08-16 15:25:33 +0200 |
---|---|---|
committer | Tobias Brunner <tobias@strongswan.org> | 2013-10-11 15:52:22 +0200 |
commit | 1a809e46f8fd2f0df7cce18451070e6bf79faddc (patch) | |
tree | d52ac35158fdc3db3e0b485c4376fb8084dd85ea | |
parent | 66229619cf428919933aa8c7daf903fb9437cb2c (diff) | |
download | strongswan-1a809e46f8fd2f0df7cce18451070e6bf79faddc.tar.bz2 strongswan-1a809e46f8fd2f0df7cce18451070e6bf79faddc.tar.xz |
eap-radius: Forward UNITY_SPLIT_INCLUDE or UNITY_LOCAL_LAN attributes
Depending on the value of the CVPN3000-IPSec-Split-Tunneling-Policy(55)
radius attribute, the subnets in the CVPN3000-IPSec-Split-Tunnel-List(27)
attribute are sent in either a UNITY_SPLIT_INCLUDE (if the value is 1)
or a UNITY_LOCAL_LAN (if the value is 2).
So if the following attributes would be configured for a RADIUS user
CVPN3000-IPSec-Split-Tunnel-List := "10.0.1.0/255.255.255.0,10.0.2.0/255.255.255.0"
CVPN3000-IPSec-Split-Tunneling-Policy := 1
A UNITY_SPLIT_INCLUDE configuration payload containing these two subnets
would be sent to the client during the ModeCfg exchange.
-rw-r--r-- | src/libcharon/plugins/eap_radius/eap_radius.c | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/src/libcharon/plugins/eap_radius/eap_radius.c b/src/libcharon/plugins/eap_radius/eap_radius.c index 469c2a3cd..9a242c0c8 100644 --- a/src/libcharon/plugins/eap_radius/eap_radius.c +++ b/src/libcharon/plugins/eap_radius/eap_radius.c @@ -21,6 +21,7 @@ #include <radius_message.h> #include <radius_client.h> +#include <bio/bio_writer.h> #include <daemon.h> @@ -413,6 +414,64 @@ static void add_unity_attribute(eap_radius_provider_t *provider, u_int32_t id, } /** + * Add a UNITY_LOCAL_LAN or UNITY_SPLIT_INCLUDE attribute + */ +static void add_unity_split_attribute(eap_radius_provider_t *provider, + u_int32_t id, configuration_attribute_type_t type, + chunk_t data) +{ + enumerator_t *enumerator; + bio_writer_t *writer; + char buffer[256], *token, *slash; + + if (snprintf(buffer, sizeof(buffer), "%.*s", (int)data.len, + data.ptr) >= sizeof(buffer)) + { + return; + } + writer = bio_writer_create(16); /* two IPv4 addresses and 6 bytes padding */ + enumerator = enumerator_create_token(buffer, ",", " "); + while (enumerator->enumerate(enumerator, &token)) + { + host_t *net, *mask = NULL; + chunk_t padding; + + slash = strchr(token, '/'); + if (slash) + { + *slash++ = '\0'; + mask = host_create_from_string(slash, 0); + } + if (!mask) + { /* default to /32 */ + mask = host_create_from_string("255.255.255.255", 0); + } + net = host_create_from_string(token, 0); + if (!net || net->get_family(net) != AF_INET || + mask->get_family(mask) != AF_INET) + { + mask->destroy(mask); + DESTROY_IF(net); + continue; + } + writer->write_data(writer, net->get_address(net)); + writer->write_data(writer, mask->get_address(mask)); + padding = writer->skip(writer, 6); /* 6 bytes pdding */ + memset(padding.ptr, 0, padding.len); + mask->destroy(mask); + net->destroy(net); + } + enumerator->destroy(enumerator); + + data = writer->get_buf(writer); + if (data.len) + { + provider->add_attribute(provider, id, type, data); + } + writer->destroy(writer); +} + +/** * Handle Framed-IP-Address and other IKE configuration attributes */ static void process_cfg_attributes(radius_message_t *msg) @@ -422,6 +481,7 @@ static void process_cfg_attributes(radius_message_t *msg) ike_sa_t *ike_sa; host_t *host; chunk_t data; + configuration_attribute_type_t split_type = 0; int type, vendor; ike_sa = charon->bus->get_sa(charon->bus); @@ -460,12 +520,45 @@ static void process_cfg_attributes(radius_message_t *msg) ike_sa->get_unique_id(ike_sa), type, data); } break; + case 55: /* CVPN3000-IPSec-Split-Tunneling-Policy */ + if (data.len) + { + switch (data.ptr[data.len - 1]) + { + case 0: /* tunnelall */ + default: + break; + case 1: /* tunnelspecified */ + split_type = UNITY_SPLIT_INCLUDE; + break; + case 2: /* excludespecified */ + split_type = UNITY_LOCAL_LAN; + break; + } + } + break; default: break; } } } enumerator->destroy(enumerator); + + if (split_type != 0 && + ike_sa->supports_extension(ike_sa, EXT_CISCO_UNITY)) + { + enumerator = msg->create_vendor_enumerator(msg); + while (enumerator->enumerate(enumerator, &vendor, &type, &data)) + { + if (vendor == PEN_ALTIGA /* aka Cisco VPN3000 */ && + type == 27 /* CVPN3000-IPSec-Split-Tunnel-List */) + { + add_unity_split_attribute(provider, + ike_sa->get_unique_id(ike_sa), split_type, data); + } + } + enumerator->destroy(enumerator); + } } } |