Annotation of embedaddon/strongswan/src/libcharon/sa/ikev2/tasks/ike_auth.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2012-2018 Tobias Brunner
! 3: * Copyright (C) 2005-2009 Martin Willi
! 4: * Copyright (C) 2005 Jan Hutter
! 5: * HSR Hochschule fuer Technik Rapperswil
! 6: *
! 7: * This program is free software; you can redistribute it and/or modify it
! 8: * under the terms of the GNU General Public License as published by the
! 9: * Free Software Foundation; either version 2 of the License, or (at your
! 10: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
! 11: *
! 12: * This program is distributed in the hope that it will be useful, but
! 13: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
! 14: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
! 15: * for more details.
! 16: */
! 17:
! 18: #include "ike_auth.h"
! 19:
! 20: #include <string.h>
! 21:
! 22: #include <daemon.h>
! 23: #include <encoding/payloads/id_payload.h>
! 24: #include <encoding/payloads/auth_payload.h>
! 25: #include <encoding/payloads/eap_payload.h>
! 26: #include <encoding/payloads/nonce_payload.h>
! 27: #include <sa/ikev2/keymat_v2.h>
! 28: #include <sa/ikev2/authenticators/eap_authenticator.h>
! 29: #include <processing/jobs/delete_ike_sa_job.h>
! 30:
! 31: typedef struct private_ike_auth_t private_ike_auth_t;
! 32:
! 33: /**
! 34: * Private members of a ike_auth_t task.
! 35: */
! 36: struct private_ike_auth_t {
! 37:
! 38: /**
! 39: * Public methods and task_t interface.
! 40: */
! 41: ike_auth_t public;
! 42:
! 43: /**
! 44: * Assigned IKE_SA.
! 45: */
! 46: ike_sa_t *ike_sa;
! 47:
! 48: /**
! 49: * Are we the initiator?
! 50: */
! 51: bool initiator;
! 52:
! 53: /**
! 54: * Nonce chosen by us in ike_init
! 55: */
! 56: chunk_t my_nonce;
! 57:
! 58: /**
! 59: * Nonce chosen by peer in ike_init
! 60: */
! 61: chunk_t other_nonce;
! 62:
! 63: /**
! 64: * PPK_ID sent or received
! 65: */
! 66: identification_t *ppk_id;
! 67:
! 68: /**
! 69: * Optional PPK to use
! 70: */
! 71: chunk_t ppk;
! 72:
! 73: /**
! 74: * IKE_SA_INIT message sent by us
! 75: */
! 76: packet_t *my_packet;
! 77:
! 78: /**
! 79: * IKE_SA_INIT message sent by peer
! 80: */
! 81: packet_t *other_packet;
! 82:
! 83: /**
! 84: * Reserved bytes of ID payload
! 85: */
! 86: char reserved[3];
! 87:
! 88: /**
! 89: * currently active authenticator, to authenticate us
! 90: */
! 91: authenticator_t *my_auth;
! 92:
! 93: /**
! 94: * currently active authenticator, to authenticate peer
! 95: */
! 96: authenticator_t *other_auth;
! 97:
! 98: /**
! 99: * peer_cfg candidates, ordered by priority
! 100: */
! 101: linked_list_t *candidates;
! 102:
! 103: /**
! 104: * selected peer config (might change when using multiple authentications)
! 105: */
! 106: peer_cfg_t *peer_cfg;
! 107:
! 108: /**
! 109: * have we planned an(other) authentication exchange?
! 110: */
! 111: bool do_another_auth;
! 112:
! 113: /**
! 114: * has the peer announced another authentication exchange?
! 115: */
! 116: bool expect_another_auth;
! 117:
! 118: /**
! 119: * should we send a AUTHENTICATION_FAILED notify?
! 120: */
! 121: bool authentication_failed;
! 122:
! 123: /**
! 124: * received an INITIAL_CONTACT?
! 125: */
! 126: bool initial_contact;
! 127:
! 128: /**
! 129: * Is EAP acceptable, did we strictly authenticate peer?
! 130: */
! 131: bool eap_acceptable;
! 132:
! 133: /**
! 134: * Gateway ID if redirected
! 135: */
! 136: identification_t *redirect_to;
! 137: };
! 138:
! 139: /**
! 140: * check if multiple authentication extension is enabled, configuration-wise
! 141: */
! 142: static bool multiple_auth_enabled()
! 143: {
! 144: return lib->settings->get_bool(lib->settings,
! 145: "%s.multiple_authentication", TRUE, lib->ns);
! 146: }
! 147:
! 148: /**
! 149: * collect the needed information in the IKE_SA_INIT exchange from our message
! 150: */
! 151: static status_t collect_my_init_data(private_ike_auth_t *this,
! 152: message_t *message)
! 153: {
! 154: nonce_payload_t *nonce;
! 155:
! 156: /* get the nonce that was generated in ike_init */
! 157: nonce = (nonce_payload_t*)message->get_payload(message, PLV2_NONCE);
! 158: if (!nonce)
! 159: {
! 160: return FAILED;
! 161: }
! 162: this->my_nonce = nonce->get_nonce(nonce);
! 163:
! 164: /* pre-generate the message, keep a copy */
! 165: if (this->ike_sa->generate_message(this->ike_sa, message,
! 166: &this->my_packet) != SUCCESS)
! 167: {
! 168: return FAILED;
! 169: }
! 170: return NEED_MORE;
! 171: }
! 172:
! 173: /**
! 174: * collect the needed information in the IKE_SA_INIT exchange from others message
! 175: */
! 176: static status_t collect_other_init_data(private_ike_auth_t *this,
! 177: message_t *message)
! 178: {
! 179: /* we collect the needed information in the IKE_SA_INIT exchange */
! 180: nonce_payload_t *nonce;
! 181:
! 182: /* get the nonce that was generated in ike_init */
! 183: nonce = (nonce_payload_t*)message->get_payload(message, PLV2_NONCE);
! 184: if (!nonce)
! 185: {
! 186: return FAILED;
! 187: }
! 188: this->other_nonce = nonce->get_nonce(nonce);
! 189:
! 190: /* keep a copy of the received packet */
! 191: this->other_packet = message->get_packet(message);
! 192: return NEED_MORE;
! 193: }
! 194:
! 195: /**
! 196: * Get and store reserved bytes of id_payload, required for AUTH payload
! 197: */
! 198: static void get_reserved_id_bytes(private_ike_auth_t *this, id_payload_t *id)
! 199: {
! 200: uint8_t *byte;
! 201: int i;
! 202:
! 203: for (i = 0; i < countof(this->reserved); i++)
! 204: {
! 205: byte = payload_get_field(&id->payload_interface, RESERVED_BYTE, i);
! 206: if (byte)
! 207: {
! 208: this->reserved[i] = *byte;
! 209: }
! 210: }
! 211: }
! 212:
! 213: /**
! 214: * Get the next authentication configuration
! 215: */
! 216: static auth_cfg_t *get_auth_cfg(private_ike_auth_t *this, bool local)
! 217: {
! 218: enumerator_t *e1, *e2;
! 219: auth_cfg_t *c1, *c2, *next = NULL;
! 220:
! 221: /* find an available config not already done */
! 222: e1 = this->peer_cfg->create_auth_cfg_enumerator(this->peer_cfg, local);
! 223: while (e1->enumerate(e1, &c1))
! 224: {
! 225: bool found = FALSE;
! 226:
! 227: e2 = this->ike_sa->create_auth_cfg_enumerator(this->ike_sa, local);
! 228: while (e2->enumerate(e2, &c2))
! 229: {
! 230: if (c2->complies(c2, c1, FALSE))
! 231: {
! 232: found = TRUE;
! 233: break;
! 234: }
! 235: }
! 236: e2->destroy(e2);
! 237: if (!found)
! 238: {
! 239: next = c1;
! 240: break;
! 241: }
! 242: }
! 243: e1->destroy(e1);
! 244: return next;
! 245: }
! 246:
! 247: /**
! 248: * Move the currently active auth config to the auth configs completed
! 249: */
! 250: static void apply_auth_cfg(private_ike_auth_t *this, bool local)
! 251: {
! 252: auth_cfg_t *cfg;
! 253:
! 254: cfg = auth_cfg_create();
! 255: cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, local), local);
! 256: this->ike_sa->add_auth_cfg(this->ike_sa, local, cfg);
! 257: }
! 258:
! 259: /**
! 260: * Check if we have should initiate another authentication round
! 261: */
! 262: static bool do_another_auth(private_ike_auth_t *this)
! 263: {
! 264: bool do_another = FALSE;
! 265: enumerator_t *done, *todo;
! 266: auth_cfg_t *done_cfg, *todo_cfg;
! 267:
! 268: if (!this->ike_sa->supports_extension(this->ike_sa, EXT_MULTIPLE_AUTH))
! 269: {
! 270: return FALSE;
! 271: }
! 272:
! 273: done = this->ike_sa->create_auth_cfg_enumerator(this->ike_sa, TRUE);
! 274: todo = this->peer_cfg->create_auth_cfg_enumerator(this->peer_cfg, TRUE);
! 275: while (todo->enumerate(todo, &todo_cfg))
! 276: {
! 277: if (!done->enumerate(done, &done_cfg))
! 278: {
! 279: done_cfg = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
! 280: }
! 281: if (!done_cfg->complies(done_cfg, todo_cfg, FALSE))
! 282: {
! 283: do_another = TRUE;
! 284: break;
! 285: }
! 286: }
! 287: done->destroy(done);
! 288: todo->destroy(todo);
! 289: return do_another;
! 290: }
! 291:
! 292: /**
! 293: * Check if this is the first authentication round
! 294: */
! 295: static bool is_first_round(private_ike_auth_t *this, bool local)
! 296: {
! 297: enumerator_t *done;
! 298: auth_cfg_t *cfg;
! 299:
! 300: if (!this->ike_sa->supports_extension(this->ike_sa, EXT_MULTIPLE_AUTH))
! 301: {
! 302: return TRUE;
! 303: }
! 304:
! 305: done = this->ike_sa->create_auth_cfg_enumerator(this->ike_sa, local);
! 306: if (done->enumerate(done, &cfg))
! 307: {
! 308: done->destroy(done);
! 309: return FALSE;
! 310: }
! 311: done->destroy(done);
! 312: return TRUE;
! 313: }
! 314:
! 315: /**
! 316: * Get peer configuration candidates from backends
! 317: */
! 318: static bool load_cfg_candidates(private_ike_auth_t *this)
! 319: {
! 320: enumerator_t *enumerator;
! 321: peer_cfg_t *peer_cfg;
! 322: ike_cfg_t *ike_cfg;
! 323: host_t *me, *other;
! 324: identification_t *my_id, *other_id;
! 325: proposal_t *ike_proposal;
! 326: bool private;
! 327:
! 328: me = this->ike_sa->get_my_host(this->ike_sa);
! 329: other = this->ike_sa->get_other_host(this->ike_sa);
! 330: my_id = this->ike_sa->get_my_id(this->ike_sa);
! 331: other_id = this->ike_sa->get_other_id(this->ike_sa);
! 332: ike_proposal = this->ike_sa->get_proposal(this->ike_sa);
! 333: private = this->ike_sa->supports_extension(this->ike_sa, EXT_STRONGSWAN) ||
! 334: lib->settings->get_bool(lib->settings, "%s.accept_private_algs",
! 335: FALSE, lib->ns);
! 336:
! 337: DBG1(DBG_CFG, "looking for peer configs matching %H[%Y]...%H[%Y]",
! 338: me, my_id, other, other_id);
! 339: enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends,
! 340: me, other, my_id, other_id, IKEV2);
! 341: while (enumerator->enumerate(enumerator, &peer_cfg))
! 342: {
! 343: /* ignore all configs that have no matching IKE proposal */
! 344: ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
! 345: if (!ike_cfg->has_proposal(ike_cfg, ike_proposal, private))
! 346: {
! 347: DBG2(DBG_CFG, "ignore candidate '%s' without matching IKE proposal",
! 348: peer_cfg->get_name(peer_cfg));
! 349: continue;
! 350: }
! 351: peer_cfg->get_ref(peer_cfg);
! 352: if (!this->peer_cfg)
! 353: { /* best match */
! 354: this->peer_cfg = peer_cfg;
! 355: }
! 356: else
! 357: {
! 358: this->candidates->insert_last(this->candidates, peer_cfg);
! 359: }
! 360: }
! 361: enumerator->destroy(enumerator);
! 362: if (this->peer_cfg)
! 363: {
! 364: this->ike_sa->set_peer_cfg(this->ike_sa, this->peer_cfg);
! 365: DBG1(DBG_CFG, "selected peer config '%s'",
! 366: this->peer_cfg->get_name(this->peer_cfg));
! 367: return TRUE;
! 368: }
! 369: DBG1(DBG_CFG, "no matching peer config found");
! 370: return FALSE;
! 371: }
! 372:
! 373: /**
! 374: * update the current peer candidate if necessary, using candidates
! 375: */
! 376: static bool update_cfg_candidates(private_ike_auth_t *this, bool strict)
! 377: {
! 378: do
! 379: {
! 380: if (this->peer_cfg)
! 381: {
! 382: char *comply_error = NULL;
! 383: enumerator_t *e1, *e2, *tmp;
! 384: auth_cfg_t *c1, *c2;
! 385:
! 386: e1 = this->ike_sa->create_auth_cfg_enumerator(this->ike_sa, FALSE);
! 387: e2 = this->peer_cfg->create_auth_cfg_enumerator(this->peer_cfg, FALSE);
! 388:
! 389: if (strict)
! 390: { /* swap lists in strict mode: all configured rounds must be
! 391: * fulfilled. If !strict, we check only the rounds done so far. */
! 392: tmp = e1;
! 393: e1 = e2;
! 394: e2 = tmp;
! 395: }
! 396: while (e1->enumerate(e1, &c1))
! 397: {
! 398: /* check if done authentications comply to configured ones */
! 399: if (!e2->enumerate(e2, &c2))
! 400: {
! 401: comply_error = "insufficient authentication rounds";
! 402: break;
! 403: }
! 404: if (!strict && !c1->complies(c1, c2, TRUE))
! 405: {
! 406: comply_error = "non-matching authentication done";
! 407: break;
! 408: }
! 409: if (strict && !c2->complies(c2, c1, TRUE))
! 410: {
! 411: comply_error = "constraint checking failed";
! 412: break;
! 413: }
! 414: }
! 415: e1->destroy(e1);
! 416: e2->destroy(e2);
! 417: if (!comply_error)
! 418: {
! 419: break;
! 420: }
! 421: DBG1(DBG_CFG, "selected peer config '%s' unacceptable: %s",
! 422: this->peer_cfg->get_name(this->peer_cfg), comply_error);
! 423: this->peer_cfg->destroy(this->peer_cfg);
! 424: }
! 425: if (this->candidates->remove_first(this->candidates,
! 426: (void**)&this->peer_cfg) != SUCCESS)
! 427: {
! 428: DBG1(DBG_CFG, "no alternative config found");
! 429: this->peer_cfg = NULL;
! 430: }
! 431: else
! 432: {
! 433: DBG1(DBG_CFG, "switching to peer config '%s'",
! 434: this->peer_cfg->get_name(this->peer_cfg));
! 435: this->ike_sa->set_peer_cfg(this->ike_sa, this->peer_cfg);
! 436: }
! 437: }
! 438: while (this->peer_cfg);
! 439:
! 440: return this->peer_cfg != NULL;
! 441: }
! 442:
! 443: /**
! 444: * Currently defined PPK_ID types
! 445: */
! 446: #define PPK_ID_OPAQUE 1
! 447: #define PPK_ID_FIXED 2
! 448:
! 449: /**
! 450: * Parse the payload data of the given PPK_IDENTITY notify
! 451: */
! 452: static bool parse_ppk_identity(notify_payload_t *notify, identification_t **id)
! 453: {
! 454: chunk_t data;
! 455:
! 456: data = notify->get_notification_data(notify);
! 457: if (data.len < 2)
! 458: {
! 459: return FALSE;
! 460: }
! 461: switch (data.ptr[0])
! 462: {
! 463: case PPK_ID_FIXED:
! 464: data = chunk_skip(data, 1);
! 465: break;
! 466: default:
! 467: return FALSE;
! 468: }
! 469: *id = identification_create_from_data(data);
! 470: return TRUE;
! 471: }
! 472:
! 473: /**
! 474: * Add a PPK_IDENTITY with the given PPK_ID to the given message
! 475: */
! 476: static void add_ppk_identity(identification_t *id, message_t *msg)
! 477: {
! 478: chunk_t data;
! 479: uint8_t type = PPK_ID_FIXED;
! 480:
! 481: /* we currently only support one type */
! 482: data = chunk_cata("cc", chunk_from_thing(type), id->get_encoding(id));
! 483: msg->add_notify(msg, FALSE, PPK_IDENTITY, data);
! 484: }
! 485:
! 486: /**
! 487: * Use the given PPK_ID to find a PPK and store it and the ID in the task
! 488: */
! 489: static bool get_ppk(private_ike_auth_t *this, identification_t *ppk_id)
! 490: {
! 491: shared_key_t *key;
! 492:
! 493: key = lib->credmgr->get_shared(lib->credmgr, SHARED_PPK, ppk_id, NULL);
! 494: if (!key)
! 495: {
! 496: if (this->peer_cfg->ppk_required(this->peer_cfg))
! 497: {
! 498: DBG1(DBG_CFG, "PPK required but no PPK found for '%Y'", ppk_id);
! 499: return FALSE;
! 500: }
! 501: DBG1(DBG_CFG, "no PPK for '%Y' found, ignored because PPK is not "
! 502: "required", ppk_id);
! 503: return TRUE;
! 504: }
! 505: this->ppk = chunk_clone(key->get_key(key));
! 506: this->ppk_id = ppk_id->clone(ppk_id);
! 507: key->destroy(key);
! 508: return TRUE;
! 509: }
! 510:
! 511: /**
! 512: * Check if we have a PPK available and, if not, whether we require one as
! 513: * initiator
! 514: */
! 515: static bool get_ppk_i(private_ike_auth_t *this)
! 516: {
! 517: identification_t *ppk_id;
! 518:
! 519: if (!this->ike_sa->supports_extension(this->ike_sa, EXT_PPK))
! 520: {
! 521: if (this->peer_cfg->ppk_required(this->peer_cfg))
! 522: {
! 523: DBG1(DBG_CFG, "PPK required but peer does not support PPK");
! 524: return FALSE;
! 525: }
! 526: return TRUE;
! 527: }
! 528:
! 529: ppk_id = this->peer_cfg->get_ppk_id(this->peer_cfg);
! 530: if (!ppk_id)
! 531: {
! 532: if (this->peer_cfg->ppk_required(this->peer_cfg))
! 533: {
! 534: DBG1(DBG_CFG, "PPK required but no PPK_ID configured");
! 535: return FALSE;
! 536: }
! 537: return TRUE;
! 538: }
! 539: return get_ppk(this, ppk_id);
! 540: }
! 541:
! 542: /**
! 543: * Check if we have a PPK available and if not whether we require one as
! 544: * responder
! 545: */
! 546: static bool get_ppk_r(private_ike_auth_t *this, message_t *msg)
! 547: {
! 548: notify_payload_t *notify;
! 549: identification_t *ppk_id, *ppk_id_cfg;
! 550: bool result;
! 551:
! 552: if (!this->ike_sa->supports_extension(this->ike_sa, EXT_PPK))
! 553: {
! 554: if (this->peer_cfg->ppk_required(this->peer_cfg))
! 555: {
! 556: DBG1(DBG_CFG, "PPK required but peer does not support PPK");
! 557: return FALSE;
! 558: }
! 559: return TRUE;
! 560: }
! 561:
! 562: notify = msg->get_notify(msg, PPK_IDENTITY);
! 563: if (!notify || !parse_ppk_identity(notify, &ppk_id))
! 564: {
! 565: if (this->peer_cfg->ppk_required(this->peer_cfg))
! 566: {
! 567: DBG1(DBG_CFG, "PPK required but no PPK_IDENTITY received");
! 568: return FALSE;
! 569: }
! 570: return TRUE;
! 571: }
! 572:
! 573: ppk_id_cfg = this->peer_cfg->get_ppk_id(this->peer_cfg);
! 574: if (ppk_id_cfg && !ppk_id->matches(ppk_id, ppk_id_cfg))
! 575: {
! 576: DBG1(DBG_CFG, "received PPK_ID '%Y', but require '%Y'", ppk_id,
! 577: ppk_id_cfg);
! 578: ppk_id->destroy(ppk_id);
! 579: return FALSE;
! 580: }
! 581: result = get_ppk(this, ppk_id);
! 582: ppk_id->destroy(ppk_id);
! 583: return result;
! 584: }
! 585:
! 586: METHOD(task_t, build_i, status_t,
! 587: private_ike_auth_t *this, message_t *message)
! 588: {
! 589: auth_cfg_t *cfg;
! 590:
! 591: if (message->get_exchange_type(message) == IKE_SA_INIT)
! 592: {
! 593: return collect_my_init_data(this, message);
! 594: }
! 595:
! 596: if (!this->peer_cfg)
! 597: {
! 598: this->peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
! 599: this->peer_cfg->get_ref(this->peer_cfg);
! 600: }
! 601:
! 602: if (message->get_message_id(message) == 1)
! 603: { /* in the first IKE_AUTH ... */
! 604: if (this->ike_sa->supports_extension(this->ike_sa, EXT_MULTIPLE_AUTH))
! 605: { /* indicate support for multiple authentication */
! 606: message->add_notify(message, FALSE, MULTIPLE_AUTH_SUPPORTED,
! 607: chunk_empty);
! 608: }
! 609: /* indicate support for EAP-only authentication */
! 610: message->add_notify(message, FALSE, EAP_ONLY_AUTHENTICATION,
! 611: chunk_empty);
! 612: /* indicate support for RFC 6311 Message ID synchronization */
! 613: message->add_notify(message, FALSE, IKEV2_MESSAGE_ID_SYNC_SUPPORTED,
! 614: chunk_empty);
! 615: /* only use a PPK in the first round */
! 616: if (!get_ppk_i(this))
! 617: {
! 618: charon->bus->alert(charon->bus, ALERT_LOCAL_AUTH_FAILED);
! 619: return FAILED;
! 620: }
! 621: }
! 622:
! 623: if (!this->do_another_auth && !this->my_auth)
! 624: { /* we have done our rounds */
! 625: return NEED_MORE;
! 626: }
! 627:
! 628: /* check if an authenticator is in progress */
! 629: if (!this->my_auth)
! 630: {
! 631: identification_t *idi, *idr = NULL;
! 632: id_payload_t *id_payload;
! 633:
! 634: /* clean up authentication config from a previous round */
! 635: cfg = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
! 636: cfg->purge(cfg, TRUE);
! 637:
! 638: /* add (optional) IDr */
! 639: cfg = get_auth_cfg(this, FALSE);
! 640: if (cfg)
! 641: {
! 642: idr = cfg->get(cfg, AUTH_RULE_IDENTITY);
! 643: if (!cfg->get(cfg, AUTH_RULE_IDENTITY_LOOSE) && idr &&
! 644: !idr->contains_wildcards(idr))
! 645: {
! 646: this->ike_sa->set_other_id(this->ike_sa, idr->clone(idr));
! 647: id_payload = id_payload_create_from_identification(
! 648: PLV2_ID_RESPONDER, idr);
! 649: message->add_payload(message, (payload_t*)id_payload);
! 650: }
! 651: }
! 652: /* add IDi */
! 653: cfg = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
! 654: cfg->merge(cfg, get_auth_cfg(this, TRUE), TRUE);
! 655: idi = cfg->get(cfg, AUTH_RULE_IDENTITY);
! 656: if (!idi || idi->get_type(idi) == ID_ANY)
! 657: { /* ID_ANY is invalid as IDi, use local IP address instead */
! 658: host_t *me;
! 659:
! 660: DBG1(DBG_CFG, "no IDi configured, fall back on IP address");
! 661: me = this->ike_sa->get_my_host(this->ike_sa);
! 662: idi = identification_create_from_sockaddr(me->get_sockaddr(me));
! 663: cfg->add(cfg, AUTH_RULE_IDENTITY, idi);
! 664: }
! 665: this->ike_sa->set_my_id(this->ike_sa, idi->clone(idi));
! 666: id_payload = id_payload_create_from_identification(PLV2_ID_INITIATOR, idi);
! 667: get_reserved_id_bytes(this, id_payload);
! 668: message->add_payload(message, (payload_t*)id_payload);
! 669:
! 670: if (idr && !idr->contains_wildcards(idr) &&
! 671: message->get_message_id(message) == 1 &&
! 672: this->peer_cfg->get_unique_policy(this->peer_cfg) != UNIQUE_NEVER)
! 673: {
! 674: host_t *host;
! 675:
! 676: host = this->ike_sa->get_other_host(this->ike_sa);
! 677: if (!charon->ike_sa_manager->has_contact(charon->ike_sa_manager,
! 678: idi, idr, host->get_family(host)))
! 679: {
! 680: message->add_notify(message, FALSE, INITIAL_CONTACT, chunk_empty);
! 681: }
! 682: }
! 683:
! 684: /* build authentication data */
! 685: this->my_auth = authenticator_create_builder(this->ike_sa, cfg,
! 686: this->other_nonce, this->my_nonce,
! 687: this->other_packet->get_data(this->other_packet),
! 688: this->my_packet->get_data(this->my_packet),
! 689: this->reserved);
! 690: if (!this->my_auth)
! 691: {
! 692: charon->bus->alert(charon->bus, ALERT_LOCAL_AUTH_FAILED);
! 693: return FAILED;
! 694: }
! 695: }
! 696: /* for authentication methods that return NEED_MORE, the PPK will be reset
! 697: * in process_i() for messages without PPK_ID notify, so we always set it
! 698: * during the first round (afterwards the PPK won't be available) */
! 699: if (this->ppk.ptr && this->my_auth->use_ppk)
! 700: {
! 701: this->my_auth->use_ppk(this->my_auth, this->ppk,
! 702: !this->peer_cfg->ppk_required(this->peer_cfg));
! 703: }
! 704: switch (this->my_auth->build(this->my_auth, message))
! 705: {
! 706: case SUCCESS:
! 707: apply_auth_cfg(this, TRUE);
! 708: this->my_auth->destroy(this->my_auth);
! 709: this->my_auth = NULL;
! 710: break;
! 711: case NEED_MORE:
! 712: break;
! 713: default:
! 714: charon->bus->alert(charon->bus, ALERT_LOCAL_AUTH_FAILED);
! 715: return FAILED;
! 716: }
! 717:
! 718: /* add a PPK_IDENTITY notify to the message that contains AUTH */
! 719: if (this->ppk_id && message->get_payload(message, PLV2_AUTH))
! 720: {
! 721: add_ppk_identity(this->ppk_id, message);
! 722: }
! 723:
! 724: /* check for additional authentication rounds */
! 725: if (do_another_auth(this))
! 726: {
! 727: if (message->get_payload(message, PLV2_AUTH))
! 728: {
! 729: message->add_notify(message, FALSE, ANOTHER_AUTH_FOLLOWS, chunk_empty);
! 730: }
! 731: }
! 732: else
! 733: {
! 734: this->do_another_auth = FALSE;
! 735: }
! 736: return NEED_MORE;
! 737: }
! 738:
! 739: METHOD(task_t, process_r, status_t,
! 740: private_ike_auth_t *this, message_t *message)
! 741: {
! 742: auth_cfg_t *cfg, *cand;
! 743: id_payload_t *id_payload;
! 744: identification_t *id;
! 745:
! 746: if (message->get_exchange_type(message) == IKE_SA_INIT)
! 747: {
! 748: return collect_other_init_data(this, message);
! 749: }
! 750:
! 751: if (!this->my_auth && this->do_another_auth)
! 752: {
! 753: /* handle (optional) IDr payload, apply proposed identity */
! 754: id_payload = (id_payload_t*)message->get_payload(message, PLV2_ID_RESPONDER);
! 755: if (id_payload)
! 756: {
! 757: id = id_payload->get_identification(id_payload);
! 758: }
! 759: else
! 760: {
! 761: id = identification_create_from_encoding(ID_ANY, chunk_empty);
! 762: }
! 763: this->ike_sa->set_my_id(this->ike_sa, id);
! 764: }
! 765:
! 766: if (!this->expect_another_auth)
! 767: {
! 768: return NEED_MORE;
! 769: }
! 770:
! 771: if (message->get_message_id(message) == 1)
! 772: { /* check for extensions in the first IKE_AUTH */
! 773: if (message->get_notify(message, MULTIPLE_AUTH_SUPPORTED))
! 774: {
! 775: this->ike_sa->enable_extension(this->ike_sa, EXT_MULTIPLE_AUTH);
! 776: }
! 777: if (message->get_notify(message, EAP_ONLY_AUTHENTICATION))
! 778: {
! 779: this->ike_sa->enable_extension(this->ike_sa,
! 780: EXT_EAP_ONLY_AUTHENTICATION);
! 781: }
! 782: if (message->get_notify(message, INITIAL_CONTACT))
! 783: {
! 784: this->initial_contact = TRUE;
! 785: }
! 786: }
! 787:
! 788: if (!this->other_auth)
! 789: {
! 790: /* handle IDi payload */
! 791: id_payload = (id_payload_t*)message->get_payload(message, PLV2_ID_INITIATOR);
! 792: if (!id_payload)
! 793: {
! 794: DBG1(DBG_IKE, "IDi payload missing");
! 795: return FAILED;
! 796: }
! 797: id = id_payload->get_identification(id_payload);
! 798: get_reserved_id_bytes(this, id_payload);
! 799: this->ike_sa->set_other_id(this->ike_sa, id);
! 800: cfg = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
! 801: cfg->add(cfg, AUTH_RULE_IDENTITY, id->clone(id));
! 802:
! 803: if (!this->peer_cfg)
! 804: {
! 805: if (!load_cfg_candidates(this))
! 806: {
! 807: this->authentication_failed = TRUE;
! 808: return NEED_MORE;
! 809: }
! 810: }
! 811: if (!message->get_payload(message, PLV2_AUTH))
! 812: { /* before authenticating with EAP, we need a EAP config */
! 813: cand = get_auth_cfg(this, FALSE);
! 814: while (!cand || (
! 815: (uintptr_t)cand->get(cand, AUTH_RULE_EAP_TYPE) == EAP_NAK &&
! 816: (uintptr_t)cand->get(cand, AUTH_RULE_EAP_VENDOR) == 0))
! 817: { /* peer requested EAP, but current config does not match */
! 818: DBG1(DBG_IKE, "peer requested EAP, config unacceptable");
! 819: this->peer_cfg->destroy(this->peer_cfg);
! 820: this->peer_cfg = NULL;
! 821: if (!update_cfg_candidates(this, FALSE))
! 822: {
! 823: this->authentication_failed = TRUE;
! 824: return NEED_MORE;
! 825: }
! 826: cand = get_auth_cfg(this, FALSE);
! 827: }
! 828: /* copy over the EAP specific rules for authentication */
! 829: cfg->add(cfg, AUTH_RULE_EAP_TYPE,
! 830: cand->get(cand, AUTH_RULE_EAP_TYPE));
! 831: cfg->add(cfg, AUTH_RULE_EAP_VENDOR,
! 832: cand->get(cand, AUTH_RULE_EAP_VENDOR));
! 833: id = (identification_t*)cand->get(cand, AUTH_RULE_EAP_IDENTITY);
! 834: if (id)
! 835: {
! 836: cfg->add(cfg, AUTH_RULE_EAP_IDENTITY, id->clone(id));
! 837: }
! 838: id = (identification_t*)cand->get(cand, AUTH_RULE_AAA_IDENTITY);
! 839: if (id)
! 840: {
! 841: cfg->add(cfg, AUTH_RULE_AAA_IDENTITY, id->clone(id));
! 842: }
! 843: }
! 844:
! 845: /* verify authentication data */
! 846: this->other_auth = authenticator_create_verifier(this->ike_sa,
! 847: message, this->other_nonce, this->my_nonce,
! 848: this->other_packet->get_data(this->other_packet),
! 849: this->my_packet->get_data(this->my_packet),
! 850: this->reserved);
! 851: if (!this->other_auth)
! 852: {
! 853: this->authentication_failed = TRUE;
! 854: return NEED_MORE;
! 855: }
! 856: }
! 857: if (message->get_payload(message, PLV2_AUTH) &&
! 858: is_first_round(this, FALSE))
! 859: {
! 860: if (!get_ppk_r(this, message))
! 861: {
! 862: this->authentication_failed = TRUE;
! 863: return NEED_MORE;
! 864: }
! 865: else if (this->ppk.ptr && this->other_auth->use_ppk)
! 866: {
! 867: this->other_auth->use_ppk(this->other_auth, this->ppk, FALSE);
! 868: }
! 869: }
! 870: switch (this->other_auth->process(this->other_auth, message))
! 871: {
! 872: case SUCCESS:
! 873: this->other_auth->destroy(this->other_auth);
! 874: this->other_auth = NULL;
! 875: break;
! 876: case NEED_MORE:
! 877: if (message->get_payload(message, PLV2_AUTH))
! 878: { /* AUTH verification successful, but another build() needed */
! 879: break;
! 880: }
! 881: return NEED_MORE;
! 882: default:
! 883: this->authentication_failed = TRUE;
! 884: return NEED_MORE;
! 885: }
! 886:
! 887: /* another auth round done, invoke authorize hook */
! 888: if (!charon->bus->authorize(charon->bus, FALSE))
! 889: {
! 890: DBG1(DBG_IKE, "authorization hook forbids IKE_SA, cancelling");
! 891: this->authentication_failed = TRUE;
! 892: return NEED_MORE;
! 893: }
! 894:
! 895: apply_auth_cfg(this, FALSE);
! 896:
! 897: if (!update_cfg_candidates(this, FALSE))
! 898: {
! 899: this->authentication_failed = TRUE;
! 900: return NEED_MORE;
! 901: }
! 902:
! 903: if (!message->get_notify(message, ANOTHER_AUTH_FOLLOWS))
! 904: {
! 905: this->expect_another_auth = FALSE;
! 906: if (!update_cfg_candidates(this, TRUE))
! 907: {
! 908: this->authentication_failed = TRUE;
! 909: return NEED_MORE;
! 910: }
! 911: }
! 912: return NEED_MORE;
! 913: }
! 914:
! 915: /**
! 916: * Clear the PPK and PPK_ID
! 917: */
! 918: static void clear_ppk(private_ike_auth_t *this)
! 919: {
! 920: DESTROY_IF(this->ppk_id);
! 921: this->ppk_id = NULL;
! 922: chunk_clear(&this->ppk);
! 923: }
! 924:
! 925: /**
! 926: * Derive new keys and clear the PPK
! 927: */
! 928: static bool apply_ppk(private_ike_auth_t *this)
! 929: {
! 930: keymat_v2_t *keymat;
! 931:
! 932: if (this->ppk.ptr)
! 933: {
! 934: keymat = (keymat_v2_t*)this->ike_sa->get_keymat(this->ike_sa);
! 935: if (!keymat->derive_ike_keys_ppk(keymat, this->ppk))
! 936: {
! 937: return FALSE;
! 938: }
! 939: DBG1(DBG_CFG, "using PPK for PPK_ID '%Y'", this->ppk_id);
! 940: this->ike_sa->set_condition(this->ike_sa, COND_PPK, TRUE);
! 941: }
! 942: clear_ppk(this);
! 943: return TRUE;
! 944: }
! 945:
! 946: METHOD(task_t, build_r, status_t,
! 947: private_ike_auth_t *this, message_t *message)
! 948: {
! 949: identification_t *gateway;
! 950: auth_cfg_t *cfg;
! 951:
! 952: if (message->get_exchange_type(message) == IKE_SA_INIT)
! 953: {
! 954: if (multiple_auth_enabled())
! 955: {
! 956: message->add_notify(message, FALSE, MULTIPLE_AUTH_SUPPORTED,
! 957: chunk_empty);
! 958: }
! 959: return collect_my_init_data(this, message);
! 960: }
! 961:
! 962: if (this->authentication_failed || !this->peer_cfg)
! 963: {
! 964: goto peer_auth_failed;
! 965: }
! 966:
! 967: if (!this->my_auth && this->do_another_auth)
! 968: {
! 969: identification_t *id, *id_cfg;
! 970: id_payload_t *id_payload;
! 971:
! 972: /* add IDr */
! 973: cfg = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
! 974: cfg->purge(cfg, TRUE);
! 975: cfg->merge(cfg, get_auth_cfg(this, TRUE), TRUE);
! 976:
! 977: id_cfg = cfg->get(cfg, AUTH_RULE_IDENTITY);
! 978: id = this->ike_sa->get_my_id(this->ike_sa);
! 979: if (id->get_type(id) == ID_ANY)
! 980: { /* no IDr received, apply configured ID */
! 981: if (!id_cfg || id_cfg->contains_wildcards(id_cfg))
! 982: { /* no ID configured, use local IP address */
! 983: host_t *me;
! 984:
! 985: DBG1(DBG_CFG, "no IDr configured, fall back on IP address");
! 986: me = this->ike_sa->get_my_host(this->ike_sa);
! 987: id_cfg = identification_create_from_sockaddr(
! 988: me->get_sockaddr(me));
! 989: cfg->add(cfg, AUTH_RULE_IDENTITY, id_cfg);
! 990: }
! 991: this->ike_sa->set_my_id(this->ike_sa, id_cfg->clone(id_cfg));
! 992: id = id_cfg;
! 993: }
! 994: else
! 995: { /* IDr received, check if it matches configuration */
! 996: if (id_cfg && !id->matches(id, id_cfg))
! 997: {
! 998: DBG1(DBG_CFG, "received IDr %Y, but require %Y", id, id_cfg);
! 999: goto peer_auth_failed;
! 1000: }
! 1001: }
! 1002:
! 1003: id_payload = id_payload_create_from_identification(PLV2_ID_RESPONDER, id);
! 1004: get_reserved_id_bytes(this, id_payload);
! 1005: message->add_payload(message, (payload_t*)id_payload);
! 1006:
! 1007: if ((uintptr_t)cfg->get(cfg, AUTH_RULE_AUTH_CLASS) == AUTH_CLASS_EAP)
! 1008: { /* EAP-only authentication */
! 1009: if (!this->ike_sa->supports_extension(this->ike_sa,
! 1010: EXT_EAP_ONLY_AUTHENTICATION))
! 1011: {
! 1012: DBG1(DBG_IKE, "configured EAP-only authentication, but peer "
! 1013: "does not support it");
! 1014: goto peer_auth_failed;
! 1015: }
! 1016: }
! 1017: else
! 1018: {
! 1019: /* build authentication data */
! 1020: this->my_auth = authenticator_create_builder(this->ike_sa, cfg,
! 1021: this->other_nonce, this->my_nonce,
! 1022: this->other_packet->get_data(this->other_packet),
! 1023: this->my_packet->get_data(this->my_packet),
! 1024: this->reserved);
! 1025: if (!this->my_auth)
! 1026: {
! 1027: goto local_auth_failed;
! 1028: }
! 1029: }
! 1030: }
! 1031:
! 1032: if (this->other_auth)
! 1033: {
! 1034: switch (this->other_auth->build(this->other_auth, message))
! 1035: {
! 1036: case SUCCESS:
! 1037: this->other_auth->destroy(this->other_auth);
! 1038: this->other_auth = NULL;
! 1039: break;
! 1040: case NEED_MORE:
! 1041: break;
! 1042: default:
! 1043: if (message->get_payload(message, PLV2_EAP))
! 1044: { /* skip AUTHENTICATION_FAILED if we have EAP_FAILURE */
! 1045: goto peer_auth_failed_no_notify;
! 1046: }
! 1047: goto peer_auth_failed;
! 1048: }
! 1049: }
! 1050: if (this->my_auth)
! 1051: {
! 1052: if (this->ppk.ptr && this->my_auth->use_ppk)
! 1053: {
! 1054: this->my_auth->use_ppk(this->my_auth, this->ppk, FALSE);
! 1055: }
! 1056: switch (this->my_auth->build(this->my_auth, message))
! 1057: {
! 1058: case SUCCESS:
! 1059: apply_auth_cfg(this, TRUE);
! 1060: this->my_auth->destroy(this->my_auth);
! 1061: this->my_auth = NULL;
! 1062: break;
! 1063: case NEED_MORE:
! 1064: break;
! 1065: default:
! 1066: goto local_auth_failed;
! 1067: }
! 1068: }
! 1069:
! 1070: /* add a PPK_IDENTITY notify and derive new keys and clear the PPK */
! 1071: if (this->ppk.ptr)
! 1072: {
! 1073: message->add_notify(message, FALSE, PPK_IDENTITY, chunk_empty);
! 1074: if (!apply_ppk(this))
! 1075: {
! 1076: goto local_auth_failed;
! 1077: }
! 1078: }
! 1079:
! 1080: /* check for additional authentication rounds */
! 1081: if (do_another_auth(this))
! 1082: {
! 1083: message->add_notify(message, FALSE, ANOTHER_AUTH_FOLLOWS, chunk_empty);
! 1084: }
! 1085: else
! 1086: {
! 1087: this->do_another_auth = FALSE;
! 1088: }
! 1089: if (this->do_another_auth || this->expect_another_auth)
! 1090: {
! 1091: return NEED_MORE;
! 1092: }
! 1093:
! 1094: if (charon->ike_sa_manager->check_uniqueness(charon->ike_sa_manager,
! 1095: this->ike_sa, this->initial_contact))
! 1096: {
! 1097: DBG1(DBG_IKE, "cancelling IKE_SA setup due to uniqueness policy");
! 1098: charon->bus->alert(charon->bus, ALERT_UNIQUE_KEEP);
! 1099: message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
! 1100: chunk_empty);
! 1101: return FAILED;
! 1102: }
! 1103: if (!charon->bus->authorize(charon->bus, TRUE))
! 1104: {
! 1105: DBG1(DBG_IKE, "final authorization hook forbids IKE_SA, cancelling");
! 1106: goto peer_auth_failed;
! 1107: }
! 1108: if (this->ike_sa->supports_extension(this->ike_sa, EXT_IKE_REDIRECTION) &&
! 1109: charon->redirect->redirect_on_auth(charon->redirect, this->ike_sa,
! 1110: &gateway))
! 1111: {
! 1112: delete_ike_sa_job_t *job;
! 1113: chunk_t data;
! 1114:
! 1115: DBG1(DBG_IKE, "redirecting peer to %Y", gateway);
! 1116: data = redirect_data_create(gateway, chunk_empty);
! 1117: message->add_notify(message, FALSE, REDIRECT, data);
! 1118: gateway->destroy(gateway);
! 1119: chunk_free(&data);
! 1120: /* we use this condition to prevent the CHILD_SA from getting created */
! 1121: this->ike_sa->set_condition(this->ike_sa, COND_REDIRECTED, TRUE);
! 1122: /* if the peer does not delete the SA we do so after a while */
! 1123: job = delete_ike_sa_job_create(this->ike_sa->get_id(this->ike_sa), TRUE);
! 1124: lib->scheduler->schedule_job(lib->scheduler, (job_t*)job,
! 1125: lib->settings->get_int(lib->settings,
! 1126: "%s.half_open_timeout", HALF_OPEN_IKE_SA_TIMEOUT,
! 1127: lib->ns));
! 1128: }
! 1129: DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%Y]...%H[%Y]",
! 1130: this->ike_sa->get_name(this->ike_sa),
! 1131: this->ike_sa->get_unique_id(this->ike_sa),
! 1132: this->ike_sa->get_my_host(this->ike_sa),
! 1133: this->ike_sa->get_my_id(this->ike_sa),
! 1134: this->ike_sa->get_other_host(this->ike_sa),
! 1135: this->ike_sa->get_other_id(this->ike_sa));
! 1136: this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
! 1137: charon->bus->ike_updown(charon->bus, this->ike_sa, TRUE);
! 1138: return SUCCESS;
! 1139:
! 1140: peer_auth_failed:
! 1141: message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty);
! 1142: peer_auth_failed_no_notify:
! 1143: charon->bus->alert(charon->bus, ALERT_PEER_AUTH_FAILED);
! 1144: return FAILED;
! 1145: local_auth_failed:
! 1146: message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty);
! 1147: charon->bus->alert(charon->bus, ALERT_LOCAL_AUTH_FAILED);
! 1148: return FAILED;
! 1149: }
! 1150:
! 1151: /**
! 1152: * Send an INFORMATIONAL message with an AUTH_FAILED before closing IKE_SA
! 1153: */
! 1154: static void send_auth_failed_informational(private_ike_auth_t *this,
! 1155: message_t *reply)
! 1156: {
! 1157: message_t *message;
! 1158: packet_t *packet;
! 1159: host_t *host;
! 1160:
! 1161: message = message_create(IKEV2_MAJOR_VERSION, IKEV2_MINOR_VERSION);
! 1162: message->set_message_id(message, reply->get_message_id(reply) + 1);
! 1163: host = this->ike_sa->get_my_host(this->ike_sa);
! 1164: message->set_source(message, host->clone(host));
! 1165: host = this->ike_sa->get_other_host(this->ike_sa);
! 1166: message->set_destination(message, host->clone(host));
! 1167: message->set_exchange_type(message, INFORMATIONAL);
! 1168: message->add_notify(message, FALSE, AUTHENTICATION_FAILED, chunk_empty);
! 1169:
! 1170: if (this->ike_sa->generate_message(this->ike_sa, message,
! 1171: &packet) == SUCCESS)
! 1172: {
! 1173: charon->sender->send(charon->sender, packet);
! 1174: }
! 1175: message->destroy(message);
! 1176: }
! 1177:
! 1178: /**
! 1179: * Check if strict constraint fulfillment required to continue current auth
! 1180: */
! 1181: static bool require_strict(private_ike_auth_t *this, bool mutual_eap)
! 1182: {
! 1183: auth_cfg_t *cfg;
! 1184:
! 1185: if (this->eap_acceptable)
! 1186: {
! 1187: return FALSE;
! 1188: }
! 1189:
! 1190: cfg = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
! 1191: switch ((uintptr_t)cfg->get(cfg, AUTH_RULE_AUTH_CLASS))
! 1192: {
! 1193: case AUTH_CLASS_EAP:
! 1194: if (mutual_eap && this->my_auth)
! 1195: {
! 1196: this->eap_acceptable = TRUE;
! 1197: return !this->my_auth->is_mutual(this->my_auth);
! 1198: }
! 1199: return TRUE;
! 1200: case AUTH_CLASS_PSK:
! 1201: return TRUE;
! 1202: case AUTH_CLASS_PUBKEY:
! 1203: case AUTH_CLASS_ANY:
! 1204: default:
! 1205: return FALSE;
! 1206: }
! 1207: }
! 1208:
! 1209: METHOD(task_t, process_i, status_t,
! 1210: private_ike_auth_t *this, message_t *message)
! 1211: {
! 1212: enumerator_t *enumerator;
! 1213: payload_t *payload;
! 1214: auth_cfg_t *cfg;
! 1215: bool mutual_eap = FALSE, ppk_id_received = FALSE;
! 1216:
! 1217: if (message->get_exchange_type(message) == IKE_SA_INIT)
! 1218: {
! 1219: if (message->get_notify(message, MULTIPLE_AUTH_SUPPORTED) &&
! 1220: multiple_auth_enabled())
! 1221: {
! 1222: this->ike_sa->enable_extension(this->ike_sa, EXT_MULTIPLE_AUTH);
! 1223: }
! 1224: return collect_other_init_data(this, message);
! 1225: }
! 1226:
! 1227: enumerator = message->create_payload_enumerator(message);
! 1228: while (enumerator->enumerate(enumerator, &payload))
! 1229: {
! 1230: if (payload->get_type(payload) == PLV2_NOTIFY)
! 1231: {
! 1232: notify_payload_t *notify = (notify_payload_t*)payload;
! 1233: notify_type_t type = notify->get_notify_type(notify);
! 1234:
! 1235: switch (type)
! 1236: {
! 1237: case NO_PROPOSAL_CHOSEN:
! 1238: case SINGLE_PAIR_REQUIRED:
! 1239: case NO_ADDITIONAL_SAS:
! 1240: case INTERNAL_ADDRESS_FAILURE:
! 1241: case FAILED_CP_REQUIRED:
! 1242: case TS_UNACCEPTABLE:
! 1243: case INVALID_SELECTORS:
! 1244: /* these are errors, but are not critical as only the
! 1245: * CHILD_SA won't get build, but IKE_SA establishes anyway */
! 1246: break;
! 1247: case MOBIKE_SUPPORTED:
! 1248: case ADDITIONAL_IP4_ADDRESS:
! 1249: case ADDITIONAL_IP6_ADDRESS:
! 1250: /* handled in ike_mobike task */
! 1251: break;
! 1252: case AUTH_LIFETIME:
! 1253: /* handled in ike_auth_lifetime task */
! 1254: break;
! 1255: case ME_ENDPOINT:
! 1256: /* handled in ike_me task */
! 1257: break;
! 1258: case REDIRECT:
! 1259: DESTROY_IF(this->redirect_to);
! 1260: this->redirect_to = redirect_data_parse(
! 1261: notify->get_notification_data(notify), NULL);
! 1262: if (!this->redirect_to)
! 1263: {
! 1264: DBG1(DBG_IKE, "received invalid REDIRECT notify");
! 1265: }
! 1266: break;
! 1267: case IKEV2_MESSAGE_ID_SYNC_SUPPORTED:
! 1268: this->ike_sa->enable_extension(this->ike_sa,
! 1269: EXT_IKE_MESSAGE_ID_SYNC);
! 1270: break;
! 1271: case PPK_IDENTITY:
! 1272: ppk_id_received = TRUE;
! 1273: break;
! 1274: default:
! 1275: {
! 1276: if (type <= 16383)
! 1277: {
! 1278: DBG1(DBG_IKE, "received %N notify error",
! 1279: notify_type_names, type);
! 1280: enumerator->destroy(enumerator);
! 1281: charon->bus->alert(charon->bus, ALERT_LOCAL_AUTH_FAILED);
! 1282: return FAILED;
! 1283: }
! 1284: DBG2(DBG_IKE, "received %N notify",
! 1285: notify_type_names, type);
! 1286: break;
! 1287: }
! 1288: }
! 1289: }
! 1290: }
! 1291: enumerator->destroy(enumerator);
! 1292:
! 1293: if (this->expect_another_auth)
! 1294: {
! 1295: if (!this->other_auth)
! 1296: {
! 1297: id_payload_t *id_payload;
! 1298: identification_t *id;
! 1299:
! 1300: /* handle IDr payload */
! 1301: id_payload = (id_payload_t*)message->get_payload(message,
! 1302: PLV2_ID_RESPONDER);
! 1303: if (!id_payload)
! 1304: {
! 1305: DBG1(DBG_IKE, "IDr payload missing");
! 1306: goto peer_auth_failed;
! 1307: }
! 1308: id = id_payload->get_identification(id_payload);
! 1309: get_reserved_id_bytes(this, id_payload);
! 1310: this->ike_sa->set_other_id(this->ike_sa, id);
! 1311: cfg = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
! 1312: cfg->add(cfg, AUTH_RULE_IDENTITY, id->clone(id));
! 1313:
! 1314: if (message->get_payload(message, PLV2_AUTH))
! 1315: {
! 1316: /* verify authentication data */
! 1317: this->other_auth = authenticator_create_verifier(this->ike_sa,
! 1318: message, this->other_nonce, this->my_nonce,
! 1319: this->other_packet->get_data(this->other_packet),
! 1320: this->my_packet->get_data(this->my_packet),
! 1321: this->reserved);
! 1322: if (!this->other_auth)
! 1323: {
! 1324: goto peer_auth_failed;
! 1325: }
! 1326: }
! 1327: else
! 1328: {
! 1329: /* responder omitted AUTH payload, indicating EAP-only */
! 1330: mutual_eap = TRUE;
! 1331: }
! 1332: }
! 1333: if (this->other_auth)
! 1334: {
! 1335: if (ppk_id_received && is_first_round(this, FALSE) &&
! 1336: this->other_auth->use_ppk)
! 1337: {
! 1338: this->other_auth->use_ppk(this->other_auth, this->ppk, FALSE);
! 1339: }
! 1340: switch (this->other_auth->process(this->other_auth, message))
! 1341: {
! 1342: case SUCCESS:
! 1343: break;
! 1344: case NEED_MORE:
! 1345: return NEED_MORE;
! 1346: default:
! 1347: goto peer_auth_failed;
! 1348: }
! 1349: this->other_auth->destroy(this->other_auth);
! 1350: this->other_auth = NULL;
! 1351: }
! 1352: /* another auth round done, invoke authorize hook */
! 1353: if (!charon->bus->authorize(charon->bus, FALSE))
! 1354: {
! 1355: DBG1(DBG_IKE, "authorization forbids IKE_SA, cancelling");
! 1356: goto peer_auth_failed;
! 1357: }
! 1358:
! 1359: if (!mutual_eap)
! 1360: {
! 1361: apply_auth_cfg(this, FALSE);
! 1362: }
! 1363: }
! 1364:
! 1365: if (require_strict(this, mutual_eap))
! 1366: {
! 1367: if (!update_cfg_candidates(this, TRUE))
! 1368: {
! 1369: goto peer_auth_failed;
! 1370: }
! 1371: }
! 1372:
! 1373: if (this->my_auth)
! 1374: {
! 1375: /* while we already set the PPK in build_i(), we MUST not use it if
! 1376: * the peer did not reply with a PPK_ID notify */
! 1377: if (this->ppk.ptr && this->my_auth->use_ppk)
! 1378: {
! 1379: this->my_auth->use_ppk(this->my_auth,
! 1380: ppk_id_received ? this->ppk : chunk_empty,
! 1381: FALSE);
! 1382: }
! 1383: switch (this->my_auth->process(this->my_auth, message))
! 1384: {
! 1385: case SUCCESS:
! 1386: apply_auth_cfg(this, TRUE);
! 1387: if (this->my_auth->is_mutual(this->my_auth))
! 1388: {
! 1389: apply_auth_cfg(this, FALSE);
! 1390: }
! 1391: this->my_auth->destroy(this->my_auth);
! 1392: this->my_auth = NULL;
! 1393: this->do_another_auth = do_another_auth(this);
! 1394: break;
! 1395: case NEED_MORE:
! 1396: break;
! 1397: default:
! 1398: goto local_auth_failed;
! 1399: }
! 1400: }
! 1401:
! 1402: /* change keys and clear PPK after we are done with our authentication, so
! 1403: * we only explicitly use it for the first round, afterwards we just use the
! 1404: * changed SK_p keys implicitly */
! 1405: if (!this->my_auth && this->ppk_id)
! 1406: {
! 1407: if (ppk_id_received)
! 1408: {
! 1409: if (!apply_ppk(this))
! 1410: {
! 1411: goto local_auth_failed;
! 1412: }
! 1413: }
! 1414: else
! 1415: {
! 1416: DBG1(DBG_CFG, "peer didn't use PPK for PPK_ID '%Y'", this->ppk_id);
! 1417: }
! 1418: clear_ppk(this);
! 1419: }
! 1420:
! 1421: if (mutual_eap)
! 1422: {
! 1423: if (!this->my_auth || !this->my_auth->is_mutual(this->my_auth))
! 1424: {
! 1425: DBG1(DBG_IKE, "do not allow non-mutual EAP-only authentication");
! 1426: goto peer_auth_failed;
! 1427: }
! 1428: DBG1(DBG_IKE, "allow mutual EAP-only authentication");
! 1429: }
! 1430:
! 1431: if (!message->get_notify(message, ANOTHER_AUTH_FOLLOWS))
! 1432: {
! 1433: this->expect_another_auth = FALSE;
! 1434: }
! 1435: if (this->expect_another_auth || this->do_another_auth || this->my_auth)
! 1436: {
! 1437: return NEED_MORE;
! 1438: }
! 1439: if (!update_cfg_candidates(this, TRUE))
! 1440: {
! 1441: goto peer_auth_failed;
! 1442: }
! 1443: if (!charon->bus->authorize(charon->bus, TRUE))
! 1444: {
! 1445: DBG1(DBG_IKE, "final authorization hook forbids IKE_SA, "
! 1446: "cancelling");
! 1447: goto peer_auth_failed;
! 1448: }
! 1449: DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%Y]...%H[%Y]",
! 1450: this->ike_sa->get_name(this->ike_sa),
! 1451: this->ike_sa->get_unique_id(this->ike_sa),
! 1452: this->ike_sa->get_my_host(this->ike_sa),
! 1453: this->ike_sa->get_my_id(this->ike_sa),
! 1454: this->ike_sa->get_other_host(this->ike_sa),
! 1455: this->ike_sa->get_other_id(this->ike_sa));
! 1456: this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
! 1457: charon->bus->ike_updown(charon->bus, this->ike_sa, TRUE);
! 1458:
! 1459: if (this->redirect_to)
! 1460: {
! 1461: this->ike_sa->handle_redirect(this->ike_sa, this->redirect_to);
! 1462: }
! 1463: return SUCCESS;
! 1464:
! 1465: peer_auth_failed:
! 1466: charon->bus->alert(charon->bus, ALERT_PEER_AUTH_FAILED);
! 1467: send_auth_failed_informational(this, message);
! 1468: return FAILED;
! 1469: local_auth_failed:
! 1470: charon->bus->alert(charon->bus, ALERT_LOCAL_AUTH_FAILED);
! 1471: send_auth_failed_informational(this, message);
! 1472: return FAILED;
! 1473: }
! 1474:
! 1475: METHOD(task_t, get_type, task_type_t,
! 1476: private_ike_auth_t *this)
! 1477: {
! 1478: return TASK_IKE_AUTH;
! 1479: }
! 1480:
! 1481: METHOD(task_t, migrate, void,
! 1482: private_ike_auth_t *this, ike_sa_t *ike_sa)
! 1483: {
! 1484: clear_ppk(this);
! 1485: chunk_free(&this->my_nonce);
! 1486: chunk_free(&this->other_nonce);
! 1487: DESTROY_IF(this->my_packet);
! 1488: DESTROY_IF(this->other_packet);
! 1489: DESTROY_IF(this->peer_cfg);
! 1490: DESTROY_IF(this->my_auth);
! 1491: DESTROY_IF(this->other_auth);
! 1492: DESTROY_IF(this->redirect_to);
! 1493: this->candidates->destroy_offset(this->candidates, offsetof(peer_cfg_t, destroy));
! 1494:
! 1495: this->my_packet = NULL;
! 1496: this->other_packet = NULL;
! 1497: this->ike_sa = ike_sa;
! 1498: this->peer_cfg = NULL;
! 1499: this->my_auth = NULL;
! 1500: this->other_auth = NULL;
! 1501: this->redirect_to = NULL;
! 1502: this->do_another_auth = TRUE;
! 1503: this->expect_another_auth = TRUE;
! 1504: this->authentication_failed = FALSE;
! 1505: this->candidates = linked_list_create();
! 1506: }
! 1507:
! 1508: METHOD(task_t, destroy, void,
! 1509: private_ike_auth_t *this)
! 1510: {
! 1511: clear_ppk(this);
! 1512: chunk_free(&this->my_nonce);
! 1513: chunk_free(&this->other_nonce);
! 1514: DESTROY_IF(this->my_packet);
! 1515: DESTROY_IF(this->other_packet);
! 1516: DESTROY_IF(this->my_auth);
! 1517: DESTROY_IF(this->other_auth);
! 1518: DESTROY_IF(this->peer_cfg);
! 1519: DESTROY_IF(this->redirect_to);
! 1520: this->candidates->destroy_offset(this->candidates, offsetof(peer_cfg_t, destroy));
! 1521: free(this);
! 1522: }
! 1523:
! 1524: /*
! 1525: * Described in header.
! 1526: */
! 1527: ike_auth_t *ike_auth_create(ike_sa_t *ike_sa, bool initiator)
! 1528: {
! 1529: private_ike_auth_t *this;
! 1530:
! 1531: INIT(this,
! 1532: .public = {
! 1533: .task = {
! 1534: .get_type = _get_type,
! 1535: .migrate = _migrate,
! 1536: .build = _build_r,
! 1537: .process = _process_r,
! 1538: .destroy = _destroy,
! 1539: },
! 1540: },
! 1541: .ike_sa = ike_sa,
! 1542: .initiator = initiator,
! 1543: .candidates = linked_list_create(),
! 1544: .do_another_auth = TRUE,
! 1545: .expect_another_auth = TRUE,
! 1546: );
! 1547: if (initiator)
! 1548: {
! 1549: this->public.task.build = _build_i;
! 1550: this->public.task.process = _process_i;
! 1551: }
! 1552: return &this->public;
! 1553: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>