summaryrefslogtreecommitdiff
path: root/src/charon/sa/tasks/ike_config.c
diff options
context:
space:
mode:
authorRene Mayrhofer <rene@mayrhofer.eu.org>2010-02-23 10:42:46 +0000
committerRene Mayrhofer <rene@mayrhofer.eu.org>2010-02-23 10:42:46 +0000
commitde6b12502cdf42d5d92118f1c0e38dc31becf7c5 (patch)
tree0edac9c79f5a43e01913dd7f71c7abc487e5727b /src/charon/sa/tasks/ike_config.c
parent172642669d4a23e17f1ed411fbc8629dcaa5fb46 (diff)
downloadvyos-strongswan-de6b12502cdf42d5d92118f1c0e38dc31becf7c5.tar.gz
vyos-strongswan-de6b12502cdf42d5d92118f1c0e38dc31becf7c5.zip
Updated to new upstream release. interfaces Patch is not from upstream.
Diffstat (limited to 'src/charon/sa/tasks/ike_config.c')
-rw-r--r--src/charon/sa/tasks/ike_config.c276
1 files changed, 189 insertions, 87 deletions
diff --git a/src/charon/sa/tasks/ike_config.c b/src/charon/sa/tasks/ike_config.c
index 1f75521b6..f010439fe 100644
--- a/src/charon/sa/tasks/ike_config.c
+++ b/src/charon/sa/tasks/ike_config.c
@@ -19,50 +19,60 @@
#include <daemon.h>
#include <encoding/payloads/cp_payload.h>
-#define DNS_SERVER_MAX 2
-#define NBNS_SERVER_MAX 2
-
typedef struct private_ike_config_t private_ike_config_t;
/**
* Private members of a ike_config_t task.
*/
struct private_ike_config_t {
-
+
/**
* Public methods and task_t interface.
*/
ike_config_t public;
-
+
/**
* Assigned IKE_SA.
*/
ike_sa_t *ike_sa;
-
+
/**
* Are we the initiator?
*/
bool initiator;
-
+
/**
* virtual ip
*/
host_t *virtual_ip;
+
+ /**
+ * list of attributes requested and its handler, entry_t
+ */
+ linked_list_t *requested;
};
/**
- * build INTERNAL_IPV4/6_ADDRESS from virtual ip
+ * Entry for a requested attribute and the requesting handler
+ */
+typedef struct {
+ /** attribute requested */
+ configuration_attribute_type_t type;
+ /** handler requesting this attribute */
+ attribute_handler_t *handler;
+} entry_t;
+
+/**
+ * build INTERNAL_IPV4/6_ADDRESS attribute from virtual ip
*/
-static void build_vip(private_ike_config_t *this, host_t *vip, cp_payload_t *cp)
+static configuration_attribute_t *build_vip(host_t *vip)
{
- configuration_attribute_t *ca;
+ configuration_attribute_type_t type;
chunk_t chunk, prefix;
-
- ca = configuration_attribute_create();
-
+
if (vip->get_family(vip) == AF_INET)
{
- ca->set_type(ca, INTERNAL_IP4_ADDRESS);
+ type = INTERNAL_IP4_ADDRESS;
if (vip->is_anyaddr(vip))
{
chunk = chunk_empty;
@@ -74,7 +84,7 @@ static void build_vip(private_ike_config_t *this, host_t *vip, cp_payload_t *cp)
}
else
{
- ca->set_type(ca, INTERNAL_IP6_ADDRESS);
+ type = INTERNAL_IP6_ADDRESS;
if (vip->is_anyaddr(vip))
{
chunk = chunk_empty;
@@ -87,8 +97,42 @@ static void build_vip(private_ike_config_t *this, host_t *vip, cp_payload_t *cp)
chunk = chunk_cata("cc", chunk, prefix);
}
}
- ca->set_value(ca, chunk);
- cp->add_configuration_attribute(cp, ca);
+ return configuration_attribute_create_value(type, chunk);
+}
+
+/**
+ * Handle a received attribute as initiator
+ */
+static void handle_attribute(private_ike_config_t *this,
+ configuration_attribute_t *ca)
+{
+ attribute_handler_t *handler = NULL;
+ enumerator_t *enumerator;
+ entry_t *entry;
+
+ /* find the handler which requested this attribute */
+ enumerator = this->requested->create_enumerator(this->requested);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->type == ca->get_type(ca))
+ {
+ handler = entry->handler;
+ this->requested->remove_at(this->requested, enumerator);
+ free(entry);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ /* and pass it to the handle function */
+ handler = lib->attributes->handle(lib->attributes,
+ this->ike_sa->get_other_id(this->ike_sa), handler,
+ ca->get_type(ca), ca->get_value(ca));
+ if (handler)
+ {
+ this->ike_sa->add_configuration_attribute(this->ike_sa,
+ handler, ca->get_type(ca), ca->get_value(ca));
+ }
}
/**
@@ -100,7 +144,7 @@ static void process_attribute(private_ike_config_t *this,
host_t *ip;
chunk_t addr;
int family = AF_INET6;
-
+
switch (ca->get_type(ca))
{
case INTERNAL_IP4_ADDRESS:
@@ -118,7 +162,7 @@ static void process_attribute(private_ike_config_t *this,
/* skip prefix byte in IPv6 payload*/
if (family == AF_INET6)
{
- addr.len--;
+ addr.len--;
}
ip = host_create_from_chunk(family, addr, 0);
}
@@ -130,15 +174,12 @@ static void process_attribute(private_ike_config_t *this,
break;
}
default:
+ {
if (this->initiator)
{
- this->ike_sa->add_configuration_attribute(this->ike_sa,
- ca->get_type(ca), ca->get_value(ca));
- }
- else
- {
- /* we do not handle attribute requests other than for VIPs */
+ handle_attribute(this, ca);
}
+ }
}
}
@@ -147,10 +188,9 @@ static void process_attribute(private_ike_config_t *this,
*/
static void process_payloads(private_ike_config_t *this, message_t *message)
{
- enumerator_t *enumerator;
- iterator_t *attributes;
+ enumerator_t *enumerator, *attributes;
payload_t *payload;
-
+
enumerator = message->create_payload_enumerator(message);
while (enumerator->enumerate(enumerator, &payload))
{
@@ -158,22 +198,25 @@ static void process_payloads(private_ike_config_t *this, message_t *message)
{
cp_payload_t *cp = (cp_payload_t*)payload;
configuration_attribute_t *ca;
- switch (cp->get_config_type(cp))
+
+ switch (cp->get_type(cp))
{
case CFG_REQUEST:
case CFG_REPLY:
{
- attributes = cp->create_attribute_iterator(cp);
- while (attributes->iterate(attributes, (void**)&ca))
+ attributes = cp->create_attribute_enumerator(cp);
+ while (attributes->enumerate(attributes, &ca))
{
+ DBG2(DBG_IKE, "processing %N attribute",
+ configuration_attribute_type_names, ca->get_type(ca));
process_attribute(this, ca);
}
attributes->destroy(attributes);
break;
}
default:
- DBG1(DBG_IKE, "ignoring %N config payload",
- config_type_names, cp->get_config_type(cp));
+ DBG1(DBG_IKE, "ignoring %N config payload",
+ config_type_names, cp->get_type(cp));
break;
}
}
@@ -188,9 +231,14 @@ static status_t build_i(private_ike_config_t *this, message_t *message)
{
if (message->get_message_id(message) == 1)
{ /* in first IKE_AUTH only */
+ cp_payload_t *cp = NULL;
+ enumerator_t *enumerator;
+ attribute_handler_t *handler;
peer_cfg_t *config;
+ configuration_attribute_type_t type;
+ chunk_t data;
host_t *vip;
-
+
/* reuse virtual IP if we already have one */
vip = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
if (!vip)
@@ -200,25 +248,38 @@ static status_t build_i(private_ike_config_t *this, message_t *message)
}
if (vip)
{
+ cp = cp_payload_create_type(CFG_REQUEST);
+ cp->add_attribute(cp, build_vip(vip));
+ }
+
+ enumerator = lib->attributes->create_initiator_enumerator(lib->attributes,
+ this->ike_sa->get_other_id(this->ike_sa), vip);
+ while (enumerator->enumerate(enumerator, &handler, &type, &data))
+ {
configuration_attribute_t *ca;
- cp_payload_t *cp;
-
- cp = cp_payload_create();
- cp->set_config_type(cp, CFG_REQUEST);
-
- build_vip(this, vip, cp);
-
- /* we currently always add a DNS request if we request an IP */
- ca = configuration_attribute_create();
- if (vip->get_family(vip) == AF_INET)
- {
- ca->set_type(ca, INTERNAL_IP4_DNS);
- }
- else
+ entry_t *entry;
+
+ /* create configuration attribute */
+ DBG2(DBG_IKE, "building %N attribute",
+ configuration_attribute_type_names, type);
+ ca = configuration_attribute_create_value(type, data);
+ if (!cp)
{
- ca->set_type(ca, INTERNAL_IP6_DNS);
+ cp = cp_payload_create_type(CFG_REQUEST);
}
- cp->add_configuration_attribute(cp, ca);
+ cp->add_attribute(cp, ca);
+
+ /* save handler along with requested type */
+ entry = malloc_thing(entry_t);
+ entry->type = type;
+ entry->handler = handler;
+
+ this->requested->insert_last(this->requested, entry);
+ }
+ enumerator->destroy(enumerator);
+
+ if (cp)
+ {
message->add_payload(message, (payload_t*)cp);
}
}
@@ -238,30 +299,62 @@ static status_t process_r(private_ike_config_t *this, message_t *message)
}
/**
+ * Find a peer (EAP) identity to query provider for attributes
+ */
+static identification_t *get_peer_identity(private_ike_config_t *this)
+{
+ identification_t *id = NULL, *current;
+ enumerator_t *enumerator;
+ auth_cfg_t *cfg;
+
+ enumerator = this->ike_sa->create_auth_cfg_enumerator(this->ike_sa, FALSE);
+ while (enumerator->enumerate(enumerator, &cfg))
+ {
+ /* prefer EAP-Identity of last round */
+ current = cfg->get(cfg, AUTH_RULE_EAP_IDENTITY);
+ if (!current || current->get_type(current) == ID_ANY)
+ {
+ current = cfg->get(cfg, AUTH_RULE_IDENTITY);
+ }
+ if (current && current->get_type(current) != ID_ANY)
+ {
+ id = current;
+ continue;
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (!id)
+ { /* fallback, should not happen */
+ id = this->ike_sa->get_other_id(this->ike_sa);
+ }
+ return id;
+}
+
+/**
* Implementation of task_t.build for responder
*/
static status_t build_r(private_ike_config_t *this, message_t *message)
{
if (this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)
{ /* in last IKE_AUTH exchange */
- peer_cfg_t *config = this->ike_sa->get_peer_cfg(this->ike_sa);
-
+ enumerator_t *enumerator;
+ configuration_attribute_type_t type;
+ chunk_t value;
+ host_t *vip = NULL;
+ cp_payload_t *cp = NULL;
+ peer_cfg_t *config;
+ identification_t *id;
+
+ id = get_peer_identity(this);
+
+ config = this->ike_sa->get_peer_cfg(this->ike_sa);
if (config && this->virtual_ip)
{
- enumerator_t *enumerator;
- configuration_attribute_type_t type;
- configuration_attribute_t *ca;
- chunk_t value;
- cp_payload_t *cp;
- host_t *vip = NULL;
-
DBG1(DBG_IKE, "peer requested virtual IP %H", this->virtual_ip);
if (config->get_pool(config))
{
- vip = charon->attributes->acquire_address(charon->attributes,
- config->get_pool(config),
- this->ike_sa->get_other_id(this->ike_sa),
- this->virtual_ip);
+ vip = lib->attributes->acquire_address(lib->attributes,
+ config->get_pool(config), id, this->virtual_ip);
}
if (vip == NULL)
{
@@ -273,27 +366,32 @@ static status_t build_r(private_ike_config_t *this, message_t *message)
}
DBG1(DBG_IKE, "assigning virtual IP %H to peer", vip);
this->ike_sa->set_virtual_ip(this->ike_sa, FALSE, vip);
-
- cp = cp_payload_create();
- cp->set_config_type(cp, CFG_REPLY);
-
- build_vip(this, vip, cp);
- vip->destroy(vip);
-
- /* if we add an IP, we also look for other attributes */
- enumerator = charon->attributes->create_attribute_enumerator(
- charon->attributes, this->ike_sa->get_other_id(this->ike_sa));
- while (enumerator->enumerate(enumerator, &type, &value))
+
+ cp = cp_payload_create_type(CFG_REPLY);
+ cp->add_attribute(cp, build_vip(vip));
+ }
+
+ /* query registered providers for additional attributes to include */
+ enumerator = lib->attributes->create_responder_enumerator(
+ lib->attributes, id, vip);
+ while (enumerator->enumerate(enumerator, &type, &value))
+ {
+ if (!cp)
{
- ca = configuration_attribute_create();
- ca->set_type(ca, type);
- ca->set_value(ca, value);
- cp->add_configuration_attribute(cp, ca);
+ cp = cp_payload_create_type(CFG_REPLY);
}
- enumerator->destroy(enumerator);
-
+ DBG2(DBG_IKE, "building %N attribute",
+ configuration_attribute_type_names, type);
+ cp->add_attribute(cp,
+ configuration_attribute_create_value(type, value));
+ }
+ enumerator->destroy(enumerator);
+
+ if (cp)
+ {
message->add_payload(message, (payload_t*)cp);
}
+ DESTROY_IF(vip);
return SUCCESS;
}
return NEED_MORE;
@@ -306,9 +404,9 @@ static status_t process_i(private_ike_config_t *this, message_t *message)
{
if (this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)
{ /* in last IKE_AUTH exchange */
-
+
process_payloads(this, message);
-
+
if (this->virtual_ip)
{
this->ike_sa->set_virtual_ip(this->ike_sa, TRUE, this->virtual_ip);
@@ -332,9 +430,11 @@ static task_type_t get_type(private_ike_config_t *this)
static void migrate(private_ike_config_t *this, ike_sa_t *ike_sa)
{
DESTROY_IF(this->virtual_ip);
-
+
this->ike_sa = ike_sa;
this->virtual_ip = NULL;
+ this->requested->destroy_function(this->requested, free);
+ this->requested = linked_list_create();
}
/**
@@ -343,6 +443,7 @@ static void migrate(private_ike_config_t *this, ike_sa_t *ike_sa)
static void destroy(private_ike_config_t *this)
{
DESTROY_IF(this->virtual_ip);
+ this->requested->destroy_function(this->requested, free);
free(this);
}
@@ -352,15 +453,16 @@ static void destroy(private_ike_config_t *this)
ike_config_t *ike_config_create(ike_sa_t *ike_sa, bool initiator)
{
private_ike_config_t *this = malloc_thing(private_ike_config_t);
-
+
this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
this->public.task.destroy = (void(*)(task_t*))destroy;
-
+
this->initiator = initiator;
this->ike_sa = ike_sa;
this->virtual_ip = NULL;
-
+ this->requested = linked_list_create();
+
if (initiator)
{
this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
@@ -371,7 +473,7 @@ ike_config_t *ike_config_create(ike_sa_t *ike_sa, bool initiator)
this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
}
-
+
return &this->public;
}