Annotation of embedaddon/strongswan/src/libcharon/sa/ikev2/task_manager_v2.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2007-2018 Tobias Brunner
! 3: * Copyright (C) 2007-2010 Martin Willi
! 4: * HSR Hochschule fuer Technik Rapperswil
! 5: *
! 6: * This program is free software; you can redistribute it and/or modify it
! 7: * under the terms of the GNU General Public License as published by the
! 8: * Free Software Foundation; either version 2 of the License, or (at your
! 9: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
! 10: *
! 11: * This program is distributed in the hope that it will be useful, but
! 12: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
! 13: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
! 14: * for more details.
! 15: */
! 16:
! 17: #include "task_manager_v2.h"
! 18:
! 19: #include <math.h>
! 20:
! 21: #include <collections/array.h>
! 22: #include <daemon.h>
! 23: #include <sa/ikev2/tasks/ike_init.h>
! 24: #include <sa/ikev2/tasks/ike_natd.h>
! 25: #include <sa/ikev2/tasks/ike_mobike.h>
! 26: #include <sa/ikev2/tasks/ike_auth.h>
! 27: #include <sa/ikev2/tasks/ike_auth_lifetime.h>
! 28: #include <sa/ikev2/tasks/ike_cert_pre.h>
! 29: #include <sa/ikev2/tasks/ike_cert_post.h>
! 30: #include <sa/ikev2/tasks/ike_rekey.h>
! 31: #include <sa/ikev2/tasks/ike_reauth.h>
! 32: #include <sa/ikev2/tasks/ike_reauth_complete.h>
! 33: #include <sa/ikev2/tasks/ike_redirect.h>
! 34: #include <sa/ikev2/tasks/ike_delete.h>
! 35: #include <sa/ikev2/tasks/ike_config.h>
! 36: #include <sa/ikev2/tasks/ike_dpd.h>
! 37: #include <sa/ikev2/tasks/ike_mid_sync.h>
! 38: #include <sa/ikev2/tasks/ike_vendor.h>
! 39: #include <sa/ikev2/tasks/ike_verify_peer_cert.h>
! 40: #include <sa/ikev2/tasks/child_create.h>
! 41: #include <sa/ikev2/tasks/child_rekey.h>
! 42: #include <sa/ikev2/tasks/child_delete.h>
! 43: #include <encoding/payloads/delete_payload.h>
! 44: #include <encoding/payloads/unknown_payload.h>
! 45: #include <processing/jobs/retransmit_job.h>
! 46: #include <processing/jobs/delete_ike_sa_job.h>
! 47: #include <processing/jobs/initiate_tasks_job.h>
! 48:
! 49: #ifdef ME
! 50: #include <sa/ikev2/tasks/ike_me.h>
! 51: #endif
! 52:
! 53: typedef struct private_task_manager_t private_task_manager_t;
! 54: typedef struct queued_task_t queued_task_t;
! 55:
! 56: /**
! 57: * private data of the task manager
! 58: */
! 59: struct private_task_manager_t {
! 60:
! 61: /**
! 62: * public functions
! 63: */
! 64: task_manager_v2_t public;
! 65:
! 66: /**
! 67: * associated IKE_SA we are serving
! 68: */
! 69: ike_sa_t *ike_sa;
! 70:
! 71: /**
! 72: * Exchange we are currently handling as responder
! 73: */
! 74: struct {
! 75: /**
! 76: * Message ID of the exchange
! 77: */
! 78: uint32_t mid;
! 79:
! 80: /**
! 81: * packet(s) for retransmission
! 82: */
! 83: array_t *packets;
! 84:
! 85: /**
! 86: * Helper to defragment the request
! 87: */
! 88: message_t *defrag;
! 89:
! 90: } responding;
! 91:
! 92: /**
! 93: * Exchange we are currently handling as initiator
! 94: */
! 95: struct {
! 96: /**
! 97: * Message ID of the exchange
! 98: */
! 99: uint32_t mid;
! 100:
! 101: /**
! 102: * how many times we have retransmitted so far
! 103: */
! 104: u_int retransmitted;
! 105:
! 106: /**
! 107: * packet(s) for retransmission
! 108: */
! 109: array_t *packets;
! 110:
! 111: /**
! 112: * type of the initiated exchange
! 113: */
! 114: exchange_type_t type;
! 115:
! 116: /**
! 117: * TRUE if exchange was deferred because no path was available
! 118: */
! 119: bool deferred;
! 120:
! 121: /**
! 122: * Helper to defragment the response
! 123: */
! 124: message_t *defrag;
! 125:
! 126: } initiating;
! 127:
! 128: /**
! 129: * Array of queued tasks not yet in action
! 130: */
! 131: array_t *queued_tasks;
! 132:
! 133: /**
! 134: * Array of active tasks, initiated by ourselves
! 135: */
! 136: array_t *active_tasks;
! 137:
! 138: /**
! 139: * Array of tasks initiated by peer
! 140: */
! 141: array_t *passive_tasks;
! 142:
! 143: /**
! 144: * the task manager has been reset
! 145: */
! 146: bool reset;
! 147:
! 148: /**
! 149: * Number of times we retransmit messages before giving up
! 150: */
! 151: u_int retransmit_tries;
! 152:
! 153: /**
! 154: * Retransmission timeout
! 155: */
! 156: double retransmit_timeout;
! 157:
! 158: /**
! 159: * Base to calculate retransmission timeout
! 160: */
! 161: double retransmit_base;
! 162:
! 163: /**
! 164: * Jitter to apply to calculated retransmit timeout (in percent)
! 165: */
! 166: u_int retransmit_jitter;
! 167:
! 168: /**
! 169: * Limit retransmit timeout to this value
! 170: */
! 171: uint32_t retransmit_limit;
! 172:
! 173: /**
! 174: * Use make-before-break instead of break-before-make reauth?
! 175: */
! 176: bool make_before_break;
! 177: };
! 178:
! 179: /**
! 180: * Queued tasks
! 181: */
! 182: struct queued_task_t {
! 183:
! 184: /**
! 185: * Queued task
! 186: */
! 187: task_t *task;
! 188:
! 189: /**
! 190: * Time before which the task is not to be initiated
! 191: */
! 192: timeval_t time;
! 193: };
! 194:
! 195: /**
! 196: * Reset retransmission packet list
! 197: */
! 198: static void clear_packets(array_t *array)
! 199: {
! 200: packet_t *packet;
! 201:
! 202: while (array_remove(array, ARRAY_TAIL, &packet))
! 203: {
! 204: packet->destroy(packet);
! 205: }
! 206: }
! 207:
! 208: METHOD(task_manager_t, flush_queue, void,
! 209: private_task_manager_t *this, task_queue_t queue)
! 210: {
! 211: array_t *array;
! 212: task_t *task;
! 213:
! 214: switch (queue)
! 215: {
! 216: case TASK_QUEUE_ACTIVE:
! 217: array = this->active_tasks;
! 218: break;
! 219: case TASK_QUEUE_PASSIVE:
! 220: array = this->passive_tasks;
! 221: break;
! 222: case TASK_QUEUE_QUEUED:
! 223: array = this->queued_tasks;
! 224: break;
! 225: default:
! 226: return;
! 227: }
! 228: while (array_remove(array, ARRAY_TAIL, &task))
! 229: {
! 230: if (queue == TASK_QUEUE_QUEUED)
! 231: {
! 232: queued_task_t *queued = (queued_task_t*)task;
! 233: task = queued->task;
! 234: free(queued);
! 235: }
! 236: task->destroy(task);
! 237: }
! 238: }
! 239:
! 240: METHOD(task_manager_t, flush, void,
! 241: private_task_manager_t *this)
! 242: {
! 243: flush_queue(this, TASK_QUEUE_QUEUED);
! 244: flush_queue(this, TASK_QUEUE_PASSIVE);
! 245: flush_queue(this, TASK_QUEUE_ACTIVE);
! 246: }
! 247:
! 248: /**
! 249: * Move a task of a specific type from the queue to the active list, if it is
! 250: * not delayed.
! 251: */
! 252: static bool activate_task(private_task_manager_t *this, task_type_t type)
! 253: {
! 254: enumerator_t *enumerator;
! 255: queued_task_t *queued;
! 256: timeval_t now;
! 257: bool found = FALSE;
! 258:
! 259: time_monotonic(&now);
! 260:
! 261: enumerator = array_create_enumerator(this->queued_tasks);
! 262: while (enumerator->enumerate(enumerator, (void**)&queued))
! 263: {
! 264: if (queued->task->get_type(queued->task) == type &&
! 265: !timercmp(&now, &queued->time, <))
! 266: {
! 267: DBG2(DBG_IKE, " activating %N task", task_type_names, type);
! 268: array_remove_at(this->queued_tasks, enumerator);
! 269: array_insert(this->active_tasks, ARRAY_TAIL, queued->task);
! 270: free(queued);
! 271: found = TRUE;
! 272: break;
! 273: }
! 274: }
! 275: enumerator->destroy(enumerator);
! 276: return found;
! 277: }
! 278:
! 279: /**
! 280: * Send packets in the given array (they get cloned). Optionally, the
! 281: * source and destination addresses are changed before sending it.
! 282: */
! 283: static void send_packets(private_task_manager_t *this, array_t *packets,
! 284: host_t *src, host_t *dst)
! 285: {
! 286: packet_t *packet, *clone;
! 287: int i;
! 288:
! 289: for (i = 0; i < array_count(packets); i++)
! 290: {
! 291: array_get(packets, i, &packet);
! 292: clone = packet->clone(packet);
! 293: if (src)
! 294: {
! 295: clone->set_source(clone, src->clone(src));
! 296: }
! 297: if (dst)
! 298: {
! 299: clone->set_destination(clone, dst->clone(dst));
! 300: }
! 301: charon->sender->send(charon->sender, clone);
! 302: }
! 303: }
! 304:
! 305: /**
! 306: * Generates the given message and stores packet(s) in the given array
! 307: */
! 308: static bool generate_message(private_task_manager_t *this, message_t *message,
! 309: array_t **packets)
! 310: {
! 311: enumerator_t *fragments;
! 312: packet_t *fragment;
! 313:
! 314: if (this->ike_sa->generate_message_fragmented(this->ike_sa, message,
! 315: &fragments) != SUCCESS)
! 316: {
! 317: return FALSE;
! 318: }
! 319: while (fragments->enumerate(fragments, &fragment))
! 320: {
! 321: array_insert_create(packets, ARRAY_TAIL, fragment);
! 322: }
! 323: fragments->destroy(fragments);
! 324: array_compress(*packets);
! 325: return TRUE;
! 326: }
! 327:
! 328: METHOD(task_manager_t, retransmit, status_t,
! 329: private_task_manager_t *this, uint32_t message_id)
! 330: {
! 331: if (message_id == this->initiating.mid &&
! 332: array_count(this->initiating.packets))
! 333: {
! 334: uint32_t timeout, max_jitter;
! 335: job_t *job;
! 336: enumerator_t *enumerator;
! 337: packet_t *packet;
! 338: task_t *task;
! 339: ike_mobike_t *mobike = NULL;
! 340:
! 341: array_get(this->initiating.packets, 0, &packet);
! 342:
! 343: /* check if we are retransmitting a MOBIKE routability check */
! 344: if (this->initiating.type == INFORMATIONAL)
! 345: {
! 346: enumerator = array_create_enumerator(this->active_tasks);
! 347: while (enumerator->enumerate(enumerator, (void*)&task))
! 348: {
! 349: if (task->get_type(task) == TASK_IKE_MOBIKE)
! 350: {
! 351: mobike = (ike_mobike_t*)task;
! 352: break;
! 353: }
! 354: }
! 355: enumerator->destroy(enumerator);
! 356: }
! 357:
! 358: if (!mobike || !mobike->is_probing(mobike))
! 359: {
! 360: if (this->initiating.retransmitted <= this->retransmit_tries)
! 361: {
! 362: timeout = (uint32_t)(this->retransmit_timeout * 1000.0 *
! 363: pow(this->retransmit_base, this->initiating.retransmitted));
! 364:
! 365: if (this->retransmit_limit)
! 366: {
! 367: timeout = min(timeout, this->retransmit_limit);
! 368: }
! 369: if (this->retransmit_jitter)
! 370: {
! 371: max_jitter = (timeout / 100.0) * this->retransmit_jitter;
! 372: timeout -= max_jitter * (random() / (RAND_MAX + 1.0));
! 373: }
! 374: }
! 375: else
! 376: {
! 377: DBG1(DBG_IKE, "giving up after %d retransmits",
! 378: this->initiating.retransmitted - 1);
! 379: charon->bus->alert(charon->bus, ALERT_RETRANSMIT_SEND_TIMEOUT,
! 380: packet);
! 381: return DESTROY_ME;
! 382: }
! 383:
! 384: if (this->initiating.retransmitted)
! 385: {
! 386: DBG1(DBG_IKE, "retransmit %d of request with message ID %d",
! 387: this->initiating.retransmitted, message_id);
! 388: charon->bus->alert(charon->bus, ALERT_RETRANSMIT_SEND, packet,
! 389: this->initiating.retransmitted);
! 390: }
! 391: if (!mobike)
! 392: {
! 393: send_packets(this, this->initiating.packets,
! 394: this->ike_sa->get_my_host(this->ike_sa),
! 395: this->ike_sa->get_other_host(this->ike_sa));
! 396: }
! 397: else
! 398: {
! 399: if (!mobike->transmit(mobike, packet))
! 400: {
! 401: DBG1(DBG_IKE, "no route found to reach peer, MOBIKE update "
! 402: "deferred");
! 403: this->ike_sa->set_condition(this->ike_sa, COND_STALE, TRUE);
! 404: this->initiating.deferred = TRUE;
! 405: return SUCCESS;
! 406: }
! 407: else if (mobike->is_probing(mobike))
! 408: {
! 409: timeout = ROUTABILITY_CHECK_INTERVAL;
! 410: }
! 411: }
! 412: }
! 413: else
! 414: { /* for routability checks, we use a more aggressive behavior */
! 415: if (this->initiating.retransmitted <= ROUTABILITY_CHECK_TRIES)
! 416: {
! 417: timeout = ROUTABILITY_CHECK_INTERVAL;
! 418: }
! 419: else
! 420: {
! 421: DBG1(DBG_IKE, "giving up after %d path probings",
! 422: this->initiating.retransmitted - 1);
! 423: return DESTROY_ME;
! 424: }
! 425:
! 426: if (this->initiating.retransmitted)
! 427: {
! 428: DBG1(DBG_IKE, "path probing attempt %d",
! 429: this->initiating.retransmitted);
! 430: }
! 431: /* TODO-FRAG: presumably these small packets are not fragmented,
! 432: * we should maybe ensure this is the case when generating them */
! 433: if (!mobike->transmit(mobike, packet))
! 434: {
! 435: DBG1(DBG_IKE, "no route found to reach peer, path probing "
! 436: "deferred");
! 437: this->ike_sa->set_condition(this->ike_sa, COND_STALE, TRUE);
! 438: this->initiating.deferred = TRUE;
! 439: return SUCCESS;
! 440: }
! 441: }
! 442:
! 443: this->initiating.retransmitted++;
! 444: job = (job_t*)retransmit_job_create(this->initiating.mid,
! 445: this->ike_sa->get_id(this->ike_sa));
! 446: lib->scheduler->schedule_job_ms(lib->scheduler, job, timeout);
! 447: }
! 448: return SUCCESS;
! 449: }
! 450:
! 451: METHOD(task_manager_t, initiate, status_t,
! 452: private_task_manager_t *this)
! 453: {
! 454: enumerator_t *enumerator;
! 455: task_t *task;
! 456: message_t *message;
! 457: host_t *me, *other;
! 458: exchange_type_t exchange = 0;
! 459:
! 460: if (this->initiating.type != EXCHANGE_TYPE_UNDEFINED)
! 461: {
! 462: DBG2(DBG_IKE, "delaying task initiation, %N exchange in progress",
! 463: exchange_type_names, this->initiating.type);
! 464: /* do not initiate if we already have a message in the air */
! 465: if (this->initiating.deferred)
! 466: { /* re-initiate deferred exchange */
! 467: this->initiating.deferred = FALSE;
! 468: this->initiating.retransmitted = 0;
! 469: return retransmit(this, this->initiating.mid);
! 470: }
! 471: return SUCCESS;
! 472: }
! 473:
! 474: if (array_count(this->active_tasks) == 0)
! 475: {
! 476: DBG2(DBG_IKE, "activating new tasks");
! 477: switch (this->ike_sa->get_state(this->ike_sa))
! 478: {
! 479: case IKE_CREATED:
! 480: activate_task(this, TASK_IKE_VENDOR);
! 481: if (activate_task(this, TASK_IKE_INIT))
! 482: {
! 483: this->initiating.mid = 0;
! 484: exchange = IKE_SA_INIT;
! 485: activate_task(this, TASK_IKE_NATD);
! 486: activate_task(this, TASK_IKE_CERT_PRE);
! 487: #ifdef ME
! 488: /* this task has to be activated before the TASK_IKE_AUTH
! 489: * task, because that task pregenerates the packet after
! 490: * which no payloads can be added to the message anymore.
! 491: */
! 492: activate_task(this, TASK_IKE_ME);
! 493: #endif /* ME */
! 494: activate_task(this, TASK_IKE_AUTH);
! 495: activate_task(this, TASK_IKE_CERT_POST);
! 496: activate_task(this, TASK_IKE_CONFIG);
! 497: activate_task(this, TASK_CHILD_CREATE);
! 498: activate_task(this, TASK_IKE_AUTH_LIFETIME);
! 499: activate_task(this, TASK_IKE_MOBIKE);
! 500: }
! 501: break;
! 502: case IKE_ESTABLISHED:
! 503: if (activate_task(this, TASK_IKE_MOBIKE))
! 504: {
! 505: exchange = INFORMATIONAL;
! 506: break;
! 507: }
! 508: if (activate_task(this, TASK_IKE_DELETE))
! 509: {
! 510: exchange = INFORMATIONAL;
! 511: break;
! 512: }
! 513: if (activate_task(this, TASK_IKE_REDIRECT))
! 514: {
! 515: exchange = INFORMATIONAL;
! 516: break;
! 517: }
! 518: if (activate_task(this, TASK_CHILD_DELETE))
! 519: {
! 520: exchange = INFORMATIONAL;
! 521: break;
! 522: }
! 523: if (activate_task(this, TASK_IKE_REAUTH))
! 524: {
! 525: exchange = INFORMATIONAL;
! 526: break;
! 527: }
! 528: if (activate_task(this, TASK_CHILD_CREATE))
! 529: {
! 530: exchange = CREATE_CHILD_SA;
! 531: break;
! 532: }
! 533: if (activate_task(this, TASK_CHILD_REKEY))
! 534: {
! 535: exchange = CREATE_CHILD_SA;
! 536: break;
! 537: }
! 538: if (activate_task(this, TASK_IKE_REKEY))
! 539: {
! 540: exchange = CREATE_CHILD_SA;
! 541: break;
! 542: }
! 543: if (activate_task(this, TASK_IKE_DPD))
! 544: {
! 545: exchange = INFORMATIONAL;
! 546: break;
! 547: }
! 548: if (activate_task(this, TASK_IKE_AUTH_LIFETIME))
! 549: {
! 550: exchange = INFORMATIONAL;
! 551: break;
! 552: }
! 553: #ifdef ME
! 554: if (activate_task(this, TASK_IKE_ME))
! 555: {
! 556: exchange = ME_CONNECT;
! 557: break;
! 558: }
! 559: #endif /* ME */
! 560: if (activate_task(this, TASK_IKE_REAUTH_COMPLETE))
! 561: {
! 562: exchange = INFORMATIONAL;
! 563: break;
! 564: }
! 565: if (activate_task(this, TASK_IKE_VERIFY_PEER_CERT))
! 566: {
! 567: exchange = INFORMATIONAL;
! 568: break;
! 569: }
! 570: case IKE_REKEYING:
! 571: case IKE_REKEYED:
! 572: if (activate_task(this, TASK_IKE_DELETE))
! 573: {
! 574: exchange = INFORMATIONAL;
! 575: break;
! 576: }
! 577: case IKE_DELETING:
! 578: default:
! 579: break;
! 580: }
! 581: }
! 582: else
! 583: {
! 584: DBG2(DBG_IKE, "reinitiating already active tasks");
! 585: enumerator = array_create_enumerator(this->active_tasks);
! 586: while (enumerator->enumerate(enumerator, &task))
! 587: {
! 588: DBG2(DBG_IKE, " %N task", task_type_names, task->get_type(task));
! 589: switch (task->get_type(task))
! 590: {
! 591: case TASK_IKE_INIT:
! 592: exchange = IKE_SA_INIT;
! 593: break;
! 594: case TASK_IKE_AUTH:
! 595: exchange = IKE_AUTH;
! 596: break;
! 597: case TASK_CHILD_CREATE:
! 598: case TASK_CHILD_REKEY:
! 599: case TASK_IKE_REKEY:
! 600: exchange = CREATE_CHILD_SA;
! 601: break;
! 602: case TASK_IKE_MOBIKE:
! 603: exchange = INFORMATIONAL;
! 604: break;
! 605: default:
! 606: continue;
! 607: }
! 608: break;
! 609: }
! 610: enumerator->destroy(enumerator);
! 611: }
! 612:
! 613: if (exchange == 0)
! 614: {
! 615: DBG2(DBG_IKE, "nothing to initiate");
! 616: /* nothing to do yet... */
! 617: return SUCCESS;
! 618: }
! 619:
! 620: me = this->ike_sa->get_my_host(this->ike_sa);
! 621: other = this->ike_sa->get_other_host(this->ike_sa);
! 622:
! 623: message = message_create(IKEV2_MAJOR_VERSION, IKEV2_MINOR_VERSION);
! 624: message->set_message_id(message, this->initiating.mid);
! 625: message->set_source(message, me->clone(me));
! 626: message->set_destination(message, other->clone(other));
! 627: message->set_exchange_type(message, exchange);
! 628: this->initiating.type = exchange;
! 629: this->initiating.retransmitted = 0;
! 630: this->initiating.deferred = FALSE;
! 631:
! 632: enumerator = array_create_enumerator(this->active_tasks);
! 633: while (enumerator->enumerate(enumerator, &task))
! 634: {
! 635: switch (task->build(task, message))
! 636: {
! 637: case SUCCESS:
! 638: /* task completed, remove it */
! 639: array_remove_at(this->active_tasks, enumerator);
! 640: task->destroy(task);
! 641: break;
! 642: case NEED_MORE:
! 643: /* processed, but task needs another exchange */
! 644: break;
! 645: case FAILED:
! 646: default:
! 647: this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
! 648: if (this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING &&
! 649: this->ike_sa->get_state(this->ike_sa) != IKE_REKEYED)
! 650: {
! 651: charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
! 652: }
! 653: /* FALL */
! 654: case DESTROY_ME:
! 655: /* critical failure, destroy IKE_SA */
! 656: enumerator->destroy(enumerator);
! 657: message->destroy(message);
! 658: flush(this);
! 659: return DESTROY_ME;
! 660: }
! 661: }
! 662: enumerator->destroy(enumerator);
! 663:
! 664: /* update exchange type if a task changed it */
! 665: this->initiating.type = message->get_exchange_type(message);
! 666: if (this->initiating.type == EXCHANGE_TYPE_UNDEFINED)
! 667: {
! 668: message->destroy(message);
! 669: return initiate(this);
! 670: }
! 671:
! 672: if (!generate_message(this, message, &this->initiating.packets))
! 673: {
! 674: /* message generation failed. There is nothing more to do than to
! 675: * close the SA */
! 676: message->destroy(message);
! 677: flush(this);
! 678: charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
! 679: return DESTROY_ME;
! 680: }
! 681: message->destroy(message);
! 682:
! 683: array_compress(this->active_tasks);
! 684: array_compress(this->queued_tasks);
! 685:
! 686: return retransmit(this, this->initiating.mid);
! 687: }
! 688:
! 689: /**
! 690: * handle an incoming response message
! 691: */
! 692: static status_t process_response(private_task_manager_t *this,
! 693: message_t *message)
! 694: {
! 695: enumerator_t *enumerator;
! 696: task_t *task;
! 697:
! 698: if (message->get_exchange_type(message) != this->initiating.type)
! 699: {
! 700: DBG1(DBG_IKE, "received %N response, but expected %N",
! 701: exchange_type_names, message->get_exchange_type(message),
! 702: exchange_type_names, this->initiating.type);
! 703: charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
! 704: return DESTROY_ME;
! 705: }
! 706:
! 707: /* handle fatal INVALID_SYNTAX notifies */
! 708: switch (message->get_exchange_type(message))
! 709: {
! 710: case CREATE_CHILD_SA:
! 711: case INFORMATIONAL:
! 712: if (message->get_notify(message, INVALID_SYNTAX))
! 713: {
! 714: DBG1(DBG_IKE, "received %N notify error, destroying IKE_SA",
! 715: notify_type_names, INVALID_SYNTAX);
! 716: charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
! 717: return DESTROY_ME;
! 718: }
! 719: break;
! 720: default:
! 721: break;
! 722: }
! 723:
! 724: enumerator = array_create_enumerator(this->active_tasks);
! 725: while (enumerator->enumerate(enumerator, &task))
! 726: {
! 727: if (!task->pre_process)
! 728: {
! 729: continue;
! 730: }
! 731: switch (task->pre_process(task, message))
! 732: {
! 733: case SUCCESS:
! 734: break;
! 735: case FAILED:
! 736: default:
! 737: /* just ignore the message */
! 738: DBG1(DBG_IKE, "ignore invalid %N response",
! 739: exchange_type_names, message->get_exchange_type(message));
! 740: enumerator->destroy(enumerator);
! 741: return SUCCESS;
! 742: case DESTROY_ME:
! 743: /* critical failure, destroy IKE_SA */
! 744: enumerator->destroy(enumerator);
! 745: return DESTROY_ME;
! 746: }
! 747: }
! 748: enumerator->destroy(enumerator);
! 749:
! 750: if (this->initiating.retransmitted > 1)
! 751: {
! 752: packet_t *packet = NULL;
! 753: array_get(this->initiating.packets, 0, &packet);
! 754: charon->bus->alert(charon->bus, ALERT_RETRANSMIT_SEND_CLEARED, packet);
! 755: }
! 756:
! 757: /* catch if we get reset while processing */
! 758: this->reset = FALSE;
! 759: enumerator = array_create_enumerator(this->active_tasks);
! 760: while (enumerator->enumerate(enumerator, &task))
! 761: {
! 762: switch (task->process(task, message))
! 763: {
! 764: case SUCCESS:
! 765: /* task completed, remove it */
! 766: array_remove_at(this->active_tasks, enumerator);
! 767: task->destroy(task);
! 768: break;
! 769: case NEED_MORE:
! 770: /* processed, but task needs another exchange */
! 771: break;
! 772: case FAILED:
! 773: default:
! 774: charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
! 775: /* FALL */
! 776: case DESTROY_ME:
! 777: /* critical failure, destroy IKE_SA */
! 778: array_remove_at(this->active_tasks, enumerator);
! 779: enumerator->destroy(enumerator);
! 780: task->destroy(task);
! 781: return DESTROY_ME;
! 782: }
! 783: if (this->reset)
! 784: { /* start all over again if we were reset */
! 785: this->reset = FALSE;
! 786: enumerator->destroy(enumerator);
! 787: return initiate(this);
! 788: }
! 789: }
! 790: enumerator->destroy(enumerator);
! 791:
! 792: this->initiating.mid++;
! 793: this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
! 794: clear_packets(this->initiating.packets);
! 795:
! 796: array_compress(this->active_tasks);
! 797:
! 798: return initiate(this);
! 799: }
! 800:
! 801: /**
! 802: * handle exchange collisions
! 803: */
! 804: static bool handle_collisions(private_task_manager_t *this, task_t *task)
! 805: {
! 806: enumerator_t *enumerator;
! 807: task_t *active;
! 808: task_type_t type;
! 809:
! 810: type = task->get_type(task);
! 811:
! 812: /* do we have to check */
! 813: if (type == TASK_IKE_REKEY || type == TASK_CHILD_REKEY ||
! 814: type == TASK_CHILD_DELETE || type == TASK_IKE_DELETE)
! 815: {
! 816: /* find an exchange collision, and notify these tasks */
! 817: enumerator = array_create_enumerator(this->active_tasks);
! 818: while (enumerator->enumerate(enumerator, &active))
! 819: {
! 820: switch (active->get_type(active))
! 821: {
! 822: case TASK_IKE_REKEY:
! 823: if (type == TASK_IKE_REKEY || type == TASK_IKE_DELETE)
! 824: {
! 825: ike_rekey_t *rekey = (ike_rekey_t*)active;
! 826: rekey->collide(rekey, task);
! 827: break;
! 828: }
! 829: continue;
! 830: case TASK_CHILD_REKEY:
! 831: if (type == TASK_CHILD_REKEY || type == TASK_CHILD_DELETE)
! 832: {
! 833: child_rekey_t *rekey = (child_rekey_t*)active;
! 834: rekey->collide(rekey, task);
! 835: break;
! 836: }
! 837: continue;
! 838: default:
! 839: continue;
! 840: }
! 841: enumerator->destroy(enumerator);
! 842: return TRUE;
! 843: }
! 844: enumerator->destroy(enumerator);
! 845: }
! 846: return FALSE;
! 847: }
! 848:
! 849: /**
! 850: * build a response depending on the "passive" task list
! 851: */
! 852: static status_t build_response(private_task_manager_t *this, message_t *request)
! 853: {
! 854: enumerator_t *enumerator;
! 855: task_t *task;
! 856: message_t *message;
! 857: host_t *me, *other;
! 858: bool delete = FALSE, hook = FALSE, mid_sync = FALSE;
! 859: ike_sa_id_t *id = NULL;
! 860: uint64_t responder_spi = 0;
! 861: bool result;
! 862:
! 863: me = request->get_destination(request);
! 864: other = request->get_source(request);
! 865:
! 866: message = message_create(IKEV2_MAJOR_VERSION, IKEV2_MINOR_VERSION);
! 867: message->set_exchange_type(message, request->get_exchange_type(request));
! 868: /* send response along the path the request came in */
! 869: message->set_source(message, me->clone(me));
! 870: message->set_destination(message, other->clone(other));
! 871: message->set_message_id(message, this->responding.mid);
! 872: message->set_request(message, FALSE);
! 873:
! 874: enumerator = array_create_enumerator(this->passive_tasks);
! 875: while (enumerator->enumerate(enumerator, (void*)&task))
! 876: {
! 877: if (task->get_type(task) == TASK_IKE_MID_SYNC)
! 878: {
! 879: mid_sync = TRUE;
! 880: }
! 881: switch (task->build(task, message))
! 882: {
! 883: case SUCCESS:
! 884: /* task completed, remove it */
! 885: array_remove_at(this->passive_tasks, enumerator);
! 886: if (!handle_collisions(this, task))
! 887: {
! 888: task->destroy(task);
! 889: }
! 890: break;
! 891: case NEED_MORE:
! 892: /* processed, but task needs another exchange */
! 893: if (handle_collisions(this, task))
! 894: {
! 895: array_remove_at(this->passive_tasks, enumerator);
! 896: }
! 897: break;
! 898: case FAILED:
! 899: default:
! 900: hook = TRUE;
! 901: /* FALL */
! 902: case DESTROY_ME:
! 903: /* destroy IKE_SA, but SEND response first */
! 904: if (handle_collisions(this, task))
! 905: {
! 906: array_remove_at(this->passive_tasks, enumerator);
! 907: }
! 908: delete = TRUE;
! 909: break;
! 910: }
! 911: if (delete)
! 912: {
! 913: break;
! 914: }
! 915: }
! 916: enumerator->destroy(enumerator);
! 917:
! 918: /* RFC 5996, section 2.6 mentions that in the event of a failure during
! 919: * IKE_SA_INIT the responder's SPI will be 0 in the response, while it
! 920: * actually explicitly allows it to be non-zero. Since we use the responder
! 921: * SPI to create hashes in the IKE_SA manager we can only set the SPI to
! 922: * zero temporarily, otherwise checking the SA in would fail. */
! 923: if (delete && request->get_exchange_type(request) == IKE_SA_INIT)
! 924: {
! 925: id = this->ike_sa->get_id(this->ike_sa);
! 926: responder_spi = id->get_responder_spi(id);
! 927: id->set_responder_spi(id, 0);
! 928: }
! 929:
! 930: /* message complete, send it */
! 931: clear_packets(this->responding.packets);
! 932: result = generate_message(this, message, &this->responding.packets);
! 933: message->destroy(message);
! 934: if (id)
! 935: {
! 936: id->set_responder_spi(id, responder_spi);
! 937: }
! 938: if (!result)
! 939: {
! 940: charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
! 941: return DESTROY_ME;
! 942: }
! 943:
! 944: send_packets(this, this->responding.packets, NULL, NULL);
! 945: if (delete)
! 946: {
! 947: if (hook)
! 948: {
! 949: charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
! 950: }
! 951: return DESTROY_ME;
! 952: }
! 953: else if (mid_sync)
! 954: {
! 955: /* we don't want to resend messages to sync MIDs if requests with the
! 956: * previous MID arrive */
! 957: clear_packets(this->responding.packets);
! 958: /* avoid increasing the expected message ID after handling a message
! 959: * to sync MIDs with MID 0 */
! 960: return NEED_MORE;
! 961: }
! 962:
! 963: array_compress(this->passive_tasks);
! 964:
! 965: return SUCCESS;
! 966: }
! 967:
! 968: /**
! 969: * handle an incoming request message
! 970: */
! 971: static status_t process_request(private_task_manager_t *this,
! 972: message_t *message)
! 973: {
! 974: enumerator_t *enumerator;
! 975: task_t *task = NULL;
! 976: payload_t *payload;
! 977: notify_payload_t *notify;
! 978: delete_payload_t *delete;
! 979: ike_sa_state_t state;
! 980:
! 981: if (array_count(this->passive_tasks) == 0)
! 982: { /* create tasks depending on request type, if not already some queued */
! 983: state = this->ike_sa->get_state(this->ike_sa);
! 984: switch (message->get_exchange_type(message))
! 985: {
! 986: case IKE_SA_INIT:
! 987: {
! 988: task = (task_t*)ike_vendor_create(this->ike_sa, FALSE);
! 989: array_insert(this->passive_tasks, ARRAY_TAIL, task);
! 990: task = (task_t*)ike_init_create(this->ike_sa, FALSE, NULL);
! 991: array_insert(this->passive_tasks, ARRAY_TAIL, task);
! 992: task = (task_t*)ike_natd_create(this->ike_sa, FALSE);
! 993: array_insert(this->passive_tasks, ARRAY_TAIL, task);
! 994: task = (task_t*)ike_cert_pre_create(this->ike_sa, FALSE);
! 995: array_insert(this->passive_tasks, ARRAY_TAIL, task);
! 996: #ifdef ME
! 997: task = (task_t*)ike_me_create(this->ike_sa, FALSE);
! 998: array_insert(this->passive_tasks, ARRAY_TAIL, task);
! 999: #endif /* ME */
! 1000: task = (task_t*)ike_auth_create(this->ike_sa, FALSE);
! 1001: array_insert(this->passive_tasks, ARRAY_TAIL, task);
! 1002: task = (task_t*)ike_cert_post_create(this->ike_sa, FALSE);
! 1003: array_insert(this->passive_tasks, ARRAY_TAIL, task);
! 1004: task = (task_t*)ike_config_create(this->ike_sa, FALSE);
! 1005: array_insert(this->passive_tasks, ARRAY_TAIL, task);
! 1006: task = (task_t*)child_create_create(this->ike_sa, NULL, FALSE,
! 1007: NULL, NULL);
! 1008: array_insert(this->passive_tasks, ARRAY_TAIL, task);
! 1009: task = (task_t*)ike_auth_lifetime_create(this->ike_sa, FALSE);
! 1010: array_insert(this->passive_tasks, ARRAY_TAIL, task);
! 1011: task = (task_t*)ike_mobike_create(this->ike_sa, FALSE);
! 1012: array_insert(this->passive_tasks, ARRAY_TAIL, task);
! 1013: break;
! 1014: }
! 1015: case CREATE_CHILD_SA:
! 1016: { /* FIXME: we should prevent this on mediation connections */
! 1017: bool notify_found = FALSE, ts_found = FALSE;
! 1018:
! 1019: if (state == IKE_CREATED ||
! 1020: state == IKE_CONNECTING)
! 1021: {
! 1022: DBG1(DBG_IKE, "received CREATE_CHILD_SA request for "
! 1023: "unestablished IKE_SA, rejected");
! 1024: return FAILED;
! 1025: }
! 1026:
! 1027: enumerator = message->create_payload_enumerator(message);
! 1028: while (enumerator->enumerate(enumerator, &payload))
! 1029: {
! 1030: switch (payload->get_type(payload))
! 1031: {
! 1032: case PLV2_NOTIFY:
! 1033: { /* if we find a rekey notify, its CHILD_SA rekeying */
! 1034: notify = (notify_payload_t*)payload;
! 1035: if (notify->get_notify_type(notify) == REKEY_SA &&
! 1036: (notify->get_protocol_id(notify) == PROTO_AH ||
! 1037: notify->get_protocol_id(notify) == PROTO_ESP))
! 1038: {
! 1039: notify_found = TRUE;
! 1040: }
! 1041: break;
! 1042: }
! 1043: case PLV2_TS_INITIATOR:
! 1044: case PLV2_TS_RESPONDER:
! 1045: { /* if we don't find a TS, its IKE rekeying */
! 1046: ts_found = TRUE;
! 1047: break;
! 1048: }
! 1049: default:
! 1050: break;
! 1051: }
! 1052: }
! 1053: enumerator->destroy(enumerator);
! 1054:
! 1055: if (ts_found)
! 1056: {
! 1057: if (notify_found)
! 1058: {
! 1059: task = (task_t*)child_rekey_create(this->ike_sa,
! 1060: PROTO_NONE, 0);
! 1061: }
! 1062: else
! 1063: {
! 1064: task = (task_t*)child_create_create(this->ike_sa, NULL,
! 1065: FALSE, NULL, NULL);
! 1066: }
! 1067: }
! 1068: else
! 1069: {
! 1070: task = (task_t*)ike_rekey_create(this->ike_sa, FALSE);
! 1071: }
! 1072: array_insert(this->passive_tasks, ARRAY_TAIL, task);
! 1073: break;
! 1074: }
! 1075: case INFORMATIONAL:
! 1076: {
! 1077: enumerator = message->create_payload_enumerator(message);
! 1078: while (enumerator->enumerate(enumerator, &payload))
! 1079: {
! 1080: switch (payload->get_type(payload))
! 1081: {
! 1082: case PLV2_NOTIFY:
! 1083: {
! 1084: notify = (notify_payload_t*)payload;
! 1085: if (state == IKE_REKEYED)
! 1086: {
! 1087: DBG1(DBG_IKE, "received unexpected notify %N "
! 1088: "for rekeyed IKE_SA, ignored",
! 1089: notify_type_names,
! 1090: notify->get_notify_type(notify));
! 1091: break;
! 1092: }
! 1093: switch (notify->get_notify_type(notify))
! 1094: {
! 1095: case ADDITIONAL_IP4_ADDRESS:
! 1096: case ADDITIONAL_IP6_ADDRESS:
! 1097: case NO_ADDITIONAL_ADDRESSES:
! 1098: case UPDATE_SA_ADDRESSES:
! 1099: case NO_NATS_ALLOWED:
! 1100: case UNACCEPTABLE_ADDRESSES:
! 1101: case UNEXPECTED_NAT_DETECTED:
! 1102: case COOKIE2:
! 1103: case NAT_DETECTION_SOURCE_IP:
! 1104: case NAT_DETECTION_DESTINATION_IP:
! 1105: task = (task_t*)ike_mobike_create(
! 1106: this->ike_sa, FALSE);
! 1107: break;
! 1108: case AUTH_LIFETIME:
! 1109: task = (task_t*)ike_auth_lifetime_create(
! 1110: this->ike_sa, FALSE);
! 1111: break;
! 1112: case AUTHENTICATION_FAILED:
! 1113: /* initiator failed to authenticate us.
! 1114: * We use ike_delete to handle this, which
! 1115: * invokes all the required hooks. */
! 1116: task = (task_t*)ike_delete_create(
! 1117: this->ike_sa, FALSE);
! 1118: break;
! 1119: case REDIRECT:
! 1120: task = (task_t*)ike_redirect_create(
! 1121: this->ike_sa, NULL);
! 1122: break;
! 1123: case IKEV2_MESSAGE_ID_SYNC:
! 1124: task = (task_t*)ike_mid_sync_create(
! 1125: this->ike_sa);
! 1126: break;
! 1127: default:
! 1128: break;
! 1129: }
! 1130: break;
! 1131: }
! 1132: case PLV2_DELETE:
! 1133: {
! 1134: delete = (delete_payload_t*)payload;
! 1135: if (delete->get_protocol_id(delete) == PROTO_IKE)
! 1136: {
! 1137: task = (task_t*)ike_delete_create(this->ike_sa,
! 1138: FALSE);
! 1139: }
! 1140: else
! 1141: {
! 1142: task = (task_t*)child_delete_create(this->ike_sa,
! 1143: PROTO_NONE, 0, FALSE);
! 1144: }
! 1145: break;
! 1146: }
! 1147: default:
! 1148: break;
! 1149: }
! 1150: if (task)
! 1151: {
! 1152: break;
! 1153: }
! 1154: }
! 1155: enumerator->destroy(enumerator);
! 1156:
! 1157: if (task == NULL)
! 1158: {
! 1159: task = (task_t*)ike_dpd_create(FALSE);
! 1160: }
! 1161: array_insert(this->passive_tasks, ARRAY_TAIL, task);
! 1162: break;
! 1163: }
! 1164: #ifdef ME
! 1165: case ME_CONNECT:
! 1166: {
! 1167: task = (task_t*)ike_me_create(this->ike_sa, FALSE);
! 1168: array_insert(this->passive_tasks, ARRAY_TAIL, task);
! 1169: }
! 1170: #endif /* ME */
! 1171: default:
! 1172: break;
! 1173: }
! 1174: }
! 1175:
! 1176: enumerator = array_create_enumerator(this->passive_tasks);
! 1177: while (enumerator->enumerate(enumerator, &task))
! 1178: {
! 1179: if (!task->pre_process)
! 1180: {
! 1181: continue;
! 1182: }
! 1183: switch (task->pre_process(task, message))
! 1184: {
! 1185: case SUCCESS:
! 1186: break;
! 1187: case FAILED:
! 1188: default:
! 1189: /* just ignore the message */
! 1190: DBG1(DBG_IKE, "ignore invalid %N request",
! 1191: exchange_type_names, message->get_exchange_type(message));
! 1192: enumerator->destroy(enumerator);
! 1193: switch (message->get_exchange_type(message))
! 1194: {
! 1195: case IKE_SA_INIT:
! 1196: /* no point in keeping the SA when it was created with
! 1197: * an invalid IKE_SA_INIT message */
! 1198: return DESTROY_ME;
! 1199: default:
! 1200: /* remove tasks we queued for this request */
! 1201: flush_queue(this, TASK_QUEUE_PASSIVE);
! 1202: /* fall-through */
! 1203: case IKE_AUTH:
! 1204: return NEED_MORE;
! 1205: }
! 1206: case DESTROY_ME:
! 1207: /* critical failure, destroy IKE_SA */
! 1208: enumerator->destroy(enumerator);
! 1209: return DESTROY_ME;
! 1210: }
! 1211: }
! 1212: enumerator->destroy(enumerator);
! 1213:
! 1214: /* let the tasks process the message */
! 1215: enumerator = array_create_enumerator(this->passive_tasks);
! 1216: while (enumerator->enumerate(enumerator, (void*)&task))
! 1217: {
! 1218: switch (task->process(task, message))
! 1219: {
! 1220: case SUCCESS:
! 1221: /* task completed, remove it */
! 1222: array_remove_at(this->passive_tasks, enumerator);
! 1223: task->destroy(task);
! 1224: break;
! 1225: case NEED_MORE:
! 1226: /* processed, but task needs at least another call to build() */
! 1227: break;
! 1228: case FAILED:
! 1229: default:
! 1230: charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
! 1231: /* FALL */
! 1232: case DESTROY_ME:
! 1233: /* critical failure, destroy IKE_SA */
! 1234: array_remove_at(this->passive_tasks, enumerator);
! 1235: enumerator->destroy(enumerator);
! 1236: task->destroy(task);
! 1237: return DESTROY_ME;
! 1238: }
! 1239: }
! 1240: enumerator->destroy(enumerator);
! 1241:
! 1242: return build_response(this, message);
! 1243: }
! 1244:
! 1245: METHOD(task_manager_t, incr_mid, void,
! 1246: private_task_manager_t *this, bool initiate)
! 1247: {
! 1248: if (initiate)
! 1249: {
! 1250: this->initiating.mid++;
! 1251: }
! 1252: else
! 1253: {
! 1254: this->responding.mid++;
! 1255: }
! 1256: }
! 1257:
! 1258: METHOD(task_manager_t, get_mid, uint32_t,
! 1259: private_task_manager_t *this, bool initiate)
! 1260: {
! 1261: return initiate ? this->initiating.mid : this->responding.mid;
! 1262: }
! 1263:
! 1264: /**
! 1265: * Handle the given IKE fragment, if it is one.
! 1266: *
! 1267: * Returns SUCCESS if the message is not a fragment, and NEED_MORE if it was
! 1268: * handled properly. Error states are returned if the fragment was invalid or
! 1269: * the reassembled message could not have been processed properly.
! 1270: */
! 1271: static status_t handle_fragment(private_task_manager_t *this,
! 1272: message_t **defrag, message_t *msg)
! 1273: {
! 1274: message_t *reassembled;
! 1275: status_t status;
! 1276:
! 1277: if (!msg->get_payload(msg, PLV2_FRAGMENT))
! 1278: {
! 1279: return SUCCESS;
! 1280: }
! 1281: if (!*defrag)
! 1282: {
! 1283: *defrag = message_create_defrag(msg);
! 1284: if (!*defrag)
! 1285: {
! 1286: return FAILED;
! 1287: }
! 1288: }
! 1289: status = (*defrag)->add_fragment(*defrag, msg);
! 1290: if (status == SUCCESS)
! 1291: {
! 1292: /* reinject the reassembled message */
! 1293: reassembled = *defrag;
! 1294: *defrag = NULL;
! 1295: status = this->ike_sa->process_message(this->ike_sa, reassembled);
! 1296: if (status == SUCCESS)
! 1297: {
! 1298: /* avoid processing the last fragment */
! 1299: status = NEED_MORE;
! 1300: }
! 1301: reassembled->destroy(reassembled);
! 1302: }
! 1303: return status;
! 1304: }
! 1305:
! 1306: /**
! 1307: * Send a notify back to the sender
! 1308: */
! 1309: static void send_notify_response(private_task_manager_t *this,
! 1310: message_t *request, notify_type_t type,
! 1311: chunk_t data)
! 1312: {
! 1313: message_t *response;
! 1314: packet_t *packet;
! 1315: host_t *me, *other;
! 1316:
! 1317: response = message_create(IKEV2_MAJOR_VERSION, IKEV2_MINOR_VERSION);
! 1318: response->set_exchange_type(response, request->get_exchange_type(request));
! 1319: response->set_request(response, FALSE);
! 1320: response->set_message_id(response, request->get_message_id(request));
! 1321: response->add_notify(response, FALSE, type, data);
! 1322: me = this->ike_sa->get_my_host(this->ike_sa);
! 1323: if (me->is_anyaddr(me))
! 1324: {
! 1325: me = request->get_destination(request);
! 1326: this->ike_sa->set_my_host(this->ike_sa, me->clone(me));
! 1327: }
! 1328: other = this->ike_sa->get_other_host(this->ike_sa);
! 1329: if (other->is_anyaddr(other))
! 1330: {
! 1331: other = request->get_source(request);
! 1332: this->ike_sa->set_other_host(this->ike_sa, other->clone(other));
! 1333: }
! 1334: response->set_source(response, me->clone(me));
! 1335: response->set_destination(response, other->clone(other));
! 1336: if (this->ike_sa->generate_message(this->ike_sa, response,
! 1337: &packet) == SUCCESS)
! 1338: {
! 1339: charon->sender->send(charon->sender, packet);
! 1340: }
! 1341: response->destroy(response);
! 1342: }
! 1343:
! 1344: /**
! 1345: * Send an INVALID_SYNTAX notify and destroy the IKE_SA for authenticated
! 1346: * messages.
! 1347: */
! 1348: static status_t send_invalid_syntax(private_task_manager_t *this,
! 1349: message_t *msg)
! 1350: {
! 1351: send_notify_response(this, msg, INVALID_SYNTAX, chunk_empty);
! 1352: incr_mid(this, FALSE);
! 1353:
! 1354: /* IKE_SA_INIT is currently the only type the parser accepts unprotected,
! 1355: * don't destroy the IKE_SA if such a message is invalid */
! 1356: if (msg->get_exchange_type(msg) == IKE_SA_INIT)
! 1357: {
! 1358: return FAILED;
! 1359: }
! 1360: return DESTROY_ME;
! 1361: }
! 1362:
! 1363: /**
! 1364: * Parse the given message and verify that it is valid.
! 1365: */
! 1366: static status_t parse_message(private_task_manager_t *this, message_t *msg)
! 1367: {
! 1368: status_t parse_status, status;
! 1369: uint8_t type = 0;
! 1370:
! 1371: parse_status = msg->parse_body(msg, this->ike_sa->get_keymat(this->ike_sa));
! 1372:
! 1373: if (parse_status == SUCCESS)
! 1374: { /* check for unsupported critical payloads */
! 1375: enumerator_t *enumerator;
! 1376: unknown_payload_t *unknown;
! 1377: payload_t *payload;
! 1378:
! 1379: enumerator = msg->create_payload_enumerator(msg);
! 1380: while (enumerator->enumerate(enumerator, &payload))
! 1381: {
! 1382: if (payload->get_type(payload) == PL_UNKNOWN)
! 1383: {
! 1384: unknown = (unknown_payload_t*)payload;
! 1385: if (unknown->is_critical(unknown))
! 1386: {
! 1387: type = unknown->get_type(unknown);
! 1388: DBG1(DBG_ENC, "payload type %N is not supported, "
! 1389: "but payload is critical!", payload_type_names, type);
! 1390: parse_status = NOT_SUPPORTED;
! 1391: break;
! 1392: }
! 1393: }
! 1394: }
! 1395: enumerator->destroy(enumerator);
! 1396: }
! 1397:
! 1398: status = parse_status;
! 1399:
! 1400: if (parse_status != SUCCESS)
! 1401: {
! 1402: bool is_request = msg->get_request(msg);
! 1403:
! 1404: switch (parse_status)
! 1405: {
! 1406: case NOT_SUPPORTED:
! 1407: DBG1(DBG_IKE, "critical unknown payloads found");
! 1408: if (is_request)
! 1409: {
! 1410: send_notify_response(this, msg,
! 1411: UNSUPPORTED_CRITICAL_PAYLOAD,
! 1412: chunk_from_thing(type));
! 1413: incr_mid(this, FALSE);
! 1414: }
! 1415: break;
! 1416: case PARSE_ERROR:
! 1417: DBG1(DBG_IKE, "message parsing failed");
! 1418: if (is_request)
! 1419: {
! 1420: status = send_invalid_syntax(this, msg);
! 1421: }
! 1422: break;
! 1423: case VERIFY_ERROR:
! 1424: DBG1(DBG_IKE, "message verification failed");
! 1425: if (is_request)
! 1426: {
! 1427: status = send_invalid_syntax(this, msg);
! 1428: }
! 1429: break;
! 1430: case FAILED:
! 1431: DBG1(DBG_IKE, "integrity check failed");
! 1432: /* ignored */
! 1433: break;
! 1434: case INVALID_STATE:
! 1435: DBG1(DBG_IKE, "found encrypted message, but no keys available");
! 1436: default:
! 1437: break;
! 1438: }
! 1439: DBG1(DBG_IKE, "%N %s with message ID %d processing failed",
! 1440: exchange_type_names, msg->get_exchange_type(msg),
! 1441: is_request ? "request" : "response",
! 1442: msg->get_message_id(msg));
! 1443:
! 1444: charon->bus->alert(charon->bus, ALERT_PARSE_ERROR_BODY, msg,
! 1445: parse_status);
! 1446:
! 1447: switch (this->ike_sa->get_state(this->ike_sa))
! 1448: {
! 1449: case IKE_CREATED:
! 1450: /* invalid initiation attempt, close SA */
! 1451: status = DESTROY_ME;
! 1452: break;
! 1453: case IKE_CONNECTING:
! 1454: case IKE_REKEYED:
! 1455: /* don't trigger updown event in these states */
! 1456: break;
! 1457: default:
! 1458: if (status == DESTROY_ME)
! 1459: {
! 1460: charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
! 1461: }
! 1462: break;
! 1463: }
! 1464: }
! 1465: return status;
! 1466: }
! 1467:
! 1468: /**
! 1469: * Check if a message with message ID 0 looks like it is used to synchronize
! 1470: * the message IDs.
! 1471: */
! 1472: static bool looks_like_mid_sync(private_task_manager_t *this, message_t *msg,
! 1473: bool strict)
! 1474: {
! 1475: enumerator_t *enumerator;
! 1476: notify_payload_t *notify;
! 1477: payload_t *payload;
! 1478: bool found = FALSE, other = FALSE;
! 1479:
! 1480: if (msg->get_exchange_type(msg) == INFORMATIONAL)
! 1481: {
! 1482: enumerator = msg->create_payload_enumerator(msg);
! 1483: while (enumerator->enumerate(enumerator, &payload))
! 1484: {
! 1485: if (payload->get_type(payload) == PLV2_NOTIFY)
! 1486: {
! 1487: notify = (notify_payload_t*)payload;
! 1488: switch (notify->get_notify_type(notify))
! 1489: {
! 1490: case IKEV2_MESSAGE_ID_SYNC:
! 1491: case IPSEC_REPLAY_COUNTER_SYNC:
! 1492: found = TRUE;
! 1493: continue;
! 1494: default:
! 1495: break;
! 1496: }
! 1497: }
! 1498: if (strict)
! 1499: {
! 1500: other = TRUE;
! 1501: break;
! 1502: }
! 1503: }
! 1504: enumerator->destroy(enumerator);
! 1505: }
! 1506: return found && !other;
! 1507: }
! 1508:
! 1509: /**
! 1510: * Check whether we should reject the given request message
! 1511: */
! 1512: static inline bool reject_request(private_task_manager_t *this,
! 1513: message_t *msg)
! 1514: {
! 1515: ike_sa_state_t state;
! 1516: exchange_type_t type;
! 1517: ike_sa_id_t *ike_sa_id;
! 1518: bool reject = FALSE;
! 1519:
! 1520: state = this->ike_sa->get_state(this->ike_sa);
! 1521: type = msg->get_exchange_type(msg);
! 1522:
! 1523: /* reject initial messages if not received in specific states */
! 1524: switch (type)
! 1525: {
! 1526: case IKE_SA_INIT:
! 1527: reject = state != IKE_CREATED;
! 1528: break;
! 1529: case IKE_AUTH:
! 1530: reject = state != IKE_CONNECTING;
! 1531: break;
! 1532: default:
! 1533: break;
! 1534: }
! 1535:
! 1536: if (!reject)
! 1537: {
! 1538: switch (state)
! 1539: {
! 1540: /* after rekeying we only expect a DELETE in an INFORMATIONAL */
! 1541: case IKE_REKEYED:
! 1542: reject = type != INFORMATIONAL;
! 1543: break;
! 1544: /* also reject requests for half-open IKE_SAs as initiator */
! 1545: case IKE_CREATED:
! 1546: case IKE_CONNECTING:
! 1547: ike_sa_id = this->ike_sa->get_id(this->ike_sa);
! 1548: reject = ike_sa_id->is_initiator(ike_sa_id);
! 1549: break;
! 1550: default:
! 1551: break;
! 1552: }
! 1553: }
! 1554:
! 1555: if (reject)
! 1556: {
! 1557: DBG1(DBG_IKE, "ignoring %N in IKE_SA state %N", exchange_type_names,
! 1558: type, ike_sa_state_names, state);
! 1559: }
! 1560: return reject;
! 1561: }
! 1562: /**
! 1563: * Check if a message with message ID 0 looks like it is used to synchronize
! 1564: * the message IDs and we are prepared to process it.
! 1565: *
! 1566: * Note: This is not called if the responder never sent a message before (i.e.
! 1567: * we expect MID 0).
! 1568: */
! 1569: static bool is_mid_sync(private_task_manager_t *this, message_t *msg)
! 1570: {
! 1571: if (this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED &&
! 1572: this->ike_sa->supports_extension(this->ike_sa,
! 1573: EXT_IKE_MESSAGE_ID_SYNC))
! 1574: {
! 1575: return looks_like_mid_sync(this, msg, TRUE);
! 1576: }
! 1577: return FALSE;
! 1578: }
! 1579:
! 1580: METHOD(task_manager_t, process_message, status_t,
! 1581: private_task_manager_t *this, message_t *msg)
! 1582: {
! 1583: host_t *me, *other;
! 1584: status_t status;
! 1585: uint32_t mid;
! 1586: bool schedule_delete_job = FALSE;
! 1587:
! 1588: charon->bus->message(charon->bus, msg, TRUE, FALSE);
! 1589: status = parse_message(this, msg);
! 1590: if (status != SUCCESS)
! 1591: {
! 1592: return status;
! 1593: }
! 1594:
! 1595: me = msg->get_destination(msg);
! 1596: other = msg->get_source(msg);
! 1597:
! 1598: /* if this IKE_SA is virgin, we check for a config */
! 1599: if (this->ike_sa->get_ike_cfg(this->ike_sa) == NULL)
! 1600: {
! 1601: ike_cfg_t *ike_cfg;
! 1602:
! 1603: ike_cfg = charon->backends->get_ike_cfg(charon->backends,
! 1604: me, other, IKEV2);
! 1605: if (ike_cfg == NULL)
! 1606: {
! 1607: /* no config found for these hosts, destroy */
! 1608: DBG1(DBG_IKE, "no IKE config found for %H...%H, sending %N",
! 1609: me, other, notify_type_names, NO_PROPOSAL_CHOSEN);
! 1610: send_notify_response(this, msg,
! 1611: NO_PROPOSAL_CHOSEN, chunk_empty);
! 1612: return DESTROY_ME;
! 1613: }
! 1614: this->ike_sa->set_ike_cfg(this->ike_sa, ike_cfg);
! 1615: ike_cfg->destroy(ike_cfg);
! 1616: /* add a timeout if peer does not establish it completely */
! 1617: schedule_delete_job = TRUE;
! 1618: }
! 1619:
! 1620: mid = msg->get_message_id(msg);
! 1621: if (msg->get_request(msg))
! 1622: {
! 1623: if (mid == this->responding.mid || (mid == 0 && is_mid_sync(this, msg)))
! 1624: {
! 1625: if (reject_request(this, msg))
! 1626: {
! 1627: return FAILED;
! 1628: }
! 1629: if (!this->ike_sa->supports_extension(this->ike_sa, EXT_MOBIKE))
! 1630: { /* with MOBIKE, we do no implicit updates */
! 1631: this->ike_sa->update_hosts(this->ike_sa, me, other, mid == 1);
! 1632: }
! 1633: status = handle_fragment(this, &this->responding.defrag, msg);
! 1634: if (status != SUCCESS)
! 1635: {
! 1636: if (status == NEED_MORE)
! 1637: {
! 1638: this->ike_sa->set_statistic(this->ike_sa, STAT_INBOUND,
! 1639: time_monotonic(NULL));
! 1640: }
! 1641: return status;
! 1642: }
! 1643: charon->bus->message(charon->bus, msg, TRUE, TRUE);
! 1644: if (msg->get_exchange_type(msg) == EXCHANGE_TYPE_UNDEFINED)
! 1645: { /* ignore messages altered to EXCHANGE_TYPE_UNDEFINED */
! 1646: return SUCCESS;
! 1647: }
! 1648: switch (process_request(this, msg))
! 1649: {
! 1650: case SUCCESS:
! 1651: this->ike_sa->set_statistic(this->ike_sa, STAT_INBOUND,
! 1652: time_monotonic(NULL));
! 1653: this->responding.mid++;
! 1654: break;
! 1655: case NEED_MORE:
! 1656: break;
! 1657: default:
! 1658: flush(this);
! 1659: return DESTROY_ME;
! 1660: }
! 1661: }
! 1662: else if ((mid == this->responding.mid - 1) &&
! 1663: array_count(this->responding.packets) &&
! 1664: !(mid == 0 && looks_like_mid_sync(this, msg, FALSE)))
! 1665: {
! 1666: status = handle_fragment(this, &this->responding.defrag, msg);
! 1667: if (status != SUCCESS)
! 1668: {
! 1669: if (status == NEED_MORE)
! 1670: {
! 1671: this->ike_sa->set_statistic(this->ike_sa, STAT_INBOUND,
! 1672: time_monotonic(NULL));
! 1673: }
! 1674: return status;
! 1675: }
! 1676: DBG1(DBG_IKE, "received retransmit of request with ID %d, "
! 1677: "retransmitting response", mid);
! 1678: this->ike_sa->set_statistic(this->ike_sa, STAT_INBOUND,
! 1679: time_monotonic(NULL));
! 1680: charon->bus->alert(charon->bus, ALERT_RETRANSMIT_RECEIVE, msg);
! 1681: send_packets(this, this->responding.packets,
! 1682: msg->get_destination(msg), msg->get_source(msg));
! 1683: }
! 1684: else
! 1685: {
! 1686: DBG1(DBG_IKE, "received message ID %d, expected %d, ignored",
! 1687: mid, this->responding.mid);
! 1688: }
! 1689: }
! 1690: else
! 1691: {
! 1692: if (mid == this->initiating.mid)
! 1693: {
! 1694: if (this->ike_sa->get_state(this->ike_sa) == IKE_CREATED ||
! 1695: this->ike_sa->get_state(this->ike_sa) == IKE_CONNECTING ||
! 1696: msg->get_exchange_type(msg) != IKE_SA_INIT)
! 1697: { /* only do updates based on verified messages (or initial ones) */
! 1698: if (!this->ike_sa->supports_extension(this->ike_sa, EXT_MOBIKE))
! 1699: { /* with MOBIKE, we do no implicit updates. we force an
! 1700: * update of the local address on IKE_SA_INIT, but never
! 1701: * for the remote address */
! 1702: this->ike_sa->update_hosts(this->ike_sa, me, NULL, mid == 0);
! 1703: this->ike_sa->update_hosts(this->ike_sa, NULL, other, FALSE);
! 1704: }
! 1705: }
! 1706: status = handle_fragment(this, &this->initiating.defrag, msg);
! 1707: if (status != SUCCESS)
! 1708: {
! 1709: if (status == NEED_MORE)
! 1710: {
! 1711: this->ike_sa->set_statistic(this->ike_sa, STAT_INBOUND,
! 1712: time_monotonic(NULL));
! 1713: }
! 1714: return status;
! 1715: }
! 1716: charon->bus->message(charon->bus, msg, TRUE, TRUE);
! 1717: if (msg->get_exchange_type(msg) == EXCHANGE_TYPE_UNDEFINED)
! 1718: { /* ignore messages altered to EXCHANGE_TYPE_UNDEFINED */
! 1719: return SUCCESS;
! 1720: }
! 1721: if (process_response(this, msg) != SUCCESS)
! 1722: {
! 1723: flush(this);
! 1724: return DESTROY_ME;
! 1725: }
! 1726: this->ike_sa->set_statistic(this->ike_sa, STAT_INBOUND,
! 1727: time_monotonic(NULL));
! 1728: }
! 1729: else
! 1730: {
! 1731: DBG1(DBG_IKE, "received message ID %d, expected %d, ignored",
! 1732: mid, this->initiating.mid);
! 1733: return SUCCESS;
! 1734: }
! 1735: }
! 1736:
! 1737: if (schedule_delete_job)
! 1738: {
! 1739: ike_sa_id_t *ike_sa_id;
! 1740: job_t *job;
! 1741:
! 1742: ike_sa_id = this->ike_sa->get_id(this->ike_sa);
! 1743: job = (job_t*)delete_ike_sa_job_create(ike_sa_id, FALSE);
! 1744: lib->scheduler->schedule_job(lib->scheduler, job,
! 1745: lib->settings->get_int(lib->settings,
! 1746: "%s.half_open_timeout", HALF_OPEN_IKE_SA_TIMEOUT,
! 1747: lib->ns));
! 1748: }
! 1749: return SUCCESS;
! 1750: }
! 1751:
! 1752: METHOD(task_manager_t, queue_task_delayed, void,
! 1753: private_task_manager_t *this, task_t *task, uint32_t delay)
! 1754: {
! 1755: queued_task_t *queued;
! 1756: timeval_t time;
! 1757:
! 1758: time_monotonic(&time);
! 1759: if (delay)
! 1760: {
! 1761: job_t *job;
! 1762:
! 1763: DBG2(DBG_IKE, "queueing %N task (delayed by %us)", task_type_names,
! 1764: task->get_type(task), delay);
! 1765: time.tv_sec += delay;
! 1766:
! 1767: job = (job_t*)initiate_tasks_job_create(
! 1768: this->ike_sa->get_id(this->ike_sa));
! 1769: lib->scheduler->schedule_job_tv(lib->scheduler, job, time);
! 1770: }
! 1771: else
! 1772: {
! 1773: DBG2(DBG_IKE, "queueing %N task", task_type_names,
! 1774: task->get_type(task));
! 1775: }
! 1776: INIT(queued,
! 1777: .task = task,
! 1778: .time = time,
! 1779: );
! 1780: array_insert(this->queued_tasks, ARRAY_TAIL, queued);
! 1781: }
! 1782:
! 1783: METHOD(task_manager_t, queue_task, void,
! 1784: private_task_manager_t *this, task_t *task)
! 1785: {
! 1786: queue_task_delayed(this, task, 0);
! 1787: }
! 1788:
! 1789: /**
! 1790: * Check if a given task has been queued already
! 1791: */
! 1792: static bool has_queued(private_task_manager_t *this, task_type_t type)
! 1793: {
! 1794: enumerator_t *enumerator;
! 1795: bool found = FALSE;
! 1796: queued_task_t *queued;
! 1797:
! 1798: enumerator = array_create_enumerator(this->queued_tasks);
! 1799: while (enumerator->enumerate(enumerator, &queued))
! 1800: {
! 1801: if (queued->task->get_type(queued->task) == type)
! 1802: {
! 1803: found = TRUE;
! 1804: break;
! 1805: }
! 1806: }
! 1807: enumerator->destroy(enumerator);
! 1808: return found;
! 1809: }
! 1810:
! 1811: METHOD(task_manager_t, queue_ike, void,
! 1812: private_task_manager_t *this)
! 1813: {
! 1814: if (!has_queued(this, TASK_IKE_VENDOR))
! 1815: {
! 1816: queue_task(this, (task_t*)ike_vendor_create(this->ike_sa, TRUE));
! 1817: }
! 1818: if (!has_queued(this, TASK_IKE_INIT))
! 1819: {
! 1820: queue_task(this, (task_t*)ike_init_create(this->ike_sa, TRUE, NULL));
! 1821: }
! 1822: if (!has_queued(this, TASK_IKE_NATD))
! 1823: {
! 1824: queue_task(this, (task_t*)ike_natd_create(this->ike_sa, TRUE));
! 1825: }
! 1826: if (!has_queued(this, TASK_IKE_CERT_PRE))
! 1827: {
! 1828: queue_task(this, (task_t*)ike_cert_pre_create(this->ike_sa, TRUE));
! 1829: }
! 1830: if (!has_queued(this, TASK_IKE_AUTH))
! 1831: {
! 1832: queue_task(this, (task_t*)ike_auth_create(this->ike_sa, TRUE));
! 1833: }
! 1834: if (!has_queued(this, TASK_IKE_CERT_POST))
! 1835: {
! 1836: queue_task(this, (task_t*)ike_cert_post_create(this->ike_sa, TRUE));
! 1837: }
! 1838: if (!has_queued(this, TASK_IKE_CONFIG))
! 1839: {
! 1840: queue_task(this, (task_t*)ike_config_create(this->ike_sa, TRUE));
! 1841: }
! 1842: if (!has_queued(this, TASK_IKE_AUTH_LIFETIME))
! 1843: {
! 1844: queue_task(this, (task_t*)ike_auth_lifetime_create(this->ike_sa, TRUE));
! 1845: }
! 1846: if (!has_queued(this, TASK_IKE_MOBIKE))
! 1847: {
! 1848: peer_cfg_t *peer_cfg;
! 1849:
! 1850: peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
! 1851: if (peer_cfg->use_mobike(peer_cfg))
! 1852: {
! 1853: queue_task(this, (task_t*)ike_mobike_create(this->ike_sa, TRUE));
! 1854: }
! 1855: }
! 1856: #ifdef ME
! 1857: if (!has_queued(this, TASK_IKE_ME))
! 1858: {
! 1859: queue_task(this, (task_t*)ike_me_create(this->ike_sa, TRUE));
! 1860: }
! 1861: #endif /* ME */
! 1862: }
! 1863:
! 1864: METHOD(task_manager_t, queue_ike_rekey, void,
! 1865: private_task_manager_t *this)
! 1866: {
! 1867: queue_task(this, (task_t*)ike_rekey_create(this->ike_sa, TRUE));
! 1868: }
! 1869:
! 1870: /**
! 1871: * Start reauthentication using make-before-break
! 1872: */
! 1873: static void trigger_mbb_reauth(private_task_manager_t *this)
! 1874: {
! 1875: enumerator_t *enumerator;
! 1876: child_sa_t *child_sa;
! 1877: child_cfg_t *cfg;
! 1878: peer_cfg_t *peer;
! 1879: ike_sa_t *new;
! 1880: host_t *host;
! 1881: queued_task_t *queued;
! 1882: bool children = FALSE;
! 1883:
! 1884: new = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager,
! 1885: this->ike_sa->get_version(this->ike_sa), TRUE);
! 1886: if (!new)
! 1887: { /* shouldn't happen */
! 1888: return;
! 1889: }
! 1890:
! 1891: peer = this->ike_sa->get_peer_cfg(this->ike_sa);
! 1892: new->set_peer_cfg(new, peer);
! 1893: host = this->ike_sa->get_other_host(this->ike_sa);
! 1894: new->set_other_host(new, host->clone(host));
! 1895: host = this->ike_sa->get_my_host(this->ike_sa);
! 1896: new->set_my_host(new, host->clone(host));
! 1897: enumerator = this->ike_sa->create_virtual_ip_enumerator(this->ike_sa, TRUE);
! 1898: while (enumerator->enumerate(enumerator, &host))
! 1899: {
! 1900: new->add_virtual_ip(new, TRUE, host);
! 1901: }
! 1902: enumerator->destroy(enumerator);
! 1903:
! 1904: enumerator = this->ike_sa->create_child_sa_enumerator(this->ike_sa);
! 1905: while (enumerator->enumerate(enumerator, &child_sa))
! 1906: {
! 1907: child_create_t *child_create;
! 1908:
! 1909: switch (child_sa->get_state(child_sa))
! 1910: {
! 1911: case CHILD_REKEYED:
! 1912: case CHILD_DELETED:
! 1913: /* ignore CHILD_SAs in these states */
! 1914: continue;
! 1915: default:
! 1916: break;
! 1917: }
! 1918: cfg = child_sa->get_config(child_sa);
! 1919: child_create = child_create_create(new, cfg->get_ref(cfg),
! 1920: FALSE, NULL, NULL);
! 1921: child_create->use_reqid(child_create, child_sa->get_reqid(child_sa));
! 1922: child_create->use_marks(child_create,
! 1923: child_sa->get_mark(child_sa, TRUE).value,
! 1924: child_sa->get_mark(child_sa, FALSE).value);
! 1925: /* interface IDs are not migrated as the new CHILD_SAs on old and new
! 1926: * IKE_SA go though regular updown events */
! 1927: new->queue_task(new, &child_create->task);
! 1928: children = TRUE;
! 1929: }
! 1930: enumerator->destroy(enumerator);
! 1931:
! 1932: enumerator = array_create_enumerator(this->queued_tasks);
! 1933: while (enumerator->enumerate(enumerator, &queued))
! 1934: {
! 1935: if (queued->task->get_type(queued->task) == TASK_CHILD_CREATE)
! 1936: {
! 1937: queued->task->migrate(queued->task, new);
! 1938: new->queue_task(new, queued->task);
! 1939: array_remove_at(this->queued_tasks, enumerator);
! 1940: free(queued);
! 1941: children = TRUE;
! 1942: }
! 1943: }
! 1944: enumerator->destroy(enumerator);
! 1945:
! 1946: if (!children
! 1947: #ifdef ME
! 1948: /* allow reauth of mediation connections without CHILD_SAs */
! 1949: && !peer->is_mediation(peer)
! 1950: #endif /* ME */
! 1951: )
! 1952: {
! 1953: charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, new);
! 1954: DBG1(DBG_IKE, "unable to reauthenticate IKE_SA, no CHILD_SA "
! 1955: "to recreate");
! 1956: return;
! 1957: }
! 1958:
! 1959: /* suspend online revocation checking until the SA is established */
! 1960: new->set_condition(new, COND_ONLINE_VALIDATION_SUSPENDED, TRUE);
! 1961:
! 1962: if (new->initiate(new, NULL, 0, NULL, NULL) != DESTROY_ME)
! 1963: {
! 1964: new->queue_task(new, (task_t*)ike_verify_peer_cert_create(new));
! 1965: new->queue_task(new, (task_t*)ike_reauth_complete_create(new,
! 1966: this->ike_sa->get_id(this->ike_sa)));
! 1967: charon->ike_sa_manager->checkin(charon->ike_sa_manager, new);
! 1968: }
! 1969: else
! 1970: {
! 1971: charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, new);
! 1972: DBG1(DBG_IKE, "reauthenticating IKE_SA failed");
! 1973: }
! 1974: charon->bus->set_sa(charon->bus, this->ike_sa);
! 1975: }
! 1976:
! 1977: METHOD(task_manager_t, queue_ike_reauth, void,
! 1978: private_task_manager_t *this)
! 1979: {
! 1980: if (this->make_before_break)
! 1981: {
! 1982: return trigger_mbb_reauth(this);
! 1983: }
! 1984: queue_task(this, (task_t*)ike_reauth_create(this->ike_sa));
! 1985: }
! 1986:
! 1987: METHOD(task_manager_t, queue_ike_delete, void,
! 1988: private_task_manager_t *this)
! 1989: {
! 1990: queue_task(this, (task_t*)ike_delete_create(this->ike_sa, TRUE));
! 1991: }
! 1992:
! 1993: /**
! 1994: * There is no need to queue more than one mobike task, so this either returns
! 1995: * an already queued task or queues one if there is none yet.
! 1996: */
! 1997: static ike_mobike_t *queue_mobike_task(private_task_manager_t *this)
! 1998: {
! 1999: enumerator_t *enumerator;
! 2000: queued_task_t *queued;
! 2001: ike_mobike_t *mobike = NULL;
! 2002:
! 2003: enumerator = array_create_enumerator(this->queued_tasks);
! 2004: while (enumerator->enumerate(enumerator, &queued))
! 2005: {
! 2006: if (queued->task->get_type(queued->task) == TASK_IKE_MOBIKE)
! 2007: {
! 2008: mobike = (ike_mobike_t*)queued->task;
! 2009: break;
! 2010: }
! 2011: }
! 2012: enumerator->destroy(enumerator);
! 2013:
! 2014: if (!mobike)
! 2015: {
! 2016: mobike = ike_mobike_create(this->ike_sa, TRUE);
! 2017: queue_task(this, &mobike->task);
! 2018: }
! 2019: return mobike;
! 2020: }
! 2021:
! 2022: METHOD(task_manager_t, queue_mobike, void,
! 2023: private_task_manager_t *this, bool roam, bool address)
! 2024: {
! 2025: ike_mobike_t *mobike;
! 2026:
! 2027: mobike = queue_mobike_task(this);
! 2028: if (roam)
! 2029: {
! 2030: enumerator_t *enumerator;
! 2031: task_t *current;
! 2032:
! 2033: mobike->roam(mobike, address);
! 2034:
! 2035: /* enable path probing for a currently active MOBIKE task. This might
! 2036: * not be the case if an address appeared on a new interface while the
! 2037: * current address is not working but has not yet disappeared. */
! 2038: enumerator = array_create_enumerator(this->active_tasks);
! 2039: while (enumerator->enumerate(enumerator, ¤t))
! 2040: {
! 2041: if (current->get_type(current) == TASK_IKE_MOBIKE)
! 2042: {
! 2043: ike_mobike_t *active = (ike_mobike_t*)current;
! 2044: active->enable_probing(active);
! 2045: break;
! 2046: }
! 2047: }
! 2048: enumerator->destroy(enumerator);
! 2049: }
! 2050: else
! 2051: {
! 2052: mobike->addresses(mobike);
! 2053: }
! 2054: }
! 2055:
! 2056: METHOD(task_manager_t, queue_dpd, void,
! 2057: private_task_manager_t *this)
! 2058: {
! 2059: ike_mobike_t *mobike;
! 2060:
! 2061: if (this->ike_sa->supports_extension(this->ike_sa, EXT_MOBIKE))
! 2062: {
! 2063: #ifdef ME
! 2064: peer_cfg_t *cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
! 2065: if (cfg->get_peer_id(cfg) ||
! 2066: this->ike_sa->has_condition(this->ike_sa, COND_ORIGINAL_INITIATOR))
! 2067: #else
! 2068: if (this->ike_sa->has_condition(this->ike_sa, COND_ORIGINAL_INITIATOR))
! 2069: #endif
! 2070: {
! 2071: /* use mobike enabled DPD to detect NAT mapping changes */
! 2072: mobike = queue_mobike_task(this);
! 2073: mobike->dpd(mobike);
! 2074: return;
! 2075: }
! 2076: }
! 2077: queue_task(this, (task_t*)ike_dpd_create(TRUE));
! 2078: }
! 2079:
! 2080: METHOD(task_manager_t, queue_child, void,
! 2081: private_task_manager_t *this, child_cfg_t *cfg, uint32_t reqid,
! 2082: traffic_selector_t *tsi, traffic_selector_t *tsr)
! 2083: {
! 2084: child_create_t *task;
! 2085:
! 2086: task = child_create_create(this->ike_sa, cfg, FALSE, tsi, tsr);
! 2087: if (reqid)
! 2088: {
! 2089: task->use_reqid(task, reqid);
! 2090: }
! 2091: queue_task(this, &task->task);
! 2092: }
! 2093:
! 2094: METHOD(task_manager_t, queue_child_rekey, void,
! 2095: private_task_manager_t *this, protocol_id_t protocol, uint32_t spi)
! 2096: {
! 2097: queue_task(this, (task_t*)child_rekey_create(this->ike_sa, protocol, spi));
! 2098: }
! 2099:
! 2100: METHOD(task_manager_t, queue_child_delete, void,
! 2101: private_task_manager_t *this, protocol_id_t protocol, uint32_t spi,
! 2102: bool expired)
! 2103: {
! 2104: queue_task(this, (task_t*)child_delete_create(this->ike_sa,
! 2105: protocol, spi, expired));
! 2106: }
! 2107:
! 2108: METHOD(task_manager_t, adopt_tasks, void,
! 2109: private_task_manager_t *this, task_manager_t *other_public)
! 2110: {
! 2111: private_task_manager_t *other = (private_task_manager_t*)other_public;
! 2112: queued_task_t *queued;
! 2113: timeval_t now;
! 2114:
! 2115: time_monotonic(&now);
! 2116:
! 2117: /* move queued tasks from other to this */
! 2118: while (array_remove(other->queued_tasks, ARRAY_TAIL, &queued))
! 2119: {
! 2120: DBG2(DBG_IKE, "migrating %N task", task_type_names,
! 2121: queued->task->get_type(queued->task));
! 2122: queued->task->migrate(queued->task, this->ike_sa);
! 2123: /* don't delay tasks on the new IKE_SA */
! 2124: queued->time = now;
! 2125: array_insert(this->queued_tasks, ARRAY_HEAD, queued);
! 2126: }
! 2127: }
! 2128:
! 2129: METHOD(task_manager_t, busy, bool,
! 2130: private_task_manager_t *this)
! 2131: {
! 2132: return array_count(this->active_tasks) > 0;
! 2133: }
! 2134:
! 2135: METHOD(task_manager_t, reset, void,
! 2136: private_task_manager_t *this, uint32_t initiate, uint32_t respond)
! 2137: {
! 2138: enumerator_t *enumerator;
! 2139: queued_task_t *queued;
! 2140: task_t *task;
! 2141: timeval_t now;
! 2142:
! 2143: /* reset message counters and retransmit packets */
! 2144: clear_packets(this->responding.packets);
! 2145: clear_packets(this->initiating.packets);
! 2146: DESTROY_IF(this->responding.defrag);
! 2147: DESTROY_IF(this->initiating.defrag);
! 2148: this->responding.defrag = NULL;
! 2149: this->initiating.defrag = NULL;
! 2150: if (initiate != UINT_MAX)
! 2151: {
! 2152: this->initiating.mid = initiate;
! 2153: }
! 2154: if (respond != UINT_MAX)
! 2155: {
! 2156: this->responding.mid = respond;
! 2157: }
! 2158: this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
! 2159:
! 2160: time_monotonic(&now);
! 2161: /* reset queued tasks */
! 2162: enumerator = array_create_enumerator(this->queued_tasks);
! 2163: while (enumerator->enumerate(enumerator, &queued))
! 2164: {
! 2165: queued->time = now;
! 2166: queued->task->migrate(queued->task, this->ike_sa);
! 2167: }
! 2168: enumerator->destroy(enumerator);
! 2169:
! 2170: /* reset active tasks */
! 2171: while (array_remove(this->active_tasks, ARRAY_TAIL, &task))
! 2172: {
! 2173: task->migrate(task, this->ike_sa);
! 2174: INIT(queued,
! 2175: .task = task,
! 2176: .time = now,
! 2177: );
! 2178: array_insert(this->queued_tasks, ARRAY_HEAD, queued);
! 2179: }
! 2180:
! 2181: this->reset = TRUE;
! 2182: }
! 2183:
! 2184: /**
! 2185: * Data for a task queue enumerator
! 2186: */
! 2187: typedef struct {
! 2188: enumerator_t public;
! 2189: task_queue_t queue;
! 2190: enumerator_t *inner;
! 2191: queued_task_t *queued;
! 2192: } task_enumerator_t;
! 2193:
! 2194: METHOD(enumerator_t, task_enumerator_destroy, void,
! 2195: task_enumerator_t *this)
! 2196: {
! 2197: this->inner->destroy(this->inner);
! 2198: free(this);
! 2199: }
! 2200:
! 2201: METHOD(enumerator_t, task_enumerator_enumerate, bool,
! 2202: task_enumerator_t *this, va_list args)
! 2203: {
! 2204: task_t **task;
! 2205:
! 2206: VA_ARGS_VGET(args, task);
! 2207: if (this->queue == TASK_QUEUE_QUEUED)
! 2208: {
! 2209: if (this->inner->enumerate(this->inner, &this->queued))
! 2210: {
! 2211: *task = this->queued->task;
! 2212: return TRUE;
! 2213: }
! 2214: }
! 2215: else if (this->inner->enumerate(this->inner, task))
! 2216: {
! 2217: return TRUE;
! 2218: }
! 2219: return FALSE;
! 2220: }
! 2221:
! 2222: METHOD(task_manager_t, create_task_enumerator, enumerator_t*,
! 2223: private_task_manager_t *this, task_queue_t queue)
! 2224: {
! 2225: task_enumerator_t *enumerator;
! 2226:
! 2227: INIT(enumerator,
! 2228: .public = {
! 2229: .enumerate = enumerator_enumerate_default,
! 2230: .venumerate = _task_enumerator_enumerate,
! 2231: .destroy = _task_enumerator_destroy,
! 2232: },
! 2233: .queue = queue,
! 2234: );
! 2235: switch (queue)
! 2236: {
! 2237: case TASK_QUEUE_ACTIVE:
! 2238: enumerator->inner = array_create_enumerator(this->active_tasks);
! 2239: break;
! 2240: case TASK_QUEUE_PASSIVE:
! 2241: enumerator->inner = array_create_enumerator(this->passive_tasks);
! 2242: break;
! 2243: case TASK_QUEUE_QUEUED:
! 2244: enumerator->inner = array_create_enumerator(this->queued_tasks);
! 2245: break;
! 2246: default:
! 2247: enumerator->inner = enumerator_create_empty();
! 2248: break;
! 2249: }
! 2250: return &enumerator->public;
! 2251: }
! 2252:
! 2253: METHOD(task_manager_t, remove_task, void,
! 2254: private_task_manager_t *this, enumerator_t *enumerator_public)
! 2255: {
! 2256: task_enumerator_t *enumerator = (task_enumerator_t*)enumerator_public;
! 2257:
! 2258: switch (enumerator->queue)
! 2259: {
! 2260: case TASK_QUEUE_ACTIVE:
! 2261: array_remove_at(this->active_tasks, enumerator->inner);
! 2262: break;
! 2263: case TASK_QUEUE_PASSIVE:
! 2264: array_remove_at(this->passive_tasks, enumerator->inner);
! 2265: break;
! 2266: case TASK_QUEUE_QUEUED:
! 2267: array_remove_at(this->queued_tasks, enumerator->inner);
! 2268: free(enumerator->queued);
! 2269: enumerator->queued = NULL;
! 2270: break;
! 2271: default:
! 2272: break;
! 2273: }
! 2274: }
! 2275:
! 2276: METHOD(task_manager_t, destroy, void,
! 2277: private_task_manager_t *this)
! 2278: {
! 2279: flush(this);
! 2280:
! 2281: array_destroy(this->active_tasks);
! 2282: array_destroy(this->queued_tasks);
! 2283: array_destroy(this->passive_tasks);
! 2284:
! 2285: clear_packets(this->responding.packets);
! 2286: array_destroy(this->responding.packets);
! 2287: clear_packets(this->initiating.packets);
! 2288: array_destroy(this->initiating.packets);
! 2289: DESTROY_IF(this->responding.defrag);
! 2290: DESTROY_IF(this->initiating.defrag);
! 2291: free(this);
! 2292: }
! 2293:
! 2294: /*
! 2295: * see header file
! 2296: */
! 2297: task_manager_v2_t *task_manager_v2_create(ike_sa_t *ike_sa)
! 2298: {
! 2299: private_task_manager_t *this;
! 2300:
! 2301: INIT(this,
! 2302: .public = {
! 2303: .task_manager = {
! 2304: .process_message = _process_message,
! 2305: .queue_task = _queue_task,
! 2306: .queue_task_delayed = _queue_task_delayed,
! 2307: .queue_ike = _queue_ike,
! 2308: .queue_ike_rekey = _queue_ike_rekey,
! 2309: .queue_ike_reauth = _queue_ike_reauth,
! 2310: .queue_ike_delete = _queue_ike_delete,
! 2311: .queue_mobike = _queue_mobike,
! 2312: .queue_child = _queue_child,
! 2313: .queue_child_rekey = _queue_child_rekey,
! 2314: .queue_child_delete = _queue_child_delete,
! 2315: .queue_dpd = _queue_dpd,
! 2316: .initiate = _initiate,
! 2317: .retransmit = _retransmit,
! 2318: .incr_mid = _incr_mid,
! 2319: .get_mid = _get_mid,
! 2320: .reset = _reset,
! 2321: .adopt_tasks = _adopt_tasks,
! 2322: .busy = _busy,
! 2323: .create_task_enumerator = _create_task_enumerator,
! 2324: .remove_task = _remove_task,
! 2325: .flush = _flush,
! 2326: .flush_queue = _flush_queue,
! 2327: .destroy = _destroy,
! 2328: },
! 2329: },
! 2330: .ike_sa = ike_sa,
! 2331: .initiating.type = EXCHANGE_TYPE_UNDEFINED,
! 2332: .queued_tasks = array_create(0, 0),
! 2333: .active_tasks = array_create(0, 0),
! 2334: .passive_tasks = array_create(0, 0),
! 2335: .retransmit_tries = lib->settings->get_int(lib->settings,
! 2336: "%s.retransmit_tries", RETRANSMIT_TRIES, lib->ns),
! 2337: .retransmit_timeout = lib->settings->get_double(lib->settings,
! 2338: "%s.retransmit_timeout", RETRANSMIT_TIMEOUT, lib->ns),
! 2339: .retransmit_base = lib->settings->get_double(lib->settings,
! 2340: "%s.retransmit_base", RETRANSMIT_BASE, lib->ns),
! 2341: .retransmit_jitter = min(lib->settings->get_int(lib->settings,
! 2342: "%s.retransmit_jitter", 0, lib->ns), RETRANSMIT_JITTER_MAX),
! 2343: .retransmit_limit = lib->settings->get_int(lib->settings,
! 2344: "%s.retransmit_limit", 0, lib->ns) * 1000,
! 2345: .make_before_break = lib->settings->get_bool(lib->settings,
! 2346: "%s.make_before_break", FALSE, lib->ns),
! 2347: );
! 2348:
! 2349: return &this->public;
! 2350: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>