summaryrefslogtreecommitdiff
path: root/src/libcharon/plugins/eap_radius/eap_radius.c
diff options
context:
space:
mode:
authorYves-Alexis Perez <corsac@debian.org>2013-11-01 13:32:07 +0100
committerYves-Alexis Perez <corsac@debian.org>2013-11-01 13:32:07 +0100
commit5313d2d78ca150515f7f5eb39801c100690b6b29 (patch)
treec78e420367283bb1b16f14210b12687cdfbd26eb /src/libcharon/plugins/eap_radius/eap_radius.c
parent6b99c8d9cff7b3e8ae8f3204b99e7ea40f791349 (diff)
downloadvyos-strongswan-5313d2d78ca150515f7f5eb39801c100690b6b29.tar.gz
vyos-strongswan-5313d2d78ca150515f7f5eb39801c100690b6b29.zip
Imported Upstream version 5.1.1
Diffstat (limited to 'src/libcharon/plugins/eap_radius/eap_radius.c')
-rw-r--r--src/libcharon/plugins/eap_radius/eap_radius.c126
1 files changed, 123 insertions, 3 deletions
diff --git a/src/libcharon/plugins/eap_radius/eap_radius.c b/src/libcharon/plugins/eap_radius/eap_radius.c
index b06b6c392..6087a528f 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>
@@ -392,6 +393,85 @@ static void process_timeout(radius_message_t *msg)
}
/**
+ * Add a Cisco Unity configuration attribute
+ */
+static void add_unity_attribute(eap_radius_provider_t *provider, u_int32_t id,
+ int type, chunk_t data)
+{
+ switch (type)
+ {
+ case 15: /* CVPN3000-IPSec-Banner1 */
+ case 36: /* CVPN3000-IPSec-Banner2 */
+ provider->add_attribute(provider, id, UNITY_BANNER, data);
+ break;
+ case 28: /* CVPN3000-IPSec-Default-Domain */
+ provider->add_attribute(provider, id, UNITY_DEF_DOMAIN, data);
+ break;
+ case 29: /* CVPN3000-IPSec-Split-DNS-Names */
+ provider->add_attribute(provider, id, UNITY_SPLITDNS_NAME, data);
+ break;
+ }
+}
+
+/**
+ * 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)
@@ -401,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);
@@ -419,6 +500,11 @@ static void process_cfg_attributes(radius_message_t *msg)
ike_sa->get_unique_id(ike_sa), host);
}
}
+ else if (type == RAT_FRAMED_IP_NETMASK && data.len == 4)
+ {
+ provider->add_attribute(provider, ike_sa->get_unique_id(ike_sa),
+ INTERNAL_IP4_NETMASK, data);
+ }
}
enumerator->destroy(enumerator);
@@ -430,12 +516,30 @@ static void process_cfg_attributes(radius_message_t *msg)
switch (type)
{
case 15: /* CVPN3000-IPSec-Banner1 */
+ case 28: /* CVPN3000-IPSec-Default-Domain */
+ case 29: /* CVPN3000-IPSec-Split-DNS-Names */
case 36: /* CVPN3000-IPSec-Banner2 */
if (ike_sa->supports_extension(ike_sa, EXT_CISCO_UNITY))
{
- provider->add_attribute(provider,
- ike_sa->get_unique_id(ike_sa),
- UNITY_BANNER, data);
+ add_unity_attribute(provider,
+ 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:
@@ -444,6 +548,22 @@ static void process_cfg_attributes(radius_message_t *msg)
}
}
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);
+ }
}
}