1 /* 2 * RADIUS client 3 * Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi> 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9 #include "includes.h" 10 11 #include "common.h" 12 #include "radius.h" 13 #include "radius_client.h" 14 #include "eloop.h" 15 16 /* Defaults for RADIUS retransmit values (exponential backoff) */ 17 18 /** 19 * RADIUS_CLIENT_FIRST_WAIT - RADIUS client timeout for first retry in seconds 20 */ 21 #define RADIUS_CLIENT_FIRST_WAIT 3 22 23 /** 24 * RADIUS_CLIENT_MAX_WAIT - RADIUS client maximum retry timeout in seconds 25 */ 26 #define RADIUS_CLIENT_MAX_WAIT 120 27 28 /** 29 * RADIUS_CLIENT_MAX_RETRIES - RADIUS client maximum retries 30 * 31 * Maximum number of retransmit attempts before the entry is removed from 32 * retransmit list. 33 */ 34 #define RADIUS_CLIENT_MAX_RETRIES 10 35 36 /** 37 * RADIUS_CLIENT_MAX_ENTRIES - RADIUS client maximum pending messages 38 * 39 * Maximum number of entries in retransmit list (oldest entries will be 40 * removed, if this limit is exceeded). 41 */ 42 #define RADIUS_CLIENT_MAX_ENTRIES 30 43 44 /** 45 * RADIUS_CLIENT_NUM_FAILOVER - RADIUS client failover point 46 * 47 * The number of failed retry attempts after which the RADIUS server will be 48 * changed (if one of more backup servers are configured). 49 */ 50 #define RADIUS_CLIENT_NUM_FAILOVER 4 51 52 53 /** 54 * struct radius_rx_handler - RADIUS client RX handler 55 * 56 * This data structure is used internally inside the RADIUS client module to 57 * store registered RX handlers. These handlers are registered by calls to 58 * radius_client_register() and unregistered when the RADIUS client is 59 * deinitialized with a call to radius_client_deinit(). 60 */ 61 struct radius_rx_handler { 62 /** 63 * handler - Received RADIUS message handler 64 */ 65 RadiusRxResult (*handler)(struct radius_msg *msg, 66 struct radius_msg *req, 67 const u8 *shared_secret, 68 size_t shared_secret_len, 69 void *data); 70 71 /** 72 * data - Context data for the handler 73 */ 74 void *data; 75 }; 76 77 78 /** 79 * struct radius_msg_list - RADIUS client message retransmit list 80 * 81 * This data structure is used internally inside the RADIUS client module to 82 * store pending RADIUS requests that may still need to be retransmitted. 83 */ 84 struct radius_msg_list { 85 /** 86 * addr - STA/client address 87 * 88 * This is used to find RADIUS messages for the same STA. 89 */ 90 u8 addr[ETH_ALEN]; 91 92 /** 93 * msg - RADIUS message 94 */ 95 struct radius_msg *msg; 96 97 /** 98 * msg_type - Message type 99 */ 100 RadiusType msg_type; 101 102 /** 103 * first_try - Time of the first transmission attempt 104 */ 105 os_time_t first_try; 106 107 /** 108 * next_try - Time for the next transmission attempt 109 */ 110 os_time_t next_try; 111 112 /** 113 * attempts - Number of transmission attempts 114 */ 115 int attempts; 116 117 /** 118 * next_wait - Next retransmission wait time in seconds 119 */ 120 int next_wait; 121 122 /** 123 * last_attempt - Time of the last transmission attempt 124 */ 125 struct os_reltime last_attempt; 126 127 /** 128 * shared_secret - Shared secret with the target RADIUS server 129 */ 130 const u8 *shared_secret; 131 132 /** 133 * shared_secret_len - shared_secret length in octets 134 */ 135 size_t shared_secret_len; 136 137 /* TODO: server config with failover to backup server(s) */ 138 139 /** 140 * next - Next message in the list 141 */ 142 struct radius_msg_list *next; 143 }; 144 145 146 /** 147 * struct radius_client_data - Internal RADIUS client data 148 * 149 * This data structure is used internally inside the RADIUS client module. 150 * External users allocate this by calling radius_client_init() and free it by 151 * calling radius_client_deinit(). The pointer to this opaque data is used in 152 * calls to other functions as an identifier for the RADIUS client instance. 153 */ 154 struct radius_client_data { 155 /** 156 * ctx - Context pointer for hostapd_logger() callbacks 157 */ 158 void *ctx; 159 160 /** 161 * conf - RADIUS client configuration (list of RADIUS servers to use) 162 */ 163 struct hostapd_radius_servers *conf; 164 165 /** 166 * auth_serv_sock - IPv4 socket for RADIUS authentication messages 167 */ 168 int auth_serv_sock; 169 170 /** 171 * acct_serv_sock - IPv4 socket for RADIUS accounting messages 172 */ 173 int acct_serv_sock; 174 175 /** 176 * auth_serv_sock6 - IPv6 socket for RADIUS authentication messages 177 */ 178 int auth_serv_sock6; 179 180 /** 181 * acct_serv_sock6 - IPv6 socket for RADIUS accounting messages 182 */ 183 int acct_serv_sock6; 184 185 /** 186 * auth_sock - Currently used socket for RADIUS authentication server 187 */ 188 int auth_sock; 189 190 /** 191 * acct_sock - Currently used socket for RADIUS accounting server 192 */ 193 int acct_sock; 194 195 /** 196 * auth_handlers - Authentication message handlers 197 */ 198 struct radius_rx_handler *auth_handlers; 199 200 /** 201 * num_auth_handlers - Number of handlers in auth_handlers 202 */ 203 size_t num_auth_handlers; 204 205 /** 206 * acct_handlers - Accounting message handlers 207 */ 208 struct radius_rx_handler *acct_handlers; 209 210 /** 211 * num_acct_handlers - Number of handlers in acct_handlers 212 */ 213 size_t num_acct_handlers; 214 215 /** 216 * msgs - Pending outgoing RADIUS messages 217 */ 218 struct radius_msg_list *msgs; 219 220 /** 221 * num_msgs - Number of pending messages in the msgs list 222 */ 223 size_t num_msgs; 224 225 /** 226 * next_radius_identifier - Next RADIUS message identifier to use 227 */ 228 u8 next_radius_identifier; 229 }; 230 231 232 static int 233 radius_change_server(struct radius_client_data *radius, 234 struct hostapd_radius_server *nserv, 235 struct hostapd_radius_server *oserv, 236 int sock, int sock6, int auth); 237 static int radius_client_init_acct(struct radius_client_data *radius); 238 static int radius_client_init_auth(struct radius_client_data *radius); 239 static void radius_client_auth_failover(struct radius_client_data *radius); 240 static void radius_client_acct_failover(struct radius_client_data *radius); 241 242 243 static void radius_client_msg_free(struct radius_msg_list *req) 244 { 245 radius_msg_free(req->msg); 246 os_free(req); 247 } 248 249 250 /** 251 * radius_client_register - Register a RADIUS client RX handler 252 * @radius: RADIUS client context from radius_client_init() 253 * @msg_type: RADIUS client type (RADIUS_AUTH or RADIUS_ACCT) 254 * @handler: Handler for received RADIUS messages 255 * @data: Context pointer for handler callbacks 256 * Returns: 0 on success, -1 on failure 257 * 258 * This function is used to register a handler for processing received RADIUS 259 * authentication and accounting messages. The handler() callback function will 260 * be called whenever a RADIUS message is received from the active server. 261 * 262 * There can be multiple registered RADIUS message handlers. The handlers will 263 * be called in order until one of them indicates that it has processed or 264 * queued the message. 265 */ 266 int radius_client_register(struct radius_client_data *radius, 267 RadiusType msg_type, 268 RadiusRxResult (*handler)(struct radius_msg *msg, 269 struct radius_msg *req, 270 const u8 *shared_secret, 271 size_t shared_secret_len, 272 void *data), 273 void *data) 274 { 275 struct radius_rx_handler **handlers, *newh; 276 size_t *num; 277 278 if (msg_type == RADIUS_ACCT) { 279 handlers = &radius->acct_handlers; 280 num = &radius->num_acct_handlers; 281 } else { 282 handlers = &radius->auth_handlers; 283 num = &radius->num_auth_handlers; 284 } 285 286 newh = os_realloc_array(*handlers, *num + 1, 287 sizeof(struct radius_rx_handler)); 288 if (newh == NULL) 289 return -1; 290 291 newh[*num].handler = handler; 292 newh[*num].data = data; 293 (*num)++; 294 *handlers = newh; 295 296 return 0; 297 } 298 299 300 /* 301 * Returns >0 if message queue was flushed (i.e., the message that triggered 302 * the error is not available anymore) 303 */ 304 static int radius_client_handle_send_error(struct radius_client_data *radius, 305 int s, RadiusType msg_type) 306 { 307 #ifndef CONFIG_NATIVE_WINDOWS 308 int _errno = errno; 309 wpa_printf(MSG_INFO, "send[RADIUS,s=%d]: %s", s, strerror(errno)); 310 if (_errno == ENOTCONN || _errno == EDESTADDRREQ || _errno == EINVAL || 311 _errno == EBADF || _errno == ENETUNREACH) { 312 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 313 HOSTAPD_LEVEL_INFO, 314 "Send failed - maybe interface status changed -" 315 " try to connect again"); 316 if (msg_type == RADIUS_ACCT || 317 msg_type == RADIUS_ACCT_INTERIM) { 318 radius_client_init_acct(radius); 319 return 0; 320 } else { 321 radius_client_init_auth(radius); 322 return 1; 323 } 324 } 325 #endif /* CONFIG_NATIVE_WINDOWS */ 326 327 return 0; 328 } 329 330 331 static int radius_client_retransmit(struct radius_client_data *radius, 332 struct radius_msg_list *entry, 333 os_time_t now) 334 { 335 struct hostapd_radius_servers *conf = radius->conf; 336 int s; 337 struct wpabuf *buf; 338 size_t prev_num_msgs; 339 340 if (entry->msg_type == RADIUS_ACCT || 341 entry->msg_type == RADIUS_ACCT_INTERIM) { 342 if (radius->acct_sock < 0) 343 radius_client_init_acct(radius); 344 if (radius->acct_sock < 0 && conf->num_acct_servers > 1) { 345 prev_num_msgs = radius->num_msgs; 346 radius_client_acct_failover(radius); 347 if (prev_num_msgs != radius->num_msgs) 348 return 0; 349 } 350 s = radius->acct_sock; 351 if (entry->attempts == 0) 352 conf->acct_server->requests++; 353 else { 354 conf->acct_server->timeouts++; 355 conf->acct_server->retransmissions++; 356 } 357 } else { 358 if (radius->auth_sock < 0) 359 radius_client_init_auth(radius); 360 if (radius->auth_sock < 0 && conf->num_auth_servers > 1) { 361 prev_num_msgs = radius->num_msgs; 362 radius_client_auth_failover(radius); 363 if (prev_num_msgs != radius->num_msgs) 364 return 0; 365 } 366 s = radius->auth_sock; 367 if (entry->attempts == 0) 368 conf->auth_server->requests++; 369 else { 370 conf->auth_server->timeouts++; 371 conf->auth_server->retransmissions++; 372 } 373 } 374 if (s < 0) { 375 wpa_printf(MSG_INFO, 376 "RADIUS: No valid socket for retransmission"); 377 return 1; 378 } 379 380 /* retransmit; remove entry if too many attempts */ 381 entry->attempts++; 382 hostapd_logger(radius->ctx, entry->addr, HOSTAPD_MODULE_RADIUS, 383 HOSTAPD_LEVEL_DEBUG, "Resending RADIUS message (id=%d)", 384 radius_msg_get_hdr(entry->msg)->identifier); 385 386 os_get_reltime(&entry->last_attempt); 387 buf = radius_msg_get_buf(entry->msg); 388 if (send(s, wpabuf_head(buf), wpabuf_len(buf), 0) < 0) { 389 if (radius_client_handle_send_error(radius, s, entry->msg_type) 390 > 0) 391 return 0; 392 } 393 394 entry->next_try = now + entry->next_wait; 395 entry->next_wait *= 2; 396 if (entry->next_wait > RADIUS_CLIENT_MAX_WAIT) 397 entry->next_wait = RADIUS_CLIENT_MAX_WAIT; 398 if (entry->attempts >= RADIUS_CLIENT_MAX_RETRIES) { 399 wpa_printf(MSG_INFO, "RADIUS: Removing un-ACKed message due to too many failed retransmit attempts"); 400 return 1; 401 } 402 403 return 0; 404 } 405 406 407 static void radius_client_timer(void *eloop_ctx, void *timeout_ctx) 408 { 409 struct radius_client_data *radius = eloop_ctx; 410 struct hostapd_radius_servers *conf = radius->conf; 411 struct os_reltime now; 412 os_time_t first; 413 struct radius_msg_list *entry, *prev, *tmp; 414 int auth_failover = 0, acct_failover = 0; 415 size_t prev_num_msgs; 416 int s; 417 418 entry = radius->msgs; 419 if (!entry) 420 return; 421 422 os_get_reltime(&now); 423 first = 0; 424 425 prev = NULL; 426 while (entry) { 427 prev_num_msgs = radius->num_msgs; 428 if (now.sec >= entry->next_try && 429 radius_client_retransmit(radius, entry, now.sec)) { 430 if (prev) 431 prev->next = entry->next; 432 else 433 radius->msgs = entry->next; 434 435 tmp = entry; 436 entry = entry->next; 437 radius_client_msg_free(tmp); 438 radius->num_msgs--; 439 continue; 440 } 441 442 if (prev_num_msgs != radius->num_msgs) { 443 wpa_printf(MSG_DEBUG, 444 "RADIUS: Message removed from queue - restart from beginning"); 445 entry = radius->msgs; 446 prev = NULL; 447 continue; 448 } 449 450 s = entry->msg_type == RADIUS_AUTH ? radius->auth_sock : 451 radius->acct_sock; 452 if (entry->attempts > RADIUS_CLIENT_NUM_FAILOVER || 453 (s < 0 && entry->attempts > 0)) { 454 if (entry->msg_type == RADIUS_ACCT || 455 entry->msg_type == RADIUS_ACCT_INTERIM) 456 acct_failover++; 457 else 458 auth_failover++; 459 } 460 461 if (first == 0 || entry->next_try < first) 462 first = entry->next_try; 463 464 prev = entry; 465 entry = entry->next; 466 } 467 468 if (radius->msgs) { 469 if (first < now.sec) 470 first = now.sec; 471 eloop_register_timeout(first - now.sec, 0, 472 radius_client_timer, radius, NULL); 473 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 474 HOSTAPD_LEVEL_DEBUG, "Next RADIUS client " 475 "retransmit in %ld seconds", 476 (long int) (first - now.sec)); 477 } 478 479 if (auth_failover && conf->num_auth_servers > 1) 480 radius_client_auth_failover(radius); 481 482 if (acct_failover && conf->num_acct_servers > 1) 483 radius_client_acct_failover(radius); 484 } 485 486 487 static void radius_client_auth_failover(struct radius_client_data *radius) 488 { 489 struct hostapd_radius_servers *conf = radius->conf; 490 struct hostapd_radius_server *next, *old; 491 struct radius_msg_list *entry; 492 char abuf[50]; 493 494 old = conf->auth_server; 495 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 496 HOSTAPD_LEVEL_NOTICE, 497 "No response from Authentication server %s:%d - failover", 498 hostapd_ip_txt(&old->addr, abuf, sizeof(abuf)), 499 old->port); 500 501 for (entry = radius->msgs; entry; entry = entry->next) { 502 if (entry->msg_type == RADIUS_AUTH) 503 old->timeouts++; 504 } 505 506 next = old + 1; 507 if (next > &(conf->auth_servers[conf->num_auth_servers - 1])) 508 next = conf->auth_servers; 509 conf->auth_server = next; 510 radius_change_server(radius, next, old, 511 radius->auth_serv_sock, 512 radius->auth_serv_sock6, 1); 513 } 514 515 516 static void radius_client_acct_failover(struct radius_client_data *radius) 517 { 518 struct hostapd_radius_servers *conf = radius->conf; 519 struct hostapd_radius_server *next, *old; 520 struct radius_msg_list *entry; 521 char abuf[50]; 522 523 old = conf->acct_server; 524 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 525 HOSTAPD_LEVEL_NOTICE, 526 "No response from Accounting server %s:%d - failover", 527 hostapd_ip_txt(&old->addr, abuf, sizeof(abuf)), 528 old->port); 529 530 for (entry = radius->msgs; entry; entry = entry->next) { 531 if (entry->msg_type == RADIUS_ACCT || 532 entry->msg_type == RADIUS_ACCT_INTERIM) 533 old->timeouts++; 534 } 535 536 next = old + 1; 537 if (next > &conf->acct_servers[conf->num_acct_servers - 1]) 538 next = conf->acct_servers; 539 conf->acct_server = next; 540 radius_change_server(radius, next, old, 541 radius->acct_serv_sock, 542 radius->acct_serv_sock6, 0); 543 } 544 545 546 static void radius_client_update_timeout(struct radius_client_data *radius) 547 { 548 struct os_reltime now; 549 os_time_t first; 550 struct radius_msg_list *entry; 551 552 eloop_cancel_timeout(radius_client_timer, radius, NULL); 553 554 if (radius->msgs == NULL) { 555 return; 556 } 557 558 first = 0; 559 for (entry = radius->msgs; entry; entry = entry->next) { 560 if (first == 0 || entry->next_try < first) 561 first = entry->next_try; 562 } 563 564 os_get_reltime(&now); 565 if (first < now.sec) 566 first = now.sec; 567 eloop_register_timeout(first - now.sec, 0, radius_client_timer, radius, 568 NULL); 569 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 570 HOSTAPD_LEVEL_DEBUG, "Next RADIUS client retransmit in" 571 " %ld seconds", (long int) (first - now.sec)); 572 } 573 574 575 static void radius_client_list_add(struct radius_client_data *radius, 576 struct radius_msg *msg, 577 RadiusType msg_type, 578 const u8 *shared_secret, 579 size_t shared_secret_len, const u8 *addr) 580 { 581 struct radius_msg_list *entry, *prev; 582 583 if (eloop_terminated()) { 584 /* No point in adding entries to retransmit queue since event 585 * loop has already been terminated. */ 586 radius_msg_free(msg); 587 return; 588 } 589 590 entry = os_zalloc(sizeof(*entry)); 591 if (entry == NULL) { 592 wpa_printf(MSG_INFO, "RADIUS: Failed to add packet into retransmit list"); 593 radius_msg_free(msg); 594 return; 595 } 596 597 if (addr) 598 os_memcpy(entry->addr, addr, ETH_ALEN); 599 entry->msg = msg; 600 entry->msg_type = msg_type; 601 entry->shared_secret = shared_secret; 602 entry->shared_secret_len = shared_secret_len; 603 os_get_reltime(&entry->last_attempt); 604 entry->first_try = entry->last_attempt.sec; 605 entry->next_try = entry->first_try + RADIUS_CLIENT_FIRST_WAIT; 606 entry->attempts = 1; 607 entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2; 608 entry->next = radius->msgs; 609 radius->msgs = entry; 610 radius_client_update_timeout(radius); 611 612 if (radius->num_msgs >= RADIUS_CLIENT_MAX_ENTRIES) { 613 wpa_printf(MSG_INFO, "RADIUS: Removing the oldest un-ACKed packet due to retransmit list limits"); 614 prev = NULL; 615 while (entry->next) { 616 prev = entry; 617 entry = entry->next; 618 } 619 if (prev) { 620 prev->next = NULL; 621 radius_client_msg_free(entry); 622 } 623 } else 624 radius->num_msgs++; 625 } 626 627 628 static void radius_client_list_del(struct radius_client_data *radius, 629 RadiusType msg_type, const u8 *addr) 630 { 631 struct radius_msg_list *entry, *prev, *tmp; 632 633 if (addr == NULL) 634 return; 635 636 entry = radius->msgs; 637 prev = NULL; 638 while (entry) { 639 if (entry->msg_type == msg_type && 640 os_memcmp(entry->addr, addr, ETH_ALEN) == 0) { 641 if (prev) 642 prev->next = entry->next; 643 else 644 radius->msgs = entry->next; 645 tmp = entry; 646 entry = entry->next; 647 hostapd_logger(radius->ctx, addr, 648 HOSTAPD_MODULE_RADIUS, 649 HOSTAPD_LEVEL_DEBUG, 650 "Removing matching RADIUS message"); 651 radius_client_msg_free(tmp); 652 radius->num_msgs--; 653 continue; 654 } 655 prev = entry; 656 entry = entry->next; 657 } 658 } 659 660 661 /** 662 * radius_client_send - Send a RADIUS request 663 * @radius: RADIUS client context from radius_client_init() 664 * @msg: RADIUS message to be sent 665 * @msg_type: Message type (RADIUS_AUTH, RADIUS_ACCT, RADIUS_ACCT_INTERIM) 666 * @addr: MAC address of the device related to this message or %NULL 667 * Returns: 0 on success, -1 on failure 668 * 669 * This function is used to transmit a RADIUS authentication (RADIUS_AUTH) or 670 * accounting request (RADIUS_ACCT or RADIUS_ACCT_INTERIM). The only difference 671 * between accounting and interim accounting messages is that the interim 672 * message will override any pending interim accounting updates while a new 673 * accounting message does not remove any pending messages. 674 * 675 * The message is added on the retransmission queue and will be retransmitted 676 * automatically until a response is received or maximum number of retries 677 * (RADIUS_CLIENT_MAX_RETRIES) is reached. 678 * 679 * The related device MAC address can be used to identify pending messages that 680 * can be removed with radius_client_flush_auth() or with interim accounting 681 * updates. 682 */ 683 int radius_client_send(struct radius_client_data *radius, 684 struct radius_msg *msg, RadiusType msg_type, 685 const u8 *addr) 686 { 687 struct hostapd_radius_servers *conf = radius->conf; 688 const u8 *shared_secret; 689 size_t shared_secret_len; 690 char *name; 691 int s, res; 692 struct wpabuf *buf; 693 694 if (msg_type == RADIUS_ACCT_INTERIM) { 695 /* Remove any pending interim acct update for the same STA. */ 696 radius_client_list_del(radius, msg_type, addr); 697 } 698 699 if (msg_type == RADIUS_ACCT || msg_type == RADIUS_ACCT_INTERIM) { 700 if (conf->acct_server && radius->acct_sock < 0) 701 radius_client_init_acct(radius); 702 703 if (conf->acct_server == NULL || radius->acct_sock < 0 || 704 conf->acct_server->shared_secret == NULL) { 705 hostapd_logger(radius->ctx, NULL, 706 HOSTAPD_MODULE_RADIUS, 707 HOSTAPD_LEVEL_INFO, 708 "No accounting server configured"); 709 return -1; 710 } 711 shared_secret = conf->acct_server->shared_secret; 712 shared_secret_len = conf->acct_server->shared_secret_len; 713 radius_msg_finish_acct(msg, shared_secret, shared_secret_len); 714 name = "accounting"; 715 s = radius->acct_sock; 716 conf->acct_server->requests++; 717 } else { 718 if (conf->auth_server && radius->auth_sock < 0) 719 radius_client_init_auth(radius); 720 721 if (conf->auth_server == NULL || radius->auth_sock < 0 || 722 conf->auth_server->shared_secret == NULL) { 723 hostapd_logger(radius->ctx, NULL, 724 HOSTAPD_MODULE_RADIUS, 725 HOSTAPD_LEVEL_INFO, 726 "No authentication server configured"); 727 return -1; 728 } 729 shared_secret = conf->auth_server->shared_secret; 730 shared_secret_len = conf->auth_server->shared_secret_len; 731 radius_msg_finish(msg, shared_secret, shared_secret_len); 732 name = "authentication"; 733 s = radius->auth_sock; 734 conf->auth_server->requests++; 735 } 736 737 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 738 HOSTAPD_LEVEL_DEBUG, "Sending RADIUS message to %s " 739 "server", name); 740 if (conf->msg_dumps) 741 radius_msg_dump(msg); 742 743 buf = radius_msg_get_buf(msg); 744 res = send(s, wpabuf_head(buf), wpabuf_len(buf), 0); 745 if (res < 0) 746 radius_client_handle_send_error(radius, s, msg_type); 747 748 radius_client_list_add(radius, msg, msg_type, shared_secret, 749 shared_secret_len, addr); 750 751 return 0; 752 } 753 754 755 static void radius_client_receive(int sock, void *eloop_ctx, void *sock_ctx) 756 { 757 struct radius_client_data *radius = eloop_ctx; 758 struct hostapd_radius_servers *conf = radius->conf; 759 RadiusType msg_type = (RadiusType) sock_ctx; 760 int len, roundtrip; 761 unsigned char buf[3000]; 762 struct radius_msg *msg; 763 struct radius_hdr *hdr; 764 struct radius_rx_handler *handlers; 765 size_t num_handlers, i; 766 struct radius_msg_list *req, *prev_req; 767 struct os_reltime now; 768 struct hostapd_radius_server *rconf; 769 int invalid_authenticator = 0; 770 771 if (msg_type == RADIUS_ACCT) { 772 handlers = radius->acct_handlers; 773 num_handlers = radius->num_acct_handlers; 774 rconf = conf->acct_server; 775 } else { 776 handlers = radius->auth_handlers; 777 num_handlers = radius->num_auth_handlers; 778 rconf = conf->auth_server; 779 } 780 781 len = recv(sock, buf, sizeof(buf), MSG_DONTWAIT); 782 if (len < 0) { 783 wpa_printf(MSG_INFO, "recv[RADIUS]: %s", strerror(errno)); 784 return; 785 } 786 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 787 HOSTAPD_LEVEL_DEBUG, "Received %d bytes from RADIUS " 788 "server", len); 789 if (len == sizeof(buf)) { 790 wpa_printf(MSG_INFO, "RADIUS: Possibly too long UDP frame for our buffer - dropping it"); 791 return; 792 } 793 794 msg = radius_msg_parse(buf, len); 795 if (msg == NULL) { 796 wpa_printf(MSG_INFO, "RADIUS: Parsing incoming frame failed"); 797 rconf->malformed_responses++; 798 return; 799 } 800 hdr = radius_msg_get_hdr(msg); 801 802 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 803 HOSTAPD_LEVEL_DEBUG, "Received RADIUS message"); 804 if (conf->msg_dumps) 805 radius_msg_dump(msg); 806 807 switch (hdr->code) { 808 case RADIUS_CODE_ACCESS_ACCEPT: 809 rconf->access_accepts++; 810 break; 811 case RADIUS_CODE_ACCESS_REJECT: 812 rconf->access_rejects++; 813 break; 814 case RADIUS_CODE_ACCESS_CHALLENGE: 815 rconf->access_challenges++; 816 break; 817 case RADIUS_CODE_ACCOUNTING_RESPONSE: 818 rconf->responses++; 819 break; 820 } 821 822 prev_req = NULL; 823 req = radius->msgs; 824 while (req) { 825 /* TODO: also match by src addr:port of the packet when using 826 * alternative RADIUS servers (?) */ 827 if ((req->msg_type == msg_type || 828 (req->msg_type == RADIUS_ACCT_INTERIM && 829 msg_type == RADIUS_ACCT)) && 830 radius_msg_get_hdr(req->msg)->identifier == 831 hdr->identifier) 832 break; 833 834 prev_req = req; 835 req = req->next; 836 } 837 838 if (req == NULL) { 839 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 840 HOSTAPD_LEVEL_DEBUG, 841 "No matching RADIUS request found (type=%d " 842 "id=%d) - dropping packet", 843 msg_type, hdr->identifier); 844 goto fail; 845 } 846 847 os_get_reltime(&now); 848 roundtrip = (now.sec - req->last_attempt.sec) * 100 + 849 (now.usec - req->last_attempt.usec) / 10000; 850 hostapd_logger(radius->ctx, req->addr, HOSTAPD_MODULE_RADIUS, 851 HOSTAPD_LEVEL_DEBUG, 852 "Received RADIUS packet matched with a pending " 853 "request, round trip time %d.%02d sec", 854 roundtrip / 100, roundtrip % 100); 855 rconf->round_trip_time = roundtrip; 856 857 /* Remove ACKed RADIUS packet from retransmit list */ 858 if (prev_req) 859 prev_req->next = req->next; 860 else 861 radius->msgs = req->next; 862 radius->num_msgs--; 863 864 for (i = 0; i < num_handlers; i++) { 865 RadiusRxResult res; 866 res = handlers[i].handler(msg, req->msg, req->shared_secret, 867 req->shared_secret_len, 868 handlers[i].data); 869 switch (res) { 870 case RADIUS_RX_PROCESSED: 871 radius_msg_free(msg); 872 /* continue */ 873 case RADIUS_RX_QUEUED: 874 radius_client_msg_free(req); 875 return; 876 case RADIUS_RX_INVALID_AUTHENTICATOR: 877 invalid_authenticator++; 878 /* continue */ 879 case RADIUS_RX_UNKNOWN: 880 /* continue with next handler */ 881 break; 882 } 883 } 884 885 if (invalid_authenticator) 886 rconf->bad_authenticators++; 887 else 888 rconf->unknown_types++; 889 hostapd_logger(radius->ctx, req->addr, HOSTAPD_MODULE_RADIUS, 890 HOSTAPD_LEVEL_DEBUG, "No RADIUS RX handler found " 891 "(type=%d code=%d id=%d)%s - dropping packet", 892 msg_type, hdr->code, hdr->identifier, 893 invalid_authenticator ? " [INVALID AUTHENTICATOR]" : 894 ""); 895 radius_client_msg_free(req); 896 897 fail: 898 radius_msg_free(msg); 899 } 900 901 902 /** 903 * radius_client_get_id - Get an identifier for a new RADIUS message 904 * @radius: RADIUS client context from radius_client_init() 905 * Returns: Allocated identifier 906 * 907 * This function is used to fetch a unique (among pending requests) identifier 908 * for a new RADIUS message. 909 */ 910 u8 radius_client_get_id(struct radius_client_data *radius) 911 { 912 struct radius_msg_list *entry, *prev, *_remove; 913 u8 id = radius->next_radius_identifier++; 914 915 /* remove entries with matching id from retransmit list to avoid 916 * using new reply from the RADIUS server with an old request */ 917 entry = radius->msgs; 918 prev = NULL; 919 while (entry) { 920 if (radius_msg_get_hdr(entry->msg)->identifier == id) { 921 hostapd_logger(radius->ctx, entry->addr, 922 HOSTAPD_MODULE_RADIUS, 923 HOSTAPD_LEVEL_DEBUG, 924 "Removing pending RADIUS message, " 925 "since its id (%d) is reused", id); 926 if (prev) 927 prev->next = entry->next; 928 else 929 radius->msgs = entry->next; 930 _remove = entry; 931 } else { 932 _remove = NULL; 933 prev = entry; 934 } 935 entry = entry->next; 936 937 if (_remove) 938 radius_client_msg_free(_remove); 939 } 940 941 return id; 942 } 943 944 945 /** 946 * radius_client_flush - Flush all pending RADIUS client messages 947 * @radius: RADIUS client context from radius_client_init() 948 * @only_auth: Whether only authentication messages are removed 949 */ 950 void radius_client_flush(struct radius_client_data *radius, int only_auth) 951 { 952 struct radius_msg_list *entry, *prev, *tmp; 953 954 if (!radius) 955 return; 956 957 prev = NULL; 958 entry = radius->msgs; 959 960 while (entry) { 961 if (!only_auth || entry->msg_type == RADIUS_AUTH) { 962 if (prev) 963 prev->next = entry->next; 964 else 965 radius->msgs = entry->next; 966 967 tmp = entry; 968 entry = entry->next; 969 radius_client_msg_free(tmp); 970 radius->num_msgs--; 971 } else { 972 prev = entry; 973 entry = entry->next; 974 } 975 } 976 977 if (radius->msgs == NULL) 978 eloop_cancel_timeout(radius_client_timer, radius, NULL); 979 } 980 981 982 static void radius_client_update_acct_msgs(struct radius_client_data *radius, 983 const u8 *shared_secret, 984 size_t shared_secret_len) 985 { 986 struct radius_msg_list *entry; 987 988 if (!radius) 989 return; 990 991 for (entry = radius->msgs; entry; entry = entry->next) { 992 if (entry->msg_type == RADIUS_ACCT) { 993 entry->shared_secret = shared_secret; 994 entry->shared_secret_len = shared_secret_len; 995 radius_msg_finish_acct(entry->msg, shared_secret, 996 shared_secret_len); 997 } 998 } 999 } 1000 1001 1002 static int 1003 radius_change_server(struct radius_client_data *radius, 1004 struct hostapd_radius_server *nserv, 1005 struct hostapd_radius_server *oserv, 1006 int sock, int sock6, int auth) 1007 { 1008 struct sockaddr_in serv, claddr; 1009 #ifdef CONFIG_IPV6 1010 struct sockaddr_in6 serv6, claddr6; 1011 #endif /* CONFIG_IPV6 */ 1012 struct sockaddr *addr, *cl_addr; 1013 socklen_t addrlen, claddrlen; 1014 char abuf[50]; 1015 int sel_sock; 1016 struct radius_msg_list *entry; 1017 struct hostapd_radius_servers *conf = radius->conf; 1018 1019 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 1020 HOSTAPD_LEVEL_INFO, 1021 "%s server %s:%d", 1022 auth ? "Authentication" : "Accounting", 1023 hostapd_ip_txt(&nserv->addr, abuf, sizeof(abuf)), 1024 nserv->port); 1025 1026 if (oserv && oserv != nserv && 1027 (nserv->shared_secret_len != oserv->shared_secret_len || 1028 os_memcmp(nserv->shared_secret, oserv->shared_secret, 1029 nserv->shared_secret_len) != 0)) { 1030 /* Pending RADIUS packets used different shared secret, so 1031 * they need to be modified. Update accounting message 1032 * authenticators here. Authentication messages are removed 1033 * since they would require more changes and the new RADIUS 1034 * server may not be prepared to receive them anyway due to 1035 * missing state information. Client will likely retry 1036 * authentication, so this should not be an issue. */ 1037 if (auth) 1038 radius_client_flush(radius, 1); 1039 else { 1040 radius_client_update_acct_msgs( 1041 radius, nserv->shared_secret, 1042 nserv->shared_secret_len); 1043 } 1044 } 1045 1046 /* Reset retry counters for the new server */ 1047 for (entry = radius->msgs; oserv && oserv != nserv && entry; 1048 entry = entry->next) { 1049 if ((auth && entry->msg_type != RADIUS_AUTH) || 1050 (!auth && entry->msg_type != RADIUS_ACCT)) 1051 continue; 1052 entry->next_try = entry->first_try + RADIUS_CLIENT_FIRST_WAIT; 1053 entry->attempts = 0; 1054 entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2; 1055 } 1056 1057 if (radius->msgs) { 1058 eloop_cancel_timeout(radius_client_timer, radius, NULL); 1059 eloop_register_timeout(RADIUS_CLIENT_FIRST_WAIT, 0, 1060 radius_client_timer, radius, NULL); 1061 } 1062 1063 switch (nserv->addr.af) { 1064 case AF_INET: 1065 os_memset(&serv, 0, sizeof(serv)); 1066 serv.sin_family = AF_INET; 1067 serv.sin_addr.s_addr = nserv->addr.u.v4.s_addr; 1068 serv.sin_port = htons(nserv->port); 1069 addr = (struct sockaddr *) &serv; 1070 addrlen = sizeof(serv); 1071 sel_sock = sock; 1072 break; 1073 #ifdef CONFIG_IPV6 1074 case AF_INET6: 1075 os_memset(&serv6, 0, sizeof(serv6)); 1076 serv6.sin6_family = AF_INET6; 1077 os_memcpy(&serv6.sin6_addr, &nserv->addr.u.v6, 1078 sizeof(struct in6_addr)); 1079 serv6.sin6_port = htons(nserv->port); 1080 addr = (struct sockaddr *) &serv6; 1081 addrlen = sizeof(serv6); 1082 sel_sock = sock6; 1083 break; 1084 #endif /* CONFIG_IPV6 */ 1085 default: 1086 return -1; 1087 } 1088 1089 if (sel_sock < 0) { 1090 wpa_printf(MSG_INFO, 1091 "RADIUS: No server socket available (af=%d sock=%d sock6=%d auth=%d", 1092 nserv->addr.af, sock, sock6, auth); 1093 return -1; 1094 } 1095 1096 if (conf->force_client_addr) { 1097 switch (conf->client_addr.af) { 1098 case AF_INET: 1099 os_memset(&claddr, 0, sizeof(claddr)); 1100 claddr.sin_family = AF_INET; 1101 claddr.sin_addr.s_addr = conf->client_addr.u.v4.s_addr; 1102 claddr.sin_port = htons(0); 1103 cl_addr = (struct sockaddr *) &claddr; 1104 claddrlen = sizeof(claddr); 1105 break; 1106 #ifdef CONFIG_IPV6 1107 case AF_INET6: 1108 os_memset(&claddr6, 0, sizeof(claddr6)); 1109 claddr6.sin6_family = AF_INET6; 1110 os_memcpy(&claddr6.sin6_addr, &conf->client_addr.u.v6, 1111 sizeof(struct in6_addr)); 1112 claddr6.sin6_port = htons(0); 1113 cl_addr = (struct sockaddr *) &claddr6; 1114 claddrlen = sizeof(claddr6); 1115 break; 1116 #endif /* CONFIG_IPV6 */ 1117 default: 1118 return -1; 1119 } 1120 1121 if (bind(sel_sock, cl_addr, claddrlen) < 0) { 1122 wpa_printf(MSG_INFO, "bind[radius]: %s", 1123 strerror(errno)); 1124 return -1; 1125 } 1126 } 1127 1128 if (connect(sel_sock, addr, addrlen) < 0) { 1129 wpa_printf(MSG_INFO, "connect[radius]: %s", strerror(errno)); 1130 return -1; 1131 } 1132 1133 #ifndef CONFIG_NATIVE_WINDOWS 1134 switch (nserv->addr.af) { 1135 case AF_INET: 1136 claddrlen = sizeof(claddr); 1137 if (getsockname(sel_sock, (struct sockaddr *) &claddr, 1138 &claddrlen) == 0) { 1139 wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u", 1140 inet_ntoa(claddr.sin_addr), 1141 ntohs(claddr.sin_port)); 1142 } 1143 break; 1144 #ifdef CONFIG_IPV6 1145 case AF_INET6: { 1146 claddrlen = sizeof(claddr6); 1147 if (getsockname(sel_sock, (struct sockaddr *) &claddr6, 1148 &claddrlen) == 0) { 1149 wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u", 1150 inet_ntop(AF_INET6, &claddr6.sin6_addr, 1151 abuf, sizeof(abuf)), 1152 ntohs(claddr6.sin6_port)); 1153 } 1154 break; 1155 } 1156 #endif /* CONFIG_IPV6 */ 1157 } 1158 #endif /* CONFIG_NATIVE_WINDOWS */ 1159 1160 if (auth) 1161 radius->auth_sock = sel_sock; 1162 else 1163 radius->acct_sock = sel_sock; 1164 1165 return 0; 1166 } 1167 1168 1169 static void radius_retry_primary_timer(void *eloop_ctx, void *timeout_ctx) 1170 { 1171 struct radius_client_data *radius = eloop_ctx; 1172 struct hostapd_radius_servers *conf = radius->conf; 1173 struct hostapd_radius_server *oserv; 1174 1175 if (radius->auth_sock >= 0 && conf->auth_servers && 1176 conf->auth_server != conf->auth_servers) { 1177 oserv = conf->auth_server; 1178 conf->auth_server = conf->auth_servers; 1179 if (radius_change_server(radius, conf->auth_server, oserv, 1180 radius->auth_serv_sock, 1181 radius->auth_serv_sock6, 1) < 0) { 1182 conf->auth_server = oserv; 1183 radius_change_server(radius, oserv, conf->auth_server, 1184 radius->auth_serv_sock, 1185 radius->auth_serv_sock6, 1); 1186 } 1187 } 1188 1189 if (radius->acct_sock >= 0 && conf->acct_servers && 1190 conf->acct_server != conf->acct_servers) { 1191 oserv = conf->acct_server; 1192 conf->acct_server = conf->acct_servers; 1193 if (radius_change_server(radius, conf->acct_server, oserv, 1194 radius->acct_serv_sock, 1195 radius->acct_serv_sock6, 0) < 0) { 1196 conf->acct_server = oserv; 1197 radius_change_server(radius, oserv, conf->acct_server, 1198 radius->acct_serv_sock, 1199 radius->acct_serv_sock6, 0); 1200 } 1201 } 1202 1203 if (conf->retry_primary_interval) 1204 eloop_register_timeout(conf->retry_primary_interval, 0, 1205 radius_retry_primary_timer, radius, 1206 NULL); 1207 } 1208 1209 1210 static int radius_client_disable_pmtu_discovery(int s) 1211 { 1212 int r = -1; 1213 #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) 1214 /* Turn off Path MTU discovery on IPv4/UDP sockets. */ 1215 int action = IP_PMTUDISC_DONT; 1216 r = setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, &action, 1217 sizeof(action)); 1218 if (r == -1) 1219 wpa_printf(MSG_ERROR, "RADIUS: Failed to set IP_MTU_DISCOVER: %s", 1220 strerror(errno)); 1221 #endif 1222 return r; 1223 } 1224 1225 1226 static void radius_close_auth_sockets(struct radius_client_data *radius) 1227 { 1228 radius->auth_sock = -1; 1229 1230 if (radius->auth_serv_sock >= 0) { 1231 eloop_unregister_read_sock(radius->auth_serv_sock); 1232 close(radius->auth_serv_sock); 1233 radius->auth_serv_sock = -1; 1234 } 1235 #ifdef CONFIG_IPV6 1236 if (radius->auth_serv_sock6 >= 0) { 1237 eloop_unregister_read_sock(radius->auth_serv_sock6); 1238 close(radius->auth_serv_sock6); 1239 radius->auth_serv_sock6 = -1; 1240 } 1241 #endif /* CONFIG_IPV6 */ 1242 } 1243 1244 1245 static void radius_close_acct_sockets(struct radius_client_data *radius) 1246 { 1247 radius->acct_sock = -1; 1248 1249 if (radius->acct_serv_sock >= 0) { 1250 eloop_unregister_read_sock(radius->acct_serv_sock); 1251 close(radius->acct_serv_sock); 1252 radius->acct_serv_sock = -1; 1253 } 1254 #ifdef CONFIG_IPV6 1255 if (radius->acct_serv_sock6 >= 0) { 1256 eloop_unregister_read_sock(radius->acct_serv_sock6); 1257 close(radius->acct_serv_sock6); 1258 radius->acct_serv_sock6 = -1; 1259 } 1260 #endif /* CONFIG_IPV6 */ 1261 } 1262 1263 1264 static int radius_client_init_auth(struct radius_client_data *radius) 1265 { 1266 struct hostapd_radius_servers *conf = radius->conf; 1267 int ok = 0; 1268 1269 radius_close_auth_sockets(radius); 1270 1271 radius->auth_serv_sock = socket(PF_INET, SOCK_DGRAM, 0); 1272 if (radius->auth_serv_sock < 0) 1273 wpa_printf(MSG_INFO, "RADIUS: socket[PF_INET,SOCK_DGRAM]: %s", 1274 strerror(errno)); 1275 else { 1276 radius_client_disable_pmtu_discovery(radius->auth_serv_sock); 1277 ok++; 1278 } 1279 1280 #ifdef CONFIG_IPV6 1281 radius->auth_serv_sock6 = socket(PF_INET6, SOCK_DGRAM, 0); 1282 if (radius->auth_serv_sock6 < 0) 1283 wpa_printf(MSG_INFO, "RADIUS: socket[PF_INET6,SOCK_DGRAM]: %s", 1284 strerror(errno)); 1285 else 1286 ok++; 1287 #endif /* CONFIG_IPV6 */ 1288 1289 if (ok == 0) 1290 return -1; 1291 1292 radius_change_server(radius, conf->auth_server, NULL, 1293 radius->auth_serv_sock, radius->auth_serv_sock6, 1294 1); 1295 1296 if (radius->auth_serv_sock >= 0 && 1297 eloop_register_read_sock(radius->auth_serv_sock, 1298 radius_client_receive, radius, 1299 (void *) RADIUS_AUTH)) { 1300 wpa_printf(MSG_INFO, "RADIUS: Could not register read socket for authentication server"); 1301 radius_close_auth_sockets(radius); 1302 return -1; 1303 } 1304 1305 #ifdef CONFIG_IPV6 1306 if (radius->auth_serv_sock6 >= 0 && 1307 eloop_register_read_sock(radius->auth_serv_sock6, 1308 radius_client_receive, radius, 1309 (void *) RADIUS_AUTH)) { 1310 wpa_printf(MSG_INFO, "RADIUS: Could not register read socket for authentication server"); 1311 radius_close_auth_sockets(radius); 1312 return -1; 1313 } 1314 #endif /* CONFIG_IPV6 */ 1315 1316 return 0; 1317 } 1318 1319 1320 static int radius_client_init_acct(struct radius_client_data *radius) 1321 { 1322 struct hostapd_radius_servers *conf = radius->conf; 1323 int ok = 0; 1324 1325 radius_close_acct_sockets(radius); 1326 1327 radius->acct_serv_sock = socket(PF_INET, SOCK_DGRAM, 0); 1328 if (radius->acct_serv_sock < 0) 1329 wpa_printf(MSG_INFO, "RADIUS: socket[PF_INET,SOCK_DGRAM]: %s", 1330 strerror(errno)); 1331 else { 1332 radius_client_disable_pmtu_discovery(radius->acct_serv_sock); 1333 ok++; 1334 } 1335 1336 #ifdef CONFIG_IPV6 1337 radius->acct_serv_sock6 = socket(PF_INET6, SOCK_DGRAM, 0); 1338 if (radius->acct_serv_sock6 < 0) 1339 wpa_printf(MSG_INFO, "RADIUS: socket[PF_INET6,SOCK_DGRAM]: %s", 1340 strerror(errno)); 1341 else 1342 ok++; 1343 #endif /* CONFIG_IPV6 */ 1344 1345 if (ok == 0) 1346 return -1; 1347 1348 radius_change_server(radius, conf->acct_server, NULL, 1349 radius->acct_serv_sock, radius->acct_serv_sock6, 1350 0); 1351 1352 if (radius->acct_serv_sock >= 0 && 1353 eloop_register_read_sock(radius->acct_serv_sock, 1354 radius_client_receive, radius, 1355 (void *) RADIUS_ACCT)) { 1356 wpa_printf(MSG_INFO, "RADIUS: Could not register read socket for accounting server"); 1357 radius_close_acct_sockets(radius); 1358 return -1; 1359 } 1360 1361 #ifdef CONFIG_IPV6 1362 if (radius->acct_serv_sock6 >= 0 && 1363 eloop_register_read_sock(radius->acct_serv_sock6, 1364 radius_client_receive, radius, 1365 (void *) RADIUS_ACCT)) { 1366 wpa_printf(MSG_INFO, "RADIUS: Could not register read socket for accounting server"); 1367 radius_close_acct_sockets(radius); 1368 return -1; 1369 } 1370 #endif /* CONFIG_IPV6 */ 1371 1372 return 0; 1373 } 1374 1375 1376 /** 1377 * radius_client_init - Initialize RADIUS client 1378 * @ctx: Callback context to be used in hostapd_logger() calls 1379 * @conf: RADIUS client configuration (RADIUS servers) 1380 * Returns: Pointer to private RADIUS client context or %NULL on failure 1381 * 1382 * The caller is responsible for keeping the configuration data available for 1383 * the lifetime of the RADIUS client, i.e., until radius_client_deinit() is 1384 * called for the returned context pointer. 1385 */ 1386 struct radius_client_data * 1387 radius_client_init(void *ctx, struct hostapd_radius_servers *conf) 1388 { 1389 struct radius_client_data *radius; 1390 1391 radius = os_zalloc(sizeof(struct radius_client_data)); 1392 if (radius == NULL) 1393 return NULL; 1394 1395 radius->ctx = ctx; 1396 radius->conf = conf; 1397 radius->auth_serv_sock = radius->acct_serv_sock = 1398 radius->auth_serv_sock6 = radius->acct_serv_sock6 = 1399 radius->auth_sock = radius->acct_sock = -1; 1400 1401 if (conf->auth_server && radius_client_init_auth(radius)) { 1402 radius_client_deinit(radius); 1403 return NULL; 1404 } 1405 1406 if (conf->acct_server && radius_client_init_acct(radius)) { 1407 radius_client_deinit(radius); 1408 return NULL; 1409 } 1410 1411 if (conf->retry_primary_interval) 1412 eloop_register_timeout(conf->retry_primary_interval, 0, 1413 radius_retry_primary_timer, radius, 1414 NULL); 1415 1416 return radius; 1417 } 1418 1419 1420 /** 1421 * radius_client_deinit - Deinitialize RADIUS client 1422 * @radius: RADIUS client context from radius_client_init() 1423 */ 1424 void radius_client_deinit(struct radius_client_data *radius) 1425 { 1426 if (!radius) 1427 return; 1428 1429 radius_close_auth_sockets(radius); 1430 radius_close_acct_sockets(radius); 1431 1432 eloop_cancel_timeout(radius_retry_primary_timer, radius, NULL); 1433 1434 radius_client_flush(radius, 0); 1435 os_free(radius->auth_handlers); 1436 os_free(radius->acct_handlers); 1437 os_free(radius); 1438 } 1439 1440 1441 /** 1442 * radius_client_flush_auth - Flush pending RADIUS messages for an address 1443 * @radius: RADIUS client context from radius_client_init() 1444 * @addr: MAC address of the related device 1445 * 1446 * This function can be used to remove pending RADIUS authentication messages 1447 * that are related to a specific device. The addr parameter is matched with 1448 * the one used in radius_client_send() call that was used to transmit the 1449 * authentication request. 1450 */ 1451 void radius_client_flush_auth(struct radius_client_data *radius, 1452 const u8 *addr) 1453 { 1454 struct radius_msg_list *entry, *prev, *tmp; 1455 1456 prev = NULL; 1457 entry = radius->msgs; 1458 while (entry) { 1459 if (entry->msg_type == RADIUS_AUTH && 1460 os_memcmp(entry->addr, addr, ETH_ALEN) == 0) { 1461 hostapd_logger(radius->ctx, addr, 1462 HOSTAPD_MODULE_RADIUS, 1463 HOSTAPD_LEVEL_DEBUG, 1464 "Removing pending RADIUS authentication" 1465 " message for removed client"); 1466 1467 if (prev) 1468 prev->next = entry->next; 1469 else 1470 radius->msgs = entry->next; 1471 1472 tmp = entry; 1473 entry = entry->next; 1474 radius_client_msg_free(tmp); 1475 radius->num_msgs--; 1476 continue; 1477 } 1478 1479 prev = entry; 1480 entry = entry->next; 1481 } 1482 } 1483 1484 1485 static int radius_client_dump_auth_server(char *buf, size_t buflen, 1486 struct hostapd_radius_server *serv, 1487 struct radius_client_data *cli) 1488 { 1489 int pending = 0; 1490 struct radius_msg_list *msg; 1491 char abuf[50]; 1492 1493 if (cli) { 1494 for (msg = cli->msgs; msg; msg = msg->next) { 1495 if (msg->msg_type == RADIUS_AUTH) 1496 pending++; 1497 } 1498 } 1499 1500 return os_snprintf(buf, buflen, 1501 "radiusAuthServerIndex=%d\n" 1502 "radiusAuthServerAddress=%s\n" 1503 "radiusAuthClientServerPortNumber=%d\n" 1504 "radiusAuthClientRoundTripTime=%d\n" 1505 "radiusAuthClientAccessRequests=%u\n" 1506 "radiusAuthClientAccessRetransmissions=%u\n" 1507 "radiusAuthClientAccessAccepts=%u\n" 1508 "radiusAuthClientAccessRejects=%u\n" 1509 "radiusAuthClientAccessChallenges=%u\n" 1510 "radiusAuthClientMalformedAccessResponses=%u\n" 1511 "radiusAuthClientBadAuthenticators=%u\n" 1512 "radiusAuthClientPendingRequests=%u\n" 1513 "radiusAuthClientTimeouts=%u\n" 1514 "radiusAuthClientUnknownTypes=%u\n" 1515 "radiusAuthClientPacketsDropped=%u\n", 1516 serv->index, 1517 hostapd_ip_txt(&serv->addr, abuf, sizeof(abuf)), 1518 serv->port, 1519 serv->round_trip_time, 1520 serv->requests, 1521 serv->retransmissions, 1522 serv->access_accepts, 1523 serv->access_rejects, 1524 serv->access_challenges, 1525 serv->malformed_responses, 1526 serv->bad_authenticators, 1527 pending, 1528 serv->timeouts, 1529 serv->unknown_types, 1530 serv->packets_dropped); 1531 } 1532 1533 1534 static int radius_client_dump_acct_server(char *buf, size_t buflen, 1535 struct hostapd_radius_server *serv, 1536 struct radius_client_data *cli) 1537 { 1538 int pending = 0; 1539 struct radius_msg_list *msg; 1540 char abuf[50]; 1541 1542 if (cli) { 1543 for (msg = cli->msgs; msg; msg = msg->next) { 1544 if (msg->msg_type == RADIUS_ACCT || 1545 msg->msg_type == RADIUS_ACCT_INTERIM) 1546 pending++; 1547 } 1548 } 1549 1550 return os_snprintf(buf, buflen, 1551 "radiusAccServerIndex=%d\n" 1552 "radiusAccServerAddress=%s\n" 1553 "radiusAccClientServerPortNumber=%d\n" 1554 "radiusAccClientRoundTripTime=%d\n" 1555 "radiusAccClientRequests=%u\n" 1556 "radiusAccClientRetransmissions=%u\n" 1557 "radiusAccClientResponses=%u\n" 1558 "radiusAccClientMalformedResponses=%u\n" 1559 "radiusAccClientBadAuthenticators=%u\n" 1560 "radiusAccClientPendingRequests=%u\n" 1561 "radiusAccClientTimeouts=%u\n" 1562 "radiusAccClientUnknownTypes=%u\n" 1563 "radiusAccClientPacketsDropped=%u\n", 1564 serv->index, 1565 hostapd_ip_txt(&serv->addr, abuf, sizeof(abuf)), 1566 serv->port, 1567 serv->round_trip_time, 1568 serv->requests, 1569 serv->retransmissions, 1570 serv->responses, 1571 serv->malformed_responses, 1572 serv->bad_authenticators, 1573 pending, 1574 serv->timeouts, 1575 serv->unknown_types, 1576 serv->packets_dropped); 1577 } 1578 1579 1580 /** 1581 * radius_client_get_mib - Get RADIUS client MIB information 1582 * @radius: RADIUS client context from radius_client_init() 1583 * @buf: Buffer for returning MIB data in text format 1584 * @buflen: Maximum buf length in octets 1585 * Returns: Number of octets written into the buffer 1586 */ 1587 int radius_client_get_mib(struct radius_client_data *radius, char *buf, 1588 size_t buflen) 1589 { 1590 struct hostapd_radius_servers *conf = radius->conf; 1591 int i; 1592 struct hostapd_radius_server *serv; 1593 int count = 0; 1594 1595 if (conf->auth_servers) { 1596 for (i = 0; i < conf->num_auth_servers; i++) { 1597 serv = &conf->auth_servers[i]; 1598 count += radius_client_dump_auth_server( 1599 buf + count, buflen - count, serv, 1600 serv == conf->auth_server ? 1601 radius : NULL); 1602 } 1603 } 1604 1605 if (conf->acct_servers) { 1606 for (i = 0; i < conf->num_acct_servers; i++) { 1607 serv = &conf->acct_servers[i]; 1608 count += radius_client_dump_acct_server( 1609 buf + count, buflen - count, serv, 1610 serv == conf->acct_server ? 1611 radius : NULL); 1612 } 1613 } 1614 1615 return count; 1616 } 1617 1618 1619 void radius_client_reconfig(struct radius_client_data *radius, 1620 struct hostapd_radius_servers *conf) 1621 { 1622 if (radius) 1623 radius->conf = conf; 1624 } 1625