Return to eap_radius.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libcharon / plugins / eap_radius |
1.1 misho 1: /* 2: * Copyright (C) 2012-2018 Tobias Brunner 3: * Copyright (C) 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_radius.h" 18: #include "eap_radius_plugin.h" 19: #include "eap_radius_forward.h" 20: #include "eap_radius_provider.h" 21: #include "eap_radius_accounting.h" 22: 23: #include <radius_message.h> 24: #include <radius_client.h> 25: #include <bio/bio_writer.h> 26: 27: #include <daemon.h> 28: 29: typedef struct private_eap_radius_t private_eap_radius_t; 30: 31: /** 32: * Private data of an eap_radius_t object. 33: */ 34: struct private_eap_radius_t { 35: 36: /** 37: * Public authenticator_t interface. 38: */ 39: eap_radius_t public; 40: 41: /** 42: * ID of the server 43: */ 44: identification_t *server; 45: 46: /** 47: * ID of the peer 48: */ 49: identification_t *peer; 50: 51: /** 52: * EAP method type we are proxying 53: */ 54: eap_type_t type; 55: 56: /** 57: * EAP vendor, if any 58: */ 59: uint32_t vendor; 60: 61: /** 62: * EAP message identifier 63: */ 64: uint8_t identifier; 65: 66: /** 67: * RADIUS client instance 68: */ 69: radius_client_t *client; 70: 71: /** 72: * TRUE to use EAP-Start, FALSE to send EAP-Identity Response directly 73: */ 74: bool eap_start; 75: 76: /** 77: * Prefix to prepend to EAP identity 78: */ 79: char *id_prefix; 80: }; 81: 82: /** 83: * Add EAP-Identity to RADIUS message 84: */ 85: static void add_eap_identity(private_eap_radius_t *this, 86: radius_message_t *request) 87: { 88: struct { 89: /** EAP code (REQUEST/RESPONSE) */ 90: uint8_t code; 91: /** unique message identifier */ 92: uint8_t identifier; 93: /** length of whole message */ 94: uint16_t length; 95: /** EAP type */ 96: uint8_t type; 97: /** identity data */ 98: uint8_t data[]; 99: } __attribute__((__packed__)) *hdr; 100: chunk_t id, prefix; 101: size_t len; 102: 103: id = this->peer->get_encoding(this->peer); 104: prefix = chunk_create(this->id_prefix, strlen(this->id_prefix)); 105: len = sizeof(*hdr) + prefix.len + id.len; 106: 107: hdr = alloca(len); 108: hdr->code = EAP_RESPONSE; 109: hdr->identifier = this->identifier; 110: hdr->length = htons(len); 111: hdr->type = EAP_IDENTITY; 112: memcpy(hdr->data, prefix.ptr, prefix.len); 113: memcpy(hdr->data + prefix.len, id.ptr, id.len); 114: 115: request->add(request, RAT_EAP_MESSAGE, chunk_create((u_char*)hdr, len)); 116: } 117: 118: /** 119: * Copy EAP-Message attribute from RADIUS message to an new EAP payload 120: */ 121: static bool radius2ike(private_eap_radius_t *this, 122: radius_message_t *msg, eap_payload_t **out) 123: { 124: enumerator_t *enumerator; 125: eap_payload_t *payload; 126: chunk_t data, message = chunk_empty; 127: int type; 128: 129: enumerator = msg->create_enumerator(msg); 130: while (enumerator->enumerate(enumerator, &type, &data)) 131: { 132: if (type == RAT_EAP_MESSAGE && data.len) 133: { 134: message = chunk_cat("mc", message, data); 135: } 136: } 137: enumerator->destroy(enumerator); 138: if (message.len) 139: { 140: *out = payload = eap_payload_create_data(message); 141: 142: /* apply EAP method selected by RADIUS server */ 143: this->type = payload->get_type(payload, &this->vendor); 144: 145: DBG3(DBG_IKE, "%N payload %B", eap_type_names, this->type, &message); 146: free(message.ptr); 147: return TRUE; 148: } 149: return FALSE; 150: } 151: 152: /** 153: * See header. 154: */ 155: void eap_radius_build_attributes(radius_message_t *request) 156: { 157: ike_sa_t *ike_sa; 158: host_t *host; 159: char buf[40], *station_id_fmt, *session_id; 160: uint32_t value; 161: chunk_t chunk; 162: 163: /* virtual NAS-Port-Type */ 164: value = htonl(5); 165: request->add(request, RAT_NAS_PORT_TYPE, chunk_from_thing(value)); 166: /* framed ServiceType */ 167: value = htonl(2); 168: request->add(request, RAT_SERVICE_TYPE, chunk_from_thing(value)); 169: 170: ike_sa = charon->bus->get_sa(charon->bus); 171: if (ike_sa) 172: { 173: value = htonl(ike_sa->get_unique_id(ike_sa)); 174: request->add(request, RAT_NAS_PORT, chunk_from_thing(value)); 175: request->add(request, RAT_NAS_PORT_ID, 176: chunk_from_str(ike_sa->get_name(ike_sa))); 177: 178: host = ike_sa->get_my_host(ike_sa); 179: chunk = host->get_address(host); 180: switch (host->get_family(host)) 181: { 182: case AF_INET: 183: request->add(request, RAT_NAS_IP_ADDRESS, chunk); 184: break; 185: case AF_INET6: 186: request->add(request, RAT_NAS_IPV6_ADDRESS, chunk); 187: default: 188: break; 189: } 190: if (lib->settings->get_bool(lib->settings, 191: "%s.plugins.eap-radius.station_id_with_port", 192: TRUE, lib->ns)) 193: { 194: station_id_fmt = "%#H"; 195: } 196: else 197: { 198: station_id_fmt = "%H"; 199: } 200: snprintf(buf, sizeof(buf), station_id_fmt, host); 201: request->add(request, RAT_CALLED_STATION_ID, chunk_from_str(buf)); 202: host = ike_sa->get_other_host(ike_sa); 203: snprintf(buf, sizeof(buf), station_id_fmt, host); 204: request->add(request, RAT_CALLING_STATION_ID, chunk_from_str(buf)); 205: 206: session_id = eap_radius_accounting_session_id(ike_sa); 207: if (session_id) 208: { 209: request->add(request, RAT_ACCT_SESSION_ID, 210: chunk_from_str(session_id)); 211: free(session_id); 212: } 213: } 214: } 215: 216: /** 217: * Add a set of RADIUS attributes to a request message 218: */ 219: static void add_radius_request_attrs(private_eap_radius_t *this, 220: radius_message_t *request) 221: { 222: chunk_t chunk; 223: 224: chunk = chunk_from_str(this->id_prefix); 225: chunk = chunk_cata("cc", chunk, this->peer->get_encoding(this->peer)); 226: request->add(request, RAT_USER_NAME, chunk); 227: 228: eap_radius_build_attributes(request); 229: eap_radius_forward_from_ike(request); 230: } 231: 232: METHOD(eap_method_t, initiate, status_t, 233: private_eap_radius_t *this, eap_payload_t **out) 234: { 235: radius_message_t *request, *response; 236: status_t status = FAILED; 237: 238: request = radius_message_create(RMC_ACCESS_REQUEST); 239: add_radius_request_attrs(this, request); 240: 241: if (this->eap_start) 242: { 243: request->add(request, RAT_EAP_MESSAGE, chunk_empty); 244: } 245: else 246: { 247: add_eap_identity(this, request); 248: } 249: 250: response = this->client->request(this->client, request); 251: if (response) 252: { 253: eap_radius_forward_to_ike(response); 254: switch (response->get_code(response)) 255: { 256: case RMC_ACCESS_CHALLENGE: 257: if (radius2ike(this, response, out)) 258: { 259: status = NEED_MORE; 260: } 261: break; 262: case RMC_ACCESS_ACCEPT: 263: /* Microsoft RADIUS servers can run in a mode where they respond 264: * like this on the first request (i.e. without authentication), 265: * we treat this as Access-Reject */ 266: case RMC_ACCESS_REJECT: 267: default: 268: DBG1(DBG_IKE, "RADIUS authentication of '%Y' failed", 269: this->peer); 270: break; 271: } 272: response->destroy(response); 273: } 274: else 275: { 276: eap_radius_handle_timeout(NULL); 277: } 278: request->destroy(request); 279: return status; 280: } 281: 282: /** 283: * Handle the Class attribute 284: */ 285: static void process_class(radius_message_t *msg) 286: { 287: enumerator_t *enumerator; 288: ike_sa_t *ike_sa; 289: identification_t *id; 290: auth_cfg_t *auth; 291: chunk_t data; 292: bool class_group, class_send; 293: int type; 294: 295: class_group = lib->settings->get_bool(lib->settings, 296: "%s.plugins.eap-radius.class_group", FALSE, lib->ns); 297: class_send = lib->settings->get_bool(lib->settings, 298: "%s.plugins.eap-radius.accounting_send_class", FALSE, lib->ns); 299: ike_sa = charon->bus->get_sa(charon->bus); 300: 301: if ((!class_group && !class_send) || !ike_sa) 302: { 303: return; 304: } 305: 306: enumerator = msg->create_enumerator(msg); 307: while (enumerator->enumerate(enumerator, &type, &data)) 308: { 309: if (type == RAT_CLASS) 310: { 311: if (class_group && data.len < 44) 312: { /* quirk: ignore long class attributes, these are used for 313: * other purposes by some RADIUS servers (such as NPS). */ 314: auth = ike_sa->get_auth_cfg(ike_sa, FALSE); 315: id = identification_create_from_data(data); 316: DBG1(DBG_CFG, "received group membership '%Y' from RADIUS", 317: id); 318: auth->add(auth, AUTH_RULE_GROUP, id); 319: } 320: if (class_send) 321: { 322: eap_radius_accounting_add_class(ike_sa, data); 323: } 324: } 325: } 326: enumerator->destroy(enumerator); 327: } 328: 329: /** 330: * Handle the Filter-Id attribute as IPsec CHILD_SA name 331: */ 332: static void process_filter_id(radius_message_t *msg) 333: { 334: enumerator_t *enumerator; 335: int type; 336: uint8_t tunnel_tag; 337: uint32_t tunnel_type; 338: chunk_t filter_id = chunk_empty, data; 339: bool is_esp_tunnel = FALSE; 340: 341: enumerator = msg->create_enumerator(msg); 342: while (enumerator->enumerate(enumerator, &type, &data)) 343: { 344: switch (type) 345: { 346: case RAT_TUNNEL_TYPE: 347: if (data.len != 4) 348: { 349: continue; 350: } 351: tunnel_tag = *data.ptr; 352: *data.ptr = 0x00; 353: tunnel_type = untoh32(data.ptr); 354: DBG1(DBG_IKE, "received RADIUS attribute Tunnel-Type: " 355: "tag = %u, value = %u", tunnel_tag, tunnel_type); 356: is_esp_tunnel = (tunnel_type == RADIUS_TUNNEL_TYPE_ESP); 357: break; 358: case RAT_FILTER_ID: 359: filter_id = data; 360: DBG1(DBG_IKE, "received RADIUS attribute Filter-Id: " 361: "'%.*s'", (int)filter_id.len, filter_id.ptr); 362: break; 363: default: 364: break; 365: } 366: } 367: enumerator->destroy(enumerator); 368: 369: if (is_esp_tunnel && filter_id.len) 370: { 371: identification_t *id; 372: ike_sa_t *ike_sa; 373: auth_cfg_t *auth; 374: 375: ike_sa = charon->bus->get_sa(charon->bus); 376: if (ike_sa) 377: { 378: auth = ike_sa->get_auth_cfg(ike_sa, FALSE); 379: id = identification_create_from_data(filter_id); 380: auth->add(auth, AUTH_RULE_GROUP, id); 381: } 382: } 383: } 384: 385: /** 386: * Handle Session-Timeout attribute and Interim updates 387: */ 388: static void process_timeout(radius_message_t *msg) 389: { 390: enumerator_t *enumerator; 391: ike_sa_t *ike_sa; 392: chunk_t data; 393: int type; 394: 395: ike_sa = charon->bus->get_sa(charon->bus); 396: if (ike_sa) 397: { 398: enumerator = msg->create_enumerator(msg); 399: while (enumerator->enumerate(enumerator, &type, &data)) 400: { 401: if (type == RAT_SESSION_TIMEOUT && data.len == 4) 402: { 403: ike_sa->set_auth_lifetime(ike_sa, untoh32(data.ptr)); 404: } 405: else if (type == RAT_ACCT_INTERIM_INTERVAL && data.len == 4) 406: { 407: eap_radius_accounting_start_interim(ike_sa, untoh32(data.ptr)); 408: } 409: } 410: enumerator->destroy(enumerator); 411: } 412: } 413: 414: /** 415: * Add a Cisco Unity configuration attribute 416: */ 417: static void add_unity_attribute(eap_radius_provider_t *provider, uint32_t id, 418: int type, chunk_t data) 419: { 420: switch (type) 421: { 422: case 15: /* CVPN3000-IPSec-Banner1 */ 423: case 36: /* CVPN3000-IPSec-Banner2 */ 424: provider->add_attribute(provider, id, UNITY_BANNER, data); 425: break; 426: case 28: /* CVPN3000-IPSec-Default-Domain */ 427: provider->add_attribute(provider, id, UNITY_DEF_DOMAIN, data); 428: break; 429: case 29: /* CVPN3000-IPSec-Split-DNS-Names */ 430: provider->add_attribute(provider, id, UNITY_SPLITDNS_NAME, data); 431: break; 432: } 433: } 434: 435: /** 436: * Add a DNS/NBNS configuration attribute 437: */ 438: static void add_nameserver_attribute(eap_radius_provider_t *provider, 439: uint32_t id, int type, chunk_t data) 440: { 441: /* these are from different vendors, but there is currently no conflict */ 442: switch (type) 443: { 444: case 5: /* CVPN3000-Primary-DNS */ 445: case 6: /* CVPN3000-Secondary-DNS */ 446: case 28: /* MS-Primary-DNS-Server */ 447: case 29: /* MS-Secondary-DNS-Server */ 448: provider->add_attribute(provider, id, INTERNAL_IP4_DNS, data); 449: break; 450: case 7: /* CVPN3000-Primary-WINS */ 451: case 8: /* CVPN3000-Secondary-WINS */ 452: case 30: /* MS-Primary-NBNS-Server */ 453: case 31: /* MS-Secondary-NBNS-Server */ 454: provider->add_attribute(provider, id, INTERNAL_IP4_NBNS, data); 455: break; 456: case RAT_FRAMED_IPV6_DNS_SERVER: 457: provider->add_attribute(provider, id, INTERNAL_IP6_DNS, data); 458: break; 459: } 460: } 461: 462: /** 463: * Add a UNITY_LOCAL_LAN or UNITY_SPLIT_INCLUDE attribute 464: */ 465: static void add_unity_split_attribute(eap_radius_provider_t *provider, 466: uint32_t id, configuration_attribute_type_t type, 467: chunk_t data) 468: { 469: enumerator_t *enumerator; 470: bio_writer_t *writer; 471: char buffer[256], *token, *slash; 472: 473: if (snprintf(buffer, sizeof(buffer), "%.*s", (int)data.len, 474: data.ptr) >= sizeof(buffer)) 475: { 476: return; 477: } 478: writer = bio_writer_create(16); /* two IPv4 addresses and 6 bytes padding */ 479: enumerator = enumerator_create_token(buffer, ",", " "); 480: while (enumerator->enumerate(enumerator, &token)) 481: { 482: host_t *net, *mask = NULL; 483: chunk_t padding; 484: 485: slash = strchr(token, '/'); 486: if (slash) 487: { 488: *slash++ = '\0'; 489: mask = host_create_from_string(slash, 0); 490: } 491: if (!mask) 492: { /* default to /32 */ 493: mask = host_create_from_string("255.255.255.255", 0); 494: } 495: net = host_create_from_string(token, 0); 496: if (!net || net->get_family(net) != AF_INET || 497: mask->get_family(mask) != AF_INET) 498: { 499: mask->destroy(mask); 500: DESTROY_IF(net); 501: continue; 502: } 503: writer->write_data(writer, net->get_address(net)); 504: writer->write_data(writer, mask->get_address(mask)); 505: padding = writer->skip(writer, 6); /* 6 bytes padding */ 506: memset(padding.ptr, 0, padding.len); 507: mask->destroy(mask); 508: net->destroy(net); 509: } 510: enumerator->destroy(enumerator); 511: 512: data = writer->get_buf(writer); 513: if (data.len) 514: { 515: provider->add_attribute(provider, id, type, data); 516: } 517: writer->destroy(writer); 518: } 519: 520: /** 521: * Handle Framed-IP-Address and other IKE configuration attributes 522: */ 523: static void process_cfg_attributes(radius_message_t *msg) 524: { 525: eap_radius_provider_t *provider; 526: enumerator_t *enumerator; 527: ike_sa_t *ike_sa; 528: host_t *host; 529: chunk_t data; 530: configuration_attribute_type_t split_type = 0; 531: int type, vendor; 532: 533: ike_sa = charon->bus->get_sa(charon->bus); 534: provider = eap_radius_provider_get(); 535: if (provider && ike_sa) 536: { 537: enumerator = msg->create_enumerator(msg); 538: while (enumerator->enumerate(enumerator, &type, &data)) 539: { 540: if ((type == RAT_FRAMED_IP_ADDRESS && data.len == 4) || 541: (type == RAT_FRAMED_IPV6_ADDRESS && data.len == 16)) 542: { 543: host = host_create_from_chunk(AF_UNSPEC, data, 0); 544: if (host) 545: { 546: provider->add_framed_ip(provider, 547: ike_sa->get_unique_id(ike_sa), host); 548: } 549: } 550: else if (type == RAT_FRAMED_IP_NETMASK && data.len == 4) 551: { 552: provider->add_attribute(provider, ike_sa->get_unique_id(ike_sa), 553: INTERNAL_IP4_NETMASK, data); 554: } 555: else if (type == RAT_FRAMED_IPV6_DNS_SERVER && data.len == 16) 556: { 557: add_nameserver_attribute(provider, 558: ike_sa->get_unique_id(ike_sa), type, data); 559: } 560: } 561: enumerator->destroy(enumerator); 562: 563: enumerator = msg->create_vendor_enumerator(msg); 564: while (enumerator->enumerate(enumerator, &vendor, &type, &data)) 565: { 566: if (vendor == PEN_ALTIGA /* aka Cisco VPN3000 */) 567: { 568: switch (type) 569: { 570: case 5: /* CVPN3000-Primary-DNS */ 571: case 6: /* CVPN3000-Secondary-DNS */ 572: case 7: /* CVPN3000-Primary-WINS */ 573: case 8: /* CVPN3000-Secondary-WINS */ 574: if (data.len == 4) 575: { 576: add_nameserver_attribute(provider, 577: ike_sa->get_unique_id(ike_sa), type, data); 578: } 579: break; 580: case 15: /* CVPN3000-IPSec-Banner1 */ 581: case 28: /* CVPN3000-IPSec-Default-Domain */ 582: case 29: /* CVPN3000-IPSec-Split-DNS-Names */ 583: case 36: /* CVPN3000-IPSec-Banner2 */ 584: if (ike_sa->supports_extension(ike_sa, EXT_CISCO_UNITY)) 585: { 586: add_unity_attribute(provider, 587: ike_sa->get_unique_id(ike_sa), type, data); 588: } 589: break; 590: case 55: /* CVPN3000-IPSec-Split-Tunneling-Policy */ 591: if (data.len) 592: { 593: switch (data.ptr[data.len - 1]) 594: { 595: case 0: /* tunnelall */ 596: default: 597: break; 598: case 1: /* tunnelspecified */ 599: split_type = UNITY_SPLIT_INCLUDE; 600: break; 601: case 2: /* excludespecified */ 602: split_type = UNITY_LOCAL_LAN; 603: break; 604: } 605: } 606: break; 607: default: 608: break; 609: } 610: } 611: if (vendor == PEN_MICROSOFT) 612: { 613: switch (type) 614: { 615: case 28: /* MS-Primary-DNS-Server */ 616: case 29: /* MS-Secondary-DNS-Server */ 617: case 30: /* MS-Primary-NBNS-Server */ 618: case 31: /* MS-Secondary-NBNS-Server */ 619: if (data.len == 4) 620: { 621: add_nameserver_attribute(provider, 622: ike_sa->get_unique_id(ike_sa), type, data); 623: } 624: break; 625: } 626: } 627: } 628: enumerator->destroy(enumerator); 629: 630: if (split_type != 0 && 631: ike_sa->supports_extension(ike_sa, EXT_CISCO_UNITY)) 632: { 633: enumerator = msg->create_vendor_enumerator(msg); 634: while (enumerator->enumerate(enumerator, &vendor, &type, &data)) 635: { 636: if (vendor == PEN_ALTIGA /* aka Cisco VPN3000 */ && 637: type == 27 /* CVPN3000-IPSec-Split-Tunnel-List */) 638: { 639: add_unity_split_attribute(provider, 640: ike_sa->get_unique_id(ike_sa), split_type, data); 641: } 642: } 643: enumerator->destroy(enumerator); 644: } 645: } 646: } 647: 648: /** 649: * See header. 650: */ 651: void eap_radius_process_attributes(radius_message_t *message) 652: { 653: process_class(message); 654: if (lib->settings->get_bool(lib->settings, 655: "%s.plugins.eap-radius.filter_id", FALSE, lib->ns)) 656: { 657: process_filter_id(message); 658: } 659: process_timeout(message); 660: process_cfg_attributes(message); 661: } 662: 663: METHOD(eap_method_t, process, status_t, 664: private_eap_radius_t *this, eap_payload_t *in, eap_payload_t **out) 665: { 666: radius_message_t *request, *response; 667: status_t status = FAILED; 668: chunk_t data; 669: 670: request = radius_message_create(RMC_ACCESS_REQUEST); 671: add_radius_request_attrs(this, request); 672: 673: data = in->get_data(in); 674: DBG3(DBG_IKE, "%N payload %B", eap_type_names, this->type, &data); 675: 676: /* fragment data suitable for RADIUS */ 677: while (data.len > MAX_RADIUS_ATTRIBUTE_SIZE) 678: { 679: request->add(request, RAT_EAP_MESSAGE, 680: chunk_create(data.ptr,MAX_RADIUS_ATTRIBUTE_SIZE)); 681: data = chunk_skip(data, MAX_RADIUS_ATTRIBUTE_SIZE); 682: } 683: request->add(request, RAT_EAP_MESSAGE, data); 684: 685: response = this->client->request(this->client, request); 686: if (response) 687: { 688: eap_radius_forward_to_ike(response); 689: switch (response->get_code(response)) 690: { 691: case RMC_ACCESS_CHALLENGE: 692: if (radius2ike(this, response, out)) 693: { 694: status = NEED_MORE; 695: break; 696: } 697: status = FAILED; 698: break; 699: case RMC_ACCESS_ACCEPT: 700: eap_radius_process_attributes(response); 701: DBG1(DBG_IKE, "RADIUS authentication of '%Y' successful", 702: this->peer); 703: status = SUCCESS; 704: break; 705: case RMC_ACCESS_REJECT: 706: default: 707: DBG1(DBG_IKE, "RADIUS authentication of '%Y' failed", 708: this->peer); 709: status = FAILED; 710: break; 711: } 712: response->destroy(response); 713: } 714: request->destroy(request); 715: return status; 716: } 717: 718: METHOD(eap_method_t, get_type, eap_type_t, 719: private_eap_radius_t *this, uint32_t *vendor) 720: { 721: *vendor = this->vendor; 722: return this->type; 723: } 724: 725: METHOD(eap_method_t, get_msk, status_t, 726: private_eap_radius_t *this, chunk_t *out) 727: { 728: chunk_t msk; 729: 730: msk = this->client->get_msk(this->client); 731: if (msk.len) 732: { 733: *out = msk; 734: return SUCCESS; 735: } 736: return FAILED; 737: } 738: 739: METHOD(eap_method_t, get_identifier, uint8_t, 740: private_eap_radius_t *this) 741: { 742: return this->identifier; 743: } 744: 745: METHOD(eap_method_t, set_identifier, void, 746: private_eap_radius_t *this, uint8_t identifier) 747: { 748: this->identifier = identifier; 749: } 750: 751: METHOD(eap_method_t, is_mutual, bool, 752: private_eap_radius_t *this) 753: { 754: switch (this->type) 755: { 756: case EAP_AKA: 757: case EAP_SIM: 758: return TRUE; 759: default: 760: return FALSE; 761: } 762: } 763: 764: METHOD(eap_method_t, destroy, void, 765: private_eap_radius_t *this) 766: { 767: this->peer->destroy(this->peer); 768: this->server->destroy(this->server); 769: this->client->destroy(this->client); 770: free(this); 771: } 772: 773: /** 774: * Generic constructor 775: */ 776: eap_radius_t *eap_radius_create(identification_t *server, identification_t *peer) 777: { 778: private_eap_radius_t *this; 779: 780: INIT(this, 781: .public = { 782: .eap_method = { 783: .initiate = _initiate, 784: .process = _process, 785: .get_type = _get_type, 786: .is_mutual = _is_mutual, 787: .get_msk = _get_msk, 788: .get_identifier = _get_identifier, 789: .set_identifier = _set_identifier, 790: .destroy = _destroy, 791: }, 792: }, 793: /* initially EAP_RADIUS, but is set to the method selected by RADIUS */ 794: .type = EAP_RADIUS, 795: .eap_start = lib->settings->get_bool(lib->settings, 796: "%s.plugins.eap-radius.eap_start", FALSE, 797: lib->ns), 798: .id_prefix = lib->settings->get_str(lib->settings, 799: "%s.plugins.eap-radius.id_prefix", "", 800: lib->ns), 801: ); 802: this->client = eap_radius_create_client(); 803: if (!this->client) 804: { 805: free(this); 806: return NULL; 807: } 808: this->peer = peer->clone(peer); 809: this->server = server->clone(server); 810: return &this->public; 811: }