Annotation of embedaddon/strongswan/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2012-2018 Tobias Brunner
! 3: * Copyright (C) 2006-2009 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 "eap_authenticator.h"
! 18:
! 19: #include <daemon.h>
! 20: #include <sa/ikev2/keymat_v2.h>
! 21: #include <sa/eap/eap_method.h>
! 22: #include <encoding/payloads/auth_payload.h>
! 23: #include <encoding/payloads/eap_payload.h>
! 24:
! 25: typedef struct private_eap_authenticator_t private_eap_authenticator_t;
! 26:
! 27: /**
! 28: * Private data of an eap_authenticator_t object.
! 29: */
! 30: struct private_eap_authenticator_t {
! 31:
! 32: /**
! 33: * Public authenticator_t interface.
! 34: */
! 35: eap_authenticator_t public;
! 36:
! 37: /**
! 38: * Assigned IKE_SA
! 39: */
! 40: ike_sa_t *ike_sa;
! 41:
! 42: /**
! 43: * others nonce to include in AUTH calculation
! 44: */
! 45: chunk_t received_nonce;
! 46:
! 47: /**
! 48: * our nonce to include in AUTH calculation
! 49: */
! 50: chunk_t sent_nonce;
! 51:
! 52: /**
! 53: * others IKE_SA_INIT message data to include in AUTH calculation
! 54: */
! 55: chunk_t received_init;
! 56:
! 57: /**
! 58: * our IKE_SA_INIT message data to include in AUTH calculation
! 59: */
! 60: chunk_t sent_init;
! 61:
! 62: /**
! 63: * Reserved bytes of ID payload
! 64: */
! 65: char reserved[3];
! 66:
! 67: /**
! 68: * PPK to use
! 69: */
! 70: chunk_t ppk;
! 71:
! 72: /**
! 73: * Add a NO_PPK_AUTH notify
! 74: */
! 75: bool no_ppk_auth;
! 76:
! 77: /**
! 78: * Current EAP method processing
! 79: */
! 80: eap_method_t *method;
! 81:
! 82: /**
! 83: * MSK used to build and verify auth payload
! 84: */
! 85: chunk_t msk;
! 86:
! 87: /**
! 88: * EAP authentication method completed successfully
! 89: */
! 90: bool eap_complete;
! 91:
! 92: /**
! 93: * Set if we require mutual EAP due EAP-only authentication
! 94: */
! 95: bool require_mutual;
! 96:
! 97: /**
! 98: * authentication payload verified successfully
! 99: */
! 100: bool auth_complete;
! 101:
! 102: /**
! 103: * generated EAP payload
! 104: */
! 105: eap_payload_t *eap_payload;
! 106:
! 107: /**
! 108: * EAP identity of peer
! 109: */
! 110: identification_t *eap_identity;
! 111: };
! 112:
! 113: /**
! 114: * load an EAP method
! 115: */
! 116: static eap_method_t *load_method(private_eap_authenticator_t *this,
! 117: eap_type_t type, uint32_t vendor, eap_role_t role)
! 118: {
! 119: identification_t *server, *peer, *aaa;
! 120: auth_cfg_t *auth;
! 121:
! 122: if (role == EAP_SERVER)
! 123: {
! 124: server = this->ike_sa->get_my_id(this->ike_sa);
! 125: peer = this->ike_sa->get_other_id(this->ike_sa);
! 126: auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
! 127: }
! 128: else
! 129: {
! 130: server = this->ike_sa->get_other_id(this->ike_sa);
! 131: peer = this->ike_sa->get_my_id(this->ike_sa);
! 132: auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
! 133: }
! 134: if (this->eap_identity)
! 135: {
! 136: peer = this->eap_identity;
! 137: }
! 138: aaa = auth->get(auth, AUTH_RULE_AAA_IDENTITY);
! 139: if (aaa)
! 140: {
! 141: server = aaa;
! 142: }
! 143: return charon->eap->create_instance(charon->eap, type, vendor,
! 144: role, server, peer);
! 145: }
! 146:
! 147: /**
! 148: * Initiate EAP conversation as server
! 149: */
! 150: static eap_payload_t* server_initiate_eap(private_eap_authenticator_t *this,
! 151: bool do_identity)
! 152: {
! 153: auth_cfg_t *auth;
! 154: eap_type_t type;
! 155: identification_t *id;
! 156: uint32_t vendor;
! 157: eap_payload_t *out;
! 158: char *action;
! 159:
! 160: auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
! 161:
! 162: /* initiate EAP-Identity exchange if required */
! 163: if (!this->eap_identity && do_identity)
! 164: {
! 165: id = auth->get(auth, AUTH_RULE_EAP_IDENTITY);
! 166: if (id)
! 167: {
! 168: if (id->get_type(id) == ID_ANY)
! 169: {
! 170: this->method = load_method(this, EAP_IDENTITY, 0, EAP_SERVER);
! 171: if (this->method)
! 172: {
! 173: if (this->method->initiate(this->method, &out) == NEED_MORE)
! 174: {
! 175: DBG1(DBG_IKE, "initiating %N method (id 0x%02X)",
! 176: eap_type_names, EAP_IDENTITY,
! 177: this->method->get_identifier(this->method));
! 178: return out;
! 179: }
! 180: this->method->destroy(this->method);
! 181: }
! 182: DBG1(DBG_IKE, "EAP-Identity request configured, "
! 183: "but not supported");
! 184: }
! 185: else
! 186: {
! 187: DBG1(DBG_IKE, "using configured EAP-Identity %Y", id);
! 188: this->eap_identity = id->clone(id);
! 189: }
! 190: }
! 191: }
! 192: /* invoke real EAP method */
! 193: type = (uintptr_t)auth->get(auth, AUTH_RULE_EAP_TYPE);
! 194: vendor = (uintptr_t)auth->get(auth, AUTH_RULE_EAP_VENDOR);
! 195: action = "loading";
! 196: this->method = load_method(this, type, vendor, EAP_SERVER);
! 197: if (this->method)
! 198: {
! 199: action = "initiating";
! 200: if (this->method->initiate(this->method, &out) == NEED_MORE)
! 201: {
! 202: type = this->method->get_type(this->method, &vendor);
! 203: if (vendor)
! 204: {
! 205: DBG1(DBG_IKE, "initiating EAP vendor type %d-%d method (id 0x%02X)",
! 206: type, vendor, out->get_identifier(out));
! 207: }
! 208: else
! 209: {
! 210: DBG1(DBG_IKE, "initiating %N method (id 0x%02X)", eap_type_names,
! 211: type, out->get_identifier(out));
! 212: }
! 213: return out;
! 214: }
! 215: /* type might have changed for virtual methods */
! 216: type = this->method->get_type(this->method, &vendor);
! 217: }
! 218: if (vendor)
! 219: {
! 220: DBG1(DBG_IKE, "%s EAP vendor type %d-%d method failed",
! 221: action, type, vendor);
! 222: }
! 223: else
! 224: {
! 225: DBG1(DBG_IKE, "%s %N method failed", action, eap_type_names, type);
! 226: }
! 227: return eap_payload_create_code(EAP_FAILURE, 0);
! 228: }
! 229:
! 230: /**
! 231: * Replace the existing EAP-Identity in other auth config
! 232: */
! 233: static void replace_eap_identity(private_eap_authenticator_t *this)
! 234: {
! 235: identification_t *eap_identity;
! 236: auth_cfg_t *cfg;
! 237:
! 238: eap_identity = this->eap_identity->clone(this->eap_identity);
! 239: cfg = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
! 240: cfg->add(cfg, AUTH_RULE_EAP_IDENTITY, eap_identity);
! 241: }
! 242:
! 243: /**
! 244: * Handle EAP exchange as server
! 245: */
! 246: static eap_payload_t* server_process_eap(private_eap_authenticator_t *this,
! 247: eap_payload_t *in)
! 248: {
! 249: eap_type_t type, received_type, conf_type;
! 250: uint32_t vendor, received_vendor, conf_vendor;
! 251: eap_payload_t *out;
! 252: auth_cfg_t *auth;
! 253:
! 254: if (in->get_code(in) != EAP_RESPONSE)
! 255: {
! 256: DBG1(DBG_IKE, "received %N, sending %N",
! 257: eap_code_names, in->get_code(in), eap_code_names, EAP_FAILURE);
! 258: return eap_payload_create_code(EAP_FAILURE, in->get_identifier(in));
! 259: }
! 260:
! 261: type = this->method->get_type(this->method, &vendor);
! 262: received_type = in->get_type(in, &received_vendor);
! 263: if (type != received_type || vendor != received_vendor)
! 264: {
! 265: if (received_vendor == 0 && received_type == EAP_NAK)
! 266: {
! 267: auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
! 268: conf_type = (uintptr_t)auth->get(auth, AUTH_RULE_EAP_TYPE);
! 269: conf_vendor = (uintptr_t)auth->get(auth, AUTH_RULE_EAP_VENDOR);
! 270: if ((type == EAP_IDENTITY && !vendor) ||
! 271: (type == conf_type && vendor == conf_vendor))
! 272: {
! 273: DBG1(DBG_IKE, "received %N, sending %N",
! 274: eap_type_names, EAP_NAK, eap_code_names, EAP_FAILURE);
! 275: return eap_payload_create_code(EAP_FAILURE,
! 276: in->get_identifier(in));
! 277: }
! 278: /* virtual methods handle NAKs in process() */
! 279: }
! 280: else
! 281: {
! 282: DBG1(DBG_IKE, "received invalid EAP response, sending %N",
! 283: eap_code_names, EAP_FAILURE);
! 284: return eap_payload_create_code(EAP_FAILURE, in->get_identifier(in));
! 285: }
! 286: }
! 287:
! 288: switch (this->method->process(this->method, in, &out))
! 289: {
! 290: case NEED_MORE:
! 291: return out;
! 292: case SUCCESS:
! 293: if (!vendor && type == EAP_IDENTITY)
! 294: {
! 295: chunk_t data;
! 296:
! 297: if (this->method->get_msk(this->method, &data) == SUCCESS)
! 298: {
! 299: this->eap_identity = identification_create_from_data(data);
! 300: DBG1(DBG_IKE, "received EAP identity '%Y'",
! 301: this->eap_identity);
! 302: replace_eap_identity(this);
! 303: }
! 304: /* restart EAP exchange, but with real method */
! 305: this->method->destroy(this->method);
! 306: return server_initiate_eap(this, FALSE);
! 307: }
! 308: if (this->method->get_msk(this->method, &this->msk) == SUCCESS)
! 309: {
! 310: this->msk = chunk_clone(this->msk);
! 311: }
! 312: if (vendor)
! 313: {
! 314: DBG1(DBG_IKE, "EAP vendor specific method %d-%d succeeded, "
! 315: "%sMSK established", type, vendor,
! 316: this->msk.ptr ? "" : "no ");
! 317: }
! 318: else
! 319: {
! 320: DBG1(DBG_IKE, "EAP method %N succeeded, %sMSK established",
! 321: eap_type_names, type, this->msk.ptr ? "" : "no ");
! 322: }
! 323: this->ike_sa->set_condition(this->ike_sa, COND_EAP_AUTHENTICATED,
! 324: TRUE);
! 325: this->eap_complete = TRUE;
! 326: return eap_payload_create_code(EAP_SUCCESS, in->get_identifier(in));
! 327: case FAILED:
! 328: default:
! 329: /* type might have changed for virtual methods */
! 330: type = this->method->get_type(this->method, &vendor);
! 331: if (vendor)
! 332: {
! 333: DBG1(DBG_IKE, "EAP vendor specific method %d-%d failed for "
! 334: "peer %Y", type, vendor,
! 335: this->ike_sa->get_other_id(this->ike_sa));
! 336: }
! 337: else
! 338: {
! 339: DBG1(DBG_IKE, "EAP method %N failed for peer %Y",
! 340: eap_type_names, type,
! 341: this->ike_sa->get_other_id(this->ike_sa));
! 342: }
! 343: return eap_payload_create_code(EAP_FAILURE, in->get_identifier(in));
! 344: }
! 345: }
! 346:
! 347: /**
! 348: * Processing method for a peer
! 349: */
! 350: static eap_payload_t* client_process_eap(private_eap_authenticator_t *this,
! 351: eap_payload_t *in)
! 352: {
! 353: eap_type_t type, conf_type;
! 354: uint32_t vendor, conf_vendor;
! 355: auth_cfg_t *auth;
! 356: eap_payload_t *out;
! 357: identification_t *id;
! 358:
! 359: type = in->get_type(in, &vendor);
! 360:
! 361: if (!vendor && type == EAP_IDENTITY)
! 362: {
! 363: DESTROY_IF(this->eap_identity);
! 364: auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
! 365: id = auth->get(auth, AUTH_RULE_EAP_IDENTITY);
! 366: if (!id || id->get_type(id) == ID_ANY)
! 367: {
! 368: id = this->ike_sa->get_my_id(this->ike_sa);
! 369: }
! 370: DBG1(DBG_IKE, "server requested %N (id 0x%02X), sending '%Y'",
! 371: eap_type_names, type, in->get_identifier(in), id);
! 372: this->eap_identity = id->clone(id);
! 373:
! 374: this->method = load_method(this, type, vendor, EAP_PEER);
! 375: if (this->method)
! 376: {
! 377: if (this->method->process(this->method, in, &out) == SUCCESS)
! 378: {
! 379: this->method->destroy(this->method);
! 380: this->method = NULL;
! 381: return out;
! 382: }
! 383: this->method->destroy(this->method);
! 384: this->method = NULL;
! 385: }
! 386: /* FIXME: sending a Nak is not correct here as EAP_IDENTITY (1) is no
! 387: * EAP method (types 3-253, 255) */
! 388: DBG1(DBG_IKE, "%N not supported, sending EAP_NAK",
! 389: eap_type_names, type);
! 390: return eap_payload_create_nak(in->get_identifier(in), 0, 0, FALSE);
! 391: }
! 392: if (this->method == NULL)
! 393: {
! 394: if (vendor)
! 395: {
! 396: DBG1(DBG_IKE, "server requested vendor specific EAP method %d-%d ",
! 397: "(id 0x%02X)", type, vendor, in->get_identifier(in));
! 398: }
! 399: else
! 400: {
! 401: DBG1(DBG_IKE, "server requested %N authentication (id 0x%02X)",
! 402: eap_type_names, type, in->get_identifier(in));
! 403: }
! 404: auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
! 405: conf_type = (uintptr_t)auth->get(auth, AUTH_RULE_EAP_TYPE);
! 406: conf_vendor = (uintptr_t)auth->get(auth, AUTH_RULE_EAP_VENDOR);
! 407: if (conf_type != EAP_NAK &&
! 408: (conf_type != type || conf_vendor != vendor))
! 409: {
! 410: if (conf_vendor)
! 411: {
! 412: DBG1(DBG_IKE, "requesting EAP method %d-%d, sending EAP_NAK",
! 413: conf_type, conf_vendor);
! 414: }
! 415: else
! 416: {
! 417: DBG1(DBG_IKE, "requesting %N authentication, sending EAP_NAK",
! 418: eap_type_names, conf_type);
! 419: }
! 420: return eap_payload_create_nak(in->get_identifier(in), conf_type,
! 421: conf_vendor, in->is_expanded(in));
! 422: }
! 423: this->method = load_method(this, type, vendor, EAP_PEER);
! 424: if (!this->method)
! 425: {
! 426: DBG1(DBG_IKE, "EAP method not supported, sending EAP_NAK");
! 427: return eap_payload_create_nak(in->get_identifier(in), 0, 0,
! 428: in->is_expanded(in));
! 429: }
! 430: }
! 431:
! 432: type = this->method->get_type(this->method, &vendor);
! 433:
! 434: if (this->method->process(this->method, in, &out) == NEED_MORE)
! 435: { /* client methods should never return SUCCESS */
! 436: return out;
! 437: }
! 438:
! 439: if (vendor)
! 440: {
! 441: DBG1(DBG_IKE, "vendor specific EAP method %d-%d failed", type, vendor);
! 442: }
! 443: else
! 444: {
! 445: DBG1(DBG_IKE, "%N method failed", eap_type_names, type);
! 446: }
! 447: return NULL;
! 448: }
! 449:
! 450: /**
! 451: * Verify AUTH payload
! 452: */
! 453: static bool verify_auth(private_eap_authenticator_t *this, message_t *message,
! 454: chunk_t nonce, chunk_t init)
! 455: {
! 456: auth_payload_t *auth_payload;
! 457: notify_payload_t *notify;
! 458: chunk_t auth_data, recv_auth_data;
! 459: identification_t *other_id;
! 460: auth_cfg_t *auth;
! 461: keymat_v2_t *keymat;
! 462: eap_type_t type;
! 463: uint32_t vendor;
! 464:
! 465: auth_payload = (auth_payload_t*)message->get_payload(message,
! 466: PLV2_AUTH);
! 467: if (!auth_payload)
! 468: {
! 469: DBG1(DBG_IKE, "AUTH payload missing");
! 470: return FALSE;
! 471: }
! 472: recv_auth_data = auth_payload->get_data(auth_payload);
! 473:
! 474: if (this->ike_sa->supports_extension(this->ike_sa, EXT_PPK) &&
! 475: !this->ppk.ptr)
! 476: { /* look for a NO_PPK_AUTH notify if we have no PPK */
! 477: notify = message->get_notify(message, NO_PPK_AUTH);
! 478: if (notify)
! 479: {
! 480: DBG1(DBG_IKE, "no PPK available, using NO_PPK_AUTH notify");
! 481: recv_auth_data = notify->get_notification_data(notify);
! 482: }
! 483: }
! 484:
! 485: other_id = this->ike_sa->get_other_id(this->ike_sa);
! 486: keymat = (keymat_v2_t*)this->ike_sa->get_keymat(this->ike_sa);
! 487: if (!keymat->get_psk_sig(keymat, TRUE, init, nonce, this->msk, this->ppk,
! 488: other_id, this->reserved, &auth_data))
! 489: {
! 490: return FALSE;
! 491: }
! 492: if (!auth_data.len || !chunk_equals_const(auth_data, recv_auth_data))
! 493: {
! 494: DBG1(DBG_IKE, "verification of AUTH payload with%s EAP MSK failed",
! 495: this->msk.ptr ? "" : "out");
! 496: chunk_free(&auth_data);
! 497: return FALSE;
! 498: }
! 499: chunk_free(&auth_data);
! 500:
! 501: DBG1(DBG_IKE, "authentication of '%Y' with %N successful",
! 502: other_id, auth_class_names, AUTH_CLASS_EAP);
! 503: this->auth_complete = TRUE;
! 504: auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
! 505: auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
! 506:
! 507: type = this->method->get_type(this->method, &vendor);
! 508: auth->add(auth, AUTH_RULE_EAP_TYPE, type);
! 509: if (vendor)
! 510: {
! 511: auth->add(auth, AUTH_RULE_EAP_VENDOR, vendor);
! 512: }
! 513: return TRUE;
! 514: }
! 515:
! 516: /**
! 517: * Build AUTH payload
! 518: */
! 519: static bool build_auth(private_eap_authenticator_t *this, message_t *message,
! 520: chunk_t nonce, chunk_t init)
! 521: {
! 522: auth_payload_t *auth_payload;
! 523: identification_t *my_id;
! 524: chunk_t auth_data;
! 525: keymat_v2_t *keymat;
! 526:
! 527: my_id = this->ike_sa->get_my_id(this->ike_sa);
! 528: keymat = (keymat_v2_t*)this->ike_sa->get_keymat(this->ike_sa);
! 529:
! 530: DBG1(DBG_IKE, "authentication of '%Y' (myself) with %N",
! 531: my_id, auth_class_names, AUTH_CLASS_EAP);
! 532:
! 533: if (!keymat->get_psk_sig(keymat, FALSE, init, nonce, this->msk, this->ppk,
! 534: my_id, this->reserved, &auth_data))
! 535: {
! 536: return FALSE;
! 537: }
! 538: auth_payload = auth_payload_create();
! 539: auth_payload->set_auth_method(auth_payload, AUTH_PSK);
! 540: auth_payload->set_data(auth_payload, auth_data);
! 541: message->add_payload(message, (payload_t*)auth_payload);
! 542: chunk_free(&auth_data);
! 543:
! 544: if (this->no_ppk_auth)
! 545: {
! 546: if (!keymat->get_psk_sig(keymat, FALSE, init, nonce, this->msk,
! 547: chunk_empty, my_id, this->reserved, &auth_data))
! 548: {
! 549: DBG1(DBG_IKE, "failed adding NO_PPK_AUTH notify");
! 550: return FALSE;
! 551: }
! 552: message->add_notify(message, FALSE, NO_PPK_AUTH, auth_data);
! 553: chunk_free(&auth_data);
! 554: }
! 555: return TRUE;
! 556: }
! 557:
! 558: METHOD(authenticator_t, process_server, status_t,
! 559: private_eap_authenticator_t *this, message_t *message)
! 560: {
! 561: eap_payload_t *eap_payload;
! 562:
! 563: if (this->eap_complete)
! 564: {
! 565: if (!verify_auth(this, message, this->sent_nonce, this->received_init))
! 566: {
! 567: return FAILED;
! 568: }
! 569: if (this->method->get_auth)
! 570: {
! 571: auth_cfg_t *auth;
! 572:
! 573: auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
! 574: auth->merge(auth, this->method->get_auth(this->method), FALSE);
! 575: }
! 576: return NEED_MORE;
! 577: }
! 578:
! 579: if (!this->method)
! 580: {
! 581: this->eap_payload = server_initiate_eap(this, TRUE);
! 582: }
! 583: else
! 584: {
! 585: eap_payload = (eap_payload_t*)message->get_payload(message,
! 586: PLV2_EAP);
! 587: if (!eap_payload)
! 588: {
! 589: return FAILED;
! 590: }
! 591: this->eap_payload = server_process_eap(this, eap_payload);
! 592: }
! 593: return NEED_MORE;
! 594: }
! 595:
! 596: METHOD(authenticator_t, build_server, status_t,
! 597: private_eap_authenticator_t *this, message_t *message)
! 598: {
! 599: if (this->eap_payload)
! 600: {
! 601: eap_code_t code;
! 602:
! 603: code = this->eap_payload->get_code(this->eap_payload);
! 604: message->add_payload(message, (payload_t*)this->eap_payload);
! 605: this->eap_payload = NULL;
! 606: if (code == EAP_FAILURE)
! 607: {
! 608: return FAILED;
! 609: }
! 610: return NEED_MORE;
! 611: }
! 612: if (this->eap_complete && this->auth_complete &&
! 613: build_auth(this, message, this->received_nonce, this->sent_init))
! 614: {
! 615: return SUCCESS;
! 616: }
! 617: return FAILED;
! 618: }
! 619:
! 620: METHOD(authenticator_t, process_client, status_t,
! 621: private_eap_authenticator_t *this, message_t *message)
! 622: {
! 623: eap_payload_t *eap_payload;
! 624:
! 625: if (this->eap_complete)
! 626: {
! 627: if (!verify_auth(this, message, this->sent_nonce, this->received_init))
! 628: {
! 629: return FAILED;
! 630: }
! 631: if (this->require_mutual && !this->method->is_mutual(this->method))
! 632: { /* we require mutual authentication due to EAP-only */
! 633: uint32_t vendor;
! 634:
! 635: DBG1(DBG_IKE, "EAP-only authentication requires a mutual and "
! 636: "MSK deriving EAP method, but %N is not",
! 637: eap_type_names, this->method->get_type(this->method, &vendor));
! 638: return FAILED;
! 639: }
! 640: return SUCCESS;
! 641: }
! 642:
! 643: eap_payload = (eap_payload_t*)message->get_payload(message,
! 644: PLV2_EAP);
! 645: if (eap_payload)
! 646: {
! 647: switch (eap_payload->get_code(eap_payload))
! 648: {
! 649: case EAP_REQUEST:
! 650: {
! 651: this->eap_payload = client_process_eap(this, eap_payload);
! 652: if (this->eap_payload)
! 653: {
! 654: return NEED_MORE;
! 655: }
! 656: return FAILED;
! 657: }
! 658: case EAP_SUCCESS:
! 659: {
! 660: eap_type_t type;
! 661: uint32_t vendor;
! 662: auth_cfg_t *cfg;
! 663:
! 664: if (this->method->get_msk(this->method, &this->msk) == SUCCESS)
! 665: {
! 666: this->msk = chunk_clone(this->msk);
! 667: }
! 668: type = this->method->get_type(this->method, &vendor);
! 669: if (vendor)
! 670: {
! 671: DBG1(DBG_IKE, "EAP vendor specific method %d-%d succeeded, "
! 672: "%sMSK established", type, vendor,
! 673: this->msk.ptr ? "" : "no ");
! 674: }
! 675: else
! 676: {
! 677: DBG1(DBG_IKE, "EAP method %N succeeded, %sMSK established",
! 678: eap_type_names, type, this->msk.ptr ? "" : "no ");
! 679: }
! 680: cfg = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
! 681: cfg->add(cfg, AUTH_RULE_EAP_TYPE, type);
! 682: if (vendor)
! 683: {
! 684: cfg->add(cfg, AUTH_RULE_EAP_VENDOR, vendor);
! 685: }
! 686: this->eap_complete = TRUE;
! 687: return NEED_MORE;
! 688: }
! 689: case EAP_FAILURE:
! 690: default:
! 691: {
! 692: DBG1(DBG_IKE, "received %N, EAP authentication failed",
! 693: eap_code_names, eap_payload->get_code(eap_payload));
! 694: return FAILED;
! 695: }
! 696: }
! 697: }
! 698: return FAILED;
! 699: }
! 700:
! 701: METHOD(authenticator_t, build_client, status_t,
! 702: private_eap_authenticator_t *this, message_t *message)
! 703: {
! 704: if (this->eap_payload)
! 705: {
! 706: message->add_payload(message, (payload_t*)this->eap_payload);
! 707: this->eap_payload = NULL;
! 708: return NEED_MORE;
! 709: }
! 710: if (this->eap_complete &&
! 711: build_auth(this, message, this->received_nonce, this->sent_init))
! 712: {
! 713: return NEED_MORE;
! 714: }
! 715: return NEED_MORE;
! 716: }
! 717:
! 718: METHOD(authenticator_t, is_mutual, bool,
! 719: private_eap_authenticator_t *this)
! 720: {
! 721: if (this->method)
! 722: {
! 723: uint32_t vendor;
! 724:
! 725: if (this->method->get_type(this->method, &vendor) != EAP_IDENTITY ||
! 726: vendor != 0)
! 727: {
! 728: return this->method->is_mutual(this->method);
! 729: }
! 730: }
! 731: /* we don't know yet, but insist on it after EAP is complete */
! 732: this->require_mutual = TRUE;
! 733: return TRUE;
! 734: }
! 735:
! 736: METHOD(authenticator_t, use_ppk, void,
! 737: private_eap_authenticator_t *this, chunk_t ppk, bool no_ppk_auth)
! 738: {
! 739: this->ppk = ppk;
! 740: this->no_ppk_auth = no_ppk_auth;
! 741: }
! 742:
! 743: METHOD(authenticator_t, destroy, void,
! 744: private_eap_authenticator_t *this)
! 745: {
! 746: DESTROY_IF(this->method);
! 747: DESTROY_IF(this->eap_payload);
! 748: DESTROY_IF(this->eap_identity);
! 749: chunk_free(&this->msk);
! 750: free(this);
! 751: }
! 752:
! 753: /*
! 754: * Described in header.
! 755: */
! 756: eap_authenticator_t *eap_authenticator_create_builder(ike_sa_t *ike_sa,
! 757: chunk_t received_nonce, chunk_t sent_nonce,
! 758: chunk_t received_init, chunk_t sent_init,
! 759: char reserved[3])
! 760: {
! 761: private_eap_authenticator_t *this;
! 762:
! 763: INIT(this,
! 764: .public = {
! 765: .authenticator = {
! 766: .build = _build_client,
! 767: .process = _process_client,
! 768: .use_ppk = _use_ppk,
! 769: .is_mutual = _is_mutual,
! 770: .destroy = _destroy,
! 771: },
! 772: },
! 773: .ike_sa = ike_sa,
! 774: .received_init = received_init,
! 775: .received_nonce = received_nonce,
! 776: .sent_init = sent_init,
! 777: .sent_nonce = sent_nonce,
! 778: );
! 779: memcpy(this->reserved, reserved, sizeof(this->reserved));
! 780:
! 781: return &this->public;
! 782: }
! 783:
! 784: /*
! 785: * Described in header.
! 786: */
! 787: eap_authenticator_t *eap_authenticator_create_verifier(ike_sa_t *ike_sa,
! 788: chunk_t received_nonce, chunk_t sent_nonce,
! 789: chunk_t received_init, chunk_t sent_init,
! 790: char reserved[3])
! 791: {
! 792: private_eap_authenticator_t *this;
! 793:
! 794: INIT(this,
! 795: .public = {
! 796: .authenticator = {
! 797: .build = _build_server,
! 798: .process = _process_server,
! 799: .use_ppk = _use_ppk,
! 800: .is_mutual = _is_mutual,
! 801: .destroy = _destroy,
! 802: },
! 803: },
! 804: .ike_sa = ike_sa,
! 805: .received_init = received_init,
! 806: .received_nonce = received_nonce,
! 807: .sent_init = sent_init,
! 808: .sent_nonce = sent_nonce,
! 809: );
! 810: memcpy(this->reserved, reserved, sizeof(this->reserved));
! 811:
! 812: return &this->public;
! 813: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>