aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAndreas Steffen <andreas.steffen@strongswan.org>2010-05-14 17:07:03 +0200
committerAndreas Steffen <andreas.steffen@strongswan.org>2010-05-14 17:07:03 +0200
commit03b5e4d8d79bceb12cdc4b227d10c46bb6721b98 (patch)
tree9146df2accfbc063e418a2752b90a19e24462c99 /src
parenta27354685451ac84a7decc411f17cfbbbb15d59f (diff)
downloadstrongswan-03b5e4d8d79bceb12cdc4b227d10c46bb6721b98.tar.bz2
strongswan-03b5e4d8d79bceb12cdc4b227d10c46bb6721b98.tar.xz
refactoring of Mode Config functionality allows transport and handling of any attribute
Diffstat (limited to 'src')
-rw-r--r--src/libhydra/attributes/attributes.c27
-rw-r--r--src/libhydra/attributes/attributes.h61
-rw-r--r--src/pluto/connections.c37
-rw-r--r--src/pluto/connections.h9
-rw-r--r--src/pluto/constants.h35
-rw-r--r--src/pluto/ipsec_doi.c27
-rw-r--r--src/pluto/kernel.c8
-rw-r--r--src/pluto/modecfg.c1245
-rw-r--r--src/pluto/modecfg.h5
9 files changed, 722 insertions, 732 deletions
diff --git a/src/libhydra/attributes/attributes.c b/src/libhydra/attributes/attributes.c
index 83feed17e..164fb1690 100644
--- a/src/libhydra/attributes/attributes.c
+++ b/src/libhydra/attributes/attributes.c
@@ -36,8 +36,31 @@ ENUM_BEGIN(configuration_attribute_type_names, INTERNAL_IP4_ADDRESS, INTERNAL_IP
"MIP6_HOME_PREFIX",
"INTERNAL_IP6_LINK",
"INTERNAL_IP6_PREFIX");
-ENUM_NEXT(configuration_attribute_type_names, INTERNAL_IP4_SERVER, INTERNAL_IP6_SERVER, INTERNAL_IP6_PREFIX,
+ENUM_NEXT(configuration_attribute_type_names, XAUTH_TYPE, XAUTH_ANSWER, INTERNAL_IP6_PREFIX,
+ "XAUTH_TYPE",
+ "XAUTH_USER_NAME",
+ "XAUTH_USER_PASSWORD",
+ "XAUTH_PASSCODE",
+ "XAUTH_MESSAGE",
+ "XAUTH_CHALLENGE",
+ "XAUTH_DOMAIN",
+ "XAUTH_STATUS",
+ "XAUTH_NEXT_PIN",
+ "XAUTH_ANSWER");
+ENUM_NEXT(configuration_attribute_type_names, INTERNAL_IP4_SERVER, INTERNAL_IP6_SERVER, XAUTH_ANSWER,
"INTERNAL_IP4_SERVER",
"INTERNAL_IP6_SERVER");
-ENUM_END(configuration_attribute_type_names, INTERNAL_IP6_SERVER);
+ENUM_NEXT(configuration_attribute_type_names, UNITY_BANNER, UNITY_DDNS_HOSTNAME, INTERNAL_IP6_SERVER,
+ "UNITY_BANNER",
+ "UNITY_SAVE_PASSWD",
+ "UNITY_DEF_DOMAIN",
+ "UNITY_SPLITDNS_NAME",
+ "UNITY_SPLIT_INCLUDE",
+ "UNITY_NATT_PORT",
+ "UNITY_LOCAL_LAN",
+ "UNITY_PFS",
+ "UNITY_FW_TYPE",
+ "UNITY_BACKUP_SERVERS",
+ "UNITY_DDNS_HOSTNAME");
+ENUM_END(configuration_attribute_type_names, UNITY_DDNS_HOSTNAME);
diff --git a/src/libhydra/attributes/attributes.h b/src/libhydra/attributes/attributes.h
index f4a396f21..b4693702a 100644
--- a/src/libhydra/attributes/attributes.h
+++ b/src/libhydra/attributes/attributes.h
@@ -30,27 +30,50 @@ typedef enum configuration_attribute_type_t configuration_attribute_type_t;
* Type of the attribute, as in IKEv2 RFC 3.15.1 or IKEv1 ModeConfig.
*/
enum configuration_attribute_type_t {
- INTERNAL_IP4_ADDRESS = 1,
- INTERNAL_IP4_NETMASK = 2,
- INTERNAL_IP4_DNS = 3,
- INTERNAL_IP4_NBNS = 4,
+ INTERNAL_IP4_ADDRESS = 1,
+ INTERNAL_IP4_NETMASK = 2,
+ INTERNAL_IP4_DNS = 3,
+ INTERNAL_IP4_NBNS = 4,
INTERNAL_ADDRESS_EXPIRY = 5,
- INTERNAL_IP4_DHCP = 6,
- APPLICATION_VERSION = 7,
- INTERNAL_IP6_ADDRESS = 8,
- INTERNAL_IP6_NETMASK = 9,
- INTERNAL_IP6_DNS = 10,
- INTERNAL_IP6_NBNS = 11,
- INTERNAL_IP6_DHCP = 12,
- INTERNAL_IP4_SUBNET = 13,
- SUPPORTED_ATTRIBUTES = 14,
- INTERNAL_IP6_SUBNET = 15,
- MIP6_HOME_PREFIX = 16,
- INTERNAL_IP6_LINK = 17,
- INTERNAL_IP6_PREFIX = 18,
+ INTERNAL_IP4_DHCP = 6,
+ APPLICATION_VERSION = 7,
+ INTERNAL_IP6_ADDRESS = 8,
+ INTERNAL_IP6_NETMASK = 9,
+ INTERNAL_IP6_DNS = 10,
+ INTERNAL_IP6_NBNS = 11,
+ INTERNAL_IP6_DHCP = 12,
+ INTERNAL_IP4_SUBNET = 13,
+ SUPPORTED_ATTRIBUTES = 14,
+ INTERNAL_IP6_SUBNET = 15,
+ MIP6_HOME_PREFIX = 16,
+ INTERNAL_IP6_LINK = 17,
+ INTERNAL_IP6_PREFIX = 18,
+ /* XAUTH attributes */
+ XAUTH_TYPE = 16520,
+ XAUTH_USER_NAME = 16521,
+ XAUTH_USER_PASSWORD = 16522,
+ XAUTH_PASSCODE = 16523,
+ XAUTH_MESSAGE = 16524,
+ XAUTH_CHALLENGE = 16525,
+ XAUTH_DOMAIN = 16526,
+ XAUTH_STATUS = 16527,
+ XAUTH_NEXT_PIN = 16528,
+ XAUTH_ANSWER = 16529,
/* proprietary Microsoft attributes */
- INTERNAL_IP4_SERVER = 23456,
- INTERNAL_IP6_SERVER = 23457
+ INTERNAL_IP4_SERVER = 23456,
+ INTERNAL_IP6_SERVER = 23457,
+ /* proprietary Cisco Unity attributes */
+ UNITY_BANNER = 28672,
+ UNITY_SAVE_PASSWD = 28673,
+ UNITY_DEF_DOMAIN = 28674,
+ UNITY_SPLITDNS_NAME = 28675,
+ UNITY_SPLIT_INCLUDE = 28676,
+ UNITY_NATT_PORT = 28677,
+ UNITY_LOCAL_LAN = 28678,
+ UNITY_PFS = 28679,
+ UNITY_FW_TYPE = 28680,
+ UNITY_BACKUP_SERVERS = 28681,
+ UNITY_DDNS_HOSTNAME = 28682
};
/**
diff --git a/src/pluto/connections.c b/src/pluto/connections.c
index d6c38514d..a8d297ebf 100644
--- a/src/pluto/connections.c
+++ b/src/pluto/connections.c
@@ -369,14 +369,10 @@ void delete_connection(connection_t *c, bool relations)
/* release virtual IP address lease if any */
if (c->spd.that.modecfg && c->spd.that.pool &&
- !isanyaddr(&c->spd.that.host_srcip))
+ !c->spd.that.host_srcip->is_anyaddr(c->spd.that.host_srcip))
{
- host_t *vip;
-
- vip = host_create_from_sockaddr((sockaddr_t*)&c->spd.that.host_srcip);
hydra->attributes->release_address(hydra->attributes, c->spd.that.pool,
- vip, c->spd.that.id);
- vip->destroy(vip);
+ c->spd.that.host_srcip, c->spd.that.id);
}
/* release requested attributes if any */
@@ -411,11 +407,14 @@ void delete_connection(connection_t *c, bool relations)
DESTROY_IF(c->spd.this.id);
DESTROY_IF(c->spd.this.ca);
DESTROY_IF(c->spd.this.groups);
+ DESTROY_IF(c->spd.this.host_srcip);
+
free(c->spd.this.updown);
free(c->spd.this.pool);
DESTROY_IF(c->spd.that.id);
DESTROY_IF(c->spd.that.ca);
DESTROY_IF(c->spd.that.groups);
+ DESTROY_IF(c->spd.that.host_srcip);
free(c->spd.that.updown);
free(c->spd.that.pool);
if (c->requested_ca)
@@ -678,7 +677,7 @@ size_t format_end(char *buf, size_t buf_len, const struct end *this,
subnettot(&this->client, 0, client, sizeof(client));
}
}
- else if (this->modecfg && isanyaddr(&this->host_srcip))
+ else if (this->modecfg && this->host_srcip->is_anyaddr(this->host_srcip))
{
/* we are mode config client, or a server with a pool */
client_sep = "===";
@@ -763,6 +762,7 @@ static void unshare_connection_strings(connection_t *c)
c->spd.this.id = c->spd.this.id->clone(c->spd.this.id);
c->spd.this.pool = clone_str(c->spd.this.pool);
c->spd.this.updown = clone_str(c->spd.this.updown);
+ c->spd.this.host_srcip = c->spd.this.host_srcip->clone(c->spd.this.host_srcip);
scx_share(c->spd.this.sc);
cert_share(c->spd.this.cert);
if (c->spd.this.ca)
@@ -776,6 +776,7 @@ static void unshare_connection_strings(connection_t *c)
c->spd.that.id = c->spd.that.id->clone(c->spd.that.id);
c->spd.that.pool = clone_str(c->spd.that.pool);
c->spd.that.updown = clone_str(c->spd.that.updown);
+ c->spd.that.host_srcip = c->spd.that.host_srcip->clone(c->spd.that.host_srcip);
scx_share(c->spd.that.sc);
cert_share(c->spd.that.cert);
if (c->spd.that.ca)
@@ -924,7 +925,7 @@ static bool extract_end(struct end *dst, const whack_end_t *src,
/* the rest is simple copying of corresponding fields */
dst->host_addr = src->host_addr;
dst->host_nexthop = src->host_nexthop;
- dst->host_srcip = src->host_srcip;
+ dst->host_srcip = host_create_from_sockaddr((sockaddr_t*)&src->host_srcip);
dst->has_natip = src->has_natip;
dst->client = src->client;
dst->protocol = src->protocol;
@@ -949,10 +950,14 @@ static bool extract_end(struct end *dst, const whack_end_t *src,
/* if host sourceip is defined but no client is present
* behind the host then set client to sourceip/32
*/
- if (addrbytesptr(&dst->host_srcip, NULL) &&
- !isanyaddr(&dst->host_srcip) && !dst->has_natip && !dst->has_client)
+ if (!dst->host_srcip->is_anyaddr(dst->host_srcip) &&
+ !dst->has_natip && !dst->has_client)
{
- err_t ugh = addrtosubnet(&dst->host_srcip, &dst->client);
+ ip_address addr;
+ err_t ugh;
+
+ addr = *(ip_address*)dst->host_srcip->get_sockaddr(dst->host_srcip);
+ ugh = addrtosubnet(&addr, &dst->client);
if (ugh)
{
@@ -1233,7 +1238,8 @@ void add_connection(const whack_message_t *wm)
c->spd.that.modecfg = TRUE;
c->spd.that.has_client = FALSE;
/* reset the host_srcip so that it gets assigned in modecfg */
- anyaddr(AF_INET, &c->spd.that.host_srcip);
+ DESTROY_IF(c->spd.that.host_srcip);
+ c->spd.that.host_srcip = host_create_any(AF_INET);
}
if (c->ikev1)
@@ -3068,7 +3074,8 @@ void ISAKMP_SA_established(connection_t *c, so_serial_t serial)
/* the connection is now oriented so that we are able to determine
* whether we are a mode config server with a virtual IP to send.
*/
- if (!isanyaddr(&c->spd.that.host_srcip) && !c->spd.that.has_natip)
+ if (!c->spd.that.host_srcip->is_anyaddr(c->spd.that.host_srcip) &&
+ !c->spd.that.has_natip)
{
c->spd.that.modecfg = TRUE;
}
@@ -3715,8 +3722,10 @@ static connection_t *fc_try(const connection_t *c, struct host_pair *hp,
}
else
{
+ host_t *vip = c->spd.that.host_srcip;
+
if (!peer_net_is_host && !(sr->that.modecfg && c->spd.that.modecfg &&
- subnetisaddr(peer_net, &c->spd.that.host_srcip)))
+ subnetisaddr(peer_net, (ip_address*)vip->get_sockaddr(vip))))
{
continue;
}
diff --git a/src/pluto/connections.h b/src/pluto/connections.h
index ae6356db1..1aa3b5757 100644
--- a/src/pluto/connections.h
+++ b/src/pluto/connections.h
@@ -1,6 +1,6 @@
/* information about connections between hosts and clients
* Copyright (C) 1998-2001 D. Hugh Redelmeier
- * Copyright (C) 2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2009-2010 Andreas Steffen - Hochschule fuer Technik Rapperswil
*
* 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
@@ -18,6 +18,7 @@
#include <sys/queue.h>
+#include <utils/host.h>
#include <utils/linked_list.h>
#include <utils/identification.h>
#include <credentials/ietf_attributes/ietf_attributes.h>
@@ -131,10 +132,8 @@ struct virtual_t;
struct end {
identification_t *id;
- ip_address
- host_addr,
- host_nexthop,
- host_srcip;
+ ip_address host_addr, host_nexthop;
+ host_t *host_srcip;
ip_subnet client;
bool is_left;
diff --git a/src/pluto/constants.h b/src/pluto/constants.h
index 9c87926d0..790bbefa6 100644
--- a/src/pluto/constants.h
+++ b/src/pluto/constants.h
@@ -543,41 +543,6 @@ extern enum_names attr_msg_type_names;
extern enum_names modecfg_attr_names;
-/* XAUTH attribute values */
-#define XAUTH_TYPE 16520
-#define XAUTH_USER_NAME 16521
-#define XAUTH_USER_PASSWORD 16522
-#define XAUTH_PASSCODE 16523
-#define XAUTH_MESSAGE 16524
-#define XAUTH_CHALLENGE 16525
-#define XAUTH_DOMAIN 16526
-#define XAUTH_STATUS 16527
-#define XAUTH_NEXT_PIN 16528
-#define XAUTH_ANSWER 16529
-
-#define XAUTH_BASE XAUTH_TYPE
-
-extern enum_names xauth_attr_names;
-
-extern enum_names microsoft_attr_names;
-
-/* ISAKMP mode config attributes specific to the Unity vendor ID */
-#define UNITY_BANNER 28672
-#define UNITY_SAVE_PASSWD 28673
-#define UNITY_DEF_DOMAIN 28674
-#define UNITY_SPLITDNS_NAME 28675
-#define UNITY_SPLIT_INCLUDE 28676
-#define UNITY_NATT_PORT 28677
-#define UNITY_LOCAL_LAN 28678
-#define UNITY_PFS 28679
-#define UNITY_FW_TYPE 28680
-#define UNITY_BACKUP_SERVERS 28681
-#define UNITY_DDNS_HOSTNAME 28682
-
-#define UNITY_BASE UNITY_BANNER
-
-extern enum_names unity_attr_names;
-
/* XAUTH authentication types */
#define XAUTH_TYPE_GENERIC 0
#define XAUTH_TYPE_CHAP 1
diff --git a/src/pluto/ipsec_doi.c b/src/pluto/ipsec_doi.c
index 34c42e294..e506d71bc 100644
--- a/src/pluto/ipsec_doi.c
+++ b/src/pluto/ipsec_doi.c
@@ -702,7 +702,7 @@ void accept_delete(struct state *st, struct msg_digest *md,
struct payload_digest *p)
{
struct isakmp_delete *d = &(p->payload.delete);
- identification_t *this_id, *that_id;
+ identification_t *this_id = NULL, *that_id = NULL;
ip_address peer_addr;
size_t sizespi;
int i;
@@ -1949,19 +1949,18 @@ stf_status quick_outI1(int whack_sock, struct state *isakmp_sa,
u_int8_t np = ISAKMP_NEXT_NONE;
if (c->spd.this.modecfg && !c->spd.this.has_client &&
- isanyaddr(&c->spd.this.host_srcip))
+ c->spd.this.host_srcip->is_anyaddr(c->spd.this.host_srcip))
{
connection_t *ph1_c = isakmp_sa->st_connection;
+ host_t * ph1_srcip = ph1_c->spd.this.host_srcip;
- if (ph1_c->spd.this.modecfg && !isanyaddr(&ph1_c->spd.this.host_srcip))
+ if (ph1_c->spd.this.modecfg && !ph1_srcip->is_anyaddr(ph1_srcip))
{
- char srcip[ADDRTOT_BUF];
-
- c->spd.this.host_srcip = ph1_c->spd.this.host_srcip;
+ c->spd.this.host_srcip->destroy(c->spd.this.host_srcip);
+ c->spd.this.host_srcip = ph1_srcip->clone(ph1_srcip);
c->spd.this.client = ph1_c->spd.this.client;
c->spd.this.has_client = TRUE;
- addrtot(&c->spd.this.host_srcip, 0, srcip, sizeof(srcip));
- plog("inheriting virtual IP source address %s from ModeCfg", srcip);
+ plog("inheriting virtual IP source address %H from ModeCfg", ph1_srcip);
}
}
@@ -4888,20 +4887,20 @@ static stf_status quick_inI1_outR1_tail(struct verify_oppo_bundle *b,
/* Plain Road Warrior:
* instantiate, carrying over authenticated peer ID
*/
+ host_t *vip = c->spd.that.host_srcip;
+
p = rw_instantiate(p, &c->spd.that.host_addr, md->sender_port
, his_net, c->spd.that.id);
/* inherit any virtual IP assigned by a Mode Config exchange */
if (p->spd.that.modecfg && c->spd.that.modecfg &&
- subnetisaddr(his_net, &c->spd.that.host_srcip))
+ subnetisaddr(his_net, (ip_address*)vip->get_sockaddr(vip)))
{
- char srcip[ADDRTOT_BUF];
-
DBG(DBG_CONTROL,
- addrtot(&c->spd.that.host_srcip, 0, srcip, sizeof(srcip));
- DBG_log("inheriting virtual IP source address %s from ModeCfg", srcip)
+ DBG_log("inheriting virtual IP source address %H from ModeCfg", vip)
)
- p->spd.that.host_srcip = c->spd.that.host_srcip;
+ p->spd.that.host_srcip->destroy(p->spd.that.host_srcip);
+ p->spd.that.host_srcip = vip->clone(vip);
p->spd.that.client = c->spd.that.client;
p->spd.that.has_client = TRUE;
}
diff --git a/src/pluto/kernel.c b/src/pluto/kernel.c
index ee22fb55e..79ba3aa57 100644
--- a/src/pluto/kernel.c
+++ b/src/pluto/kernel.c
@@ -483,16 +483,14 @@ static bool do_command(connection_t *c, struct spd_route *sr,
strncat(nexthop_str, "' ", sizeof(nexthop_str));
}
- if (addrbytesptr(&sr->this.host_srcip, NULL)
- && !isanyaddr(&sr->this.host_srcip))
+ if (!sr->this.host_srcip->is_anyaddr(sr->this.host_srcip))
{
char *n;
strcpy(srcip_str, "PLUTO_MY_SOURCEIP='");
n = srcip_str + strlen(srcip_str);
-
- addrtot(&sr->this.host_srcip, 0
- ,n , sizeof(srcip_str)-strlen(srcip_str));
+ snprintf(n, sizeof(srcip_str)-strlen(srcip_str), "%H",
+ sr->this.host_srcip);
strncat(srcip_str, "' ", sizeof(srcip_str));
}
diff --git a/src/pluto/modecfg.c b/src/pluto/modecfg.c
index 1f2711f33..2ca771d17 100644
--- a/src/pluto/modecfg.c
+++ b/src/pluto/modecfg.c
@@ -2,7 +2,7 @@
* Copyright (C) 2001-2002 Colubris Networks
* Copyright (C) 2003 Sean Mathews - Nu Tech Software Solutions, inc.
* Copyright (C) 2003-2004 Xelerance Corporation
- * Copyright (C) 2006-2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2006-2010 Andreas Steffen - Hochschule fuer Technik Rapperswil
*
* 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
@@ -44,19 +44,7 @@
#define MAX_XAUTH_TRIES 3
-#define SUPPORTED_ATTR_SET ( LELEM(INTERNAL_IP4_ADDRESS) \
- | LELEM(INTERNAL_IP4_NETMASK) \
- | LELEM(INTERNAL_IP4_DNS) \
- | LELEM(INTERNAL_IP4_NBNS) \
- | LELEM(APPLICATION_VERSION) \
- | LELEM(INTERNAL_IP6_DNS) \
- | LELEM(INTERNAL_IP6_NBNS) \
- )
-
-#define SUPPORTED_UNITY_ATTR_SET ( LELEM(UNITY_BANNER - UNITY_BASE) )
-
-#define UNITY_BANNER_STR "Welcome to strongSwan - the Linux VPN Solution!\n"
-
+#define DEFAULT_UNITY_BANNER "Welcome to strongSwan - the Linux VPN Solution!\n"
/**
* Creates a modecfg_attribute_t object
@@ -68,6 +56,7 @@ static modecfg_attribute_t *modecfg_attribute_create(configuration_attribute_typ
this = malloc_thing(modecfg_attribute_t);
this->type = ((u_int16_t)type) & 0x7FFF;
+ this->is_tv = FALSE;
this->value = chunk_clone(value);
this->handler = NULL;
@@ -75,66 +64,85 @@ static modecfg_attribute_t *modecfg_attribute_create(configuration_attribute_typ
}
/**
- * Destroys a modecfg_attribute_t object
+ * Creates a modecfg_attribute_t object coded in TV format
*/
-void modecfg_attribute_destroy(modecfg_attribute_t *this)
+static modecfg_attribute_t *modecfg_attribute_create_tv(configuration_attribute_type_t type,
+ size_t value)
{
- free(this->value.ptr);
- free(this);
-}
-
-/*
- * Addresses assigned (usually via ModeCfg) to the Initiator
- */
-typedef struct internal_addr internal_addr_t;
-
-struct internal_addr
-{
- lset_t attr_set;
- lset_t xauth_attr_set;
- lset_t unity_attr_set;
-
- /* ModeCfg variables */
- ip_address ipaddr;
+ modecfg_attribute_t *this;
- char *unity_banner;
+ this = modecfg_attribute_create(type, chunk_empty);
+ this->value.len = value;
+ this->is_tv = TRUE;
- /* XAUTH variables */
- u_int16_t xauth_type;
- xauth_t xauth_secret;
- bool xauth_status;
-};
+ return this;
+}
/**
- * Initialize an internal_addr struct
+ * Destroys a modecfg_attribute_t object
*/
-static void init_internal_addr(internal_addr_t *ia)
+void modecfg_attribute_destroy(modecfg_attribute_t *this)
{
- ia->attr_set = LEMPTY;
- ia->xauth_attr_set = LEMPTY;
- ia->xauth_secret.user_name = chunk_empty;
- ia->xauth_secret.user_password = chunk_empty;
- ia->xauth_type = XAUTH_TYPE_GENERIC;
- ia->xauth_status = XAUTH_STATUS_FAIL;
- ia->unity_attr_set = LEMPTY;
- ia->unity_banner = NULL;
-
- anyaddr(AF_INET, &ia->ipaddr);
+ free(this->value.ptr);
+ free(this);
}
/**
- * Get internal IP address for a connection
+ * Get attributes to be sent to client
*/
-static void get_internal_addr(connection_t *c, host_t *requested_vip,
- internal_addr_t *ia, linked_list_t *ca_list)
+static void get_attributes(connection_t *c, linked_list_t *ca_list)
{
- enumerator_t *enumerator;
configuration_attribute_type_t type;
- chunk_t value;
modecfg_attribute_t *ca;
- host_t *vip = NULL;
+ enumerator_t *enumerator;
+ chunk_t value;
+ host_t *vip = NULL, *requested_vip = NULL;
+ bool want_unity_banner = FALSE;
+ int family;
+
+#ifdef CISCO_QUIRKS
+ /* always send banner in ModeCfg push mode */
+ if (ca_list->get_count(ca_list) == 0)
+ {
+ want_unity_banner = TRUE;
+ }
+#endif
+
+ /* scan list of requested attributes in ModeCfg pull mode */
+ while (ca_list->remove_last(ca_list, (void **)&ca) == SUCCESS)
+ {
+ switch (ca->type)
+ {
+ case INTERNAL_IP4_ADDRESS:
+ case INTERNAL_IP6_ADDRESS:
+ {
+ int family;
+
+ family = (ca->type == INTERNAL_IP4_ADDRESS) ? AF_INET : AF_INET6;
+ requested_vip = (ca->value.len) ?
+ host_create_from_chunk(family, ca->value, 0) :
+ host_create_any(family);
+ plog("peer requested virtual IP %H", requested_vip);
+ break;
+ }
+#ifdef CISCO_QUIRKS
+ case UNITY_BANNER:
+ want_unity_banner = TRUE;
+ break;
+#endif
+ default:
+ break;
+ }
+ modecfg_attribute_destroy(ca);
+ }
- if (isanyaddr(&c->spd.that.host_srcip))
+ if (requested_vip == NULL)
+ {
+ requested_vip = host_create_any(AF_INET);
+ }
+
+ /* if no virtual IP has been assigned yet - acquire one */
+ if (c->spd.that.host_srcip->is_anyaddr(c->spd.that.host_srcip))
{
if (c->spd.that.pool)
{
@@ -143,11 +151,8 @@ static void get_internal_addr(connection_t *c, host_t *requested_vip,
requested_vip);
if (vip)
{
- chunk_t addr = vip->get_address(vip);
-
- plog("assigning virtual IP %H to peer", vip);
- initaddr(addr.ptr, addr.len, vip->get_family(vip), &ia->ipaddr);
-
+ c->spd.that.host_srcip->destroy(c->spd.that.host_srcip);
+ c->spd.that.host_srcip = vip;
}
}
else
@@ -155,22 +160,25 @@ static void get_internal_addr(connection_t *c, host_t *requested_vip,
plog("no virtual IP found");
}
}
- else
+
+ requested_vip->destroy(requested_vip);
+
+ /* if we have a virtual IP address - send it */
+ if (!c->spd.that.host_srcip->is_anyaddr(c->spd.that.host_srcip))
{
- ia->ipaddr = c->spd.that.host_srcip;
- vip = host_create_from_sockaddr((sockaddr_t*)&ia->ipaddr);
+ vip = c->spd.that.host_srcip;
plog("assigning virtual IP %H to peer", vip);
- }
+ family = vip->get_family(vip);
+ ca = modecfg_attribute_create((family == AF_INET) ?
+ INTERNAL_IP4_ADDRESS :
+ INTERNAL_IP6_ADDRESS,
+ vip->get_address(vip));
+ ca_list->insert_last(ca_list, ca);
- if (!isanyaddr(&ia->ipaddr)) /* We got an IP address, send it */
- {
- c->spd.that.host_srcip = ia->ipaddr;
- c->spd.that.client.addr = ia->ipaddr;
- c->spd.that.client.maskbits = 32;
+ /* set the remote client subnet to virtual IP */
+ c->spd.that.client.addr = *(ip_address*)vip->get_sockaddr(vip);
+ c->spd.that.client.maskbits = (family == AF_INET) ? 32 : 128;
c->spd.that.has_client = TRUE;
-
- ia->attr_set = LELEM(INTERNAL_IP4_ADDRESS)
- | LELEM(INTERNAL_IP4_NETMASK);
}
/* assign attributes from registered providers */
@@ -178,103 +186,158 @@ static void get_internal_addr(connection_t *c, host_t *requested_vip,
c->spd.that.id, vip);
while (enumerator->enumerate(enumerator, &type, &value))
{
- DBG(DBG_CONTROLMORE,
- DBG_log("building %N attribute",
- configuration_attribute_type_names, type)
- )
ca = modecfg_attribute_create(type, value);
ca_list->insert_last(ca_list, ca);
+ if (type == UNITY_BANNER)
+ {
+ want_unity_banner = FALSE;
+ }
}
enumerator->destroy(enumerator);
- DESTROY_IF(vip);
-}
+ if (want_unity_banner)
+ {
+ ca = modecfg_attribute_create(UNITY_BANNER,
+ chunk_create(DEFAULT_UNITY_BANNER,
+ strlen(DEFAULT_UNITY_BANNER)));
+ ca_list->insert_last(ca_list, ca);
+ }
+}
/**
* Set srcip and client subnet to internal IP address
*/
-static bool set_internal_addr(connection_t *c, internal_addr_t *ia,
- linked_list_t *ca_list)
+static bool set_attributes(connection_t *c, linked_list_t *ca_list)
{
- if (ia->attr_set & LELEM(INTERNAL_IP4_ADDRESS)
- && !isanyaddr(&ia->ipaddr))
+ host_t *vip, *srcip;
+ modecfg_attribute_t *ca, *ca_handler;
+ enumerator_t *enumerator;
+ bool vip_set = FALSE;
+
+ enumerator = ca_list->create_enumerator(ca_list);
+ while (enumerator->enumerate(enumerator, &ca))
{
- host_t *vip;
- modecfg_attribute_t *ca;
- enumerator_t *enumerator;
+ int family = AF_INET6;
+ attribute_handler_t *handler = NULL;
+ enumerator_t *e;
- if (addrbytesptr(&c->spd.this.host_srcip, NULL) == 0
- || isanyaddr(&c->spd.this.host_srcip)
- || sameaddr(&c->spd.this.host_srcip, &ia->ipaddr))
+ switch (ca->type)
{
- char srcip[ADDRTOT_BUF];
+ case INTERNAL_IP4_ADDRESS:
+ family = AF_INET;
+ /* fall */
+ case INTERNAL_IP6_ADDRESS:
+ if (ca->value.len == 0)
+ {
+ vip = host_create_any(family);
+ }
+ else
+ {
+ /* skip prefix byte in IPv6 payload*/
+ if (family == AF_INET6)
+ {
+ ca->value.len = 16;
+ }
+ vip = host_create_from_chunk(family, ca->value, 0);
+ }
+ if (vip)
+ {
+ srcip = c->spd.this.host_srcip;
- addrtot(&ia->ipaddr, 0, srcip, sizeof(srcip));
- plog("setting virtual IP source address to %s", srcip);
+ if (srcip->is_anyaddr(srcip) || srcip->equals(srcip, vip))
+ {
+ plog("setting virtual IP source address to %H", vip);
+ }
+ else
+ {
+ plog("replacing virtual IP source address %H by %H",
+ srcip, vip);
+ }
+ srcip->destroy(srcip);
+ c->spd.this.host_srcip = vip;
+
+ /* setting client subnet to vip/32 */
+ addrtosubnet((ip_address*)vip->get_sockaddr(vip),
+ &c->spd.this.client);
+ setportof(0, &c->spd.this.client.addr);
+ c->spd.this.has_client = TRUE;
+
+ vip_set = TRUE;
+ }
+ continue;
+ case APPLICATION_VERSION:
+#ifdef CISCO_QUIRKS
+ case UNITY_BANNER:
+#endif
+ if (ca->value.len > 0)
+ {
+ DBG(DBG_PARSING | DBG_CONTROLMORE,
+ DBG_log(" '%.*s'", ca->value.len, ca->value.ptr)
+ )
+ }
+ break;
+ default:
+ break;
}
- else
- {
- char old_srcip[ADDRTOT_BUF];
- char new_srcip[ADDRTOT_BUF];
- addrtot(&c->spd.this.host_srcip, 0, old_srcip, sizeof(old_srcip));
- addrtot(&ia->ipaddr, 0, new_srcip, sizeof(new_srcip));
- plog("replacing virtual IP source address %s by %s"
- , old_srcip, new_srcip);
+ /* find the first handler which requested this attribute */
+ e = c->requested->create_enumerator(c->requested);
+ while (e->enumerate(e, &ca_handler))
+ {
+ if (ca_handler->type == ca->type)
+ {
+ handler = ca_handler->handler;
+ break;
+ }
}
+ e->destroy(e);
- /* setting srcip */
- c->spd.this.host_srcip = ia->ipaddr;
- vip = host_create_from_sockaddr((sockaddr_t*)&ia->ipaddr);
-
- /* setting client subnet to srcip/32 */
- addrtosubnet(&ia->ipaddr, &c->spd.this.client);
- setportof(0, &c->spd.this.client.addr);
- c->spd.this.has_client = TRUE;
-
- /* setting other attributes (e.g. DNS and NBNS servers) */
- enumerator = ca_list->create_enumerator(ca_list);
- while (enumerator->enumerate(enumerator, &ca))
+ /* and pass it to the handle function */
+ handler = hydra->attributes->handle(hydra->attributes,
+ c->spd.that.id, handler, ca->type, ca->value);
+ if (handler)
{
- modecfg_attribute_t *ca_handler;
- attribute_handler_t *handler = NULL;
- enumerator_t *e;
+ ca_handler = modecfg_attribute_create(ca->type, ca->value);
+ ca_handler->handler = handler;
- /* find the first handler which requested this attribute */
- e = c->requested->create_enumerator(c->requested);
- while (e->enumerate(e, &ca_handler))
+ if (c->attributes == NULL)
{
- if (ca_handler->type == ca->type)
- {
- handler = ca_handler->handler;
- break;
- }
+ c->attributes = linked_list_create();
}
- e->destroy(e);
+ c->attributes->insert_last(c->attributes, ca_handler);
+ }
+ }
+ enumerator->destroy(enumerator);
+ c->requested->destroy_function(c->requested, (void*)modecfg_attribute_destroy);
+ c->requested = NULL;
+ return vip_set;
+}
- /* and pass it to the handle function */
- handler = hydra->attributes->handle(hydra->attributes,
- c->spd.that.id, handler, ca->type, ca->value);
- if (handler)
- {
- ca_handler = modecfg_attribute_create(ca->type, ca->value);
- ca_handler->handler = handler;
+/**
+ * Register configuration attribute handlers
+ */
+static void register_attribute_handlers(connection_t *c)
+{
+ configuration_attribute_type_t type;
+ modecfg_attribute_t *ca;
+ chunk_t value;
+ attribute_handler_t *handler;
+ enumerator_t *enumerator;
- if (c->attributes == NULL)
- {
- c->attributes = linked_list_create();
- }
- c->attributes->insert_last(c->attributes, ca_handler);
- }
- }
- enumerator->destroy(enumerator);
- vip->destroy(vip);
- c->requested->destroy_function(c->requested,
- (void*)modecfg_attribute_destroy);
- c->requested = NULL;
- return TRUE;
+ /* add configuration attributes requested by handlers */
+ if (c->requested == NULL)
+ {
+ c->requested = linked_list_create();
+ }
+ enumerator = hydra->attributes->create_initiator_enumerator(
+ hydra->attributes,c->spd.that.id, c->spd.this.host_srcip);
+ while (enumerator->enumerate(enumerator, &handler, &type, &value))
+ {
+ ca = modecfg_attribute_create(type, value);
+ ca->handler = handler;
+ c->requested->insert_last(c->requested, ca);
}
- return FALSE;
+ enumerator->destroy(enumerator);
}
/**
@@ -309,188 +372,53 @@ static size_t modecfg_hash(u_char *dest, u_char *start, u_char *roof,
* Generate an IKE message containing ModeCfg information (eg: IP, DNS, WINS)
*/
static stf_status modecfg_build_msg(struct state *st, pb_stream *rbody,
- u_int16_t msg_type,
- internal_addr_t *ia,
- linked_list_t *ca_list,
+ u_int16_t msg_type, linked_list_t *ca_list,
u_int16_t ap_id)
{
u_char *r_hash_start, *r_hashval;
+ struct isakmp_mode_attr attrh;
+ struct isakmp_attribute attr;
+ pb_stream strattr,attrval;
+ enumerator_t *enumerator;
+ modecfg_attribute_t *ca;
START_HASH_PAYLOAD(*rbody, ISAKMP_NEXT_ATTR);
- /* ATTR out */
+ attrh.isama_np = ISAKMP_NEXT_NONE;
+ attrh.isama_type = msg_type;
+ attrh.isama_identifier = ap_id;
+
+ if (!out_struct(&attrh, &isakmp_attr_desc, rbody, &strattr))
{
- struct isakmp_mode_attr attrh;
- struct isakmp_attribute attr;
- pb_stream strattr,attrval;
- int attr_type;
- bool is_xauth_attr_set = ia->xauth_attr_set != LEMPTY;
- bool is_unity_attr_set = ia->unity_attr_set != LEMPTY;
- lset_t attr_set = ia->attr_set;
- enumerator_t *enumerator;
- modecfg_attribute_t *ca;
-
- attrh.isama_np = ISAKMP_NEXT_NONE;
- attrh.isama_type = msg_type;
- attrh.isama_identifier = ap_id;
-
- if (!out_struct(&attrh, &isakmp_attr_desc, rbody, &strattr))
- {
- return STF_INTERNAL_ERROR;
- }
- attr_type = 0;
+ return STF_INTERNAL_ERROR;
+ }
- enumerator = ca_list->create_enumerator(ca_list);
- while (enumerator->enumerate(enumerator, &ca))
+ enumerator = ca_list->create_enumerator(ca_list);
+ while (enumerator->enumerate(enumerator, &ca))
+ {
+ DBG(DBG_CONTROLMORE,
+ DBG_log("building %N attribute", configuration_attribute_type_names, ca->type)
+ )
+ if (ca->is_tv)
{
- char ca_type_name[BUF_LEN];
-
- snprintf(ca_type_name, BUF_LEN, "%N",
- configuration_attribute_type_names, ca->type);
- attr.isaat_af_type = ca->type | ISAKMP_ATTR_AF_TLV;
+ attr.isaat_af_type = ca->type | ISAKMP_ATTR_AF_TV;
+ attr.isaat_lv = ca->value.len;
out_struct(&attr, &isakmp_modecfg_attribute_desc, &strattr, &attrval);
- out_raw(ca->value.ptr, ca->value.len, &attrval, ca_type_name);
- close_output_pbs(&attrval);
}
- enumerator->destroy(enumerator);
-
- while (attr_set != LEMPTY || is_xauth_attr_set || is_unity_attr_set)
+ else
{
- if (attr_set == LEMPTY)
- {
- if (is_xauth_attr_set)
- {
- attr_set = ia->xauth_attr_set;
- attr_type = XAUTH_BASE;
- is_xauth_attr_set = FALSE;
- }
- else
- {
- attr_set = ia->unity_attr_set;
- attr_type = UNITY_BASE;
- is_unity_attr_set = FALSE;
- }
- }
-
- if (attr_set & 1)
- {
- const u_char *byte_ptr;
- u_int len;
-
- /* ISAKMP attr out */
- if (attr_type == XAUTH_TYPE)
- {
- attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TV;
- attr.isaat_lv = ia->xauth_type;
- }
- else if (attr_type == XAUTH_STATUS)
- {
- attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TV;
- attr.isaat_lv = ia->xauth_status;
- }
- else
- {
- attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TLV;
- }
- out_struct(&attr, &isakmp_modecfg_attribute_desc, &strattr, &attrval);
+ char buf[BUF_LEN];
- switch (attr_type)
- {
- case INTERNAL_IP4_ADDRESS:
- if (!isanyaddr(&ia->ipaddr))
- {
- len = addrbytesptr(&ia->ipaddr, &byte_ptr);
- out_raw(byte_ptr, len, &attrval, "IP4_addr");
- }
- break;
- case INTERNAL_IP4_NETMASK:
- {
- u_int mask;
-#if 0
- char mask[4],bits[8]={0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe};
- int t,m=st->st_connection->that.host_addr.maskbit;
- for (t=0; t<4; t++)
- {
- if (m < 8)
- mask[t] = bits[m];
- else
- mask[t] = 0xff;
- m -= 8;
- }
-#endif
- if (st->st_connection->spd.this.client.maskbits == 0)
- {
- mask = 0;
- }
- else
- {
- mask = 0xffffffff * 1;
- out_raw(&mask, 4, &attrval, "IP4_mask");
- }
- }
- break;
- case INTERNAL_IP4_SUBNET:
- {
- char mask[4];
- char bits[8] = {0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe};
- int t;
- int m = st->st_connection->spd.this.client.maskbits;
-
- for (t = 0; t < 4; t++)
- {
- mask[t] = (m < 8) ? bits[m] : 0xff;
- m -= 8;
- if (m < 0)
- {
- m = 0;
- }
- }
- len = addrbytesptr(&st->st_connection->spd.this.client.addr, &byte_ptr);
- out_raw(byte_ptr, len, &attrval, "IP4_subnet");
- out_raw(mask, sizeof(mask), &attrval, "IP4_submsk");
- }
- break;
- case XAUTH_TYPE:
- break;
- case XAUTH_USER_NAME:
- if (ia->xauth_secret.user_name.ptr != NULL)
- {
- out_raw(ia->xauth_secret.user_name.ptr
- , ia->xauth_secret.user_name.len
- , &attrval, "xauth_user_name");
- }
- break;
- case XAUTH_USER_PASSWORD:
- if (ia->xauth_secret.user_password.ptr != NULL)
- {
- out_raw(ia->xauth_secret.user_password.ptr
- , ia->xauth_secret.user_password.len
- , &attrval, "xauth_user_password");
- }
- break;
- case XAUTH_STATUS:
- break;
- case UNITY_BANNER:
- if (ia->unity_banner != NULL)
- {
- out_raw(ia->unity_banner
- , strlen(ia->unity_banner)
- , &attrval, "UNITY_BANNER");
- }
- break;
- default:
- plog("attempt to send unsupported mode cfg attribute %s."
- , enum_show(&modecfg_attr_names, attr_type));
- break;
- }
- close_output_pbs(&attrval);
- }
- attr_type++;
- attr_set >>= 1;
+ attr.isaat_af_type = ca->type | ISAKMP_ATTR_AF_TLV;
+ out_struct(&attr, &isakmp_modecfg_attribute_desc, &strattr, &attrval);
+ snprintf(buf, BUF_LEN, "%N", configuration_attribute_type_names, ca->type);
+ out_raw(ca->value.ptr, ca->value.len, &attrval, buf);
}
- close_message(&strattr);
+ close_output_pbs(&attrval);
}
-
+ enumerator->destroy(enumerator);
+ close_message(&strattr);
+
modecfg_hash(r_hashval, r_hash_start, rbody->cur, st);
close_message(rbody);
encrypt_message(rbody, st);
@@ -501,7 +429,7 @@ static stf_status modecfg_build_msg(struct state *st, pb_stream *rbody,
* Send ModeCfg message
*/
static stf_status modecfg_send_msg(struct state *st, int isama_type,
- internal_addr_t *ia, linked_list_t *ca_list)
+ linked_list_t *ca_list)
{
pb_stream msg;
pb_stream rbody;
@@ -534,7 +462,7 @@ static stf_status modecfg_send_msg(struct state *st, int isama_type,
}
/* ATTR out with isama_id of 0 */
- modecfg_build_msg(st, &rbody, isama_type, ia, ca_list, 0);
+ modecfg_build_msg(st, &rbody, isama_type, ca_list, 0);
free(st->st_tpacket.ptr);
st->st_tpacket = chunk_create(msg.start, pbs_offset(&msg));
@@ -554,20 +482,17 @@ static stf_status modecfg_send_msg(struct state *st, int isama_type,
/**
* Parse a ModeCfg attribute payload
*/
-static stf_status modecfg_parse_attributes(pb_stream *attrs, internal_addr_t *ia,
- linked_list_t *ca_list)
+static stf_status modecfg_parse_attributes(pb_stream *attrs, linked_list_t *ca_list)
{
struct isakmp_attribute attr;
pb_stream strattr;
- err_t ugh;
+ u_int16_t attr_type;
+ u_int16_t attr_len;
+ chunk_t attr_chunk;
+ modecfg_attribute_t *ca;
while (pbs_left(attrs) >= sizeof(struct isakmp_attribute))
{
- u_int16_t attr_type;
- u_int16_t attr_len;
- chunk_t attr_chunk;
- modecfg_attribute_t *ca;
-
if (!in_struct(&attr, &isakmp_modecfg_attribute_desc, attrs, &strattr))
{
return STF_FAIL;
@@ -581,149 +506,139 @@ static stf_status modecfg_parse_attributes(pb_stream *attrs, internal_addr_t *ia
switch (attr_type)
{
- case INTERNAL_IP4_ADDRESS:
- if (attr_len == 4)
- {
- ugh = initaddr((char *)(strattr.cur), 4, AF_INET, &ia->ipaddr);
- if (ugh != NULL)
+ case INTERNAL_IP4_ADDRESS:
+ case INTERNAL_IP4_NETMASK:
+ case INTERNAL_IP4_DNS:
+ case INTERNAL_IP4_NBNS:
+ case INTERNAL_ADDRESS_EXPIRY:
+ case INTERNAL_IP4_DHCP:
+ if (attr_len != 4 && attr_len != 0)
{
- plog("received invalid virtual IPv4 address: %s", ugh);
+ goto error;
}
- }
- ia->attr_set |= LELEM(attr_type);
- break;
- case INTERNAL_IP4_DNS:
- case INTERNAL_IP4_NBNS:
- if (attr_len == 4)
- {
- attr_chunk = chunk_create(strattr.cur, attr_len);
- ca = modecfg_attribute_create(attr_type, attr_chunk);
- ca_list->insert_last(ca_list, ca);
- }
- break;
- case INTERNAL_IP6_DNS:
- case INTERNAL_IP6_NBNS:
- if (attr_len == 16)
- {
- attr_chunk = chunk_create(strattr.cur, attr_len);
- ca = modecfg_attribute_create(attr_type, attr_chunk);
- ca_list->insert_last(ca_list, ca);
- }
- break;
- case INTERNAL_IP4_NETMASK:
- case INTERNAL_IP4_SUBNET:
- case INTERNAL_ADDRESS_EXPIRY:
- case INTERNAL_IP4_DHCP:
- case INTERNAL_IP6_ADDRESS:
- case INTERNAL_IP6_NETMASK:
- case INTERNAL_IP6_DHCP:
- case SUPPORTED_ATTRIBUTES:
- case INTERNAL_IP6_SUBNET:
- ia->attr_set |= LELEM(attr_type);
- break;
- case APPLICATION_VERSION:
- if (attr_len > 0)
- {
- DBG(DBG_PARSING,
- DBG_log(" '%.*s'", attr_len, strattr.cur)
- )
- }
- ia->attr_set |= LELEM(attr_type);
- break;
- case XAUTH_TYPE:
- ia->xauth_type = attr.isaat_lv;
- ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE);
- break;
- case XAUTH_USER_NAME:
- ia->xauth_secret.user_name = chunk_create(strattr.cur, attr_len);
- ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE);
- break;
- case XAUTH_USER_PASSWORD:
- ia->xauth_secret.user_password = chunk_create(strattr.cur, attr_len);
- ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE);
- break;
- case XAUTH_STATUS:
- ia->xauth_status = attr.isaat_lv;
- ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE);
- break;
- case XAUTH_MESSAGE:
- if (attr_len > 0)
- {
- DBG(DBG_PARSING,
- DBG_log(" '%.*s'", attr_len, strattr.cur)
- )
- }
- /* fall through to set attribute flag */
- case XAUTH_PASSCODE:
- case XAUTH_CHALLENGE:
- case XAUTH_DOMAIN:
- case XAUTH_NEXT_PIN:
- case XAUTH_ANSWER:
- ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE);
- break;
- case UNITY_DDNS_HOSTNAME:
- if (attr_len > 0)
- {
- DBG(DBG_PARSING,
- DBG_log(" '%.*s'", attr_len, strattr.cur)
- )
- }
- /* fall through to set attribute flag */
- case UNITY_BANNER:
- case UNITY_SAVE_PASSWD:
- case UNITY_DEF_DOMAIN:
- case UNITY_SPLITDNS_NAME:
- case UNITY_SPLIT_INCLUDE:
- case UNITY_NATT_PORT:
- case UNITY_LOCAL_LAN:
- case UNITY_PFS:
- case UNITY_FW_TYPE:
- case UNITY_BACKUP_SERVERS:
- ia->unity_attr_set |= LELEM(attr_type - UNITY_BASE);
- break;
- default:
- plog("unsupported ModeCfg attribute %s received."
- , enum_show(&modecfg_attr_names, attr_type));
- break;
+ break;
+ case INTERNAL_IP4_SUBNET:
+ if (attr_len != 8 && attr_len != 0)
+ {
+ goto error;
+ }
+ break;
+ case INTERNAL_IP6_NETMASK:
+ case INTERNAL_IP6_DNS:
+ case INTERNAL_IP6_NBNS:
+ case INTERNAL_IP6_DHCP:
+ if (attr_len != 16 && attr_len != 0)
+ {
+ goto error;
+ }
+ break;
+ case INTERNAL_IP6_ADDRESS:
+ if (attr_len != 17 && attr_len != 16 && attr_len != 0)
+ {
+ goto error;
+ }
+ break;
+ case INTERNAL_IP6_SUBNET:
+ if (attr_len != 17 && attr_len != 0)
+ {
+ goto error;
+ }
+ break;
+ case SUPPORTED_ATTRIBUTES:
+ if (attr_len % 2)
+ {
+ goto error;
+ }
+ break;
+ case APPLICATION_VERSION:
+ break;
+ /* XAUTH attributes */
+ case XAUTH_TYPE:
+ case XAUTH_STATUS:
+ if (!(attr.isaat_af_type & ISAKMP_ATTR_AF_TV))
+ {
+ plog("%N attribute is not TV encoded",
+ configuration_attribute_type_names, attr_type);
+ return STF_FAIL;
+ }
+ case XAUTH_USER_NAME:
+ case XAUTH_USER_PASSWORD:
+ case XAUTH_PASSCODE:
+ case XAUTH_MESSAGE:
+ case XAUTH_CHALLENGE:
+ case XAUTH_DOMAIN:
+ case XAUTH_NEXT_PIN:
+ case XAUTH_ANSWER:
+ break;
+ /* Microsoft attributes */
+ case INTERNAL_IP4_SERVER:
+ case INTERNAL_IP6_SERVER:
+ break;
+ /* Cisco Unity attributes */
+ case UNITY_BANNER:
+ case UNITY_SAVE_PASSWD:
+ case UNITY_DEF_DOMAIN:
+ case UNITY_SPLITDNS_NAME:
+ case UNITY_SPLIT_INCLUDE:
+ case UNITY_NATT_PORT:
+ case UNITY_LOCAL_LAN:
+ case UNITY_PFS:
+ case UNITY_FW_TYPE:
+ case UNITY_BACKUP_SERVERS:
+ case UNITY_DDNS_HOSTNAME:
+ break;
+ default:
+ plog("unknown attribute type (%u)", attr_type);
+ continue;
+ }
+
+ /* add attribute */
+ if (attr.isaat_af_type & ISAKMP_ATTR_AF_TV)
+ {
+ ca = modecfg_attribute_create_tv(attr_type, attr_len);
+ }
+ else
+ {
+ attr_chunk = chunk_create(strattr.cur, attr_len);
+ ca = modecfg_attribute_create(attr_type, attr_chunk);
}
+ ca_list->insert_last(ca_list, ca);
}
return STF_OK;
+
+error:
+ plog("%N attribute has invalid size of %u octets",
+ configuration_attribute_type_names, attr_type, attr_len);
+ return STF_FAIL;
}
/**
* Parse a ModeCfg message
*/
static stf_status modecfg_parse_msg(struct msg_digest *md, int isama_type,
- u_int16_t *isama_id, internal_addr_t *ia,
- linked_list_t *ca_list)
+ u_int16_t *isama_id, linked_list_t *ca_list)
{
+ modecfg_attribute_t *ca;
struct state *const st = md->st;
struct payload_digest *p;
stf_status stat;
st->st_msgid = md->hdr.isa_msgid;
- CHECK_QUICK_HASH(md, modecfg_hash(hash_val
- , hash_pbs->roof
- , md->message_pbs.roof, st)
- , "MODECFG-HASH", "ISAKMP_CFG_MSG");
+ CHECK_QUICK_HASH(md, modecfg_hash(hash_val, hash_pbs->roof,
+ md->message_pbs.roof, st), "MODECFG-HASH", "ISAKMP_CFG_MSG");
/* process the ModeCfg payloads received */
for (p = md->chain[ISAKMP_NEXT_ATTR]; p != NULL; p = p->next)
{
- internal_addr_t ia_candidate;
-
- init_internal_addr(&ia_candidate);
-
if (p->payload.attribute.isama_type == isama_type)
{
*isama_id = p->payload.attribute.isama_identifier;
- stat = modecfg_parse_attributes(&p->pbs, &ia_candidate, ca_list);
+ stat = modecfg_parse_attributes(&p->pbs, ca_list);
if (stat == STF_OK)
{
/* return with a valid set of attributes */
- *ia = ia_candidate;
return STF_OK;
}
}
@@ -733,63 +648,61 @@ static stf_status modecfg_parse_msg(struct msg_digest *md, int isama_type,
, enum_name(&attr_msg_type_names, isama_type)
, enum_name(&attr_msg_type_names, p->payload.attribute.isama_type));
- stat = modecfg_parse_attributes(&p->pbs, &ia_candidate, ca_list);
+ stat = modecfg_parse_attributes(&p->pbs, ca_list);
}
+
+ /* abort if a parsing error occurred */
if (stat != STF_OK)
{
+ ca_list->destroy_function(ca_list, (void*)modecfg_attribute_destroy);
return stat;
}
+
+ /* discard the parsed attributes and look for another payload */
+ while (ca_list->remove_last(ca_list, (void **)&ca) == SUCCESS) {}
}
return STF_IGNORE;
}
/**
- * Send ModeCfg request message from client to server in pull mode
+ * Used in ModeCfg pull mode on the client (initiator)
+ * called in demux.c
+ * client -> CFG_REQUEST
+ * STF_OK transitions to STATE_MODE_CFG_I1
*/
stf_status modecfg_send_request(struct state *st)
{
connection_t *c = st->st_connection;
stf_status stat;
- internal_addr_t ia;
- attribute_handler_t *handler;
- configuration_attribute_type_t type;
- chunk_t data;
- host_t *vip;
+ modecfg_attribute_t *ca;
enumerator_t *enumerator;
+ int family;
+ chunk_t value;
+ host_t *vip;
+ linked_list_t *ca_list = linked_list_create();
- init_internal_addr(&ia);
-
- ia.attr_set = LELEM(INTERNAL_IP4_ADDRESS)
- | LELEM(INTERNAL_IP4_NETMASK);
- ia.ipaddr = c->spd.this.host_srcip;
- vip = host_create_from_sockaddr((sockaddr_t*)&ia.ipaddr);
-
- /* add configuration attributes requested by handlers */
- enumerator = hydra->attributes->create_initiator_enumerator(
- hydra->attributes,c->spd.that.id, vip);
- while (enumerator->enumerate(enumerator, &handler, &type, &data))
+ vip = c->spd.this.host_srcip;
+ value = vip->is_anyaddr(vip) ? chunk_empty : vip->get_address(vip);
+ family = vip->get_family(vip);
+ ca = modecfg_attribute_create((family == AF_INET) ?
+ INTERNAL_IP4_ADDRESS : INTERNAL_IP6_ADDRESS,
+ value);
+ ca_list->insert_last(ca_list, ca);
+
+ register_attribute_handlers(c);
+ enumerator = c->requested->create_enumerator(c->requested);
+ while (enumerator->enumerate(enumerator, &ca))
{
- modecfg_attribute_t *ca;
-
- /* create configuration attribute request and link to handler */
- DBG(DBG_CONTROLMORE,
- DBG_log("building %N attribute", configuration_attribute_type_names, type)
- )
- ca = modecfg_attribute_create(type, data);
- ca->handler = handler;
-
- if (c->requested == NULL)
- {
- c->requested = linked_list_create();
- }
- c->requested->insert_last(c->requested, ca);
+ ca = modecfg_attribute_create(ca->type, chunk_empty);
+ ca_list->insert_last(ca_list, ca);
}
enumerator->destroy(enumerator);
- vip->destroy(vip);
plog("sending ModeCfg request");
+
st->st_state = STATE_MODE_CFG_I1;
- stat = modecfg_send_msg(st, ISAKMP_CFG_REQUEST, &ia, c->requested);
+ stat = modecfg_send_msg(st, ISAKMP_CFG_REQUEST, ca_list);
+ ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy);
if (stat == STF_OK)
{
st->st_modecfg.started = TRUE;
@@ -797,56 +710,35 @@ stf_status modecfg_send_request(struct state *st)
return stat;
}
-/* STATE_MODE_CFG_R0:
- * HDR*, HASH, ATTR(REQ=IP) --> HDR*, HASH, ATTR(REPLY=IP)
- *
- * used in ModeCfg pull mode, on the server (responder)
+/**
+ * Used in ModeCfg pull mode on the server (responder)
+ * called in demux.c from STATE_MODE_CFG_R0
+ * server <- CFG_REQUEST
+ * server -> CFG_REPLY
+ * STF_OK transitions to STATE_MODE_CFG_R0
*/
stf_status modecfg_inR0(struct msg_digest *md)
{
struct state *const st = md->st;
u_int16_t isama_id;
- internal_addr_t ia;
- bool want_unity_banner;
stf_status stat, stat_build;
- host_t *requested_vip;
linked_list_t *ca_list = linked_list_create();
- stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, &ia, ca_list);
+ plog("parsing ModeCfg request");
+
+ stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, ca_list);
if (stat != STF_OK)
{
return stat;
}
- if (ia.attr_set & LELEM(INTERNAL_IP4_ADDRESS))
- {
- requested_vip = host_create_from_sockaddr((sockaddr_t*)&ia.ipaddr);
- }
- else
- {
- requested_vip = host_create_any(AF_INET);
- }
- plog("peer requested virtual IP %H", requested_vip);
-
- want_unity_banner = (ia.unity_attr_set & LELEM(UNITY_BANNER - UNITY_BASE)) != LEMPTY;
- ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy);
-
/* build the CFG_REPLY */
- ca_list = linked_list_create();
- init_internal_addr(&ia);
- get_internal_addr(st->st_connection, requested_vip, &ia, ca_list);
- requested_vip->destroy(requested_vip);
-
- if (want_unity_banner)
- {
- ia.unity_banner = UNITY_BANNER_STR;
- ia.unity_attr_set |= LELEM(UNITY_BANNER - UNITY_BASE);
- }
+ get_attributes(st->st_connection, ca_list);
plog("sending ModeCfg reply");
stat_build = modecfg_build_msg(st, &md->rbody, ISAKMP_CFG_REPLY,
- &ia, ca_list, isama_id);
+ ca_list, isama_id);
ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy);
if (stat_build != STF_OK)
@@ -857,56 +749,49 @@ stf_status modecfg_inR0(struct msg_digest *md)
return STF_OK;
}
-/* STATE_MODE_CFG_I1:
- * HDR*, HASH, ATTR(REPLY=IP)
- *
- * used in ModeCfg pull mode, on the client (initiator)
+/**
+ * Used in ModeCfg pull mode on the client (initiator)
+ * called in demux.c from STATE_MODE_CFG_I1
+ * client <- CFG_REPLY
+ * STF_OK transitions to STATE_MODE_CFG_I2
*/
stf_status modecfg_inI1(struct msg_digest *md)
{
struct state *const st = md->st;
u_int16_t isama_id;
- internal_addr_t ia;
stf_status stat;
linked_list_t *ca_list = linked_list_create();
plog("parsing ModeCfg reply");
- stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, &ia, ca_list);
+ stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, ca_list);
if (stat != STF_OK)
{
return stat;
}
- st->st_modecfg.vars_set = set_internal_addr(st->st_connection, &ia, ca_list);
+ st->st_modecfg.vars_set = set_attributes(st->st_connection, ca_list);
st->st_msgid = 0;
ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy);
return STF_OK;
}
-
/**
- * Send ModeCfg set message from server to client in push mode
+ * Used in ModeCfg push mode on the server (responder)
+ * called in demux.c
+ * server -> CFG_SET
+ * STF_OK transitions to STATE_MODE_CFG_R3
*/
stf_status modecfg_send_set(struct state *st)
{
stf_status stat;
- internal_addr_t ia;
- host_t *vip;
linked_list_t *ca_list = linked_list_create();
- init_internal_addr(&ia);
- vip = host_create_any(AF_INET);
- get_internal_addr(st->st_connection, vip, &ia, ca_list);
- vip->destroy(vip);
-#ifdef CISCO_QUIRKS
- ia.unity_banner = UNITY_BANNER_STR;
- ia.unity_attr_set |= LELEM(UNITY_BANNER - UNITY_BASE);
-#endif
+ plog("sending ModeCfg set");
- plog("sending ModeCfg set");
+ get_attributes(st->st_connection, ca_list);
st->st_state = STATE_MODE_CFG_R3;
- stat = modecfg_send_msg(st, ISAKMP_CFG_SET, &ia, ca_list);
+ stat = modecfg_send_msg(st, ISAKMP_CFG_SET, ca_list);
ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy);
if (stat == STF_OK)
{
@@ -915,43 +800,64 @@ stf_status modecfg_send_set(struct state *st)
return stat;
}
-/* STATE_MODE_CFG_I0:
- * HDR*, HASH, ATTR(SET=IP) --> HDR*, HASH, ATTR(ACK,OK)
- *
- * used in ModeCfg push mode, on the client (initiator).
+/**
+ * Used in ModeCfg push mode on the client (initiator)
+ * called in demux.c from STATE_MODE_CFG_I0
+ * client <- CFG_SET
+ * client -> CFG_ACK
+ * STF_OK transitions to STATE_MODE_CFG_I3
*/
stf_status modecfg_inI0(struct msg_digest *md)
{
struct state *const st = md->st;
u_int16_t isama_id;
- internal_addr_t ia;
- lset_t attr_set, unity_attr_set;
stf_status stat, stat_build;
- linked_list_t *ca_list = linked_list_create();
+ modecfg_attribute_t *ca;
+ linked_list_t *ca_list, *ca_ack_list;
plog("parsing ModeCfg set");
- stat = modecfg_parse_msg(md, ISAKMP_CFG_SET, &isama_id, &ia, ca_list);
- ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy);
-
+ ca_list = linked_list_create();
+ stat = modecfg_parse_msg(md, ISAKMP_CFG_SET, &isama_id, ca_list);
if (stat != STF_OK)
{
return stat;
}
- st->st_modecfg.vars_set = set_internal_addr(st->st_connection, &ia, ca_list);
+ register_attribute_handlers(st->st_connection);
+ st->st_modecfg.vars_set = set_attributes(st->st_connection, ca_list);
/* prepare ModeCfg ack which sends zero length attributes */
- attr_set = ia.attr_set;
- unity_attr_set = ia.unity_attr_set;
- init_internal_addr(&ia);
- ia.attr_set = attr_set & SUPPORTED_ATTR_SET;
- ia.unity_attr_set = unity_attr_set & SUPPORTED_UNITY_ATTR_SET;
+ ca_ack_list = linked_list_create();
+ while (ca_list->remove_last(ca_list, (void **)&ca) == SUCCESS)
+ {
+ switch (ca->type)
+ {
+ case INTERNAL_IP4_ADDRESS:
+ case INTERNAL_IP4_DNS:
+ case INTERNAL_IP4_NBNS:
+ case APPLICATION_VERSION:
+ case INTERNAL_IP6_ADDRESS:
+ case INTERNAL_IP6_DNS:
+ case INTERNAL_IP6_NBNS:
+#ifdef CISCO_QUIRKS
+ case UNITY_BANNER:
+#endif
+ /* supported attributes */
+ ca->value.len = 0;
+ ca_ack_list->insert_last(ca_ack_list, ca);
+ break;
+ default:
+ /* unsupportd attributes */
+ modecfg_attribute_destroy(ca);
+ }
+ }
+ ca_list->destroy(ca_list);
plog("sending ModeCfg ack");
stat_build = modecfg_build_msg(st, &md->rbody, ISAKMP_CFG_ACK,
- &ia, ca_list, isama_id);
- ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy);
+ ca_ack_list, isama_id);
+ ca_ack_list->destroy_function(ca_ack_list, (void *)modecfg_attribute_destroy);
if (stat_build != STF_OK)
{
return stat_build;
@@ -960,22 +866,22 @@ stf_status modecfg_inI0(struct msg_digest *md)
return STF_OK;
}
-/* STATE_MODE_CFG_R3:
- * HDR*, HASH, ATTR(ACK,OK)
- *
- * used in ModeCfg push mode, on the server (responder)
+/**
+ * Used in ModeCfg push mode on the server (responder)
+ * called in demux.c from STATE_MODE_CFG_R3
+ * server <- CFG_ACK
+ * STF_OK transitions to STATE_MODE_CFG_R4
*/
stf_status modecfg_inR3(struct msg_digest *md)
{
struct state *const st = md->st;
u_int16_t isama_id;
- internal_addr_t ia;
stf_status stat;
linked_list_t *ca_list = linked_list_create();
plog("parsing ModeCfg ack");
- stat = modecfg_parse_msg(md, ISAKMP_CFG_ACK, &isama_id, &ia, ca_list);
+ stat = modecfg_parse_msg(md, ISAKMP_CFG_ACK, &isama_id, ca_list);
ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy);
if (stat != STF_OK)
{
@@ -986,21 +892,25 @@ stf_status modecfg_inR3(struct msg_digest *md)
}
/**
- * Send XAUTH credentials request (username + password)
+ * Used on the XAUTH server (responder)
+ * called in demux.c
+ * server -> CFG_REQUEST
+ * STF_OK transitions to STATE_XAUTH_R1
*/
stf_status xauth_send_request(struct state *st)
{
stf_status stat;
- internal_addr_t ia;
+ modecfg_attribute_t *ca;
linked_list_t *ca_list = linked_list_create();
- init_internal_addr(&ia);
- ia.xauth_attr_set = LELEM(XAUTH_USER_NAME - XAUTH_BASE)
- | LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE);
+ ca = modecfg_attribute_create(XAUTH_USER_NAME, chunk_empty);
+ ca_list->insert_last(ca_list, ca);
+ ca = modecfg_attribute_create(XAUTH_USER_PASSWORD, chunk_empty);
+ ca_list->insert_last(ca_list, ca);
plog("sending XAUTH request");
st->st_state = STATE_XAUTH_R1;
- stat = modecfg_send_msg(st, ISAKMP_CFG_REQUEST, &ia, ca_list);
+ stat = modecfg_send_msg(st, ISAKMP_CFG_REQUEST, ca_list);
ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy);
if (stat == STF_OK)
{
@@ -1009,55 +919,85 @@ stf_status xauth_send_request(struct state *st)
return stat;
}
-/* STATE_XAUTH_I0:
- * HDR*, HASH, ATTR(REQ) --> HDR*, HASH, ATTR(REPLY=USERNAME/PASSWORD)
- *
- * used on the XAUTH client (initiator)
+/**
+ * Used on the XAUTH client (initiator)
+ * called in demux.c from STATE_XAUTH_I0
+ * client <- CFG_REQUEST
+ * client -> CFG_REPLY
+ * STF_OK transitions to STATE_XAUTH_I1
*/
stf_status xauth_inI0(struct msg_digest *md)
{
struct state *const st = md->st;
u_int16_t isama_id;
- internal_addr_t ia;
stf_status stat, stat_build;
- bool xauth_type_present;
+ modecfg_attribute_t *ca;
+ bool xauth_user_name = FALSE;
+ bool xauth_user_password = FALSE;
+ bool xauth_type_present = FALSE;
+ xauth_t xauth_secret;
linked_list_t *ca_list = linked_list_create();
plog("parsing XAUTH request");
- stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, &ia, ca_list);
- ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy);
+ stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, ca_list);
if (stat != STF_OK)
{
return stat;
}
- /* check XAUTH attributes */
- xauth_type_present = (ia.xauth_attr_set & LELEM(XAUTH_TYPE - XAUTH_BASE)) != LEMPTY;
-
- if (xauth_type_present && ia.xauth_type != XAUTH_TYPE_GENERIC)
+ while (ca_list->remove_last(ca_list, (void **)&ca) == SUCCESS)
{
- plog("xauth type %s is not supported", enum_name(&xauth_type_names, ia.xauth_type));
- stat = STF_FAIL;
+ switch (ca->type)
+ {
+ case XAUTH_TYPE:
+ if (ca->value.len != XAUTH_TYPE_GENERIC)
+ {
+ plog("xauth type %s is not supported",
+ enum_name(&xauth_type_names, ca->value.len));
+ stat = STF_FAIL;
+ }
+ else
+ {
+ xauth_type_present = TRUE;
+ }
+ break;
+ case XAUTH_USER_NAME:
+ xauth_user_name = TRUE;
+ break;
+ case XAUTH_USER_PASSWORD:
+ xauth_user_password = TRUE;
+ break;
+ case XAUTH_MESSAGE:
+ if (ca->value.len)
+ {
+ DBG(DBG_PARSING | DBG_CONTROLMORE,
+ DBG_log(" '%.*s'", ca->value.len, ca->value.ptr)
+ )
+ }
+ break;
+ default:
+ break;
+ }
+ modecfg_attribute_destroy(ca);
}
- else if ((ia.xauth_attr_set & LELEM(XAUTH_USER_NAME - XAUTH_BASE)) == LEMPTY)
+
+ if (!xauth_user_name)
{
plog("user name attribute is missing in XAUTH request");
stat = STF_FAIL;
}
- else if ((ia.xauth_attr_set & LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE)) == LEMPTY)
+ if (!xauth_user_password)
{
plog("user password attribute is missing in XAUTH request");
stat = STF_FAIL;
}
/* prepare XAUTH reply */
- init_internal_addr(&ia);
-
if (stat == STF_OK)
{
/* get user credentials using a plugin function */
- if (!xauth_module.get_secret(&ia.xauth_secret))
+ if (!xauth_module.get_secret(&xauth_secret))
{
plog("xauth user credentials not found");
stat = STF_FAIL;
@@ -1065,33 +1005,33 @@ stf_status xauth_inI0(struct msg_digest *md)
}
if (stat == STF_OK)
{
+ if (xauth_type_present)
+ {
+ ca = modecfg_attribute_create_tv(XAUTH_TYPE, XAUTH_TYPE_GENERIC);
+ ca_list->insert_last(ca_list, ca);
+ }
DBG(DBG_CONTROL,
- DBG_log("my xauth user name is '%.*s'"
- , ia.xauth_secret.user_name.len
- , ia.xauth_secret.user_name.ptr)
+ DBG_log("my xauth user name is '%.*s'", xauth_secret.user_name.len,
+ xauth_secret.user_name.ptr)
)
+ ca = modecfg_attribute_create(XAUTH_USER_NAME, xauth_secret.user_name);
+ ca_list->insert_last(ca_list, ca);
DBG(DBG_PRIVATE,
- DBG_log("my xauth user password is '%.*s'"
- , ia.xauth_secret.user_password.len
- , ia.xauth_secret.user_password.ptr)
+ DBG_log("my xauth user password is '%.*s'", xauth_secret.user_password.len,
+ xauth_secret.user_password.ptr)
)
- ia.xauth_attr_set = LELEM(XAUTH_USER_NAME - XAUTH_BASE)
- | LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE);
- if (xauth_type_present)
- {
- ia.xauth_attr_set |= LELEM(XAUTH_TYPE - XAUTH_BASE);
- }
+ ca = modecfg_attribute_create(XAUTH_USER_PASSWORD, xauth_secret.user_password);
+ ca_list->insert_last(ca_list, ca);
}
else
{
- ia.xauth_attr_set = LELEM(XAUTH_STATUS - XAUTH_BASE);
- ia.xauth_status = XAUTH_STATUS_FAIL;
+ ca = modecfg_attribute_create_tv(XAUTH_STATUS, XAUTH_STATUS_FAIL);
+ ca_list->insert_last(ca_list, ca);
}
plog("sending XAUTH reply");
-
stat_build = modecfg_build_msg(st, &md->rbody, ISAKMP_CFG_REPLY,
- &ia, ca_list, isama_id);
+ ca_list, isama_id);
ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy);
if (stat_build != STF_OK)
{
@@ -1115,45 +1055,71 @@ stf_status xauth_inI0(struct msg_digest *md)
}
}
-/* STATE_XAUTH_R1:
- * HDR*, HASH, ATTR(REPLY=USERNAME/PASSWORD) --> HDR*, HASH, ATTR(STATUS)
- *
- * used on the XAUTH server (responder)
+/**
+ * Used on the XAUTH server (responder)
+ * called in demux.c from STATE_XAUTH_R1
+ server <- CFG_REPLY
+ server -> CFG_SET
+ STF_OK transitions to STATE_XAUTH_R2
*/
stf_status xauth_inR1(struct msg_digest *md)
{
struct state *const st = md->st;
u_int16_t isama_id;
- internal_addr_t ia;
stf_status stat, stat_build;
+ xauth_t xauth_secret;
+ int xauth_status = XAUTH_STATUS_OK;
+ modecfg_attribute_t *ca;
linked_list_t *ca_list = linked_list_create();
plog("parsing XAUTH reply");
- stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, &ia, ca_list);
- ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy);
+ stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, ca_list);
if (stat != STF_OK)
{
return stat;
}
+ /* initialize xauth_secret */
+ xauth_secret.user_name = chunk_empty;
+ xauth_secret.user_password = chunk_empty;
+
+ while (ca_list->remove_last(ca_list, (void **)&ca) == SUCCESS)
+ {
+ switch (ca->type)
+ {
+ case XAUTH_STATUS:
+ xauth_status = ca->value.len;
+ break;
+ case XAUTH_USER_NAME:
+ xauth_secret.user_name = chunk_clone(ca->value);
+ break;
+ case XAUTH_USER_PASSWORD:
+ xauth_secret.user_password = chunk_clone(ca->value);
+ break;
+ default:
+ break;
+ }
+ modecfg_attribute_destroy(ca);
+ }
/* did the client return an XAUTH FAIL status? */
- if ((ia.xauth_attr_set & LELEM(XAUTH_STATUS - XAUTH_BASE)) != LEMPTY)
+ if (xauth_status == XAUTH_STATUS_FAIL)
{
plog("received FAIL status in XAUTH reply");
/* client is not able to do XAUTH, delete ISAKMP SA */
delete_state(st);
+ ca_list->destroy(ca_list);
return STF_IGNORE;
}
/* check XAUTH reply */
- if ((ia.xauth_attr_set & LELEM(XAUTH_USER_NAME - XAUTH_BASE)) == LEMPTY)
+ if (xauth_secret.user_name.ptr == NULL)
{
plog("user name attribute is missing in XAUTH reply");
st->st_xauth.status = FALSE;
}
- else if ((ia.xauth_attr_set & LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE)) == LEMPTY)
+ else if (xauth_secret.user_password.ptr == NULL)
{
plog("user password attribute is missing in XAUTH reply");
st->st_xauth.status = FALSE;
@@ -1164,33 +1130,28 @@ stf_status xauth_inR1(struct msg_digest *md)
peer.conn_name = st->st_connection->name;
addrtot(&md->sender, 0, peer.ip_address, sizeof(peer.ip_address));
- snprintf(peer.id, sizeof(peer.id), "%Y",
- md->st->st_connection->spd.that.id);
+ snprintf(peer.id, sizeof(peer.id), "%Y", md->st->st_connection->spd.that.id);
DBG(DBG_CONTROL,
- DBG_log("peer xauth user name is '%.*s'"
- , ia.xauth_secret.user_name.len
- , ia.xauth_secret.user_name.ptr)
+ DBG_log("peer xauth user name is '%.*s'", xauth_secret.user_name.len,
+ xauth_secret.user_name.ptr)
)
DBG(DBG_PRIVATE,
- DBG_log("peer xauth user password is '%.*s'"
- , ia.xauth_secret.user_password.len
- , ia.xauth_secret.user_password.ptr)
+ DBG_log("peer xauth user password is '%.*s'", xauth_secret.user_password.len,
+ xauth_secret.user_password.ptr)
)
/* verify the user credentials using a plugin function */
- st->st_xauth.status = xauth_module.verify_secret(&peer, &ia.xauth_secret);
+ st->st_xauth.status = xauth_module.verify_secret(&peer, &xauth_secret);
plog("extended authentication %s", st->st_xauth.status? "was successful":"failed");
}
-
- /* prepare XAUTH set which sends the authentication status */
- init_internal_addr(&ia);
- ia.xauth_attr_set = LELEM(XAUTH_STATUS - XAUTH_BASE);
- ia.xauth_status = (st->st_xauth.status)? XAUTH_STATUS_OK : XAUTH_STATUS_FAIL;
- ca_list = linked_list_create();
-
- plog("sending XAUTH status:");
-
- stat_build = modecfg_send_msg(st, ISAKMP_CFG_SET, &ia, ca_list);
+ chunk_clear(&xauth_secret.user_name);
+ chunk_clear(&xauth_secret.user_password);
+
+ plog("sending XAUTH status");
+ xauth_status = (st->st_xauth.status) ? XAUTH_STATUS_OK : XAUTH_STATUS_FAIL;
+ ca = modecfg_attribute_create_tv(XAUTH_STATUS, xauth_status);
+ ca_list->insert_last(ca_list, ca);
+ stat_build = modecfg_send_msg(st, ISAKMP_CFG_SET, ca_list);
ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy);
if (stat_build != STF_OK)
{
@@ -1199,22 +1160,23 @@ stf_status xauth_inR1(struct msg_digest *md)
return STF_OK;
}
-/* STATE_XAUTH_I1:
- * HDR*, HASH, ATTR(STATUS) --> HDR*, HASH, ATTR(ACK)
- *
- * used on the XAUTH client (initiator)
+/**
+ * Used on the XAUTH client (initiator)
+ * called in demux.c from STATE_XAUTH_I1
+ * client <- CFG_SET
+ * client -> CFG_ACK
+ * STF_OK transitions to STATE_XAUTH_I2
*/
stf_status xauth_inI1(struct msg_digest *md)
{
struct state *const st = md->st;
u_int16_t isama_id;
- internal_addr_t ia;
stf_status stat, stat_build;
+ modecfg_attribute_t *ca;
linked_list_t *ca_list = linked_list_create();
plog("parsing XAUTH status");
- stat = modecfg_parse_msg(md, ISAKMP_CFG_SET, &isama_id, &ia, ca_list);
- ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy);
+ stat = modecfg_parse_msg(md, ISAKMP_CFG_SET, &isama_id, ca_list);
if (stat != STF_OK)
{
/* notification payload - not exactly the right choice, but okay */
@@ -1222,14 +1184,21 @@ stf_status xauth_inI1(struct msg_digest *md)
return stat;
}
- st->st_xauth.status = ia.xauth_status;
+ st->st_xauth.status = FALSE;
+ while (ca_list->remove_last(ca_list, (void **)&ca) == SUCCESS)
+ {
+ if (ca->type == XAUTH_STATUS)
+ {
+ st->st_xauth.status = (ca->value.len == XAUTH_STATUS_OK);
+ }
+ modecfg_attribute_destroy(ca);
+ }
plog("extended authentication %s", st->st_xauth.status? "was successful":"failed");
plog("sending XAUTH ack");
- init_internal_addr(&ia);
- stat_build = modecfg_build_msg(st, &md->rbody, ISAKMP_CFG_ACK,
- &ia, ca_list, isama_id);
- ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy);
+ stat_build = modecfg_build_msg(st, &md->rbody, ISAKMP_CFG_ACK, ca_list, isama_id);
+ ca_list->destroy(ca_list);
+
if (stat_build != STF_OK)
{
return stat_build;
@@ -1251,27 +1220,27 @@ stf_status xauth_inI1(struct msg_digest *md)
}
}
-/* STATE_XAUTH_R2:
- * HDR*, ATTR(STATUS), HASH --> Done
- *
- * used on the XAUTH server (responder)
+/**
+ * Used on the XAUTH server (responder)
+ * called in demux.c from STATE_XAUTH_R2
+ * server <- CFG_ACK
+ * STF_OK transitions to STATE_XAUTH_R3
*/
stf_status xauth_inR2(struct msg_digest *md)
{
struct state *const st = md->st;
u_int16_t isama_id;
- internal_addr_t ia;
stf_status stat;
linked_list_t *ca_list = linked_list_create();
plog("parsing XAUTH ack");
- stat = modecfg_parse_msg(md, ISAKMP_CFG_ACK, &isama_id, &ia, ca_list);
- ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy);
+ stat = modecfg_parse_msg(md, ISAKMP_CFG_ACK, &isama_id, ca_list);
if (stat != STF_OK)
{
return stat;
}
+ ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy);
st->st_msgid = 0;
if (st->st_xauth.status)
{
diff --git a/src/pluto/modecfg.h b/src/pluto/modecfg.h
index 8ed5de9a5..7adf18682 100644
--- a/src/pluto/modecfg.h
+++ b/src/pluto/modecfg.h
@@ -34,6 +34,11 @@ struct modecfg_attribute_t {
u_int16_t type;
/**
+ * Attribute is coded as TV
+ */
+ bool is_tv;
+
+ /**
* Attribute value as chunk.
*/
chunk_t value;