summaryrefslogtreecommitdiff
path: root/src/charon/sa/tasks/ike_auth.c
diff options
context:
space:
mode:
authorRene Mayrhofer <rene@mayrhofer.eu.org>2010-05-27 15:43:45 +0000
committerRene Mayrhofer <rene@mayrhofer.eu.org>2010-05-27 15:43:45 +0000
commit6c2828d075efdfc02348369149b4347447857c8c (patch)
tree6c9ec7c9f342792e5eb2c2973daa7bbbeb45362e /src/charon/sa/tasks/ike_auth.c
parentcc7f376e575482c9a4866a4bd0c1f470394d740b (diff)
downloadvyos-strongswan-6c2828d075efdfc02348369149b4347447857c8c.tar.gz
vyos-strongswan-6c2828d075efdfc02348369149b4347447857c8c.zip
Remove leftovers after source code restructuring.
Diffstat (limited to 'src/charon/sa/tasks/ike_auth.c')
-rw-r--r--src/charon/sa/tasks/ike_auth.c1041
1 files changed, 0 insertions, 1041 deletions
diff --git a/src/charon/sa/tasks/ike_auth.c b/src/charon/sa/tasks/ike_auth.c
deleted file mode 100644
index a07f96767..000000000
--- a/src/charon/sa/tasks/ike_auth.c
+++ /dev/null
@@ -1,1041 +0,0 @@
-/*
- * Copyright (C) 2005-2009 Martin Willi
- * Copyright (C) 2005 Jan Hutter
- * 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
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details
- */
-
-#include "ike_auth.h"
-
-#include <string.h>
-
-#include <daemon.h>
-#include <encoding/payloads/id_payload.h>
-#include <encoding/payloads/auth_payload.h>
-#include <encoding/payloads/eap_payload.h>
-#include <encoding/payloads/nonce_payload.h>
-#include <sa/authenticators/eap_authenticator.h>
-
-typedef struct private_ike_auth_t private_ike_auth_t;
-
-/**
- * Private members of a ike_auth_t task.
- */
-struct private_ike_auth_t {
-
- /**
- * Public methods and task_t interface.
- */
- ike_auth_t public;
-
- /**
- * Assigned IKE_SA.
- */
- ike_sa_t *ike_sa;
-
- /**
- * Are we the initiator?
- */
- bool initiator;
-
- /**
- * Nonce chosen by us in ike_init
- */
- chunk_t my_nonce;
-
- /**
- * Nonce chosen by peer in ike_init
- */
- chunk_t other_nonce;
-
- /**
- * IKE_SA_INIT message sent by us
- */
- packet_t *my_packet;
-
- /**
- * IKE_SA_INIT message sent by peer
- */
- packet_t *other_packet;
-
- /**
- * currently active authenticator, to authenticate us
- */
- authenticator_t *my_auth;
-
- /**
- * currently active authenticator, to authenticate peer
- */
- authenticator_t *other_auth;
-
- /**
- * peer_cfg candidates, ordered by priority
- */
- linked_list_t *candidates;
-
- /**
- * selected peer config (might change when using multiple authentications)
- */
- peer_cfg_t *peer_cfg;
-
- /**
- * have we planned an(other) authentication exchange?
- */
- bool do_another_auth;
-
- /**
- * has the peer announced another authentication exchange?
- */
- bool expect_another_auth;
-
- /**
- * should we send a AUTHENTICATION_FAILED notify?
- */
- bool authentication_failed;
-};
-
-/**
- * check if multiple authentication extension is enabled, configuration-wise
- */
-static bool multiple_auth_enabled()
-{
- return lib->settings->get_bool(lib->settings,
- "charon.multiple_authentication", TRUE);
-}
-
-/**
- * collect the needed information in the IKE_SA_INIT exchange from our message
- */
-static status_t collect_my_init_data(private_ike_auth_t *this,
- message_t *message)
-{
- nonce_payload_t *nonce;
-
- /* get the nonce that was generated in ike_init */
- nonce = (nonce_payload_t*)message->get_payload(message, NONCE);
- if (nonce == NULL)
- {
- return FAILED;
- }
- this->my_nonce = nonce->get_nonce(nonce);
-
- /* pre-generate the message, keep a copy */
- if (this->ike_sa->generate_message(this->ike_sa, message,
- &this->my_packet) != SUCCESS)
- {
- return FAILED;
- }
- return NEED_MORE;
-}
-
-/**
- * collect the needed information in the IKE_SA_INIT exchange from others message
- */
-static status_t collect_other_init_data(private_ike_auth_t *this,
- message_t *message)
-{
- /* we collect the needed information in the IKE_SA_INIT exchange */
- nonce_payload_t *nonce;
-
- /* get the nonce that was generated in ike_init */
- nonce = (nonce_payload_t*)message->get_payload(message, NONCE);
- if (nonce == NULL)
- {
- return FAILED;
- }
- this->other_nonce = nonce->get_nonce(nonce);
-
- /* keep a copy of the received packet */
- this->other_packet = message->get_packet(message);
- return NEED_MORE;
-}
-
-/**
- * Get the next authentication configuration
- */
-static auth_cfg_t *get_auth_cfg(private_ike_auth_t *this, bool local)
-{
- enumerator_t *e1, *e2;
- auth_cfg_t *c1, *c2, *next = NULL;
-
- /* find an available config not already done */
- e1 = this->peer_cfg->create_auth_cfg_enumerator(this->peer_cfg, local);
- while (e1->enumerate(e1, &c1))
- {
- bool found = FALSE;
-
- e2 = this->ike_sa->create_auth_cfg_enumerator(this->ike_sa, local);
- while (e2->enumerate(e2, &c2))
- {
- if (c2->complies(c2, c1, FALSE))
- {
- found = TRUE;
- break;
- }
- }
- e2->destroy(e2);
- if (!found)
- {
- next = c1;
- break;
- }
- }
- e1->destroy(e1);
- return next;
-}
-
-/**
- * Check if we have should initiate another authentication round
- */
-static bool do_another_auth(private_ike_auth_t *this)
-{
- bool do_another = FALSE;
- enumerator_t *done, *todo;
- auth_cfg_t *done_cfg, *todo_cfg;
-
- if (!this->ike_sa->supports_extension(this->ike_sa, EXT_MULTIPLE_AUTH))
- {
- return FALSE;
- }
-
- done = this->ike_sa->create_auth_cfg_enumerator(this->ike_sa, TRUE);
- todo = this->peer_cfg->create_auth_cfg_enumerator(this->peer_cfg, TRUE);
- while (todo->enumerate(todo, &todo_cfg))
- {
- if (!done->enumerate(done, &done_cfg))
- {
- done_cfg = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
- }
- if (!done_cfg->complies(done_cfg, todo_cfg, FALSE))
- {
- do_another = TRUE;
- break;
- }
- }
- done->destroy(done);
- todo->destroy(todo);
- return do_another;
-}
-
-/**
- * Get peer configuration candidates from backends
- */
-static bool load_cfg_candidates(private_ike_auth_t *this)
-{
- enumerator_t *enumerator;
- peer_cfg_t *peer_cfg;
- host_t *me, *other;
- identification_t *my_id, *other_id;
-
- me = this->ike_sa->get_my_host(this->ike_sa);
- other = this->ike_sa->get_other_host(this->ike_sa);
- my_id = this->ike_sa->get_my_id(this->ike_sa);
- other_id = this->ike_sa->get_other_id(this->ike_sa);
-
- enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends,
- me, other, my_id, other_id);
- while (enumerator->enumerate(enumerator, &peer_cfg))
- {
- peer_cfg->get_ref(peer_cfg);
- if (this->peer_cfg == NULL)
- { /* best match */
- this->peer_cfg = peer_cfg;
- this->ike_sa->set_peer_cfg(this->ike_sa, peer_cfg);
- }
- else
- {
- this->candidates->insert_last(this->candidates, peer_cfg);
- }
- }
- enumerator->destroy(enumerator);
- if (this->peer_cfg)
- {
- DBG1(DBG_CFG, "selected peer config '%s'",
- this->peer_cfg->get_name(this->peer_cfg));
- return TRUE;
- }
- DBG1(DBG_CFG, "no matching peer config found");
- return FALSE;
-}
-
-/**
- * update the current peer candidate if necessary, using candidates
- */
-static bool update_cfg_candidates(private_ike_auth_t *this, bool strict)
-{
- do
- {
- if (this->peer_cfg)
- {
- bool complies = TRUE;
- enumerator_t *e1, *e2, *tmp;
- auth_cfg_t *c1, *c2;
-
- e1 = this->ike_sa->create_auth_cfg_enumerator(this->ike_sa, FALSE);
- e2 = this->peer_cfg->create_auth_cfg_enumerator(this->peer_cfg, FALSE);
-
- if (strict)
- { /* swap lists in strict mode: all configured rounds must be
- * fulfilled. If !strict, we check only the rounds done so far. */
- tmp = e1;
- e1 = e2;
- e2 = tmp;
- }
- while (e1->enumerate(e1, &c1))
- {
- /* check if done authentications comply to configured ones */
- if ((!e2->enumerate(e2, &c2)) ||
- (!strict && !c1->complies(c1, c2, TRUE)) ||
- (strict && !c2->complies(c2, c1, TRUE)))
- {
- complies = FALSE;
- break;
- }
- }
- e1->destroy(e1);
- e2->destroy(e2);
- if (complies)
- {
- break;
- }
- DBG1(DBG_CFG, "selected peer config '%s' inacceptable",
- this->peer_cfg->get_name(this->peer_cfg));
- this->peer_cfg->destroy(this->peer_cfg);
- }
- if (this->candidates->remove_first(this->candidates,
- (void**)&this->peer_cfg) != SUCCESS)
- {
- DBG1(DBG_CFG, "no alternative config found");
- this->peer_cfg = NULL;
- }
- else
- {
- DBG1(DBG_CFG, "switching to peer config '%s'",
- this->peer_cfg->get_name(this->peer_cfg));
- this->ike_sa->set_peer_cfg(this->ike_sa, this->peer_cfg);
- }
- }
- while (this->peer_cfg);
-
- return this->peer_cfg != NULL;
-}
-
-/**
- * Implementation of task_t.build for initiator
- */
-static status_t build_i(private_ike_auth_t *this, message_t *message)
-{
- auth_cfg_t *cfg;
-
- if (message->get_exchange_type(message) == IKE_SA_INIT)
- {
- return collect_my_init_data(this, message);
- }
-
- if (this->peer_cfg == NULL)
- {
- this->peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
- this->peer_cfg->get_ref(this->peer_cfg);
- }
-
- if (message->get_message_id(message) == 1)
- { /* in the first IKE_AUTH ... */
- if (this->ike_sa->supports_extension(this->ike_sa, EXT_MULTIPLE_AUTH))
- { /* indicate support for multiple authentication */
- message->add_notify(message, FALSE, MULTIPLE_AUTH_SUPPORTED,
- chunk_empty);
- }
- /* indicate support for EAP-only authentication */
- message->add_notify(message, FALSE, EAP_ONLY_AUTHENTICATION,
- chunk_empty);
- }
-
- if (!this->do_another_auth && !this->my_auth)
- { /* we have done our rounds */
- return NEED_MORE;
- }
-
- /* check if an authenticator is in progress */
- if (this->my_auth == NULL)
- {
- identification_t *id;
- id_payload_t *id_payload;
-
- /* clean up authentication config from a previous round */
- cfg = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
- cfg->purge(cfg, TRUE);
-
- /* add (optional) IDr */
- cfg = get_auth_cfg(this, FALSE);
- if (cfg)
- {
- id = cfg->get(cfg, AUTH_RULE_IDENTITY);
- if (id && !id->contains_wildcards(id))
- {
- this->ike_sa->set_other_id(this->ike_sa, id->clone(id));
- id_payload = id_payload_create_from_identification(
- ID_RESPONDER, id);
- message->add_payload(message, (payload_t*)id_payload);
- }
- }
- /* add IDi */
- cfg = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
- cfg->merge(cfg, get_auth_cfg(this, TRUE), TRUE);
- id = cfg->get(cfg, AUTH_RULE_IDENTITY);
- if (!id)
- {
- DBG1(DBG_CFG, "configuration misses IDi");
- return FAILED;
- }
- this->ike_sa->set_my_id(this->ike_sa, id->clone(id));
- id_payload = id_payload_create_from_identification(ID_INITIATOR, id);
- message->add_payload(message, (payload_t*)id_payload);
-
- /* build authentication data */
- this->my_auth = authenticator_create_builder(this->ike_sa, cfg,
- this->other_nonce, this->my_nonce,
- this->other_packet->get_data(this->other_packet),
- this->my_packet->get_data(this->my_packet));
- if (!this->my_auth)
- {
- return FAILED;
- }
- }
- switch (this->my_auth->build(this->my_auth, message))
- {
- case SUCCESS:
- /* authentication step complete, reset authenticator */
- cfg = auth_cfg_create();
- cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, TRUE), TRUE);
- this->ike_sa->add_auth_cfg(this->ike_sa, TRUE, cfg);
- this->my_auth->destroy(this->my_auth);
- this->my_auth = NULL;
- break;
- case NEED_MORE:
- break;
- default:
- return FAILED;
- }
-
- /* check for additional authentication rounds */
- if (do_another_auth(this))
- {
- if (message->get_payload(message, AUTHENTICATION))
- {
- message->add_notify(message, FALSE, ANOTHER_AUTH_FOLLOWS, chunk_empty);
- }
- }
- else
- {
- this->do_another_auth = FALSE;
- }
- return NEED_MORE;
-}
-
-/**
- * Implementation of task_t.process for responder
- */
-static status_t process_r(private_ike_auth_t *this, message_t *message)
-{
- auth_cfg_t *cfg, *cand;
- id_payload_t *id_payload;
- identification_t *id;
-
- if (message->get_exchange_type(message) == IKE_SA_INIT)
- {
- return collect_other_init_data(this, message);
- }
-
- if (this->my_auth == NULL && this->do_another_auth)
- {
- /* handle (optional) IDr payload, apply proposed identity */
- id_payload = (id_payload_t*)message->get_payload(message, ID_RESPONDER);
- if (id_payload)
- {
- id = id_payload->get_identification(id_payload);
- }
- else
- {
- id = identification_create_from_encoding(ID_ANY, chunk_empty);
- }
- this->ike_sa->set_my_id(this->ike_sa, id);
- }
-
- if (!this->expect_another_auth)
- {
- return NEED_MORE;
- }
-
- if (message->get_message_id(message) == 1)
- { /* check for extensions in the first IKE_AUTH */
- if (message->get_notify(message, MULTIPLE_AUTH_SUPPORTED))
- {
- this->ike_sa->enable_extension(this->ike_sa, EXT_MULTIPLE_AUTH);
- }
- if (this->ike_sa->supports_extension(this->ike_sa, EXT_STRONGSWAN) &&
- message->get_notify(message, EAP_ONLY_AUTHENTICATION))
- { /* EAP-only has no official notify, accept only from strongSwan */
- this->ike_sa->enable_extension(this->ike_sa,
- EXT_EAP_ONLY_AUTHENTICATION);
- }
- }
-
- if (this->other_auth == NULL)
- {
- /* handle IDi payload */
- id_payload = (id_payload_t*)message->get_payload(message, ID_INITIATOR);
- if (!id_payload)
- {
- DBG1(DBG_IKE, "IDi payload missing");
- return FAILED;
- }
- id = id_payload->get_identification(id_payload);
- this->ike_sa->set_other_id(this->ike_sa, id);
- cfg = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
- cfg->add(cfg, AUTH_RULE_IDENTITY, id->clone(id));
-
- if (this->peer_cfg == NULL)
- {
- if (!load_cfg_candidates(this))
- {
- this->authentication_failed = TRUE;
- return NEED_MORE;
- }
- }
- if (message->get_payload(message, AUTHENTICATION) == NULL)
- { /* before authenticating with EAP, we need a EAP config */
- cand = get_auth_cfg(this, FALSE);
- while (!cand || (
- (uintptr_t)cand->get(cand, AUTH_RULE_EAP_TYPE) == EAP_NAK &&
- (uintptr_t)cand->get(cand, AUTH_RULE_EAP_VENDOR) == 0))
- { /* peer requested EAP, but current config does not match */
- this->peer_cfg->destroy(this->peer_cfg);
- this->peer_cfg = NULL;
- if (!update_cfg_candidates(this, FALSE))
- {
- this->authentication_failed = TRUE;
- return NEED_MORE;
- }
- cand = get_auth_cfg(this, FALSE);
- }
- cfg->merge(cfg, cand, TRUE);
- }
-
- /* verify authentication data */
- this->other_auth = authenticator_create_verifier(this->ike_sa,
- message, this->other_nonce, this->my_nonce,
- this->other_packet->get_data(this->other_packet),
- this->my_packet->get_data(this->my_packet));
- if (!this->other_auth)
- {
- this->authentication_failed = TRUE;
- return NEED_MORE;
- }
- }
- switch (this->other_auth->process(this->other_auth, message))
- {
- case SUCCESS:
- this->other_auth->destroy(this->other_auth);
- this->other_auth = NULL;
- break;
- case NEED_MORE:
- if (message->get_payload(message, AUTHENTICATION))
- { /* AUTH verification successful, but another build() needed */
- break;
- }
- return NEED_MORE;
- default:
- this->authentication_failed = TRUE;
- return NEED_MORE;
- }
-
- /* store authentication information */
- cfg = auth_cfg_create();
- cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, FALSE), FALSE);
- this->ike_sa->add_auth_cfg(this->ike_sa, FALSE, cfg);
-
- /* another auth round done, invoke authorize hook */
- if (!charon->bus->authorize(charon->bus, FALSE))
- {
- DBG1(DBG_IKE, "authorization hook forbids IKE_SA, cancelling");
- this->authentication_failed = TRUE;
- return NEED_MORE;
- }
-
- if (!update_cfg_candidates(this, FALSE))
- {
- this->authentication_failed = TRUE;
- return NEED_MORE;
- }
-
- if (message->get_notify(message, ANOTHER_AUTH_FOLLOWS) == NULL)
- {
- this->expect_another_auth = FALSE;
- if (!update_cfg_candidates(this, TRUE))
- {
- this->authentication_failed = TRUE;
- return NEED_MORE;
- }
- }
- return NEED_MORE;
-}
-
-/**
- * Implementation of task_t.build for responder
- */
-static status_t build_r(private_ike_auth_t *this, message_t *message)
-{
- auth_cfg_t *cfg;
-
- if (message->get_exchange_type(message) == IKE_SA_INIT)
- {
- if (multiple_auth_enabled())
- {
- message->add_notify(message, FALSE, MULTIPLE_AUTH_SUPPORTED,
- chunk_empty);
- }
- return collect_my_init_data(this, message);
- }
-
- if (this->authentication_failed || this->peer_cfg == NULL)
- {
- message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty);
- return FAILED;
- }
-
- if (this->my_auth == NULL && this->do_another_auth)
- {
- identification_t *id, *id_cfg;
- id_payload_t *id_payload;
-
- /* add IDr */
- cfg = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
- cfg->purge(cfg, TRUE);
- cfg->merge(cfg, get_auth_cfg(this, TRUE), TRUE);
-
- id_cfg = cfg->get(cfg, AUTH_RULE_IDENTITY);
- id = this->ike_sa->get_my_id(this->ike_sa);
- if (id->get_type(id) == ID_ANY)
- { /* no IDr received, apply configured ID */
- if (!id_cfg || id_cfg->contains_wildcards(id_cfg))
- {
- DBG1(DBG_CFG, "IDr not configured and negotiation failed");
- message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
- chunk_empty);
- return FAILED;
- }
- this->ike_sa->set_my_id(this->ike_sa, id_cfg->clone(id_cfg));
- id = id_cfg;
- }
- else
- { /* IDr received, check if it matches configuration */
- if (id_cfg && !id->matches(id, id_cfg))
- {
- DBG1(DBG_CFG, "received IDr %Y, but require %Y", id, id_cfg);
- message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
- chunk_empty);
- return FAILED;
- }
- }
-
- id_payload = id_payload_create_from_identification(ID_RESPONDER, id);
- message->add_payload(message, (payload_t*)id_payload);
-
- if ((uintptr_t)cfg->get(cfg, AUTH_RULE_AUTH_CLASS) == AUTH_CLASS_EAP)
- { /* EAP-only authentication */
- if (!this->ike_sa->supports_extension(this->ike_sa,
- EXT_EAP_ONLY_AUTHENTICATION))
- {
- DBG1(DBG_IKE, "configured EAP-only authentication, but peer "
- "does not support it");
- message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
- chunk_empty);
- return FAILED;
- }
- }
- else
- {
- /* build authentication data */
- this->my_auth = authenticator_create_builder(this->ike_sa, cfg,
- this->other_nonce, this->my_nonce,
- this->other_packet->get_data(this->other_packet),
- this->my_packet->get_data(this->my_packet));
- if (!this->my_auth)
- {
- message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
- chunk_empty);
- return FAILED;
- }
- }
- }
-
- if (this->other_auth)
- {
- switch (this->other_auth->build(this->other_auth, message))
- {
- case SUCCESS:
- this->other_auth->destroy(this->other_auth);
- this->other_auth = NULL;
- break;
- case NEED_MORE:
- break;
- default:
- if (!message->get_payload(message, EXTENSIBLE_AUTHENTICATION))
- { /* skip AUTHENTICATION_FAILED if we have EAP_FAILURE */
- message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
- chunk_empty);
- }
- return FAILED;
- }
- }
- if (this->my_auth)
- {
- switch (this->my_auth->build(this->my_auth, message))
- {
- case SUCCESS:
- cfg = auth_cfg_create();
- cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, TRUE),
- TRUE);
- this->ike_sa->add_auth_cfg(this->ike_sa, TRUE, cfg);
- this->my_auth->destroy(this->my_auth);
- this->my_auth = NULL;
- break;
- case NEED_MORE:
- break;
- default:
- message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
- chunk_empty);
- return FAILED;
- }
- }
-
- /* check for additional authentication rounds */
- if (do_another_auth(this))
- {
- message->add_notify(message, FALSE, ANOTHER_AUTH_FOLLOWS, chunk_empty);
- }
- else
- {
- this->do_another_auth = FALSE;
- }
- if (!this->do_another_auth && !this->expect_another_auth)
- {
- if (charon->ike_sa_manager->check_uniqueness(charon->ike_sa_manager,
- this->ike_sa))
- {
- DBG1(DBG_IKE, "cancelling IKE_SA setup due uniqueness policy");
- message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
- chunk_empty);
- return FAILED;
- }
- if (!charon->bus->authorize(charon->bus, TRUE))
- {
- DBG1(DBG_IKE, "final authorization hook forbids IKE_SA, cancelling");
- message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
- chunk_empty);
- return FAILED;
- }
- DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%Y]...%H[%Y]",
- this->ike_sa->get_name(this->ike_sa),
- this->ike_sa->get_unique_id(this->ike_sa),
- this->ike_sa->get_my_host(this->ike_sa),
- this->ike_sa->get_my_id(this->ike_sa),
- this->ike_sa->get_other_host(this->ike_sa),
- this->ike_sa->get_other_id(this->ike_sa));
- this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
- charon->bus->ike_updown(charon->bus, this->ike_sa, TRUE);
- return SUCCESS;
- }
- return NEED_MORE;
-}
-
-/**
- * Implementation of task_t.process for initiator
- */
-static status_t process_i(private_ike_auth_t *this, message_t *message)
-{
- enumerator_t *enumerator;
- payload_t *payload;
- auth_cfg_t *cfg;
- bool mutual_eap = FALSE;
-
- if (message->get_exchange_type(message) == IKE_SA_INIT)
- {
- if (message->get_notify(message, MULTIPLE_AUTH_SUPPORTED) &&
- multiple_auth_enabled())
- {
- this->ike_sa->enable_extension(this->ike_sa, EXT_MULTIPLE_AUTH);
- }
- return collect_other_init_data(this, message);
- }
-
- enumerator = message->create_payload_enumerator(message);
- while (enumerator->enumerate(enumerator, &payload))
- {
- if (payload->get_type(payload) == NOTIFY)
- {
- notify_payload_t *notify = (notify_payload_t*)payload;
- notify_type_t type = notify->get_notify_type(notify);
-
- switch (type)
- {
- case NO_PROPOSAL_CHOSEN:
- case SINGLE_PAIR_REQUIRED:
- case NO_ADDITIONAL_SAS:
- case INTERNAL_ADDRESS_FAILURE:
- case FAILED_CP_REQUIRED:
- case TS_UNACCEPTABLE:
- case INVALID_SELECTORS:
- /* these are errors, but are not critical as only the
- * CHILD_SA won't get build, but IKE_SA establishes anyway */
- break;
- case MOBIKE_SUPPORTED:
- case ADDITIONAL_IP4_ADDRESS:
- case ADDITIONAL_IP6_ADDRESS:
- /* handled in ike_mobike task */
- break;
- case AUTH_LIFETIME:
- /* handled in ike_auth_lifetime task */
- break;
- case ME_ENDPOINT:
- /* handled in ike_me task */
- break;
- default:
- {
- if (type < 16383)
- {
- DBG1(DBG_IKE, "received %N notify error",
- notify_type_names, type);
- enumerator->destroy(enumerator);
- return FAILED;
- }
- DBG2(DBG_IKE, "received %N notify",
- notify_type_names, type);
- break;
- }
- }
- }
- }
- enumerator->destroy(enumerator);
-
- if (this->expect_another_auth)
- {
- if (this->other_auth == NULL)
- {
- id_payload_t *id_payload;
- identification_t *id;
-
- /* handle IDr payload */
- id_payload = (id_payload_t*)message->get_payload(message,
- ID_RESPONDER);
- if (!id_payload)
- {
- DBG1(DBG_IKE, "IDr payload missing");
- return FAILED;
- }
- id = id_payload->get_identification(id_payload);
- this->ike_sa->set_other_id(this->ike_sa, id);
- cfg = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
- cfg->add(cfg, AUTH_RULE_IDENTITY, id->clone(id));
-
- if (message->get_payload(message, AUTHENTICATION))
- {
- /* verify authentication data */
- this->other_auth = authenticator_create_verifier(this->ike_sa,
- message, this->other_nonce, this->my_nonce,
- this->other_packet->get_data(this->other_packet),
- this->my_packet->get_data(this->my_packet));
- if (!this->other_auth)
- {
- return FAILED;
- }
- }
- else
- {
- /* responder omitted AUTH payload, indicating EAP-only */
- mutual_eap = TRUE;
- }
- }
- if (this->other_auth)
- {
- switch (this->other_auth->process(this->other_auth, message))
- {
- case SUCCESS:
- break;
- case NEED_MORE:
- return NEED_MORE;
- default:
- return FAILED;
- }
- this->other_auth->destroy(this->other_auth);
- this->other_auth = NULL;
- }
- /* store authentication information, reset authenticator */
- cfg = auth_cfg_create();
- cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, FALSE), FALSE);
- this->ike_sa->add_auth_cfg(this->ike_sa, FALSE, cfg);
-
- /* another auth round done, invoke authorize hook */
- if (!charon->bus->authorize(charon->bus, FALSE))
- {
- DBG1(DBG_IKE, "authorization forbids IKE_SA, cancelling");
- return FAILED;
- }
- }
-
- if (this->my_auth)
- {
- switch (this->my_auth->process(this->my_auth, message))
- {
- case SUCCESS:
- cfg = auth_cfg_create();
- cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, TRUE),
- TRUE);
- this->ike_sa->add_auth_cfg(this->ike_sa, TRUE, cfg);
- this->my_auth->destroy(this->my_auth);
- this->my_auth = NULL;
- this->do_another_auth = do_another_auth(this);
- break;
- case NEED_MORE:
- break;
- default:
- return FAILED;
- }
- }
- if (mutual_eap)
- {
- if (!this->my_auth || !this->my_auth->is_mutual(this->my_auth))
- {
- DBG1(DBG_IKE, "do not allow non-mutual EAP-only authentication");
- return FAILED;
- }
- DBG1(DBG_IKE, "allow mutual EAP-only authentication");
- }
-
- if (message->get_notify(message, ANOTHER_AUTH_FOLLOWS) == NULL)
- {
- this->expect_another_auth = FALSE;
- }
- if (!this->expect_another_auth && !this->do_another_auth && !this->my_auth)
- {
- if (!update_cfg_candidates(this, TRUE))
- {
- return FAILED;
- }
- if (!charon->bus->authorize(charon->bus, TRUE))
- {
- DBG1(DBG_IKE, "final authorization hook forbids IKE_SA, cancelling");
- return FAILED;
- }
- DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%Y]...%H[%Y]",
- this->ike_sa->get_name(this->ike_sa),
- this->ike_sa->get_unique_id(this->ike_sa),
- this->ike_sa->get_my_host(this->ike_sa),
- this->ike_sa->get_my_id(this->ike_sa),
- this->ike_sa->get_other_host(this->ike_sa),
- this->ike_sa->get_other_id(this->ike_sa));
- this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
- charon->bus->ike_updown(charon->bus, this->ike_sa, TRUE);
- return SUCCESS;
- }
- return NEED_MORE;
-}
-
-/**
- * Implementation of task_t.get_type
- */
-static task_type_t get_type(private_ike_auth_t *this)
-{
- return IKE_AUTHENTICATE;
-}
-
-/**
- * Implementation of task_t.migrate
- */
-static void migrate(private_ike_auth_t *this, ike_sa_t *ike_sa)
-{
- chunk_free(&this->my_nonce);
- chunk_free(&this->other_nonce);
- DESTROY_IF(this->my_packet);
- DESTROY_IF(this->other_packet);
- DESTROY_IF(this->peer_cfg);
- DESTROY_IF(this->my_auth);
- DESTROY_IF(this->other_auth);
- this->candidates->destroy_offset(this->candidates, offsetof(peer_cfg_t, destroy));
-
- this->my_packet = NULL;
- this->other_packet = NULL;
- this->ike_sa = ike_sa;
- this->peer_cfg = NULL;
- this->my_auth = NULL;
- this->other_auth = NULL;
- this->do_another_auth = TRUE;
- this->expect_another_auth = TRUE;
- this->authentication_failed = FALSE;
- this->candidates = linked_list_create();
-}
-
-/**
- * Implementation of task_t.destroy
- */
-static void destroy(private_ike_auth_t *this)
-{
- chunk_free(&this->my_nonce);
- chunk_free(&this->other_nonce);
- DESTROY_IF(this->my_packet);
- DESTROY_IF(this->other_packet);
- DESTROY_IF(this->my_auth);
- DESTROY_IF(this->other_auth);
- DESTROY_IF(this->peer_cfg);
- this->candidates->destroy_offset(this->candidates, offsetof(peer_cfg_t, destroy));
- free(this);
-}
-
-/*
- * Described in header.
- */
-ike_auth_t *ike_auth_create(ike_sa_t *ike_sa, bool initiator)
-{
- private_ike_auth_t *this = malloc_thing(private_ike_auth_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;
-
- if (initiator)
- {
- this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
- this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
- }
- else
- {
- this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
- this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
- }
-
- this->ike_sa = ike_sa;
- this->initiator = initiator;
- this->my_nonce = chunk_empty;
- this->other_nonce = chunk_empty;
- this->my_packet = NULL;
- this->other_packet = NULL;
- this->peer_cfg = NULL;
- this->candidates = linked_list_create();
- this->my_auth = NULL;
- this->other_auth = NULL;
- this->do_another_auth = TRUE;
- this->expect_another_auth = TRUE;
- this->authentication_failed = FALSE;
-
- return &this->public;
-}
-