aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2013-08-16 15:25:33 +0200
committerTobias Brunner <tobias@strongswan.org>2013-10-11 15:52:22 +0200
commit1a809e46f8fd2f0df7cce18451070e6bf79faddc (patch)
treed52ac35158fdc3db3e0b485c4376fb8084dd85ea
parent66229619cf428919933aa8c7daf903fb9437cb2c (diff)
downloadstrongswan-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.c93
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);
+ }
}
}