aboutsummaryrefslogtreecommitdiffstats
path: root/src/charon/sa/transactions/ike_auth.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/charon/sa/transactions/ike_auth.c')
-rw-r--r--src/charon/sa/transactions/ike_auth.c1562
1 files changed, 0 insertions, 1562 deletions
diff --git a/src/charon/sa/transactions/ike_auth.c b/src/charon/sa/transactions/ike_auth.c
deleted file mode 100644
index bf7fd6d12..000000000
--- a/src/charon/sa/transactions/ike_auth.c
+++ /dev/null
@@ -1,1562 +0,0 @@
-/**
- * @file ike_auth.c
- *
- * @brief Implementation of ike_auth_t transaction.
- *
- */
-
-/*
- * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger
- * Copyright (C) 2005-2006 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/sa_payload.h>
-#include <encoding/payloads/id_payload.h>
-#include <encoding/payloads/cert_payload.h>
-#include <encoding/payloads/certreq_payload.h>
-#include <encoding/payloads/auth_payload.h>
-#include <encoding/payloads/ts_payload.h>
-#include <sa/authenticators/authenticator.h>
-#include <sa/authenticators/eap_authenticator.h>
-#include <sa/child_sa.h>
-
-
-typedef struct private_ike_auth_t private_ike_auth_t;
-
-/**
- * Private members of a ike_auth_t object..
- */
-struct private_ike_auth_t {
-
- /**
- * Public methods and transaction_t interface.
- */
- ike_auth_t public;
-
- /**
- * Assigned IKE_SA.
- */
- ike_sa_t *ike_sa;
-
- /**
- * Message sent by our peer, if already generated
- */
- message_t *message;
-
- /**
- * Message ID this transaction uses
- */
- u_int32_t message_id;
-
- /**
- * Times we did send the request
- */
- u_int32_t requested;
-
- /**
- * initiator chosen nonce
- */
- chunk_t nonce_i;
-
- /**
- * responder chosen nonce
- */
- chunk_t nonce_r;
-
- /**
- * encoded request message of ike_sa_init transaction
- */
- chunk_t init_request;
-
- /**
- * encoded response message of ike_sa_init transaction
- */
- chunk_t init_response;
-
- /**
- * connection definition used for IKE_SA setup
- */
- connection_t *connection;
-
- /**
- * policy definition used CHILD_SA creation
- */
- policy_t *policy;
-
- /**
- * Negotiated proposal used for CHILD_SA
- */
- proposal_t *proposal;
-
- /**
- * Negotiated traffic selectors for initiator
- */
- linked_list_t *tsi;
-
- /**
- * Negotiated traffic selectors for responder
- */
- linked_list_t *tsr;
-
- /**
- * CHILD_SA created along with IKE_AUTH
- */
- child_sa_t *child_sa;
-
- /**
- * did other peer create a CHILD_SA?
- */
- bool build_child;
-
- /**
- * reqid to use for CHILD_SA setup
- */
- u_int32_t reqid;
-
- /**
- * List of CA certificates the other peer trusts
- */
- linked_list_t *cacerts;
-
- /**
- * EAP uses this authentication, which is passed along multiple ike_auths
- */
- eap_authenticator_t *eap_auth;
-
- /**
- * if the client receives a EAP request, it is stored here for later use
- */
- eap_payload_t *eap_next;
-
- /**
- * set to TRUE if authentication should be done with EAP only
- */
- bool eap_only;
-
- /**
- * has the other peer been authenticated yet?
- */
- bool peer_authenticated;
-
- /**
- * mode the CHILD_SA uses: tranport, tunnel, BEET
- */
- mode_t mode;
-};
-
-/**
- * Implementation of transaction_t.get_message_id.
- */
-static u_int32_t get_message_id(private_ike_auth_t *this)
-{
- return this->message_id;
-}
-
-/**
- * Implementation of transaction_t.requested.
- */
-static u_int32_t requested(private_ike_auth_t *this)
-{
- return this->requested++;
-}
-
-/**
- * Implementation of transaction_t.set_config.
- */
-static void set_config(private_ike_auth_t *this,
- connection_t *connection, policy_t *policy)
-{
- this->connection = connection;
- this->policy = policy;
-}
-
-/**
- * Implementation of transaction_t.set_reqid.
- */
-static void set_reqid(private_ike_auth_t *this, u_int32_t reqid)
-{
- this->reqid = reqid;
-}
-
-/**
- * Implementation of transaction_t.set_nonces.
- */
-static void set_nonces(private_ike_auth_t *this, chunk_t nonce_i, chunk_t nonce_r)
-{
- this->nonce_i = nonce_i;
- this->nonce_r = nonce_r;
-}
-
-/**
- * Implementation of transaction_t.set_init_messages.
- */
-static void set_init_messages(private_ike_auth_t *this, chunk_t init_request, chunk_t init_response)
-{
- this->init_request = init_request;
- this->init_response = init_response;
-}
-
-/**
- * Build a notify message.
- */
-static void build_notify(notify_type_t type, message_t *message, bool flush_message)
-{
- notify_payload_t *notify;
-
- if (flush_message)
- {
- payload_t *payload;
- iterator_t *iterator = message->get_payload_iterator(message);
- while (iterator->iterate(iterator, (void**)&payload))
- {
- payload->destroy(payload);
- iterator->remove(iterator);
- }
- iterator->destroy(iterator);
- }
-
- notify = notify_payload_create();
- notify->set_notify_type(notify, type);
- message->add_payload(message, (payload_t*)notify);
-}
-
-/**
- * Implementation of transaction_t.get_request.
- */
-static status_t get_request(private_ike_auth_t *this, message_t **result)
-{
- message_t *request;
- host_t *me, *other;
- identification_t *my_id, *other_id;
- id_payload_t *my_id_payload;
-
- /* check if we already have built a message (retransmission) */
- if (this->message)
- {
- *result = this->message;
- return SUCCESS;
- }
-
- me = this->ike_sa->get_my_host(this->ike_sa);
- other = this->ike_sa->get_other_host(this->ike_sa);
- my_id = this->policy->get_my_id(this->policy);
- other_id = this->policy->get_other_id(this->policy);
-
- /* build the request */
- request = message_create();
- request->set_source(request, me->clone(me));
- request->set_destination(request, other->clone(other));
- request->set_exchange_type(request, IKE_AUTH);
- request->set_request(request, TRUE);
- request->set_ike_sa_id(request, this->ike_sa->get_id(this->ike_sa));
- /* apply for caller */
- *result = request;
- /* store for retransmission */
- this->message = request;
-
- this->message_id = this->ike_sa->get_next_message_id(this->ike_sa);
- request->set_message_id(request, this->message_id);
-
- if (this->eap_auth)
- {
- /* we already sent ID, SA, TS in an earlier ike_auth, we now
- * continiue EAP processing */
- if (this->eap_next)
- {
- /* if we have another outstanding EAP response, send it */
- request->add_payload(request, (payload_t*)this->eap_next);
- this->eap_next = NULL;
- return SUCCESS;
- }
- else
- {
- /* if not, we have received an EAP_SUCCESS, send AUTH payload.
- * we only send our data if:
- * a) The peer has been authenticated using RSA/PSK, or
- * b) The EAP method is mutual and gives us enough security
- */
- if (this->eap_auth->is_mutual(this->eap_auth) ||
- this->peer_authenticated)
- {
- auth_payload_t *auth_payload;
- authenticator_t *authenticator = (authenticator_t*)this->eap_auth;
-
- if (authenticator->build(authenticator, this->init_request,
- this->nonce_r, &auth_payload) != SUCCESS)
- {
- SIG(IKE_UP_FAILED,
- "EAP authentication data generation failed, deleting IKE_SA");
- SIG(CHILD_UP_FAILED,
- "initiating CHILD_SA failed, unable to create IKE_SA");
- return DESTROY_ME;
- }
- request->add_payload(request, (payload_t*)auth_payload);
- return SUCCESS;
- }
- else
- {
- SIG(IKE_UP_FAILED,
- "peer didn't send authentication data, deleting IKE_SA");
- SIG(CHILD_UP_FAILED,
- "initiating CHILD_SA failed, unable to create IKE_SA");
- return DESTROY_ME;
- }
- }
- }
- /* otherwise we do a normal ike_auth request... */
-
- { /* build ID payload */
- my_id_payload = id_payload_create_from_identification(TRUE, my_id);
- request->add_payload(request, (payload_t*)my_id_payload);
- }
-
- /* build certificate request payload */
- if (this->connection->get_certreq_policy(this->connection) != CERT_NEVER_SEND)
- {
- certreq_payload_t *certreq_payload;
- identification_t *other_ca = this->policy->get_other_ca(this->policy);
-
- if (other_ca)
- {
- if (other_ca->get_type(other_ca) == ID_ANY)
- {
- certreq_payload = certreq_payload_create_from_cacerts();
- }
- else
- {
- certreq_payload = certreq_payload_create_from_cacert(other_ca);
- }
- if (certreq_payload != NULL)
- {
- request->add_payload(request, (payload_t*)certreq_payload);
- }
- }
- }
-
- /* build certificate payload. TODO: Handle certreq from init_ike_sa. */
- if (this->policy->get_auth_method(this->policy) == AUTH_RSA &&
- this->connection->get_cert_policy(this->connection) != CERT_NEVER_SEND)
- {
- cert_payload_t *cert_payload;
-
- x509_t *cert = charon->credentials->get_certificate(charon->credentials, my_id);
-
- if (cert)
- {
- cert_payload = cert_payload_create_from_x509(cert);
- request->add_payload(request, (payload_t*)cert_payload);
- }
- else
- {
- DBG1(DBG_IKE, "could not find my certificate, certificate payload omitted");
- }
- }
-
- { /* build IDr payload, if other_id defined */
- id_payload_t *id_payload;
- if (!other_id->contains_wildcards(other_id))
- {
- id_payload = id_payload_create_from_identification(FALSE, other_id);
- request->add_payload(request, (payload_t*)id_payload);
- }
- }
-
- if (this->policy->get_auth_method(this->policy) != AUTH_EAP)
- { /* build auth payload */
- authenticator_t *authenticator;
- auth_payload_t *auth_payload;
- auth_method_t auth_method;
- status_t status;
-
- auth_method = this->policy->get_auth_method(this->policy);
- authenticator = authenticator_create(this->ike_sa, auth_method);
- if (authenticator == NULL)
- {
- SIG(IKE_UP_FAILED, "auth method %N not supported, deleting IKE_SA",
- auth_method_names, auth_method);
- SIG(CHILD_UP_FAILED, "initiating CHILD_SA failed, unable to create IKE_SA");
- return DESTROY_ME;
- }
- status = authenticator->build(authenticator, this->init_request,
- this->nonce_r, &auth_payload);
- authenticator->destroy(authenticator);
- if (status != SUCCESS)
- {
- SIG(IKE_UP_FAILED, "could not generate AUTH data, deleting IKE_SA");
- SIG(CHILD_UP_FAILED, "initiating CHILD_SA failed, unable to create IKE_SA");
- return DESTROY_ME;
- }
- request->add_payload(request, (payload_t*)auth_payload);
- }
- else
- {
- this->eap_auth = eap_authenticator_create(this->ike_sa);
- /* include notify that we support EAP only authentication */
- build_notify(EAP_ONLY_AUTHENTICATION, request, FALSE);
- }
-
- { /* build SA payload for CHILD_SA */
- linked_list_t *proposal_list;
- sa_payload_t *sa_payload;
- u_int32_t soft_lifetime, hard_lifetime;
- bool enable_natt;
-
- proposal_list = this->policy->get_proposals(this->policy);
- soft_lifetime = this->policy->get_soft_lifetime(this->policy);
- hard_lifetime = this->policy->get_hard_lifetime(this->policy);
- enable_natt = this->ike_sa->is_natt_enabled(this->ike_sa);
- this->child_sa = child_sa_create(this->reqid, me, other, my_id, other_id,
- soft_lifetime, hard_lifetime,
- this->policy->get_updown(this->policy),
- this->policy->get_hostaccess(this->policy),
- enable_natt);
- this->child_sa->set_name(this->child_sa, this->policy->get_name(this->policy));
- if (this->child_sa->alloc(this->child_sa, proposal_list) != SUCCESS)
- {
- SIG(IKE_UP_FAILED, "could not install CHILD_SA, deleting IKE_SA");
- SIG(CHILD_UP_FAILED, "initiating CHILD_SA failed, unable to create IKE_SA");
- return DESTROY_ME;
- }
- sa_payload = sa_payload_create_from_proposal_list(proposal_list);
- proposal_list->destroy_offset(proposal_list, offsetof(proposal_t, destroy));
- request->add_payload(request, (payload_t*)sa_payload);
- }
-
- /* notify for transport/BEET mode, we propose it
- * independent of the traffic selectors */
- switch (this->policy->get_mode(this->policy))
- {
- case MODE_TUNNEL:
- /* is the default */
- break;
- case MODE_TRANSPORT:
- if (this->ike_sa->is_natt_enabled(this->ike_sa))
- {
- DBG1(DBG_IKE, "not using tranport mode, as connection NATed");
- }
- else
- {
- build_notify(USE_TRANSPORT_MODE, request, FALSE);
- }
- break;
- case MODE_BEET:
- build_notify(USE_BEET_MODE, request, FALSE);
- break;
- }
-
- { /* build TSi payload */
- linked_list_t *ts_list;
- ts_payload_t *ts_payload;
-
- ts_list = this->policy->get_my_traffic_selectors(this->policy, me);
- ts_payload = ts_payload_create_from_traffic_selectors(TRUE, ts_list);
- ts_list->destroy_offset(ts_list, offsetof(traffic_selector_t, destroy));
-
- request->add_payload(request, (payload_t*)ts_payload);
- }
-
- { /* build TSr payload */
- linked_list_t *ts_list;
- ts_payload_t *ts_payload;
-
- ts_list = this->policy->get_other_traffic_selectors(this->policy, other);
- ts_payload = ts_payload_create_from_traffic_selectors(FALSE, ts_list);
- ts_list->destroy_offset(ts_list, offsetof(traffic_selector_t, destroy));
-
- request->add_payload(request, (payload_t*)ts_payload);
- }
-
- return SUCCESS;
-}
-
-/**
- * Handle all kind of notifies
- */
-static status_t process_notifies(private_ike_auth_t *this, notify_payload_t *notify_payload)
-{
- notify_type_t notify_type = notify_payload->get_notify_type(notify_payload);
-
- DBG2(DBG_IKE, "process notify type %N", notify_type_names, notify_type);
-
- switch (notify_type)
- {
- /* these notifies are not critical. no child_sa is built, but IKE stays alive */
- case SINGLE_PAIR_REQUIRED:
- {
- SIG(CHILD_UP_FAILED, "received a SINGLE_PAIR_REQUIRED notify");
- this->build_child = FALSE;
- return SUCCESS;
- }
- case TS_UNACCEPTABLE:
- {
- SIG(CHILD_UP_FAILED, "received TS_UNACCEPTABLE notify");
- this->build_child = FALSE;
- return SUCCESS;
- }
- case NO_PROPOSAL_CHOSEN:
- {
- SIG(CHILD_UP_FAILED, "received NO_PROPOSAL_CHOSEN notify");
- this->build_child = FALSE;
- return SUCCESS;
- }
- case EAP_ONLY_AUTHENTICATION:
- {
- DBG1(DBG_IKE, "peer requested EAP_ONLY_AUTHENTICATION");
- this->eap_only = TRUE;
- return SUCCESS;
- }
- case USE_TRANSPORT_MODE:
- {
- this->mode = MODE_TRANSPORT;
- return SUCCESS;
- }
- case USE_BEET_MODE:
- {
- this->mode = MODE_BEET;
- return SUCCESS;
- }
- default:
- {
- if (notify_type < 16383)
- {
- SIG(IKE_UP_FAILED, "received %N notify error, deleting IKE_SA",
- notify_type_names, notify_type);
- return DESTROY_ME;
- }
- else
- {
- DBG1(DBG_IKE, "received %N notify, ignored",
- notify_type_names, notify_type);
- return SUCCESS;
- }
- }
- }
-}
-
-/**
- * Import certificate requests from a certreq payload
- */
-static void process_certificate_request(private_ike_auth_t *this,
- certreq_payload_t *certreq_payload)
-{
- chunk_t keyids;
- cert_encoding_t encoding = certreq_payload->get_cert_encoding(certreq_payload);
-
- if (encoding != CERT_X509_SIGNATURE)
- {
- DBG1(DBG_IKE, "certreq payload %N not supported, ignored",
- cert_encoding_names, encoding);
- return;
- }
-
- keyids = certreq_payload->get_data(certreq_payload);
- while (keyids.len >= HASH_SIZE_SHA1)
- {
- chunk_t keyid = { keyids.ptr, HASH_SIZE_SHA1};
- x509_t *cacert = charon->credentials->get_ca_certificate_by_keyid(
- charon->credentials, keyid);
- if (cacert)
- {
- DBG2(DBG_IKE, "request for certificate issued by ca '%D'",
- cacert->get_subject(cacert));
- this->cacerts->insert_last(this->cacerts, cacert);
- }
- else
- {
- DBG2(DBG_IKE, "request for certificate issued by unknown ca");
- }
- DBG2(DBG_IKE, " with keyid %#B", &keyid);
-
- keyids.ptr += HASH_SIZE_SHA1;
- keyids.len -= HASH_SIZE_SHA1;
- }
-}
-
-/**
- * Import a certificate from a cert payload
- */
-static void import_certificate(cert_payload_t *cert_payload)
-{
- bool found;
- x509_t *cert;
- cert_encoding_t encoding;
-
- encoding = cert_payload->get_cert_encoding(cert_payload);
- if (encoding != CERT_X509_SIGNATURE)
- {
- DBG1(DBG_IKE, "certificate payload %N not supported, ignored",
- cert_encoding_names, encoding);
- return;
- }
- cert = x509_create_from_chunk(cert_payload->get_data_clone(cert_payload));
- if (cert)
- {
- if (charon->credentials->verify(charon->credentials, cert, &found))
- {
- DBG2(DBG_IKE, "received end entity certificate is trusted, added to store");
- if (!found)
- {
- charon->credentials->add_end_certificate(charon->credentials, cert);
- }
- else
- {
- cert->destroy(cert);
- }
- }
- else
- {
- DBG1(DBG_IKE, "received end entity certificate is not trusted, discarded");
- cert->destroy(cert);
- }
- }
- else
- {
- DBG1(DBG_IKE, "parsing of received certificate failed, discarded");
- }
-}
-
-/**
- * Check a list of traffic selectors if any selector belongs to host
- */
-static bool ts_list_is_host(linked_list_t *list, host_t *host)
-{
- traffic_selector_t *ts;
- bool is_host = TRUE;
- iterator_t *iterator = list->create_iterator(list, TRUE);
-
- while (is_host && iterator->iterate(iterator, (void**)&ts))
- {
- is_host = is_host && ts->is_host(ts, host);
- }
- iterator->destroy(iterator);
- return is_host;
-}
-
-/**
- * Install a CHILD_SA for usage
- */
-static status_t install_child_sa(private_ike_auth_t *this, bool initiator)
-{
- prf_plus_t *prf_plus;
- chunk_t seed;
- status_t status;
-
- seed = chunk_alloc(this->nonce_i.len + this->nonce_r.len);
- memcpy(seed.ptr, this->nonce_i.ptr, this->nonce_i.len);
- memcpy(seed.ptr + this->nonce_i.len, this->nonce_r.ptr, this->nonce_r.len);
- prf_plus = prf_plus_create(this->ike_sa->get_child_prf(this->ike_sa), seed);
- chunk_free(&seed);
-
- if (initiator)
- {
- status = this->child_sa->update(this->child_sa, this->proposal,
- this->mode, prf_plus);
- }
- else
- {
- status = this->child_sa->add(this->child_sa, this->proposal,
- this->mode, prf_plus);
- }
- prf_plus->destroy(prf_plus);
- if (status != SUCCESS)
- {
- return DESTROY_ME;
- }
- if (initiator)
- {
- status = this->child_sa->add_policies(this->child_sa, this->tsi,
- this->tsr, this->mode);
- }
- else
- {
- status = this->child_sa->add_policies(this->child_sa, this->tsr,
- this->tsi, this->mode);
- }
- if (status != SUCCESS)
- {
- return DESTROY_ME;
- }
-
- /* add to IKE_SA, and remove from transaction */
- this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
- this->ike_sa->add_child_sa(this->ike_sa, this->child_sa);
- this->child_sa = NULL;
- return SUCCESS;
-}
-
-/**
- * create a CHILD SA, install it, and build response message
- */
-static void setup_child_sa(private_ike_auth_t *this, message_t *response)
-{
- bool use_natt;
- u_int32_t soft_lifetime, hard_lifetime;
- 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);
-
- soft_lifetime = this->policy->get_soft_lifetime(this->policy);
- hard_lifetime = this->policy->get_hard_lifetime(this->policy);
- use_natt = this->ike_sa->is_natt_enabled(this->ike_sa);
- this->child_sa = child_sa_create(this->reqid, me, other, my_id, other_id,
- soft_lifetime, hard_lifetime,
- this->policy->get_updown(this->policy),
- this->policy->get_hostaccess(this->policy),
- use_natt);
- this->child_sa->set_name(this->child_sa, this->policy->get_name(this->policy));
- /* check mode, and include notify into reply */
- switch (this->mode)
- {
- case MODE_TUNNEL:
- /* is the default */
- break;
- case MODE_TRANSPORT:
- if (!ts_list_is_host(this->tsi, other) ||
- !ts_list_is_host(this->tsr, me))
- {
- this->mode = MODE_TUNNEL;
- DBG1(DBG_IKE, "not using tranport mode, not host-to-host");
- }
- else if (this->ike_sa->is_natt_enabled(this->ike_sa))
- {
- this->mode = MODE_TUNNEL;
- DBG1(DBG_IKE, "not using tranport mode, as connection NATed");
- }
- else
- {
- build_notify(USE_TRANSPORT_MODE, response, FALSE);
- }
- break;
- case MODE_BEET:
- if (!ts_list_is_host(this->tsi, NULL) ||
- !ts_list_is_host(this->tsr, NULL))
- {
- this->mode = MODE_TUNNEL;
- DBG1(DBG_IKE, "not using BEET mode, not host-to-host");
- }
- else
- {
- build_notify(USE_BEET_MODE, response, FALSE);
- }
- break;
- }
-
- if (install_child_sa(this, FALSE) != SUCCESS)
- {
- SIG(CHILD_UP_FAILED, "installing CHILD_SA %s failed, no CHILD_SA created",
- this->policy->get_name(this->policy));
- DBG1(DBG_IKE, "adding NO_PROPOSAL_CHOSEN notify to response");
- build_notify(NO_PROPOSAL_CHOSEN, response, FALSE);
- }
- else
- {
- /* build SA and TS payloads */
- SIG(CHILD_UP_SUCCESS, "CHILD_SA created");
- ts_payload_t *ts_response;
- sa_payload_t *sa_response = sa_payload_create();
- sa_response->add_proposal(sa_response, this->proposal);
- response->add_payload(response, (payload_t*)sa_response);
- ts_response = ts_payload_create_from_traffic_selectors(TRUE, this->tsi);
- response->add_payload(response, (payload_t*)ts_response);
- ts_response = ts_payload_create_from_traffic_selectors(FALSE, this->tsr);
- response->add_payload(response, (payload_t*)ts_response);
- }
-}
-
-/**
- * clone the transaction to requeue it for EAP handling
- */
-static private_ike_auth_t *clone_for_eap(private_ike_auth_t *this)
-{
- private_ike_auth_t *clone;
- clone = (private_ike_auth_t*)ike_auth_create(this->ike_sa);
-
- clone->tsi = this->tsi; this->tsi = NULL;
- clone->tsr = this->tsr; this->tsr = NULL;
- clone->eap_auth = this->eap_auth; this->eap_auth = NULL;
- clone->eap_next = this->eap_next; this->eap_next = NULL;
- clone->build_child = this->build_child;
- clone->nonce_i = this->nonce_i; this->nonce_i = chunk_empty;
- clone->nonce_r = this->nonce_r; this->nonce_r = chunk_empty;
- clone->child_sa = this->child_sa; this->child_sa = NULL;
- clone->proposal = this->proposal; this->proposal = NULL;
- clone->peer_authenticated = this->peer_authenticated;
- clone->connection = this->connection; this->connection = NULL;
- clone->policy = this->policy; this->policy = NULL;
-
- return clone;
-}
-
-/**
- * Implementation of transaction_t.get_response.
- */
-static status_t get_response(private_ike_auth_t *this, message_t *request,
- message_t **result, transaction_t **next)
-{
- host_t *me, *other;
- identification_t *my_id, *other_id;
- message_t *response;
- status_t status;
- iterator_t *payloads;
- payload_t *payload;
- id_payload_t *idi_request = NULL;
- id_payload_t *idr_request = NULL;
- auth_payload_t *auth_request = NULL;
- certreq_payload_t *certreq_request = NULL;
- cert_payload_t *cert_request = NULL;
- sa_payload_t *sa_request = NULL;
- ts_payload_t *tsi_request = NULL;
- ts_payload_t *tsr_request = NULL;
- eap_payload_t *eap_request = NULL;
- id_payload_t *idr_response;
-
- /* check if we already have built a response (retransmission) */
- if (this->message)
- {
- *result = this->message;
- return SUCCESS;
- }
-
- SIG(CHILD_UP_START, "setting up CHILD_SA along with IKE_AUTH");
-
- 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);
- this->message_id = request->get_message_id(request);
-
- /* set up response */
- response = message_create();
- response->set_source(response, me->clone(me));
- response->set_destination(response, other->clone(other));
- response->set_exchange_type(response, IKE_AUTH);
- response->set_request(response, FALSE);
- response->set_message_id(response, this->message_id);
- response->set_ike_sa_id(response, this->ike_sa->get_id(this->ike_sa));
- this->message = response;
- *result = response;
-
- /* check message type */
- if (request->get_exchange_type(request) != IKE_AUTH)
- {
- SIG(IKE_UP_FAILED, "IKE_AUTH response of invalid type, deleting IKE_SA");
- SIG(CHILD_UP_FAILED, "initiating CHILD_SA failed, unable to create IKE_SA");
- return DESTROY_ME;
- }
-
- /* Iterate over all payloads. */
- payloads = request->get_payload_iterator(request);
- while (payloads->iterate(payloads, (void**)&payload))
- {
- switch (payload->get_type(payload))
- {
- case ID_INITIATOR:
- idi_request = (id_payload_t*)payload;
- break;
- case ID_RESPONDER:
- idr_request = (id_payload_t*)payload;
- break;
- case AUTHENTICATION:
- auth_request = (auth_payload_t*)payload;
- break;
- case CERTIFICATE_REQUEST:
- certreq_request = (certreq_payload_t*)payload;
- process_certificate_request(this, certreq_request);
- break;
- case CERTIFICATE:
- cert_request = (cert_payload_t*)payload;
- break;
- case SECURITY_ASSOCIATION:
- sa_request = (sa_payload_t*)payload;
- break;
- case TRAFFIC_SELECTOR_INITIATOR:
- tsi_request = (ts_payload_t*)payload;
- break;
- case TRAFFIC_SELECTOR_RESPONDER:
- tsr_request = (ts_payload_t*)payload;
- break;
- case EXTENSIBLE_AUTHENTICATION:
- eap_request = (eap_payload_t*)payload;
- break;
- case NOTIFY:
- {
- status = process_notifies(this, (notify_payload_t*)payload);
- if (status == FAILED)
- {
- payloads->destroy(payloads);
- /* we return SUCCESS, returned FAILED means do next transaction */
- return SUCCESS;
- }
- if (status == DESTROY_ME)
- {
- payloads->destroy(payloads);
- SIG(CHILD_UP_FAILED, "initiating CHILD_SA failed, unable to create IKE_SA");
- return DESTROY_ME;
- }
- break;
- }
- default:
- {
- DBG1(DBG_IKE, "ignoring %N payload",
- payload_type_names, payload->get_type(payload));
- break;
- }
- }
- }
- payloads->destroy(payloads);
-
- /* if message contains an EAP payload, we process it */
- if (eap_request && this->eap_auth)
- {
- eap_payload_t *eap_response;
- private_ike_auth_t *next_auth;
-
- status = this->eap_auth->process(this->eap_auth, eap_request, &eap_response);
- response->add_payload(response, (payload_t*)eap_response);
-
- if (status == FAILED)
- {
- /* shut down if EAP message is EAP_FAILURE */
- return DESTROY_ME;
- }
-
- next_auth = clone_for_eap(this);
- next_auth->message_id = this->message_id + 1;
- *next = (transaction_t*)next_auth;
- return SUCCESS;
- }
-
- /* if we do EAP authentication and a AUTH payload comes in, verify it */
- if (auth_request && this->eap_auth)
- {
- auth_payload_t *auth_response;
- authenticator_t *authenticator = (authenticator_t*)this->eap_auth;
-
- if (authenticator->verify(authenticator, this->init_request,
- this->nonce_r, auth_request) != SUCCESS)
- {
- SIG(IKE_UP_FAILED, "authentication with EAP failed, deleting IKE_SA");
- SIG(CHILD_UP_FAILED, "initiating CHILD_SA failed, unable to create IKE_SA");
- build_notify(AUTHENTICATION_FAILED, response, TRUE);
- return DESTROY_ME;
- }
-
- if (authenticator->build(authenticator, this->init_response,
- this->nonce_i, &auth_response) != SUCCESS)
- {
- SIG(IKE_UP_FAILED, "EAP authentication data generation failed, deleting IKE_SA");
- SIG(CHILD_UP_FAILED, "initiating CHILD_SA failed, unable to create IKE_SA");
- build_notify(AUTHENTICATION_FAILED, response, TRUE);
- return DESTROY_ME;
- }
- response->add_payload(response, (payload_t*)auth_response);
-
- SIG(IKE_UP_SUCCESS, "IKE_SA '%s' established between %H[%D]...%H[%D]",
- this->ike_sa->get_name(this->ike_sa), me, my_id, other, other_id);
- this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
-
- setup_child_sa(this, response);
-
- return SUCCESS;
- }
-
- /* check if we have all payloads (AUTH is not checked, not required with EAP) */
- if (!(idi_request && sa_request && tsi_request && tsr_request))
- {
- build_notify(INVALID_SYNTAX, response, TRUE);
- SIG(IKE_UP_FAILED, "request message incomplete, deleting IKE_SA");
- SIG(CHILD_UP_FAILED, "initiating CHILD_SA failed, unable to create IKE_SA");
- return DESTROY_ME;
- }
-
- { /* process ID payload */
- other_id = idi_request->get_identification(idi_request);
- if (idr_request)
- {
- my_id = idr_request->get_identification(idr_request);
- }
- else
- {
- my_id = identification_create_from_encoding(ID_ANY, chunk_empty);
- }
- }
-
- { /* get a policy and process traffic selectors */
- linked_list_t *my_ts, *other_ts;
-
- my_ts = tsr_request->get_traffic_selectors(tsr_request);
- other_ts = tsi_request->get_traffic_selectors(tsi_request);
-
- this->policy = charon->policies->get_policy(charon->policies,
- my_id, other_id,
- my_ts, other_ts,
- me, other);
-
- if (this->policy)
- {
- this->tsr = this->policy->select_my_traffic_selectors(this->policy, my_ts, me);
- this->tsi = this->policy->select_other_traffic_selectors(this->policy, other_ts, other);
- }
- my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
- other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
-
- /* TODO: We should check somehow if we have a policy, but with other
- * traffic selectors. Then we would create a IKE_SA without a CHILD_SA. */
- if (this->policy == NULL)
- {
- SIG(IKE_UP_FAILED, "no acceptable policy for IDs %D - %D found, "
- "deleting IKE_SA", my_id, other_id);
- SIG(CHILD_UP_FAILED, "initiating CHILD_SA failed, unable to create IKE_SA");
- my_id->destroy(my_id);
- other_id->destroy(other_id);
- build_notify(AUTHENTICATION_FAILED, response, TRUE);
- return DESTROY_ME;
- }
- my_id->destroy(my_id);
-
- /* get my id from policy, which must contain a fully qualified valid id */
- my_id = this->policy->get_my_id(this->policy);
- this->ike_sa->set_my_id(this->ike_sa, my_id->clone(my_id));
- this->ike_sa->set_other_id(this->ike_sa, other_id);
-
- idr_response = id_payload_create_from_identification(FALSE, my_id);
- response->add_payload(response, (payload_t*)idr_response);
- }
-
- if (this->policy->get_auth_method(this->policy) == AUTH_RSA &&
- this->connection->get_cert_policy(this->connection) != CERT_NEVER_SEND)
- { /* build certificate payload */
- x509_t *cert;
- cert_payload_t *cert_payload;
-
- cert = charon->credentials->get_certificate(charon->credentials, my_id);
- if (cert)
- {
- cert_payload = cert_payload_create_from_x509(cert);
- response->add_payload(response, (payload_t *)cert_payload);
- }
- else
- {
- DBG1(DBG_IKE, "could not find my certificate, cert payload omitted");
- }
- }
-
- if (cert_request)
- { /* process certificate payload */
- import_certificate(cert_request);
- }
-
- { /* process SA payload */
- linked_list_t *proposal_list;
-
- /* get proposals from request, and select one with ours */
- proposal_list = sa_request->get_proposals(sa_request);
- DBG2(DBG_IKE, "selecting proposals:");
- this->proposal = this->policy->select_proposal(this->policy, proposal_list);
- proposal_list->destroy_offset(proposal_list, offsetof(proposal_t, destroy));
-
- /* do we have a proposal? */
- if (this->proposal == NULL)
- {
- SIG(CHILD_UP_FAILED, "CHILD_SA proposals unacceptable, no CHILD_SA created");
- DBG1(DBG_IKE, "adding NO_PROPOSAL_CHOSEN notify to response");
- build_notify(NO_PROPOSAL_CHOSEN, response, FALSE);
- this->build_child = FALSE;
- }
- /* do we have traffic selectors? */
- else if (this->tsi->get_count(this->tsi) == 0 || this->tsr->get_count(this->tsr) == 0)
- {
- SIG(CHILD_UP_FAILED, "CHILD_SA traffic selectors unacceptable, no CHILD_SA created");
- DBG1(DBG_IKE, "adding TS_UNACCEPTABLE notify to response");
- build_notify(TS_UNACCEPTABLE, response, FALSE);
- this->build_child = FALSE;
- }
- }
-
- if (!this->eap_only || this->policy->get_auth_method(this->policy) != AUTH_EAP)
- { /* build response AUTH payload when not using a mutual EAP authentication */
- auth_payload_t *auth_response;
- authenticator_t *authenticator;
- auth_method_t auth_method;
- status_t status;
-
- auth_method = this->policy->get_auth_method(this->policy);
- if (auth_method == AUTH_EAP)
- {
- SIG(IKE_UP_FAILED,
- "peer does not support EAP only authentication, deleting IKE_SA");
- SIG(CHILD_UP_FAILED,
- "initiating CHILD_SA failed, unable to create IKE_SA");
- build_notify(AUTHENTICATION_FAILED, response, TRUE);
- return DESTROY_ME;
- }
-
- authenticator = authenticator_create(this->ike_sa, auth_method);
- if (authenticator == NULL)
- {
- SIG(IKE_UP_FAILED, "auth method %N not supported, deleting IKE_SA",
- auth_method_names, auth_method);
- SIG(CHILD_UP_FAILED, "initiating CHILD_SA failed, unable to create IKE_SA");
- build_notify(AUTHENTICATION_FAILED, response, TRUE);
- return DESTROY_ME;
- }
- status = authenticator->build(authenticator, this->init_response,
- this->nonce_i, &auth_response);
- authenticator->destroy(authenticator);
- if (status != SUCCESS)
- {
- SIG(IKE_UP_FAILED, "authentication data generation failed, deleting IKE_SA");
- SIG(CHILD_UP_FAILED, "initiating CHILD_SA failed, unable to create IKE_SA");
- build_notify(AUTHENTICATION_FAILED, response, TRUE);
- return DESTROY_ME;
- }
- response->add_payload(response, (payload_t*)auth_response);
- }
-
- if (auth_request)
- { /* process auth payload, if not using EAP */
- authenticator_t *authenticator;
- auth_method_t auth_method;
- status_t status;
-
- auth_method = auth_request->get_auth_method(auth_request);
- authenticator = authenticator_create(this->ike_sa, auth_method);
- if (authenticator == NULL)
- {
- SIG(IKE_UP_FAILED, "auth method %N not supported, deleting IKE_SA",
- auth_method_names, auth_method);
- SIG(CHILD_UP_FAILED, "initiating CHILD_SA failed, unable to create IKE_SA");
- return DESTROY_ME;
- }
- status = authenticator->verify(authenticator, this->init_request,
- this->nonce_r, auth_request);
- authenticator->destroy(authenticator);
- if (status != SUCCESS)
- {
- SIG(IKE_UP_FAILED, "authentication failed, deleting IKE_SA");
- SIG(CHILD_UP_FAILED, "initiating CHILD_SA failed, unable to create IKE_SA");
- build_notify(AUTHENTICATION_FAILED, response, TRUE);
- return DESTROY_ME;
- }
-
- SIG(IKE_UP_SUCCESS, "IKE_SA '%s' established between %H[%D]...%H[%D]",
- this->ike_sa->get_name(this->ike_sa), me, my_id, other, other_id);
- this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
-
- /* set up CHILD_SA if negotiation succeded */
- if (this->build_child)
- {
- setup_child_sa(this, response);
- }
-
- this->peer_authenticated = TRUE;
- }
- else
- {
- /* if no AUTH payload was included, we start with an EAP exchange.
- * eap_response is a request in the EAP meaning, but is
- * contained in a IKEv2 response */
- eap_payload_t *eap_response;
- private_ike_auth_t *next_auth;
- eap_type_t eap_type;
-
- eap_type = this->policy->get_eap_type(this->policy);
- this->eap_auth = eap_authenticator_create(this->ike_sa);
- status = this->eap_auth->initiate(this->eap_auth, eap_type, &eap_response);
- response->add_payload(response, (payload_t*)eap_response);
-
- if (status == FAILED)
- {
- /* EAP initiaton failed, we send the EAP_FAILURE message and quit */
- return DESTROY_ME;
- }
- /* we send an EAP request. to handle the reply, we reschedule
- * this transaction, as it knows how to handle the reply */
- next_auth = clone_for_eap(this);
- next_auth->message_id = this->message_id + 1;
- *next = (transaction_t*)next_auth;
- }
- return SUCCESS;
-}
-
-/**
- * Implementation of transaction_t.conclude
- */
-static status_t conclude(private_ike_auth_t *this, message_t *response,
- transaction_t **next)
-{
- iterator_t *payloads;
- payload_t *payload;
- host_t *me, *other;
- identification_t *other_id, *my_id;
- ts_payload_t *tsi_payload = NULL;
- ts_payload_t *tsr_payload = NULL;
- id_payload_t *idr_payload = NULL;
- cert_payload_t *cert_payload = NULL;
- auth_payload_t *auth_payload = NULL;
- sa_payload_t *sa_payload = NULL;
- eap_payload_t *eap_payload = NULL;
- status_t status;
-
- /* check message type */
- if (response->get_exchange_type(response) != IKE_AUTH)
- {
- SIG(IKE_UP_FAILED, "IKE_AUTH response of invalid type, deleting IKE_SA");
- SIG(CHILD_UP_FAILED, "initiating CHILD_SA failed, unable to create IKE_SA");
- return DESTROY_ME;
- }
-
- 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);
-
- /* Iterate over all payloads to collect them */
- payloads = response->get_payload_iterator(response);
- while (payloads->iterate(payloads, (void**)&payload))
- {
- switch (payload->get_type(payload))
- {
- case ID_RESPONDER:
- idr_payload = (id_payload_t*)payload;
- break;
- case AUTHENTICATION:
- auth_payload = (auth_payload_t*)payload;
- break;
- case CERTIFICATE:
- cert_payload = (cert_payload_t*)payload;
- break;
- case SECURITY_ASSOCIATION:
- sa_payload = (sa_payload_t*)payload;
- break;
- case TRAFFIC_SELECTOR_INITIATOR:
- tsi_payload = (ts_payload_t*)payload;
- break;
- case TRAFFIC_SELECTOR_RESPONDER:
- tsr_payload = (ts_payload_t*)payload;
- break;
- case EXTENSIBLE_AUTHENTICATION:
- eap_payload = (eap_payload_t*)payload;
- break;
- case NOTIFY:
- {
- status = process_notifies(this, (notify_payload_t*)payload);
- if (status == FAILED)
- {
- payloads->destroy(payloads);
- /* we return SUCCESS, as transaction completet */
- return SUCCESS;
- }
- if (status == DESTROY_ME)
- {
- SIG(CHILD_UP_FAILED, "initiating CHILD_SA failed, unable to create IKE_SA");
- payloads->destroy(payloads);
- return status;
- }
- break;
- }
- default:
- {
- DBG1(DBG_IKE, "ignoring payload %N",
- payload_type_names, payload->get_type(payload));
- break;
- }
- }
- }
- payloads->destroy(payloads);
-
- if (idr_payload)
- { /* process idr payload */
- identification_t *configured_other_id;
- int wildcards;
-
- other_id = idr_payload->get_identification(idr_payload);
- configured_other_id = this->policy->get_other_id(this->policy);
-
- if (!other_id->matches(other_id, configured_other_id, &wildcards))
- {
- other_id->destroy(other_id);
- SIG(IKE_UP_FAILED, "other peer uses unacceptable ID (%D, excepted "
- "%D), deleting IKE_SA", other_id, configured_other_id);
- SIG(CHILD_UP_FAILED, "initiating CHILD_SA failed, unable to create IKE_SA");
- return DESTROY_ME;
- }
- /* update other ID. It was already set, but may contain wildcards */
- this->ike_sa->set_other_id(this->ike_sa, other_id);
- }
-
- if (cert_payload)
- { /* process cert payload */
- import_certificate(cert_payload);
- }
-
- if (auth_payload && idr_payload)
- { /* authenticate peer */
- authenticator_t *authenticator;
- auth_method_t auth_method;
- status_t status;
-
- my_id = this->policy->get_my_id(this->policy);
- auth_method = auth_payload->get_auth_method(auth_payload);
- authenticator = authenticator_create(this->ike_sa, auth_method);
- if (authenticator == NULL)
- {
- SIG(IKE_UP_FAILED, "auth method %N not supported, deleting IKE_SA",
- auth_method_names, auth_method);
- SIG(CHILD_UP_FAILED, "initiating CHILD_SA failed, unable to create IKE_SA");
- return DESTROY_ME;
- }
- status = authenticator->verify(authenticator, this->init_response,
- this->nonce_i, auth_payload);
- authenticator->destroy(authenticator);
- if (status != SUCCESS)
- {
- SIG(IKE_UP_FAILED, "authentication of '%D' with %N failed, "
- "deleting IKE_SA", other_id, auth_method_names, auth_method);
- SIG(CHILD_UP_FAILED, "initiating CHILD_SA failed, unable to create IKE_SA");
- return DESTROY_ME;
- }
- this->peer_authenticated = TRUE;
- }
-
- if (eap_payload && this->eap_auth)
- {
- switch (this->eap_auth->process(this->eap_auth, eap_payload, &this->eap_next))
- {
- case SUCCESS:
- {
- /* EAP message was EAP_SUCCESS, send AUTH in next transaction */
- DBG2(DBG_IKE, "EAP authentication exchanges completed successful");
- this->eap_next = NULL;
- /* fall through */
- }
- case NEED_MORE:
- {
- /* EAP message was a EAP_REQUEST, handle it in next transaction */
- private_ike_auth_t *next_auth = clone_for_eap(this);
- next_auth->message_id = this->message_id + 1;
- *next = (transaction_t*)next_auth;
- return SUCCESS;
- }
- case FAILED:
- default:
- {
- /* EAP message was EAP_FAILURE */
- SIG(IKE_UP_FAILED, "EAP authentication failed, deleting IKE_SA");
- SIG(CHILD_UP_FAILED, "initiating CHILD_SA failed, unable to create IKE_SA");
- return DESTROY_ME;
- }
- }
- }
-
- if (!(auth_payload && sa_payload && tsi_payload && tsr_payload))
- {
- SIG(IKE_UP_FAILED, "response message incomplete, deleting IKE_SA");
- SIG(CHILD_UP_FAILED, "initiating CHILD_SA failed, unable to create IKE_SA");
- return DESTROY_ME;
- }
-
- /* if we do EAP authentication and a AUTH payload comes in, verify it */
- if (this->eap_auth &&
- (this->eap_auth->is_mutual(this->eap_auth) || this->peer_authenticated))
- {
- authenticator_t *authenticator = (authenticator_t*)this->eap_auth;
-
- if (authenticator->verify(authenticator, this->init_response,
- this->nonce_i, auth_payload) != SUCCESS)
- {
- SIG(IKE_UP_FAILED, "authentication with EAP failed, deleting IKE_SA");
- SIG(CHILD_UP_FAILED, "initiating CHILD_SA failed, unable to create IKE_SA");
- return DESTROY_ME;
- }
- this->peer_authenticated = TRUE;
- }
-
- if (!this->peer_authenticated)
- {
- SIG(IKE_UP_FAILED, "server didn't send authentication data, deleting IKE_SA");
- SIG(CHILD_UP_FAILED, "initiating CHILD_SA failed, unable to create IKE_SA");
- return DESTROY_ME;
- }
-
- SIG(IKE_UP_SUCCESS, "IKE_SA '%s' established between %H[%D]...%H[%D]",
- this->ike_sa->get_name(this->ike_sa), me, my_id, other, other_id);
- this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
-
- { /* process traffic selectors for us */
- linked_list_t *ts_received = tsi_payload->get_traffic_selectors(tsi_payload);
- this->tsi = this->policy->select_my_traffic_selectors(this->policy, ts_received, me);
- ts_received->destroy_offset(ts_received, offsetof(traffic_selector_t, destroy));
- }
-
- { /* process traffic selectors for other */
- linked_list_t *ts_received = tsr_payload->get_traffic_selectors(tsr_payload);
- this->tsr = this->policy->select_other_traffic_selectors(this->policy, ts_received, other);
- ts_received->destroy_offset(ts_received, offsetof(traffic_selector_t, destroy));
- }
-
- { /* process sa payload */
- linked_list_t *proposal_list;
-
- proposal_list = sa_payload->get_proposals(sa_payload);
- /* we have to re-check here if other's selection is valid */
- this->proposal = this->policy->select_proposal(this->policy, proposal_list);
- proposal_list->destroy_offset(proposal_list, offsetof(proposal_t, destroy));
-
- /* everything fine to create CHILD? */
- if (this->proposal == NULL ||
- this->tsi->get_count(this->tsi) == 0 ||
- this->tsr->get_count(this->tsr) == 0 ||
- !this->build_child)
- {
- SIG(CHILD_UP_FAILED, "CHILD_SA negotiation failed, no CHILD_SA built");
- }
- else
- {
- /* check mode if it is acceptable */
- switch (this->mode)
- {
- case MODE_TUNNEL:
- /* is the default */
- break;
- case MODE_TRANSPORT:
- /* TODO: we should close the CHILD_SA if negotiated
- * mode is not acceptable for us */
- if (!ts_list_is_host(this->tsi, me) ||
- !ts_list_is_host(this->tsr, other))
- {
- this->mode = MODE_TUNNEL;
- DBG1(DBG_IKE, "not using tranport mode, not host-to-host");
- }
- else if (this->ike_sa->is_natt_enabled(this->ike_sa))
- {
- this->mode = MODE_TUNNEL;
- DBG1(DBG_IKE, "not using tranport mode, as connection NATed");
- }
- break;
- case MODE_BEET:
- if (!ts_list_is_host(this->tsi, NULL) ||
- !ts_list_is_host(this->tsr, NULL))
- {
- this->mode = MODE_TUNNEL;
- DBG1(DBG_IKE, "not using BEET mode, not host-to-host");
- }
- break;
- }
-
- if (install_child_sa(this, TRUE) != SUCCESS)
- {
- SIG(CHILD_UP_FAILED, "installing CHILD_SA '%s' failed, no CHILD_SA built",
- this->policy->get_name(this->policy));
- /* TODO: we should send a DELETE for that CHILD to stay
- * synchronous with the peer */
- }
- else
- {
- SIG(CHILD_UP_SUCCESS, "CHILD_SA '%s' created",
- this->policy->get_name(this->policy));
- }
- }
- }
- return SUCCESS;
-}
-
-/**
- * implements transaction_t.destroy
- */
-static void destroy(private_ike_auth_t *this)
-{
- DESTROY_IF(this->message);
- DESTROY_IF(this->proposal);
- DESTROY_IF(this->child_sa);
- DESTROY_IF(this->policy);
- DESTROY_IF(this->connection);
- DESTROY_IF(this->cacerts);
- if (this->eap_auth)
- {
- this->eap_auth->authenticator_interface.destroy(&this->eap_auth->authenticator_interface);
- }
- DESTROY_IF(this->eap_next);
- if (this->tsi)
- {
- this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
- }
- if (this->tsr)
- {
- this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
- }
- chunk_free(&this->nonce_i);
- chunk_free(&this->nonce_r);
- chunk_free(&this->init_request);
- chunk_free(&this->init_response);
- free(this);
-}
-
-/*
- * Described in header.
- */
-ike_auth_t *ike_auth_create(ike_sa_t *ike_sa)
-{
- private_ike_auth_t *this = malloc_thing(private_ike_auth_t);
-
- /* transaction interface functions */
- this->public.transaction.get_request = (status_t(*)(transaction_t*,message_t**))get_request;
- this->public.transaction.get_response = (status_t(*)(transaction_t*,message_t*,message_t**,transaction_t**))get_response;
- this->public.transaction.conclude = (status_t(*)(transaction_t*,message_t*,transaction_t**))conclude;
- this->public.transaction.get_message_id = (u_int32_t(*)(transaction_t*))get_message_id;
- this->public.transaction.requested = (u_int32_t(*)(transaction_t*))requested;
- this->public.transaction.destroy = (void(*)(transaction_t*))destroy;
-
- /* public functions */
- this->public.set_config = (void(*)(ike_auth_t*,connection_t*,policy_t*))set_config;
- this->public.set_reqid = (void(*)(ike_auth_t*,u_int32_t))set_reqid;
- this->public.set_nonces = (void(*)(ike_auth_t*,chunk_t,chunk_t))set_nonces;
- this->public.set_init_messages = (void(*)(ike_auth_t*,chunk_t,chunk_t))set_init_messages;
-
- /* private data */
- this->ike_sa = ike_sa;
- this->message_id = 0;
- this->message = NULL;
- this->requested = 0;
- this->nonce_i = chunk_empty;
- this->nonce_r = chunk_empty;
- this->init_request = chunk_empty;
- this->init_response = chunk_empty;
- this->child_sa = NULL;
- this->proposal = NULL;
- this->policy = NULL;
- this->connection = NULL;
- this->tsi = NULL;
- this->tsr = NULL;
- this->build_child = TRUE;
- this->eap_auth = NULL;
- this->eap_next = NULL;
- this->eap_only = FALSE;
- this->peer_authenticated = FALSE;
- this->reqid = 0;
- this->cacerts = linked_list_create();
- this->mode = MODE_TUNNEL;
-
- return &this->public;
-}