radius_server.c revision 1f69aa52ea2e0a73ac502565df8c666ee49cab6a
1/* 2 * RADIUS authentication server 3 * Copyright (c) 2005-2009, 2011, Jouni Malinen <j@w1.fi> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 * 9 * Alternatively, this software may be distributed under the terms of BSD 10 * license. 11 * 12 * See README and COPYING for more details. 13 */ 14 15#include "includes.h" 16#include <net/if.h> 17 18#include "common.h" 19#include "radius.h" 20#include "eloop.h" 21#include "eap_server/eap.h" 22#include "radius_server.h" 23 24/** 25 * RADIUS_SESSION_TIMEOUT - Session timeout in seconds 26 */ 27#define RADIUS_SESSION_TIMEOUT 60 28 29/** 30 * RADIUS_MAX_SESSION - Maximum number of active sessions 31 */ 32#define RADIUS_MAX_SESSION 100 33 34/** 35 * RADIUS_MAX_MSG_LEN - Maximum message length for incoming RADIUS messages 36 */ 37#define RADIUS_MAX_MSG_LEN 3000 38 39static struct eapol_callbacks radius_server_eapol_cb; 40 41struct radius_client; 42struct radius_server_data; 43 44/** 45 * struct radius_server_counters - RADIUS server statistics counters 46 */ 47struct radius_server_counters { 48 u32 access_requests; 49 u32 invalid_requests; 50 u32 dup_access_requests; 51 u32 access_accepts; 52 u32 access_rejects; 53 u32 access_challenges; 54 u32 malformed_access_requests; 55 u32 bad_authenticators; 56 u32 packets_dropped; 57 u32 unknown_types; 58}; 59 60/** 61 * struct radius_session - Internal RADIUS server data for a session 62 */ 63struct radius_session { 64 struct radius_session *next; 65 struct radius_client *client; 66 struct radius_server_data *server; 67 unsigned int sess_id; 68 struct eap_sm *eap; 69 struct eap_eapol_interface *eap_if; 70 71 struct radius_msg *last_msg; 72 char *last_from_addr; 73 int last_from_port; 74 struct sockaddr_storage last_from; 75 socklen_t last_fromlen; 76 u8 last_identifier; 77 struct radius_msg *last_reply; 78 u8 last_authenticator[16]; 79}; 80 81/** 82 * struct radius_client - Internal RADIUS server data for a client 83 */ 84struct radius_client { 85 struct radius_client *next; 86 struct in_addr addr; 87 struct in_addr mask; 88#ifdef CONFIG_IPV6 89 struct in6_addr addr6; 90 struct in6_addr mask6; 91#endif /* CONFIG_IPV6 */ 92 char *shared_secret; 93 int shared_secret_len; 94 struct radius_session *sessions; 95 struct radius_server_counters counters; 96}; 97 98/** 99 * struct radius_server_data - Internal RADIUS server data 100 */ 101struct radius_server_data { 102 /** 103 * auth_sock - Socket for RADIUS authentication messages 104 */ 105 int auth_sock; 106 107 /** 108 * clients - List of authorized RADIUS clients 109 */ 110 struct radius_client *clients; 111 112 /** 113 * next_sess_id - Next session identifier 114 */ 115 unsigned int next_sess_id; 116 117 /** 118 * conf_ctx - Context pointer for callbacks 119 * 120 * This is used as the ctx argument in get_eap_user() calls. 121 */ 122 void *conf_ctx; 123 124 /** 125 * num_sess - Number of active sessions 126 */ 127 int num_sess; 128 129 /** 130 * eap_sim_db_priv - EAP-SIM/AKA database context 131 * 132 * This is passed to the EAP-SIM/AKA server implementation as a 133 * callback context. 134 */ 135 void *eap_sim_db_priv; 136 137 /** 138 * ssl_ctx - TLS context 139 * 140 * This is passed to the EAP server implementation as a callback 141 * context for TLS operations. 142 */ 143 void *ssl_ctx; 144 145 /** 146 * pac_opaque_encr_key - PAC-Opaque encryption key for EAP-FAST 147 * 148 * This parameter is used to set a key for EAP-FAST to encrypt the 149 * PAC-Opaque data. It can be set to %NULL if EAP-FAST is not used. If 150 * set, must point to a 16-octet key. 151 */ 152 u8 *pac_opaque_encr_key; 153 154 /** 155 * eap_fast_a_id - EAP-FAST authority identity (A-ID) 156 * 157 * If EAP-FAST is not used, this can be set to %NULL. In theory, this 158 * is a variable length field, but due to some existing implementations 159 * requiring A-ID to be 16 octets in length, it is recommended to use 160 * that length for the field to provide interoperability with deployed 161 * peer implementations. 162 */ 163 u8 *eap_fast_a_id; 164 165 /** 166 * eap_fast_a_id_len - Length of eap_fast_a_id buffer in octets 167 */ 168 size_t eap_fast_a_id_len; 169 170 /** 171 * eap_fast_a_id_info - EAP-FAST authority identifier information 172 * 173 * This A-ID-Info contains a user-friendly name for the A-ID. For 174 * example, this could be the enterprise and server names in 175 * human-readable format. This field is encoded as UTF-8. If EAP-FAST 176 * is not used, this can be set to %NULL. 177 */ 178 char *eap_fast_a_id_info; 179 180 /** 181 * eap_fast_prov - EAP-FAST provisioning modes 182 * 183 * 0 = provisioning disabled, 1 = only anonymous provisioning allowed, 184 * 2 = only authenticated provisioning allowed, 3 = both provisioning 185 * modes allowed. 186 */ 187 int eap_fast_prov; 188 189 /** 190 * pac_key_lifetime - EAP-FAST PAC-Key lifetime in seconds 191 * 192 * This is the hard limit on how long a provisioned PAC-Key can be 193 * used. 194 */ 195 int pac_key_lifetime; 196 197 /** 198 * pac_key_refresh_time - EAP-FAST PAC-Key refresh time in seconds 199 * 200 * This is a soft limit on the PAC-Key. The server will automatically 201 * generate a new PAC-Key when this number of seconds (or fewer) of the 202 * lifetime remains. 203 */ 204 int pac_key_refresh_time; 205 206 /** 207 * eap_sim_aka_result_ind - EAP-SIM/AKA protected success indication 208 * 209 * This controls whether the protected success/failure indication 210 * (AT_RESULT_IND) is used with EAP-SIM and EAP-AKA. 211 */ 212 int eap_sim_aka_result_ind; 213 214 /** 215 * tnc - Trusted Network Connect (TNC) 216 * 217 * This controls whether TNC is enabled and will be required before the 218 * peer is allowed to connect. Note: This is only used with EAP-TTLS 219 * and EAP-FAST. If any other EAP method is enabled, the peer will be 220 * allowed to connect without TNC. 221 */ 222 int tnc; 223 224 /** 225 * pwd_group - The D-H group assigned for EAP-pwd 226 * 227 * If EAP-pwd is not used it can be set to zero. 228 */ 229 u16 pwd_group; 230 231 /** 232 * wps - Wi-Fi Protected Setup context 233 * 234 * If WPS is used with an external RADIUS server (which is quite 235 * unlikely configuration), this is used to provide a pointer to WPS 236 * context data. Normally, this can be set to %NULL. 237 */ 238 struct wps_context *wps; 239 240 /** 241 * ipv6 - Whether to enable IPv6 support in the RADIUS server 242 */ 243 int ipv6; 244 245 /** 246 * start_time - Timestamp of server start 247 */ 248 struct os_time start_time; 249 250 /** 251 * counters - Statistics counters for server operations 252 * 253 * These counters are the sum over all clients. 254 */ 255 struct radius_server_counters counters; 256 257 /** 258 * get_eap_user - Callback for fetching EAP user information 259 * @ctx: Context data from conf_ctx 260 * @identity: User identity 261 * @identity_len: identity buffer length in octets 262 * @phase2: Whether this is for Phase 2 identity 263 * @user: Data structure for filling in the user information 264 * Returns: 0 on success, -1 on failure 265 * 266 * This is used to fetch information from user database. The callback 267 * will fill in information about allowed EAP methods and the user 268 * password. The password field will be an allocated copy of the 269 * password data and RADIUS server will free it after use. 270 */ 271 int (*get_eap_user)(void *ctx, const u8 *identity, size_t identity_len, 272 int phase2, struct eap_user *user); 273 274 /** 275 * eap_req_id_text - Optional data for EAP-Request/Identity 276 * 277 * This can be used to configure an optional, displayable message that 278 * will be sent in EAP-Request/Identity. This string can contain an 279 * ASCII-0 character (nul) to separate network infromation per RFC 280 * 4284. The actual string length is explicit provided in 281 * eap_req_id_text_len since nul character will not be used as a string 282 * terminator. 283 */ 284 char *eap_req_id_text; 285 286 /** 287 * eap_req_id_text_len - Length of eap_req_id_text buffer in octets 288 */ 289 size_t eap_req_id_text_len; 290 291 /* 292 * msg_ctx - Context data for wpa_msg() calls 293 */ 294 void *msg_ctx; 295 296#ifdef CONFIG_RADIUS_TEST 297 char *dump_msk_file; 298#endif /* CONFIG_RADIUS_TEST */ 299}; 300 301 302extern int wpa_debug_level; 303 304#define RADIUS_DEBUG(args...) \ 305wpa_printf(MSG_DEBUG, "RADIUS SRV: " args) 306#define RADIUS_ERROR(args...) \ 307wpa_printf(MSG_ERROR, "RADIUS SRV: " args) 308#define RADIUS_DUMP(args...) \ 309wpa_hexdump(MSG_MSGDUMP, "RADIUS SRV: " args) 310#define RADIUS_DUMP_ASCII(args...) \ 311wpa_hexdump_ascii(MSG_MSGDUMP, "RADIUS SRV: " args) 312 313 314static void radius_server_session_timeout(void *eloop_ctx, void *timeout_ctx); 315static void radius_server_session_remove_timeout(void *eloop_ctx, 316 void *timeout_ctx); 317 318 319static struct radius_client * 320radius_server_get_client(struct radius_server_data *data, struct in_addr *addr, 321 int ipv6) 322{ 323 struct radius_client *client = data->clients; 324 325 while (client) { 326#ifdef CONFIG_IPV6 327 if (ipv6) { 328 struct in6_addr *addr6; 329 int i; 330 331 addr6 = (struct in6_addr *) addr; 332 for (i = 0; i < 16; i++) { 333 if ((addr6->s6_addr[i] & 334 client->mask6.s6_addr[i]) != 335 (client->addr6.s6_addr[i] & 336 client->mask6.s6_addr[i])) { 337 i = 17; 338 break; 339 } 340 } 341 if (i == 16) { 342 break; 343 } 344 } 345#endif /* CONFIG_IPV6 */ 346 if (!ipv6 && (client->addr.s_addr & client->mask.s_addr) == 347 (addr->s_addr & client->mask.s_addr)) { 348 break; 349 } 350 351 client = client->next; 352 } 353 354 return client; 355} 356 357 358static struct radius_session * 359radius_server_get_session(struct radius_client *client, unsigned int sess_id) 360{ 361 struct radius_session *sess = client->sessions; 362 363 while (sess) { 364 if (sess->sess_id == sess_id) { 365 break; 366 } 367 sess = sess->next; 368 } 369 370 return sess; 371} 372 373 374static void radius_server_session_free(struct radius_server_data *data, 375 struct radius_session *sess) 376{ 377 eloop_cancel_timeout(radius_server_session_timeout, data, sess); 378 eloop_cancel_timeout(radius_server_session_remove_timeout, data, sess); 379 eap_server_sm_deinit(sess->eap); 380 radius_msg_free(sess->last_msg); 381 os_free(sess->last_from_addr); 382 radius_msg_free(sess->last_reply); 383 os_free(sess); 384 data->num_sess--; 385} 386 387 388static void radius_server_session_remove(struct radius_server_data *data, 389 struct radius_session *sess) 390{ 391 struct radius_client *client = sess->client; 392 struct radius_session *session, *prev; 393 394 eloop_cancel_timeout(radius_server_session_remove_timeout, data, sess); 395 396 prev = NULL; 397 session = client->sessions; 398 while (session) { 399 if (session == sess) { 400 if (prev == NULL) { 401 client->sessions = sess->next; 402 } else { 403 prev->next = sess->next; 404 } 405 radius_server_session_free(data, sess); 406 break; 407 } 408 prev = session; 409 session = session->next; 410 } 411} 412 413 414static void radius_server_session_remove_timeout(void *eloop_ctx, 415 void *timeout_ctx) 416{ 417 struct radius_server_data *data = eloop_ctx; 418 struct radius_session *sess = timeout_ctx; 419 RADIUS_DEBUG("Removing completed session 0x%x", sess->sess_id); 420 radius_server_session_remove(data, sess); 421} 422 423 424static void radius_server_session_timeout(void *eloop_ctx, void *timeout_ctx) 425{ 426 struct radius_server_data *data = eloop_ctx; 427 struct radius_session *sess = timeout_ctx; 428 429 RADIUS_DEBUG("Timing out authentication session 0x%x", sess->sess_id); 430 radius_server_session_remove(data, sess); 431} 432 433 434static struct radius_session * 435radius_server_new_session(struct radius_server_data *data, 436 struct radius_client *client) 437{ 438 struct radius_session *sess; 439 440 if (data->num_sess >= RADIUS_MAX_SESSION) { 441 RADIUS_DEBUG("Maximum number of existing session - no room " 442 "for a new session"); 443 return NULL; 444 } 445 446 sess = os_zalloc(sizeof(*sess)); 447 if (sess == NULL) 448 return NULL; 449 450 sess->server = data; 451 sess->client = client; 452 sess->sess_id = data->next_sess_id++; 453 sess->next = client->sessions; 454 client->sessions = sess; 455 eloop_register_timeout(RADIUS_SESSION_TIMEOUT, 0, 456 radius_server_session_timeout, data, sess); 457 data->num_sess++; 458 return sess; 459} 460 461 462static struct radius_session * 463radius_server_get_new_session(struct radius_server_data *data, 464 struct radius_client *client, 465 struct radius_msg *msg) 466{ 467 u8 *user; 468 size_t user_len; 469 int res; 470 struct radius_session *sess; 471 struct eap_config eap_conf; 472 473 RADIUS_DEBUG("Creating a new session"); 474 475 user = os_malloc(256); 476 if (user == NULL) { 477 return NULL; 478 } 479 res = radius_msg_get_attr(msg, RADIUS_ATTR_USER_NAME, user, 256); 480 if (res < 0 || res > 256) { 481 RADIUS_DEBUG("Could not get User-Name"); 482 os_free(user); 483 return NULL; 484 } 485 user_len = res; 486 RADIUS_DUMP_ASCII("User-Name", user, user_len); 487 488 res = data->get_eap_user(data->conf_ctx, user, user_len, 0, NULL); 489 os_free(user); 490 491 if (res == 0) { 492 RADIUS_DEBUG("Matching user entry found"); 493 sess = radius_server_new_session(data, client); 494 if (sess == NULL) { 495 RADIUS_DEBUG("Failed to create a new session"); 496 return NULL; 497 } 498 } else { 499 RADIUS_DEBUG("User-Name not found from user database"); 500 return NULL; 501 } 502 503 os_memset(&eap_conf, 0, sizeof(eap_conf)); 504 eap_conf.ssl_ctx = data->ssl_ctx; 505 eap_conf.msg_ctx = data->msg_ctx; 506 eap_conf.eap_sim_db_priv = data->eap_sim_db_priv; 507 eap_conf.backend_auth = TRUE; 508 eap_conf.eap_server = 1; 509 eap_conf.pac_opaque_encr_key = data->pac_opaque_encr_key; 510 eap_conf.eap_fast_a_id = data->eap_fast_a_id; 511 eap_conf.eap_fast_a_id_len = data->eap_fast_a_id_len; 512 eap_conf.eap_fast_a_id_info = data->eap_fast_a_id_info; 513 eap_conf.eap_fast_prov = data->eap_fast_prov; 514 eap_conf.pac_key_lifetime = data->pac_key_lifetime; 515 eap_conf.pac_key_refresh_time = data->pac_key_refresh_time; 516 eap_conf.eap_sim_aka_result_ind = data->eap_sim_aka_result_ind; 517 eap_conf.tnc = data->tnc; 518 eap_conf.wps = data->wps; 519 eap_conf.pwd_group = data->pwd_group; 520 sess->eap = eap_server_sm_init(sess, &radius_server_eapol_cb, 521 &eap_conf); 522 if (sess->eap == NULL) { 523 RADIUS_DEBUG("Failed to initialize EAP state machine for the " 524 "new session"); 525 radius_server_session_free(data, sess); 526 return NULL; 527 } 528 sess->eap_if = eap_get_interface(sess->eap); 529 sess->eap_if->eapRestart = TRUE; 530 sess->eap_if->portEnabled = TRUE; 531 532 RADIUS_DEBUG("New session 0x%x initialized", sess->sess_id); 533 534 return sess; 535} 536 537 538static struct radius_msg * 539radius_server_encapsulate_eap(struct radius_server_data *data, 540 struct radius_client *client, 541 struct radius_session *sess, 542 struct radius_msg *request) 543{ 544 struct radius_msg *msg; 545 int code; 546 unsigned int sess_id; 547 struct radius_hdr *hdr = radius_msg_get_hdr(request); 548 549 if (sess->eap_if->eapFail) { 550 sess->eap_if->eapFail = FALSE; 551 code = RADIUS_CODE_ACCESS_REJECT; 552 } else if (sess->eap_if->eapSuccess) { 553 sess->eap_if->eapSuccess = FALSE; 554 code = RADIUS_CODE_ACCESS_ACCEPT; 555 } else { 556 sess->eap_if->eapReq = FALSE; 557 code = RADIUS_CODE_ACCESS_CHALLENGE; 558 } 559 560 msg = radius_msg_new(code, hdr->identifier); 561 if (msg == NULL) { 562 RADIUS_DEBUG("Failed to allocate reply message"); 563 return NULL; 564 } 565 566 sess_id = htonl(sess->sess_id); 567 if (code == RADIUS_CODE_ACCESS_CHALLENGE && 568 !radius_msg_add_attr(msg, RADIUS_ATTR_STATE, 569 (u8 *) &sess_id, sizeof(sess_id))) { 570 RADIUS_DEBUG("Failed to add State attribute"); 571 } 572 573 if (sess->eap_if->eapReqData && 574 !radius_msg_add_eap(msg, wpabuf_head(sess->eap_if->eapReqData), 575 wpabuf_len(sess->eap_if->eapReqData))) { 576 RADIUS_DEBUG("Failed to add EAP-Message attribute"); 577 } 578 579 if (code == RADIUS_CODE_ACCESS_ACCEPT && sess->eap_if->eapKeyData) { 580 int len; 581#ifdef CONFIG_RADIUS_TEST 582 if (data->dump_msk_file) { 583 FILE *f; 584 char buf[2 * 64 + 1]; 585 f = fopen(data->dump_msk_file, "a"); 586 if (f) { 587 len = sess->eap_if->eapKeyDataLen; 588 if (len > 64) 589 len = 64; 590 len = wpa_snprintf_hex( 591 buf, sizeof(buf), 592 sess->eap_if->eapKeyData, len); 593 buf[len] = '\0'; 594 fprintf(f, "%s\n", buf); 595 fclose(f); 596 } 597 } 598#endif /* CONFIG_RADIUS_TEST */ 599 if (sess->eap_if->eapKeyDataLen > 64) { 600 len = 32; 601 } else { 602 len = sess->eap_if->eapKeyDataLen / 2; 603 } 604 if (!radius_msg_add_mppe_keys(msg, hdr->authenticator, 605 (u8 *) client->shared_secret, 606 client->shared_secret_len, 607 sess->eap_if->eapKeyData + len, 608 len, sess->eap_if->eapKeyData, 609 len)) { 610 RADIUS_DEBUG("Failed to add MPPE key attributes"); 611 } 612 } 613 614 if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) { 615 RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)"); 616 radius_msg_free(msg); 617 return NULL; 618 } 619 620 if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret, 621 client->shared_secret_len, 622 hdr->authenticator) < 0) { 623 RADIUS_DEBUG("Failed to add Message-Authenticator attribute"); 624 } 625 626 return msg; 627} 628 629 630static int radius_server_reject(struct radius_server_data *data, 631 struct radius_client *client, 632 struct radius_msg *request, 633 struct sockaddr *from, socklen_t fromlen, 634 const char *from_addr, int from_port) 635{ 636 struct radius_msg *msg; 637 int ret = 0; 638 struct eap_hdr eapfail; 639 struct wpabuf *buf; 640 struct radius_hdr *hdr = radius_msg_get_hdr(request); 641 642 RADIUS_DEBUG("Reject invalid request from %s:%d", 643 from_addr, from_port); 644 645 msg = radius_msg_new(RADIUS_CODE_ACCESS_REJECT, hdr->identifier); 646 if (msg == NULL) { 647 return -1; 648 } 649 650 os_memset(&eapfail, 0, sizeof(eapfail)); 651 eapfail.code = EAP_CODE_FAILURE; 652 eapfail.identifier = 0; 653 eapfail.length = host_to_be16(sizeof(eapfail)); 654 655 if (!radius_msg_add_eap(msg, (u8 *) &eapfail, sizeof(eapfail))) { 656 RADIUS_DEBUG("Failed to add EAP-Message attribute"); 657 } 658 659 if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) { 660 RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)"); 661 radius_msg_free(msg); 662 return -1; 663 } 664 665 if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret, 666 client->shared_secret_len, 667 hdr->authenticator) < 668 0) { 669 RADIUS_DEBUG("Failed to add Message-Authenticator attribute"); 670 } 671 672 if (wpa_debug_level <= MSG_MSGDUMP) { 673 radius_msg_dump(msg); 674 } 675 676 data->counters.access_rejects++; 677 client->counters.access_rejects++; 678 buf = radius_msg_get_buf(msg); 679 if (sendto(data->auth_sock, wpabuf_head(buf), wpabuf_len(buf), 0, 680 (struct sockaddr *) from, sizeof(*from)) < 0) { 681 perror("sendto[RADIUS SRV]"); 682 ret = -1; 683 } 684 685 radius_msg_free(msg); 686 687 return ret; 688} 689 690 691static int radius_server_request(struct radius_server_data *data, 692 struct radius_msg *msg, 693 struct sockaddr *from, socklen_t fromlen, 694 struct radius_client *client, 695 const char *from_addr, int from_port, 696 struct radius_session *force_sess) 697{ 698 u8 *eap = NULL; 699 size_t eap_len; 700 int res, state_included = 0; 701 u8 statebuf[4]; 702 unsigned int state; 703 struct radius_session *sess; 704 struct radius_msg *reply; 705 int is_complete = 0; 706 707 if (force_sess) 708 sess = force_sess; 709 else { 710 res = radius_msg_get_attr(msg, RADIUS_ATTR_STATE, statebuf, 711 sizeof(statebuf)); 712 state_included = res >= 0; 713 if (res == sizeof(statebuf)) { 714 state = WPA_GET_BE32(statebuf); 715 sess = radius_server_get_session(client, state); 716 } else { 717 sess = NULL; 718 } 719 } 720 721 if (sess) { 722 RADIUS_DEBUG("Request for session 0x%x", sess->sess_id); 723 } else if (state_included) { 724 RADIUS_DEBUG("State attribute included but no session found"); 725 radius_server_reject(data, client, msg, from, fromlen, 726 from_addr, from_port); 727 return -1; 728 } else { 729 sess = radius_server_get_new_session(data, client, msg); 730 if (sess == NULL) { 731 RADIUS_DEBUG("Could not create a new session"); 732 radius_server_reject(data, client, msg, from, fromlen, 733 from_addr, from_port); 734 return -1; 735 } 736 } 737 738 if (sess->last_from_port == from_port && 739 sess->last_identifier == radius_msg_get_hdr(msg)->identifier && 740 os_memcmp(sess->last_authenticator, 741 radius_msg_get_hdr(msg)->authenticator, 16) == 0) { 742 RADIUS_DEBUG("Duplicate message from %s", from_addr); 743 data->counters.dup_access_requests++; 744 client->counters.dup_access_requests++; 745 746 if (sess->last_reply) { 747 struct wpabuf *buf; 748 buf = radius_msg_get_buf(sess->last_reply); 749 res = sendto(data->auth_sock, wpabuf_head(buf), 750 wpabuf_len(buf), 0, 751 (struct sockaddr *) from, fromlen); 752 if (res < 0) { 753 perror("sendto[RADIUS SRV]"); 754 } 755 return 0; 756 } 757 758 RADIUS_DEBUG("No previous reply available for duplicate " 759 "message"); 760 return -1; 761 } 762 763 eap = radius_msg_get_eap(msg, &eap_len); 764 if (eap == NULL) { 765 RADIUS_DEBUG("No EAP-Message in RADIUS packet from %s", 766 from_addr); 767 data->counters.packets_dropped++; 768 client->counters.packets_dropped++; 769 return -1; 770 } 771 772 RADIUS_DUMP("Received EAP data", eap, eap_len); 773 774 /* FIX: if Code is Request, Success, or Failure, send Access-Reject; 775 * RFC3579 Sect. 2.6.2. 776 * Include EAP-Response/Nak with no preferred method if 777 * code == request. 778 * If code is not 1-4, discard the packet silently. 779 * Or is this already done by the EAP state machine? */ 780 781 wpabuf_free(sess->eap_if->eapRespData); 782 sess->eap_if->eapRespData = wpabuf_alloc_ext_data(eap, eap_len); 783 if (sess->eap_if->eapRespData == NULL) 784 os_free(eap); 785 eap = NULL; 786 sess->eap_if->eapResp = TRUE; 787 eap_server_sm_step(sess->eap); 788 789 if ((sess->eap_if->eapReq || sess->eap_if->eapSuccess || 790 sess->eap_if->eapFail) && sess->eap_if->eapReqData) { 791 RADIUS_DUMP("EAP data from the state machine", 792 wpabuf_head(sess->eap_if->eapReqData), 793 wpabuf_len(sess->eap_if->eapReqData)); 794 } else if (sess->eap_if->eapFail) { 795 RADIUS_DEBUG("No EAP data from the state machine, but eapFail " 796 "set"); 797 } else if (eap_sm_method_pending(sess->eap)) { 798 radius_msg_free(sess->last_msg); 799 sess->last_msg = msg; 800 sess->last_from_port = from_port; 801 os_free(sess->last_from_addr); 802 sess->last_from_addr = os_strdup(from_addr); 803 sess->last_fromlen = fromlen; 804 os_memcpy(&sess->last_from, from, fromlen); 805 return -2; 806 } else { 807 RADIUS_DEBUG("No EAP data from the state machine - ignore this" 808 " Access-Request silently (assuming it was a " 809 "duplicate)"); 810 data->counters.packets_dropped++; 811 client->counters.packets_dropped++; 812 return -1; 813 } 814 815 if (sess->eap_if->eapSuccess || sess->eap_if->eapFail) 816 is_complete = 1; 817 818 reply = radius_server_encapsulate_eap(data, client, sess, msg); 819 820 if (reply) { 821 struct wpabuf *buf; 822 struct radius_hdr *hdr; 823 824 RADIUS_DEBUG("Reply to %s:%d", from_addr, from_port); 825 if (wpa_debug_level <= MSG_MSGDUMP) { 826 radius_msg_dump(reply); 827 } 828 829 switch (radius_msg_get_hdr(reply)->code) { 830 case RADIUS_CODE_ACCESS_ACCEPT: 831 data->counters.access_accepts++; 832 client->counters.access_accepts++; 833 break; 834 case RADIUS_CODE_ACCESS_REJECT: 835 data->counters.access_rejects++; 836 client->counters.access_rejects++; 837 break; 838 case RADIUS_CODE_ACCESS_CHALLENGE: 839 data->counters.access_challenges++; 840 client->counters.access_challenges++; 841 break; 842 } 843 buf = radius_msg_get_buf(reply); 844 res = sendto(data->auth_sock, wpabuf_head(buf), 845 wpabuf_len(buf), 0, 846 (struct sockaddr *) from, fromlen); 847 if (res < 0) { 848 perror("sendto[RADIUS SRV]"); 849 } 850 radius_msg_free(sess->last_reply); 851 sess->last_reply = reply; 852 sess->last_from_port = from_port; 853 hdr = radius_msg_get_hdr(msg); 854 sess->last_identifier = hdr->identifier; 855 os_memcpy(sess->last_authenticator, hdr->authenticator, 16); 856 } else { 857 data->counters.packets_dropped++; 858 client->counters.packets_dropped++; 859 } 860 861 if (is_complete) { 862 RADIUS_DEBUG("Removing completed session 0x%x after timeout", 863 sess->sess_id); 864 eloop_cancel_timeout(radius_server_session_remove_timeout, 865 data, sess); 866 eloop_register_timeout(10, 0, 867 radius_server_session_remove_timeout, 868 data, sess); 869 } 870 871 return 0; 872} 873 874 875static void radius_server_receive_auth(int sock, void *eloop_ctx, 876 void *sock_ctx) 877{ 878 struct radius_server_data *data = eloop_ctx; 879 u8 *buf = NULL; 880 union { 881 struct sockaddr_storage ss; 882 struct sockaddr_in sin; 883#ifdef CONFIG_IPV6 884 struct sockaddr_in6 sin6; 885#endif /* CONFIG_IPV6 */ 886 } from; 887 socklen_t fromlen; 888 int len; 889 struct radius_client *client = NULL; 890 struct radius_msg *msg = NULL; 891 char abuf[50]; 892 int from_port = 0; 893 894 buf = os_malloc(RADIUS_MAX_MSG_LEN); 895 if (buf == NULL) { 896 goto fail; 897 } 898 899 fromlen = sizeof(from); 900 len = recvfrom(sock, buf, RADIUS_MAX_MSG_LEN, 0, 901 (struct sockaddr *) &from.ss, &fromlen); 902 if (len < 0) { 903 perror("recvfrom[radius_server]"); 904 goto fail; 905 } 906 907#ifdef CONFIG_IPV6 908 if (data->ipv6) { 909 if (inet_ntop(AF_INET6, &from.sin6.sin6_addr, abuf, 910 sizeof(abuf)) == NULL) 911 abuf[0] = '\0'; 912 from_port = ntohs(from.sin6.sin6_port); 913 RADIUS_DEBUG("Received %d bytes from %s:%d", 914 len, abuf, from_port); 915 916 client = radius_server_get_client(data, 917 (struct in_addr *) 918 &from.sin6.sin6_addr, 1); 919 } 920#endif /* CONFIG_IPV6 */ 921 922 if (!data->ipv6) { 923 os_strlcpy(abuf, inet_ntoa(from.sin.sin_addr), sizeof(abuf)); 924 from_port = ntohs(from.sin.sin_port); 925 RADIUS_DEBUG("Received %d bytes from %s:%d", 926 len, abuf, from_port); 927 928 client = radius_server_get_client(data, &from.sin.sin_addr, 0); 929 } 930 931 RADIUS_DUMP("Received data", buf, len); 932 933 if (client == NULL) { 934 RADIUS_DEBUG("Unknown client %s - packet ignored", abuf); 935 data->counters.invalid_requests++; 936 goto fail; 937 } 938 939 msg = radius_msg_parse(buf, len); 940 if (msg == NULL) { 941 RADIUS_DEBUG("Parsing incoming RADIUS frame failed"); 942 data->counters.malformed_access_requests++; 943 client->counters.malformed_access_requests++; 944 goto fail; 945 } 946 947 os_free(buf); 948 buf = NULL; 949 950 if (wpa_debug_level <= MSG_MSGDUMP) { 951 radius_msg_dump(msg); 952 } 953 954 if (radius_msg_get_hdr(msg)->code != RADIUS_CODE_ACCESS_REQUEST) { 955 RADIUS_DEBUG("Unexpected RADIUS code %d", 956 radius_msg_get_hdr(msg)->code); 957 data->counters.unknown_types++; 958 client->counters.unknown_types++; 959 goto fail; 960 } 961 962 data->counters.access_requests++; 963 client->counters.access_requests++; 964 965 if (radius_msg_verify_msg_auth(msg, (u8 *) client->shared_secret, 966 client->shared_secret_len, NULL)) { 967 RADIUS_DEBUG("Invalid Message-Authenticator from %s", abuf); 968 data->counters.bad_authenticators++; 969 client->counters.bad_authenticators++; 970 goto fail; 971 } 972 973 if (radius_server_request(data, msg, (struct sockaddr *) &from, 974 fromlen, client, abuf, from_port, NULL) == 975 -2) 976 return; /* msg was stored with the session */ 977 978fail: 979 radius_msg_free(msg); 980 os_free(buf); 981} 982 983 984static int radius_server_disable_pmtu_discovery(int s) 985{ 986 int r = -1; 987#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) 988 /* Turn off Path MTU discovery on IPv4/UDP sockets. */ 989 int action = IP_PMTUDISC_DONT; 990 r = setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, &action, 991 sizeof(action)); 992 if (r == -1) 993 wpa_printf(MSG_ERROR, "Failed to set IP_MTU_DISCOVER: " 994 "%s", strerror(errno)); 995#endif 996 return r; 997} 998 999 1000static int radius_server_open_socket(int port) 1001{ 1002 int s; 1003 struct sockaddr_in addr; 1004 1005 s = socket(PF_INET, SOCK_DGRAM, 0); 1006 if (s < 0) { 1007 perror("socket"); 1008 return -1; 1009 } 1010 1011 radius_server_disable_pmtu_discovery(s); 1012 1013 os_memset(&addr, 0, sizeof(addr)); 1014 addr.sin_family = AF_INET; 1015 addr.sin_port = htons(port); 1016 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 1017 perror("bind"); 1018 close(s); 1019 return -1; 1020 } 1021 1022 return s; 1023} 1024 1025 1026#ifdef CONFIG_IPV6 1027static int radius_server_open_socket6(int port) 1028{ 1029 int s; 1030 struct sockaddr_in6 addr; 1031 1032 s = socket(PF_INET6, SOCK_DGRAM, 0); 1033 if (s < 0) { 1034 perror("socket[IPv6]"); 1035 return -1; 1036 } 1037 1038 os_memset(&addr, 0, sizeof(addr)); 1039 addr.sin6_family = AF_INET6; 1040 os_memcpy(&addr.sin6_addr, &in6addr_any, sizeof(in6addr_any)); 1041 addr.sin6_port = htons(port); 1042 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 1043 perror("bind"); 1044 close(s); 1045 return -1; 1046 } 1047 1048 return s; 1049} 1050#endif /* CONFIG_IPV6 */ 1051 1052 1053static void radius_server_free_sessions(struct radius_server_data *data, 1054 struct radius_session *sessions) 1055{ 1056 struct radius_session *session, *prev; 1057 1058 session = sessions; 1059 while (session) { 1060 prev = session; 1061 session = session->next; 1062 radius_server_session_free(data, prev); 1063 } 1064} 1065 1066 1067static void radius_server_free_clients(struct radius_server_data *data, 1068 struct radius_client *clients) 1069{ 1070 struct radius_client *client, *prev; 1071 1072 client = clients; 1073 while (client) { 1074 prev = client; 1075 client = client->next; 1076 1077 radius_server_free_sessions(data, prev->sessions); 1078 os_free(prev->shared_secret); 1079 os_free(prev); 1080 } 1081} 1082 1083 1084static struct radius_client * 1085radius_server_read_clients(const char *client_file, int ipv6) 1086{ 1087 FILE *f; 1088 const int buf_size = 1024; 1089 char *buf, *pos; 1090 struct radius_client *clients, *tail, *entry; 1091 int line = 0, mask, failed = 0, i; 1092 struct in_addr addr; 1093#ifdef CONFIG_IPV6 1094 struct in6_addr addr6; 1095#endif /* CONFIG_IPV6 */ 1096 unsigned int val; 1097 1098 f = fopen(client_file, "r"); 1099 if (f == NULL) { 1100 RADIUS_ERROR("Could not open client file '%s'", client_file); 1101 return NULL; 1102 } 1103 1104 buf = os_malloc(buf_size); 1105 if (buf == NULL) { 1106 fclose(f); 1107 return NULL; 1108 } 1109 1110 clients = tail = NULL; 1111 while (fgets(buf, buf_size, f)) { 1112 /* Configuration file format: 1113 * 192.168.1.0/24 secret 1114 * 192.168.1.2 secret 1115 * fe80::211:22ff:fe33:4455/64 secretipv6 1116 */ 1117 line++; 1118 buf[buf_size - 1] = '\0'; 1119 pos = buf; 1120 while (*pos != '\0' && *pos != '\n') 1121 pos++; 1122 if (*pos == '\n') 1123 *pos = '\0'; 1124 if (*buf == '\0' || *buf == '#') 1125 continue; 1126 1127 pos = buf; 1128 while ((*pos >= '0' && *pos <= '9') || *pos == '.' || 1129 (*pos >= 'a' && *pos <= 'f') || *pos == ':' || 1130 (*pos >= 'A' && *pos <= 'F')) { 1131 pos++; 1132 } 1133 1134 if (*pos == '\0') { 1135 failed = 1; 1136 break; 1137 } 1138 1139 if (*pos == '/') { 1140 char *end; 1141 *pos++ = '\0'; 1142 mask = strtol(pos, &end, 10); 1143 if ((pos == end) || 1144 (mask < 0 || mask > (ipv6 ? 128 : 32))) { 1145 failed = 1; 1146 break; 1147 } 1148 pos = end; 1149 } else { 1150 mask = ipv6 ? 128 : 32; 1151 *pos++ = '\0'; 1152 } 1153 1154 if (!ipv6 && inet_aton(buf, &addr) == 0) { 1155 failed = 1; 1156 break; 1157 } 1158#ifdef CONFIG_IPV6 1159 if (ipv6 && inet_pton(AF_INET6, buf, &addr6) <= 0) { 1160 if (inet_pton(AF_INET, buf, &addr) <= 0) { 1161 failed = 1; 1162 break; 1163 } 1164 /* Convert IPv4 address to IPv6 */ 1165 if (mask <= 32) 1166 mask += (128 - 32); 1167 os_memset(addr6.s6_addr, 0, 10); 1168 addr6.s6_addr[10] = 0xff; 1169 addr6.s6_addr[11] = 0xff; 1170 os_memcpy(addr6.s6_addr + 12, (char *) &addr.s_addr, 1171 4); 1172 } 1173#endif /* CONFIG_IPV6 */ 1174 1175 while (*pos == ' ' || *pos == '\t') { 1176 pos++; 1177 } 1178 1179 if (*pos == '\0') { 1180 failed = 1; 1181 break; 1182 } 1183 1184 entry = os_zalloc(sizeof(*entry)); 1185 if (entry == NULL) { 1186 failed = 1; 1187 break; 1188 } 1189 entry->shared_secret = os_strdup(pos); 1190 if (entry->shared_secret == NULL) { 1191 failed = 1; 1192 os_free(entry); 1193 break; 1194 } 1195 entry->shared_secret_len = os_strlen(entry->shared_secret); 1196 entry->addr.s_addr = addr.s_addr; 1197 if (!ipv6) { 1198 val = 0; 1199 for (i = 0; i < mask; i++) 1200 val |= 1 << (31 - i); 1201 entry->mask.s_addr = htonl(val); 1202 } 1203#ifdef CONFIG_IPV6 1204 if (ipv6) { 1205 int offset = mask / 8; 1206 1207 os_memcpy(entry->addr6.s6_addr, addr6.s6_addr, 16); 1208 os_memset(entry->mask6.s6_addr, 0xff, offset); 1209 val = 0; 1210 for (i = 0; i < (mask % 8); i++) 1211 val |= 1 << (7 - i); 1212 if (offset < 16) 1213 entry->mask6.s6_addr[offset] = val; 1214 } 1215#endif /* CONFIG_IPV6 */ 1216 1217 if (tail == NULL) { 1218 clients = tail = entry; 1219 } else { 1220 tail->next = entry; 1221 tail = entry; 1222 } 1223 } 1224 1225 if (failed) { 1226 RADIUS_ERROR("Invalid line %d in '%s'", line, client_file); 1227 radius_server_free_clients(NULL, clients); 1228 clients = NULL; 1229 } 1230 1231 os_free(buf); 1232 fclose(f); 1233 1234 return clients; 1235} 1236 1237 1238/** 1239 * radius_server_init - Initialize RADIUS server 1240 * @conf: Configuration for the RADIUS server 1241 * Returns: Pointer to private RADIUS server context or %NULL on failure 1242 * 1243 * This initializes a RADIUS server instance and returns a context pointer that 1244 * will be used in other calls to the RADIUS server module. The server can be 1245 * deinitialize by calling radius_server_deinit(). 1246 */ 1247struct radius_server_data * 1248radius_server_init(struct radius_server_conf *conf) 1249{ 1250 struct radius_server_data *data; 1251 1252#ifndef CONFIG_IPV6 1253 if (conf->ipv6) { 1254 fprintf(stderr, "RADIUS server compiled without IPv6 " 1255 "support.\n"); 1256 return NULL; 1257 } 1258#endif /* CONFIG_IPV6 */ 1259 1260 data = os_zalloc(sizeof(*data)); 1261 if (data == NULL) 1262 return NULL; 1263 1264 os_get_time(&data->start_time); 1265 data->conf_ctx = conf->conf_ctx; 1266 data->eap_sim_db_priv = conf->eap_sim_db_priv; 1267 data->ssl_ctx = conf->ssl_ctx; 1268 data->msg_ctx = conf->msg_ctx; 1269 data->ipv6 = conf->ipv6; 1270 if (conf->pac_opaque_encr_key) { 1271 data->pac_opaque_encr_key = os_malloc(16); 1272 os_memcpy(data->pac_opaque_encr_key, conf->pac_opaque_encr_key, 1273 16); 1274 } 1275 if (conf->eap_fast_a_id) { 1276 data->eap_fast_a_id = os_malloc(conf->eap_fast_a_id_len); 1277 if (data->eap_fast_a_id) { 1278 os_memcpy(data->eap_fast_a_id, conf->eap_fast_a_id, 1279 conf->eap_fast_a_id_len); 1280 data->eap_fast_a_id_len = conf->eap_fast_a_id_len; 1281 } 1282 } 1283 if (conf->eap_fast_a_id_info) 1284 data->eap_fast_a_id_info = os_strdup(conf->eap_fast_a_id_info); 1285 data->eap_fast_prov = conf->eap_fast_prov; 1286 data->pac_key_lifetime = conf->pac_key_lifetime; 1287 data->pac_key_refresh_time = conf->pac_key_refresh_time; 1288 data->get_eap_user = conf->get_eap_user; 1289 data->eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind; 1290 data->tnc = conf->tnc; 1291 data->wps = conf->wps; 1292 data->pwd_group = conf->pwd_group; 1293 if (conf->eap_req_id_text) { 1294 data->eap_req_id_text = os_malloc(conf->eap_req_id_text_len); 1295 if (data->eap_req_id_text) { 1296 os_memcpy(data->eap_req_id_text, conf->eap_req_id_text, 1297 conf->eap_req_id_text_len); 1298 data->eap_req_id_text_len = conf->eap_req_id_text_len; 1299 } 1300 } 1301 1302#ifdef CONFIG_RADIUS_TEST 1303 if (conf->dump_msk_file) 1304 data->dump_msk_file = os_strdup(conf->dump_msk_file); 1305#endif /* CONFIG_RADIUS_TEST */ 1306 1307 data->clients = radius_server_read_clients(conf->client_file, 1308 conf->ipv6); 1309 if (data->clients == NULL) { 1310 printf("No RADIUS clients configured.\n"); 1311 radius_server_deinit(data); 1312 return NULL; 1313 } 1314 1315#ifdef CONFIG_IPV6 1316 if (conf->ipv6) 1317 data->auth_sock = radius_server_open_socket6(conf->auth_port); 1318 else 1319#endif /* CONFIG_IPV6 */ 1320 data->auth_sock = radius_server_open_socket(conf->auth_port); 1321 if (data->auth_sock < 0) { 1322 printf("Failed to open UDP socket for RADIUS authentication " 1323 "server\n"); 1324 radius_server_deinit(data); 1325 return NULL; 1326 } 1327 if (eloop_register_read_sock(data->auth_sock, 1328 radius_server_receive_auth, 1329 data, NULL)) { 1330 radius_server_deinit(data); 1331 return NULL; 1332 } 1333 1334 return data; 1335} 1336 1337 1338/** 1339 * radius_server_deinit - Deinitialize RADIUS server 1340 * @data: RADIUS server context from radius_server_init() 1341 */ 1342void radius_server_deinit(struct radius_server_data *data) 1343{ 1344 if (data == NULL) 1345 return; 1346 1347 if (data->auth_sock >= 0) { 1348 eloop_unregister_read_sock(data->auth_sock); 1349 close(data->auth_sock); 1350 } 1351 1352 radius_server_free_clients(data, data->clients); 1353 1354 os_free(data->pac_opaque_encr_key); 1355 os_free(data->eap_fast_a_id); 1356 os_free(data->eap_fast_a_id_info); 1357 os_free(data->eap_req_id_text); 1358#ifdef CONFIG_RADIUS_TEST 1359 os_free(data->dump_msk_file); 1360#endif /* CONFIG_RADIUS_TEST */ 1361 os_free(data); 1362} 1363 1364 1365/** 1366 * radius_server_get_mib - Get RADIUS server MIB information 1367 * @data: RADIUS server context from radius_server_init() 1368 * @buf: Buffer for returning the MIB data in text format 1369 * @buflen: buf length in octets 1370 * Returns: Number of octets written into buf 1371 */ 1372int radius_server_get_mib(struct radius_server_data *data, char *buf, 1373 size_t buflen) 1374{ 1375 int ret, uptime; 1376 unsigned int idx; 1377 char *end, *pos; 1378 struct os_time now; 1379 struct radius_client *cli; 1380 1381 /* RFC 2619 - RADIUS Authentication Server MIB */ 1382 1383 if (data == NULL || buflen == 0) 1384 return 0; 1385 1386 pos = buf; 1387 end = buf + buflen; 1388 1389 os_get_time(&now); 1390 uptime = (now.sec - data->start_time.sec) * 100 + 1391 ((now.usec - data->start_time.usec) / 10000) % 100; 1392 ret = os_snprintf(pos, end - pos, 1393 "RADIUS-AUTH-SERVER-MIB\n" 1394 "radiusAuthServIdent=hostapd\n" 1395 "radiusAuthServUpTime=%d\n" 1396 "radiusAuthServResetTime=0\n" 1397 "radiusAuthServConfigReset=4\n", 1398 uptime); 1399 if (ret < 0 || ret >= end - pos) { 1400 *pos = '\0'; 1401 return pos - buf; 1402 } 1403 pos += ret; 1404 1405 ret = os_snprintf(pos, end - pos, 1406 "radiusAuthServTotalAccessRequests=%u\n" 1407 "radiusAuthServTotalInvalidRequests=%u\n" 1408 "radiusAuthServTotalDupAccessRequests=%u\n" 1409 "radiusAuthServTotalAccessAccepts=%u\n" 1410 "radiusAuthServTotalAccessRejects=%u\n" 1411 "radiusAuthServTotalAccessChallenges=%u\n" 1412 "radiusAuthServTotalMalformedAccessRequests=%u\n" 1413 "radiusAuthServTotalBadAuthenticators=%u\n" 1414 "radiusAuthServTotalPacketsDropped=%u\n" 1415 "radiusAuthServTotalUnknownTypes=%u\n", 1416 data->counters.access_requests, 1417 data->counters.invalid_requests, 1418 data->counters.dup_access_requests, 1419 data->counters.access_accepts, 1420 data->counters.access_rejects, 1421 data->counters.access_challenges, 1422 data->counters.malformed_access_requests, 1423 data->counters.bad_authenticators, 1424 data->counters.packets_dropped, 1425 data->counters.unknown_types); 1426 if (ret < 0 || ret >= end - pos) { 1427 *pos = '\0'; 1428 return pos - buf; 1429 } 1430 pos += ret; 1431 1432 for (cli = data->clients, idx = 0; cli; cli = cli->next, idx++) { 1433 char abuf[50], mbuf[50]; 1434#ifdef CONFIG_IPV6 1435 if (data->ipv6) { 1436 if (inet_ntop(AF_INET6, &cli->addr6, abuf, 1437 sizeof(abuf)) == NULL) 1438 abuf[0] = '\0'; 1439 if (inet_ntop(AF_INET6, &cli->mask6, abuf, 1440 sizeof(mbuf)) == NULL) 1441 mbuf[0] = '\0'; 1442 } 1443#endif /* CONFIG_IPV6 */ 1444 if (!data->ipv6) { 1445 os_strlcpy(abuf, inet_ntoa(cli->addr), sizeof(abuf)); 1446 os_strlcpy(mbuf, inet_ntoa(cli->mask), sizeof(mbuf)); 1447 } 1448 1449 ret = os_snprintf(pos, end - pos, 1450 "radiusAuthClientIndex=%u\n" 1451 "radiusAuthClientAddress=%s/%s\n" 1452 "radiusAuthServAccessRequests=%u\n" 1453 "radiusAuthServDupAccessRequests=%u\n" 1454 "radiusAuthServAccessAccepts=%u\n" 1455 "radiusAuthServAccessRejects=%u\n" 1456 "radiusAuthServAccessChallenges=%u\n" 1457 "radiusAuthServMalformedAccessRequests=%u\n" 1458 "radiusAuthServBadAuthenticators=%u\n" 1459 "radiusAuthServPacketsDropped=%u\n" 1460 "radiusAuthServUnknownTypes=%u\n", 1461 idx, 1462 abuf, mbuf, 1463 cli->counters.access_requests, 1464 cli->counters.dup_access_requests, 1465 cli->counters.access_accepts, 1466 cli->counters.access_rejects, 1467 cli->counters.access_challenges, 1468 cli->counters.malformed_access_requests, 1469 cli->counters.bad_authenticators, 1470 cli->counters.packets_dropped, 1471 cli->counters.unknown_types); 1472 if (ret < 0 || ret >= end - pos) { 1473 *pos = '\0'; 1474 return pos - buf; 1475 } 1476 pos += ret; 1477 } 1478 1479 return pos - buf; 1480} 1481 1482 1483static int radius_server_get_eap_user(void *ctx, const u8 *identity, 1484 size_t identity_len, int phase2, 1485 struct eap_user *user) 1486{ 1487 struct radius_session *sess = ctx; 1488 struct radius_server_data *data = sess->server; 1489 1490 return data->get_eap_user(data->conf_ctx, identity, identity_len, 1491 phase2, user); 1492} 1493 1494 1495static const char * radius_server_get_eap_req_id_text(void *ctx, size_t *len) 1496{ 1497 struct radius_session *sess = ctx; 1498 struct radius_server_data *data = sess->server; 1499 *len = data->eap_req_id_text_len; 1500 return data->eap_req_id_text; 1501} 1502 1503 1504static struct eapol_callbacks radius_server_eapol_cb = 1505{ 1506 .get_eap_user = radius_server_get_eap_user, 1507 .get_eap_req_id_text = radius_server_get_eap_req_id_text, 1508}; 1509 1510 1511/** 1512 * radius_server_eap_pending_cb - Pending EAP data notification 1513 * @data: RADIUS server context from radius_server_init() 1514 * @ctx: Pending EAP context pointer 1515 * 1516 * This function is used to notify EAP server module that a pending operation 1517 * has been completed and processing of the EAP session can proceed. 1518 */ 1519void radius_server_eap_pending_cb(struct radius_server_data *data, void *ctx) 1520{ 1521 struct radius_client *cli; 1522 struct radius_session *s, *sess = NULL; 1523 struct radius_msg *msg; 1524 1525 if (data == NULL) 1526 return; 1527 1528 for (cli = data->clients; cli; cli = cli->next) { 1529 for (s = cli->sessions; s; s = s->next) { 1530 if (s->eap == ctx && s->last_msg) { 1531 sess = s; 1532 break; 1533 } 1534 if (sess) 1535 break; 1536 } 1537 if (sess) 1538 break; 1539 } 1540 1541 if (sess == NULL) { 1542 RADIUS_DEBUG("No session matched callback ctx"); 1543 return; 1544 } 1545 1546 msg = sess->last_msg; 1547 sess->last_msg = NULL; 1548 eap_sm_pending_cb(sess->eap); 1549 if (radius_server_request(data, msg, 1550 (struct sockaddr *) &sess->last_from, 1551 sess->last_fromlen, cli, 1552 sess->last_from_addr, 1553 sess->last_from_port, sess) == -2) 1554 return; /* msg was stored with the session */ 1555 1556 radius_msg_free(msg); 1557} 1558