Annotation of embedaddon/strongswan/src/libcharon/sa/ike_sa.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2006-2019 Tobias Brunner
! 3: * Copyright (C) 2006 Daniel Roethlisberger
! 4: * Copyright (C) 2005-2009 Martin Willi
! 5: * Copyright (C) 2005 Jan Hutter
! 6: * HSR Hochschule fuer Technik Rapperswil
! 7: *
! 8: * This program is free software; you can redistribute it and/or modify it
! 9: * under the terms of the GNU General Public License as published by the
! 10: * Free Software Foundation; either version 2 of the License, or (at your
! 11: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
! 12: *
! 13: * This program is distributed in the hope that it will be useful, but
! 14: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
! 15: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
! 16: * for more details.
! 17: */
! 18:
! 19: /*
! 20: * Copyright (c) 2014 Volker RĂ¼melin
! 21: *
! 22: * Permission is hereby granted, free of charge, to any person obtaining a copy
! 23: * of this software and associated documentation files (the "Software"), to deal
! 24: * in the Software without restriction, including without limitation the rights
! 25: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
! 26: * copies of the Software, and to permit persons to whom the Software is
! 27: * furnished to do so, subject to the following conditions:
! 28: *
! 29: * The above copyright notice and this permission notice shall be included in
! 30: * all copies or substantial portions of the Software.
! 31: *
! 32: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
! 33: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
! 34: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
! 35: * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
! 36: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
! 37: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
! 38: * THE SOFTWARE.
! 39: */
! 40:
! 41: #include <string.h>
! 42: #include <sys/stat.h>
! 43: #include <errno.h>
! 44: #include <time.h>
! 45:
! 46: #include "ike_sa.h"
! 47:
! 48: #include <library.h>
! 49: #include <daemon.h>
! 50: #include <collections/array.h>
! 51: #include <utils/lexparser.h>
! 52: #include <processing/jobs/retransmit_job.h>
! 53: #include <processing/jobs/delete_ike_sa_job.h>
! 54: #include <processing/jobs/send_dpd_job.h>
! 55: #include <processing/jobs/send_keepalive_job.h>
! 56: #include <processing/jobs/rekey_ike_sa_job.h>
! 57: #include <processing/jobs/retry_initiate_job.h>
! 58: #include <sa/ikev2/tasks/ike_auth_lifetime.h>
! 59: #include <sa/ikev2/tasks/ike_reauth_complete.h>
! 60: #include <sa/ikev2/tasks/ike_redirect.h>
! 61: #include <credentials/sets/auth_cfg_wrapper.h>
! 62:
! 63: #ifdef ME
! 64: #include <sa/ikev2/tasks/ike_me.h>
! 65: #include <processing/jobs/initiate_mediation_job.h>
! 66: #endif
! 67:
! 68: ENUM(ike_sa_state_names, IKE_CREATED, IKE_DESTROYING,
! 69: "CREATED",
! 70: "CONNECTING",
! 71: "ESTABLISHED",
! 72: "PASSIVE",
! 73: "REKEYING",
! 74: "REKEYED",
! 75: "DELETING",
! 76: "DESTROYING",
! 77: );
! 78:
! 79: typedef struct private_ike_sa_t private_ike_sa_t;
! 80: typedef struct attribute_entry_t attribute_entry_t;
! 81:
! 82: /**
! 83: * Private data of an ike_sa_t object.
! 84: */
! 85: struct private_ike_sa_t {
! 86:
! 87: /**
! 88: * Public members
! 89: */
! 90: ike_sa_t public;
! 91:
! 92: /**
! 93: * Identifier for the current IKE_SA.
! 94: */
! 95: ike_sa_id_t *ike_sa_id;
! 96:
! 97: /**
! 98: * IKE version of this SA.
! 99: */
! 100: ike_version_t version;
! 101:
! 102: /**
! 103: * unique numerical ID for this IKE_SA.
! 104: */
! 105: uint32_t unique_id;
! 106:
! 107: /**
! 108: * Current state of the IKE_SA
! 109: */
! 110: ike_sa_state_t state;
! 111:
! 112: /**
! 113: * IKE configuration used to set up this IKE_SA
! 114: */
! 115: ike_cfg_t *ike_cfg;
! 116:
! 117: /**
! 118: * Peer and authentication information to establish IKE_SA.
! 119: */
! 120: peer_cfg_t *peer_cfg;
! 121:
! 122: /**
! 123: * currently used authentication ruleset, local
! 124: */
! 125: auth_cfg_t *my_auth;
! 126:
! 127: /**
! 128: * currently used authentication constraints, remote
! 129: */
! 130: auth_cfg_t *other_auth;
! 131:
! 132: /**
! 133: * Array of completed local authentication rounds (as auth_cfg_t)
! 134: */
! 135: array_t *my_auths;
! 136:
! 137: /**
! 138: * Array of completed remote authentication rounds (as auth_cfg_t)
! 139: */
! 140: array_t *other_auths;
! 141:
! 142: /**
! 143: * Selected IKE proposal
! 144: */
! 145: proposal_t *proposal;
! 146:
! 147: /**
! 148: * Juggles tasks to process messages
! 149: */
! 150: task_manager_t *task_manager;
! 151:
! 152: /**
! 153: * Address of local host
! 154: */
! 155: host_t *my_host;
! 156:
! 157: /**
! 158: * Address of remote host
! 159: */
! 160: host_t *other_host;
! 161:
! 162: #ifdef ME
! 163: /**
! 164: * Are we mediation server
! 165: */
! 166: bool is_mediation_server;
! 167:
! 168: /**
! 169: * Server reflexive host
! 170: */
! 171: host_t *server_reflexive_host;
! 172:
! 173: /**
! 174: * Connect ID
! 175: */
! 176: chunk_t connect_id;
! 177: #endif /* ME */
! 178:
! 179: /**
! 180: * Identification used for us
! 181: */
! 182: identification_t *my_id;
! 183:
! 184: /**
! 185: * Identification used for other
! 186: */
! 187: identification_t *other_id;
! 188:
! 189: /**
! 190: * set of extensions the peer supports
! 191: */
! 192: ike_extension_t extensions;
! 193:
! 194: /**
! 195: * set of condition flags currently enabled for this IKE_SA
! 196: */
! 197: ike_condition_t conditions;
! 198:
! 199: /**
! 200: * Array containing the child sa's of the current IKE_SA.
! 201: */
! 202: array_t *child_sas;
! 203:
! 204: /**
! 205: * keymat of this IKE_SA
! 206: */
! 207: keymat_t *keymat;
! 208:
! 209: /**
! 210: * Virtual IPs on local host
! 211: */
! 212: array_t *my_vips;
! 213:
! 214: /**
! 215: * Virtual IPs on remote host
! 216: */
! 217: array_t *other_vips;
! 218:
! 219: /**
! 220: * List of configuration attributes (attribute_entry_t)
! 221: */
! 222: array_t *attributes;
! 223:
! 224: /**
! 225: * list of peer's addresses, additional ones transmitted via MOBIKE
! 226: */
! 227: array_t *peer_addresses;
! 228:
! 229: /**
! 230: * previously value of received DESTINATION_IP hash
! 231: */
! 232: chunk_t nat_detection_dest;
! 233:
! 234: /**
! 235: * NAT keep alive interval
! 236: */
! 237: uint32_t keepalive_interval;
! 238:
! 239: /**
! 240: * The scheduled keep alive job, if any
! 241: */
! 242: send_keepalive_job_t *keepalive_job;
! 243:
! 244: /**
! 245: * interval for retries during initiation (e.g. if DNS resolution failed),
! 246: * 0 to disable (default)
! 247: */
! 248: uint32_t retry_initiate_interval;
! 249:
! 250: /**
! 251: * TRUE if a retry_initiate_job has been queued
! 252: */
! 253: bool retry_initiate_queued;
! 254:
! 255: /**
! 256: * Timestamps for this IKE_SA
! 257: */
! 258: uint32_t stats[STAT_MAX];
! 259:
! 260: /**
! 261: * how many times we have retried so far (keyingtries)
! 262: */
! 263: uint32_t keyingtry;
! 264:
! 265: /**
! 266: * local host address to be used for IKE, set via MIGRATE kernel message
! 267: */
! 268: host_t *local_host;
! 269:
! 270: /**
! 271: * remote host address to be used for IKE, set via MIGRATE kernel message
! 272: */
! 273: host_t *remote_host;
! 274:
! 275: /**
! 276: * Flush auth configs once established?
! 277: */
! 278: bool flush_auth_cfg;
! 279:
! 280: /**
! 281: * Maximum length of a single fragment, 0 for address-specific defaults
! 282: */
! 283: size_t fragment_size;
! 284:
! 285: /**
! 286: * Whether to follow IKEv2 redirects
! 287: */
! 288: bool follow_redirects;
! 289:
! 290: /**
! 291: * Original gateway address from which we got redirected
! 292: */
! 293: host_t *redirected_from;
! 294:
! 295: /**
! 296: * Timestamps of redirect attempts to handle loops
! 297: */
! 298: array_t *redirected_at;
! 299:
! 300: /**
! 301: * Inbound interface ID
! 302: */
! 303: uint32_t if_id_in;
! 304:
! 305: /**
! 306: * Outbound interface ID
! 307: */
! 308: uint32_t if_id_out;
! 309: };
! 310:
! 311: /**
! 312: * Entry to maintain install configuration attributes during IKE_SA lifetime
! 313: */
! 314: struct attribute_entry_t {
! 315: /** handler used to install this attribute */
! 316: attribute_handler_t *handler;
! 317: /** attribute type */
! 318: configuration_attribute_type_t type;
! 319: /** attribute data */
! 320: chunk_t data;
! 321: };
! 322:
! 323: /**
! 324: * get the time of the latest traffic processed by the kernel
! 325: */
! 326: static time_t get_use_time(private_ike_sa_t* this, bool inbound)
! 327: {
! 328: enumerator_t *enumerator;
! 329: child_sa_t *child_sa;
! 330: time_t use_time, current;
! 331:
! 332: if (inbound)
! 333: {
! 334: use_time = this->stats[STAT_INBOUND];
! 335: }
! 336: else
! 337: {
! 338: use_time = this->stats[STAT_OUTBOUND];
! 339: }
! 340:
! 341: enumerator = array_create_enumerator(this->child_sas);
! 342: while (enumerator->enumerate(enumerator, &child_sa))
! 343: {
! 344: child_sa->get_usestats(child_sa, inbound, ¤t, NULL, NULL);
! 345: use_time = max(use_time, current);
! 346: }
! 347: enumerator->destroy(enumerator);
! 348:
! 349: return use_time;
! 350: }
! 351:
! 352: METHOD(ike_sa_t, get_unique_id, uint32_t,
! 353: private_ike_sa_t *this)
! 354: {
! 355: return this->unique_id;
! 356: }
! 357:
! 358: METHOD(ike_sa_t, get_name, char*,
! 359: private_ike_sa_t *this)
! 360: {
! 361: if (this->peer_cfg)
! 362: {
! 363: return this->peer_cfg->get_name(this->peer_cfg);
! 364: }
! 365: return "(unnamed)";
! 366: }
! 367:
! 368: METHOD(ike_sa_t, get_statistic, uint32_t,
! 369: private_ike_sa_t *this, statistic_t kind)
! 370: {
! 371: if (kind < STAT_MAX)
! 372: {
! 373: return this->stats[kind];
! 374: }
! 375: return 0;
! 376: }
! 377:
! 378: METHOD(ike_sa_t, set_statistic, void,
! 379: private_ike_sa_t *this, statistic_t kind, uint32_t value)
! 380: {
! 381: if (kind < STAT_MAX)
! 382: {
! 383: this->stats[kind] = value;
! 384: }
! 385: }
! 386:
! 387: METHOD(ike_sa_t, get_my_host, host_t*,
! 388: private_ike_sa_t *this)
! 389: {
! 390: return this->my_host;
! 391: }
! 392:
! 393: METHOD(ike_sa_t, set_my_host, void,
! 394: private_ike_sa_t *this, host_t *me)
! 395: {
! 396: DESTROY_IF(this->my_host);
! 397: this->my_host = me;
! 398: }
! 399:
! 400: METHOD(ike_sa_t, get_other_host, host_t*,
! 401: private_ike_sa_t *this)
! 402: {
! 403: return this->other_host;
! 404: }
! 405:
! 406: METHOD(ike_sa_t, set_other_host, void,
! 407: private_ike_sa_t *this, host_t *other)
! 408: {
! 409: DESTROY_IF(this->other_host);
! 410: this->other_host = other;
! 411: }
! 412:
! 413: METHOD(ike_sa_t, get_redirected_from, host_t*,
! 414: private_ike_sa_t *this)
! 415: {
! 416: return this->redirected_from;
! 417: }
! 418:
! 419: METHOD(ike_sa_t, get_peer_cfg, peer_cfg_t*,
! 420: private_ike_sa_t *this)
! 421: {
! 422: return this->peer_cfg;
! 423: }
! 424:
! 425: METHOD(ike_sa_t, set_peer_cfg, void,
! 426: private_ike_sa_t *this, peer_cfg_t *peer_cfg)
! 427: {
! 428: peer_cfg->get_ref(peer_cfg);
! 429: DESTROY_IF(this->peer_cfg);
! 430: this->peer_cfg = peer_cfg;
! 431:
! 432: if (!this->ike_cfg)
! 433: {
! 434: this->ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
! 435: this->ike_cfg->get_ref(this->ike_cfg);
! 436: }
! 437:
! 438: this->if_id_in = peer_cfg->get_if_id(peer_cfg, TRUE);
! 439: this->if_id_out = peer_cfg->get_if_id(peer_cfg, FALSE);
! 440: allocate_unique_if_ids(&this->if_id_in, &this->if_id_out);
! 441: }
! 442:
! 443: METHOD(ike_sa_t, get_auth_cfg, auth_cfg_t*,
! 444: private_ike_sa_t *this, bool local)
! 445: {
! 446: if (local)
! 447: {
! 448: return this->my_auth;
! 449: }
! 450: return this->other_auth;
! 451: }
! 452:
! 453: METHOD(ike_sa_t, add_auth_cfg, void,
! 454: private_ike_sa_t *this, bool local, auth_cfg_t *cfg)
! 455: {
! 456: if (local)
! 457: {
! 458: array_insert(this->my_auths, ARRAY_TAIL, cfg);
! 459: }
! 460: else
! 461: {
! 462: array_insert(this->other_auths, ARRAY_TAIL, cfg);
! 463: }
! 464: }
! 465:
! 466: METHOD(ike_sa_t, create_auth_cfg_enumerator, enumerator_t*,
! 467: private_ike_sa_t *this, bool local)
! 468: {
! 469: if (local)
! 470: {
! 471: return array_create_enumerator(this->my_auths);
! 472: }
! 473: return array_create_enumerator(this->other_auths);
! 474: }
! 475:
! 476: /**
! 477: * Flush the stored authentication round information
! 478: */
! 479: static void flush_auth_cfgs(private_ike_sa_t *this)
! 480: {
! 481: auth_cfg_t *cfg;
! 482:
! 483: this->my_auth->purge(this->my_auth, FALSE);
! 484: this->other_auth->purge(this->other_auth, FALSE);
! 485:
! 486: while (array_remove(this->my_auths, ARRAY_TAIL, &cfg))
! 487: {
! 488: cfg->destroy(cfg);
! 489: }
! 490: while (array_remove(this->other_auths, ARRAY_TAIL, &cfg))
! 491: {
! 492: cfg->destroy(cfg);
! 493: }
! 494: }
! 495:
! 496: METHOD(ike_sa_t, verify_peer_certificate, bool,
! 497: private_ike_sa_t *this)
! 498: {
! 499: enumerator_t *e1, *e2, *certs;
! 500: auth_cfg_t *cfg, *cfg_done;
! 501: certificate_t *peer, *cert;
! 502: public_key_t *key;
! 503: auth_cfg_t *auth;
! 504: auth_cfg_wrapper_t *wrapper;
! 505: time_t not_before, not_after;
! 506: bool valid = TRUE, found;
! 507:
! 508: if (this->state != IKE_ESTABLISHED)
! 509: {
! 510: DBG1(DBG_IKE, "unable to verify peer certificate in state %N",
! 511: ike_sa_state_names, this->state);
! 512: return FALSE;
! 513: }
! 514:
! 515: if (!this->flush_auth_cfg &&
! 516: lib->settings->get_bool(lib->settings,
! 517: "%s.flush_auth_cfg", FALSE, lib->ns))
! 518: { /* we can do this check only once if auth configs are flushed */
! 519: DBG1(DBG_IKE, "unable to verify peer certificate as authentication "
! 520: "information has been flushed");
! 521: return FALSE;
! 522: }
! 523: this->public.set_condition(&this->public, COND_ONLINE_VALIDATION_SUSPENDED,
! 524: FALSE);
! 525:
! 526: e1 = this->peer_cfg->create_auth_cfg_enumerator(this->peer_cfg, FALSE);
! 527: e2 = array_create_enumerator(this->other_auths);
! 528: while (e1->enumerate(e1, &cfg))
! 529: {
! 530: if (!e2->enumerate(e2, &cfg_done))
! 531: { /* this should not happen as the authentication should never have
! 532: * succeeded */
! 533: valid = FALSE;
! 534: break;
! 535: }
! 536: if ((uintptr_t)cfg_done->get(cfg_done,
! 537: AUTH_RULE_AUTH_CLASS) != AUTH_CLASS_PUBKEY)
! 538: {
! 539: continue;
! 540: }
! 541: peer = cfg_done->get(cfg_done, AUTH_RULE_SUBJECT_CERT);
! 542: if (!peer)
! 543: {
! 544: DBG1(DBG_IKE, "no subject certificate found, skipping certificate "
! 545: "verification");
! 546: continue;
! 547: }
! 548: if (!peer->get_validity(peer, NULL, ¬_before, ¬_after))
! 549: {
! 550: DBG1(DBG_IKE, "peer certificate invalid (valid from %T to %T)",
! 551: ¬_before, FALSE, ¬_after, FALSE);
! 552: valid = FALSE;
! 553: break;
! 554: }
! 555: key = peer->get_public_key(peer);
! 556: if (!key)
! 557: {
! 558: DBG1(DBG_IKE, "unable to retrieve public key, skipping certificate "
! 559: "verification");
! 560: continue;
! 561: }
! 562: DBG1(DBG_IKE, "verifying peer certificate");
! 563: /* serve received certificates */
! 564: wrapper = auth_cfg_wrapper_create(cfg_done);
! 565: lib->credmgr->add_local_set(lib->credmgr, &wrapper->set, FALSE);
! 566: certs = lib->credmgr->create_trusted_enumerator(lib->credmgr,
! 567: key->get_type(key), peer->get_subject(peer), TRUE);
! 568: key->destroy(key);
! 569:
! 570: found = FALSE;
! 571: while (certs->enumerate(certs, &cert, &auth))
! 572: {
! 573: if (peer->equals(peer, cert))
! 574: {
! 575: cfg_done->add(cfg_done, AUTH_RULE_CERT_VALIDATION_SUSPENDED,
! 576: FALSE);
! 577: cfg_done->merge(cfg_done, auth, FALSE);
! 578: valid = cfg_done->complies(cfg_done, cfg, TRUE);
! 579: found = TRUE;
! 580: break;
! 581: }
! 582: }
! 583: certs->destroy(certs);
! 584: lib->credmgr->remove_local_set(lib->credmgr, &wrapper->set);
! 585: wrapper->destroy(wrapper);
! 586: if (!found || !valid)
! 587: {
! 588: valid = FALSE;
! 589: break;
! 590: }
! 591: }
! 592: e1->destroy(e1);
! 593: e2->destroy(e2);
! 594:
! 595: if (this->flush_auth_cfg)
! 596: {
! 597: this->flush_auth_cfg = FALSE;
! 598: flush_auth_cfgs(this);
! 599: }
! 600: return valid;
! 601: }
! 602:
! 603: METHOD(ike_sa_t, get_proposal, proposal_t*,
! 604: private_ike_sa_t *this)
! 605: {
! 606: return this->proposal;
! 607: }
! 608:
! 609: METHOD(ike_sa_t, set_proposal, void,
! 610: private_ike_sa_t *this, proposal_t *proposal)
! 611: {
! 612: DESTROY_IF(this->proposal);
! 613: this->proposal = proposal->clone(proposal, 0);
! 614: }
! 615:
! 616: METHOD(ike_sa_t, set_message_id, void,
! 617: private_ike_sa_t *this, bool initiate, uint32_t mid)
! 618: {
! 619: if (initiate)
! 620: {
! 621: this->task_manager->reset(this->task_manager, mid, UINT_MAX);
! 622: }
! 623: else
! 624: {
! 625: this->task_manager->reset(this->task_manager, UINT_MAX, mid);
! 626: }
! 627: }
! 628:
! 629: METHOD(ike_sa_t, get_message_id, uint32_t,
! 630: private_ike_sa_t *this, bool initiate)
! 631: {
! 632: return this->task_manager->get_mid(this->task_manager, initiate);
! 633: }
! 634:
! 635: METHOD(ike_sa_t, send_keepalive, void,
! 636: private_ike_sa_t *this, bool scheduled)
! 637: {
! 638: time_t last_out, now, diff;
! 639:
! 640: if (scheduled)
! 641: {
! 642: this->keepalive_job = NULL;
! 643: }
! 644: if (!this->keepalive_interval || this->state == IKE_PASSIVE)
! 645: { /* keepalives disabled either by configuration or for passive IKE_SAs */
! 646: return;
! 647: }
! 648: if (!(this->conditions & COND_NAT_HERE) || (this->conditions & COND_STALE))
! 649: { /* disable keepalives if we are not NATed anymore, or the SA is stale */
! 650: return;
! 651: }
! 652:
! 653: last_out = get_use_time(this, FALSE);
! 654: now = time_monotonic(NULL);
! 655:
! 656: diff = now - last_out;
! 657:
! 658: if (diff >= this->keepalive_interval)
! 659: {
! 660: packet_t *packet;
! 661: chunk_t data;
! 662:
! 663: packet = packet_create();
! 664: packet->set_source(packet, this->my_host->clone(this->my_host));
! 665: packet->set_destination(packet, this->other_host->clone(this->other_host));
! 666: data.ptr = malloc(1);
! 667: data.ptr[0] = 0xFF;
! 668: data.len = 1;
! 669: packet->set_data(packet, data);
! 670: DBG1(DBG_IKE, "sending keep alive to %#H", this->other_host);
! 671: charon->sender->send_no_marker(charon->sender, packet);
! 672: diff = 0;
! 673: }
! 674: if (!this->keepalive_job)
! 675: {
! 676: this->keepalive_job = send_keepalive_job_create(this->ike_sa_id);
! 677: lib->scheduler->schedule_job(lib->scheduler, (job_t*)this->keepalive_job,
! 678: this->keepalive_interval - diff);
! 679: }
! 680: }
! 681:
! 682: METHOD(ike_sa_t, get_ike_cfg, ike_cfg_t*,
! 683: private_ike_sa_t *this)
! 684: {
! 685: return this->ike_cfg;
! 686: }
! 687:
! 688: METHOD(ike_sa_t, set_ike_cfg, void,
! 689: private_ike_sa_t *this, ike_cfg_t *ike_cfg)
! 690: {
! 691: DESTROY_IF(this->ike_cfg);
! 692: ike_cfg->get_ref(ike_cfg);
! 693: this->ike_cfg = ike_cfg;
! 694: }
! 695:
! 696: METHOD(ike_sa_t, enable_extension, void,
! 697: private_ike_sa_t *this, ike_extension_t extension)
! 698: {
! 699: this->extensions |= extension;
! 700: }
! 701:
! 702: METHOD(ike_sa_t, supports_extension, bool,
! 703: private_ike_sa_t *this, ike_extension_t extension)
! 704: {
! 705: return (this->extensions & extension) != FALSE;
! 706: }
! 707:
! 708: METHOD(ike_sa_t, has_condition, bool,
! 709: private_ike_sa_t *this, ike_condition_t condition)
! 710: {
! 711: return (this->conditions & condition) != FALSE;
! 712: }
! 713:
! 714: METHOD(ike_sa_t, set_condition, void,
! 715: private_ike_sa_t *this, ike_condition_t condition, bool enable)
! 716: {
! 717: if (has_condition(this, condition) != enable)
! 718: {
! 719: if (enable)
! 720: {
! 721: this->conditions |= condition;
! 722: switch (condition)
! 723: {
! 724: case COND_NAT_HERE:
! 725: DBG1(DBG_IKE, "local host is behind NAT, sending keep alives");
! 726: this->conditions |= COND_NAT_ANY;
! 727: send_keepalive(this, FALSE);
! 728: break;
! 729: case COND_NAT_THERE:
! 730: DBG1(DBG_IKE, "remote host is behind NAT");
! 731: this->conditions |= COND_NAT_ANY;
! 732: break;
! 733: case COND_NAT_FAKE:
! 734: DBG1(DBG_IKE, "faking NAT situation to enforce UDP encapsulation");
! 735: this->conditions |= COND_NAT_ANY;
! 736: break;
! 737: default:
! 738: break;
! 739: }
! 740: }
! 741: else
! 742: {
! 743: this->conditions &= ~condition;
! 744: switch (condition)
! 745: {
! 746: case COND_NAT_HERE:
! 747: case COND_NAT_THERE:
! 748: DBG1(DBG_IKE, "%s host is not behind NAT anymore",
! 749: condition == COND_NAT_HERE ? "local" : "remote");
! 750: /* fall-through */
! 751: case COND_NAT_FAKE:
! 752: set_condition(this, COND_NAT_ANY,
! 753: has_condition(this, COND_NAT_HERE) ||
! 754: has_condition(this, COND_NAT_THERE) ||
! 755: has_condition(this, COND_NAT_FAKE));
! 756: break;
! 757: case COND_STALE:
! 758: send_keepalive(this, FALSE);
! 759: break;
! 760: default:
! 761: break;
! 762: }
! 763: }
! 764: }
! 765: }
! 766:
! 767: METHOD(ike_sa_t, send_dpd, status_t,
! 768: private_ike_sa_t *this)
! 769: {
! 770: job_t *job;
! 771: time_t diff, delay;
! 772: bool task_queued = FALSE;
! 773:
! 774: if (this->state == IKE_PASSIVE)
! 775: {
! 776: return INVALID_STATE;
! 777: }
! 778: if (this->version == IKEV1 && this->state == IKE_REKEYING)
! 779: { /* don't send DPDs for rekeyed IKEv1 SAs */
! 780: return SUCCESS;
! 781: }
! 782: delay = this->peer_cfg->get_dpd(this->peer_cfg);
! 783: if (this->task_manager->busy(this->task_manager))
! 784: {
! 785: /* an exchange is in the air, no need to start a DPD check */
! 786: diff = 0;
! 787: }
! 788: else
! 789: {
! 790: /* check if there was any inbound traffic */
! 791: time_t last_in, now;
! 792: last_in = get_use_time(this, TRUE);
! 793: now = time_monotonic(NULL);
! 794: diff = now - last_in;
! 795: if (!delay || diff >= delay)
! 796: {
! 797: /* too long ago, initiate dead peer detection */
! 798: DBG1(DBG_IKE, "sending DPD request");
! 799: this->task_manager->queue_dpd(this->task_manager);
! 800: task_queued = TRUE;
! 801: diff = 0;
! 802: }
! 803: }
! 804: /* recheck in "interval" seconds */
! 805: if (delay)
! 806: {
! 807: job = (job_t*)send_dpd_job_create(this->ike_sa_id);
! 808: lib->scheduler->schedule_job(lib->scheduler, job, delay - diff);
! 809: }
! 810: if (task_queued)
! 811: {
! 812: return this->task_manager->initiate(this->task_manager);
! 813: }
! 814: return SUCCESS;
! 815: }
! 816:
! 817: METHOD(ike_sa_t, get_state, ike_sa_state_t,
! 818: private_ike_sa_t *this)
! 819: {
! 820: return this->state;
! 821: }
! 822:
! 823: METHOD(ike_sa_t, set_state, void,
! 824: private_ike_sa_t *this, ike_sa_state_t state)
! 825: {
! 826: bool trigger_dpd = FALSE, keepalives = FALSE;
! 827:
! 828: DBG2(DBG_IKE, "IKE_SA %s[%d] state change: %N => %N",
! 829: get_name(this), this->unique_id,
! 830: ike_sa_state_names, this->state,
! 831: ike_sa_state_names, state);
! 832:
! 833: switch (state)
! 834: {
! 835: case IKE_ESTABLISHED:
! 836: {
! 837: if (this->state == IKE_CONNECTING ||
! 838: this->state == IKE_PASSIVE)
! 839: {
! 840: job_t *job;
! 841: uint32_t t;
! 842:
! 843: /* calculate rekey, reauth and lifetime */
! 844: this->stats[STAT_ESTABLISHED] = time_monotonic(NULL);
! 845:
! 846: /* schedule rekeying if we have a time which is smaller than
! 847: * an already scheduled rekeying */
! 848: t = this->peer_cfg->get_rekey_time(this->peer_cfg, TRUE);
! 849: if (t && (this->stats[STAT_REKEY] == 0 ||
! 850: (this->stats[STAT_REKEY] > t + this->stats[STAT_ESTABLISHED])))
! 851: {
! 852: this->stats[STAT_REKEY] = t + this->stats[STAT_ESTABLISHED];
! 853: job = (job_t*)rekey_ike_sa_job_create(this->ike_sa_id, FALSE);
! 854: lib->scheduler->schedule_job(lib->scheduler, job, t);
! 855: DBG1(DBG_IKE, "scheduling rekeying in %ds", t);
! 856: }
! 857: t = this->peer_cfg->get_reauth_time(this->peer_cfg, TRUE);
! 858: if (t && (this->stats[STAT_REAUTH] == 0 ||
! 859: (this->stats[STAT_REAUTH] > t + this->stats[STAT_ESTABLISHED])))
! 860: {
! 861: this->stats[STAT_REAUTH] = t + this->stats[STAT_ESTABLISHED];
! 862: job = (job_t*)rekey_ike_sa_job_create(this->ike_sa_id, TRUE);
! 863: lib->scheduler->schedule_job(lib->scheduler, job, t);
! 864: DBG1(DBG_IKE, "scheduling reauthentication in %ds", t);
! 865: }
! 866: t = this->peer_cfg->get_over_time(this->peer_cfg);
! 867: if (this->stats[STAT_REKEY] || this->stats[STAT_REAUTH])
! 868: {
! 869: if (this->stats[STAT_REAUTH] == 0)
! 870: {
! 871: this->stats[STAT_DELETE] = this->stats[STAT_REKEY];
! 872: }
! 873: else if (this->stats[STAT_REKEY] == 0)
! 874: {
! 875: this->stats[STAT_DELETE] = this->stats[STAT_REAUTH];
! 876: }
! 877: else
! 878: {
! 879: this->stats[STAT_DELETE] = min(this->stats[STAT_REKEY],
! 880: this->stats[STAT_REAUTH]);
! 881: }
! 882: this->stats[STAT_DELETE] += t;
! 883: t = this->stats[STAT_DELETE] - this->stats[STAT_ESTABLISHED];
! 884: job = (job_t*)delete_ike_sa_job_create(this->ike_sa_id, TRUE);
! 885: lib->scheduler->schedule_job(lib->scheduler, job, t);
! 886: DBG1(DBG_IKE, "maximum IKE_SA lifetime %ds", t);
! 887: }
! 888: trigger_dpd = this->peer_cfg->get_dpd(this->peer_cfg);
! 889: if (trigger_dpd)
! 890: {
! 891: /* Some peers delay the DELETE after rekeying an IKE_SA.
! 892: * If this delay is longer than our DPD delay, we would
! 893: * send a DPD request here. The IKE_SA is not ready to do
! 894: * so yet, so prevent that. */
! 895: this->stats[STAT_INBOUND] = this->stats[STAT_ESTABLISHED];
! 896: }
! 897: if (this->state == IKE_PASSIVE)
! 898: {
! 899: keepalives = TRUE;
! 900: }
! 901: DESTROY_IF(this->redirected_from);
! 902: this->redirected_from = NULL;
! 903: }
! 904: break;
! 905: }
! 906: default:
! 907: break;
! 908: }
! 909: charon->bus->ike_state_change(charon->bus, &this->public, state);
! 910: this->state = state;
! 911:
! 912: if (trigger_dpd)
! 913: {
! 914: if (supports_extension(this, EXT_DPD))
! 915: {
! 916: send_dpd(this);
! 917: }
! 918: else
! 919: {
! 920: DBG1(DBG_IKE, "DPD not supported by peer, disabled");
! 921: }
! 922: }
! 923: if (keepalives)
! 924: {
! 925: send_keepalive(this, FALSE);
! 926: }
! 927: }
! 928:
! 929: METHOD(ike_sa_t, reset, void,
! 930: private_ike_sa_t *this, bool new_spi)
! 931: {
! 932: /* reset the initiator SPI if requested */
! 933: if (new_spi)
! 934: {
! 935: charon->ike_sa_manager->new_initiator_spi(charon->ike_sa_manager,
! 936: &this->public);
! 937: }
! 938: /* the responder ID is reset, as peer may choose another one */
! 939: if (this->ike_sa_id->is_initiator(this->ike_sa_id))
! 940: {
! 941: this->ike_sa_id->set_responder_spi(this->ike_sa_id, 0);
! 942: }
! 943:
! 944: set_state(this, IKE_CREATED);
! 945:
! 946: flush_auth_cfgs(this);
! 947:
! 948: this->keymat->destroy(this->keymat);
! 949: this->keymat = keymat_create(this->version,
! 950: this->ike_sa_id->is_initiator(this->ike_sa_id));
! 951:
! 952: this->task_manager->reset(this->task_manager, 0, 0);
! 953: this->task_manager->queue_ike(this->task_manager);
! 954: }
! 955:
! 956: METHOD(ike_sa_t, get_keymat, keymat_t*,
! 957: private_ike_sa_t *this)
! 958: {
! 959: return this->keymat;
! 960: }
! 961:
! 962: METHOD(ike_sa_t, add_virtual_ip, void,
! 963: private_ike_sa_t *this, bool local, host_t *ip)
! 964: {
! 965: if (local)
! 966: {
! 967: char *iface;
! 968:
! 969: if (charon->kernel->get_interface(charon->kernel, this->my_host,
! 970: &iface))
! 971: {
! 972: DBG1(DBG_IKE, "installing new virtual IP %H", ip);
! 973: if (charon->kernel->add_ip(charon->kernel, ip, -1,
! 974: iface) == SUCCESS)
! 975: {
! 976: array_insert_create(&this->my_vips, ARRAY_TAIL, ip->clone(ip));
! 977: }
! 978: else
! 979: {
! 980: DBG1(DBG_IKE, "installing virtual IP %H failed", ip);
! 981: }
! 982: free(iface);
! 983: }
! 984: else
! 985: {
! 986: DBG1(DBG_IKE, "looking up interface for virtual IP %H failed", ip);
! 987: }
! 988: }
! 989: else
! 990: {
! 991: array_insert_create(&this->other_vips, ARRAY_TAIL, ip->clone(ip));
! 992: }
! 993: }
! 994:
! 995:
! 996: METHOD(ike_sa_t, clear_virtual_ips, void,
! 997: private_ike_sa_t *this, bool local)
! 998: {
! 999: array_t *vips;
! 1000: host_t *vip;
! 1001:
! 1002: vips = local ? this->my_vips : this->other_vips;
! 1003: if (!local && array_count(vips))
! 1004: {
! 1005: charon->bus->assign_vips(charon->bus, &this->public, FALSE);
! 1006: }
! 1007: while (array_remove(vips, ARRAY_HEAD, &vip))
! 1008: {
! 1009: if (local)
! 1010: {
! 1011: charon->kernel->del_ip(charon->kernel, vip, -1, TRUE);
! 1012: }
! 1013: vip->destroy(vip);
! 1014: }
! 1015: }
! 1016:
! 1017: METHOD(ike_sa_t, create_virtual_ip_enumerator, enumerator_t*,
! 1018: private_ike_sa_t *this, bool local)
! 1019: {
! 1020: if (local)
! 1021: {
! 1022: return array_create_enumerator(this->my_vips);
! 1023: }
! 1024: return array_create_enumerator(this->other_vips);
! 1025: }
! 1026:
! 1027: METHOD(ike_sa_t, add_peer_address, void,
! 1028: private_ike_sa_t *this, host_t *host)
! 1029: {
! 1030: array_insert_create(&this->peer_addresses, ARRAY_TAIL, host);
! 1031: }
! 1032:
! 1033: METHOD(ike_sa_t, create_peer_address_enumerator, enumerator_t*,
! 1034: private_ike_sa_t *this)
! 1035: {
! 1036: if (this->peer_addresses)
! 1037: {
! 1038: return array_create_enumerator(this->peer_addresses);
! 1039: }
! 1040: /* in case we don't have MOBIKE */
! 1041: return enumerator_create_single(this->other_host, NULL);
! 1042: }
! 1043:
! 1044: METHOD(ike_sa_t, clear_peer_addresses, void,
! 1045: private_ike_sa_t *this)
! 1046: {
! 1047: array_destroy_offset(this->peer_addresses, offsetof(host_t, destroy));
! 1048: this->peer_addresses = NULL;
! 1049: }
! 1050:
! 1051: METHOD(ike_sa_t, has_mapping_changed, bool,
! 1052: private_ike_sa_t *this, chunk_t hash)
! 1053: {
! 1054: if (this->nat_detection_dest.ptr == NULL)
! 1055: {
! 1056: this->nat_detection_dest = chunk_clone(hash);
! 1057: return FALSE;
! 1058: }
! 1059: if (chunk_equals(hash, this->nat_detection_dest))
! 1060: {
! 1061: return FALSE;
! 1062: }
! 1063: free(this->nat_detection_dest.ptr);
! 1064: this->nat_detection_dest = chunk_clone(hash);
! 1065: return TRUE;
! 1066: }
! 1067:
! 1068: METHOD(ike_sa_t, float_ports, void,
! 1069: private_ike_sa_t *this)
! 1070: {
! 1071: /* even if the remote port is not 500 (e.g. because the response was natted)
! 1072: * we switch the remote port if we used port 500 */
! 1073: if (this->other_host->get_port(this->other_host) == IKEV2_UDP_PORT ||
! 1074: this->my_host->get_port(this->my_host) == IKEV2_UDP_PORT)
! 1075: {
! 1076: this->other_host->set_port(this->other_host, IKEV2_NATT_PORT);
! 1077: }
! 1078: if (this->my_host->get_port(this->my_host) ==
! 1079: charon->socket->get_port(charon->socket, FALSE))
! 1080: {
! 1081: this->my_host->set_port(this->my_host,
! 1082: charon->socket->get_port(charon->socket, TRUE));
! 1083: }
! 1084: }
! 1085:
! 1086: METHOD(ike_sa_t, update_hosts, void,
! 1087: private_ike_sa_t *this, host_t *me, host_t *other, bool force)
! 1088: {
! 1089: bool update = FALSE;
! 1090:
! 1091: if (me == NULL)
! 1092: {
! 1093: me = this->my_host;
! 1094: }
! 1095: if (other == NULL)
! 1096: {
! 1097: other = this->other_host;
! 1098: }
! 1099:
! 1100: /* apply hosts on first received message */
! 1101: if (this->my_host->is_anyaddr(this->my_host) ||
! 1102: this->other_host->is_anyaddr(this->other_host))
! 1103: {
! 1104: set_my_host(this, me->clone(me));
! 1105: set_other_host(this, other->clone(other));
! 1106: update = TRUE;
! 1107: }
! 1108: else
! 1109: {
! 1110: /* update our address in any case */
! 1111: if (force && !me->equals(me, this->my_host))
! 1112: {
! 1113: charon->bus->ike_update(charon->bus, &this->public, TRUE, me);
! 1114: set_my_host(this, me->clone(me));
! 1115: update = TRUE;
! 1116: }
! 1117:
! 1118: if (!other->equals(other, this->other_host) &&
! 1119: (force || has_condition(this, COND_NAT_THERE)))
! 1120: {
! 1121: /* only update other's address if we are behind a static NAT,
! 1122: * which we assume is the case if we are not initiator */
! 1123: if (force ||
! 1124: (!has_condition(this, COND_NAT_HERE) ||
! 1125: !has_condition(this, COND_ORIGINAL_INITIATOR)))
! 1126: {
! 1127: charon->bus->ike_update(charon->bus, &this->public, FALSE, other);
! 1128: set_other_host(this, other->clone(other));
! 1129: update = TRUE;
! 1130: }
! 1131: }
! 1132: }
! 1133:
! 1134: /* update all associated CHILD_SAs, if required */
! 1135: if (update)
! 1136: {
! 1137: enumerator_t *enumerator;
! 1138: child_sa_t *child_sa;
! 1139: linked_list_t *vips;
! 1140:
! 1141: vips = linked_list_create_from_enumerator(
! 1142: array_create_enumerator(this->my_vips));
! 1143:
! 1144: enumerator = array_create_enumerator(this->child_sas);
! 1145: while (enumerator->enumerate(enumerator, &child_sa))
! 1146: {
! 1147: charon->child_sa_manager->remove(charon->child_sa_manager, child_sa);
! 1148: charon->child_sa_manager->add(charon->child_sa_manager,
! 1149: child_sa, &this->public);
! 1150:
! 1151: if (child_sa->update(child_sa, this->my_host, this->other_host,
! 1152: vips, has_condition(this, COND_NAT_ANY)) == NOT_SUPPORTED)
! 1153: {
! 1154: this->public.rekey_child_sa(&this->public,
! 1155: child_sa->get_protocol(child_sa),
! 1156: child_sa->get_spi(child_sa, TRUE));
! 1157: }
! 1158:
! 1159: }
! 1160: enumerator->destroy(enumerator);
! 1161:
! 1162: vips->destroy(vips);
! 1163: }
! 1164: }
! 1165:
! 1166: /**
! 1167: * Set configured DSCP value on packet
! 1168: */
! 1169: static void set_dscp(private_ike_sa_t *this, packet_t *packet)
! 1170: {
! 1171: ike_cfg_t *ike_cfg;
! 1172:
! 1173: /* prefer IKE config on peer_cfg, as its selection is more accurate
! 1174: * then the initial IKE config */
! 1175: if (this->peer_cfg)
! 1176: {
! 1177: ike_cfg = this->peer_cfg->get_ike_cfg(this->peer_cfg);
! 1178: }
! 1179: else
! 1180: {
! 1181: ike_cfg = this->ike_cfg;
! 1182: }
! 1183: if (ike_cfg)
! 1184: {
! 1185: packet->set_dscp(packet, ike_cfg->get_dscp(ike_cfg));
! 1186: }
! 1187: }
! 1188:
! 1189: METHOD(ike_sa_t, generate_message, status_t,
! 1190: private_ike_sa_t *this, message_t *message, packet_t **packet)
! 1191: {
! 1192: status_t status;
! 1193:
! 1194: if (message->is_encoded(message))
! 1195: { /* already encoded in task, but set DSCP value */
! 1196: *packet = message->get_packet(message);
! 1197: set_dscp(this, *packet);
! 1198: return SUCCESS;
! 1199: }
! 1200: this->stats[STAT_OUTBOUND] = time_monotonic(NULL);
! 1201: message->set_ike_sa_id(message, this->ike_sa_id);
! 1202: charon->bus->message(charon->bus, message, FALSE, TRUE);
! 1203: status = message->generate(message, this->keymat, packet);
! 1204: if (status == SUCCESS)
! 1205: {
! 1206: set_dscp(this, *packet);
! 1207: charon->bus->message(charon->bus, message, FALSE, FALSE);
! 1208: }
! 1209: return status;
! 1210: }
! 1211:
! 1212: CALLBACK(filter_fragments, bool,
! 1213: private_ike_sa_t *this, enumerator_t *orig, va_list args)
! 1214: {
! 1215: packet_t *fragment, **packet;
! 1216:
! 1217: VA_ARGS_VGET(args, packet);
! 1218:
! 1219: if (orig->enumerate(orig, &fragment))
! 1220: {
! 1221: *packet = fragment->clone(fragment);
! 1222: set_dscp(this, *packet);
! 1223: return TRUE;
! 1224: }
! 1225: return FALSE;
! 1226: }
! 1227:
! 1228: METHOD(ike_sa_t, generate_message_fragmented, status_t,
! 1229: private_ike_sa_t *this, message_t *message, enumerator_t **packets)
! 1230: {
! 1231: enumerator_t *fragments;
! 1232: packet_t *packet;
! 1233: status_t status;
! 1234: bool use_frags = FALSE;
! 1235: bool pre_generated = FALSE;
! 1236:
! 1237: if (this->ike_cfg)
! 1238: {
! 1239: switch (this->ike_cfg->fragmentation(this->ike_cfg))
! 1240: {
! 1241: case FRAGMENTATION_FORCE:
! 1242: use_frags = TRUE;
! 1243: break;
! 1244: case FRAGMENTATION_YES:
! 1245: use_frags = supports_extension(this, EXT_IKE_FRAGMENTATION);
! 1246: if (use_frags && this->version == IKEV1 &&
! 1247: supports_extension(this, EXT_MS_WINDOWS))
! 1248: {
! 1249: /* It seems Windows 7 and 8 peers only accept proprietary
! 1250: * fragmented messages if they expect certificates. */
! 1251: use_frags = message->get_payload(message,
! 1252: PLV1_CERTIFICATE) != NULL;
! 1253: }
! 1254: break;
! 1255: default:
! 1256: break;
! 1257: }
! 1258: }
! 1259: if (!use_frags)
! 1260: {
! 1261: status = generate_message(this, message, &packet);
! 1262: if (status != SUCCESS)
! 1263: {
! 1264: return status;
! 1265: }
! 1266: *packets = enumerator_create_single(packet, NULL);
! 1267: return SUCCESS;
! 1268: }
! 1269:
! 1270: pre_generated = message->is_encoded(message);
! 1271: this->stats[STAT_OUTBOUND] = time_monotonic(NULL);
! 1272: message->set_ike_sa_id(message, this->ike_sa_id);
! 1273: if (!pre_generated)
! 1274: {
! 1275: charon->bus->message(charon->bus, message, FALSE, TRUE);
! 1276: }
! 1277: status = message->fragment(message, this->keymat, this->fragment_size,
! 1278: &fragments);
! 1279: if (status == SUCCESS)
! 1280: {
! 1281: if (!pre_generated)
! 1282: {
! 1283: charon->bus->message(charon->bus, message, FALSE, FALSE);
! 1284: }
! 1285: *packets = enumerator_create_filter(fragments, filter_fragments,
! 1286: this, NULL);
! 1287: }
! 1288: return status;
! 1289: }
! 1290:
! 1291: METHOD(ike_sa_t, set_kmaddress, void,
! 1292: private_ike_sa_t *this, host_t *local, host_t *remote)
! 1293: {
! 1294: DESTROY_IF(this->local_host);
! 1295: DESTROY_IF(this->remote_host);
! 1296: this->local_host = local->clone(local);
! 1297: this->remote_host = remote->clone(remote);
! 1298: }
! 1299:
! 1300: #ifdef ME
! 1301: METHOD(ike_sa_t, act_as_mediation_server, void,
! 1302: private_ike_sa_t *this)
! 1303: {
! 1304: charon->mediation_manager->update_sa_id(charon->mediation_manager,
! 1305: this->other_id, this->ike_sa_id);
! 1306: this->is_mediation_server = TRUE;
! 1307: }
! 1308:
! 1309: METHOD(ike_sa_t, get_server_reflexive_host, host_t*,
! 1310: private_ike_sa_t *this)
! 1311: {
! 1312: return this->server_reflexive_host;
! 1313: }
! 1314:
! 1315: METHOD(ike_sa_t, set_server_reflexive_host, void,
! 1316: private_ike_sa_t *this, host_t *host)
! 1317: {
! 1318: DESTROY_IF(this->server_reflexive_host);
! 1319: this->server_reflexive_host = host;
! 1320: }
! 1321:
! 1322: METHOD(ike_sa_t, get_connect_id, chunk_t,
! 1323: private_ike_sa_t *this)
! 1324: {
! 1325: return this->connect_id;
! 1326: }
! 1327:
! 1328: METHOD(ike_sa_t, respond, status_t,
! 1329: private_ike_sa_t *this, identification_t *peer_id, chunk_t connect_id)
! 1330: {
! 1331: ike_me_t *task = ike_me_create(&this->public, TRUE);
! 1332: task->respond(task, peer_id, connect_id);
! 1333: this->task_manager->queue_task(this->task_manager, (task_t*)task);
! 1334: return this->task_manager->initiate(this->task_manager);
! 1335: }
! 1336:
! 1337: METHOD(ike_sa_t, callback, status_t,
! 1338: private_ike_sa_t *this, identification_t *peer_id)
! 1339: {
! 1340: ike_me_t *task = ike_me_create(&this->public, TRUE);
! 1341: task->callback(task, peer_id);
! 1342: this->task_manager->queue_task(this->task_manager, (task_t*)task);
! 1343: return this->task_manager->initiate(this->task_manager);
! 1344: }
! 1345:
! 1346: METHOD(ike_sa_t, relay, status_t,
! 1347: private_ike_sa_t *this, identification_t *requester, chunk_t connect_id,
! 1348: chunk_t connect_key, linked_list_t *endpoints, bool response)
! 1349: {
! 1350: ike_me_t *task = ike_me_create(&this->public, TRUE);
! 1351: task->relay(task, requester, connect_id, connect_key, endpoints, response);
! 1352: this->task_manager->queue_task(this->task_manager, (task_t*)task);
! 1353: return this->task_manager->initiate(this->task_manager);
! 1354: }
! 1355:
! 1356: METHOD(ike_sa_t, initiate_mediation, status_t,
! 1357: private_ike_sa_t *this, peer_cfg_t *mediated_cfg)
! 1358: {
! 1359: ike_me_t *task = ike_me_create(&this->public, TRUE);
! 1360: task->connect(task, mediated_cfg->get_peer_id(mediated_cfg));
! 1361: this->task_manager->queue_task(this->task_manager, (task_t*)task);
! 1362: return this->task_manager->initiate(this->task_manager);
! 1363: }
! 1364:
! 1365: METHOD(ike_sa_t, initiate_mediated, status_t,
! 1366: private_ike_sa_t *this, host_t *me, host_t *other, chunk_t connect_id)
! 1367: {
! 1368: set_my_host(this, me->clone(me));
! 1369: set_other_host(this, other->clone(other));
! 1370: chunk_free(&this->connect_id);
! 1371: this->connect_id = chunk_clone(connect_id);
! 1372: return this->task_manager->initiate(this->task_manager);
! 1373: }
! 1374: #endif /* ME */
! 1375:
! 1376: /**
! 1377: * Resolve DNS host in configuration
! 1378: */
! 1379: static void resolve_hosts(private_ike_sa_t *this)
! 1380: {
! 1381: host_t *host;
! 1382: int family = AF_UNSPEC;
! 1383:
! 1384: switch (charon->socket->supported_families(charon->socket))
! 1385: {
! 1386: case SOCKET_FAMILY_IPV4:
! 1387: family = AF_INET;
! 1388: break;
! 1389: case SOCKET_FAMILY_IPV6:
! 1390: family = AF_INET6;
! 1391: break;
! 1392: case SOCKET_FAMILY_BOTH:
! 1393: case SOCKET_FAMILY_NONE:
! 1394: break;
! 1395: }
! 1396:
! 1397: /* if an IP address is set locally, use the same family to resolve remote */
! 1398: if (family == AF_UNSPEC && !this->remote_host)
! 1399: {
! 1400: if (this->local_host)
! 1401: {
! 1402: family = this->local_host->get_family(this->local_host);
! 1403: }
! 1404: else
! 1405: {
! 1406: family = ike_cfg_get_family(this->ike_cfg, TRUE);
! 1407: }
! 1408: }
! 1409:
! 1410: if (this->remote_host)
! 1411: {
! 1412: host = this->remote_host->clone(this->remote_host);
! 1413: host->set_port(host, IKEV2_UDP_PORT);
! 1414: }
! 1415: else
! 1416: {
! 1417: host = this->ike_cfg->resolve_other(this->ike_cfg, family);
! 1418: }
! 1419: if (host)
! 1420: {
! 1421: if (!host->is_anyaddr(host) ||
! 1422: this->other_host->is_anyaddr(this->other_host))
! 1423: { /* don't set to %any if we currently have an address, but the
! 1424: * address family might have changed */
! 1425: set_other_host(this, host);
! 1426: }
! 1427: else
! 1428: { /* reuse the original port as some implementations might not like
! 1429: * initial IKE messages on other ports */
! 1430: this->other_host->set_port(this->other_host, host->get_port(host));
! 1431: host->destroy(host);
! 1432: }
! 1433: }
! 1434:
! 1435: if (this->local_host)
! 1436: {
! 1437: host = this->local_host->clone(this->local_host);
! 1438: host->set_port(host, charon->socket->get_port(charon->socket, FALSE));
! 1439: }
! 1440: else
! 1441: {
! 1442: /* use same address family as for other */
! 1443: if (!this->other_host->is_anyaddr(this->other_host))
! 1444: {
! 1445: family = this->other_host->get_family(this->other_host);
! 1446: }
! 1447: host = this->ike_cfg->resolve_me(this->ike_cfg, family);
! 1448:
! 1449: if (host && host->is_anyaddr(host) &&
! 1450: !this->other_host->is_anyaddr(this->other_host))
! 1451: {
! 1452: host->destroy(host);
! 1453: host = charon->kernel->get_source_addr(charon->kernel,
! 1454: this->other_host, NULL);
! 1455: if (host)
! 1456: {
! 1457: host->set_port(host, this->ike_cfg->get_my_port(this->ike_cfg));
! 1458: }
! 1459: else
! 1460: { /* fallback to address family specific %any(6), if configured */
! 1461: host = this->ike_cfg->resolve_me(this->ike_cfg, family);
! 1462: }
! 1463: }
! 1464: }
! 1465: if (host)
! 1466: {
! 1467: set_my_host(this, host);
! 1468: }
! 1469: }
! 1470:
! 1471: METHOD(ike_sa_t, initiate, status_t,
! 1472: private_ike_sa_t *this, child_cfg_t *child_cfg, uint32_t reqid,
! 1473: traffic_selector_t *tsi, traffic_selector_t *tsr)
! 1474: {
! 1475: bool defer_initiate = FALSE;
! 1476:
! 1477: if (this->state == IKE_CREATED)
! 1478: {
! 1479: if (this->my_host->is_anyaddr(this->my_host) ||
! 1480: this->other_host->is_anyaddr(this->other_host))
! 1481: {
! 1482: resolve_hosts(this);
! 1483: }
! 1484:
! 1485: if (this->other_host->is_anyaddr(this->other_host)
! 1486: #ifdef ME
! 1487: && !this->peer_cfg->get_mediated_by(this->peer_cfg)
! 1488: #endif /* ME */
! 1489: )
! 1490: {
! 1491: char *addr;
! 1492:
! 1493: addr = this->ike_cfg->get_other_addr(this->ike_cfg);
! 1494: if (!this->retry_initiate_interval)
! 1495: {
! 1496: DBG1(DBG_IKE, "unable to resolve %s, initiate aborted",
! 1497: addr);
! 1498: DESTROY_IF(child_cfg);
! 1499: charon->bus->alert(charon->bus, ALERT_PEER_ADDR_FAILED);
! 1500: return DESTROY_ME;
! 1501: }
! 1502: DBG1(DBG_IKE, "unable to resolve %s, retrying in %ds",
! 1503: addr, this->retry_initiate_interval);
! 1504: defer_initiate = TRUE;
! 1505: }
! 1506:
! 1507: set_condition(this, COND_ORIGINAL_INITIATOR, TRUE);
! 1508: this->task_manager->queue_ike(this->task_manager);
! 1509: }
! 1510:
! 1511: #ifdef ME
! 1512: if (this->peer_cfg->is_mediation(this->peer_cfg))
! 1513: {
! 1514: if (this->state == IKE_ESTABLISHED)
! 1515: {
! 1516: /* mediation connection is already established, retrigger state
! 1517: * change to notify bus listeners */
! 1518: DBG1(DBG_IKE, "mediation connection is already up");
! 1519: set_state(this, IKE_ESTABLISHED);
! 1520: }
! 1521: DESTROY_IF(child_cfg);
! 1522: }
! 1523: else
! 1524: #endif /* ME */
! 1525: if (child_cfg)
! 1526: {
! 1527: /* normal IKE_SA with CHILD_SA */
! 1528: this->task_manager->queue_child(this->task_manager, child_cfg, reqid,
! 1529: tsi, tsr);
! 1530: #ifdef ME
! 1531: if (this->peer_cfg->get_mediated_by(this->peer_cfg))
! 1532: {
! 1533: /* mediated connection, initiate mediation process */
! 1534: job_t *job = (job_t*)initiate_mediation_job_create(this->ike_sa_id);
! 1535: lib->processor->queue_job(lib->processor, job);
! 1536: return SUCCESS;
! 1537: }
! 1538: #endif /* ME */
! 1539: }
! 1540:
! 1541: if (defer_initiate)
! 1542: {
! 1543: if (!this->retry_initiate_queued)
! 1544: {
! 1545: job_t *job = (job_t*)retry_initiate_job_create(this->ike_sa_id);
! 1546: lib->scheduler->schedule_job(lib->scheduler, (job_t*)job,
! 1547: this->retry_initiate_interval);
! 1548: this->retry_initiate_queued = TRUE;
! 1549: }
! 1550: return SUCCESS;
! 1551: }
! 1552: this->retry_initiate_queued = FALSE;
! 1553: return this->task_manager->initiate(this->task_manager);
! 1554: }
! 1555:
! 1556: METHOD(ike_sa_t, retry_initiate, status_t,
! 1557: private_ike_sa_t *this)
! 1558: {
! 1559: if (this->retry_initiate_queued)
! 1560: {
! 1561: this->retry_initiate_queued = FALSE;
! 1562: return initiate(this, NULL, 0, NULL, NULL);
! 1563: }
! 1564: return SUCCESS;
! 1565: }
! 1566:
! 1567: METHOD(ike_sa_t, process_message, status_t,
! 1568: private_ike_sa_t *this, message_t *message)
! 1569: {
! 1570: status_t status;
! 1571:
! 1572: if (this->state == IKE_PASSIVE)
! 1573: { /* do not handle messages in passive state */
! 1574: return FAILED;
! 1575: }
! 1576: if (message->get_major_version(message) != this->version)
! 1577: {
! 1578: DBG1(DBG_IKE, "ignoring %N IKEv%u exchange on %N SA",
! 1579: exchange_type_names, message->get_exchange_type(message),
! 1580: message->get_major_version(message),
! 1581: ike_version_names, this->version);
! 1582: /* TODO-IKEv1: fall back to IKEv1 if we receive an IKEv1
! 1583: * INVALID_MAJOR_VERSION on an IKEv2 SA. */
! 1584: return FAILED;
! 1585: }
! 1586: status = this->task_manager->process_message(this->task_manager, message);
! 1587: if (this->flush_auth_cfg && this->state == IKE_ESTABLISHED)
! 1588: {
! 1589: /* authentication completed but if the online validation is suspended we
! 1590: * need the auth cfgs until we did the delayed verification, we flush
! 1591: * them afterwards */
! 1592: if (!has_condition(this, COND_ONLINE_VALIDATION_SUSPENDED))
! 1593: {
! 1594: this->flush_auth_cfg = FALSE;
! 1595: flush_auth_cfgs(this);
! 1596: }
! 1597: }
! 1598: return status;
! 1599: }
! 1600:
! 1601: METHOD(ike_sa_t, get_id, ike_sa_id_t*,
! 1602: private_ike_sa_t *this)
! 1603: {
! 1604: return this->ike_sa_id;
! 1605: }
! 1606:
! 1607: METHOD(ike_sa_t, get_version, ike_version_t,
! 1608: private_ike_sa_t *this)
! 1609: {
! 1610: return this->version;
! 1611: }
! 1612:
! 1613: METHOD(ike_sa_t, get_my_id, identification_t*,
! 1614: private_ike_sa_t *this)
! 1615: {
! 1616: return this->my_id;
! 1617: }
! 1618:
! 1619: METHOD(ike_sa_t, set_my_id, void,
! 1620: private_ike_sa_t *this, identification_t *me)
! 1621: {
! 1622: DESTROY_IF(this->my_id);
! 1623: this->my_id = me;
! 1624: }
! 1625:
! 1626: METHOD(ike_sa_t, get_other_id, identification_t*,
! 1627: private_ike_sa_t *this)
! 1628: {
! 1629: return this->other_id;
! 1630: }
! 1631:
! 1632: METHOD(ike_sa_t, get_other_eap_id, identification_t*,
! 1633: private_ike_sa_t *this)
! 1634: {
! 1635: identification_t *id = NULL, *current;
! 1636: enumerator_t *enumerator;
! 1637: auth_cfg_t *cfg;
! 1638:
! 1639: enumerator = array_create_enumerator(this->other_auths);
! 1640: while (enumerator->enumerate(enumerator, &cfg))
! 1641: {
! 1642: /* prefer EAP-Identity of last round */
! 1643: current = cfg->get(cfg, AUTH_RULE_EAP_IDENTITY);
! 1644: if (!current || current->get_type(current) == ID_ANY)
! 1645: {
! 1646: current = cfg->get(cfg, AUTH_RULE_XAUTH_IDENTITY);
! 1647: }
! 1648: if (!current || current->get_type(current) == ID_ANY)
! 1649: {
! 1650: current = cfg->get(cfg, AUTH_RULE_IDENTITY);
! 1651: }
! 1652: if (current && current->get_type(current) != ID_ANY)
! 1653: {
! 1654: id = current;
! 1655: continue;
! 1656: }
! 1657: }
! 1658: enumerator->destroy(enumerator);
! 1659: if (id)
! 1660: {
! 1661: return id;
! 1662: }
! 1663: return this->other_id;
! 1664: }
! 1665:
! 1666: METHOD(ike_sa_t, set_other_id, void,
! 1667: private_ike_sa_t *this, identification_t *other)
! 1668: {
! 1669: DESTROY_IF(this->other_id);
! 1670: this->other_id = other;
! 1671: }
! 1672:
! 1673: METHOD(ike_sa_t, get_if_id, uint32_t,
! 1674: private_ike_sa_t *this, bool inbound)
! 1675: {
! 1676: return inbound ? this->if_id_in : this->if_id_out;
! 1677: }
! 1678:
! 1679: METHOD(ike_sa_t, add_child_sa, void,
! 1680: private_ike_sa_t *this, child_sa_t *child_sa)
! 1681: {
! 1682: array_insert_create(&this->child_sas, ARRAY_TAIL, child_sa);
! 1683: charon->child_sa_manager->add(charon->child_sa_manager,
! 1684: child_sa, &this->public);
! 1685: }
! 1686:
! 1687: METHOD(ike_sa_t, get_child_sa, child_sa_t*,
! 1688: private_ike_sa_t *this, protocol_id_t protocol, uint32_t spi, bool inbound)
! 1689: {
! 1690: enumerator_t *enumerator;
! 1691: child_sa_t *current, *found = NULL;
! 1692:
! 1693: enumerator = array_create_enumerator(this->child_sas);
! 1694: while (enumerator->enumerate(enumerator, (void**)¤t))
! 1695: {
! 1696: if (current->get_spi(current, inbound) == spi &&
! 1697: current->get_protocol(current) == protocol)
! 1698: {
! 1699: found = current;
! 1700: }
! 1701: }
! 1702: enumerator->destroy(enumerator);
! 1703: return found;
! 1704: }
! 1705:
! 1706: METHOD(ike_sa_t, get_child_count, int,
! 1707: private_ike_sa_t *this)
! 1708: {
! 1709: return array_count(this->child_sas);
! 1710: }
! 1711:
! 1712: /**
! 1713: * Private data of a create_child_sa_enumerator()
! 1714: */
! 1715: typedef struct {
! 1716: /** implements enumerator */
! 1717: enumerator_t public;
! 1718: /** inner array enumerator */
! 1719: enumerator_t *inner;
! 1720: /** current item */
! 1721: child_sa_t *current;
! 1722: } child_enumerator_t;
! 1723:
! 1724: METHOD(enumerator_t, child_enumerate, bool,
! 1725: child_enumerator_t *this, va_list args)
! 1726: {
! 1727: child_sa_t **child_sa;
! 1728:
! 1729: VA_ARGS_VGET(args, child_sa);
! 1730: if (this->inner->enumerate(this->inner, &this->current))
! 1731: {
! 1732: *child_sa = this->current;
! 1733: return TRUE;
! 1734: }
! 1735: return FALSE;
! 1736: }
! 1737:
! 1738: METHOD(enumerator_t, child_enumerator_destroy, void,
! 1739: child_enumerator_t *this)
! 1740: {
! 1741: this->inner->destroy(this->inner);
! 1742: free(this);
! 1743: }
! 1744:
! 1745: METHOD(ike_sa_t, create_child_sa_enumerator, enumerator_t*,
! 1746: private_ike_sa_t *this)
! 1747: {
! 1748: child_enumerator_t *enumerator;
! 1749:
! 1750: INIT(enumerator,
! 1751: .public = {
! 1752: .enumerate = enumerator_enumerate_default,
! 1753: .venumerate = _child_enumerate,
! 1754: .destroy = _child_enumerator_destroy,
! 1755: },
! 1756: .inner = array_create_enumerator(this->child_sas),
! 1757: );
! 1758: return &enumerator->public;
! 1759: }
! 1760:
! 1761: METHOD(ike_sa_t, remove_child_sa, void,
! 1762: private_ike_sa_t *this, enumerator_t *enumerator)
! 1763: {
! 1764: child_enumerator_t *ce = (child_enumerator_t*)enumerator;
! 1765:
! 1766: charon->child_sa_manager->remove(charon->child_sa_manager, ce->current);
! 1767: array_remove_at(this->child_sas, ce->inner);
! 1768: }
! 1769:
! 1770: METHOD(ike_sa_t, rekey_child_sa, status_t,
! 1771: private_ike_sa_t *this, protocol_id_t protocol, uint32_t spi)
! 1772: {
! 1773: if (this->state == IKE_PASSIVE)
! 1774: {
! 1775: return INVALID_STATE;
! 1776: }
! 1777: this->task_manager->queue_child_rekey(this->task_manager, protocol, spi);
! 1778: return this->task_manager->initiate(this->task_manager);
! 1779: }
! 1780:
! 1781: METHOD(ike_sa_t, delete_child_sa, status_t,
! 1782: private_ike_sa_t *this, protocol_id_t protocol, uint32_t spi, bool expired)
! 1783: {
! 1784: if (this->state == IKE_PASSIVE)
! 1785: {
! 1786: return INVALID_STATE;
! 1787: }
! 1788: this->task_manager->queue_child_delete(this->task_manager,
! 1789: protocol, spi, expired);
! 1790: return this->task_manager->initiate(this->task_manager);
! 1791: }
! 1792:
! 1793: METHOD(ike_sa_t, destroy_child_sa, status_t,
! 1794: private_ike_sa_t *this, protocol_id_t protocol, uint32_t spi)
! 1795: {
! 1796: enumerator_t *enumerator;
! 1797: child_sa_t *child_sa;
! 1798: status_t status = NOT_FOUND;
! 1799:
! 1800: enumerator = create_child_sa_enumerator(this);
! 1801: while (enumerator->enumerate(enumerator, (void**)&child_sa))
! 1802: {
! 1803: if (child_sa->get_protocol(child_sa) == protocol &&
! 1804: child_sa->get_spi(child_sa, TRUE) == spi)
! 1805: {
! 1806: remove_child_sa(this, enumerator);
! 1807: child_sa->destroy(child_sa);
! 1808: status = SUCCESS;
! 1809: break;
! 1810: }
! 1811: }
! 1812: enumerator->destroy(enumerator);
! 1813: return status;
! 1814: }
! 1815:
! 1816: METHOD(ike_sa_t, delete_, status_t,
! 1817: private_ike_sa_t *this, bool force)
! 1818: {
! 1819: status_t status = DESTROY_ME;
! 1820:
! 1821: switch (this->state)
! 1822: {
! 1823: case IKE_ESTABLISHED:
! 1824: case IKE_REKEYING:
! 1825: if (time_monotonic(NULL) >= this->stats[STAT_DELETE] &&
! 1826: !(this->version == IKEV1 && this->state == IKE_REKEYING))
! 1827: { /* IKE_SA hard lifetime hit, ignored for reauthenticated
! 1828: * IKEv1 SAs */
! 1829: charon->bus->alert(charon->bus, ALERT_IKE_SA_EXPIRED);
! 1830: }
! 1831: this->task_manager->queue_ike_delete(this->task_manager);
! 1832: status = this->task_manager->initiate(this->task_manager);
! 1833: break;
! 1834: case IKE_CREATED:
! 1835: DBG1(DBG_IKE, "deleting unestablished IKE_SA");
! 1836: break;
! 1837: case IKE_PASSIVE:
! 1838: break;
! 1839: default:
! 1840: DBG1(DBG_IKE, "destroying IKE_SA in state %N without notification",
! 1841: ike_sa_state_names, this->state);
! 1842: force = TRUE;
! 1843: break;
! 1844: }
! 1845:
! 1846: if (force)
! 1847: {
! 1848: status = DESTROY_ME;
! 1849:
! 1850: if (this->version == IKEV2)
! 1851: { /* for IKEv1 we trigger this in the ISAKMP delete task */
! 1852: switch (this->state)
! 1853: {
! 1854: case IKE_ESTABLISHED:
! 1855: case IKE_REKEYING:
! 1856: case IKE_DELETING:
! 1857: charon->bus->ike_updown(charon->bus, &this->public, FALSE);
! 1858: default:
! 1859: break;
! 1860: }
! 1861: }
! 1862: }
! 1863: return status;
! 1864: }
! 1865:
! 1866: METHOD(ike_sa_t, rekey, status_t,
! 1867: private_ike_sa_t *this)
! 1868: {
! 1869: if (this->state == IKE_PASSIVE)
! 1870: {
! 1871: return INVALID_STATE;
! 1872: }
! 1873: this->task_manager->queue_ike_rekey(this->task_manager);
! 1874: return this->task_manager->initiate(this->task_manager);
! 1875: }
! 1876:
! 1877: METHOD(ike_sa_t, reauth, status_t,
! 1878: private_ike_sa_t *this)
! 1879: {
! 1880: if (this->state == IKE_PASSIVE)
! 1881: {
! 1882: return INVALID_STATE;
! 1883: }
! 1884: if (this->state == IKE_CONNECTING)
! 1885: {
! 1886: DBG0(DBG_IKE, "reinitiating IKE_SA %s[%d]",
! 1887: get_name(this), this->unique_id);
! 1888: reset(this, TRUE);
! 1889: return this->task_manager->initiate(this->task_manager);
! 1890: }
! 1891: /* we can't reauthenticate as responder when we use EAP or virtual IPs.
! 1892: * If the peer does not support RFC4478, there is no way to keep the
! 1893: * IKE_SA up. */
! 1894: if (!has_condition(this, COND_ORIGINAL_INITIATOR))
! 1895: {
! 1896: DBG1(DBG_IKE, "initiator did not reauthenticate as requested");
! 1897: if (array_count(this->other_vips) != 0 ||
! 1898: has_condition(this, COND_XAUTH_AUTHENTICATED) ||
! 1899: has_condition(this, COND_EAP_AUTHENTICATED)
! 1900: #ifdef ME
! 1901: /* as mediation server we too cannot reauth the IKE_SA */
! 1902: || this->is_mediation_server
! 1903: #endif /* ME */
! 1904: )
! 1905: {
! 1906: time_t del, now;
! 1907:
! 1908: del = this->stats[STAT_DELETE];
! 1909: now = time_monotonic(NULL);
! 1910: DBG1(DBG_IKE, "IKE_SA %s[%d] will timeout in %V",
! 1911: get_name(this), this->unique_id, &now, &del);
! 1912: return FAILED;
! 1913: }
! 1914: else
! 1915: {
! 1916: DBG0(DBG_IKE, "reauthenticating IKE_SA %s[%d] actively",
! 1917: get_name(this), this->unique_id);
! 1918: }
! 1919: }
! 1920: else
! 1921: {
! 1922: DBG0(DBG_IKE, "reauthenticating IKE_SA %s[%d]",
! 1923: get_name(this), this->unique_id);
! 1924: }
! 1925: set_condition(this, COND_REAUTHENTICATING, TRUE);
! 1926: this->task_manager->queue_ike_reauth(this->task_manager);
! 1927: return this->task_manager->initiate(this->task_manager);
! 1928: }
! 1929:
! 1930: /**
! 1931: * Check if any tasks of a specific type are queued in the given queue.
! 1932: */
! 1933: static bool is_task_queued(private_ike_sa_t *this, task_queue_t queue,
! 1934: task_type_t type)
! 1935: {
! 1936: enumerator_t *enumerator;
! 1937: task_t *task;
! 1938: bool found = FALSE;
! 1939:
! 1940: enumerator = this->task_manager->create_task_enumerator(this->task_manager,
! 1941: queue);
! 1942: while (enumerator->enumerate(enumerator, &task))
! 1943: {
! 1944: if (task->get_type(task) == type)
! 1945: {
! 1946: found = TRUE;
! 1947: break;
! 1948: }
! 1949: }
! 1950: enumerator->destroy(enumerator);
! 1951: return found;
! 1952: }
! 1953:
! 1954: /**
! 1955: * Check if any tasks to create CHILD_SAs are queued in the given queue.
! 1956: */
! 1957: static bool is_child_queued(private_ike_sa_t *this, task_queue_t queue)
! 1958: {
! 1959: return is_task_queued(this, queue,
! 1960: this->version == IKEV1 ? TASK_QUICK_MODE : TASK_CHILD_CREATE);
! 1961: }
! 1962:
! 1963: /**
! 1964: * Check if any tasks to delete the IKE_SA are queued in the given queue.
! 1965: */
! 1966: static bool is_delete_queued(private_ike_sa_t *this, task_queue_t queue)
! 1967: {
! 1968: return is_task_queued(this, queue,
! 1969: this->version == IKEV1 ? TASK_ISAKMP_DELETE : TASK_IKE_DELETE);
! 1970: }
! 1971:
! 1972: /**
! 1973: * Reestablish CHILD_SAs and migrate queued tasks.
! 1974: *
! 1975: * If force is true all SAs are restarted, otherwise their close/dpd_action
! 1976: * is followed.
! 1977: */
! 1978: static status_t reestablish_children(private_ike_sa_t *this, ike_sa_t *new,
! 1979: bool force)
! 1980: {
! 1981: enumerator_t *enumerator;
! 1982: child_sa_t *child_sa;
! 1983: child_cfg_t *child_cfg;
! 1984: action_t action;
! 1985: status_t status = FAILED;
! 1986:
! 1987: /* handle existing CHILD_SAs */
! 1988: enumerator = create_child_sa_enumerator(this);
! 1989: while (enumerator->enumerate(enumerator, (void**)&child_sa))
! 1990: {
! 1991: switch (child_sa->get_state(child_sa))
! 1992: {
! 1993: case CHILD_REKEYED:
! 1994: case CHILD_DELETED:
! 1995: /* ignore CHILD_SAs in these states */
! 1996: continue;
! 1997: default:
! 1998: break;
! 1999: }
! 2000: if (force)
! 2001: {
! 2002: action = ACTION_RESTART;
! 2003: }
! 2004: else
! 2005: { /* only restart CHILD_SAs that are configured accordingly */
! 2006: if (this->state == IKE_DELETING)
! 2007: {
! 2008: action = child_sa->get_close_action(child_sa);
! 2009: }
! 2010: else
! 2011: {
! 2012: action = child_sa->get_dpd_action(child_sa);
! 2013: }
! 2014: }
! 2015: switch (action)
! 2016: {
! 2017: case ACTION_RESTART:
! 2018: child_cfg = child_sa->get_config(child_sa);
! 2019: DBG1(DBG_IKE, "restarting CHILD_SA %s",
! 2020: child_cfg->get_name(child_cfg));
! 2021: child_cfg->get_ref(child_cfg);
! 2022: status = new->initiate(new, child_cfg,
! 2023: child_sa->get_reqid(child_sa), NULL, NULL);
! 2024: break;
! 2025: default:
! 2026: continue;
! 2027: }
! 2028: if (status == DESTROY_ME)
! 2029: {
! 2030: break;
! 2031: }
! 2032: }
! 2033: enumerator->destroy(enumerator);
! 2034: /* adopt any active or queued CHILD-creating tasks */
! 2035: if (status != DESTROY_ME)
! 2036: {
! 2037: new->adopt_child_tasks(new, &this->public);
! 2038: if (new->get_state(new) == IKE_CREATED)
! 2039: {
! 2040: status = new->initiate(new, NULL, 0, NULL, NULL);
! 2041: }
! 2042: }
! 2043: return status;
! 2044: }
! 2045:
! 2046: METHOD(ike_sa_t, reestablish, status_t,
! 2047: private_ike_sa_t *this)
! 2048: {
! 2049: ike_sa_t *new;
! 2050: host_t *host;
! 2051: action_t action;
! 2052: enumerator_t *enumerator;
! 2053: child_sa_t *child_sa;
! 2054: bool restart = FALSE;
! 2055: status_t status = FAILED;
! 2056:
! 2057: if (is_delete_queued(this, TASK_QUEUE_QUEUED))
! 2058: { /* don't reestablish IKE_SAs that have explicitly been deleted in the
! 2059: * mean time */
! 2060: return FAILED;
! 2061: }
! 2062:
! 2063: if (has_condition(this, COND_REAUTHENTICATING))
! 2064: { /* only reauthenticate if we have children */
! 2065: if (array_count(this->child_sas) == 0
! 2066: #ifdef ME
! 2067: /* allow reauth of mediation connections without CHILD_SAs */
! 2068: && !this->peer_cfg->is_mediation(this->peer_cfg)
! 2069: #endif /* ME */
! 2070: )
! 2071: {
! 2072: DBG1(DBG_IKE, "unable to reauthenticate IKE_SA, no CHILD_SA "
! 2073: "to recreate");
! 2074: }
! 2075: else
! 2076: {
! 2077: restart = TRUE;
! 2078: }
! 2079: }
! 2080: else
! 2081: { /* check if we have children to keep up at all */
! 2082: enumerator = array_create_enumerator(this->child_sas);
! 2083: while (enumerator->enumerate(enumerator, (void**)&child_sa))
! 2084: {
! 2085: switch (child_sa->get_state(child_sa))
! 2086: {
! 2087: case CHILD_REKEYED:
! 2088: case CHILD_DELETED:
! 2089: /* ignore CHILD_SAs in these states */
! 2090: continue;
! 2091: default:
! 2092: break;
! 2093: }
! 2094: if (this->state == IKE_DELETING)
! 2095: {
! 2096: action = child_sa->get_close_action(child_sa);
! 2097: }
! 2098: else
! 2099: {
! 2100: action = child_sa->get_dpd_action(child_sa);
! 2101: }
! 2102: switch (action)
! 2103: {
! 2104: case ACTION_RESTART:
! 2105: restart = TRUE;
! 2106: break;
! 2107: case ACTION_ROUTE:
! 2108: charon->traps->install(charon->traps, this->peer_cfg,
! 2109: child_sa->get_config(child_sa));
! 2110: break;
! 2111: default:
! 2112: break;
! 2113: }
! 2114: }
! 2115: enumerator->destroy(enumerator);
! 2116: /* check if we have tasks that recreate children */
! 2117: if (!restart)
! 2118: {
! 2119: restart = is_child_queued(this, TASK_QUEUE_ACTIVE) ||
! 2120: is_child_queued(this, TASK_QUEUE_QUEUED);
! 2121: }
! 2122: #ifdef ME
! 2123: /* mediation connections have no children, keep them up anyway */
! 2124: if (this->peer_cfg->is_mediation(this->peer_cfg))
! 2125: {
! 2126: restart = TRUE;
! 2127: }
! 2128: #endif /* ME */
! 2129: }
! 2130: if (!restart)
! 2131: {
! 2132: return FAILED;
! 2133: }
! 2134:
! 2135: /* check if we are able to reestablish this IKE_SA */
! 2136: if (!has_condition(this, COND_ORIGINAL_INITIATOR) &&
! 2137: (array_count(this->other_vips) != 0 ||
! 2138: has_condition(this, COND_EAP_AUTHENTICATED)
! 2139: #ifdef ME
! 2140: || this->is_mediation_server
! 2141: #endif /* ME */
! 2142: ))
! 2143: {
! 2144: DBG1(DBG_IKE, "unable to reestablish IKE_SA due to asymmetric setup");
! 2145: return FAILED;
! 2146: }
! 2147:
! 2148: new = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager,
! 2149: this->version, TRUE);
! 2150: if (!new)
! 2151: {
! 2152: return FAILED;
! 2153: }
! 2154: new->set_peer_cfg(new, this->peer_cfg);
! 2155: host = this->other_host;
! 2156: new->set_other_host(new, host->clone(host));
! 2157: host = this->my_host;
! 2158: new->set_my_host(new, host->clone(host));
! 2159: charon->bus->ike_reestablish_pre(charon->bus, &this->public, new);
! 2160: if (!has_condition(this, COND_REAUTHENTICATING))
! 2161: { /* reauthenticate to the same addresses, but resolve hosts if
! 2162: * reestablishing (old addresses serve as fallback) */
! 2163: resolve_hosts((private_ike_sa_t*)new);
! 2164: }
! 2165: /* if we already have a virtual IP, we reuse it */
! 2166: enumerator = array_create_enumerator(this->my_vips);
! 2167: while (enumerator->enumerate(enumerator, &host))
! 2168: {
! 2169: new->add_virtual_ip(new, TRUE, host);
! 2170: }
! 2171: enumerator->destroy(enumerator);
! 2172:
! 2173: #ifdef ME
! 2174: if (this->peer_cfg->is_mediation(this->peer_cfg))
! 2175: {
! 2176: status = new->initiate(new, NULL, 0, NULL, NULL);
! 2177: }
! 2178: else
! 2179: #endif /* ME */
! 2180: {
! 2181: status = reestablish_children(this, new,
! 2182: has_condition(this, COND_REAUTHENTICATING));
! 2183: }
! 2184:
! 2185: if (status == DESTROY_ME)
! 2186: {
! 2187: charon->bus->ike_reestablish_post(charon->bus, &this->public, new,
! 2188: FALSE);
! 2189: charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, new);
! 2190: status = FAILED;
! 2191: }
! 2192: else
! 2193: {
! 2194: charon->bus->ike_reestablish_post(charon->bus, &this->public, new,
! 2195: TRUE);
! 2196: charon->ike_sa_manager->checkin(charon->ike_sa_manager, new);
! 2197: status = SUCCESS;
! 2198: }
! 2199: charon->bus->set_sa(charon->bus, &this->public);
! 2200: return status;
! 2201: }
! 2202:
! 2203: /**
! 2204: * Resolve the given gateway ID
! 2205: */
! 2206: static host_t *resolve_gateway_id(identification_t *gateway)
! 2207: {
! 2208: char gw[BUF_LEN];
! 2209: host_t *addr;
! 2210:
! 2211: snprintf(gw, sizeof(gw), "%Y", gateway);
! 2212: gw[sizeof(gw)-1] = '\0';
! 2213: addr = host_create_from_dns(gw, AF_UNSPEC, IKEV2_UDP_PORT);
! 2214: if (!addr)
! 2215: {
! 2216: DBG1(DBG_IKE, "unable to resolve gateway ID '%Y', redirect failed",
! 2217: gateway);
! 2218: }
! 2219: return addr;
! 2220: }
! 2221:
! 2222: /**
! 2223: * Redirect the current SA to the given target host
! 2224: */
! 2225: static bool redirect_established(private_ike_sa_t *this, identification_t *to)
! 2226: {
! 2227: private_ike_sa_t *new_priv;
! 2228: ike_sa_t *new;
! 2229: host_t *other;
! 2230: time_t redirect;
! 2231:
! 2232: new = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager,
! 2233: this->version, TRUE);
! 2234: if (!new)
! 2235: {
! 2236: return FALSE;
! 2237: }
! 2238: new_priv = (private_ike_sa_t*)new;
! 2239: new->set_peer_cfg(new, this->peer_cfg);
! 2240: new_priv->redirected_from = this->other_host->clone(this->other_host);
! 2241: charon->bus->ike_reestablish_pre(charon->bus, &this->public, new);
! 2242: other = resolve_gateway_id(to);
! 2243: if (other)
! 2244: {
! 2245: set_my_host(new_priv, this->my_host->clone(this->my_host));
! 2246: /* this allows us to force the remote address while we still properly
! 2247: * resolve the local address */
! 2248: new_priv->remote_host = other;
! 2249: resolve_hosts(new_priv);
! 2250: new_priv->redirected_at = array_create(sizeof(time_t), MAX_REDIRECTS);
! 2251: while (array_remove(this->redirected_at, ARRAY_HEAD, &redirect))
! 2252: {
! 2253: array_insert(new_priv->redirected_at, ARRAY_TAIL, &redirect);
! 2254: }
! 2255: if (reestablish_children(this, new, TRUE) != DESTROY_ME)
! 2256: {
! 2257: #ifdef USE_IKEV2
! 2258: new->queue_task(new, (task_t*)ike_reauth_complete_create(new,
! 2259: this->ike_sa_id));
! 2260: #endif
! 2261: charon->bus->ike_reestablish_post(charon->bus, &this->public, new,
! 2262: TRUE);
! 2263: charon->ike_sa_manager->checkin(charon->ike_sa_manager, new);
! 2264: charon->bus->set_sa(charon->bus, &this->public);
! 2265: return TRUE;
! 2266: }
! 2267: }
! 2268: charon->bus->ike_reestablish_post(charon->bus, &this->public, new,
! 2269: FALSE);
! 2270: charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, new);
! 2271: charon->bus->set_sa(charon->bus, &this->public);
! 2272: return FALSE;
! 2273: }
! 2274:
! 2275: /**
! 2276: * Redirect the current connecting SA to the given target host
! 2277: */
! 2278: static bool redirect_connecting(private_ike_sa_t *this, identification_t *to)
! 2279: {
! 2280: host_t *other;
! 2281:
! 2282: other = resolve_gateway_id(to);
! 2283: if (!other)
! 2284: {
! 2285: return FALSE;
! 2286: }
! 2287: reset(this, TRUE);
! 2288: DESTROY_IF(this->redirected_from);
! 2289: this->redirected_from = this->other_host->clone(this->other_host);
! 2290: DESTROY_IF(this->remote_host);
! 2291: /* this allows us to force the remote address while we still properly
! 2292: * resolve the local address */
! 2293: this->remote_host = other;
! 2294: resolve_hosts(this);
! 2295: return TRUE;
! 2296: }
! 2297:
! 2298: /**
! 2299: * Check if the current redirect exceeds the limits for redirects
! 2300: */
! 2301: static bool redirect_count_exceeded(private_ike_sa_t *this)
! 2302: {
! 2303: time_t now, redirect;
! 2304:
! 2305: now = time_monotonic(NULL);
! 2306: /* remove entries outside the defined period */
! 2307: while (array_get(this->redirected_at, ARRAY_HEAD, &redirect) &&
! 2308: now - redirect >= REDIRECT_LOOP_DETECT_PERIOD)
! 2309: {
! 2310: array_remove(this->redirected_at, ARRAY_HEAD, NULL);
! 2311: }
! 2312: if (array_count(this->redirected_at) < MAX_REDIRECTS)
! 2313: {
! 2314: if (!this->redirected_at)
! 2315: {
! 2316: this->redirected_at = array_create(sizeof(time_t), MAX_REDIRECTS);
! 2317: }
! 2318: array_insert(this->redirected_at, ARRAY_TAIL, &now);
! 2319: return FALSE;
! 2320: }
! 2321: return TRUE;
! 2322: }
! 2323:
! 2324: METHOD(ike_sa_t, handle_redirect, bool,
! 2325: private_ike_sa_t *this, identification_t *gateway)
! 2326: {
! 2327: DBG1(DBG_IKE, "redirected to %Y", gateway);
! 2328: if (!this->follow_redirects)
! 2329: {
! 2330: DBG1(DBG_IKE, "server sent REDIRECT even though we disabled it");
! 2331: return FALSE;
! 2332: }
! 2333: if (redirect_count_exceeded(this))
! 2334: {
! 2335: DBG1(DBG_IKE, "only %d redirects are allowed within %d seconds",
! 2336: MAX_REDIRECTS, REDIRECT_LOOP_DETECT_PERIOD);
! 2337: return FALSE;
! 2338: }
! 2339:
! 2340: switch (this->state)
! 2341: {
! 2342: case IKE_CONNECTING:
! 2343: return redirect_connecting(this, gateway);
! 2344: case IKE_ESTABLISHED:
! 2345: return redirect_established(this, gateway);
! 2346: default:
! 2347: DBG1(DBG_IKE, "unable to handle redirect for IKE_SA in state %N",
! 2348: ike_sa_state_names, this->state);
! 2349: return FALSE;
! 2350: }
! 2351: }
! 2352:
! 2353: METHOD(ike_sa_t, redirect, status_t,
! 2354: private_ike_sa_t *this, identification_t *gateway)
! 2355: {
! 2356: switch (this->state)
! 2357: {
! 2358: case IKE_CONNECTING:
! 2359: case IKE_ESTABLISHED:
! 2360: case IKE_REKEYING:
! 2361: if (has_condition(this, COND_REDIRECTED))
! 2362: { /* IKE_SA already got redirected */
! 2363: return SUCCESS;
! 2364: }
! 2365: if (has_condition(this, COND_ORIGINAL_INITIATOR))
! 2366: {
! 2367: DBG1(DBG_IKE, "unable to redirect IKE_SA as initiator");
! 2368: return FAILED;
! 2369: }
! 2370: if (this->version == IKEV1)
! 2371: {
! 2372: DBG1(DBG_IKE, "unable to redirect IKEv1 SA");
! 2373: return FAILED;
! 2374: }
! 2375: if (!supports_extension(this, EXT_IKE_REDIRECTION))
! 2376: {
! 2377: DBG1(DBG_IKE, "client does not support IKE redirection");
! 2378: return FAILED;
! 2379: }
! 2380: #ifdef USE_IKEV2
! 2381: this->task_manager->queue_task(this->task_manager,
! 2382: (task_t*)ike_redirect_create(&this->public, gateway));
! 2383: #endif
! 2384: return this->task_manager->initiate(this->task_manager);
! 2385: default:
! 2386: DBG1(DBG_IKE, "unable to redirect IKE_SA in state %N",
! 2387: ike_sa_state_names, this->state);
! 2388: return INVALID_STATE;
! 2389: }
! 2390: }
! 2391:
! 2392: METHOD(ike_sa_t, retransmit, status_t,
! 2393: private_ike_sa_t *this, uint32_t message_id)
! 2394: {
! 2395: if (this->state == IKE_PASSIVE)
! 2396: {
! 2397: return INVALID_STATE;
! 2398: }
! 2399: this->stats[STAT_OUTBOUND] = time_monotonic(NULL);
! 2400: if (this->task_manager->retransmit(this->task_manager, message_id) != SUCCESS)
! 2401: {
! 2402: /* send a proper signal to brief interested bus listeners */
! 2403: switch (this->state)
! 2404: {
! 2405: case IKE_CONNECTING:
! 2406: {
! 2407: /* retry IKE_SA_INIT/Main Mode if we have multiple keyingtries */
! 2408: uint32_t tries = this->peer_cfg->get_keyingtries(this->peer_cfg);
! 2409: charon->bus->alert(charon->bus, ALERT_PEER_INIT_UNREACHABLE,
! 2410: this->keyingtry);
! 2411: this->keyingtry++;
! 2412: if (tries == 0 || tries > this->keyingtry)
! 2413: {
! 2414: DBG1(DBG_IKE, "peer not responding, trying again (%d/%d)",
! 2415: this->keyingtry + 1, tries);
! 2416: reset(this, TRUE);
! 2417: resolve_hosts(this);
! 2418: return this->task_manager->initiate(this->task_manager);
! 2419: }
! 2420: DBG1(DBG_IKE, "establishing IKE_SA failed, peer not responding");
! 2421:
! 2422: if (this->version == IKEV1 && array_count(this->child_sas))
! 2423: {
! 2424: enumerator_t *enumerator;
! 2425: child_sa_t *child_sa;
! 2426:
! 2427: /* if reauthenticating an IKEv1 SA failed (assumed for an SA
! 2428: * in this state with CHILD_SAs), try again from scratch */
! 2429: DBG1(DBG_IKE, "reauthentication failed, trying to "
! 2430: "reestablish IKE_SA");
! 2431: reestablish(this);
! 2432: /* trigger down events for the CHILD_SAs, as no down event
! 2433: * is triggered below for IKE SAs in this state */
! 2434: enumerator = array_create_enumerator(this->child_sas);
! 2435: while (enumerator->enumerate(enumerator, &child_sa))
! 2436: {
! 2437: if (child_sa->get_state(child_sa) != CHILD_REKEYED &&
! 2438: child_sa->get_state(child_sa) != CHILD_DELETED)
! 2439: {
! 2440: charon->bus->child_updown(charon->bus, child_sa,
! 2441: FALSE);
! 2442: }
! 2443: }
! 2444: enumerator->destroy(enumerator);
! 2445: }
! 2446: break;
! 2447: }
! 2448: case IKE_DELETING:
! 2449: DBG1(DBG_IKE, "proper IKE_SA delete failed, peer not responding");
! 2450: if (has_condition(this, COND_REAUTHENTICATING) &&
! 2451: !lib->settings->get_bool(lib->settings,
! 2452: "%s.make_before_break", FALSE, lib->ns))
! 2453: {
! 2454: DBG1(DBG_IKE, "delete during reauthentication failed, "
! 2455: "trying to reestablish IKE_SA anyway");
! 2456: reestablish(this);
! 2457: }
! 2458: break;
! 2459: case IKE_REKEYING:
! 2460: DBG1(DBG_IKE, "rekeying IKE_SA failed, peer not responding");
! 2461: /* FALL */
! 2462: default:
! 2463: reestablish(this);
! 2464: break;
! 2465: }
! 2466: if (this->state != IKE_CONNECTING &&
! 2467: this->state != IKE_REKEYED)
! 2468: {
! 2469: charon->bus->ike_updown(charon->bus, &this->public, FALSE);
! 2470: }
! 2471: return DESTROY_ME;
! 2472: }
! 2473: return SUCCESS;
! 2474: }
! 2475:
! 2476: METHOD(ike_sa_t, set_auth_lifetime, status_t,
! 2477: private_ike_sa_t *this, uint32_t lifetime)
! 2478: {
! 2479: uint32_t diff, hard, soft, now;
! 2480: bool send_update;
! 2481:
! 2482: diff = this->peer_cfg->get_over_time(this->peer_cfg);
! 2483: now = time_monotonic(NULL);
! 2484: hard = now + lifetime;
! 2485: soft = hard - diff;
! 2486:
! 2487: /* check if we have to send an AUTH_LIFETIME to enforce the new lifetime.
! 2488: * We send the notify in IKE_AUTH if not yet ESTABLISHED. */
! 2489: send_update = this->state == IKE_ESTABLISHED && this->version == IKEV2 &&
! 2490: !has_condition(this, COND_ORIGINAL_INITIATOR) &&
! 2491: (array_count(this->other_vips) != 0 ||
! 2492: has_condition(this, COND_EAP_AUTHENTICATED));
! 2493:
! 2494: if (lifetime < diff)
! 2495: {
! 2496: this->stats[STAT_REAUTH] = now;
! 2497:
! 2498: if (!send_update)
! 2499: {
! 2500: DBG1(DBG_IKE, "received AUTH_LIFETIME of %ds, "
! 2501: "starting reauthentication", lifetime);
! 2502: lib->processor->queue_job(lib->processor,
! 2503: (job_t*)rekey_ike_sa_job_create(this->ike_sa_id, TRUE));
! 2504: }
! 2505: }
! 2506: else if (this->stats[STAT_REAUTH] == 0 ||
! 2507: this->stats[STAT_REAUTH] > soft)
! 2508: {
! 2509: this->stats[STAT_REAUTH] = soft;
! 2510: if (!send_update)
! 2511: {
! 2512: DBG1(DBG_IKE, "received AUTH_LIFETIME of %ds, scheduling "
! 2513: "reauthentication in %ds", lifetime, lifetime - diff);
! 2514: lib->scheduler->schedule_job(lib->scheduler,
! 2515: (job_t*)rekey_ike_sa_job_create(this->ike_sa_id, TRUE),
! 2516: lifetime - diff);
! 2517: }
! 2518: }
! 2519: else
! 2520: {
! 2521: DBG1(DBG_IKE, "received AUTH_LIFETIME of %ds, "
! 2522: "reauthentication already scheduled in %ds", lifetime,
! 2523: this->stats[STAT_REAUTH] - time_monotonic(NULL));
! 2524: send_update = FALSE;
! 2525: }
! 2526: /* give at least some seconds to reauthenticate */
! 2527: this->stats[STAT_DELETE] = max(hard, now + 10);
! 2528:
! 2529: #ifdef USE_IKEV2
! 2530: if (send_update)
! 2531: {
! 2532: ike_auth_lifetime_t *task;
! 2533:
! 2534: task = ike_auth_lifetime_create(&this->public, TRUE);
! 2535: this->task_manager->queue_task(this->task_manager, &task->task);
! 2536: return this->task_manager->initiate(this->task_manager);
! 2537: }
! 2538: #endif
! 2539: return SUCCESS;
! 2540: }
! 2541:
! 2542: /**
! 2543: * Check if the current combination of source and destination address is still
! 2544: * valid.
! 2545: */
! 2546: static bool is_current_path_valid(private_ike_sa_t *this)
! 2547: {
! 2548: bool valid = FALSE;
! 2549: host_t *src;
! 2550:
! 2551: if (supports_extension(this, EXT_MOBIKE) &&
! 2552: lib->settings->get_bool(lib->settings,
! 2553: "%s.prefer_best_path", FALSE, lib->ns))
! 2554: {
! 2555: /* check if the current path is the best path; migrate otherwise */
! 2556: src = charon->kernel->get_source_addr(charon->kernel, this->other_host,
! 2557: NULL);
! 2558: if (src)
! 2559: {
! 2560: valid = src->ip_equals(src, this->my_host);
! 2561: src->destroy(src);
! 2562: }
! 2563: if (!valid)
! 2564: {
! 2565: DBG1(DBG_IKE, "old path is not preferred anymore");
! 2566: }
! 2567: return valid;
! 2568: }
! 2569: src = charon->kernel->get_source_addr(charon->kernel, this->other_host,
! 2570: this->my_host);
! 2571: if (src)
! 2572: {
! 2573: if (src->ip_equals(src, this->my_host))
! 2574: {
! 2575: valid = TRUE;
! 2576: }
! 2577: src->destroy(src);
! 2578: }
! 2579: if (!valid)
! 2580: {
! 2581: DBG1(DBG_IKE, "old path is not available anymore, try to find another");
! 2582: }
! 2583: return valid;
! 2584: }
! 2585:
! 2586: /**
! 2587: * Check if we have any path available for this IKE SA.
! 2588: */
! 2589: static bool is_any_path_valid(private_ike_sa_t *this)
! 2590: {
! 2591: bool valid = FALSE;
! 2592: enumerator_t *enumerator;
! 2593: host_t *src = NULL, *addr;
! 2594: int family = AF_UNSPEC;
! 2595:
! 2596: switch (charon->socket->supported_families(charon->socket))
! 2597: {
! 2598: case SOCKET_FAMILY_IPV4:
! 2599: family = AF_INET;
! 2600: break;
! 2601: case SOCKET_FAMILY_IPV6:
! 2602: family = AF_INET6;
! 2603: break;
! 2604: case SOCKET_FAMILY_BOTH:
! 2605: case SOCKET_FAMILY_NONE:
! 2606: break;
! 2607: }
! 2608:
! 2609: enumerator = create_peer_address_enumerator(this);
! 2610: while (enumerator->enumerate(enumerator, &addr))
! 2611: {
! 2612: if (family != AF_UNSPEC && addr->get_family(addr) != family)
! 2613: {
! 2614: continue;
! 2615: }
! 2616: DBG1(DBG_IKE, "looking for a route to %H ...", addr);
! 2617: src = charon->kernel->get_source_addr(charon->kernel, addr, NULL);
! 2618: if (src)
! 2619: {
! 2620: break;
! 2621: }
! 2622: }
! 2623: enumerator->destroy(enumerator);
! 2624: if (src)
! 2625: {
! 2626: valid = TRUE;
! 2627: src->destroy(src);
! 2628: }
! 2629: return valid;
! 2630: }
! 2631:
! 2632: METHOD(ike_sa_t, roam, status_t,
! 2633: private_ike_sa_t *this, bool address)
! 2634: {
! 2635: switch (this->state)
! 2636: {
! 2637: case IKE_CREATED:
! 2638: case IKE_DELETING:
! 2639: case IKE_DESTROYING:
! 2640: case IKE_PASSIVE:
! 2641: case IKE_REKEYED:
! 2642: return SUCCESS;
! 2643: default:
! 2644: break;
! 2645: }
! 2646:
! 2647: if (!this->ike_cfg)
! 2648: { /* this is the case for new HA SAs not yet in state IKE_PASSIVE and
! 2649: * without config assigned */
! 2650: return SUCCESS;
! 2651: }
! 2652: if (this->version == IKEV1)
! 2653: { /* ignore roam events for IKEv1 where we don't have MOBIKE and would
! 2654: * have to reestablish from scratch (reauth is not enough) */
! 2655: return SUCCESS;
! 2656: }
! 2657:
! 2658: /* ignore roam events if MOBIKE is not supported/enabled and the local
! 2659: * address is statically configured */
! 2660: if (!supports_extension(this, EXT_MOBIKE) &&
! 2661: ike_cfg_has_address(this->ike_cfg, this->my_host, TRUE))
! 2662: {
! 2663: DBG2(DBG_IKE, "keeping statically configured path %H - %H",
! 2664: this->my_host, this->other_host);
! 2665: return SUCCESS;
! 2666: }
! 2667:
! 2668: /* keep existing path if possible */
! 2669: if (is_current_path_valid(this))
! 2670: {
! 2671: DBG2(DBG_IKE, "keeping connection path %H - %H",
! 2672: this->my_host, this->other_host);
! 2673: set_condition(this, COND_STALE, FALSE);
! 2674:
! 2675: if (supports_extension(this, EXT_MOBIKE) && address)
! 2676: { /* if any addresses changed, send an updated list */
! 2677: DBG1(DBG_IKE, "sending address list update using MOBIKE");
! 2678: this->task_manager->queue_mobike(this->task_manager, FALSE, TRUE);
! 2679: return this->task_manager->initiate(this->task_manager);
! 2680: }
! 2681: return SUCCESS;
! 2682: }
! 2683:
! 2684: if (!is_any_path_valid(this))
! 2685: {
! 2686: DBG1(DBG_IKE, "no route found to reach %H, MOBIKE update deferred",
! 2687: this->other_host);
! 2688: set_condition(this, COND_STALE, TRUE);
! 2689: return SUCCESS;
! 2690: }
! 2691: set_condition(this, COND_STALE, FALSE);
! 2692:
! 2693: /* update addresses with mobike, if supported ... */
! 2694: if (supports_extension(this, EXT_MOBIKE))
! 2695: {
! 2696: if (!has_condition(this, COND_ORIGINAL_INITIATOR))
! 2697: { /* responder updates the peer about changed address config */
! 2698: DBG1(DBG_IKE, "sending address list update using MOBIKE, "
! 2699: "implicitly requesting an address change");
! 2700: address = TRUE;
! 2701: }
! 2702: else
! 2703: {
! 2704: DBG1(DBG_IKE, "requesting address change using MOBIKE");
! 2705: }
! 2706: this->task_manager->queue_mobike(this->task_manager, TRUE, address);
! 2707: return this->task_manager->initiate(this->task_manager);
! 2708: }
! 2709:
! 2710: /* ... reauth if not */
! 2711: if (!has_condition(this, COND_ORIGINAL_INITIATOR))
! 2712: { /* responder does not reauthenticate */
! 2713: set_condition(this, COND_STALE, TRUE);
! 2714: return SUCCESS;
! 2715: }
! 2716: DBG1(DBG_IKE, "reauthenticating IKE_SA due to address change");
! 2717: /* since our previous path is not valid anymore, try and find a new one */
! 2718: resolve_hosts(this);
! 2719: return reauth(this);
! 2720: }
! 2721:
! 2722: METHOD(ike_sa_t, add_configuration_attribute, void,
! 2723: private_ike_sa_t *this, attribute_handler_t *handler,
! 2724: configuration_attribute_type_t type, chunk_t data)
! 2725: {
! 2726: attribute_entry_t entry = {
! 2727: .handler = handler,
! 2728: .type = type,
! 2729: .data = chunk_clone(data),
! 2730: };
! 2731: array_insert(this->attributes, ARRAY_TAIL, &entry);
! 2732: }
! 2733:
! 2734: CALLBACK(filter_attribute, bool,
! 2735: void *null, enumerator_t *orig, va_list args)
! 2736: {
! 2737: attribute_entry_t *entry;
! 2738: configuration_attribute_type_t *type;
! 2739: chunk_t *data;
! 2740: bool *handled;
! 2741:
! 2742: VA_ARGS_VGET(args, type, data, handled);
! 2743:
! 2744: if (orig->enumerate(orig, &entry))
! 2745: {
! 2746: *type = entry->type;
! 2747: *data = entry->data;
! 2748: *handled = entry->handler != NULL;
! 2749: return TRUE;
! 2750: }
! 2751: return FALSE;
! 2752: }
! 2753:
! 2754: METHOD(ike_sa_t, create_attribute_enumerator, enumerator_t*,
! 2755: private_ike_sa_t *this)
! 2756: {
! 2757: return enumerator_create_filter(array_create_enumerator(this->attributes),
! 2758: filter_attribute, NULL, NULL);
! 2759: }
! 2760:
! 2761: METHOD(ike_sa_t, create_task_enumerator, enumerator_t*,
! 2762: private_ike_sa_t *this, task_queue_t queue)
! 2763: {
! 2764: return this->task_manager->create_task_enumerator(this->task_manager, queue);
! 2765: }
! 2766:
! 2767: METHOD(ike_sa_t, remove_task, void,
! 2768: private_ike_sa_t *this, enumerator_t *enumerator)
! 2769: {
! 2770: return this->task_manager->remove_task(this->task_manager, enumerator);
! 2771: }
! 2772:
! 2773: METHOD(ike_sa_t, flush_queue, void,
! 2774: private_ike_sa_t *this, task_queue_t queue)
! 2775: {
! 2776: this->task_manager->flush_queue(this->task_manager, queue);
! 2777: }
! 2778:
! 2779: METHOD(ike_sa_t, queue_task, void,
! 2780: private_ike_sa_t *this, task_t *task)
! 2781: {
! 2782: this->task_manager->queue_task(this->task_manager, task);
! 2783: }
! 2784:
! 2785: METHOD(ike_sa_t, queue_task_delayed, void,
! 2786: private_ike_sa_t *this, task_t *task, uint32_t delay)
! 2787: {
! 2788: this->task_manager->queue_task_delayed(this->task_manager, task, delay);
! 2789: }
! 2790:
! 2791: /**
! 2792: * Migrate and queue child-creating tasks from another IKE_SA
! 2793: */
! 2794: static void migrate_child_tasks(private_ike_sa_t *this, ike_sa_t *other,
! 2795: task_queue_t queue)
! 2796: {
! 2797: enumerator_t *enumerator;
! 2798: task_t *task;
! 2799:
! 2800: enumerator = other->create_task_enumerator(other, queue);
! 2801: while (enumerator->enumerate(enumerator, &task))
! 2802: {
! 2803: if (task->get_type(task) == TASK_CHILD_CREATE ||
! 2804: task->get_type(task) == TASK_QUICK_MODE)
! 2805: {
! 2806: other->remove_task(other, enumerator);
! 2807: task->migrate(task, &this->public);
! 2808: queue_task(this, task);
! 2809: }
! 2810: }
! 2811: enumerator->destroy(enumerator);
! 2812: }
! 2813:
! 2814: METHOD(ike_sa_t, adopt_child_tasks, void,
! 2815: private_ike_sa_t *this, ike_sa_t *other)
! 2816: {
! 2817: migrate_child_tasks(this, other, TASK_QUEUE_ACTIVE);
! 2818: migrate_child_tasks(this, other, TASK_QUEUE_QUEUED);
! 2819: }
! 2820:
! 2821: METHOD(ike_sa_t, inherit_pre, void,
! 2822: private_ike_sa_t *this, ike_sa_t *other_public)
! 2823: {
! 2824: private_ike_sa_t *other = (private_ike_sa_t*)other_public;
! 2825:
! 2826: /* apply config and hosts */
! 2827: set_peer_cfg(this, other->peer_cfg);
! 2828: set_my_host(this, other->my_host->clone(other->my_host));
! 2829: set_other_host(this, other->other_host->clone(other->other_host));
! 2830:
! 2831: /* apply extensions and conditions with a few exceptions */
! 2832: this->extensions = other->extensions;
! 2833: this->conditions = other->conditions;
! 2834: this->conditions &= ~COND_STALE;
! 2835: this->conditions &= ~COND_REAUTHENTICATING;
! 2836: }
! 2837:
! 2838: METHOD(ike_sa_t, inherit_post, void,
! 2839: private_ike_sa_t *this, ike_sa_t *other_public)
! 2840: {
! 2841: private_ike_sa_t *other = (private_ike_sa_t*)other_public;
! 2842: child_sa_t *child_sa;
! 2843: enumerator_t *enumerator;
! 2844: attribute_entry_t entry;
! 2845: auth_cfg_t *cfg;
! 2846: host_t *vip;
! 2847:
! 2848: /* apply hosts and ids */
! 2849: this->my_host->destroy(this->my_host);
! 2850: this->other_host->destroy(this->other_host);
! 2851: this->my_id->destroy(this->my_id);
! 2852: this->other_id->destroy(this->other_id);
! 2853: this->my_host = other->my_host->clone(other->my_host);
! 2854: this->other_host = other->other_host->clone(other->other_host);
! 2855: this->my_id = other->my_id->clone(other->my_id);
! 2856: this->other_id = other->other_id->clone(other->other_id);
! 2857: this->if_id_in = other->if_id_in;
! 2858: this->if_id_out = other->if_id_out;
! 2859:
! 2860: /* apply assigned virtual IPs... */
! 2861: while (array_remove(other->my_vips, ARRAY_HEAD, &vip))
! 2862: {
! 2863: array_insert_create(&this->my_vips, ARRAY_TAIL, vip);
! 2864: }
! 2865: while (array_remove(other->other_vips, ARRAY_HEAD, &vip))
! 2866: {
! 2867: array_insert_create(&this->other_vips, ARRAY_TAIL, vip);
! 2868: }
! 2869:
! 2870: /* MOBIKE additional addresses */
! 2871: while (array_remove(other->peer_addresses, ARRAY_HEAD, &vip))
! 2872: {
! 2873: array_insert_create(&this->peer_addresses, ARRAY_TAIL, vip);
! 2874: }
! 2875:
! 2876: /* authentication information */
! 2877: enumerator = array_create_enumerator(other->my_auths);
! 2878: while (enumerator->enumerate(enumerator, &cfg))
! 2879: {
! 2880: array_insert(this->my_auths, ARRAY_TAIL, cfg->clone(cfg));
! 2881: }
! 2882: enumerator->destroy(enumerator);
! 2883: enumerator = array_create_enumerator(other->other_auths);
! 2884: while (enumerator->enumerate(enumerator, &cfg))
! 2885: {
! 2886: array_insert(this->other_auths, ARRAY_TAIL, cfg->clone(cfg));
! 2887: }
! 2888: enumerator->destroy(enumerator);
! 2889:
! 2890: /* ... and configuration attributes */
! 2891: while (array_remove(other->attributes, ARRAY_HEAD, &entry))
! 2892: {
! 2893: array_insert(this->attributes, ARRAY_TAIL, &entry);
! 2894: }
! 2895:
! 2896: /* inherit all conditions */
! 2897: this->conditions = other->conditions;
! 2898: if (this->conditions & COND_NAT_HERE)
! 2899: {
! 2900: send_keepalive(this, FALSE);
! 2901: }
! 2902:
! 2903: #ifdef ME
! 2904: if (other->is_mediation_server)
! 2905: {
! 2906: act_as_mediation_server(this);
! 2907: }
! 2908: else if (other->server_reflexive_host)
! 2909: {
! 2910: this->server_reflexive_host = other->server_reflexive_host->clone(
! 2911: other->server_reflexive_host);
! 2912: }
! 2913: #endif /* ME */
! 2914:
! 2915: /* adopt all children */
! 2916: while (array_remove(other->child_sas, ARRAY_HEAD, &child_sa))
! 2917: {
! 2918: charon->child_sa_manager->remove(charon->child_sa_manager, child_sa);
! 2919: add_child_sa(this, child_sa);
! 2920: }
! 2921:
! 2922: /* move pending tasks to the new IKE_SA */
! 2923: this->task_manager->adopt_tasks(this->task_manager, other->task_manager);
! 2924:
! 2925: /* reauthentication timeout survives a rekeying */
! 2926: if (other->stats[STAT_REAUTH])
! 2927: {
! 2928: time_t reauth, delete, now = time_monotonic(NULL);
! 2929:
! 2930: this->stats[STAT_REAUTH] = other->stats[STAT_REAUTH];
! 2931: reauth = this->stats[STAT_REAUTH] - now;
! 2932: delete = reauth + this->peer_cfg->get_over_time(this->peer_cfg);
! 2933: this->stats[STAT_DELETE] = this->stats[STAT_REAUTH] + delete;
! 2934: DBG1(DBG_IKE, "rescheduling reauthentication in %ds after rekeying, "
! 2935: "lifetime reduced to %ds", reauth, delete);
! 2936: lib->scheduler->schedule_job(lib->scheduler,
! 2937: (job_t*)rekey_ike_sa_job_create(this->ike_sa_id, TRUE), reauth);
! 2938: lib->scheduler->schedule_job(lib->scheduler,
! 2939: (job_t*)delete_ike_sa_job_create(this->ike_sa_id, TRUE), delete);
! 2940: }
! 2941: }
! 2942:
! 2943: METHOD(ike_sa_t, destroy, void,
! 2944: private_ike_sa_t *this)
! 2945: {
! 2946: attribute_entry_t entry;
! 2947: child_sa_t *child_sa;
! 2948: host_t *vip;
! 2949:
! 2950: charon->bus->set_sa(charon->bus, &this->public);
! 2951:
! 2952: set_state(this, IKE_DESTROYING);
! 2953: if (this->task_manager)
! 2954: {
! 2955: this->task_manager->flush(this->task_manager);
! 2956: }
! 2957:
! 2958: /* remove attributes first, as we pass the IKE_SA to the handler */
! 2959: charon->bus->handle_vips(charon->bus, &this->public, FALSE);
! 2960: while (array_remove(this->attributes, ARRAY_TAIL, &entry))
! 2961: {
! 2962: if (entry.handler)
! 2963: {
! 2964: charon->attributes->release(charon->attributes, entry.handler,
! 2965: &this->public, entry.type, entry.data);
! 2966: }
! 2967: free(entry.data.ptr);
! 2968: }
! 2969: /* uninstall CHILD_SAs before virtual IPs, otherwise we might kill
! 2970: * routes that the CHILD_SA tries to uninstall. */
! 2971: while (array_remove(this->child_sas, ARRAY_TAIL, &child_sa))
! 2972: {
! 2973: charon->child_sa_manager->remove(charon->child_sa_manager, child_sa);
! 2974: child_sa->destroy(child_sa);
! 2975: }
! 2976: while (array_remove(this->my_vips, ARRAY_TAIL, &vip))
! 2977: {
! 2978: charon->kernel->del_ip(charon->kernel, vip, -1, TRUE);
! 2979: vip->destroy(vip);
! 2980: }
! 2981: if (array_count(this->other_vips))
! 2982: {
! 2983: charon->bus->assign_vips(charon->bus, &this->public, FALSE);
! 2984: }
! 2985: while (array_remove(this->other_vips, ARRAY_TAIL, &vip))
! 2986: {
! 2987: if (this->peer_cfg)
! 2988: {
! 2989: linked_list_t *pools;
! 2990:
! 2991: pools = linked_list_create_from_enumerator(
! 2992: this->peer_cfg->create_pool_enumerator(this->peer_cfg));
! 2993: charon->attributes->release_address(charon->attributes,
! 2994: pools, vip, &this->public);
! 2995: pools->destroy(pools);
! 2996: }
! 2997: vip->destroy(vip);
! 2998: }
! 2999:
! 3000: /* unset SA after here to avoid usage by the listeners */
! 3001: charon->bus->set_sa(charon->bus, NULL);
! 3002:
! 3003: array_destroy(this->child_sas);
! 3004: DESTROY_IF(this->task_manager);
! 3005: DESTROY_IF(this->keymat);
! 3006: array_destroy(this->attributes);
! 3007: array_destroy(this->my_vips);
! 3008: array_destroy(this->other_vips);
! 3009: array_destroy_offset(this->peer_addresses, offsetof(host_t, destroy));
! 3010: #ifdef ME
! 3011: if (this->is_mediation_server)
! 3012: {
! 3013: charon->mediation_manager->remove(charon->mediation_manager,
! 3014: this->ike_sa_id);
! 3015: }
! 3016: DESTROY_IF(this->server_reflexive_host);
! 3017: chunk_free(&this->connect_id);
! 3018: #endif /* ME */
! 3019: free(this->nat_detection_dest.ptr);
! 3020:
! 3021: DESTROY_IF(this->my_host);
! 3022: DESTROY_IF(this->other_host);
! 3023: DESTROY_IF(this->my_id);
! 3024: DESTROY_IF(this->other_id);
! 3025: DESTROY_IF(this->local_host);
! 3026: DESTROY_IF(this->remote_host);
! 3027: DESTROY_IF(this->redirected_from);
! 3028: array_destroy(this->redirected_at);
! 3029:
! 3030: DESTROY_IF(this->ike_cfg);
! 3031: DESTROY_IF(this->peer_cfg);
! 3032: DESTROY_IF(this->proposal);
! 3033: this->my_auth->destroy(this->my_auth);
! 3034: this->other_auth->destroy(this->other_auth);
! 3035: array_destroy_offset(this->my_auths, offsetof(auth_cfg_t, destroy));
! 3036: array_destroy_offset(this->other_auths, offsetof(auth_cfg_t, destroy));
! 3037:
! 3038: this->ike_sa_id->destroy(this->ike_sa_id);
! 3039: free(this);
! 3040: }
! 3041:
! 3042: /*
! 3043: * Described in header.
! 3044: */
! 3045: ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator,
! 3046: ike_version_t version)
! 3047: {
! 3048: private_ike_sa_t *this;
! 3049: static refcount_t unique_id = 0;
! 3050:
! 3051: if (version == IKE_ANY)
! 3052: { /* prefer IKEv2 if protocol not specified */
! 3053: #ifdef USE_IKEV2
! 3054: version = IKEV2;
! 3055: #else
! 3056: version = IKEV1;
! 3057: #endif
! 3058: }
! 3059:
! 3060: INIT(this,
! 3061: .public = {
! 3062: .get_version = _get_version,
! 3063: .get_state = _get_state,
! 3064: .set_state = _set_state,
! 3065: .get_name = _get_name,
! 3066: .get_statistic = _get_statistic,
! 3067: .set_statistic = _set_statistic,
! 3068: .process_message = _process_message,
! 3069: .initiate = _initiate,
! 3070: .retry_initiate = _retry_initiate,
! 3071: .get_ike_cfg = _get_ike_cfg,
! 3072: .set_ike_cfg = _set_ike_cfg,
! 3073: .get_peer_cfg = _get_peer_cfg,
! 3074: .set_peer_cfg = _set_peer_cfg,
! 3075: .get_auth_cfg = _get_auth_cfg,
! 3076: .create_auth_cfg_enumerator = _create_auth_cfg_enumerator,
! 3077: .verify_peer_certificate = _verify_peer_certificate,
! 3078: .add_auth_cfg = _add_auth_cfg,
! 3079: .get_proposal = _get_proposal,
! 3080: .set_proposal = _set_proposal,
! 3081: .get_id = _get_id,
! 3082: .get_my_host = _get_my_host,
! 3083: .set_my_host = _set_my_host,
! 3084: .get_other_host = _get_other_host,
! 3085: .set_other_host = _set_other_host,
! 3086: .set_message_id = _set_message_id,
! 3087: .get_message_id = _get_message_id,
! 3088: .float_ports = _float_ports,
! 3089: .update_hosts = _update_hosts,
! 3090: .get_my_id = _get_my_id,
! 3091: .set_my_id = _set_my_id,
! 3092: .get_other_id = _get_other_id,
! 3093: .set_other_id = _set_other_id,
! 3094: .get_other_eap_id = _get_other_eap_id,
! 3095: .enable_extension = _enable_extension,
! 3096: .supports_extension = _supports_extension,
! 3097: .set_condition = _set_condition,
! 3098: .has_condition = _has_condition,
! 3099: .create_peer_address_enumerator = _create_peer_address_enumerator,
! 3100: .add_peer_address = _add_peer_address,
! 3101: .clear_peer_addresses = _clear_peer_addresses,
! 3102: .has_mapping_changed = _has_mapping_changed,
! 3103: .retransmit = _retransmit,
! 3104: .delete = _delete_,
! 3105: .destroy = _destroy,
! 3106: .send_dpd = _send_dpd,
! 3107: .send_keepalive = _send_keepalive,
! 3108: .redirect = _redirect,
! 3109: .handle_redirect = _handle_redirect,
! 3110: .get_redirected_from = _get_redirected_from,
! 3111: .get_keymat = _get_keymat,
! 3112: .add_child_sa = _add_child_sa,
! 3113: .get_child_sa = _get_child_sa,
! 3114: .get_child_count = _get_child_count,
! 3115: .create_child_sa_enumerator = _create_child_sa_enumerator,
! 3116: .remove_child_sa = _remove_child_sa,
! 3117: .rekey_child_sa = _rekey_child_sa,
! 3118: .delete_child_sa = _delete_child_sa,
! 3119: .destroy_child_sa = _destroy_child_sa,
! 3120: .rekey = _rekey,
! 3121: .reauth = _reauth,
! 3122: .reestablish = _reestablish,
! 3123: .set_auth_lifetime = _set_auth_lifetime,
! 3124: .roam = _roam,
! 3125: .inherit_pre = _inherit_pre,
! 3126: .inherit_post = _inherit_post,
! 3127: .generate_message = _generate_message,
! 3128: .generate_message_fragmented = _generate_message_fragmented,
! 3129: .reset = _reset,
! 3130: .get_unique_id = _get_unique_id,
! 3131: .add_virtual_ip = _add_virtual_ip,
! 3132: .clear_virtual_ips = _clear_virtual_ips,
! 3133: .create_virtual_ip_enumerator = _create_virtual_ip_enumerator,
! 3134: .add_configuration_attribute = _add_configuration_attribute,
! 3135: .create_attribute_enumerator = _create_attribute_enumerator,
! 3136: .get_if_id = _get_if_id,
! 3137: .set_kmaddress = _set_kmaddress,
! 3138: .create_task_enumerator = _create_task_enumerator,
! 3139: .remove_task = _remove_task,
! 3140: .flush_queue = _flush_queue,
! 3141: .queue_task = _queue_task,
! 3142: .queue_task_delayed = _queue_task_delayed,
! 3143: .adopt_child_tasks = _adopt_child_tasks,
! 3144: #ifdef ME
! 3145: .act_as_mediation_server = _act_as_mediation_server,
! 3146: .get_server_reflexive_host = _get_server_reflexive_host,
! 3147: .set_server_reflexive_host = _set_server_reflexive_host,
! 3148: .get_connect_id = _get_connect_id,
! 3149: .initiate_mediation = _initiate_mediation,
! 3150: .initiate_mediated = _initiate_mediated,
! 3151: .relay = _relay,
! 3152: .callback = _callback,
! 3153: .respond = _respond,
! 3154: #endif /* ME */
! 3155: },
! 3156: .ike_sa_id = ike_sa_id->clone(ike_sa_id),
! 3157: .version = version,
! 3158: .my_host = host_create_any(AF_INET),
! 3159: .other_host = host_create_any(AF_INET),
! 3160: .my_id = identification_create_from_encoding(ID_ANY, chunk_empty),
! 3161: .other_id = identification_create_from_encoding(ID_ANY, chunk_empty),
! 3162: .keymat = keymat_create(version, initiator),
! 3163: .state = IKE_CREATED,
! 3164: .stats[STAT_INBOUND] = time_monotonic(NULL),
! 3165: .stats[STAT_OUTBOUND] = time_monotonic(NULL),
! 3166: .my_auth = auth_cfg_create(),
! 3167: .other_auth = auth_cfg_create(),
! 3168: .my_auths = array_create(0, 0),
! 3169: .other_auths = array_create(0, 0),
! 3170: .attributes = array_create(sizeof(attribute_entry_t), 0),
! 3171: .unique_id = ref_get(&unique_id),
! 3172: .keepalive_interval = lib->settings->get_time(lib->settings,
! 3173: "%s.keep_alive", KEEPALIVE_INTERVAL, lib->ns),
! 3174: .retry_initiate_interval = lib->settings->get_time(lib->settings,
! 3175: "%s.retry_initiate_interval", 0, lib->ns),
! 3176: .flush_auth_cfg = lib->settings->get_bool(lib->settings,
! 3177: "%s.flush_auth_cfg", FALSE, lib->ns),
! 3178: .fragment_size = lib->settings->get_int(lib->settings,
! 3179: "%s.fragment_size", 1280, lib->ns),
! 3180: .follow_redirects = lib->settings->get_bool(lib->settings,
! 3181: "%s.follow_redirects", TRUE, lib->ns),
! 3182: );
! 3183:
! 3184: if (version == IKEV2)
! 3185: { /* always supported with IKEv2 */
! 3186: enable_extension(this, EXT_DPD);
! 3187: }
! 3188:
! 3189: this->task_manager = task_manager_create(&this->public);
! 3190: this->my_host->set_port(this->my_host,
! 3191: charon->socket->get_port(charon->socket, FALSE));
! 3192:
! 3193: if (!this->task_manager || !this->keymat)
! 3194: {
! 3195: DBG1(DBG_IKE, "IKE version %d not supported", this->version);
! 3196: destroy(this);
! 3197: return NULL;
! 3198: }
! 3199: return &this->public;
! 3200: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>