diff options
author | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2010-05-27 15:43:45 +0000 |
---|---|---|
committer | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2010-05-27 15:43:45 +0000 |
commit | 6c2828d075efdfc02348369149b4347447857c8c (patch) | |
tree | 6c9ec7c9f342792e5eb2c2973daa7bbbeb45362e /src/charon/sa/tasks | |
parent | cc7f376e575482c9a4866a4bd0c1f470394d740b (diff) | |
download | vyos-strongswan-6c2828d075efdfc02348369149b4347447857c8c.tar.gz vyos-strongswan-6c2828d075efdfc02348369149b4347447857c8c.zip |
Remove leftovers after source code restructuring.
Diffstat (limited to 'src/charon/sa/tasks')
36 files changed, 0 insertions, 9554 deletions
diff --git a/src/charon/sa/tasks/child_create.c b/src/charon/sa/tasks/child_create.c deleted file mode 100644 index 3f002f263..000000000 --- a/src/charon/sa/tasks/child_create.c +++ /dev/null @@ -1,1351 +0,0 @@ -/* - * Copyright (C) 2008 Tobias Brunner - * Copyright (C) 2005-2008 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 "child_create.h" - -#include <daemon.h> -#include <crypto/diffie_hellman.h> -#include <credentials/certificates/x509.h> -#include <encoding/payloads/sa_payload.h> -#include <encoding/payloads/ke_payload.h> -#include <encoding/payloads/ts_payload.h> -#include <encoding/payloads/nonce_payload.h> -#include <encoding/payloads/notify_payload.h> -#include <processing/jobs/delete_ike_sa_job.h> -#include <processing/jobs/inactivity_job.h> - - -typedef struct private_child_create_t private_child_create_t; - -/** - * Private members of a child_create_t task. - */ -struct private_child_create_t { - - /** - * Public methods and task_t interface. - */ - child_create_t public; - - /** - * Assigned IKE_SA. - */ - ike_sa_t *ike_sa; - - /** - * Are we the initiator? - */ - bool initiator; - - /** - * nonce chosen by us - */ - chunk_t my_nonce; - - /** - * nonce chosen by peer - */ - chunk_t other_nonce; - - /** - * config to create the CHILD_SA from - */ - child_cfg_t *config; - - /** - * list of proposal candidates - */ - linked_list_t *proposals; - - /** - * selected proposal to use for CHILD_SA - */ - proposal_t *proposal; - - /** - * traffic selectors for initiators side - */ - linked_list_t *tsi; - - /** - * traffic selectors for responders side - */ - linked_list_t *tsr; - - /** - * source of triggering packet - */ - traffic_selector_t *packet_tsi; - - /** - * destination of triggering packet - */ - traffic_selector_t *packet_tsr; - - /** - * optional diffie hellman exchange - */ - diffie_hellman_t *dh; - - /** - * group used for DH exchange - */ - diffie_hellman_group_t dh_group; - - /** - * IKE_SAs keymat - */ - keymat_t *keymat; - - /** - * mode the new CHILD_SA uses (transport/tunnel/beet) - */ - ipsec_mode_t mode; - - /** - * IPComp transform to use - */ - ipcomp_transform_t ipcomp; - - /** - * IPComp transform proposed or accepted by the other peer - */ - ipcomp_transform_t ipcomp_received; - - /** - * Own allocated SPI - */ - u_int32_t my_spi; - - /** - * SPI received in proposal - */ - u_int32_t other_spi; - - /** - * Own allocated Compression Parameter Index (CPI) - */ - u_int16_t my_cpi; - - /** - * Other Compression Parameter Index (CPI), received via IPCOMP_SUPPORTED - */ - u_int16_t other_cpi; - - /** - * reqid to use if we are rekeying - */ - u_int32_t reqid; - - /** - * CHILD_SA which gets established - */ - child_sa_t *child_sa; - - /** - * successfully established the CHILD? - */ - bool established; - - /** - * whether the CHILD_SA rekeys an existing one - */ - bool rekey; -}; - -/** - * get the nonce from a message - */ -static status_t get_nonce(message_t *message, chunk_t *nonce) -{ - nonce_payload_t *payload; - - payload = (nonce_payload_t*)message->get_payload(message, NONCE); - if (payload == NULL) - { - return FAILED; - } - *nonce = payload->get_nonce(payload); - return NEED_MORE; -} - -/** - * generate a new nonce to include in a CREATE_CHILD_SA message - */ -static status_t generate_nonce(chunk_t *nonce) -{ - rng_t *rng; - - rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); - if (!rng) - { - DBG1(DBG_IKE, "error generating nonce value, no RNG found"); - return FAILED; - } - rng->allocate_bytes(rng, NONCE_SIZE, nonce); - rng->destroy(rng); - return SUCCESS; -} - -/** - * 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; -} - -/** - * Allocate SPIs and update proposals - */ -static bool allocate_spi(private_child_create_t *this) -{ - enumerator_t *enumerator; - proposal_t *proposal; - - /* TODO: allocate additional SPI for AH if we have such proposals */ - this->my_spi = this->child_sa->alloc_spi(this->child_sa, PROTO_ESP); - if (this->my_spi) - { - if (this->initiator) - { - enumerator = this->proposals->create_enumerator(this->proposals); - while (enumerator->enumerate(enumerator, &proposal)) - { - proposal->set_spi(proposal, this->my_spi); - } - enumerator->destroy(enumerator); - } - else - { - this->proposal->set_spi(this->proposal, this->my_spi); - } - return TRUE; - } - return FALSE; -} - -/** - * Schedule inactivity timeout for CHILD_SA with reqid, if enabled - */ -static void schedule_inactivity_timeout(private_child_create_t *this) -{ - u_int32_t timeout; - bool close_ike; - - timeout = this->config->get_inactivity(this->config); - if (timeout) - { - close_ike = lib->settings->get_bool(lib->settings, - "charon.inactivity_close_ike", FALSE); - charon->scheduler->schedule_job(charon->scheduler, (job_t*) - inactivity_job_create(this->child_sa->get_reqid(this->child_sa), - timeout, close_ike), timeout); - } -} - -/** - * Install a CHILD_SA for usage, return value: - * - FAILED: no acceptable proposal - * - INVALID_ARG: diffie hellman group inacceptable - * - NOT_FOUND: TS inacceptable - */ -static status_t select_and_install(private_child_create_t *this, bool no_dh) -{ - status_t status, status_i, status_o; - chunk_t nonce_i, nonce_r; - chunk_t encr_i = chunk_empty, encr_r = chunk_empty; - chunk_t integ_i = chunk_empty, integ_r = chunk_empty; - linked_list_t *my_ts, *other_ts; - host_t *me, *other, *other_vip, *my_vip; - bool private; - - if (this->proposals == NULL) - { - DBG1(DBG_IKE, "SA payload missing in message"); - return FAILED; - } - if (this->tsi == NULL || this->tsr == NULL) - { - DBG1(DBG_IKE, "TS payloads missing in message"); - return NOT_FOUND; - } - - me = this->ike_sa->get_my_host(this->ike_sa); - other = this->ike_sa->get_other_host(this->ike_sa); - my_vip = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE); - other_vip = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE); - - private = this->ike_sa->supports_extension(this->ike_sa, EXT_STRONGSWAN); - this->proposal = this->config->select_proposal(this->config, - this->proposals, no_dh, private); - if (this->proposal == NULL) - { - DBG1(DBG_IKE, "no acceptable proposal found"); - return FAILED; - } - this->other_spi = this->proposal->get_spi(this->proposal); - - if (!this->initiator && !allocate_spi(this)) - { /* responder has no SPI allocated yet */ - DBG1(DBG_IKE, "allocating SPI failed"); - return FAILED; - } - this->child_sa->set_proposal(this->child_sa, this->proposal); - - if (!this->proposal->has_dh_group(this->proposal, this->dh_group)) - { - u_int16_t group; - - if (this->proposal->get_algorithm(this->proposal, DIFFIE_HELLMAN_GROUP, - &group, NULL)) - { - DBG1(DBG_IKE, "DH group %N inacceptable, requesting %N", - diffie_hellman_group_names, this->dh_group, - diffie_hellman_group_names, group); - this->dh_group = group; - return INVALID_ARG; - } - else - { - DBG1(DBG_IKE, "no acceptable proposal found"); - return FAILED; - } - } - - if (my_vip == NULL) - { - my_vip = me; - } - if (other_vip == NULL) - { - other_vip = other; - } - - if (this->initiator) - { - nonce_i = this->my_nonce; - nonce_r = this->other_nonce; - my_ts = this->tsi; - other_ts = this->tsr; - } - else - { - nonce_r = this->my_nonce; - nonce_i = this->other_nonce; - my_ts = this->tsr; - other_ts = this->tsi; - } - my_ts = this->config->get_traffic_selectors(this->config, TRUE, my_ts, - my_vip); - other_ts = this->config->get_traffic_selectors(this->config, FALSE, other_ts, - other_vip); - - if (my_ts->get_count(my_ts) == 0 || other_ts->get_count(other_ts) == 0) - { - my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy)); - other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy)); - DBG1(DBG_IKE, "no acceptable traffic selectors found"); - return NOT_FOUND; - } - - this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy)); - this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy)); - if (this->initiator) - { - this->tsi = my_ts; - this->tsr = other_ts; - } - else - { - this->tsr = my_ts; - this->tsi = other_ts; - } - - if (!this->initiator) - { - /* check if requested mode is acceptable, downgrade if required */ - switch (this->mode) - { - case MODE_TRANSPORT: - if (!this->config->use_proxy_mode(this->config) && - (!ts_list_is_host(this->tsi, other) || - !ts_list_is_host(this->tsr, me)) - ) - { - this->mode = MODE_TUNNEL; - DBG1(DBG_IKE, "not using transport mode, not host-to-host"); - } - else if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY)) - { - this->mode = MODE_TUNNEL; - DBG1(DBG_IKE, "not using transport mode, 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; - default: - break; - } - } - - /* check for any certificate-based IP address block constraints */ - if (this->mode == MODE_BEET || this->mode == MODE_TUNNEL) - { - auth_cfg_t *auth; - enumerator_t *auth_enum; - certificate_t *cert = NULL; - - auth_enum = this->ike_sa->create_auth_cfg_enumerator(this->ike_sa, FALSE); - while (auth_enum->enumerate(auth_enum, &auth)) - { - cert = auth->get(auth, AUTH_HELPER_SUBJECT_CERT); - if (cert) - { - break; - } - } - auth_enum->destroy(auth_enum); - - if (cert && cert->get_type(cert) == CERT_X509) - { - x509_t *x509 = (x509_t*)cert; - - if (x509->get_flags(x509) & X509_IP_ADDR_BLOCKS) - { - enumerator_t *enumerator, *block_enum; - traffic_selector_t *ts, *block_ts; - - DBG1(DBG_IKE, "checking certificate-based traffic selector " - "constraints [RFC 3779]"); - enumerator = other_ts->create_enumerator(other_ts); - while (enumerator->enumerate(enumerator, &ts)) - { - bool contained = FALSE; - - block_enum = x509->create_ipAddrBlock_enumerator(x509); - while (block_enum->enumerate(block_enum, &block_ts)) - { - if (ts->is_contained_in(ts, block_ts)) - { - DBG1(DBG_IKE, " TS %R is contained in address block" - " constraint %R", ts, block_ts); - contained = TRUE; - break; - } - } - block_enum->destroy(block_enum); - - if (!contained) - { - DBG1(DBG_IKE, " TS %R is not contained in any" - " address block constraint", ts); - enumerator->destroy(enumerator); - return FAILED; - } - } - enumerator->destroy(enumerator); - } - } - } - - this->child_sa->set_state(this->child_sa, CHILD_INSTALLING); - this->child_sa->set_ipcomp(this->child_sa, this->ipcomp); - this->child_sa->set_mode(this->child_sa, this->mode); - this->child_sa->set_protocol(this->child_sa, - this->proposal->get_protocol(this->proposal)); - - if (this->my_cpi == 0 || this->other_cpi == 0 || this->ipcomp == IPCOMP_NONE) - { - this->my_cpi = this->other_cpi = 0; - this->ipcomp = IPCOMP_NONE; - } - status_i = status_o = FAILED; - if (this->keymat->derive_child_keys(this->keymat, this->proposal, - this->dh, nonce_i, nonce_r, &encr_i, &integ_i, &encr_r, &integ_r)) - { - if (this->initiator) - { - status_i = this->child_sa->install(this->child_sa, encr_r, integ_r, - this->my_spi, this->my_cpi, TRUE, my_ts, other_ts); - status_o = this->child_sa->install(this->child_sa, encr_i, integ_i, - this->other_spi, this->other_cpi, FALSE, my_ts, other_ts); - } - else - { - status_i = this->child_sa->install(this->child_sa, encr_i, integ_i, - this->my_spi, this->my_cpi, TRUE, my_ts, other_ts); - status_o = this->child_sa->install(this->child_sa, encr_r, integ_r, - this->other_spi, this->other_cpi, FALSE, my_ts, other_ts); - } - } - chunk_clear(&integ_i); - chunk_clear(&integ_r); - chunk_clear(&encr_i); - chunk_clear(&encr_r); - - if (status_i != SUCCESS || status_o != SUCCESS) - { - DBG1(DBG_IKE, "unable to install %s%s%sIPsec SA (SAD) in kernel", - (status_i != SUCCESS) ? "inbound " : "", - (status_i != SUCCESS && status_o != SUCCESS) ? "and ": "", - (status_o != SUCCESS) ? "outbound " : ""); - return FAILED; - } - - status = this->child_sa->add_policies(this->child_sa, my_ts, other_ts); - if (status != SUCCESS) - { - DBG1(DBG_IKE, "unable to install IPsec policies (SPD) in kernel"); - return NOT_FOUND; - } - - charon->bus->child_keys(charon->bus, this->child_sa, this->dh, - nonce_i, nonce_r); - - /* add to IKE_SA, and remove from task */ - this->child_sa->set_state(this->child_sa, CHILD_INSTALLED); - this->ike_sa->add_child_sa(this->ike_sa, this->child_sa); - this->established = TRUE; - - if (!this->rekey) - { /* a rekeyed SA uses the same reqid, no need for a new job */ - schedule_inactivity_timeout(this); - } - return SUCCESS; -} - -/** - * build the payloads for the message - */ -static void build_payloads(private_child_create_t *this, message_t *message) -{ - sa_payload_t *sa_payload; - nonce_payload_t *nonce_payload; - ke_payload_t *ke_payload; - ts_payload_t *ts_payload; - - /* add SA payload */ - if (this->initiator) - { - sa_payload = sa_payload_create_from_proposal_list(this->proposals); - } - else - { - sa_payload = sa_payload_create_from_proposal(this->proposal); - } - message->add_payload(message, (payload_t*)sa_payload); - - /* add nonce payload if not in IKE_AUTH */ - if (message->get_exchange_type(message) == CREATE_CHILD_SA) - { - nonce_payload = nonce_payload_create(); - nonce_payload->set_nonce(nonce_payload, this->my_nonce); - message->add_payload(message, (payload_t*)nonce_payload); - } - - /* diffie hellman exchange, if PFS enabled */ - if (this->dh) - { - ke_payload = ke_payload_create_from_diffie_hellman(this->dh); - message->add_payload(message, (payload_t*)ke_payload); - } - - /* add TSi/TSr payloads */ - ts_payload = ts_payload_create_from_traffic_selectors(TRUE, this->tsi); - message->add_payload(message, (payload_t*)ts_payload); - ts_payload = ts_payload_create_from_traffic_selectors(FALSE, this->tsr); - message->add_payload(message, (payload_t*)ts_payload); - - /* add a notify if we are not in tunnel mode */ - switch (this->mode) - { - case MODE_TRANSPORT: - message->add_notify(message, FALSE, USE_TRANSPORT_MODE, chunk_empty); - break; - case MODE_BEET: - message->add_notify(message, FALSE, USE_BEET_MODE, chunk_empty); - break; - default: - break; - } -} - -/** - * Adds an IPCOMP_SUPPORTED notify to the message, allocating a CPI - */ -static void add_ipcomp_notify(private_child_create_t *this, - message_t *message, u_int8_t ipcomp) -{ - if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY)) - { - DBG1(DBG_IKE, "IPComp is not supported if either peer is natted, " - "IPComp disabled"); - return; - } - - this->my_cpi = this->child_sa->alloc_cpi(this->child_sa); - if (this->my_cpi) - { - this->ipcomp = ipcomp; - message->add_notify(message, FALSE, IPCOMP_SUPPORTED, - chunk_cata("cc", chunk_from_thing(this->my_cpi), - chunk_from_thing(ipcomp))); - } - else - { - DBG1(DBG_IKE, "unable to allocate a CPI from kernel, IPComp disabled"); - } -} - -/** - * handle a received notify payload - */ -static void handle_notify(private_child_create_t *this, notify_payload_t *notify) -{ - switch (notify->get_notify_type(notify)) - { - case USE_TRANSPORT_MODE: - this->mode = MODE_TRANSPORT; - break; - case USE_BEET_MODE: - if (this->ike_sa->supports_extension(this->ike_sa, EXT_STRONGSWAN)) - { /* handle private use notify only if we know its meaning */ - this->mode = MODE_BEET; - } - else - { - DBG1(DBG_IKE, "received a notify strongSwan uses for BEET " - "mode, but peer implementation unknown, skipped"); - } - break; - case IPCOMP_SUPPORTED: - { - ipcomp_transform_t ipcomp; - u_int16_t cpi; - chunk_t data; - - data = notify->get_notification_data(notify); - cpi = *(u_int16_t*)data.ptr; - ipcomp = (ipcomp_transform_t)(*(data.ptr + 2)); - switch (ipcomp) - { - case IPCOMP_DEFLATE: - this->other_cpi = cpi; - this->ipcomp_received = ipcomp; - break; - case IPCOMP_LZS: - case IPCOMP_LZJH: - default: - DBG1(DBG_IKE, "received IPCOMP_SUPPORTED notify with a " - "transform ID we don't support %N", - ipcomp_transform_names, ipcomp); - break; - } - } - default: - break; - } -} - -/** - * Read payloads from message - */ -static void process_payloads(private_child_create_t *this, message_t *message) -{ - enumerator_t *enumerator; - payload_t *payload; - sa_payload_t *sa_payload; - ke_payload_t *ke_payload; - ts_payload_t *ts_payload; - - /* defaults to TUNNEL mode */ - this->mode = MODE_TUNNEL; - - enumerator = message->create_payload_enumerator(message); - while (enumerator->enumerate(enumerator, &payload)) - { - switch (payload->get_type(payload)) - { - case SECURITY_ASSOCIATION: - sa_payload = (sa_payload_t*)payload; - this->proposals = sa_payload->get_proposals(sa_payload); - break; - case KEY_EXCHANGE: - ke_payload = (ke_payload_t*)payload; - if (!this->initiator) - { - this->dh_group = ke_payload->get_dh_group_number(ke_payload); - this->dh = this->keymat->create_dh(this->keymat, this->dh_group); - } - if (this->dh) - { - this->dh->set_other_public_value(this->dh, - ke_payload->get_key_exchange_data(ke_payload)); - } - break; - case TRAFFIC_SELECTOR_INITIATOR: - ts_payload = (ts_payload_t*)payload; - this->tsi = ts_payload->get_traffic_selectors(ts_payload); - break; - case TRAFFIC_SELECTOR_RESPONDER: - ts_payload = (ts_payload_t*)payload; - this->tsr = ts_payload->get_traffic_selectors(ts_payload); - break; - case NOTIFY: - handle_notify(this, (notify_payload_t*)payload); - break; - default: - break; - } - } - enumerator->destroy(enumerator); -} - -/** - * Implementation of task_t.build for initiator - */ -static status_t build_i(private_child_create_t *this, message_t *message) -{ - host_t *me, *other, *vip; - peer_cfg_t *peer_cfg; - - switch (message->get_exchange_type(message)) - { - case IKE_SA_INIT: - return get_nonce(message, &this->my_nonce); - case CREATE_CHILD_SA: - if (generate_nonce(&this->my_nonce) != SUCCESS) - { - message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty); - return SUCCESS; - } - if (this->dh_group == MODP_NONE) - { - this->dh_group = this->config->get_dh_group(this->config); - } - break; - case IKE_AUTH: - if (message->get_message_id(message) != 1) - { - /* send only in the first request, not in subsequent rounds */ - return NEED_MORE; - } - break; - default: - break; - } - - if (this->reqid) - { - DBG0(DBG_IKE, "establishing CHILD_SA %s{%d}", - this->config->get_name(this->config), this->reqid); - } - else - { - DBG0(DBG_IKE, "establishing CHILD_SA %s", - this->config->get_name(this->config)); - } - - /* reuse virtual IP if we already have one */ - me = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE); - if (me == NULL) - { - me = this->ike_sa->get_my_host(this->ike_sa); - } - other = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE); - if (other == NULL) - { - other = this->ike_sa->get_other_host(this->ike_sa); - } - - /* check if we want a virtual IP, but don't have one */ - peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa); - vip = peer_cfg->get_virtual_ip(peer_cfg); - if (!this->reqid && vip) - { - /* propose a 0.0.0.0/0 or ::/0 subnet when we use virtual ip */ - vip = host_create_any(vip->get_family(vip)); - this->tsi = this->config->get_traffic_selectors(this->config, TRUE, - NULL, vip); - vip->destroy(vip); - } - else - { /* but narrow it for host2host / if we already have a vip */ - this->tsi = this->config->get_traffic_selectors(this->config, TRUE, - NULL, me); - } - this->tsr = this->config->get_traffic_selectors(this->config, FALSE, - NULL, other); - - if (this->packet_tsi) - { - this->tsi->insert_first(this->tsi, - this->packet_tsi->clone(this->packet_tsi)); - } - if (this->packet_tsr) - { - this->tsr->insert_first(this->tsr, - this->packet_tsr->clone(this->packet_tsr)); - } - this->proposals = this->config->get_proposals(this->config, - this->dh_group == MODP_NONE); - this->mode = this->config->get_mode(this->config); - if (this->mode == MODE_TRANSPORT && - this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY)) - { - this->mode = MODE_TUNNEL; - DBG1(DBG_IKE, "not using transport mode, connection NATed"); - } - - this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa), - this->ike_sa->get_other_host(this->ike_sa), this->config, this->reqid, - this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY)); - - if (!allocate_spi(this)) - { - DBG1(DBG_IKE, "unable to allocate SPIs from kernel"); - return FAILED; - } - - if (this->dh_group != MODP_NONE) - { - this->dh = this->keymat->create_dh(this->keymat, this->dh_group); - } - - if (this->config->use_ipcomp(this->config)) - { - /* IPCOMP_DEFLATE is the only transform we support at the moment */ - add_ipcomp_notify(this, message, IPCOMP_DEFLATE); - } - - build_payloads(this, message); - - this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy)); - this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy)); - this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy)); - this->tsi = NULL; - this->tsr = NULL; - this->proposals = NULL; - - return NEED_MORE; -} - -/** - * Implementation of task_t.process for responder - */ -static status_t process_r(private_child_create_t *this, message_t *message) -{ - switch (message->get_exchange_type(message)) - { - case IKE_SA_INIT: - return get_nonce(message, &this->other_nonce); - case CREATE_CHILD_SA: - get_nonce(message, &this->other_nonce); - break; - case IKE_AUTH: - if (message->get_message_id(message) != 1) - { - /* only handle first AUTH payload, not additional rounds */ - return NEED_MORE; - } - default: - break; - } - - process_payloads(this, message); - - return NEED_MORE; -} - -/** - * handle CHILD_SA setup failure - */ -static void handle_child_sa_failure(private_child_create_t *this, - message_t *message) -{ - if (message->get_exchange_type(message) == IKE_AUTH && - lib->settings->get_bool(lib->settings, - "charon.close_ike_on_child_failure", FALSE)) - { - /* we delay the delete for 100ms, as the IKE_AUTH response must arrive - * first */ - DBG1(DBG_IKE, "closing IKE_SA due CHILD_SA setup failure"); - charon->scheduler->schedule_job_ms(charon->scheduler, (job_t*) - delete_ike_sa_job_create(this->ike_sa->get_id(this->ike_sa), TRUE), - 100); - } -} - -/** - * Implementation of task_t.build for responder - */ -static status_t build_r(private_child_create_t *this, message_t *message) -{ - peer_cfg_t *peer_cfg; - payload_t *payload; - enumerator_t *enumerator; - bool no_dh = TRUE; - - switch (message->get_exchange_type(message)) - { - case IKE_SA_INIT: - return get_nonce(message, &this->my_nonce); - case CREATE_CHILD_SA: - if (generate_nonce(&this->my_nonce) != SUCCESS) - { - message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, - chunk_empty); - return SUCCESS; - } - no_dh = FALSE; - break; - case IKE_AUTH: - if (this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED) - { /* wait until all authentication round completed */ - return NEED_MORE; - } - default: - break; - } - - if (this->ike_sa->get_state(this->ike_sa) == IKE_REKEYING) - { - DBG1(DBG_IKE, "unable to create CHILD_SA while rekeying IKE_SA"); - message->add_notify(message, TRUE, NO_ADDITIONAL_SAS, chunk_empty); - return SUCCESS; - } - - peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa); - if (peer_cfg && this->tsi && this->tsr) - { - host_t *me, *other; - - me = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE); - if (me == NULL) - { - me = this->ike_sa->get_my_host(this->ike_sa); - } - other = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE); - if (other == NULL) - { - other = this->ike_sa->get_other_host(this->ike_sa); - } - this->config = peer_cfg->select_child_cfg(peer_cfg, this->tsr, - this->tsi, me, other); - } - - if (this->config == NULL) - { - DBG1(DBG_IKE, "traffic selectors %#R=== %#R inacceptable", - this->tsr, this->tsi); - message->add_notify(message, FALSE, TS_UNACCEPTABLE, chunk_empty); - handle_child_sa_failure(this, message); - return SUCCESS; - } - - /* check if ike_config_t included non-critical error notifies */ - 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; - - switch (notify->get_notify_type(notify)) - { - case INTERNAL_ADDRESS_FAILURE: - case FAILED_CP_REQUIRED: - { - DBG1(DBG_IKE,"configuration payload negotation " - "failed, no CHILD_SA built"); - enumerator->destroy(enumerator); - handle_child_sa_failure(this, message); - return SUCCESS; - } - default: - break; - } - } - } - enumerator->destroy(enumerator); - - this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa), - this->ike_sa->get_other_host(this->ike_sa), this->config, this->reqid, - this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY)); - - if (this->ipcomp_received != IPCOMP_NONE) - { - if (this->config->use_ipcomp(this->config)) - { - add_ipcomp_notify(this, message, this->ipcomp_received); - } - else - { - DBG1(DBG_IKE, "received %N notify but IPComp is disabled, ignoring", - notify_type_names, IPCOMP_SUPPORTED); - } - } - - switch (select_and_install(this, no_dh)) - { - case SUCCESS: - break; - case NOT_FOUND: - message->add_notify(message, FALSE, TS_UNACCEPTABLE, chunk_empty); - handle_child_sa_failure(this, message); - return SUCCESS; - case INVALID_ARG: - { - u_int16_t group = htons(this->dh_group); - message->add_notify(message, FALSE, INVALID_KE_PAYLOAD, - chunk_from_thing(group)); - handle_child_sa_failure(this, message); - return SUCCESS; - } - case FAILED: - default: - message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty); - handle_child_sa_failure(this, message); - return SUCCESS; - } - - build_payloads(this, message); - - DBG0(DBG_IKE, "CHILD_SA %s{%d} established " - "with SPIs %.8x_i %.8x_o and TS %#R=== %#R", - this->child_sa->get_name(this->child_sa), - this->child_sa->get_reqid(this->child_sa), - ntohl(this->child_sa->get_spi(this->child_sa, TRUE)), - ntohl(this->child_sa->get_spi(this->child_sa, FALSE)), - this->child_sa->get_traffic_selectors(this->child_sa, TRUE), - this->child_sa->get_traffic_selectors(this->child_sa, FALSE)); - - if (!this->rekey) - { /* invoke the child_up() hook if we are not rekeying */ - charon->bus->child_updown(charon->bus, this->child_sa, TRUE); - } - return SUCCESS; -} - -/** - * Implementation of task_t.process for initiator - */ -static status_t process_i(private_child_create_t *this, message_t *message) -{ - enumerator_t *enumerator; - payload_t *payload; - bool no_dh = TRUE; - - switch (message->get_exchange_type(message)) - { - case IKE_SA_INIT: - return get_nonce(message, &this->other_nonce); - case CREATE_CHILD_SA: - get_nonce(message, &this->other_nonce); - no_dh = FALSE; - break; - case IKE_AUTH: - if (this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED) - { /* wait until all authentication round completed */ - return NEED_MORE; - } - default: - break; - } - - /* check for erronous notifies */ - 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) - { - /* handle notify errors related to CHILD_SA only */ - 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: - { - DBG1(DBG_IKE, "received %N notify, no CHILD_SA built", - notify_type_names, type); - enumerator->destroy(enumerator); - handle_child_sa_failure(this, message); - /* an error in CHILD_SA creation is not critical */ - return SUCCESS; - } - case INVALID_KE_PAYLOAD: - { - chunk_t data; - u_int16_t group = MODP_NONE; - - data = notify->get_notification_data(notify); - if (data.len == sizeof(group)) - { - memcpy(&group, data.ptr, data.len); - group = ntohs(group); - } - DBG1(DBG_IKE, "peer didn't accept DH group %N, " - "it requested %N", diffie_hellman_group_names, - this->dh_group, diffie_hellman_group_names, group); - this->dh_group = group; - this->public.task.migrate(&this->public.task, this->ike_sa); - enumerator->destroy(enumerator); - return NEED_MORE; - } - default: - break; - } - } - } - enumerator->destroy(enumerator); - - process_payloads(this, message); - - if (this->ipcomp == IPCOMP_NONE && this->ipcomp_received != IPCOMP_NONE) - { - DBG1(DBG_IKE, "received an IPCOMP_SUPPORTED notify without requesting" - " one, no CHILD_SA built"); - handle_child_sa_failure(this, message); - return SUCCESS; - } - else if (this->ipcomp != IPCOMP_NONE && this->ipcomp_received == IPCOMP_NONE) - { - DBG1(DBG_IKE, "peer didn't accept our proposed IPComp transforms, " - "IPComp is disabled"); - this->ipcomp = IPCOMP_NONE; - } - else if (this->ipcomp != IPCOMP_NONE && this->ipcomp != this->ipcomp_received) - { - DBG1(DBG_IKE, "received an IPCOMP_SUPPORTED notify we didn't propose, " - "no CHILD_SA built"); - handle_child_sa_failure(this, message); - return SUCCESS; - } - - if (select_and_install(this, no_dh) == SUCCESS) - { - DBG0(DBG_IKE, "CHILD_SA %s{%d} established " - "with SPIs %.8x_i %.8x_o and TS %#R=== %#R", - this->child_sa->get_name(this->child_sa), - this->child_sa->get_reqid(this->child_sa), - ntohl(this->child_sa->get_spi(this->child_sa, TRUE)), - ntohl(this->child_sa->get_spi(this->child_sa, FALSE)), - this->child_sa->get_traffic_selectors(this->child_sa, TRUE), - this->child_sa->get_traffic_selectors(this->child_sa, FALSE)); - - if (!this->rekey) - { /* invoke the child_up() hook if we are not rekeying */ - charon->bus->child_updown(charon->bus, this->child_sa, TRUE); - } - } - else - { - handle_child_sa_failure(this, message); - } - return SUCCESS; -} - -/** - * Implementation of task_t.get_type - */ -static task_type_t get_type(private_child_create_t *this) -{ - return CHILD_CREATE; -} - -/** - * Implementation of child_create_t.use_reqid - */ -static void use_reqid(private_child_create_t *this, u_int32_t reqid) -{ - this->reqid = reqid; -} - -/** - * Implementation of child_create_t.get_child - */ -static child_sa_t* get_child(private_child_create_t *this) -{ - return this->child_sa; -} - -/** - * Implementation of child_create_t.get_lower_nonce - */ -static chunk_t get_lower_nonce(private_child_create_t *this) -{ - if (memcmp(this->my_nonce.ptr, this->other_nonce.ptr, - min(this->my_nonce.len, this->other_nonce.len)) < 0) - { - return this->my_nonce; - } - else - { - return this->other_nonce; - } -} - -/** - * Implementation of task_t.migrate - */ -static void migrate(private_child_create_t *this, ike_sa_t *ike_sa) -{ - chunk_free(&this->my_nonce); - chunk_free(&this->other_nonce); - if (this->tsi) - { - this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy)); - } - if (this->tsr) - { - this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy)); - } - DESTROY_IF(this->child_sa); - DESTROY_IF(this->proposal); - DESTROY_IF(this->dh); - if (this->proposals) - { - this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy)); - } - - this->ike_sa = ike_sa; - this->keymat = ike_sa->get_keymat(ike_sa); - this->proposal = NULL; - this->proposals = NULL; - this->tsi = NULL; - this->tsr = NULL; - this->dh = NULL; - this->child_sa = NULL; - this->mode = MODE_TUNNEL; - this->ipcomp = IPCOMP_NONE; - this->ipcomp_received = IPCOMP_NONE; - this->other_cpi = 0; - this->reqid = 0; - this->established = FALSE; -} - -/** - * Implementation of task_t.destroy - */ -static void destroy(private_child_create_t *this) -{ - chunk_free(&this->my_nonce); - chunk_free(&this->other_nonce); - if (this->tsr) - { - this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy)); - } - if (this->tsi) - { - this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy)); - } - if (!this->established) - { - DESTROY_IF(this->child_sa); - } - DESTROY_IF(this->packet_tsi); - DESTROY_IF(this->packet_tsr); - DESTROY_IF(this->proposal); - DESTROY_IF(this->dh); - if (this->proposals) - { - this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy)); - } - - DESTROY_IF(this->config); - free(this); -} - -/* - * Described in header. - */ -child_create_t *child_create_create(ike_sa_t *ike_sa, - child_cfg_t *config, bool rekey, - traffic_selector_t *tsi, traffic_selector_t *tsr) -{ - private_child_create_t *this = malloc_thing(private_child_create_t); - - this->public.get_child = (child_sa_t*(*)(child_create_t*))get_child; - this->public.get_lower_nonce = (chunk_t(*)(child_create_t*))get_lower_nonce; - this->public.use_reqid = (void(*)(child_create_t*,u_int32_t))use_reqid; - 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 (config) - { - this->public.task.build = (status_t(*)(task_t*,message_t*))build_i; - this->public.task.process = (status_t(*)(task_t*,message_t*))process_i; - this->initiator = TRUE; - config->get_ref(config); - } - 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->initiator = FALSE; - } - - this->ike_sa = ike_sa; - this->config = config; - this->my_nonce = chunk_empty; - this->other_nonce = chunk_empty; - this->proposals = NULL; - this->proposal = NULL; - this->tsi = NULL; - this->tsr = NULL; - this->packet_tsi = tsi ? tsi->clone(tsi) : NULL; - this->packet_tsr = tsr ? tsr->clone(tsr) : NULL; - this->dh = NULL; - this->dh_group = MODP_NONE; - this->keymat = ike_sa->get_keymat(ike_sa); - this->child_sa = NULL; - this->mode = MODE_TUNNEL; - this->ipcomp = IPCOMP_NONE; - this->ipcomp_received = IPCOMP_NONE; - this->my_spi = 0; - this->other_spi = 0; - this->my_cpi = 0; - this->other_cpi = 0; - this->reqid = 0; - this->established = FALSE; - this->rekey = rekey; - - return &this->public; -} diff --git a/src/charon/sa/tasks/child_create.h b/src/charon/sa/tasks/child_create.h deleted file mode 100644 index 5dedeb8b1..000000000 --- a/src/charon/sa/tasks/child_create.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2007 Martin Willi - * 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. - */ - -/** - * @defgroup child_create child_create - * @{ @ingroup tasks - */ - -#ifndef CHILD_CREATE_H_ -#define CHILD_CREATE_H_ - -typedef struct child_create_t child_create_t; - -#include <library.h> -#include <sa/ike_sa.h> -#include <sa/tasks/task.h> -#include <config/child_cfg.h> - -/** - * Task of type CHILD_CREATE, established a new CHILD_SA. - * - * This task may be included in the IKE_AUTH message or in a separate - * CREATE_CHILD_SA exchange. - */ -struct child_create_t { - - /** - * Implements the task_t interface - */ - task_t task; - - /** - * Use a specific reqid for the CHILD_SA. - * - * When this task is used for rekeying, the same reqid is used - * for the new CHILD_SA. - * - * @param reqid reqid to use - */ - void (*use_reqid) (child_create_t *this, u_int32_t reqid); - - /** - * Get the lower of the two nonces, used for rekey collisions. - * - * @return lower nonce - */ - chunk_t (*get_lower_nonce) (child_create_t *this); - - /** - * Get the CHILD_SA established/establishing by this task. - * - * @return child_sa - */ - child_sa_t* (*get_child) (child_create_t *this); -}; - -/** - * Create a new child_create task. - * - * @param ike_sa IKE_SA this task works for - * @param config child_cfg if task initiator, NULL if responder - * @param rekey whether we do a rekey or not - * @param tsi source of triggering packet, or NULL - * @param tsr destination of triggering packet, or NULL - * @return child_create task to handle by the task_manager - */ -child_create_t *child_create_create(ike_sa_t *ike_sa, - child_cfg_t *config, bool rekey, - traffic_selector_t *tsi, traffic_selector_t *tsr); - -#endif /** CHILD_CREATE_H_ @}*/ diff --git a/src/charon/sa/tasks/child_delete.c b/src/charon/sa/tasks/child_delete.c deleted file mode 100644 index d7c6b0541..000000000 --- a/src/charon/sa/tasks/child_delete.c +++ /dev/null @@ -1,402 +0,0 @@ -/* - * Copyright (C) 2006-2007 Martin Willi - * 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 "child_delete.h" - -#include <daemon.h> -#include <encoding/payloads/delete_payload.h> - - -typedef struct private_child_delete_t private_child_delete_t; - -/** - * Private members of a child_delete_t task. - */ -struct private_child_delete_t { - - /** - * Public methods and task_t interface. - */ - child_delete_t public; - - /** - * Assigned IKE_SA. - */ - ike_sa_t *ike_sa; - - /** - * Are we the initiator? - */ - bool initiator; - - /** - * Protocol of CHILD_SA to delete - */ - protocol_id_t protocol; - - /** - * Inbound SPI of CHILD_SA to delete - */ - u_int32_t spi; - - /** - * whether to enforce delete action policy - */ - bool check_delete_action; - - /** - * is this delete exchange following a rekey? - */ - bool rekeyed; - - /** - * CHILD_SAs which get deleted - */ - linked_list_t *child_sas; -}; - -/** - * build the delete payloads from the listed child_sas - */ -static void build_payloads(private_child_delete_t *this, message_t *message) -{ - delete_payload_t *ah = NULL, *esp = NULL; - iterator_t *iterator; - child_sa_t *child_sa; - - iterator = this->child_sas->create_iterator(this->child_sas, TRUE); - while (iterator->iterate(iterator, (void**)&child_sa)) - { - protocol_id_t protocol = child_sa->get_protocol(child_sa); - u_int32_t spi = child_sa->get_spi(child_sa, TRUE); - - switch (protocol) - { - case PROTO_ESP: - if (esp == NULL) - { - esp = delete_payload_create(PROTO_ESP); - message->add_payload(message, (payload_t*)esp); - } - esp->add_spi(esp, spi); - DBG1(DBG_IKE, "sending DELETE for %N CHILD_SA with SPI %.8x", - protocol_id_names, protocol, ntohl(spi)); - break; - case PROTO_AH: - if (ah == NULL) - { - ah = delete_payload_create(PROTO_AH); - message->add_payload(message, (payload_t*)ah); - } - ah->add_spi(ah, spi); - DBG1(DBG_IKE, "sending DELETE for %N CHILD_SA with SPI %.8x", - protocol_id_names, protocol, ntohl(spi)); - break; - default: - break; - } - child_sa->set_state(child_sa, CHILD_DELETING); - } - iterator->destroy(iterator); -} - -/** - * read in payloads and find the children to delete - */ -static void process_payloads(private_child_delete_t *this, message_t *message) -{ - enumerator_t *payloads; - iterator_t *spis; - payload_t *payload; - delete_payload_t *delete_payload; - u_int32_t *spi; - protocol_id_t protocol; - child_sa_t *child_sa; - - payloads = message->create_payload_enumerator(message); - while (payloads->enumerate(payloads, &payload)) - { - if (payload->get_type(payload) == DELETE) - { - delete_payload = (delete_payload_t*)payload; - protocol = delete_payload->get_protocol_id(delete_payload); - if (protocol != PROTO_ESP && protocol != PROTO_AH) - { - continue; - } - spis = delete_payload->create_spi_iterator(delete_payload); - while (spis->iterate(spis, (void**)&spi)) - { - child_sa = this->ike_sa->get_child_sa(this->ike_sa, protocol, - *spi, FALSE); - if (child_sa == NULL) - { - DBG1(DBG_IKE, "received DELETE for %N CHILD_SA with SPI %.8x, " - "but no such SA", protocol_id_names, protocol, ntohl(*spi)); - continue; - } - DBG1(DBG_IKE, "received DELETE for %N CHILD_SA with SPI %.8x", - protocol_id_names, protocol, ntohl(*spi)); - - switch (child_sa->get_state(child_sa)) - { - case CHILD_REKEYING: - this->rekeyed = TRUE; - /* we reply as usual, rekeying will fail */ - break; - case CHILD_DELETING: - /* we don't send back a delete if we initiated ourself */ - if (!this->initiator) - { - this->ike_sa->destroy_child_sa(this->ike_sa, - protocol, *spi); - continue; - } - case CHILD_INSTALLED: - if (!this->initiator) - { /* reestablish installed children if required */ - this->check_delete_action = TRUE; - } - default: - break; - } - - this->child_sas->insert_last(this->child_sas, child_sa); - } - spis->destroy(spis); - } - } - payloads->destroy(payloads); -} - -/** - * destroy the children listed in this->child_sas, reestablish by policy - */ -static status_t destroy_and_reestablish(private_child_delete_t *this) -{ - iterator_t *iterator; - child_sa_t *child_sa; - child_cfg_t *child_cfg; - protocol_id_t protocol; - u_int32_t spi; - status_t status = SUCCESS; - - iterator = this->child_sas->create_iterator(this->child_sas, TRUE); - while (iterator->iterate(iterator, (void**)&child_sa)) - { - /* signal child down event if we are not rekeying */ - if (!this->rekeyed) - { - charon->bus->child_updown(charon->bus, child_sa, FALSE); - } - spi = child_sa->get_spi(child_sa, TRUE); - protocol = child_sa->get_protocol(child_sa); - child_cfg = child_sa->get_config(child_sa); - child_cfg->get_ref(child_cfg); - this->ike_sa->destroy_child_sa(this->ike_sa, protocol, spi); - if (this->check_delete_action) - { /* enforce child_cfg policy if deleted passively */ - switch (child_cfg->get_close_action(child_cfg)) - { - case ACTION_RESTART: - child_cfg->get_ref(child_cfg); - status = this->ike_sa->initiate(this->ike_sa, child_cfg, 0, - NULL, NULL); - break; - case ACTION_ROUTE: - charon->traps->install(charon->traps, - this->ike_sa->get_peer_cfg(this->ike_sa), child_cfg); - break; - default: - break; - } - } - child_cfg->destroy(child_cfg); - if (status != SUCCESS) - { - break; - } - } - iterator->destroy(iterator); - return status; -} - -/** - * send closing signals for all CHILD_SAs over the bus - */ -static void log_children(private_child_delete_t *this) -{ - iterator_t *iterator; - child_sa_t *child_sa; - u_int64_t bytes_in, bytes_out; - - iterator = this->child_sas->create_iterator(this->child_sas, TRUE); - while (iterator->iterate(iterator, (void**)&child_sa)) - { - child_sa->get_usestats(child_sa, TRUE, NULL, &bytes_in); - child_sa->get_usestats(child_sa, FALSE, NULL, &bytes_out); - - DBG0(DBG_IKE, "closing CHILD_SA %s{%d} " - "with SPIs %.8x_i (%llu bytes) %.8x_o (%llu bytes) and TS %#R=== %#R", - child_sa->get_name(child_sa), child_sa->get_reqid(child_sa), - ntohl(child_sa->get_spi(child_sa, TRUE)), bytes_in, - ntohl(child_sa->get_spi(child_sa, FALSE)), bytes_out, - child_sa->get_traffic_selectors(child_sa, TRUE), - child_sa->get_traffic_selectors(child_sa, FALSE)); - } - iterator->destroy(iterator); -} - -/** - * Implementation of task_t.build for initiator - */ -static status_t build_i(private_child_delete_t *this, message_t *message) -{ - child_sa_t *child_sa; - - child_sa = this->ike_sa->get_child_sa(this->ike_sa, this->protocol, - this->spi, TRUE); - if (!child_sa) - { /* check if it is an outbound sa */ - child_sa = this->ike_sa->get_child_sa(this->ike_sa, this->protocol, - this->spi, FALSE); - if (!child_sa) - { /* child does not exist anymore */ - return SUCCESS; - } - /* we work only with the inbound SPI */ - this->spi = child_sa->get_spi(child_sa, TRUE); - } - this->child_sas->insert_last(this->child_sas, child_sa); - if (child_sa->get_state(child_sa) == CHILD_REKEYING) - { - this->rekeyed = TRUE; - } - log_children(this); - build_payloads(this, message); - return NEED_MORE; -} - -/** - * Implementation of task_t.process for initiator - */ -static status_t process_i(private_child_delete_t *this, message_t *message) -{ - /* flush the list before adding new SAs */ - this->child_sas->destroy(this->child_sas); - this->child_sas = linked_list_create(); - - process_payloads(this, message); - DBG1(DBG_IKE, "CHILD_SA closed"); - return destroy_and_reestablish(this); -} - -/** - * Implementation of task_t.process for initiator - */ -static status_t process_r(private_child_delete_t *this, message_t *message) -{ - process_payloads(this, message); - log_children(this); - return NEED_MORE; -} - -/** - * Implementation of task_t.build for responder - */ -static status_t build_r(private_child_delete_t *this, message_t *message) -{ - /* if we are rekeying, we send an empty informational */ - if (this->ike_sa->get_state(this->ike_sa) != IKE_REKEYING) - { - build_payloads(this, message); - } - DBG1(DBG_IKE, "CHILD_SA closed"); - return destroy_and_reestablish(this); -} - -/** - * Implementation of task_t.get_type - */ -static task_type_t get_type(private_child_delete_t *this) -{ - return CHILD_DELETE; -} - -/** - * Implementation of child_delete_t.get_child - */ -static child_sa_t* get_child(private_child_delete_t *this) -{ - child_sa_t *child_sa = NULL; - this->child_sas->get_first(this->child_sas, (void**)&child_sa); - return child_sa; -} - -/** - * Implementation of task_t.migrate - */ -static void migrate(private_child_delete_t *this, ike_sa_t *ike_sa) -{ - this->check_delete_action = FALSE; - this->ike_sa = ike_sa; - - this->child_sas->destroy(this->child_sas); - this->child_sas = linked_list_create(); -} - -/** - * Implementation of task_t.destroy - */ -static void destroy(private_child_delete_t *this) -{ - this->child_sas->destroy(this->child_sas); - free(this); -} - -/* - * Described in header. - */ -child_delete_t *child_delete_create(ike_sa_t *ike_sa, protocol_id_t protocol, - u_int32_t spi) -{ - private_child_delete_t *this = malloc_thing(private_child_delete_t); - - this->public.get_child = (child_sa_t*(*)(child_delete_t*))get_child; - 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->ike_sa = ike_sa; - this->check_delete_action = FALSE; - this->child_sas = linked_list_create(); - this->protocol = protocol; - this->spi = spi; - this->rekeyed = FALSE; - - if (protocol != PROTO_NONE) - { - this->public.task.build = (status_t(*)(task_t*,message_t*))build_i; - this->public.task.process = (status_t(*)(task_t*,message_t*))process_i; - this->initiator = TRUE; - } - 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->initiator = FALSE; - } - return &this->public; -} diff --git a/src/charon/sa/tasks/child_delete.h b/src/charon/sa/tasks/child_delete.h deleted file mode 100644 index 365807c68..000000000 --- a/src/charon/sa/tasks/child_delete.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2007 Martin Willi - * 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. - */ - -/** - * @defgroup child_delete child_delete - * @{ @ingroup tasks - */ - -#ifndef CHILD_DELETE_H_ -#define CHILD_DELETE_H_ - -typedef struct child_delete_t child_delete_t; - -#include <library.h> -#include <sa/ike_sa.h> -#include <sa/tasks/task.h> -#include <sa/child_sa.h> - -/** - * Task of type child_delete, delete a CHILD_SA. - */ -struct child_delete_t { - - /** - * Implements the task_t interface - */ - task_t task; - - /** - * Get the CHILD_SA to delete by this task. - * - * @return child_sa - */ - child_sa_t* (*get_child) (child_delete_t *this); -}; - -/** - * Create a new child_delete task. - * - * @param ike_sa IKE_SA this task works for - * @param protocol protocol of CHILD_SA to delete, PROTO_NONE as responder - * @param spi inbound SPI of CHILD_SA to delete - * @return child_delete task to handle by the task_manager - */ -child_delete_t *child_delete_create(ike_sa_t *ike_sa, protocol_id_t protocol, - u_int32_t spi); - -#endif /** CHILD_DELETE_H_ @}*/ diff --git a/src/charon/sa/tasks/child_rekey.c b/src/charon/sa/tasks/child_rekey.c deleted file mode 100644 index b5e4e84b4..000000000 --- a/src/charon/sa/tasks/child_rekey.c +++ /dev/null @@ -1,430 +0,0 @@ -/* - * Copyright (C) 2005-2007 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 "child_rekey.h" - -#include <daemon.h> -#include <encoding/payloads/notify_payload.h> -#include <sa/tasks/child_create.h> -#include <sa/tasks/child_delete.h> -#include <processing/jobs/rekey_child_sa_job.h> -#include <processing/jobs/rekey_ike_sa_job.h> - - -typedef struct private_child_rekey_t private_child_rekey_t; - -/** - * Private members of a child_rekey_t task. - */ -struct private_child_rekey_t { - - /** - * Public methods and task_t interface. - */ - child_rekey_t public; - - /** - * Assigned IKE_SA. - */ - ike_sa_t *ike_sa; - - /** - * Are we the initiator? - */ - bool initiator; - - /** - * Protocol of CHILD_SA to rekey - */ - protocol_id_t protocol; - - /** - * Inbound SPI of CHILD_SA to rekey - */ - u_int32_t spi; - - /** - * the CHILD_CREATE task which is reused to simplify rekeying - */ - child_create_t *child_create; - - /** - * the CHILD_DELETE task to delete rekeyed CHILD_SA - */ - child_delete_t *child_delete; - - /** - * CHILD_SA which gets rekeyed - */ - child_sa_t *child_sa; - - /** - * colliding task, may be delete or rekey - */ - task_t *collision; -}; - -/** - * Implementation of task_t.build for initiator, after rekeying - */ -static status_t build_i_delete(private_child_rekey_t *this, message_t *message) -{ - /* update exchange type to INFORMATIONAL for the delete */ - message->set_exchange_type(message, INFORMATIONAL); - - return this->child_delete->task.build(&this->child_delete->task, message); -} - -/** - * Implementation of task_t.process for initiator, after rekeying - */ -static status_t process_i_delete(private_child_rekey_t *this, message_t *message) -{ - return this->child_delete->task.process(&this->child_delete->task, message); -} - -/** - * find a child using the REKEY_SA notify - */ -static void find_child(private_child_rekey_t *this, message_t *message) -{ - notify_payload_t *notify; - protocol_id_t protocol; - u_int32_t spi; - - notify = message->get_notify(message, REKEY_SA); - if (notify) - { - protocol = notify->get_protocol_id(notify); - spi = notify->get_spi(notify); - - if (protocol == PROTO_ESP || protocol == PROTO_AH) - { - this->child_sa = this->ike_sa->get_child_sa(this->ike_sa, protocol, - spi, FALSE); - } - } -} - -/** - * Implementation of task_t.build for initiator - */ -static status_t build_i(private_child_rekey_t *this, message_t *message) -{ - notify_payload_t *notify; - u_int32_t reqid; - child_cfg_t *config; - - this->child_sa = this->ike_sa->get_child_sa(this->ike_sa, this->protocol, - this->spi, TRUE); - if (!this->child_sa) - { /* check if it is an outbound CHILD_SA */ - this->child_sa = this->ike_sa->get_child_sa(this->ike_sa, this->protocol, - this->spi, FALSE); - if (!this->child_sa) - { /* CHILD_SA is gone, unable to rekey. As an empty CREATE_CHILD_SA - * exchange is invalid, we fall back to an INFORMATIONAL exchange.*/ - message->set_exchange_type(message, INFORMATIONAL); - return SUCCESS; - } - /* we work only with the inbound SPI */ - this->spi = this->child_sa->get_spi(this->child_sa, TRUE); - } - config = this->child_sa->get_config(this->child_sa); - - /* we just need the rekey notify ... */ - notify = notify_payload_create_from_protocol_and_type(this->protocol, - REKEY_SA); - notify->set_spi(notify, this->spi); - message->add_payload(message, (payload_t*)notify); - - /* ... our CHILD_CREATE task does the hard work for us. */ - if (!this->child_create) - { - this->child_create = child_create_create(this->ike_sa, config, TRUE, - NULL, NULL); - } - reqid = this->child_sa->get_reqid(this->child_sa); - this->child_create->use_reqid(this->child_create, reqid); - this->child_create->task.build(&this->child_create->task, message); - - this->child_sa->set_state(this->child_sa, CHILD_REKEYING); - - return NEED_MORE; -} - -/** - * Implementation of task_t.process for initiator - */ -static status_t process_r(private_child_rekey_t *this, message_t *message) -{ - /* let the CHILD_CREATE task process the message */ - this->child_create->task.process(&this->child_create->task, message); - - find_child(this, message); - - return NEED_MORE; -} - -/** - * Implementation of task_t.build for responder - */ -static status_t build_r(private_child_rekey_t *this, message_t *message) -{ - u_int32_t reqid; - - if (this->child_sa == NULL || - this->child_sa->get_state(this->child_sa) == CHILD_DELETING) - { - DBG1(DBG_IKE, "unable to rekey, CHILD_SA not found"); - message->add_notify(message, TRUE, NO_PROPOSAL_CHOSEN, chunk_empty); - return SUCCESS; - } - - /* let the CHILD_CREATE task build the response */ - reqid = this->child_sa->get_reqid(this->child_sa); - this->child_create->use_reqid(this->child_create, reqid); - this->child_create->task.build(&this->child_create->task, message); - - if (message->get_payload(message, SECURITY_ASSOCIATION) == NULL) - { - /* rekeying failed, reuse old child */ - this->child_sa->set_state(this->child_sa, CHILD_INSTALLED); - return SUCCESS; - } - - this->child_sa->set_state(this->child_sa, CHILD_REKEYING); - - /* invoke rekey hook */ - charon->bus->child_rekey(charon->bus, this->child_sa, - this->child_create->get_child(this->child_create)); - return SUCCESS; -} - -/** - * Implementation of task_t.process for initiator - */ -static status_t process_i(private_child_rekey_t *this, message_t *message) -{ - protocol_id_t protocol; - u_int32_t spi; - child_sa_t *to_delete; - - if (message->get_notify(message, NO_ADDITIONAL_SAS)) - { - DBG1(DBG_IKE, "peer seems to not support CHILD_SA rekeying, " - "starting reauthentication"); - this->child_sa->set_state(this->child_sa, CHILD_INSTALLED); - charon->processor->queue_job(charon->processor, - (job_t*)rekey_ike_sa_job_create( - this->ike_sa->get_id(this->ike_sa), TRUE)); - return SUCCESS; - } - - if (this->child_create->task.process(&this->child_create->task, - message) == NEED_MORE) - { - /* bad DH group while rekeying, try again */ - this->child_create->task.migrate(&this->child_create->task, this->ike_sa); - return NEED_MORE; - } - if (message->get_payload(message, SECURITY_ASSOCIATION) == NULL) - { - /* establishing new child failed, reuse old. but not when we - * recieved a delete in the meantime */ - if (!(this->collision && - this->collision->get_type(this->collision) == CHILD_DELETE)) - { - job_t *job; - u_int32_t retry = RETRY_INTERVAL - (random() % RETRY_JITTER); - - job = (job_t*)rekey_child_sa_job_create( - this->child_sa->get_reqid(this->child_sa), - this->child_sa->get_protocol(this->child_sa), - this->child_sa->get_spi(this->child_sa, TRUE)); - DBG1(DBG_IKE, "CHILD_SA rekeying failed, " - "trying again in %d seconds", retry); - this->child_sa->set_state(this->child_sa, CHILD_INSTALLED); - charon->scheduler->schedule_job(charon->scheduler, job, retry); - } - return SUCCESS; - } - - to_delete = this->child_sa; - - /* check for rekey collisions */ - if (this->collision && - this->collision->get_type(this->collision) == CHILD_REKEY) - { - chunk_t this_nonce, other_nonce; - private_child_rekey_t *other = (private_child_rekey_t*)this->collision; - - this_nonce = this->child_create->get_lower_nonce(this->child_create); - other_nonce = other->child_create->get_lower_nonce(other->child_create); - - /* if we have the lower nonce, delete rekeyed SA. If not, delete - * the redundant. */ - if (memcmp(this_nonce.ptr, other_nonce.ptr, - min(this_nonce.len, other_nonce.len)) < 0) - { - DBG1(DBG_IKE, "CHILD_SA rekey collision won, deleting rekeyed child"); - } - else - { - DBG1(DBG_IKE, "CHILD_SA rekey collision lost, deleting redundant child"); - to_delete = this->child_create->get_child(this->child_create); - if (to_delete == NULL) - { - /* ooops, should not happen, fallback */ - to_delete = this->child_sa; - } - } - } - - if (to_delete != this->child_create->get_child(this->child_create)) - { /* invoke rekey hook if rekeying successful */ - charon->bus->child_rekey(charon->bus, this->child_sa, - this->child_create->get_child(this->child_create)); - } - - spi = to_delete->get_spi(to_delete, TRUE); - protocol = to_delete->get_protocol(to_delete); - - /* rekeying done, delete the obsolete CHILD_SA using a subtask */ - this->child_delete = child_delete_create(this->ike_sa, protocol, spi); - this->public.task.build = (status_t(*)(task_t*,message_t*))build_i_delete; - this->public.task.process = (status_t(*)(task_t*,message_t*))process_i_delete; - - return NEED_MORE; -} - -/** - * Implementation of task_t.get_type - */ -static task_type_t get_type(private_child_rekey_t *this) -{ - return CHILD_REKEY; -} - -/** - * Implementation of child_rekey_t.collide - */ -static void collide(private_child_rekey_t *this, task_t *other) -{ - /* the task manager only detects exchange collision, but not if - * the collision is for the same child. we check it here. */ - if (other->get_type(other) == CHILD_REKEY) - { - private_child_rekey_t *rekey = (private_child_rekey_t*)other; - if (rekey == NULL || rekey->child_sa != this->child_sa) - { - /* not the same child => no collision */ - other->destroy(other); - return; - } - } - else if (other->get_type(other) == CHILD_DELETE) - { - child_delete_t *del = (child_delete_t*)other; - if (del == NULL || del->get_child(del) != this->child_sa) - { - /* not the same child => no collision */ - other->destroy(other); - return; - } - } - else - { - /* any other task is not critical for collisisions, ignore */ - other->destroy(other); - return; - } - DESTROY_IF(this->collision); - this->collision = other; -} - -/** - * Implementation of task_t.migrate - */ -static void migrate(private_child_rekey_t *this, ike_sa_t *ike_sa) -{ - if (this->child_create) - { - this->child_create->task.migrate(&this->child_create->task, ike_sa); - } - if (this->child_delete) - { - this->child_delete->task.migrate(&this->child_delete->task, ike_sa); - } - DESTROY_IF(this->collision); - - this->ike_sa = ike_sa; - this->collision = NULL; -} - -/** - * Implementation of task_t.destroy - */ -static void destroy(private_child_rekey_t *this) -{ - if (this->child_create) - { - this->child_create->task.destroy(&this->child_create->task); - } - if (this->child_delete) - { - this->child_delete->task.destroy(&this->child_delete->task); - } - DESTROY_IF(this->collision); - free(this); -} - -/* - * Described in header. - */ -child_rekey_t *child_rekey_create(ike_sa_t *ike_sa, protocol_id_t protocol, - u_int32_t spi) -{ - private_child_rekey_t *this = malloc_thing(private_child_rekey_t); - - this->public.collide = (void (*)(child_rekey_t*,task_t*))collide; - 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 (protocol != PROTO_NONE) - { - this->public.task.build = (status_t(*)(task_t*,message_t*))build_i; - this->public.task.process = (status_t(*)(task_t*,message_t*))process_i; - this->initiator = TRUE; - this->child_create = NULL; - } - 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->initiator = FALSE; - this->child_create = child_create_create(ike_sa, NULL, TRUE, NULL, NULL); - } - - this->ike_sa = ike_sa; - this->child_sa = NULL; - this->protocol = protocol; - this->spi = spi; - this->collision = NULL; - this->child_delete = NULL; - - return &this->public; -} diff --git a/src/charon/sa/tasks/child_rekey.h b/src/charon/sa/tasks/child_rekey.h deleted file mode 100644 index 9b1aea5fa..000000000 --- a/src/charon/sa/tasks/child_rekey.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2007 Martin Willi - * 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. - */ - -/** - * @defgroup child_rekey child_rekey - * @{ @ingroup tasks - */ - -#ifndef CHILD_REKEY_H_ -#define CHILD_REKEY_H_ - -typedef struct child_rekey_t child_rekey_t; - -#include <library.h> -#include <sa/ike_sa.h> -#include <sa/child_sa.h> -#include <sa/tasks/task.h> - -/** - * Task of type CHILD_REKEY, rekey an established CHILD_SA. - */ -struct child_rekey_t { - - /** - * Implements the task_t interface - */ - task_t task; - - /** - * Register a rekeying task which collides with this one - * - * If two peers initiate rekeying at the same time, the collision must - * be handled gracefully. The task manager is aware of what exchanges - * are going on and notifies the outgoing task by passing the incoming. - * - * @param other incoming task - */ - void (*collide)(child_rekey_t* this, task_t *other); -}; - -/** - * Create a new CHILD_REKEY task. - * - * @param ike_sa IKE_SA this task works for - * @param protocol protocol of CHILD_SA to rekey, PROTO_NONE as responder - * @param spi inbound SPI of CHILD_SA to rekey - * @return child_rekey task to handle by the task_manager - */ -child_rekey_t *child_rekey_create(ike_sa_t *ike_sa, protocol_id_t protocol, - u_int32_t spi); - -#endif /** CHILD_REKEY_H_ @}*/ 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; -} - diff --git a/src/charon/sa/tasks/ike_auth.h b/src/charon/sa/tasks/ike_auth.h deleted file mode 100644 index bba46d961..000000000 --- a/src/charon/sa/tasks/ike_auth.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2007 Martin Willi - * 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. - */ - -/** - * @defgroup ike_auth ike_auth - * @{ @ingroup tasks - */ - -#ifndef IKE_AUTH_H_ -#define IKE_AUTH_H_ - -typedef struct ike_auth_t ike_auth_t; - -#include <library.h> -#include <sa/ike_sa.h> -#include <sa/tasks/task.h> - -/** - * Task of type ike_auth, authenticates an IKE_SA using authenticators. - * - * The ike_auth task authenticates the IKE_SA using the IKE_AUTH - * exchange. It processes and build IDi and IDr payloads and also - * handles AUTH payloads. The AUTH payloads are passed to authenticator_t's, - * which do the actual authentication process. If the ike_auth task is used - * with EAP authentication, it stays alive over multiple exchanges until - * EAP has completed. - */ -struct ike_auth_t { - - /** - * Implements the task_t interface - */ - task_t task; -}; - -/** - * Create a new task of type IKE_AUTHENTICATE. - * - * @param ike_sa IKE_SA this task works for - * @param initiator TRUE if thask is the initator of an exchange - * @return ike_auth task to handle by the task_manager - */ -ike_auth_t *ike_auth_create(ike_sa_t *ike_sa, bool initiator); - -#endif /** IKE_AUTH_H_ @}*/ diff --git a/src/charon/sa/tasks/ike_auth_lifetime.c b/src/charon/sa/tasks/ike_auth_lifetime.c deleted file mode 100644 index 75ff35168..000000000 --- a/src/charon/sa/tasks/ike_auth_lifetime.c +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (C) 2007 Martin Willi - * 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_lifetime.h" - -#include <time.h> - -#include <daemon.h> -#include <encoding/payloads/notify_payload.h> - - -typedef struct private_ike_auth_lifetime_t private_ike_auth_lifetime_t; - -/** - * Private members of a ike_auth_lifetime_t task. - */ -struct private_ike_auth_lifetime_t { - - /** - * Public methods and task_t interface. - */ - ike_auth_lifetime_t public; - - /** - * Assigned IKE_SA. - */ - ike_sa_t *ike_sa; -}; - -/** - * add the AUTH_LIFETIME notify to the message - */ -static void add_auth_lifetime(private_ike_auth_lifetime_t *this, message_t *message) -{ - chunk_t chunk; - u_int32_t lifetime; - - lifetime = this->ike_sa->get_statistic(this->ike_sa, STAT_REAUTH); - if (lifetime) - { - lifetime -= time_monotonic(NULL); - chunk = chunk_from_thing(lifetime); - *(u_int32_t*)chunk.ptr = htonl(lifetime); - message->add_notify(message, FALSE, AUTH_LIFETIME, chunk); - } -} - -/** - * read notifys from message and evaluate them - */ -static void process_payloads(private_ike_auth_lifetime_t *this, message_t *message) -{ - notify_payload_t *notify; - chunk_t data; - u_int32_t lifetime; - - notify = message->get_notify(message, AUTH_LIFETIME); - if (notify) - { - data = notify->get_notification_data(notify); - lifetime = ntohl(*(u_int32_t*)data.ptr); - this->ike_sa->set_auth_lifetime(this->ike_sa, lifetime); - } -} - -/** - * Implementation of task_t.process for initiator - */ -static status_t build_i(private_ike_auth_lifetime_t *this, message_t *message) -{ - if (message->get_exchange_type(message) == INFORMATIONAL) - { - add_auth_lifetime(this, message); - return SUCCESS; - } - return NEED_MORE; -} - -/** - * Implementation of task_t.process for responder - */ -static status_t process_r(private_ike_auth_lifetime_t *this, message_t *message) -{ - if (message->get_exchange_type(message) == INFORMATIONAL) - { - process_payloads(this, message); - return SUCCESS; - } - return NEED_MORE; -} - -/** - * Implementation of task_t.build for responder - */ -static status_t build_r(private_ike_auth_lifetime_t *this, message_t *message) -{ - if (message->get_exchange_type(message) == IKE_AUTH && - this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED) - { - add_auth_lifetime(this, message); - return SUCCESS; - } - return NEED_MORE; -} - -/** - * Implementation of task_t.process for initiator - */ -static status_t process_i(private_ike_auth_lifetime_t *this, message_t *message) -{ - if (message->get_exchange_type(message) == IKE_AUTH && - this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED) - { - process_payloads(this, message); - return SUCCESS; - } - return NEED_MORE; -} - -/** - * Implementation of task_t.get_type - */ -static task_type_t get_type(private_ike_auth_lifetime_t *this) -{ - return IKE_AUTH_LIFETIME; -} - -/** - * Implementation of task_t.migrate - */ -static void migrate(private_ike_auth_lifetime_t *this, ike_sa_t *ike_sa) -{ - this->ike_sa = ike_sa; -} - -/** - * Implementation of task_t.destroy - */ -static void destroy(private_ike_auth_lifetime_t *this) -{ - free(this); -} - -/* - * Described in header. - */ -ike_auth_lifetime_t *ike_auth_lifetime_create(ike_sa_t *ike_sa, bool initiator) -{ - private_ike_auth_lifetime_t *this = malloc_thing(private_ike_auth_lifetime_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; - - return &this->public; -} - diff --git a/src/charon/sa/tasks/ike_auth_lifetime.h b/src/charon/sa/tasks/ike_auth_lifetime.h deleted file mode 100644 index 3b129b9e3..000000000 --- a/src/charon/sa/tasks/ike_auth_lifetime.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2007 Martin Willi - * 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. - */ - -/** - * @defgroup ike_auth_lifetime ike_auth_lifetime - * @{ @ingroup tasks - */ - -#ifndef IKE_AUTH_LIFETIME_H_ -#define IKE_AUTH_LIFETIME_H_ - -typedef struct ike_auth_lifetime_t ike_auth_lifetime_t; - -#include <library.h> -#include <sa/ike_sa.h> -#include <sa/tasks/task.h> - -/** - * Task of type IKE_AUTH_LIFETIME, implements RFC4478. - * - * This task exchanges lifetimes for IKE_AUTH to force a client to - * reauthenticate before the responders lifetime reaches the limit. - */ -struct ike_auth_lifetime_t { - - /** - * Implements the task_t interface - */ - task_t task; -}; - -/** - * Create a new IKE_AUTH_LIFETIME task. - * - * @param ike_sa IKE_SA this task works for - * @param initiator TRUE if taks is initiated by us - * @return ike_auth_lifetime task to handle by the task_manager - */ -ike_auth_lifetime_t *ike_auth_lifetime_create(ike_sa_t *ike_sa, bool initiator); - -#endif /** IKE_MOBIKE_H_ @}*/ diff --git a/src/charon/sa/tasks/ike_cert_post.c b/src/charon/sa/tasks/ike_cert_post.c deleted file mode 100644 index c831df975..000000000 --- a/src/charon/sa/tasks/ike_cert_post.c +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Copyright (C) 2008 Tobias Brunner - * Copyright (C) 2006-2009 Martin Willi - * 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_cert_post.h" - -#include <daemon.h> -#include <sa/ike_sa.h> -#include <encoding/payloads/cert_payload.h> -#include <encoding/payloads/certreq_payload.h> -#include <encoding/payloads/auth_payload.h> -#include <credentials/certificates/x509.h> - - -typedef struct private_ike_cert_post_t private_ike_cert_post_t; - -/** - * Private members of a ike_cert_post_t task. - */ -struct private_ike_cert_post_t { - - /** - * Public methods and task_t interface. - */ - ike_cert_post_t public; - - /** - * Assigned IKE_SA. - */ - ike_sa_t *ike_sa; - - /** - * Are we the initiator? - */ - bool initiator; -}; - -/** - * Generates the cert payload, if possible with "Hash and URL" - */ -static cert_payload_t *build_cert_payload(private_ike_cert_post_t *this, - certificate_t *cert) -{ - hasher_t *hasher; - identification_t *id; - chunk_t hash, encoded ; - enumerator_t *enumerator; - char *url; - cert_payload_t *payload = NULL; - - if (!this->ike_sa->supports_extension(this->ike_sa, EXT_HASH_AND_URL)) - { - return cert_payload_create_from_cert(cert); - } - - hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); - if (!hasher) - { - DBG1(DBG_IKE, "unable to use hash-and-url: sha1 not supported"); - return cert_payload_create_from_cert(cert); - } - - encoded = cert->get_encoding(cert); - hasher->allocate_hash(hasher, encoded, &hash); - chunk_free(&encoded); - hasher->destroy(hasher); - id = identification_create_from_encoding(ID_KEY_ID, hash); - - enumerator = charon->credentials->create_cdp_enumerator(charon->credentials, - CERT_X509, id); - if (enumerator->enumerate(enumerator, &url)) - { - payload = cert_payload_create_from_hash_and_url(hash, url); - } - else - { - payload = cert_payload_create_from_cert(cert); - } - enumerator->destroy(enumerator); - chunk_free(&hash); - id->destroy(id); - return payload; -} - -/** - * add certificates to message - */ -static void build_certs(private_ike_cert_post_t *this, message_t *message) -{ - peer_cfg_t *peer_cfg; - auth_payload_t *payload; - - payload = (auth_payload_t*)message->get_payload(message, AUTHENTICATION); - peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa); - if (!peer_cfg || !payload || payload->get_auth_method(payload) == AUTH_PSK) - { /* no CERT payload for EAP/PSK */ - return; - } - - switch (peer_cfg->get_cert_policy(peer_cfg)) - { - case CERT_NEVER_SEND: - break; - case CERT_SEND_IF_ASKED: - if (!this->ike_sa->has_condition(this->ike_sa, COND_CERTREQ_SEEN)) - { - break; - } - /* FALL */ - case CERT_ALWAYS_SEND: - { - cert_payload_t *payload; - enumerator_t *enumerator; - certificate_t *cert; - auth_rule_t type; - auth_cfg_t *auth; - - auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE); - - /* get subject cert first, then issuing certificates */ - cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT); - if (!cert) - { - break; - } - payload = build_cert_payload(this, cert); - if (!payload) - { - break; - } - DBG1(DBG_IKE, "sending end entity cert \"%Y\"", - cert->get_subject(cert)); - message->add_payload(message, (payload_t*)payload); - - enumerator = auth->create_enumerator(auth); - while (enumerator->enumerate(enumerator, &type, &cert)) - { - if (type == AUTH_RULE_IM_CERT) - { - payload = cert_payload_create_from_cert(cert); - if (payload) - { - DBG1(DBG_IKE, "sending issuer cert \"%Y\"", - cert->get_subject(cert)); - message->add_payload(message, (payload_t*)payload); - } - } - } - enumerator->destroy(enumerator); - } - } -} - -/** - * Implementation of task_t.process for initiator - */ -static status_t build_i(private_ike_cert_post_t *this, message_t *message) -{ - build_certs(this, message); - - return NEED_MORE; -} - -/** - * Implementation of task_t.process for responder - */ -static status_t process_r(private_ike_cert_post_t *this, message_t *message) -{ - return NEED_MORE; -} - -/** - * Implementation of task_t.build for responder - */ -static status_t build_r(private_ike_cert_post_t *this, message_t *message) -{ - build_certs(this, message); - - if (this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED) - { /* stay alive, we might have additional rounds with certs */ - return NEED_MORE; - } - return SUCCESS; -} - -/** - * Implementation of task_t.process for initiator - */ -static status_t process_i(private_ike_cert_post_t *this, message_t *message) -{ - if (this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED) - { /* stay alive, we might have additional rounds with CERTS */ - return NEED_MORE; - } - return SUCCESS; -} - -/** - * Implementation of task_t.get_type - */ -static task_type_t get_type(private_ike_cert_post_t *this) -{ - return IKE_CERT_POST; -} - -/** - * Implementation of task_t.migrate - */ -static void migrate(private_ike_cert_post_t *this, ike_sa_t *ike_sa) -{ - this->ike_sa = ike_sa; -} - -/** - * Implementation of task_t.destroy - */ -static void destroy(private_ike_cert_post_t *this) -{ - free(this); -} - -/* - * Described in header. - */ -ike_cert_post_t *ike_cert_post_create(ike_sa_t *ike_sa, bool initiator) -{ - private_ike_cert_post_t *this = malloc_thing(private_ike_cert_post_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; - - return &this->public; -} - diff --git a/src/charon/sa/tasks/ike_cert_post.h b/src/charon/sa/tasks/ike_cert_post.h deleted file mode 100644 index a21f45927..000000000 --- a/src/charon/sa/tasks/ike_cert_post.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2007-2008 Martin Willi - * 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. - */ - -/** - * @defgroup ike_cert_post ike_cert_post - * @{ @ingroup tasks - */ - -#ifndef IKE_CERT_POST_H_ -#define IKE_CERT_POST_H_ - -typedef struct ike_cert_post_t ike_cert_post_t; - -#include <library.h> -#include <sa/ike_sa.h> -#include <sa/tasks/task.h> - -/** - * Task of type ike_cert_post, certificate processing after authentication. - */ -struct ike_cert_post_t { - - /** - * Implements the task_t interface - */ - task_t task; -}; - -/** - * Create a new ike_cert_post task. - * - * The initiator parameter means the original initiator, not the initiator - * of the certificate request. - * - * @param ike_sa IKE_SA this task works for - * @param initiator TRUE if thask is the original initator - * @return ike_cert_post task to handle by the task_manager - */ -ike_cert_post_t *ike_cert_post_create(ike_sa_t *ike_sa, bool initiator); - -#endif /** IKE_CERT_POST_H_ @}*/ diff --git a/src/charon/sa/tasks/ike_cert_pre.c b/src/charon/sa/tasks/ike_cert_pre.c deleted file mode 100644 index 0805d0290..000000000 --- a/src/charon/sa/tasks/ike_cert_pre.c +++ /dev/null @@ -1,524 +0,0 @@ -/* - * Copyright (C) 2008 Tobias Brunner - * Copyright (C) 2006-2009 Martin Willi - * 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_cert_pre.h" - -#include <daemon.h> -#include <sa/ike_sa.h> -#include <encoding/payloads/cert_payload.h> -#include <encoding/payloads/certreq_payload.h> -#include <credentials/certificates/x509.h> - - -typedef struct private_ike_cert_pre_t private_ike_cert_pre_t; - -/** - * Private members of a ike_cert_pre_t task. - */ -struct private_ike_cert_pre_t { - - /** - * Public methods and task_t interface. - */ - ike_cert_pre_t public; - - /** - * Assigned IKE_SA. - */ - ike_sa_t *ike_sa; - - /** - * Are we the initiator? - */ - bool initiator; - - /** - * Do we accept HTTP certificate lookup requests - */ - bool do_http_lookup; - - /** - * wheter this is the final authentication round - */ - bool final; -}; - -/** - * read certificate requests - */ -static void process_certreqs(private_ike_cert_pre_t *this, message_t *message) -{ - enumerator_t *enumerator; - payload_t *payload; - auth_cfg_t *auth; - - auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE); - - enumerator = message->create_payload_enumerator(message); - while (enumerator->enumerate(enumerator, &payload)) - { - switch (payload->get_type(payload)) - { - case CERTIFICATE_REQUEST: - { - certreq_payload_t *certreq = (certreq_payload_t*)payload; - enumerator_t *enumerator; - chunk_t keyid; - - this->ike_sa->set_condition(this->ike_sa, COND_CERTREQ_SEEN, TRUE); - - if (certreq->get_cert_type(certreq) != CERT_X509) - { - DBG1(DBG_IKE, "cert payload %N not supported - ignored", - certificate_type_names, certreq->get_cert_type(certreq)); - break; - } - enumerator = certreq->create_keyid_enumerator(certreq); - while (enumerator->enumerate(enumerator, &keyid)) - { - identification_t *id; - certificate_t *cert; - - id = identification_create_from_encoding(ID_KEY_ID, keyid); - cert = charon->credentials->get_cert(charon->credentials, - CERT_X509, KEY_ANY, id, TRUE); - if (cert) - { - DBG1(DBG_IKE, "received cert request for \"%Y\"", - cert->get_subject(cert)); - auth->add(auth, AUTH_RULE_CA_CERT, cert); - } - else - { - DBG1(DBG_IKE, "received cert request for unknown ca " - "with keyid %Y", id); - } - id->destroy(id); - } - enumerator->destroy(enumerator); - break; - } - case NOTIFY: - { - notify_payload_t *notify = (notify_payload_t*)payload; - - /* we only handle one type of notify here */ - if (notify->get_notify_type(notify) == HTTP_CERT_LOOKUP_SUPPORTED) - { - this->ike_sa->enable_extension(this->ike_sa, EXT_HASH_AND_URL); - } - break; - } - default: - /* ignore other payloads here, these are handled elsewhere */ - break; - } - } - enumerator->destroy(enumerator); -} - -/** - * tries to extract a certificate from the cert payload or the credential - * manager (based on the hash of a "Hash and URL" encoded cert). - * Note: the returned certificate (if any) has to be destroyed - */ -static certificate_t *try_get_cert(cert_payload_t *cert_payload) -{ - certificate_t *cert = NULL; - - switch (cert_payload->get_cert_encoding(cert_payload)) - { - case ENC_X509_SIGNATURE: - { - cert = cert_payload->get_cert(cert_payload); - break; - } - case ENC_X509_HASH_AND_URL: - { - identification_t *id; - chunk_t hash = cert_payload->get_hash(cert_payload); - if (!hash.ptr) - { - /* invalid "Hash and URL" data (logged elsewhere) */ - break; - } - id = identification_create_from_encoding(ID_KEY_ID, hash); - cert = charon->credentials->get_cert(charon->credentials, - CERT_X509, KEY_ANY, id, FALSE); - id->destroy(id); - break; - } - default: - { - break; - } - } - return cert; -} - -/** - * import certificates - */ -static void process_certs(private_ike_cert_pre_t *this, message_t *message) -{ - enumerator_t *enumerator; - payload_t *payload; - auth_cfg_t *auth; - bool first = TRUE; - - auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE); - - enumerator = message->create_payload_enumerator(message); - while (enumerator->enumerate(enumerator, &payload)) - { - if (payload->get_type(payload) == CERTIFICATE) - { - cert_payload_t *cert_payload; - cert_encoding_t encoding; - certificate_t *cert; - char *url; - - cert_payload = (cert_payload_t*)payload; - encoding = cert_payload->get_cert_encoding(cert_payload); - - switch (encoding) - { - case ENC_X509_HASH_AND_URL: - { - if (!this->do_http_lookup) - { - DBG1(DBG_IKE, "received hash-and-url encoded cert, but" - " we don't accept them, ignore"); - break; - } - /* FALL */ - } - case ENC_X509_SIGNATURE: - { - cert = try_get_cert(cert_payload); - if (cert) - { - if (first) - { /* the first is an end entity certificate */ - DBG1(DBG_IKE, "received end entity cert \"%Y\"", - cert->get_subject(cert)); - auth->add(auth, AUTH_HELPER_SUBJECT_CERT, cert); - first = FALSE; - } - else - { - DBG1(DBG_IKE, "received issuer cert \"%Y\"", - cert->get_subject(cert)); - auth->add(auth, AUTH_HELPER_IM_CERT, cert); - } - } - else if (encoding == ENC_X509_HASH_AND_URL) - { - /* we fetch the certificate not yet, but only if - * it is really needed during authentication */ - url = cert_payload->get_url(cert_payload); - if (!url) - { - DBG1(DBG_IKE, "received invalid hash-and-url " - "encoded cert, ignore"); - break; - } - url = strdup(url); - if (first) - { /* first URL is for an end entity certificate */ - DBG1(DBG_IKE, "received hash-and-url for end" - " entity cert \"%s\"", url); - auth->add(auth, AUTH_HELPER_SUBJECT_HASH_URL, url); - first = FALSE; - } - else - { - DBG1(DBG_IKE, "received hash-and-url for issuer" - " cert \"%s\"", url); - auth->add(auth, AUTH_HELPER_IM_HASH_URL, url); - } - } - break; - } - case ENC_PKCS7_WRAPPED_X509: - case ENC_PGP: - case ENC_DNS_SIGNED_KEY: - case ENC_KERBEROS_TOKEN: - case ENC_CRL: - case ENC_ARL: - case ENC_SPKI: - case ENC_X509_ATTRIBUTE: - case ENC_RAW_RSA_KEY: - case ENC_X509_HASH_AND_URL_BUNDLE: - case ENC_OCSP_CONTENT: - default: - DBG1(DBG_ENC, "certificate encoding %N not supported", - cert_encoding_names, encoding); - } - } - } - enumerator->destroy(enumerator); -} - -/** - * add the keyid of a certificate to the certificate request payload - */ -static void add_certreq(certreq_payload_t **req, certificate_t *cert) -{ - switch (cert->get_type(cert)) - { - case CERT_X509: - { - public_key_t *public; - chunk_t keyid; - x509_t *x509 = (x509_t*)cert; - - if (!(x509->get_flags(x509) & X509_CA)) - { /* no CA cert, skip */ - break; - } - public = cert->get_public_key(cert); - if (!public) - { - break; - } - if (*req == NULL) - { - *req = certreq_payload_create_type(CERT_X509); - } - if (public->get_fingerprint(public, KEY_ID_PUBKEY_INFO_SHA1, &keyid)) - { - (*req)->add_keyid(*req, keyid); - DBG1(DBG_IKE, "sending cert request for \"%Y\"", - cert->get_subject(cert)); - } - public->destroy(public); - break; - } - default: - break; - } -} - -/** - * add a auth_cfg's CA certificates to the certificate request - */ -static void add_certreqs(certreq_payload_t **req, auth_cfg_t *auth) -{ - enumerator_t *enumerator; - auth_rule_t type; - void *value; - - enumerator = auth->create_enumerator(auth); - while (enumerator->enumerate(enumerator, &type, &value)) - { - switch (type) - { - case AUTH_RULE_CA_CERT: - add_certreq(req, (certificate_t*)value); - break; - default: - break; - } - } - enumerator->destroy(enumerator); -} - -/** - * build certificate requests - */ -static void build_certreqs(private_ike_cert_pre_t *this, message_t *message) -{ - enumerator_t *enumerator; - ike_cfg_t *ike_cfg; - peer_cfg_t *peer_cfg; - certificate_t *cert; - auth_cfg_t *auth; - certreq_payload_t *req = NULL; - - ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa); - if (!ike_cfg->send_certreq(ike_cfg)) - { - return; - } - - /* check if we require a specific CA for that peer */ - peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa); - if (peer_cfg) - { - enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, FALSE); - while (enumerator->enumerate(enumerator, &auth)) - { - add_certreqs(&req, auth); - } - enumerator->destroy(enumerator); - } - - if (!req) - { - /* otherwise add all trusted CA certificates */ - enumerator = charon->credentials->create_cert_enumerator( - charon->credentials, CERT_ANY, KEY_ANY, NULL, TRUE); - while (enumerator->enumerate(enumerator, &cert)) - { - add_certreq(&req, cert); - } - enumerator->destroy(enumerator); - } - - if (req) - { - message->add_payload(message, (payload_t*)req); - - if (lib->settings->get_bool(lib->settings, "charon.hash_and_url", FALSE)) - { - message->add_notify(message, FALSE, HTTP_CERT_LOOKUP_SUPPORTED, - chunk_empty); - this->do_http_lookup = TRUE; - } - } -} - -/** - * Check if this is the final authentication round - */ -static bool final_auth(message_t *message) -{ - /* we check for an AUTH payload without a ANOTHER_AUTH_FOLLOWS notify */ - if (message->get_payload(message, AUTHENTICATION) == NULL) - { - return FALSE; - } - if (message->get_notify(message, ANOTHER_AUTH_FOLLOWS)) - { - return FALSE; - } - return TRUE; -} - -/** - * Implementation of task_t.process for initiator - */ -static status_t build_i(private_ike_cert_pre_t *this, message_t *message) -{ - if (message->get_message_id(message) == 1) - { /* initiator sends CERTREQs in first IKE_AUTH */ - build_certreqs(this, message); - } - return NEED_MORE; -} - -/** - * Implementation of task_t.process for responder - */ -static status_t process_r(private_ike_cert_pre_t *this, message_t *message) -{ - if (message->get_exchange_type(message) != IKE_SA_INIT) - { /* handle certreqs/certs in any IKE_AUTH, just in case */ - process_certreqs(this, message); - process_certs(this, message); - } - this->final = final_auth(message); - return NEED_MORE; -} - -/** - * Implementation of task_t.build for responder - */ -static status_t build_r(private_ike_cert_pre_t *this, message_t *message) -{ - if (message->get_exchange_type(message) == IKE_SA_INIT) - { - build_certreqs(this, message); - } - if (this->final) - { - return SUCCESS; - } - return NEED_MORE; -} - -/** - * Implementation of task_t.process for initiator - */ -static status_t process_i(private_ike_cert_pre_t *this, message_t *message) -{ - if (message->get_exchange_type(message) == IKE_SA_INIT) - { - process_certreqs(this, message); - } - process_certs(this, message); - - if (final_auth(message)) - { - return SUCCESS; - } - return NEED_MORE; -} - -/** - * Implementation of task_t.get_type - */ -static task_type_t get_type(private_ike_cert_pre_t *this) -{ - return IKE_CERT_PRE; -} - -/** - * Implementation of task_t.migrate - */ -static void migrate(private_ike_cert_pre_t *this, ike_sa_t *ike_sa) -{ - this->ike_sa = ike_sa; -} - -/** - * Implementation of task_t.destroy - */ -static void destroy(private_ike_cert_pre_t *this) -{ - free(this); -} - -/* - * Described in header. - */ -ike_cert_pre_t *ike_cert_pre_create(ike_sa_t *ike_sa, bool initiator) -{ - private_ike_cert_pre_t *this = malloc_thing(private_ike_cert_pre_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->do_http_lookup = FALSE; - this->final = FALSE; - - return &this->public; -} diff --git a/src/charon/sa/tasks/ike_cert_pre.h b/src/charon/sa/tasks/ike_cert_pre.h deleted file mode 100644 index 1541b80e5..000000000 --- a/src/charon/sa/tasks/ike_cert_pre.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2007-2008 Martin Willi - * 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. - */ - -/** - * @defgroup ike_cert_pre ike_cert_pre - * @{ @ingroup tasks - */ - -#ifndef IKE_CERT_PRE_H_ -#define IKE_CERT_PRE_H_ - -typedef struct ike_cert_pre_t ike_cert_pre_t; - -#include <library.h> -#include <sa/ike_sa.h> -#include <sa/tasks/task.h> - -/** - * Task of type ike_cert_post, certificate processing before authentication. - */ -struct ike_cert_pre_t { - - /** - * Implements the task_t interface - */ - task_t task; -}; - -/** - * Create a new ike_cert_pre task. - * - * The initiator parameter means the original initiator, not the initiator - * of the certificate request. - * - * @param ike_sa IKE_SA this task works for - * @param initiator TRUE if thask is the original initator - * @return ike_cert_pre task to handle by the task_manager - */ -ike_cert_pre_t *ike_cert_pre_create(ike_sa_t *ike_sa, bool initiator); - -#endif /** IKE_CERT_PRE_H_ @}*/ diff --git a/src/charon/sa/tasks/ike_config.c b/src/charon/sa/tasks/ike_config.c deleted file mode 100644 index f010439fe..000000000 --- a/src/charon/sa/tasks/ike_config.c +++ /dev/null @@ -1,479 +0,0 @@ -/* - * Copyright (C) 2007 Martin Willi - * Copyright (C) 2006-2007 Fabian Hartmann, Noah Heusser - * 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_config.h" - -#include <daemon.h> -#include <encoding/payloads/cp_payload.h> - -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; -}; - -/** - * 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 configuration_attribute_t *build_vip(host_t *vip) -{ - configuration_attribute_type_t type; - chunk_t chunk, prefix; - - if (vip->get_family(vip) == AF_INET) - { - type = INTERNAL_IP4_ADDRESS; - if (vip->is_anyaddr(vip)) - { - chunk = chunk_empty; - } - else - { - chunk = vip->get_address(vip); - } - } - else - { - type = INTERNAL_IP6_ADDRESS; - if (vip->is_anyaddr(vip)) - { - chunk = chunk_empty; - } - else - { - prefix = chunk_alloca(1); - *prefix.ptr = 64; - chunk = vip->get_address(vip); - chunk = chunk_cata("cc", chunk, prefix); - } - } - 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)); - } -} - -/** - * process a single configuration attribute - */ -static void process_attribute(private_ike_config_t *this, - configuration_attribute_t *ca) -{ - host_t *ip; - chunk_t addr; - int family = AF_INET6; - - switch (ca->get_type(ca)) - { - case INTERNAL_IP4_ADDRESS: - family = AF_INET; - /* fall */ - case INTERNAL_IP6_ADDRESS: - { - addr = ca->get_value(ca); - if (addr.len == 0) - { - ip = host_create_any(family); - } - else - { - /* skip prefix byte in IPv6 payload*/ - if (family == AF_INET6) - { - addr.len--; - } - ip = host_create_from_chunk(family, addr, 0); - } - if (ip) - { - DESTROY_IF(this->virtual_ip); - this->virtual_ip = ip; - } - break; - } - default: - { - if (this->initiator) - { - handle_attribute(this, ca); - } - } - } -} - -/** - * Scan for configuration payloads and attributes - */ -static void process_payloads(private_ike_config_t *this, message_t *message) -{ - enumerator_t *enumerator, *attributes; - payload_t *payload; - - enumerator = message->create_payload_enumerator(message); - while (enumerator->enumerate(enumerator, &payload)) - { - if (payload->get_type(payload) == CONFIGURATION) - { - cp_payload_t *cp = (cp_payload_t*)payload; - configuration_attribute_t *ca; - - switch (cp->get_type(cp)) - { - case CFG_REQUEST: - case CFG_REPLY: - { - 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_type(cp)); - break; - } - } - } - enumerator->destroy(enumerator); -} - -/** - * Implementation of task_t.process for initiator - */ -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) - { - config = this->ike_sa->get_peer_cfg(this->ike_sa); - vip = config->get_virtual_ip(config); - } - 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; - 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) - { - cp = cp_payload_create_type(CFG_REQUEST); - } - 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); - } - } - return NEED_MORE; -} - -/** - * Implementation of task_t.process for responder - */ -static status_t process_r(private_ike_config_t *this, message_t *message) -{ - if (message->get_message_id(message) == 1) - { /* in first IKE_AUTH only */ - process_payloads(this, message); - } - return NEED_MORE; -} - -/** - * 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 */ - 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) - { - DBG1(DBG_IKE, "peer requested virtual IP %H", this->virtual_ip); - if (config->get_pool(config)) - { - vip = lib->attributes->acquire_address(lib->attributes, - config->get_pool(config), id, this->virtual_ip); - } - if (vip == NULL) - { - DBG1(DBG_IKE, "no virtual IP found, sending %N", - notify_type_names, INTERNAL_ADDRESS_FAILURE); - message->add_notify(message, FALSE, INTERNAL_ADDRESS_FAILURE, - chunk_empty); - return SUCCESS; - } - 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_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) - { - cp = cp_payload_create_type(CFG_REPLY); - } - 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; -} - -/** - * Implementation of task_t.process for initiator - */ -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); - } - return SUCCESS; - } - return NEED_MORE; -} - -/** - * Implementation of task_t.get_type - */ -static task_type_t get_type(private_ike_config_t *this) -{ - return IKE_CONFIG; -} - -/** - * Implementation of task_t.migrate - */ -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(); -} - -/** - * Implementation of task_t.destroy - */ -static void destroy(private_ike_config_t *this) -{ - DESTROY_IF(this->virtual_ip); - this->requested->destroy_function(this->requested, free); - free(this); -} - -/* - * Described in header. - */ -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; - 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; - } - - return &this->public; -} - diff --git a/src/charon/sa/tasks/ike_config.h b/src/charon/sa/tasks/ike_config.h deleted file mode 100644 index 8cef08697..000000000 --- a/src/charon/sa/tasks/ike_config.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2007 Martin Willi - * 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. - */ - -/** - * @defgroup ike_config ike_config - * @{ @ingroup tasks - */ - -#ifndef IKE_CONFIG_H_ -#define IKE_CONFIG_H_ - -typedef struct ike_config_t ike_config_t; - -#include <library.h> -#include <sa/ike_sa.h> -#include <sa/tasks/task.h> - -/** - * Task of type IKE_CONFIG, sets up a virtual IP and other - * configurations for an IKE_SA. - */ -struct ike_config_t { - - /** - * Implements the task_t interface - */ - task_t task; -}; - -/** - * Create a new ike_config task. - * - * @param ike_sa IKE_SA this task works for - * @param initiator TRUE for initiator - * @return ike_config task to handle by the task_manager - */ -ike_config_t *ike_config_create(ike_sa_t *ike_sa, bool initiator); - -#endif /** IKE_CONFIG_H_ @}*/ diff --git a/src/charon/sa/tasks/ike_delete.c b/src/charon/sa/tasks/ike_delete.c deleted file mode 100644 index 130948836..000000000 --- a/src/charon/sa/tasks/ike_delete.c +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright (C) 2006-2007 Martin Willi - * 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_delete.h" - -#include <daemon.h> -#include <encoding/payloads/delete_payload.h> - - -typedef struct private_ike_delete_t private_ike_delete_t; - -/** - * Private members of a ike_delete_t task. - */ -struct private_ike_delete_t { - - /** - * Public methods and task_t interface. - */ - ike_delete_t public; - - /** - * Assigned IKE_SA. - */ - ike_sa_t *ike_sa; - - /** - * Are we the initiator? - */ - bool initiator; - - /** - * are we deleting a rekeyed SA? - */ - bool rekeyed; - - /** - * are we responding to a delete, but have initated our own? - */ - bool simultaneous; -}; - -/** - * Implementation of task_t.build for initiator - */ -static status_t build_i(private_ike_delete_t *this, message_t *message) -{ - delete_payload_t *delete_payload; - - DBG0(DBG_IKE, "deleting IKE_SA %s[%d] 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)); - - delete_payload = delete_payload_create(PROTO_IKE); - message->add_payload(message, (payload_t*)delete_payload); - - if (this->ike_sa->get_state(this->ike_sa) == IKE_REKEYING) - { - this->rekeyed = TRUE; - } - this->ike_sa->set_state(this->ike_sa, IKE_DELETING); - - DBG1(DBG_IKE, "sending DELETE for IKE_SA %s[%d]", - this->ike_sa->get_name(this->ike_sa), - this->ike_sa->get_unique_id(this->ike_sa)); - - return NEED_MORE; -} - -/** - * Implementation of task_t.process for initiator - */ -static status_t process_i(private_ike_delete_t *this, message_t *message) -{ - DBG0(DBG_IKE, "IKE_SA deleted"); - if (!this->rekeyed) - { /* invoke ike_down() hook if SA has not been rekeyed */ - charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE); - } - /* completed, delete IKE_SA by returning DESTROY_ME */ - return DESTROY_ME; -} - -/** - * Implementation of task_t.process for responder - */ -static status_t process_r(private_ike_delete_t *this, message_t *message) -{ - /* we don't even scan the payloads, as the message wouldn't have - * come so far without being correct */ - DBG1(DBG_IKE, "received DELETE for IKE_SA %s[%d]", - this->ike_sa->get_name(this->ike_sa), - this->ike_sa->get_unique_id(this->ike_sa)); - DBG0(DBG_IKE, "deleting IKE_SA %s[%d] 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)); - - switch (this->ike_sa->get_state(this->ike_sa)) - { - case IKE_ESTABLISHED: - this->ike_sa->set_state(this->ike_sa, IKE_DELETING); - this->ike_sa->reestablish(this->ike_sa); - return NEED_MORE; - case IKE_REKEYING: - this->rekeyed = TRUE; - break; - case IKE_DELETING: - this->simultaneous = TRUE; - break; - default: - break; - } - this->ike_sa->set_state(this->ike_sa, IKE_DELETING); - return NEED_MORE; -} - -/** - * Implementation of task_t.build for responder - */ -static status_t build_r(private_ike_delete_t *this, message_t *message) -{ - DBG0(DBG_IKE, "IKE_SA deleted"); - - if (this->simultaneous) - { - /* wait for peer's response for our delete request, but set a timeout */ - return SUCCESS; - } - if (!this->rekeyed) - { /* invoke ike_down() hook if SA has not been rekeyed */ - charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE); - } - /* completed, delete IKE_SA by returning DESTROY_ME */ - return DESTROY_ME; -} - -/** - * Implementation of task_t.get_type - */ -static task_type_t get_type(private_ike_delete_t *this) -{ - return IKE_DELETE; -} - -/** - * Implementation of task_t.migrate - */ -static void migrate(private_ike_delete_t *this, ike_sa_t *ike_sa) -{ - this->ike_sa = ike_sa; - this->simultaneous = FALSE; -} - -/** - * Implementation of task_t.destroy - */ -static void destroy(private_ike_delete_t *this) -{ - free(this); -} - -/* - * Described in header. - */ -ike_delete_t *ike_delete_create(ike_sa_t *ike_sa, bool initiator) -{ - private_ike_delete_t *this = malloc_thing(private_ike_delete_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->rekeyed = FALSE; - this->simultaneous = FALSE; - - return &this->public; -} diff --git a/src/charon/sa/tasks/ike_delete.h b/src/charon/sa/tasks/ike_delete.h deleted file mode 100644 index 82782f393..000000000 --- a/src/charon/sa/tasks/ike_delete.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2007 Martin Willi - * 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. - */ - -/** - * @defgroup ike_delete ike_delete - * @{ @ingroup tasks - */ - -#ifndef IKE_DELETE_H_ -#define IKE_DELETE_H_ - -typedef struct ike_delete_t ike_delete_t; - -#include <library.h> -#include <sa/ike_sa.h> -#include <sa/tasks/task.h> - -/** - * Task of type ike_delete, delete an IKE_SA. - */ -struct ike_delete_t { - - /** - * Implements the task_t interface - */ - task_t task; -}; - -/** - * Create a new ike_delete task. - * - * @param ike_sa IKE_SA this task works for - * @param initiator TRUE if we initiate the delete - * @return ike_delete task to handle by the task_manager - */ -ike_delete_t *ike_delete_create(ike_sa_t *ike_sa, bool initiator); - -#endif /** IKE_DELETE_H_ @}*/ diff --git a/src/charon/sa/tasks/ike_dpd.c b/src/charon/sa/tasks/ike_dpd.c deleted file mode 100644 index 4c6ba7662..000000000 --- a/src/charon/sa/tasks/ike_dpd.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2007 Martin Willi - * 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_dpd.h" - -#include <daemon.h> - - -typedef struct private_ike_dpd_t private_ike_dpd_t; - -/** - * Private members of a ike_dpd_t task. - */ -struct private_ike_dpd_t { - - /** - * Public methods and task_t interface. - */ - ike_dpd_t public; -}; - -/** - * Implementation of task_t.build for initiator - * Implementation of task_t.process for responder - */ -static status_t return_need_more(private_ike_dpd_t *this, message_t *message) -{ - return NEED_MORE; -} - -/** - * Implementation of task_t.process for initiator - * Implementation of task_t.build for responder - */ -static status_t return_success(private_ike_dpd_t *this, message_t *message) -{ - return SUCCESS; -} - -/** - * Implementation of task_t.get_type - */ -static task_type_t get_type(private_ike_dpd_t *this) -{ - return IKE_DPD; -} - -/** - * Implementation of task_t.migrate - */ -static void migrate(private_ike_dpd_t *this, ike_sa_t *ike_sa) -{ - -} - -/** - * Implementation of task_t.destroy - */ -static void destroy(private_ike_dpd_t *this) -{ - free(this); -} - -/* - * Described in header. - */ -ike_dpd_t *ike_dpd_create(bool initiator) -{ - private_ike_dpd_t *this = malloc_thing(private_ike_dpd_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*))return_need_more; - this->public.task.process = (status_t(*)(task_t*,message_t*))return_success; - } - else - { - this->public.task.build = (status_t(*)(task_t*,message_t*))return_success; - this->public.task.process = (status_t(*)(task_t*,message_t*))return_need_more; - } - - return &this->public; -} diff --git a/src/charon/sa/tasks/ike_dpd.h b/src/charon/sa/tasks/ike_dpd.h deleted file mode 100644 index 36388d15b..000000000 --- a/src/charon/sa/tasks/ike_dpd.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2007 Martin Willi - * 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. - */ - -/** - * @defgroup ike_dpd ike_dpd - * @{ @ingroup tasks - */ - -#ifndef IKE_DPD_H_ -#define IKE_DPD_H_ - -typedef struct ike_dpd_t ike_dpd_t; - -#include <library.h> -#include <sa/ike_sa.h> -#include <sa/tasks/task.h> - -/** - * Task of type ike_dpd, detects dead peers. - * - * The DPD task actually does nothing, as a DPD has no associated payloads. - */ -struct ike_dpd_t { - - /** - * Implements the task_t interface - */ - task_t task; -}; - -/** - * Create a new ike_dpd task. - * - * @param initiator TRUE if thask is the original initator - * @return ike_dpd task to handle by the task_manager - */ -ike_dpd_t *ike_dpd_create(bool initiator); - -#endif /** IKE_DPD_H_ @}*/ diff --git a/src/charon/sa/tasks/ike_init.c b/src/charon/sa/tasks/ike_init.c deleted file mode 100644 index 5eb33b540..000000000 --- a/src/charon/sa/tasks/ike_init.c +++ /dev/null @@ -1,600 +0,0 @@ -/* - * Copyright (C) 2008-2009 Tobias Brunner - * Copyright (C) 2005-2008 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_init.h" - -#include <string.h> - -#include <daemon.h> -#include <crypto/diffie_hellman.h> -#include <encoding/payloads/sa_payload.h> -#include <encoding/payloads/ke_payload.h> -#include <encoding/payloads/nonce_payload.h> - -/** maximum retries to do with cookies/other dh groups */ -#define MAX_RETRIES 5 - -typedef struct private_ike_init_t private_ike_init_t; - -/** - * Private members of a ike_init_t task. - */ -struct private_ike_init_t { - - /** - * Public methods and task_t interface. - */ - ike_init_t public; - - /** - * Assigned IKE_SA. - */ - ike_sa_t *ike_sa; - - /** - * Are we the initiator? - */ - bool initiator; - - /** - * IKE config to establish - */ - ike_cfg_t *config; - - /** - * diffie hellman group to use - */ - diffie_hellman_group_t dh_group; - - /** - * diffie hellman key exchange - */ - diffie_hellman_t *dh; - - /** - * Keymat derivation (from IKE_SA) - */ - keymat_t *keymat; - - /** - * nonce chosen by us - */ - chunk_t my_nonce; - - /** - * nonce chosen by peer - */ - chunk_t other_nonce; - - /** - * Negotiated proposal used for IKE_SA - */ - proposal_t *proposal; - - /** - * Old IKE_SA which gets rekeyed - */ - ike_sa_t *old_sa; - - /** - * cookie received from responder - */ - chunk_t cookie; - - /** - * retries done so far after failure (cookie or bad dh group) - */ - u_int retry; -}; - -/** - * build the payloads for the message - */ -static void build_payloads(private_ike_init_t *this, message_t *message) -{ - sa_payload_t *sa_payload; - ke_payload_t *ke_payload; - nonce_payload_t *nonce_payload; - linked_list_t *proposal_list; - ike_sa_id_t *id; - proposal_t *proposal; - iterator_t *iterator; - - id = this->ike_sa->get_id(this->ike_sa); - - this->config = this->ike_sa->get_ike_cfg(this->ike_sa); - - if (this->initiator) - { - proposal_list = this->config->get_proposals(this->config); - if (this->old_sa) - { - /* include SPI of new IKE_SA when we are rekeying */ - iterator = proposal_list->create_iterator(proposal_list, TRUE); - while (iterator->iterate(iterator, (void**)&proposal)) - { - proposal->set_spi(proposal, id->get_initiator_spi(id)); - } - iterator->destroy(iterator); - } - - sa_payload = sa_payload_create_from_proposal_list(proposal_list); - proposal_list->destroy_offset(proposal_list, offsetof(proposal_t, destroy)); - } - else - { - if (this->old_sa) - { - /* include SPI of new IKE_SA when we are rekeying */ - this->proposal->set_spi(this->proposal, id->get_responder_spi(id)); - } - sa_payload = sa_payload_create_from_proposal(this->proposal); - } - message->add_payload(message, (payload_t*)sa_payload); - - nonce_payload = nonce_payload_create(); - nonce_payload->set_nonce(nonce_payload, this->my_nonce); - ke_payload = ke_payload_create_from_diffie_hellman(this->dh); - - if (this->old_sa) - { /* payload order differs if we are rekeying */ - message->add_payload(message, (payload_t*)nonce_payload); - message->add_payload(message, (payload_t*)ke_payload); - } - else - { - message->add_payload(message, (payload_t*)ke_payload); - message->add_payload(message, (payload_t*)nonce_payload); - } -} - -/** - * Read payloads from message - */ -static void process_payloads(private_ike_init_t *this, message_t *message) -{ - enumerator_t *enumerator; - payload_t *payload; - - enumerator = message->create_payload_enumerator(message); - while (enumerator->enumerate(enumerator, &payload)) - { - switch (payload->get_type(payload)) - { - case SECURITY_ASSOCIATION: - { - sa_payload_t *sa_payload = (sa_payload_t*)payload; - linked_list_t *proposal_list; - bool private; - - proposal_list = sa_payload->get_proposals(sa_payload); - private = this->ike_sa->supports_extension(this->ike_sa, - EXT_STRONGSWAN); - this->proposal = this->config->select_proposal(this->config, - proposal_list, private); - proposal_list->destroy_offset(proposal_list, - offsetof(proposal_t, destroy)); - break; - } - case KEY_EXCHANGE: - { - ke_payload_t *ke_payload = (ke_payload_t*)payload; - - this->dh_group = ke_payload->get_dh_group_number(ke_payload); - if (!this->initiator) - { - this->dh = this->keymat->create_dh(this->keymat, - this->dh_group); - } - if (this->dh) - { - this->dh->set_other_public_value(this->dh, - ke_payload->get_key_exchange_data(ke_payload)); - } - break; - } - case NONCE: - { - nonce_payload_t *nonce_payload = (nonce_payload_t*)payload; - - this->other_nonce = nonce_payload->get_nonce(nonce_payload); - break; - } - default: - break; - } - } - enumerator->destroy(enumerator); -} - -/** - * Implementation of task_t.process for initiator - */ -static status_t build_i(private_ike_init_t *this, message_t *message) -{ - rng_t *rng; - - this->config = this->ike_sa->get_ike_cfg(this->ike_sa); - DBG0(DBG_IKE, "initiating IKE_SA %s[%d] to %H", - this->ike_sa->get_name(this->ike_sa), - this->ike_sa->get_unique_id(this->ike_sa), - this->ike_sa->get_other_host(this->ike_sa)); - this->ike_sa->set_state(this->ike_sa, IKE_CONNECTING); - - if (this->retry >= MAX_RETRIES) - { - DBG1(DBG_IKE, "giving up after %d retries", MAX_RETRIES); - return FAILED; - } - - /* if the DH group is set via use_dh_group(), we already have a DH object */ - if (!this->dh) - { - this->dh_group = this->config->get_dh_group(this->config); - this->dh = this->keymat->create_dh(this->keymat, this->dh_group); - if (!this->dh) - { - DBG1(DBG_IKE, "configured DH group %N not supported", - diffie_hellman_group_names, this->dh_group); - return FAILED; - } - } - - /* generate nonce only when we are trying the first time */ - if (this->my_nonce.ptr == NULL) - { - rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); - if (!rng) - { - DBG1(DBG_IKE, "error generating nonce"); - return FAILED; - } - rng->allocate_bytes(rng, NONCE_SIZE, &this->my_nonce); - rng->destroy(rng); - } - - if (this->cookie.ptr) - { - message->add_notify(message, FALSE, COOKIE, this->cookie); - } - - build_payloads(this, message); - -#ifdef ME - { - chunk_t connect_id = this->ike_sa->get_connect_id(this->ike_sa); - if (connect_id.ptr) - { - message->add_notify(message, FALSE, ME_CONNECTID, connect_id); - } - } -#endif /* ME */ - - return NEED_MORE; -} - -/** - * Implementation of task_t.process for responder - */ -static status_t process_r(private_ike_init_t *this, message_t *message) -{ - rng_t *rng; - - this->config = this->ike_sa->get_ike_cfg(this->ike_sa); - DBG0(DBG_IKE, "%H is initiating an IKE_SA", message->get_source(message)); - this->ike_sa->set_state(this->ike_sa, IKE_CONNECTING); - - rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); - if (!rng) - { - DBG1(DBG_IKE, "error generating nonce"); - return FAILED; - } - rng->allocate_bytes(rng, NONCE_SIZE, &this->my_nonce); - rng->destroy(rng); - -#ifdef ME - { - notify_payload_t *notify = message->get_notify(message, ME_CONNECTID); - if (notify) - { - chunk_t connect_id = notify->get_notification_data(notify); - DBG2(DBG_IKE, "received ME_CONNECTID %#B", &connect_id); - charon->connect_manager->stop_checks(charon->connect_manager, - connect_id); - } - } -#endif /* ME */ - - process_payloads(this, message); - - return NEED_MORE; -} - -/** - * Derive the keymat for the IKE_SA - */ -static bool derive_keys(private_ike_init_t *this, - chunk_t nonce_i, chunk_t nonce_r) -{ - keymat_t *old_keymat; - pseudo_random_function_t prf_alg = PRF_UNDEFINED; - chunk_t skd = chunk_empty; - ike_sa_id_t *id; - - id = this->ike_sa->get_id(this->ike_sa); - if (this->old_sa) - { - /* rekeying: Include old SKd, use old PRF, apply SPI */ - old_keymat = this->old_sa->get_keymat(this->old_sa); - prf_alg = old_keymat->get_skd(old_keymat, &skd); - if (this->initiator) - { - id->set_responder_spi(id, this->proposal->get_spi(this->proposal)); - } - else - { - id->set_initiator_spi(id, this->proposal->get_spi(this->proposal)); - } - } - if (!this->keymat->derive_ike_keys(this->keymat, this->proposal, this->dh, - nonce_i, nonce_r, id, prf_alg, skd)) - { - return FALSE; - } - charon->bus->ike_keys(charon->bus, this->ike_sa, this->dh, - nonce_i, nonce_r, this->old_sa); - return TRUE; -} - -/** - * Implementation of task_t.build for responder - */ -static status_t build_r(private_ike_init_t *this, message_t *message) -{ - /* check if we have everything we need */ - if (this->proposal == NULL || - this->other_nonce.len == 0 || this->my_nonce.len == 0) - { - DBG1(DBG_IKE, "received proposals inacceptable"); - message->add_notify(message, TRUE, NO_PROPOSAL_CHOSEN, chunk_empty); - return FAILED; - } - this->ike_sa->set_proposal(this->ike_sa, this->proposal); - - if (this->dh == NULL || - !this->proposal->has_dh_group(this->proposal, this->dh_group)) - { - u_int16_t group; - - if (this->proposal->get_algorithm(this->proposal, DIFFIE_HELLMAN_GROUP, - &group, NULL)) - { - DBG1(DBG_IKE, "DH group %N inacceptable, requesting %N", - diffie_hellman_group_names, this->dh_group, - diffie_hellman_group_names, group); - this->dh_group = group; - group = htons(group); - message->add_notify(message, FALSE, INVALID_KE_PAYLOAD, - chunk_from_thing(group)); - } - else - { - DBG1(DBG_IKE, "no acceptable proposal found"); - } - return FAILED; - } - - if (!derive_keys(this, this->other_nonce, this->my_nonce)) - { - DBG1(DBG_IKE, "key derivation failed"); - message->add_notify(message, TRUE, NO_PROPOSAL_CHOSEN, chunk_empty); - return FAILED; - } - build_payloads(this, message); - return SUCCESS; -} - -/** - * Implementation of task_t.process for initiator - */ -static status_t process_i(private_ike_init_t *this, message_t *message) -{ - enumerator_t *enumerator; - payload_t *payload; - - /* check for erronous notifies */ - 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 INVALID_KE_PAYLOAD: - { - chunk_t data; - diffie_hellman_group_t bad_group; - - bad_group = this->dh_group; - data = notify->get_notification_data(notify); - this->dh_group = ntohs(*((u_int16_t*)data.ptr)); - DBG1(DBG_IKE, "peer didn't accept DH group %N, " - "it requested %N", diffie_hellman_group_names, - bad_group, diffie_hellman_group_names, this->dh_group); - - if (this->old_sa == NULL) - { /* reset the IKE_SA if we are not rekeying */ - this->ike_sa->reset(this->ike_sa); - } - - enumerator->destroy(enumerator); - this->retry++; - return NEED_MORE; - } - case NAT_DETECTION_SOURCE_IP: - case NAT_DETECTION_DESTINATION_IP: - /* skip, handled in ike_natd_t */ - break; - case MULTIPLE_AUTH_SUPPORTED: - /* handled in ike_auth_t */ - break; - case COOKIE: - { - chunk_free(&this->cookie); - this->cookie = chunk_clone(notify->get_notification_data(notify)); - this->ike_sa->reset(this->ike_sa); - enumerator->destroy(enumerator); - DBG2(DBG_IKE, "received %N notify", notify_type_names, type); - this->retry++; - return NEED_MORE; - } - 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); - - process_payloads(this, message); - - /* check if we have everything */ - if (this->proposal == NULL || - this->other_nonce.len == 0 || this->my_nonce.len == 0) - { - DBG1(DBG_IKE, "peers proposal selection invalid"); - return FAILED; - } - this->ike_sa->set_proposal(this->ike_sa, this->proposal); - - if (this->dh == NULL || - !this->proposal->has_dh_group(this->proposal, this->dh_group)) - { - DBG1(DBG_IKE, "peer DH group selection invalid"); - return FAILED; - } - - if (!derive_keys(this, this->my_nonce, this->other_nonce)) - { - DBG1(DBG_IKE, "key derivation failed"); - return FAILED; - } - return SUCCESS; -} - -/** - * Implementation of task_t.get_type - */ -static task_type_t get_type(private_ike_init_t *this) -{ - return IKE_INIT; -} - -/** - * Implementation of task_t.get_type - */ -static chunk_t get_lower_nonce(private_ike_init_t *this) -{ - if (memcmp(this->my_nonce.ptr, this->other_nonce.ptr, - min(this->my_nonce.len, this->other_nonce.len)) < 0) - { - return this->my_nonce; - } - else - { - return this->other_nonce; - } -} - -/** - * Implementation of task_t.migrate - */ -static void migrate(private_ike_init_t *this, ike_sa_t *ike_sa) -{ - DESTROY_IF(this->proposal); - chunk_free(&this->other_nonce); - - this->ike_sa = ike_sa; - this->proposal = NULL; - DESTROY_IF(this->dh); - this->dh = this->keymat->create_dh(this->keymat, this->dh_group); -} - -/** - * Implementation of task_t.destroy - */ -static void destroy(private_ike_init_t *this) -{ - DESTROY_IF(this->dh); - DESTROY_IF(this->proposal); - chunk_free(&this->my_nonce); - chunk_free(&this->other_nonce); - chunk_free(&this->cookie); - free(this); -} - -/* - * Described in header. - */ -ike_init_t *ike_init_create(ike_sa_t *ike_sa, bool initiator, ike_sa_t *old_sa) -{ - private_ike_init_t *this = malloc_thing(private_ike_init_t); - - this->public.get_lower_nonce = (chunk_t(*)(ike_init_t*))get_lower_nonce; - 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->dh_group = MODP_NONE; - this->dh = NULL; - this->keymat = ike_sa->get_keymat(ike_sa); - this->my_nonce = chunk_empty; - this->other_nonce = chunk_empty; - this->cookie = chunk_empty; - this->proposal = NULL; - this->config = NULL; - this->old_sa = old_sa; - this->retry = 0; - - return &this->public; -} diff --git a/src/charon/sa/tasks/ike_init.h b/src/charon/sa/tasks/ike_init.h deleted file mode 100644 index 7bd784cff..000000000 --- a/src/charon/sa/tasks/ike_init.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2007 Martin Willi - * 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. - */ - -/** - * @defgroup ike_init ike_init - * @{ @ingroup tasks - */ - -#ifndef IKE_INIT_H_ -#define IKE_INIT_H_ - -typedef struct ike_init_t ike_init_t; - -#include <library.h> -#include <sa/ike_sa.h> -#include <sa/tasks/task.h> - -/** - * Task of type IKE_INIT, creates an IKE_SA without authentication. - * - * The authentication of is handle in the ike_auth task. - */ -struct ike_init_t { - - /** - * Implements the task_t interface - */ - task_t task; - - /** - * Get the lower of the two nonces, used for rekey collisions. - * - * @return lower nonce - */ - chunk_t (*get_lower_nonce) (ike_init_t *this); -}; - -/** - * Create a new IKE_INIT task. - * - * @param ike_sa IKE_SA this task works for (new one when rekeying) - * @param initiator TRUE if thask is the original initator - * @param old_sa old IKE_SA when we are rekeying - * @return ike_init task to handle by the task_manager - */ -ike_init_t *ike_init_create(ike_sa_t *ike_sa, bool initiator, ike_sa_t *old_sa); - -#endif /** IKE_INIT_H_ @}*/ diff --git a/src/charon/sa/tasks/ike_me.c b/src/charon/sa/tasks/ike_me.c deleted file mode 100644 index 2d2847ae0..000000000 --- a/src/charon/sa/tasks/ike_me.c +++ /dev/null @@ -1,856 +0,0 @@ -/* - * Copyright (C) 2007-2008 Tobias Brunner - * 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_me.h" - -#include <string.h> - -#include <daemon.h> -#include <config/peer_cfg.h> -#include <encoding/payloads/id_payload.h> -#include <encoding/payloads/notify_payload.h> -#include <encoding/payloads/endpoint_notify.h> -#include <processing/jobs/mediation_job.h> - -#define ME_CONNECTID_LEN 4 -#define ME_CONNECTKEY_LEN 16 - -typedef struct private_ike_me_t private_ike_me_t; - -/** - * Private members of a ike_me_t task. - */ -struct private_ike_me_t { - - /** - * Public methods and task_t interface. - */ - ike_me_t public; - - /** - * Assigned IKE_SA. - */ - ike_sa_t *ike_sa; - - /** - * Are we the initiator? - */ - bool initiator; - - /** - * Is this a mediation connection? - */ - bool mediation; - - /** - * Is this the response from another peer? - */ - bool response; - - /** - * Gathered endpoints - */ - linked_list_t *local_endpoints; - - /** - * Parsed endpoints - */ - linked_list_t *remote_endpoints; - - /** - * Did the peer request a callback? - */ - bool callback; - - /** - * Did the connect fail? - */ - bool failed; - - /** - * Was there anything wrong with the payloads? - */ - bool invalid_syntax; - - /** - * The requested peer - */ - identification_t *peer_id; - /** - * Received ID used for connectivity checks - */ - chunk_t connect_id; - - /** - * Received key used for connectivity checks - */ - chunk_t connect_key; - - /** - * Peer config of the mediated connection - */ - peer_cfg_t *mediated_cfg; - -}; - -/** - * Adds a list of endpoints as notifies to a given message - */ -static void add_endpoints_to_message(message_t *message, linked_list_t *endpoints) -{ - iterator_t *iterator; - endpoint_notify_t *endpoint; - - iterator = endpoints->create_iterator(endpoints, TRUE); - while (iterator->iterate(iterator, (void**)&endpoint)) - { - message->add_payload(message, (payload_t*)endpoint->build_notify(endpoint)); - } - iterator->destroy(iterator); -} - -/** - * Gathers endpoints and adds them to the current message - */ -static void gather_and_add_endpoints(private_ike_me_t *this, message_t *message) -{ - enumerator_t *enumerator; - host_t *addr, *host; - u_int16_t port; - - /* get the port that is used to communicate with the ms */ - host = this->ike_sa->get_my_host(this->ike_sa); - port = host->get_port(host); - - enumerator = charon->kernel_interface->create_address_enumerator( - charon->kernel_interface, FALSE, FALSE); - while (enumerator->enumerate(enumerator, (void**)&addr)) - { - host = addr->clone(addr); - host->set_port(host, port); - - this->local_endpoints->insert_last(this->local_endpoints, - endpoint_notify_create_from_host(HOST, host, NULL)); - - host->destroy(host); - } - enumerator->destroy(enumerator); - - host = this->ike_sa->get_server_reflexive_host(this->ike_sa); - if (host) - { - this->local_endpoints->insert_last(this->local_endpoints, - endpoint_notify_create_from_host(SERVER_REFLEXIVE, host, - this->ike_sa->get_my_host(this->ike_sa))); - } - - add_endpoints_to_message(message, this->local_endpoints); -} - -/** - * read notifys from message and evaluate them - */ -static void process_payloads(private_ike_me_t *this, message_t *message) -{ - enumerator_t *enumerator; - payload_t *payload; - - enumerator = message->create_payload_enumerator(message); - while (enumerator->enumerate(enumerator, &payload)) - { - if (payload->get_type(payload) != NOTIFY) - { - continue; - } - - notify_payload_t *notify = (notify_payload_t*)payload; - - switch (notify->get_notify_type(notify)) - { - case ME_CONNECT_FAILED: - { - DBG2(DBG_IKE, "received ME_CONNECT_FAILED notify"); - this->failed = TRUE; - break; - } - case ME_MEDIATION: - { - DBG2(DBG_IKE, "received ME_MEDIATION notify"); - this->mediation = TRUE; - break; - } - case ME_ENDPOINT: - { - endpoint_notify_t *endpoint; - endpoint = endpoint_notify_create_from_payload(notify); - if (!endpoint) - { - DBG1(DBG_IKE, "received invalid ME_ENDPOINT notify"); - break; - } - DBG1(DBG_IKE, "received %N ME_ENDPOINT %#H", - me_endpoint_type_names, endpoint->get_type(endpoint), - endpoint->get_host(endpoint)); - - this->remote_endpoints->insert_last(this->remote_endpoints, - endpoint); - break; - } - case ME_CALLBACK: - { - DBG2(DBG_IKE, "received ME_CALLBACK notify"); - this->callback = TRUE; - break; - } - case ME_CONNECTID: - { - chunk_free(&this->connect_id); - this->connect_id = chunk_clone(notify->get_notification_data(notify)); - DBG2(DBG_IKE, "received ME_CONNECTID %#B", &this->connect_id); - break; - } - case ME_CONNECTKEY: - { - chunk_free(&this->connect_key); - this->connect_key = chunk_clone(notify->get_notification_data(notify)); - DBG4(DBG_IKE, "received ME_CONNECTKEY %#B", &this->connect_key); - break; - } - case ME_RESPONSE: - { - DBG2(DBG_IKE, "received ME_RESPONSE notify"); - this->response = TRUE; - break; - } - default: - break; - } - } - enumerator->destroy(enumerator); -} - -/** - * Implementation of task_t.build for initiator - */ -static status_t build_i(private_ike_me_t *this, message_t *message) -{ - switch(message->get_exchange_type(message)) - { - case IKE_SA_INIT: - { - peer_cfg_t *peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa); - if (peer_cfg->is_mediation(peer_cfg)) - { - DBG2(DBG_IKE, "adding ME_MEDIATION"); - message->add_notify(message, FALSE, ME_MEDIATION, chunk_empty); - } - else - { - return SUCCESS; - } - break; - } - case IKE_AUTH: - { - if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_HERE)) - { - endpoint_notify_t *endpoint; - endpoint = endpoint_notify_create_from_host(SERVER_REFLEXIVE, - NULL, NULL); - message->add_payload(message, (payload_t*)endpoint->build_notify(endpoint)); - endpoint->destroy(endpoint); - } - break; - } - case ME_CONNECT: - { - rng_t *rng; - id_payload_t *id_payload; - id_payload = id_payload_create_from_identification(ID_PEER, - this->peer_id); - message->add_payload(message, (payload_t*)id_payload); - - rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG); - if (!rng) - { - DBG1(DBG_IKE, "unable to generate connect ID for ME_CONNECT"); - return FAILED; - } - if (!this->response) - { - /* only the initiator creates a connect ID. the responder - * returns the connect ID that it received from the initiator */ - rng->allocate_bytes(rng, ME_CONNECTID_LEN, &this->connect_id); - } - rng->allocate_bytes(rng, ME_CONNECTKEY_LEN, &this->connect_key); - rng->destroy(rng); - - message->add_notify(message, FALSE, ME_CONNECTID, this->connect_id); - message->add_notify(message, FALSE, ME_CONNECTKEY, this->connect_key); - - if (this->response) - { - message->add_notify(message, FALSE, ME_RESPONSE, chunk_empty); - } - else - { - /* FIXME: should we make this configurable? */ - message->add_notify(message, FALSE, ME_CALLBACK, chunk_empty); - } - - gather_and_add_endpoints(this, message); - - break; - } - default: - break; - } - return NEED_MORE; -} - -/** - * Implementation of task_t.process for responder - */ -static status_t process_r(private_ike_me_t *this, message_t *message) -{ - switch(message->get_exchange_type(message)) - { - case ME_CONNECT: - { - id_payload_t *id_payload; - id_payload = (id_payload_t*)message->get_payload(message, ID_PEER); - if (!id_payload) - { - DBG1(DBG_IKE, "received ME_CONNECT without ID_PEER payload" - ", aborting"); - break; - } - this->peer_id = id_payload->get_identification(id_payload); - - process_payloads(this, message); - - if (this->callback) - { - DBG1(DBG_IKE, "received ME_CALLBACK for '%Y'", this->peer_id); - break; - } - - if (!this->connect_id.ptr) - { - DBG1(DBG_IKE, "received ME_CONNECT without ME_CONNECTID notify" - ", aborting"); - this->invalid_syntax = TRUE; - break; - } - - if (!this->connect_key.ptr) - { - DBG1(DBG_IKE, "received ME_CONNECT without ME_CONNECTKEY " - "notify, aborting"); - this->invalid_syntax = TRUE; - break; - } - - if (!this->remote_endpoints->get_count(this->remote_endpoints)) - { - DBG1(DBG_IKE, "received ME_CONNECT without any ME_ENDPOINT " - "payloads, aborting"); - this->invalid_syntax = TRUE; - break; - } - - DBG1(DBG_IKE, "received ME_CONNECT"); - break; - } - default: - break; - } - return NEED_MORE; -} - -/** - * Implementation of task_t.build for responder - */ -static status_t build_r(private_ike_me_t *this, message_t *message) -{ - switch(message->get_exchange_type(message)) - { - case ME_CONNECT: - { - if (this->invalid_syntax) - { - message->add_notify(message, TRUE, INVALID_SYNTAX, chunk_empty); - break; - } - - if (this->callback) - { - /* we got a callback from the mediation server, initiate the - * queued mediated connecction */ - charon->connect_manager->check_and_initiate( - charon->connect_manager, - this->ike_sa->get_id(this->ike_sa), - this->ike_sa->get_my_id(this->ike_sa), this->peer_id); - return SUCCESS; - } - - if (this->response) - { - /* FIXME: handle result of set_responder_data - * as initiator, upon receiving a response from another peer, - * update the checklist and start sending checks */ - charon->connect_manager->set_responder_data( - charon->connect_manager, - this->connect_id, this->connect_key, - this->remote_endpoints); - } - else - { - /* FIXME: handle result of set_initiator_data - * as responder, create a checklist with the initiator's data */ - charon->connect_manager->set_initiator_data( - charon->connect_manager, - this->peer_id, this->ike_sa->get_my_id(this->ike_sa), - this->connect_id, this->connect_key, - this->remote_endpoints, FALSE); - if (this->ike_sa->respond(this->ike_sa, this->peer_id, - this->connect_id) != SUCCESS) - { - return FAILED; - } - } - break; - } - default: - break; - } - return SUCCESS; -} - -/** - * Implementation of task_t.process for initiator - */ -static status_t process_i(private_ike_me_t *this, message_t *message) -{ - switch(message->get_exchange_type(message)) - { - case IKE_SA_INIT: - { - process_payloads(this, message); - if (!this->mediation) - { - DBG1(DBG_IKE, "server did not return a ME_MEDIATION, aborting"); - return FAILED; - } - return NEED_MORE; - } - case IKE_AUTH: - { - process_payloads(this, message); - /* FIXME: we should update the server reflexive endpoint somehow, - * if mobike notices a change */ - endpoint_notify_t *reflexive; - if (this->remote_endpoints->get_first(this->remote_endpoints, - (void**)&reflexive) == SUCCESS && - reflexive->get_type(reflexive) == SERVER_REFLEXIVE) - { /* FIXME: should we accept this endpoint even if we did not send - * a request? */ - host_t *endpoint = reflexive->get_host(reflexive); - endpoint = endpoint->clone(endpoint); - this->ike_sa->set_server_reflexive_host(this->ike_sa, endpoint); - } - break; - } - case ME_CONNECT: - { - process_payloads(this, message); - - if (this->failed) - { - DBG1(DBG_IKE, "peer '%Y' is not online", this->peer_id); - /* FIXME: notify the mediated connection (job?) */ - } - else - { - if (this->response) - { - /* FIXME: handle result of set_responder_data. */ - /* as responder, we update the checklist and start sending - * checks */ - charon->connect_manager->set_responder_data( - charon->connect_manager, this->connect_id, - this->connect_key, this->local_endpoints); - } - else - { - /* FIXME: handle result of set_initiator_data */ - /* as initiator, we create a checklist and set the - * initiator's data */ - charon->connect_manager->set_initiator_data( - charon->connect_manager, - this->ike_sa->get_my_id(this->ike_sa), - this->peer_id, this->connect_id, this->connect_key, - this->local_endpoints, TRUE); - /* FIXME: also start a timer for the whole transaction - * (maybe within the connect_manager?) */ - } - } - break; - } - default: - break; - } - return SUCCESS; -} - -/** - * Implementation of task_t.build for initiator (mediation server) - */ -static status_t build_i_ms(private_ike_me_t *this, message_t *message) -{ - switch(message->get_exchange_type(message)) - { - case ME_CONNECT: - { - id_payload_t *id_payload; - id_payload = id_payload_create_from_identification(ID_PEER, - this->peer_id); - message->add_payload(message, (payload_t*)id_payload); - - if (this->callback) - { - message->add_notify(message, FALSE, ME_CALLBACK, chunk_empty); - } - else - { - if (this->response) - { - message->add_notify(message, FALSE, ME_RESPONSE, - chunk_empty); - } - message->add_notify(message, FALSE, ME_CONNECTID, - this->connect_id); - message->add_notify(message, FALSE, ME_CONNECTKEY, - this->connect_key); - add_endpoints_to_message(message, this->remote_endpoints); - } - break; - } - default: - break; - } - return NEED_MORE; -} - -/** - * Implementation of task_t.process for responder (mediation server) - */ -static status_t process_r_ms(private_ike_me_t *this, message_t *message) -{ - switch(message->get_exchange_type(message)) - { - case IKE_SA_INIT: - { - /* FIXME: we should check for SA* and TS* payloads. if there are - * any, send NO_ADDITIONAL_SAS back and delete this SA */ - process_payloads(this, message); - return this->mediation ? NEED_MORE : SUCCESS; - } - case IKE_AUTH: - { - /* FIXME: we should check whether the current peer_config is - * configured as mediation connection */ - process_payloads(this, message); - break; - } - case CREATE_CHILD_SA: - { - /* FIXME: if this is not to rekey the IKE SA we have to return a - * NO_ADDITIONAL_SAS and then delete the SA */ - break; - } - case ME_CONNECT: - { - id_payload_t *id_payload; - id_payload = (id_payload_t*)message->get_payload(message, ID_PEER); - if (!id_payload) - { - DBG1(DBG_IKE, "received ME_CONNECT without ID_PEER payload" - ", aborting"); - this->invalid_syntax = TRUE; - break; - } - this->peer_id = id_payload->get_identification(id_payload); - - process_payloads(this, message); - - if (!this->connect_id.ptr) - { - DBG1(DBG_IKE, "received ME_CONNECT without ME_CONNECTID notify" - ", aborting"); - this->invalid_syntax = TRUE; - break; - } - - if (!this->connect_key.ptr) - { - DBG1(DBG_IKE, "received ME_CONNECT without ME_CONNECTKEY notify" - ", aborting"); - this->invalid_syntax = TRUE; - break; - } - - if (!this->remote_endpoints->get_count(this->remote_endpoints)) - { - DBG1(DBG_IKE, "received ME_CONNECT without any ME_ENDPOINT " - "payloads, aborting"); - this->invalid_syntax = TRUE; - break; - } - break; - } - default: - break; - } - return NEED_MORE; -} - -/** - * Implementation of task_t.build for responder (mediation server) - */ -static status_t build_r_ms(private_ike_me_t *this, message_t *message) -{ - switch(message->get_exchange_type(message)) - { - case IKE_SA_INIT: - { - message->add_notify(message, FALSE, ME_MEDIATION, chunk_empty); - return NEED_MORE; - } - case IKE_AUTH: - { - endpoint_notify_t *endpoint; - if (this->remote_endpoints->get_first(this->remote_endpoints, - (void**)&endpoint) == SUCCESS && - endpoint->get_type(endpoint) == SERVER_REFLEXIVE) - { - host_t *host = this->ike_sa->get_other_host(this->ike_sa); - DBG2(DBG_IKE, "received request for a server reflexive " - "endpoint sending: %#H", host); - endpoint = endpoint_notify_create_from_host(SERVER_REFLEXIVE, - host, NULL); - message->add_payload(message, (payload_t*)endpoint->build_notify(endpoint)); - endpoint->destroy(endpoint); - } - this->ike_sa->act_as_mediation_server(this->ike_sa); - break; - } - case ME_CONNECT: - { - if (this->invalid_syntax) - { - message->add_notify(message, TRUE, INVALID_SYNTAX, chunk_empty); - break; - } - - ike_sa_id_t *peer_sa; - if (this->callback) - { - peer_sa = charon->mediation_manager->check_and_register( - charon->mediation_manager, this->peer_id, - this->ike_sa->get_other_id(this->ike_sa)); - } - else - { - peer_sa = charon->mediation_manager->check( - charon->mediation_manager, this->peer_id); - } - - if (!peer_sa) - { - /* the peer is not online */ - message->add_notify(message, TRUE, ME_CONNECT_FAILED, - chunk_empty); - break; - } - - job_t *job = (job_t*)mediation_job_create(this->peer_id, - this->ike_sa->get_other_id(this->ike_sa), this->connect_id, - this->connect_key, this->remote_endpoints, this->response); - charon->processor->queue_job(charon->processor, job); - break; - } - default: - break; - } - return SUCCESS; -} - -/** - * Implementation of task_t.process for initiator (mediation server) - */ -static status_t process_i_ms(private_ike_me_t *this, message_t *message) -{ - /* FIXME: theoretically we should be prepared to receive a ME_CONNECT_FAILED - * here if the responding peer is not able to proceed. in this case we shall - * notify the initiating peer with a ME_CONNECT request containing only a - * ME_CONNECT_FAILED */ - return SUCCESS; -} - -/** - * Implementation of ike_me.connect - */ -static void me_connect(private_ike_me_t *this, identification_t *peer_id) -{ - this->peer_id = peer_id->clone(peer_id); -} - -/** - * Implementation of ike_me.respond - */ -static void me_respond(private_ike_me_t *this, identification_t *peer_id, - chunk_t connect_id) -{ - this->peer_id = peer_id->clone(peer_id); - this->connect_id = chunk_clone(connect_id); - this->response = TRUE; -} - -/** - * Implementation of ike_me.callback - */ -static void me_callback(private_ike_me_t *this, identification_t *peer_id) -{ - this->peer_id = peer_id->clone(peer_id); - this->callback = TRUE; -} - -/** - * Implementation of ike_me.relay - */ -static void relay(private_ike_me_t *this, identification_t *requester, - chunk_t connect_id, chunk_t connect_key, - linked_list_t *endpoints, bool response) -{ - this->peer_id = requester->clone(requester); - this->connect_id = chunk_clone(connect_id); - this->connect_key = chunk_clone(connect_key); - - this->remote_endpoints->destroy_offset(this->remote_endpoints, - offsetof(endpoint_notify_t, destroy)); - this->remote_endpoints = endpoints->clone_offset(endpoints, - offsetof(endpoint_notify_t, clone)); - - this->response = response; -} - -/** - * Implementation of task_t.get_type - */ -static task_type_t get_type(private_ike_me_t *this) -{ - return IKE_ME; -} - -/** - * Implementation of task_t.migrate - */ -static void migrate(private_ike_me_t *this, ike_sa_t *ike_sa) -{ - this->ike_sa = ike_sa; -} - -/** - * Implementation of task_t.destroy - */ -static void destroy(private_ike_me_t *this) -{ - DESTROY_IF(this->peer_id); - - chunk_free(&this->connect_id); - chunk_free(&this->connect_key); - - this->local_endpoints->destroy_offset(this->local_endpoints, - offsetof(endpoint_notify_t, destroy)); - this->remote_endpoints->destroy_offset(this->remote_endpoints, - offsetof(endpoint_notify_t, destroy)); - - DESTROY_IF(this->mediated_cfg); - free(this); -} - -/* - * Described in header. - */ -ike_me_t *ike_me_create(ike_sa_t *ike_sa, bool initiator) -{ - private_ike_me_t *this = malloc_thing(private_ike_me_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 (ike_sa->has_condition(ike_sa, COND_ORIGINAL_INITIATOR)) - { - 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; - } - } - else - { - /* mediation server */ - if (initiator) - { - this->public.task.build = (status_t(*)(task_t*,message_t*))build_i_ms; - this->public.task.process = (status_t(*)(task_t*,message_t*))process_i_ms; - } - else - { - this->public.task.build = (status_t(*)(task_t*,message_t*))build_r_ms; - this->public.task.process = (status_t(*)(task_t*,message_t*))process_r_ms; - } - } - - this->public.connect = (void(*)(ike_me_t*,identification_t*))me_connect; - this->public.respond = (void(*)(ike_me_t*,identification_t*,chunk_t))me_respond; - this->public.callback = (void(*)(ike_me_t*,identification_t*))me_callback; - this->public.relay = (void(*)(ike_me_t*,identification_t*,chunk_t,chunk_t,linked_list_t*,bool))relay; - - this->ike_sa = ike_sa; - this->initiator = initiator; - - this->peer_id = NULL; - this->connect_id = chunk_empty; - this->connect_key = chunk_empty; - this->local_endpoints = linked_list_create(); - this->remote_endpoints = linked_list_create(); - this->mediation = FALSE; - this->response = FALSE; - this->callback = FALSE; - this->failed = FALSE; - this->invalid_syntax = FALSE; - - this->mediated_cfg = NULL; - - return &this->public; -} diff --git a/src/charon/sa/tasks/ike_me.h b/src/charon/sa/tasks/ike_me.h deleted file mode 100644 index 31285a426..000000000 --- a/src/charon/sa/tasks/ike_me.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2007 Tobias Brunner - * 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. - */ - -/** - * @defgroup ike_me ike_me - * @{ @ingroup tasks - */ - -#ifndef IKE_ME_H_ -#define IKE_ME_H_ - -typedef struct ike_me_t ike_me_t; - -#include <library.h> -#include <sa/ike_sa.h> -#include <sa/tasks/task.h> - -/** - * Task of type IKE_ME, detects and handles IKE-ME extensions. - * - * This tasks handles the ME_MEDIATION Notify exchange to setup a mediation - * connection, allows to initiate mediated connections using ME_CONNECT - * exchanges and to request reflexive addresses from the mediation server using - * ME_ENDPOINT notifies. - * - * @note This task has to be activated before the IKE_AUTH task, because that - * task generates the IKE_SA_INIT message so that no more payloads can be added - * to it afterwards. - */ -struct ike_me_t { - /** - * Implements the task_t interface - */ - task_t task; - - /** - * Initiates a connection with another peer (i.e. sends a ME_CONNECT - * to the mediation server) - * - * @param peer_id ID of the other peer (gets cloned) - */ - void (*connect)(ike_me_t *this, identification_t *peer_id); - - /** - * Responds to a ME_CONNECT from another peer (i.e. sends a ME_CONNECT - * to the mediation server) - * - * Data gets cloned. - * - * @param peer_id ID of the other peer - * @param connect_id the connect ID as provided by the initiator - */ - void (*respond)(ike_me_t *this, identification_t *peer_id, - chunk_t connect_id); - - /** - * Sends a ME_CALLBACK to a peer that previously requested some other peer. - * - * @param peer_id ID of the other peer (gets cloned) - */ - void (*callback)(ike_me_t *this, identification_t *peer_id); - - /** - * Relays data to another peer (i.e. sends a ME_CONNECT to the peer) - * - * Data gets cloned. - * - * @param requester ID of the requesting peer - * @param connect_id content of the ME_CONNECTID notify - * @param connect_key content of the ME_CONNECTKEY notify - * @param endpoints endpoints - * @param response TRUE if this is a response - */ - void (*relay)(ike_me_t *this, identification_t *requester, - chunk_t connect_id, chunk_t connect_key, - linked_list_t *endpoints, bool response); -}; - -/** - * Create a new ike_me task. - * - * @param ike_sa IKE_SA this task works for - * @param initiator TRUE if task is initiated by us - * @return ike_me task to be handled by the task_manager - */ -ike_me_t *ike_me_create(ike_sa_t *ike_sa, bool initiator); - -#endif /** IKE_ME_H_ @}*/ diff --git a/src/charon/sa/tasks/ike_mobike.c b/src/charon/sa/tasks/ike_mobike.c deleted file mode 100644 index d76ba8d2b..000000000 --- a/src/charon/sa/tasks/ike_mobike.c +++ /dev/null @@ -1,637 +0,0 @@ -/* - * Copyright (C) 2007 Martin Willi - * 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_mobike.h" - -#include <string.h> - -#include <daemon.h> -#include <sa/tasks/ike_natd.h> -#include <encoding/payloads/notify_payload.h> - -#define COOKIE2_SIZE 16 -#define MAX_ADDITIONAL_ADDRS 8 - -typedef struct private_ike_mobike_t private_ike_mobike_t; - -/** - * Private members of a ike_mobike_t task. - */ -struct private_ike_mobike_t { - - /** - * Public methods and task_t interface. - */ - ike_mobike_t public; - - /** - * Assigned IKE_SA. - */ - ike_sa_t *ike_sa; - - /** - * Are we the initiator? - */ - bool initiator; - - /** - * cookie2 value to verify new addresses - */ - chunk_t cookie2; - - /** - * NAT discovery reusing the IKE_NATD task - */ - ike_natd_t *natd; - - /** - * use task to update addresses - */ - bool update; - - /** - * do routability check - */ - bool check; - - /** - * include address list update - */ - bool address; -}; - -/** - * flush the IKE_SAs list of additional addresses - */ -static void flush_additional_addresses(private_ike_mobike_t *this) -{ - iterator_t *iterator; - host_t *host; - - iterator = this->ike_sa->create_additional_address_iterator(this->ike_sa); - while (iterator->iterate(iterator, (void**)&host)) - { - iterator->remove(iterator); - host->destroy(host); - } - iterator->destroy(iterator); -} - - -/** - * read notifys from message and evaluate them - */ -static void process_payloads(private_ike_mobike_t *this, message_t *message) -{ - enumerator_t *enumerator; - payload_t *payload; - bool first = TRUE; - - enumerator = message->create_payload_enumerator(message); - while (enumerator->enumerate(enumerator, &payload)) - { - int family = AF_INET; - notify_payload_t *notify; - chunk_t data; - host_t *host; - - if (payload->get_type(payload) != NOTIFY) - { - continue; - } - notify = (notify_payload_t*)payload; - switch (notify->get_notify_type(notify)) - { - case MOBIKE_SUPPORTED: - { - peer_cfg_t *peer_cfg; - - peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa); - if (!this->initiator && - peer_cfg && !peer_cfg->use_mobike(peer_cfg)) - { - DBG1(DBG_IKE, "peer supports MOBIKE, but disabled in config"); - } - else - { - DBG1(DBG_IKE, "peer supports MOBIKE"); - this->ike_sa->enable_extension(this->ike_sa, EXT_MOBIKE); - } - break; - } - case COOKIE2: - { - chunk_free(&this->cookie2); - this->cookie2 = chunk_clone(notify->get_notification_data(notify)); - break; - } - case ADDITIONAL_IP6_ADDRESS: - { - family = AF_INET6; - /* fall through */ - } - case ADDITIONAL_IP4_ADDRESS: - { - if (first) - { /* an ADDITIONAL_*_ADDRESS means replace, so flush once */ - flush_additional_addresses(this); - first = FALSE; - } - data = notify->get_notification_data(notify); - host = host_create_from_chunk(family, data, 0); - DBG2(DBG_IKE, "got additional MOBIKE peer address: %H", host); - this->ike_sa->add_additional_address(this->ike_sa, host); - break; - } - case UPDATE_SA_ADDRESSES: - { - this->update = TRUE; - break; - } - case NO_ADDITIONAL_ADDRESSES: - { - flush_additional_addresses(this); - break; - } - case NAT_DETECTION_SOURCE_IP: - case NAT_DETECTION_DESTINATION_IP: - { - /* NAT check in this MOBIKE exchange, create subtask for it */ - if (this->natd == NULL) - { - this->natd = ike_natd_create(this->ike_sa, this->initiator); - } - break; - } - default: - break; - } - } - enumerator->destroy(enumerator); -} - -/** - * Add ADDITIONAL_*_ADDRESS notifys depending on our address list - */ -static void build_address_list(private_ike_mobike_t *this, message_t *message) -{ - enumerator_t *enumerator; - host_t *host, *me; - notify_type_t type; - int added = 0; - - me = this->ike_sa->get_my_host(this->ike_sa); - enumerator = charon->kernel_interface->create_address_enumerator( - charon->kernel_interface, FALSE, FALSE); - while (enumerator->enumerate(enumerator, (void**)&host)) - { - if (me->ip_equals(me, host)) - { /* "ADDITIONAL" means do not include IKE_SAs host */ - continue; - } - switch (host->get_family(host)) - { - case AF_INET: - type = ADDITIONAL_IP4_ADDRESS; - break; - case AF_INET6: - type = ADDITIONAL_IP6_ADDRESS; - break; - default: - continue; - } - message->add_notify(message, FALSE, type, host->get_address(host)); - if (++added >= MAX_ADDITIONAL_ADDRS) - { /* limit number of notifys, some implementations do not like too - * many of them (f.e. strongSwan ;-) */ - break; - } - } - if (!added) - { - message->add_notify(message, FALSE, NO_ADDITIONAL_ADDRESSES, chunk_empty); - } - enumerator->destroy(enumerator); -} - -/** - * build a cookie and add it to the message - */ -static void build_cookie(private_ike_mobike_t *this, message_t *message) -{ - rng_t *rng; - - chunk_free(&this->cookie2); - rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG); - if (rng) - { - rng->allocate_bytes(rng, COOKIE2_SIZE, &this->cookie2); - rng->destroy(rng); - message->add_notify(message, FALSE, COOKIE2, this->cookie2); - } -} - -/** - * update addresses of associated CHILD_SAs - */ -static void update_children(private_ike_mobike_t *this) -{ - iterator_t *iterator; - child_sa_t *child_sa; - - iterator = this->ike_sa->create_child_sa_iterator(this->ike_sa); - while (iterator->iterate(iterator, (void**)&child_sa)) - { - if (child_sa->update(child_sa, - this->ike_sa->get_my_host(this->ike_sa), - this->ike_sa->get_other_host(this->ike_sa), - this->ike_sa->get_virtual_ip(this->ike_sa, TRUE), - this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY)) == NOT_SUPPORTED) - { - this->ike_sa->rekey_child_sa(this->ike_sa, - child_sa->get_protocol(child_sa), - child_sa->get_spi(child_sa, TRUE)); - } - } - iterator->destroy(iterator); -} - -/** - * Implementation of ike_mobike_t.transmit - */ -static void transmit(private_ike_mobike_t *this, packet_t *packet) -{ - host_t *me, *other, *me_old, *other_old; - iterator_t *iterator; - packet_t *copy; - - if (!this->check) - { - return; - } - - me_old = this->ike_sa->get_my_host(this->ike_sa); - other_old = this->ike_sa->get_other_host(this->ike_sa); - - me = charon->kernel_interface->get_source_addr( - charon->kernel_interface, other_old, NULL); - if (me) - { - me->set_port(me, me->ip_equals(me, me_old) ? - me_old->get_port(me_old) : IKEV2_NATT_PORT); - DBG1(DBG_IKE, "checking original path %#H - %#H", me, other_old); - copy = packet->clone(packet); - copy->set_source(copy, me); - charon->sender->send(charon->sender, copy); - } - - iterator = this->ike_sa->create_additional_address_iterator(this->ike_sa); - while (iterator->iterate(iterator, (void**)&other)) - { - me = charon->kernel_interface->get_source_addr( - charon->kernel_interface, other, NULL); - if (me) - { - if (me->get_family(me) != other->get_family(other)) - { - me->destroy(me); - continue; - } - /* reuse port for an active address, 4500 otherwise */ - me->set_port(me, me->ip_equals(me, me_old) ? - me_old->get_port(me_old) : IKEV2_NATT_PORT); - other = other->clone(other); - other->set_port(other, other->ip_equals(other, other_old) ? - other_old->get_port(other_old) : IKEV2_NATT_PORT); - DBG1(DBG_IKE, "checking path %#H - %#H", me, other); - copy = packet->clone(packet); - copy->set_source(copy, me); - copy->set_destination(copy, other); - charon->sender->send(charon->sender, copy); - } - } - iterator->destroy(iterator); -} - -/** - * Implementation of task_t.process for initiator - */ -static status_t build_i(private_ike_mobike_t *this, message_t *message) -{ - if (message->get_message_id(message) == 1) - { /* only in first IKE_AUTH */ - message->add_notify(message, FALSE, MOBIKE_SUPPORTED, chunk_empty); - build_address_list(this, message); - } - else if (message->get_exchange_type(message) == INFORMATIONAL) - { - host_t *old, *new; - - /* we check if the existing address is still valid */ - old = message->get_source(message); - new = charon->kernel_interface->get_source_addr(charon->kernel_interface, - message->get_destination(message), old); - if (new) - { - if (!new->ip_equals(new, old)) - { - new->set_port(new, old->get_port(old)); - message->set_source(message, new); - } - else - { - new->destroy(new); - } - } - if (this->update) - { - message->add_notify(message, FALSE, UPDATE_SA_ADDRESSES, chunk_empty); - build_cookie(this, message); - update_children(this); - } - if (this->address) - { - build_address_list(this, message); - } - if (this->natd) - { - this->natd->task.build(&this->natd->task, message); - } - } - return NEED_MORE; -} - -/** - * Implementation of task_t.process for responder - */ -static status_t process_r(private_ike_mobike_t *this, message_t *message) -{ - if (message->get_message_id(message) == 1) - { /* only first IKE_AUTH */ - process_payloads(this, message); - } - else if (message->get_exchange_type(message) == INFORMATIONAL) - { - process_payloads(this, message); - if (this->update) - { - host_t *me, *other; - - me = message->get_destination(message); - other = message->get_source(message); - this->ike_sa->set_my_host(this->ike_sa, me->clone(me)); - this->ike_sa->set_other_host(this->ike_sa, other->clone(other)); - } - - if (this->natd) - { - this->natd->task.process(&this->natd->task, message); - } - } - return NEED_MORE; -} - -/** - * Implementation of task_t.build for responder - */ -static status_t build_r(private_ike_mobike_t *this, message_t *message) -{ - if (message->get_exchange_type(message) == IKE_AUTH && - this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED) - { - if (this->ike_sa->supports_extension(this->ike_sa, EXT_MOBIKE)) - { - message->add_notify(message, FALSE, MOBIKE_SUPPORTED, chunk_empty); - build_address_list(this, message); - } - return SUCCESS; - } - else if (message->get_exchange_type(message) == INFORMATIONAL) - { - if (this->natd) - { - this->natd->task.build(&this->natd->task, message); - } - if (this->cookie2.ptr) - { - message->add_notify(message, FALSE, COOKIE2, this->cookie2); - chunk_free(&this->cookie2); - } - if (this->update) - { - update_children(this); - } - return SUCCESS; - } - return NEED_MORE; -} - -/** - * Implementation of task_t.process for initiator - */ -static status_t process_i(private_ike_mobike_t *this, message_t *message) -{ - if (message->get_exchange_type(message) == IKE_AUTH && - this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED) - { - process_payloads(this, message); - return SUCCESS; - } - else if (message->get_exchange_type(message) == INFORMATIONAL) - { - u_int32_t updates = this->ike_sa->get_pending_updates(this->ike_sa) - 1; - this->ike_sa->set_pending_updates(this->ike_sa, updates); - if (updates > 0) - { - /* newer update queued, ignore this one */ - return SUCCESS; - } - if (this->cookie2.ptr) - { /* check cookie if we included one */ - chunk_t cookie2; - - cookie2 = this->cookie2; - this->cookie2 = chunk_empty; - process_payloads(this, message); - if (!chunk_equals(cookie2, this->cookie2)) - { - chunk_free(&cookie2); - DBG1(DBG_IKE, "COOKIE2 mismatch, closing IKE_SA"); - return FAILED; - } - chunk_free(&cookie2); - } - else - { - process_payloads(this, message); - } - if (this->natd) - { - this->natd->task.process(&this->natd->task, message); - if (this->natd->has_mapping_changed(this->natd)) - { - /* force an update if mappings have changed */ - this->update = this->check = TRUE; - DBG1(DBG_IKE, "detected changes in NAT mappings, " - "initiating MOBIKE update"); - } - } - if (this->update) - { - /* update again, as NAT state may have changed */ - update_children(this); - } - if (this->check) - { - host_t *me_new, *me_old, *other_new, *other_old; - - me_new = message->get_destination(message); - other_new = message->get_source(message); - me_old = this->ike_sa->get_my_host(this->ike_sa); - other_old = this->ike_sa->get_other_host(this->ike_sa); - - if (!me_new->equals(me_new, me_old)) - { - this->update = TRUE; - this->ike_sa->set_my_host(this->ike_sa, me_new->clone(me_new)); - } - if (!other_new->equals(other_new, other_old)) - { - this->update = TRUE; - this->ike_sa->set_other_host(this->ike_sa, other_new->clone(other_new)); - } - if (this->update) - { - /* start the update with the same task */ - this->check = FALSE; - this->address = FALSE; - if (this->natd) - { - this->natd->task.destroy(&this->natd->task); - } - this->natd = ike_natd_create(this->ike_sa, this->initiator); - this->ike_sa->set_pending_updates(this->ike_sa, 1); - return NEED_MORE; - } - } - return SUCCESS; - } - return NEED_MORE; -} - -/** - * Implementation of ike_mobike_t.roam. - */ -static void roam(private_ike_mobike_t *this, bool address) -{ - this->check = TRUE; - this->address = address; - this->ike_sa->set_pending_updates(this->ike_sa, - this->ike_sa->get_pending_updates(this->ike_sa) + 1); -} - -/** - * Implementation of ike_mobike_t.dpd - */ -static void dpd(private_ike_mobike_t *this) -{ - if (!this->natd) - { - this->natd = ike_natd_create(this->ike_sa, this->initiator); - } - this->address = FALSE; - this->ike_sa->set_pending_updates(this->ike_sa, - this->ike_sa->get_pending_updates(this->ike_sa) + 1); -} - -/** - * Implementation of ike_mobike_t.is_probing. - */ -static bool is_probing(private_ike_mobike_t *this) -{ - return this->check; -} - -/** - * Implementation of task_t.get_type - */ -static task_type_t get_type(private_ike_mobike_t *this) -{ - return IKE_MOBIKE; -} - -/** - * Implementation of task_t.migrate - */ -static void migrate(private_ike_mobike_t *this, ike_sa_t *ike_sa) -{ - chunk_free(&this->cookie2); - this->ike_sa = ike_sa; - if (this->natd) - { - this->natd->task.migrate(&this->natd->task, ike_sa); - } -} - -/** - * Implementation of task_t.destroy - */ -static void destroy(private_ike_mobike_t *this) -{ - chunk_free(&this->cookie2); - if (this->natd) - { - this->natd->task.destroy(&this->natd->task); - } - free(this); -} - -/* - * Described in header. - */ -ike_mobike_t *ike_mobike_create(ike_sa_t *ike_sa, bool initiator) -{ - private_ike_mobike_t *this = malloc_thing(private_ike_mobike_t); - - this->public.roam = (void(*)(ike_mobike_t*,bool))roam; - this->public.dpd = (void(*)(ike_mobike_t*))dpd; - this->public.transmit = (void(*)(ike_mobike_t*,packet_t*))transmit; - this->public.is_probing = (bool(*)(ike_mobike_t*))is_probing; - 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->update = FALSE; - this->check = FALSE; - this->address = TRUE; - this->cookie2 = chunk_empty; - this->natd = NULL; - - return &this->public; -} - diff --git a/src/charon/sa/tasks/ike_mobike.h b/src/charon/sa/tasks/ike_mobike.h deleted file mode 100644 index 05b2224d1..000000000 --- a/src/charon/sa/tasks/ike_mobike.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2007 Martin Willi - * 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. - */ - -/** - * @defgroup ike_mobike ike_mobike - * @{ @ingroup tasks - */ - -#ifndef IKE_MOBIKE_H_ -#define IKE_MOBIKE_H_ - -typedef struct ike_mobike_t ike_mobike_t; - -#include <library.h> -#include <sa/ike_sa.h> -#include <sa/tasks/task.h> -#include <network/packet.h> - -/** - * Task of type ike_mobike, detects and handles MOBIKE extension. - * - * The MOBIKE extension is defined in RFC4555. It allows to update IKE - * and IPsec tunnel addresses. - * This tasks handles the MOBIKE_SUPPORTED notify exchange to detect MOBIKE - * support, allows the exchange of ADDITIONAL_*_ADDRESS to exchange additional - * endpoints and handles the UPDATE_SA_ADDRESS notify to finally update - * endpoints. - */ -struct ike_mobike_t { - - /** - * Implements the task_t interface - */ - task_t task; - - /** - * Use the task to roam to other addresses. - * - * @param address TRUE to include address list update - */ - void (*roam)(ike_mobike_t *this, bool address); - - /** - * Use the task for a DPD check which detects changes in NAT mappings. - */ - void (*dpd)(ike_mobike_t *this); - - /** - * Transmision hook, called by task manager. - * - * The task manager calls this hook whenever it transmits a packet. It - * allows the mobike task to send the packet on multiple paths to do path - * probing. - * - * @param packet the packet to transmit - */ - void (*transmit)(ike_mobike_t *this, packet_t *packet); - - /** - * Check if this task is probing for routability. - * - * @return TRUE if task is probing - */ - bool (*is_probing)(ike_mobike_t *this); -}; - -/** - * Create a new ike_mobike task. - * - * @param ike_sa IKE_SA this task works for - * @param initiator TRUE if taks is initiated by us - * @return ike_mobike task to handle by the task_manager - */ -ike_mobike_t *ike_mobike_create(ike_sa_t *ike_sa, bool initiator); - -#endif /** IKE_MOBIKE_H_ @}*/ diff --git a/src/charon/sa/tasks/ike_natd.c b/src/charon/sa/tasks/ike_natd.c deleted file mode 100644 index 9121fe2ea..000000000 --- a/src/charon/sa/tasks/ike_natd.c +++ /dev/null @@ -1,487 +0,0 @@ -/* - * Copyright (C) 2006-2007 Martin Willi - * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger - * 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_natd.h" - -#include <string.h> - -#include <daemon.h> -#include <config/peer_cfg.h> -#include <crypto/hashers/hasher.h> -#include <encoding/payloads/notify_payload.h> - - -typedef struct private_ike_natd_t private_ike_natd_t; - -/** - * Private members of a ike_natd_t task. - */ -struct private_ike_natd_t { - - /** - * Public methods and task_t interface. - */ - ike_natd_t public; - - /** - * Assigned IKE_SA. - */ - ike_sa_t *ike_sa; - - /** - * Are we the initiator? - */ - bool initiator; - - /** - * Hasher used to build NAT detection hashes - */ - hasher_t *hasher; - - /** - * Did we process any NAT detection notifys for a source address? - */ - bool src_seen; - - /** - * Did we process any NAT detection notifys for a destination address? - */ - bool dst_seen; - - /** - * Have we found a matching source address NAT hash? - */ - bool src_matched; - - /** - * Have we found a matching destination address NAT hash? - */ - bool dst_matched; - - /** - * whether NAT mappings for our NATed address has changed - */ - bool mapping_changed; -}; - - -/** - * Build NAT detection hash for a host - */ -static chunk_t generate_natd_hash(private_ike_natd_t *this, - ike_sa_id_t *ike_sa_id, host_t *host) -{ - chunk_t natd_chunk, spi_i_chunk, spi_r_chunk, addr_chunk, port_chunk; - chunk_t natd_hash; - u_int64_t spi_i, spi_r; - u_int16_t port; - - /* prepare all required chunks */ - spi_i = ike_sa_id->get_initiator_spi(ike_sa_id); - spi_r = ike_sa_id->get_responder_spi(ike_sa_id); - spi_i_chunk.ptr = (void*)&spi_i; - spi_i_chunk.len = sizeof(spi_i); - spi_r_chunk.ptr = (void*)&spi_r; - spi_r_chunk.len = sizeof(spi_r); - port = htons(host->get_port(host)); - port_chunk.ptr = (void*)&port; - port_chunk.len = sizeof(port); - addr_chunk = host->get_address(host); - - /* natd_hash = SHA1( spi_i | spi_r | address | port ) */ - natd_chunk = chunk_cat("cccc", spi_i_chunk, spi_r_chunk, addr_chunk, port_chunk); - this->hasher->allocate_hash(this->hasher, natd_chunk, &natd_hash); - DBG3(DBG_IKE, "natd_chunk %B", &natd_chunk); - DBG3(DBG_IKE, "natd_hash %B", &natd_hash); - - chunk_free(&natd_chunk); - return natd_hash; -} - -/** - * build a faked NATD payload to enforce UDP encap - */ -static chunk_t generate_natd_hash_faked(private_ike_natd_t *this) -{ - rng_t *rng; - chunk_t chunk; - - rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); - if (!rng) - { - DBG1(DBG_IKE, "unable to get random bytes for NATD fake"); - return chunk_empty; - } - rng->allocate_bytes(rng, HASH_SIZE_SHA1, &chunk); - rng->destroy(rng); - return chunk; -} - -/** - * Build a NAT detection notify payload. - */ -static notify_payload_t *build_natd_payload(private_ike_natd_t *this, - notify_type_t type, host_t *host) -{ - chunk_t hash; - notify_payload_t *notify; - ike_sa_id_t *ike_sa_id; - ike_cfg_t *config; - - ike_sa_id = this->ike_sa->get_id(this->ike_sa); - config = this->ike_sa->get_ike_cfg(this->ike_sa); - if (config->force_encap(config) && type == NAT_DETECTION_SOURCE_IP) - { - hash = generate_natd_hash_faked(this); - } - else - { - hash = generate_natd_hash(this, ike_sa_id, host); - } - notify = notify_payload_create(); - notify->set_notify_type(notify, type); - notify->set_notification_data(notify, hash); - chunk_free(&hash); - - return notify; -} - -/** - * read notifys from message and evaluate them - */ -static void process_payloads(private_ike_natd_t *this, message_t *message) -{ - enumerator_t *enumerator; - payload_t *payload; - notify_payload_t *notify; - chunk_t hash, src_hash, dst_hash; - ike_sa_id_t *ike_sa_id; - host_t *me, *other; - ike_cfg_t *config; - - /* Precompute NAT-D hashes for incoming NAT notify comparison */ - ike_sa_id = message->get_ike_sa_id(message); - me = message->get_destination(message); - other = message->get_source(message); - dst_hash = generate_natd_hash(this, ike_sa_id, me); - src_hash = generate_natd_hash(this, ike_sa_id, other); - - DBG3(DBG_IKE, "precalculated src_hash %B", &src_hash); - DBG3(DBG_IKE, "precalculated dst_hash %B", &dst_hash); - - enumerator = message->create_payload_enumerator(message); - while (enumerator->enumerate(enumerator, &payload)) - { - if (payload->get_type(payload) != NOTIFY) - { - continue; - } - notify = (notify_payload_t*)payload; - switch (notify->get_notify_type(notify)) - { - case NAT_DETECTION_DESTINATION_IP: - { - this->dst_seen = TRUE; - hash = notify->get_notification_data(notify); - if (!this->dst_matched) - { - DBG3(DBG_IKE, "received dst_hash %B", &hash); - if (chunk_equals(hash, dst_hash)) - { - this->dst_matched = TRUE; - } - } - /* RFC4555 says we should also compare against IKE_SA_INIT - * NATD payloads, but this does not work: We are running - * there at port 500, but use 4500 afterwards... */ - if (message->get_exchange_type(message) == INFORMATIONAL && - this->initiator && !this->dst_matched) - { - this->mapping_changed = this->ike_sa->has_mapping_changed( - this->ike_sa, hash); - } - break; - } - case NAT_DETECTION_SOURCE_IP: - { - this->src_seen = TRUE; - if (!this->src_matched) - { - hash = notify->get_notification_data(notify); - DBG3(DBG_IKE, "received src_hash %B", &hash); - if (chunk_equals(hash, src_hash)) - { - this->src_matched = TRUE; - } - } - break; - } - default: - break; - } - } - enumerator->destroy(enumerator); - - chunk_free(&src_hash); - chunk_free(&dst_hash); - - if (this->src_seen && this->dst_seen) - { - this->ike_sa->enable_extension(this->ike_sa, EXT_NATT); - - this->ike_sa->set_condition(this->ike_sa, COND_NAT_HERE, - !this->dst_matched); - this->ike_sa->set_condition(this->ike_sa, COND_NAT_THERE, - !this->src_matched); - config = this->ike_sa->get_ike_cfg(this->ike_sa); - if (this->dst_matched && this->src_matched && - config->force_encap(config)) - { - this->ike_sa->set_condition(this->ike_sa, COND_NAT_FAKE, TRUE); - } - } -} - -/** - * Implementation of task_t.process for initiator - */ -static status_t process_i(private_ike_natd_t *this, message_t *message) -{ - process_payloads(this, message); - - if (message->get_exchange_type(message) == IKE_SA_INIT) - { - peer_cfg_t *peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa); - -#ifdef ME - /* if we are on a mediated connection we have already switched to - * port 4500 and the correct destination port is already configured, - * therefore we must not switch again */ - if (peer_cfg->get_mediated_by(peer_cfg)) - { - return SUCCESS; - } -#endif /* ME */ - - if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY) || -#ifdef ME - /* if we are on a mediation connection we switch to port 4500 even - * if no NAT is detected. */ - peer_cfg->is_mediation(peer_cfg) || -#endif /* ME */ - /* if peer supports NAT-T, we switch to port 4500 even - * if no NAT is detected. MOBIKE requires this. */ - (peer_cfg->use_mobike(peer_cfg) && - this->ike_sa->supports_extension(this->ike_sa, EXT_NATT))) - { - host_t *me, *other; - - /* do not switch if we have a custom port from mobike/NAT */ - me = this->ike_sa->get_my_host(this->ike_sa); - if (me->get_port(me) == IKEV2_UDP_PORT) - { - me->set_port(me, IKEV2_NATT_PORT); - } - other = this->ike_sa->get_other_host(this->ike_sa); - if (other->get_port(other) == IKEV2_UDP_PORT) - { - other->set_port(other, IKEV2_NATT_PORT); - } - } - } - - return SUCCESS; -} - -/** - * Implementation of task_t.process for initiator - */ -static status_t build_i(private_ike_natd_t *this, message_t *message) -{ - notify_payload_t *notify; - enumerator_t *enumerator; - host_t *host; - - if (this->hasher == NULL) - { - DBG1(DBG_IKE, "unable to build NATD payloads, SHA1 not supported"); - return NEED_MORE; - } - - /* destination is always set */ - host = message->get_destination(message); - notify = build_natd_payload(this, NAT_DETECTION_DESTINATION_IP, host); - message->add_payload(message, (payload_t*)notify); - - /* source may be any, we have 3 possibilities to get our source address: - * 1. It is defined in the config => use the one of the IKE_SA - * 2. We do a routing lookup in the kernel interface - * 3. Include all possbile addresses - */ - host = message->get_source(message); - if (!host->is_anyaddr(host)) - { /* 1. */ - notify = build_natd_payload(this, NAT_DETECTION_SOURCE_IP, host); - message->add_payload(message, (payload_t*)notify); - } - else - { - host = charon->kernel_interface->get_source_addr(charon->kernel_interface, - this->ike_sa->get_other_host(this->ike_sa), NULL); - if (host) - { /* 2. */ - host->set_port(host, IKEV2_UDP_PORT); - notify = build_natd_payload(this, NAT_DETECTION_SOURCE_IP, host); - message->add_payload(message, (payload_t*)notify); - host->destroy(host); - } - else - { /* 3. */ - enumerator = charon->kernel_interface->create_address_enumerator( - charon->kernel_interface, FALSE, FALSE); - while (enumerator->enumerate(enumerator, (void**)&host)) - { - /* apply port 500 to host, but work on a copy */ - host = host->clone(host); - host->set_port(host, IKEV2_UDP_PORT); - notify = build_natd_payload(this, NAT_DETECTION_SOURCE_IP, host); - host->destroy(host); - message->add_payload(message, (payload_t*)notify); - } - enumerator->destroy(enumerator); - } - } - return NEED_MORE; -} - -/** - * Implementation of task_t.build for responder - */ -static status_t build_r(private_ike_natd_t *this, message_t *message) -{ - notify_payload_t *notify; - host_t *me, *other; - - /* only add notifies on successfull responses. */ - if (message->get_exchange_type(message) == IKE_SA_INIT && - message->get_payload(message, SECURITY_ASSOCIATION) == NULL) - { - return SUCCESS; - } - - if (this->src_seen && this->dst_seen) - { - if (this->hasher == NULL) - { - DBG1(DBG_IKE, "unable to build NATD payloads, SHA1 not supported"); - return SUCCESS; - } - - /* initiator seems to support NAT detection, add response */ - me = message->get_source(message); - notify = build_natd_payload(this, NAT_DETECTION_SOURCE_IP, me); - message->add_payload(message, (payload_t*)notify); - - other = message->get_destination(message); - notify = build_natd_payload(this, NAT_DETECTION_DESTINATION_IP, other); - message->add_payload(message, (payload_t*)notify); - } - return SUCCESS; -} - -/** - * Implementation of task_t.process for responder - */ -static status_t process_r(private_ike_natd_t *this, message_t *message) -{ - process_payloads(this, message); - - return NEED_MORE; -} - -/** - * Implementation of task_t.get_type - */ -static task_type_t get_type(private_ike_natd_t *this) -{ - return IKE_NATD; -} - -/** - * Implementation of task_t.migrate - */ -static void migrate(private_ike_natd_t *this, ike_sa_t *ike_sa) -{ - this->ike_sa = ike_sa; - this->src_seen = FALSE; - this->dst_seen = FALSE; - this->src_matched = FALSE; - this->dst_matched = FALSE; - this->mapping_changed = FALSE; -} - -/** - * Implementation of ike_natd_t.has_mapping_changed - */ -static bool has_mapping_changed(private_ike_natd_t *this) -{ - return this->mapping_changed; -} - -/** - * Implementation of task_t.destroy - */ -static void destroy(private_ike_natd_t *this) -{ - DESTROY_IF(this->hasher); - free(this); -} - -/* - * Described in header. - */ -ike_natd_t *ike_natd_create(ike_sa_t *ike_sa, bool initiator) -{ - private_ike_natd_t *this = malloc_thing(private_ike_natd_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->public.has_mapping_changed = (bool(*)(ike_natd_t*))has_mapping_changed; - - this->ike_sa = ike_sa; - this->initiator = initiator; - this->hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); - this->src_seen = FALSE; - this->dst_seen = FALSE; - this->src_matched = FALSE; - this->dst_matched = FALSE; - this->mapping_changed = FALSE; - - return &this->public; -} diff --git a/src/charon/sa/tasks/ike_natd.h b/src/charon/sa/tasks/ike_natd.h deleted file mode 100644 index 97b652ead..000000000 --- a/src/charon/sa/tasks/ike_natd.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2007 Martin Willi - * 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. - */ - -/** - * @defgroup ike_natd ike_natd - * @{ @ingroup tasks - */ - -#ifndef IKE_NATD_H_ -#define IKE_NATD_H_ - -typedef struct ike_natd_t ike_natd_t; - -#include <library.h> -#include <sa/ike_sa.h> -#include <sa/tasks/task.h> - -/** - * Task of type ike_natd, detects NAT situation in IKE_SA_INIT exchange. - */ -struct ike_natd_t { - - /** - * Implements the task_t interface - */ - task_t task; - - /** - * Check if the NAT mapping has changed for our address. - * - * MOBIKE uses NAT payloads in DPD to detect changes in the NAT mappings. - * - * @return TRUE if mappings have changed - */ - bool (*has_mapping_changed)(ike_natd_t *this); -}; - -/** - * Create a new ike_natd task. - * - * @param ike_sa IKE_SA this task works for - * @param initiator TRUE if thask is the original initator - * @return ike_natd task to handle by the task_manager - */ -ike_natd_t *ike_natd_create(ike_sa_t *ike_sa, bool initiator); - -#endif /** IKE_NATD_H_ @}*/ diff --git a/src/charon/sa/tasks/ike_reauth.c b/src/charon/sa/tasks/ike_reauth.c deleted file mode 100644 index ac89c358b..000000000 --- a/src/charon/sa/tasks/ike_reauth.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright (C) 2006-2008 Martin Willi - * 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_reauth.h" - -#include <daemon.h> -#include <sa/tasks/ike_delete.h> - - -typedef struct private_ike_reauth_t private_ike_reauth_t; - -/** - * Private members of a ike_reauth_t task. - */ -struct private_ike_reauth_t { - - /** - * Public methods and task_t interface. - */ - ike_reauth_t public; - - /** - * Assigned IKE_SA. - */ - ike_sa_t *ike_sa; - - /** - * reused ike_delete task - */ - ike_delete_t *ike_delete; -}; - -/** - * Implementation of task_t.build for initiator - */ -static status_t build_i(private_ike_reauth_t *this, message_t *message) -{ - return this->ike_delete->task.build(&this->ike_delete->task, message); -} - -/** - * Implementation of task_t.process for initiator - */ -static status_t process_i(private_ike_reauth_t *this, message_t *message) -{ - ike_sa_t *new; - host_t *host; - iterator_t *iterator; - child_sa_t *child_sa; - peer_cfg_t *peer_cfg; - - /* process delete response first */ - this->ike_delete->task.process(&this->ike_delete->task, message); - - peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa); - - /* reauthenticate only if we have children */ - iterator = this->ike_sa->create_child_sa_iterator(this->ike_sa); - if (iterator->get_count(iterator) == 0 -#ifdef ME - /* we allow peers to reauth mediation connections (without children) */ - && !peer_cfg->is_mediation(peer_cfg) -#endif /* ME */ - ) - { - DBG1(DBG_IKE, "unable to reauthenticate IKE_SA, no CHILD_SA to recreate"); - iterator->destroy(iterator); - return FAILED; - } - - new = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager, TRUE); - - new->set_peer_cfg(new, peer_cfg); - host = this->ike_sa->get_other_host(this->ike_sa); - new->set_other_host(new, host->clone(host)); - host = this->ike_sa->get_my_host(this->ike_sa); - new->set_my_host(new, host->clone(host)); - /* if we already have a virtual IP, we reuse it */ - host = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE); - if (host) - { - new->set_virtual_ip(new, TRUE, host); - } - -#ifdef ME - /* we initiate the new IKE_SA of the mediation connection without CHILD_SA */ - if (peer_cfg->is_mediation(peer_cfg)) - { - if (new->initiate(new, NULL, 0, NULL, NULL) == DESTROY_ME) - { - charon->ike_sa_manager->checkin_and_destroy( - charon->ike_sa_manager, new); - /* set threads active IKE_SA after checkin */ - charon->bus->set_sa(charon->bus, this->ike_sa); - DBG1(DBG_IKE, "reauthenticating IKE_SA failed"); - return FAILED; - } - } -#endif /* ME */ - - while (iterator->iterate(iterator, (void**)&child_sa)) - { - switch (child_sa->get_state(child_sa)) - { - case CHILD_ROUTED: - { - /* move routed child directly */ - iterator->remove(iterator); - new->add_child_sa(new, child_sa); - break; - } - default: - { - /* initiate/queue all child SAs */ - child_cfg_t *child_cfg = child_sa->get_config(child_sa); - child_cfg->get_ref(child_cfg); - if (new->initiate(new, child_cfg, 0, NULL, NULL) == DESTROY_ME) - { - iterator->destroy(iterator); - charon->ike_sa_manager->checkin_and_destroy( - charon->ike_sa_manager, new); - /* set threads active IKE_SA after checkin */ - charon->bus->set_sa(charon->bus, this->ike_sa); - DBG1(DBG_IKE, "reauthenticating IKE_SA failed"); - return FAILED; - } - break; - } - } - } - iterator->destroy(iterator); - charon->ike_sa_manager->checkin(charon->ike_sa_manager, new); - /* set threads active IKE_SA after checkin */ - charon->bus->set_sa(charon->bus, this->ike_sa); - - /* we always return failed to delete the obsolete IKE_SA */ - return FAILED; -} - -/** - * Implementation of task_t.get_type - */ -static task_type_t get_type(private_ike_reauth_t *this) -{ - return IKE_REAUTH; -} - -/** - * Implementation of task_t.migrate - */ -static void migrate(private_ike_reauth_t *this, ike_sa_t *ike_sa) -{ - this->ike_delete->task.migrate(&this->ike_delete->task, ike_sa); - this->ike_sa = ike_sa; -} - -/** - * Implementation of task_t.destroy - */ -static void destroy(private_ike_reauth_t *this) -{ - this->ike_delete->task.destroy(&this->ike_delete->task); - free(this); -} - -/* - * Described in header. - */ -ike_reauth_t *ike_reauth_create(ike_sa_t *ike_sa) -{ - private_ike_reauth_t *this = malloc_thing(private_ike_reauth_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->public.task.build = (status_t(*)(task_t*,message_t*))build_i; - this->public.task.process = (status_t(*)(task_t*,message_t*))process_i; - - this->ike_sa = ike_sa; - this->ike_delete = ike_delete_create(ike_sa, TRUE); - - return &this->public; -} - diff --git a/src/charon/sa/tasks/ike_reauth.h b/src/charon/sa/tasks/ike_reauth.h deleted file mode 100644 index 5e97b719c..000000000 --- a/src/charon/sa/tasks/ike_reauth.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2007 Martin Willi - * 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. - */ - -/** - * @defgroup ike_reauth ike_reauth - * @{ @ingroup tasks - */ - -#ifndef IKE_REAUTH_H_ -#define IKE_REAUTH_H_ - -typedef struct ike_reauth_t ike_reauth_t; - -#include <library.h> -#include <sa/ike_sa.h> -#include <sa/tasks/task.h> - -/** - * Task of type ike_reauth, reestablishes an IKE_SA. - */ -struct ike_reauth_t { - - /** - * Implements the task_t interface - */ - task_t task; -}; - -/** - * Create a new ike_reauth task. - * - * This task is initiator only. - * - * @param ike_sa IKE_SA this task works for - * @return ike_reauth task to handle by the task_manager - */ -ike_reauth_t *ike_reauth_create(ike_sa_t *ike_sa); - -#endif /** IKE_REAUTH_H_ @}*/ diff --git a/src/charon/sa/tasks/ike_rekey.c b/src/charon/sa/tasks/ike_rekey.c deleted file mode 100644 index a2275e796..000000000 --- a/src/charon/sa/tasks/ike_rekey.c +++ /dev/null @@ -1,409 +0,0 @@ -/* - * Copyright (C) 2005-2008 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_rekey.h" - -#include <daemon.h> -#include <encoding/payloads/notify_payload.h> -#include <sa/tasks/ike_init.h> -#include <sa/tasks/ike_delete.h> -#include <processing/jobs/delete_ike_sa_job.h> -#include <processing/jobs/rekey_ike_sa_job.h> - - -typedef struct private_ike_rekey_t private_ike_rekey_t; - -/** - * Private members of a ike_rekey_t task. - */ -struct private_ike_rekey_t { - - /** - * Public methods and task_t interface. - */ - ike_rekey_t public; - - /** - * Assigned IKE_SA. - */ - ike_sa_t *ike_sa; - - /** - * New IKE_SA which replaces the current one - */ - ike_sa_t *new_sa; - - /** - * Are we the initiator? - */ - bool initiator; - - /** - * the IKE_INIT task which is reused to simplify rekeying - */ - ike_init_t *ike_init; - - /** - * IKE_DELETE task to delete the old IKE_SA after rekeying was successful - */ - ike_delete_t *ike_delete; - - /** - * colliding task detected by the task manager - */ - task_t *collision; -}; - -/** - * Implementation of task_t.build for initiator, after rekeying - */ -static status_t build_i_delete(private_ike_rekey_t *this, message_t *message) -{ - /* update exchange type to INFORMATIONAL for the delete */ - message->set_exchange_type(message, INFORMATIONAL); - - return this->ike_delete->task.build(&this->ike_delete->task, message); -} - -/** - * Implementation of task_t.process for initiator, after rekeying - */ -static status_t process_i_delete(private_ike_rekey_t *this, message_t *message) -{ - return this->ike_delete->task.process(&this->ike_delete->task, message); -} - -/** - * Implementation of task_t.build for initiator - */ -static status_t build_i(private_ike_rekey_t *this, message_t *message) -{ - peer_cfg_t *peer_cfg; - host_t *other_host; - - /* create new SA only on first try */ - if (this->new_sa == NULL) - { - this->new_sa = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager, - TRUE); - - peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa); - other_host = this->ike_sa->get_other_host(this->ike_sa); - this->new_sa->set_peer_cfg(this->new_sa, peer_cfg); - this->new_sa->set_other_host(this->new_sa, other_host->clone(other_host)); - this->ike_init = ike_init_create(this->new_sa, TRUE, this->ike_sa); - this->ike_sa->set_state(this->ike_sa, IKE_REKEYING); - } - this->ike_init->task.build(&this->ike_init->task, message); - - return NEED_MORE; -} - -/** - * Implementation of task_t.process for responder - */ -static status_t process_r(private_ike_rekey_t *this, message_t *message) -{ - peer_cfg_t *peer_cfg; - iterator_t *iterator; - child_sa_t *child_sa; - - if (this->ike_sa->get_state(this->ike_sa) == IKE_DELETING) - { - DBG1(DBG_IKE, "peer initiated rekeying, but we are deleting"); - return NEED_MORE; - } - - iterator = this->ike_sa->create_child_sa_iterator(this->ike_sa); - while (iterator->iterate(iterator, (void**)&child_sa)) - { - switch (child_sa->get_state(child_sa)) - { - case CHILD_CREATED: - case CHILD_REKEYING: - case CHILD_DELETING: - /* we do not allow rekeying while we have children in-progress */ - DBG1(DBG_IKE, "peer initiated rekeying, but a child is half-open"); - iterator->destroy(iterator); - return NEED_MORE; - default: - break; - } - } - iterator->destroy(iterator); - - this->new_sa = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager, - FALSE); - - peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa); - this->new_sa->set_peer_cfg(this->new_sa, peer_cfg); - this->ike_init = ike_init_create(this->new_sa, FALSE, this->ike_sa); - this->ike_init->task.process(&this->ike_init->task, message); - - return NEED_MORE; -} - -/** - * Implementation of task_t.build for responder - */ -static status_t build_r(private_ike_rekey_t *this, message_t *message) -{ - if (this->new_sa == NULL) - { - /* IKE_SA/a CHILD_SA is in an inacceptable state, deny rekeying */ - message->add_notify(message, TRUE, NO_PROPOSAL_CHOSEN, chunk_empty); - return SUCCESS; - } - - if (this->ike_init->task.build(&this->ike_init->task, message) == FAILED) - { - return SUCCESS; - } - - this->ike_sa->set_state(this->ike_sa, IKE_REKEYING); - this->new_sa->set_state(this->new_sa, IKE_ESTABLISHED); - DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%Y]...%H[%Y]", - this->new_sa->get_name(this->new_sa), - this->new_sa->get_unique_id(this->new_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)); - - return SUCCESS; -} - -/** - * Implementation of task_t.process for initiator - */ -static status_t process_i(private_ike_rekey_t *this, message_t *message) -{ - if (message->get_notify(message, NO_ADDITIONAL_SAS)) - { - DBG1(DBG_IKE, "peer seems to not support IKE rekeying, " - "starting reauthentication"); - this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED); - charon->processor->queue_job(charon->processor, - (job_t*)rekey_ike_sa_job_create( - this->ike_sa->get_id(this->ike_sa), TRUE)); - return SUCCESS; - } - - switch (this->ike_init->task.process(&this->ike_init->task, message)) - { - case FAILED: - /* rekeying failed, fallback to old SA */ - if (!(this->collision && ( - this->collision->get_type(this->collision) == IKE_DELETE || - this->collision->get_type(this->collision) == IKE_REAUTH))) - { - job_t *job; - u_int32_t retry = RETRY_INTERVAL - (random() % RETRY_JITTER); - job = (job_t*)rekey_ike_sa_job_create( - this->ike_sa->get_id(this->ike_sa), FALSE); - DBG1(DBG_IKE, "IKE_SA rekeying failed, " - "trying again in %d seconds", retry); - this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED); - charon->scheduler->schedule_job(charon->scheduler, job, retry); - } - return SUCCESS; - case NEED_MORE: - /* bad dh group, try again */ - this->ike_init->task.migrate(&this->ike_init->task, this->new_sa); - return NEED_MORE; - default: - break; - } - - this->new_sa->set_state(this->new_sa, IKE_ESTABLISHED); - DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%Y]...%H[%Y]", - this->new_sa->get_name(this->new_sa), - this->new_sa->get_unique_id(this->new_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)); - - /* check for collisions */ - if (this->collision && - this->collision->get_type(this->collision) == IKE_REKEY) - { - chunk_t this_nonce, other_nonce; - host_t *host; - private_ike_rekey_t *other = (private_ike_rekey_t*)this->collision; - - this_nonce = this->ike_init->get_lower_nonce(this->ike_init); - other_nonce = other->ike_init->get_lower_nonce(other->ike_init); - - /* if we have the lower nonce, delete rekeyed SA. If not, delete - * the redundant. */ - if (memcmp(this_nonce.ptr, other_nonce.ptr, - min(this_nonce.len, other_nonce.len)) < 0) - { - /* peer should delete this SA. Add a timeout just in case. */ - job_t *job = (job_t*)delete_ike_sa_job_create( - other->new_sa->get_id(other->new_sa), TRUE); - charon->scheduler->schedule_job(charon->scheduler, job, 10); - DBG1(DBG_IKE, "IKE_SA rekey collision won, deleting rekeyed IKE_SA"); - charon->ike_sa_manager->checkin(charon->ike_sa_manager, other->new_sa); - other->new_sa = NULL; - } - else - { - DBG1(DBG_IKE, "IKE_SA rekey collision lost, deleting redundant IKE_SA"); - /* apply host for a proper delete */ - host = this->ike_sa->get_my_host(this->ike_sa); - this->new_sa->set_my_host(this->new_sa, host->clone(host)); - host = this->ike_sa->get_other_host(this->ike_sa); - this->new_sa->set_other_host(this->new_sa, host->clone(host)); - this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED); - if (this->new_sa->delete(this->new_sa) == DESTROY_ME) - { - charon->ike_sa_manager->checkin_and_destroy( - charon->ike_sa_manager, this->new_sa); - } - else - { - charon->ike_sa_manager->checkin( - charon->ike_sa_manager, this->new_sa); - } - /* set threads active IKE_SA after checkin */ - charon->bus->set_sa(charon->bus, this->ike_sa); - /* inherit to other->new_sa in destroy() */ - this->new_sa = other->new_sa; - other->new_sa = NULL; - return SUCCESS; - } - /* set threads active IKE_SA after checkin */ - charon->bus->set_sa(charon->bus, this->ike_sa); - } - - /* rekeying successful, delete the IKE_SA using a subtask */ - this->ike_delete = ike_delete_create(this->ike_sa, TRUE); - this->public.task.build = (status_t(*)(task_t*,message_t*))build_i_delete; - this->public.task.process = (status_t(*)(task_t*,message_t*))process_i_delete; - - return NEED_MORE; -} - -/** - * Implementation of task_t.get_type - */ -static task_type_t get_type(private_ike_rekey_t *this) -{ - return IKE_REKEY; -} - -static void collide(private_ike_rekey_t* this, task_t *other) -{ - DESTROY_IF(this->collision); - this->collision = other; -} - -/** - * Implementation of task_t.migrate - */ -static void migrate(private_ike_rekey_t *this, ike_sa_t *ike_sa) -{ - if (this->ike_init) - { - this->ike_init->task.destroy(&this->ike_init->task); - } - if (this->ike_delete) - { - this->ike_delete->task.destroy(&this->ike_delete->task); - } - if (this->new_sa) - { - charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, - this->new_sa); - /* set threads active IKE_SA after checkin */ - charon->bus->set_sa(charon->bus, this->ike_sa); - } - DESTROY_IF(this->collision); - - this->collision = NULL; - this->ike_sa = ike_sa; - this->new_sa = NULL; - this->ike_init = NULL; - this->ike_delete = NULL; -} - -/** - * Implementation of task_t.destroy - */ -static void destroy(private_ike_rekey_t *this) -{ - if (this->new_sa) - { - if (this->new_sa->get_state(this->new_sa) == IKE_ESTABLISHED && - this->new_sa->inherit(this->new_sa, this->ike_sa) != DESTROY_ME) - { - /* invoke hook if rekeying was successful */ - charon->bus->ike_rekey(charon->bus, this->ike_sa, this->new_sa); - charon->ike_sa_manager->checkin(charon->ike_sa_manager, this->new_sa); - } - else - { - charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, - this->new_sa); - } - /* set threads active IKE_SA after checkin */ - charon->bus->set_sa(charon->bus, this->ike_sa); - } - if (this->ike_init) - { - this->ike_init->task.destroy(&this->ike_init->task); - } - if (this->ike_delete) - { - this->ike_delete->task.destroy(&this->ike_delete->task); - } - DESTROY_IF(this->collision); - free(this); -} - -/* - * Described in header. - */ -ike_rekey_t *ike_rekey_create(ike_sa_t *ike_sa, bool initiator) -{ - private_ike_rekey_t *this = malloc_thing(private_ike_rekey_t); - - this->public.collide = (void(*)(ike_rekey_t*,task_t*))collide; - 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->new_sa = NULL; - this->ike_init = NULL; - this->ike_delete = NULL; - this->initiator = initiator; - this->collision = NULL; - - return &this->public; -} diff --git a/src/charon/sa/tasks/ike_rekey.h b/src/charon/sa/tasks/ike_rekey.h deleted file mode 100644 index 1c9550768..000000000 --- a/src/charon/sa/tasks/ike_rekey.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2007 Martin Willi - * 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. - */ - -/** - * @defgroup ike_rekey ike_rekey - * @{ @ingroup tasks - */ - -#ifndef IKE_REKEY_H_ -#define IKE_REKEY_H_ - -typedef struct ike_rekey_t ike_rekey_t; - -#include <library.h> -#include <sa/ike_sa.h> -#include <sa/tasks/task.h> - -/** - * Task of type IKE_REKEY, rekey an established IKE_SA. - */ -struct ike_rekey_t { - - /** - * Implements the task_t interface - */ - task_t task; - - /** - * Register a rekeying task which collides with this one. - * - * If two peers initiate rekeying at the same time, the collision must - * be handled gracefully. The task manager is aware of what exchanges - * are going on and notifies the outgoing task by passing the incoming. - * - * @param other incoming task - */ - void (*collide)(ike_rekey_t* this, task_t *other); -}; - -/** - * Create a new IKE_REKEY task. - * - * @param ike_sa IKE_SA this task works for - * @param initiator TRUE for initiator, FALSE for responder - * @return IKE_REKEY task to handle by the task_manager - */ -ike_rekey_t *ike_rekey_create(ike_sa_t *ike_sa, bool initiator); - -#endif /** IKE_REKEY_H_ @}*/ diff --git a/src/charon/sa/tasks/ike_vendor.c b/src/charon/sa/tasks/ike_vendor.c deleted file mode 100644 index 7c435b6d1..000000000 --- a/src/charon/sa/tasks/ike_vendor.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (C) 2009 Martin Willi - * 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_vendor.h" - -#include <daemon.h> -#include <encoding/payloads/vendor_id_payload.h> - -typedef struct private_ike_vendor_t private_ike_vendor_t; - -/** - * Private data of an ike_vendor_t object. - */ -struct private_ike_vendor_t { - - /** - * Public ike_vendor_t interface. - */ - ike_vendor_t public; - - /** - * Associated IKE_SA - */ - ike_sa_t *ike_sa; - - /** - * Are we the inititator of this task - */ - bool initiator; -}; - -/** - * strongSwan specific vendor ID without version, MD5("strongSwan") - */ -static chunk_t strongswan_vid = chunk_from_chars( - 0x88,0x2f,0xe5,0x6d,0x6f,0xd2,0x0d,0xbc, - 0x22,0x51,0x61,0x3b,0x2e,0xbe,0x5b,0xeb -); - -METHOD(task_t, build, status_t, - private_ike_vendor_t *this, message_t *message) -{ - if (lib->settings->get_bool(lib->settings, - "charon.send_vendor_id", FALSE)) - { - vendor_id_payload_t *vid; - - vid = vendor_id_payload_create_data(chunk_clone(strongswan_vid)); - message->add_payload(message, &vid->payload_interface); - } - - return this->initiator ? NEED_MORE : SUCCESS; -} - -METHOD(task_t, process, status_t, - private_ike_vendor_t *this, message_t *message) -{ - enumerator_t *enumerator; - payload_t *payload; - - enumerator = message->create_payload_enumerator(message); - while (enumerator->enumerate(enumerator, &payload)) - { - if (payload->get_type(payload) == VENDOR_ID) - { - vendor_id_payload_t *vid; - chunk_t data; - - vid = (vendor_id_payload_t*)payload; - data = vid->get_data(vid); - - if (chunk_equals(data, strongswan_vid)) - { - DBG1(DBG_IKE, "received strongSwan vendor id"); - this->ike_sa->enable_extension(this->ike_sa, EXT_STRONGSWAN); - } - else - { - DBG1(DBG_ENC, "received unknown vendor id: %#B", &data); - } - } - } - enumerator->destroy(enumerator); - - return this->initiator ? SUCCESS : NEED_MORE; -} - -METHOD(task_t, migrate, void, - private_ike_vendor_t *this, ike_sa_t *ike_sa) -{ - this->ike_sa = ike_sa; -} - -METHOD(task_t, get_type, task_type_t, - private_ike_vendor_t *this) -{ - return IKE_VENDOR; -} - -METHOD(task_t, destroy, void, - private_ike_vendor_t *this) -{ - free(this); -} - -/** - * See header - */ -ike_vendor_t *ike_vendor_create(ike_sa_t *ike_sa, bool initiator) -{ - private_ike_vendor_t *this; - - INIT(this, - .public.task = { - .build = _build, - .process = _process, - .migrate = _migrate, - .get_type = _get_type, - .destroy = _destroy, - }, - .initiator = initiator, - .ike_sa = ike_sa, - ); - - return &this->public; -} - diff --git a/src/charon/sa/tasks/ike_vendor.h b/src/charon/sa/tasks/ike_vendor.h deleted file mode 100644 index dcdd37424..000000000 --- a/src/charon/sa/tasks/ike_vendor.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2009 Martin Willi - * 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. - */ - -/** - * @defgroup ike_vendor ike_vendor - * @{ @ingroup tasks - */ - -#ifndef IKE_VENDOR_H_ -#define IKE_VENDOR_H_ - -typedef struct ike_vendor_t ike_vendor_t; - -#include <library.h> -#include <sa/ike_sa.h> -#include <sa/tasks/task.h> - -/** - * Vendor ID processing task. - */ -struct ike_vendor_t { - - /** - * Implements task interface. - */ - task_t task; -}; - -/** - * Create a ike_vendor instance. - * - * @param ike_sa IKE_SA this task works for - * @param initiator TRUE if thask is the original initator - */ -ike_vendor_t *ike_vendor_create(ike_sa_t *ike_sa, bool initiator); - -#endif /** IKE_VENDOR_H_ @}*/ diff --git a/src/charon/sa/tasks/task.c b/src/charon/sa/tasks/task.c deleted file mode 100644 index 0d7383141..000000000 --- a/src/charon/sa/tasks/task.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2007 Tobias Brunner - * Copyright (C) 2007 Martin Willi - * 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 "task.h" - -#ifdef ME -ENUM(task_type_names, IKE_INIT, CHILD_REKEY, - "IKE_INIT", - "IKE_NATD", - "IKE_MOBIKE", - "IKE_AUTHENTICATE", - "IKE_AUTH_LIFETIME", - "IKE_CERT_PRE", - "IKE_CERT_POST", - "IKE_CONFIG", - "IKE_REKEY", - "IKE_REAUTH", - "IKE_DELETE", - "IKE_DPD", - "IKE_VENDOR", - "IKE_ME", - "CHILD_CREATE", - "CHILD_DELETE", - "CHILD_REKEY", -); -#else -ENUM(task_type_names, IKE_INIT, CHILD_REKEY, - "IKE_INIT", - "IKE_NATD", - "IKE_MOBIKE", - "IKE_AUTHENTICATE", - "IKE_AUTH_LIFETIME", - "IKE_CERT_PRE", - "IKE_CERT_POST", - "IKE_CONFIG", - "IKE_REKEY", - "IKE_REAUTH", - "IKE_DELETE", - "IKE_DPD", - "IKE_VENDOR", - "CHILD_CREATE", - "CHILD_DELETE", - "CHILD_REKEY", -); -#endif /* ME */ diff --git a/src/charon/sa/tasks/task.h b/src/charon/sa/tasks/task.h deleted file mode 100644 index 4468f2ebe..000000000 --- a/src/charon/sa/tasks/task.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (C) 2007 Tobias Brunner - * Copyright (C) 2006 Martin Willi - * 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. - */ - -/** - * @defgroup task task - * @{ @ingroup tasks - */ - -#ifndef TASK_H_ -#define TASK_H_ - -typedef enum task_type_t task_type_t; -typedef struct task_t task_t; - -#include <library.h> -#include <sa/ike_sa.h> -#include <encoding/message.h> - -/** - * Different kinds of tasks. - */ -enum task_type_t { - /** establish an unauthenticated IKE_SA */ - IKE_INIT, - /** detect NAT situation */ - IKE_NATD, - /** handle MOBIKE stuff */ - IKE_MOBIKE, - /** authenticate the initiated IKE_SA */ - IKE_AUTHENTICATE, - /** AUTH_LIFETIME negotiation, RFC4478 */ - IKE_AUTH_LIFETIME, - /** certificate processing before authentication (certreqs, cert parsing) */ - IKE_CERT_PRE, - /** certificate processing after authentication (certs payload generation) */ - IKE_CERT_POST, - /** Configuration payloads, virtual IP and such */ - IKE_CONFIG, - /** rekey an IKE_SA */ - IKE_REKEY, - /** reestablish a complete IKE_SA */ - IKE_REAUTH, - /** delete an IKE_SA */ - IKE_DELETE, - /** liveness check */ - IKE_DPD, - /** Vendor ID processing */ - IKE_VENDOR, -#ifdef ME - /** handle ME stuff */ - IKE_ME, -#endif /* ME */ - /** establish a CHILD_SA within an IKE_SA */ - CHILD_CREATE, - /** delete an established CHILD_SA */ - CHILD_DELETE, - /** rekey an CHILD_SA */ - CHILD_REKEY, -}; - -/** - * enum names for task_type_t. - */ -extern enum_name_t *task_type_names; - -/** - * Interface for a task, an operation handled within exchanges. - * - * A task is an elemantary operation. It may be handled by a single or by - * multiple exchanges. An exchange may even complete multiple tasks. - * A task has a build() and an process() operation. The build() operation - * creates payloads and adds it to the message. The process() operation - * inspects a message and handles its payloads. An initiator of an exchange - * first calls build() to build the request, and processes the response message - * with the process() method. - * A responder does the opposite; it calls process() first to handle an incoming - * request and secondly calls build() to build an appropriate response. - * Both methods return either SUCCESS, NEED_MORE or FAILED. A SUCCESS indicates - * that the task completed, even when the task completed unsuccesfully. The - * manager then removes the task from the list. A NEED_MORE is returned when - * the task needs further build()/process() calls to complete, the manager - * leaves the taks in the queue. A returned FAILED indicates a critical failure. - * The manager closes the IKE_SA whenever a task returns FAILED. - */ -struct task_t { - - /** - * Build a request or response message for this task. - * - * @param message message to add payloads to - * @return - * - FAILED if a critical error occured - * - DESTROY_ME if IKE_SA has been properly deleted - * - NEED_MORE if another call to build/process needed - * - SUCCESS if task completed - */ - status_t (*build) (task_t *this, message_t *message); - - /** - * Process a request or response message for this task. - * - * @param message message to read payloads from - * @return - * - FAILED if a critical error occured - * - DESTROY_ME if IKE_SA has been properly deleted - * - NEED_MORE if another call to build/process needed - * - SUCCESS if task completed - */ - status_t (*process) (task_t *this, message_t *message); - - /** - * Get the type of the task implementation. - */ - task_type_t (*get_type) (task_t *this); - - /** - * Migrate a task to a new IKE_SA. - * - * After migrating a task, it goes back to a state where it can be - * used again to initate an exchange. This is useful when a task - * has to get migrated to a new IKE_SA. - * A special usage is when a INVALID_KE_PAYLOAD is received. A call - * to reset resets the task, but uses another DH group for the next - * try. - * The ike_sa is the new IKE_SA this task belongs to and operates on. - * - * @param ike_sa new IKE_SA this task works for - */ - void (*migrate) (task_t *this, ike_sa_t *ike_sa); - - /** - * Destroys a task_t object. - */ - void (*destroy) (task_t *this); -}; - -#endif /** TASK_H_ @}*/ |