Annotation of embedaddon/strongswan/src/libcharon/plugins/eap_aka/eap_aka_server.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2006-2009 Martin Willi
! 3: * HSR Hochschule fuer Technik Rapperswil
! 4: *
! 5: * This program is free software; you can redistribute it and/or modify it
! 6: * under the terms of the GNU General Public License as published by the
! 7: * Free Software Foundation; either version 2 of the License, or (at your
! 8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
! 9: *
! 10: * This program is distributed in the hope that it will be useful, but
! 11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
! 12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
! 13: * for more details.
! 14: */
! 15:
! 16: #include "eap_aka_server.h"
! 17:
! 18: #include <daemon.h>
! 19: #include <library.h>
! 20:
! 21: #include <simaka_message.h>
! 22: #include <simaka_crypto.h>
! 23: #include <simaka_manager.h>
! 24:
! 25: /** length of the AT_NONCE_S value */
! 26: #define NONCE_LEN 16
! 27:
! 28: typedef struct private_eap_aka_server_t private_eap_aka_server_t;
! 29:
! 30: /**
! 31: * Private data of an eap_aka_server_t object.
! 32: */
! 33: struct private_eap_aka_server_t {
! 34:
! 35: /**
! 36: * Public authenticator_t interface.
! 37: */
! 38: eap_aka_server_t public;
! 39:
! 40: /**
! 41: * AKA backend manager
! 42: */
! 43: simaka_manager_t *mgr;
! 44:
! 45: /**
! 46: * EAP-AKA crypto helper
! 47: */
! 48: simaka_crypto_t *crypto;
! 49:
! 50: /**
! 51: * permanent ID of the peer
! 52: */
! 53: identification_t *permanent;
! 54:
! 55: /**
! 56: * pseudonym ID of peer
! 57: */
! 58: identification_t *pseudonym;
! 59:
! 60: /**
! 61: * reauthentication ID of peer
! 62: */
! 63: identification_t *reauth;
! 64:
! 65: /**
! 66: * EAP message identifier
! 67: */
! 68: uint8_t identifier;
! 69:
! 70: /**
! 71: * Expected Result XRES
! 72: */
! 73: chunk_t xres;
! 74:
! 75: /**
! 76: * Random value RAND
! 77: */
! 78: chunk_t rand;
! 79:
! 80: /**
! 81: * MSK
! 82: */
! 83: chunk_t msk;
! 84:
! 85: /**
! 86: * Nonce value used in AT_NONCE_S
! 87: */
! 88: chunk_t nonce;
! 89:
! 90: /**
! 91: * Counter value negotiated, network order
! 92: */
! 93: chunk_t counter;
! 94:
! 95: /**
! 96: * Do we request fast reauthentication?
! 97: */
! 98: bool use_reauth;
! 99:
! 100: /**
! 101: * Do we request pseudonym identities?
! 102: */
! 103: bool use_pseudonym;
! 104:
! 105: /**
! 106: * Do we request permanent identities?
! 107: */
! 108: bool use_permanent;
! 109:
! 110: /**
! 111: * EAP-AKA message we have initiated
! 112: */
! 113: simaka_subtype_t pending;
! 114:
! 115: /**
! 116: * Did the client send a synchronize request?
! 117: */
! 118: bool synchronized;
! 119: };
! 120:
! 121: /**
! 122: * Generate a payload from a message, destroy message
! 123: */
! 124: static bool generate_payload(simaka_message_t *message, chunk_t data,
! 125: eap_payload_t **out)
! 126: {
! 127: chunk_t chunk;
! 128: bool ok;
! 129:
! 130: ok = message->generate(message, data, &chunk);
! 131: if (ok)
! 132: {
! 133: *out = eap_payload_create_data_own(chunk);
! 134: }
! 135: message->destroy(message);
! 136: return ok;
! 137: }
! 138:
! 139: /**
! 140: * Create EAP-AKA/Request/Identity message
! 141: */
! 142: static status_t identity(private_eap_aka_server_t *this, eap_payload_t **out)
! 143: {
! 144: simaka_message_t *message;
! 145:
! 146: message = simaka_message_create(TRUE, this->identifier++, EAP_AKA,
! 147: AKA_IDENTITY, this->crypto);
! 148: if (this->use_reauth)
! 149: {
! 150: message->add_attribute(message, AT_ANY_ID_REQ, chunk_empty);
! 151: }
! 152: else if (this->use_pseudonym)
! 153: {
! 154: message->add_attribute(message, AT_FULLAUTH_ID_REQ, chunk_empty);
! 155: }
! 156: else if (this->use_permanent)
! 157: {
! 158: message->add_attribute(message, AT_PERMANENT_ID_REQ, chunk_empty);
! 159: }
! 160: if (!generate_payload(message, chunk_empty, out))
! 161: {
! 162: return FAILED;
! 163: }
! 164: this->pending = AKA_IDENTITY;
! 165: return NEED_MORE;
! 166: }
! 167:
! 168: /**
! 169: * Create EAP-AKA/Request/Challenge message
! 170: */
! 171: static status_t challenge(private_eap_aka_server_t *this, eap_payload_t **out)
! 172: {
! 173: simaka_message_t *message;
! 174: char rand[AKA_RAND_LEN], xres[AKA_RES_MAX];
! 175: char ck[AKA_CK_LEN], ik[AKA_IK_LEN], autn[AKA_AUTN_LEN];
! 176: int xres_len;
! 177: chunk_t data, mk;
! 178: identification_t *id;
! 179:
! 180: if (!this->mgr->provider_get_quintuplet(this->mgr, this->permanent,
! 181: rand, xres, &xres_len, ck, ik, autn))
! 182: {
! 183: if (this->use_pseudonym)
! 184: {
! 185: /* probably received a pseudonym/reauth id we couldn't map */
! 186: DBG1(DBG_IKE, "failed to map pseudonym/reauth identity '%Y', "
! 187: "fallback to permanent identity request", this->permanent);
! 188: this->use_pseudonym = FALSE;
! 189: DESTROY_IF(this->pseudonym);
! 190: this->pseudonym = NULL;
! 191: return identity(this, out);
! 192: }
! 193: return FAILED;
! 194: }
! 195: id = this->permanent;
! 196: if (this->pseudonym)
! 197: {
! 198: id = this->pseudonym;
! 199: }
! 200: data = chunk_cata("cc", chunk_create(ik, AKA_IK_LEN),
! 201: chunk_create(ck, AKA_CK_LEN));
! 202: chunk_clear(&this->msk);
! 203: if (!this->crypto->derive_keys_full(this->crypto, id, data, &mk, &this->msk))
! 204: {
! 205: return FAILED;
! 206: }
! 207: this->rand = chunk_clone(chunk_create(rand, AKA_RAND_LEN));
! 208: this->xres = chunk_clone(chunk_create(xres, xres_len));
! 209:
! 210: message = simaka_message_create(TRUE, this->identifier++, EAP_AKA,
! 211: AKA_CHALLENGE, this->crypto);
! 212: message->add_attribute(message, AT_RAND, this->rand);
! 213: message->add_attribute(message, AT_AUTN, chunk_create(autn, AKA_AUTN_LEN));
! 214: id = this->mgr->provider_gen_reauth(this->mgr, this->permanent, mk.ptr);
! 215: free(mk.ptr);
! 216: if (id)
! 217: {
! 218: message->add_attribute(message, AT_NEXT_REAUTH_ID,
! 219: id->get_encoding(id));
! 220: id->destroy(id);
! 221: }
! 222: id = this->mgr->provider_gen_pseudonym(this->mgr, this->permanent);
! 223: if (id)
! 224: {
! 225: message->add_attribute(message, AT_NEXT_PSEUDONYM,
! 226: id->get_encoding(id));
! 227: id->destroy(id);
! 228: }
! 229: if (!generate_payload(message, chunk_empty, out))
! 230: {
! 231: return FAILED;
! 232: }
! 233: this->pending = AKA_CHALLENGE;
! 234: return NEED_MORE;
! 235: }
! 236:
! 237: /**
! 238: * Initiate EAP-AKA/Request/Re-authentication message
! 239: */
! 240: static status_t reauthenticate(private_eap_aka_server_t *this,
! 241: char mk[HASH_SIZE_SHA1], uint16_t counter,
! 242: eap_payload_t **out)
! 243: {
! 244: simaka_message_t *message;
! 245: identification_t *next;
! 246: chunk_t mkc;
! 247: rng_t *rng;
! 248:
! 249: DBG1(DBG_IKE, "initiating EAP-AKA reauthentication");
! 250:
! 251: rng = this->crypto->get_rng(this->crypto);
! 252: if (!rng->allocate_bytes(rng, NONCE_LEN, &this->nonce))
! 253: {
! 254: return FAILED;
! 255: }
! 256:
! 257: mkc = chunk_create(mk, HASH_SIZE_SHA1);
! 258: counter = htons(counter);
! 259: this->counter = chunk_clone(chunk_create((char*)&counter, sizeof(counter)));
! 260:
! 261: if (!this->crypto->derive_keys_reauth(this->crypto, mkc) ||
! 262: !this->crypto->derive_keys_reauth_msk(this->crypto,
! 263: this->reauth, this->counter, this->nonce, mkc, &this->msk))
! 264: {
! 265: return FAILED;
! 266: }
! 267:
! 268: message = simaka_message_create(TRUE, this->identifier++, EAP_AKA,
! 269: AKA_REAUTHENTICATION, this->crypto);
! 270: message->add_attribute(message, AT_COUNTER, this->counter);
! 271: message->add_attribute(message, AT_NONCE_S, this->nonce);
! 272: next = this->mgr->provider_gen_reauth(this->mgr, this->permanent, mk);
! 273: if (next)
! 274: {
! 275: message->add_attribute(message, AT_NEXT_REAUTH_ID,
! 276: next->get_encoding(next));
! 277: next->destroy(next);
! 278: }
! 279: if (!generate_payload(message, chunk_empty, out))
! 280: {
! 281: return FAILED;
! 282: }
! 283: this->pending = SIM_REAUTHENTICATION;
! 284: return NEED_MORE;
! 285: }
! 286:
! 287: METHOD(eap_method_t, initiate, status_t,
! 288: private_eap_aka_server_t *this, eap_payload_t **out)
! 289: {
! 290: if (this->use_permanent || this->use_pseudonym || this->use_reauth)
! 291: {
! 292: return identity(this, out);
! 293: }
! 294: return challenge(this, out);
! 295: }
! 296:
! 297: /**
! 298: * Process EAP-AKA/Response/Identity message
! 299: */
! 300: static status_t process_identity(private_eap_aka_server_t *this,
! 301: simaka_message_t *in, eap_payload_t **out)
! 302: {
! 303: identification_t *permanent, *id;
! 304: enumerator_t *enumerator;
! 305: simaka_attribute_t type;
! 306: chunk_t data, identity = chunk_empty;
! 307:
! 308: if (this->pending != AKA_IDENTITY)
! 309: {
! 310: DBG1(DBG_IKE, "received %N, but not expected",
! 311: simaka_subtype_names, AKA_IDENTITY);
! 312: return FAILED;
! 313: }
! 314:
! 315: enumerator = in->create_attribute_enumerator(in);
! 316: while (enumerator->enumerate(enumerator, &type, &data))
! 317: {
! 318: switch (type)
! 319: {
! 320: case AT_IDENTITY:
! 321: identity = data;
! 322: break;
! 323: default:
! 324: if (!simaka_attribute_skippable(type))
! 325: {
! 326: enumerator->destroy(enumerator);
! 327: return FAILED;
! 328: }
! 329: break;
! 330: }
! 331: }
! 332: enumerator->destroy(enumerator);
! 333:
! 334: if (!identity.len)
! 335: {
! 336: DBG1(DBG_IKE, "received incomplete Identity response");
! 337: return FAILED;
! 338: }
! 339:
! 340: id = identification_create_from_data(identity);
! 341: if (this->use_reauth)
! 342: {
! 343: char mk[HASH_SIZE_SHA1];
! 344: uint16_t counter;
! 345:
! 346: permanent = this->mgr->provider_is_reauth(this->mgr, id, mk, &counter);
! 347: if (permanent)
! 348: {
! 349: this->permanent->destroy(this->permanent);
! 350: this->permanent = permanent;
! 351: this->reauth = id;
! 352: return reauthenticate(this, mk, counter, out);
! 353: }
! 354: /* unable to map, maybe a pseudonym? */
! 355: DBG1(DBG_IKE, "'%Y' is not a reauth identity", id);
! 356: this->use_reauth = FALSE;
! 357: }
! 358: if (this->use_pseudonym)
! 359: {
! 360: permanent = this->mgr->provider_is_pseudonym(this->mgr, id);
! 361: if (permanent)
! 362: {
! 363: this->permanent->destroy(this->permanent);
! 364: this->permanent = permanent;
! 365: this->pseudonym = id->clone(id);
! 366: /* we already have a new permanent identity now */
! 367: this->use_permanent = FALSE;
! 368: }
! 369: else
! 370: {
! 371: DBG1(DBG_IKE, "'%Y' is not a pseudonym", id);
! 372: }
! 373: }
! 374: if (!this->pseudonym && this->use_permanent)
! 375: {
! 376: /* got a permanent identity or a pseudonym reauth id wou couldn't map,
! 377: * try to get quintuplets */
! 378: DBG1(DBG_IKE, "received identity '%Y'", id);
! 379: this->permanent->destroy(this->permanent);
! 380: this->permanent = id->clone(id);
! 381: }
! 382: id->destroy(id);
! 383:
! 384: return challenge(this, out);
! 385: }
! 386:
! 387: /**
! 388: * Process EAP-AKA/Response/Challenge message
! 389: */
! 390: static status_t process_challenge(private_eap_aka_server_t *this,
! 391: simaka_message_t *in)
! 392: {
! 393: enumerator_t *enumerator;
! 394: simaka_attribute_t type;
! 395: chunk_t data, res = chunk_empty;
! 396:
! 397: if (this->pending != AKA_CHALLENGE)
! 398: {
! 399: DBG1(DBG_IKE, "received %N, but not expected",
! 400: simaka_subtype_names, AKA_CHALLENGE);
! 401: return FAILED;
! 402: }
! 403: /* verify MAC of EAP message, AT_MAC */
! 404: if (!in->verify(in, chunk_empty))
! 405: {
! 406: return FAILED;
! 407: }
! 408: enumerator = in->create_attribute_enumerator(in);
! 409: while (enumerator->enumerate(enumerator, &type, &data))
! 410: {
! 411: switch (type)
! 412: {
! 413: case AT_RES:
! 414: res = data;
! 415: break;
! 416: default:
! 417: if (!simaka_attribute_skippable(type))
! 418: {
! 419: enumerator->destroy(enumerator);
! 420: return FAILED;
! 421: }
! 422: break;
! 423: }
! 424: }
! 425: enumerator->destroy(enumerator);
! 426:
! 427: /* compare received RES against stored XRES */
! 428: if (!chunk_equals_const(res, this->xres))
! 429: {
! 430: DBG1(DBG_IKE, "received RES does not match XRES");
! 431: return FAILED;
! 432: }
! 433: return SUCCESS;
! 434: }
! 435:
! 436: /**
! 437: * process an EAP-AKA/Response/Reauthentication message
! 438: */
! 439: static status_t process_reauthentication(private_eap_aka_server_t *this,
! 440: simaka_message_t *in, eap_payload_t **out)
! 441: {
! 442: enumerator_t *enumerator;
! 443: simaka_attribute_t type;
! 444: chunk_t data, counter = chunk_empty;
! 445: bool too_small = FALSE;
! 446:
! 447: if (this->pending != AKA_REAUTHENTICATION)
! 448: {
! 449: DBG1(DBG_IKE, "received %N, but not expected",
! 450: simaka_subtype_names, AKA_REAUTHENTICATION);
! 451: return FAILED;
! 452: }
! 453: /* verify AT_MAC attribute, signature is over "EAP packet | NONCE_S" */
! 454: if (!in->verify(in, this->nonce))
! 455: {
! 456: return FAILED;
! 457: }
! 458:
! 459: enumerator = in->create_attribute_enumerator(in);
! 460: while (enumerator->enumerate(enumerator, &type, &data))
! 461: {
! 462: switch (type)
! 463: {
! 464: case AT_COUNTER:
! 465: counter = data;
! 466: break;
! 467: case AT_COUNTER_TOO_SMALL:
! 468: too_small = TRUE;
! 469: break;
! 470: default:
! 471: if (!simaka_attribute_skippable(type))
! 472: {
! 473: enumerator->destroy(enumerator);
! 474: return FAILED;
! 475: }
! 476: break;
! 477: }
! 478: }
! 479: enumerator->destroy(enumerator);
! 480:
! 481: if (too_small)
! 482: {
! 483: DBG1(DBG_IKE, "received %N, initiating full authentication",
! 484: simaka_attribute_names, AT_COUNTER_TOO_SMALL);
! 485: this->use_reauth = FALSE;
! 486: this->crypto->clear_keys(this->crypto);
! 487: return challenge(this, out);
! 488: }
! 489: if (!chunk_equals_const(counter, this->counter))
! 490: {
! 491: DBG1(DBG_IKE, "received counter does not match");
! 492: return FAILED;
! 493: }
! 494: return SUCCESS;
! 495: }
! 496:
! 497: /**
! 498: * Process EAP-AKA/Response/SynchronizationFailure message
! 499: */
! 500: static status_t process_synchronize(private_eap_aka_server_t *this,
! 501: simaka_message_t *in, eap_payload_t **out)
! 502: {
! 503: enumerator_t *enumerator;
! 504: simaka_attribute_t type;
! 505: chunk_t data, auts = chunk_empty;
! 506:
! 507: if (this->synchronized)
! 508: {
! 509: DBG1(DBG_IKE, "received %N, but peer did already resynchronize",
! 510: simaka_subtype_names, AKA_SYNCHRONIZATION_FAILURE);
! 511: return FAILED;
! 512: }
! 513:
! 514: DBG1(DBG_IKE, "received synchronization request, retrying...");
! 515:
! 516: enumerator = in->create_attribute_enumerator(in);
! 517: while (enumerator->enumerate(enumerator, &type, &data))
! 518: {
! 519: switch (type)
! 520: {
! 521: case AT_AUTS:
! 522: auts = data;
! 523: break;
! 524: default:
! 525: if (!simaka_attribute_skippable(type))
! 526: {
! 527: enumerator->destroy(enumerator);
! 528: return FAILED;
! 529: }
! 530: break;
! 531: }
! 532: }
! 533: enumerator->destroy(enumerator);
! 534:
! 535: if (!auts.len)
! 536: {
! 537: DBG1(DBG_IKE, "synchronization request didn't contain usable AUTS");
! 538: return FAILED;
! 539: }
! 540:
! 541: if (!this->mgr->provider_resync(this->mgr, this->permanent,
! 542: this->rand.ptr, auts.ptr))
! 543: {
! 544: DBG1(DBG_IKE, "no AKA provider found supporting "
! 545: "resynchronization for '%Y'", this->permanent);
! 546: return FAILED;
! 547: }
! 548: this->synchronized = TRUE;
! 549: return challenge(this, out);
! 550: }
! 551:
! 552: /**
! 553: * Process EAP-AKA/Response/ClientErrorCode message
! 554: */
! 555: static status_t process_client_error(private_eap_aka_server_t *this,
! 556: simaka_message_t *in)
! 557: {
! 558: enumerator_t *enumerator;
! 559: simaka_attribute_t type;
! 560: chunk_t data;
! 561:
! 562: enumerator = in->create_attribute_enumerator(in);
! 563: while (enumerator->enumerate(enumerator, &type, &data))
! 564: {
! 565: if (type == AT_CLIENT_ERROR_CODE)
! 566: {
! 567: uint16_t code;
! 568:
! 569: memcpy(&code, data.ptr, sizeof(code));
! 570: DBG1(DBG_IKE, "received EAP-AKA client error '%N'",
! 571: simaka_client_error_names, ntohs(code));
! 572: }
! 573: else if (!simaka_attribute_skippable(type))
! 574: {
! 575: break;
! 576: }
! 577: }
! 578: enumerator->destroy(enumerator);
! 579: return FAILED;
! 580: }
! 581:
! 582: /**
! 583: * Process EAP-AKA/Response/AuthenticationReject message
! 584: */
! 585: static status_t process_authentication_reject(private_eap_aka_server_t *this,
! 586: simaka_message_t *in)
! 587: {
! 588: DBG1(DBG_IKE, "received %N, authentication failed",
! 589: simaka_subtype_names, in->get_subtype(in));
! 590: return FAILED;
! 591: }
! 592:
! 593: METHOD(eap_method_t, process, status_t,
! 594: private_eap_aka_server_t *this, eap_payload_t *in, eap_payload_t **out)
! 595: {
! 596: simaka_message_t *message;
! 597: status_t status;
! 598:
! 599: message = simaka_message_create_from_payload(in->get_data(in), this->crypto);
! 600: if (!message)
! 601: {
! 602: return FAILED;
! 603: }
! 604: if (!message->parse(message))
! 605: {
! 606: message->destroy(message);
! 607: return FAILED;
! 608: }
! 609: switch (message->get_subtype(message))
! 610: {
! 611: case AKA_IDENTITY:
! 612: status = process_identity(this, message, out);
! 613: break;
! 614: case AKA_CHALLENGE:
! 615: status = process_challenge(this, message);
! 616: break;
! 617: case AKA_REAUTHENTICATION:
! 618: status = process_reauthentication(this, message, out);
! 619: break;
! 620: case AKA_SYNCHRONIZATION_FAILURE:
! 621: status = process_synchronize(this, message, out);
! 622: break;
! 623: case AKA_CLIENT_ERROR:
! 624: status = process_client_error(this, message);
! 625: break;
! 626: case AKA_AUTHENTICATION_REJECT:
! 627: status = process_authentication_reject(this, message);
! 628: break;
! 629: default:
! 630: DBG1(DBG_IKE, "unable to process EAP-AKA subtype %N",
! 631: simaka_subtype_names, message->get_subtype(message));
! 632: status = FAILED;
! 633: break;
! 634: }
! 635: message->destroy(message);
! 636: return status;
! 637: }
! 638:
! 639: METHOD(eap_method_t, get_type, eap_type_t,
! 640: private_eap_aka_server_t *this, uint32_t *vendor)
! 641: {
! 642: *vendor = 0;
! 643: return EAP_AKA;
! 644: }
! 645:
! 646: METHOD(eap_method_t, get_msk, status_t,
! 647: private_eap_aka_server_t *this, chunk_t *msk)
! 648: {
! 649: if (this->msk.ptr)
! 650: {
! 651: *msk = this->msk;
! 652: return SUCCESS;
! 653: }
! 654: return FAILED;
! 655: }
! 656:
! 657: METHOD(eap_method_t, get_identifier, uint8_t,
! 658: private_eap_aka_server_t *this)
! 659: {
! 660: return this->identifier;
! 661: }
! 662:
! 663: METHOD(eap_method_t, set_identifier, void,
! 664: private_eap_aka_server_t *this, uint8_t identifier)
! 665: {
! 666: this->identifier = identifier;
! 667: }
! 668:
! 669: METHOD(eap_method_t, is_mutual, bool,
! 670: private_eap_aka_server_t *this)
! 671: {
! 672: return TRUE;
! 673: }
! 674:
! 675: METHOD(eap_method_t, destroy, void,
! 676: private_eap_aka_server_t *this)
! 677: {
! 678: this->crypto->destroy(this->crypto);
! 679: this->permanent->destroy(this->permanent);
! 680: DESTROY_IF(this->pseudonym);
! 681: DESTROY_IF(this->reauth);
! 682: free(this->xres.ptr);
! 683: free(this->rand.ptr);
! 684: free(this->nonce.ptr);
! 685: free(this->msk.ptr);
! 686: free(this->counter.ptr);
! 687: free(this);
! 688: }
! 689:
! 690: /*
! 691: * Described in header.
! 692: */
! 693: eap_aka_server_t *eap_aka_server_create(identification_t *server,
! 694: identification_t *peer)
! 695: {
! 696: private_eap_aka_server_t *this;
! 697:
! 698: INIT(this,
! 699: .public = {
! 700: .interface = {
! 701: .initiate = _initiate,
! 702: .process = _process,
! 703: .get_type = _get_type,
! 704: .is_mutual = _is_mutual,
! 705: .get_msk = _get_msk,
! 706: .get_identifier = _get_identifier,
! 707: .set_identifier = _set_identifier,
! 708: .destroy = _destroy,
! 709: },
! 710: },
! 711: .crypto = simaka_crypto_create(EAP_AKA),
! 712: .mgr = lib->get(lib, "aka-manager"),
! 713: );
! 714:
! 715: if (!this->crypto)
! 716: {
! 717: free(this);
! 718: return NULL;
! 719: }
! 720:
! 721: this->permanent = peer->clone(peer);
! 722: this->use_reauth = this->use_pseudonym = this->use_permanent =
! 723: lib->settings->get_bool(lib->settings,
! 724: "%s.plugins.eap-aka.request_identity", TRUE, lib->ns);
! 725:
! 726: /* generate a non-zero identifier */
! 727: do {
! 728: this->identifier = random();
! 729: } while (!this->identifier);
! 730:
! 731: return &this->public;
! 732: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>