diff options
author | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2010-02-23 10:42:46 +0000 |
---|---|---|
committer | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2010-02-23 10:42:46 +0000 |
commit | de6b12502cdf42d5d92118f1c0e38dc31becf7c5 (patch) | |
tree | 0edac9c79f5a43e01913dd7f71c7abc487e5727b /src/charon/sa/tasks/ike_config.c | |
parent | 172642669d4a23e17f1ed411fbc8629dcaa5fb46 (diff) | |
download | vyos-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.c | 276 |
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; } |