Annotation of embedaddon/strongswan/src/libcharon/plugins/eap_radius/eap_radius.c, revision 1.1
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: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>