1 /* 2 * RADIUS client 3 * Copyright (c) 2002-2024, 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 #include <fcntl.h> 11 #include <net/if.h> 12 13 #include "common.h" 14 #include "eloop.h" 15 #include "crypto/tls.h" 16 #include "radius.h" 17 #include "radius_client.h" 18 19 /* Defaults for RADIUS retransmit values (exponential backoff) */ 20 21 /** 22 * RADIUS_CLIENT_FIRST_WAIT - RADIUS client timeout for first retry in seconds 23 */ 24 #define RADIUS_CLIENT_FIRST_WAIT 3 25 26 /** 27 * RADIUS_CLIENT_MAX_WAIT - RADIUS client maximum retry timeout in seconds 28 */ 29 #define RADIUS_CLIENT_MAX_WAIT 120 30 31 /** 32 * RADIUS_CLIENT_MAX_FAILOVER - RADIUS client maximum retries 33 * 34 * Maximum number of server failovers before the entry is removed from 35 * retransmit list. 36 */ 37 #define RADIUS_CLIENT_MAX_FAILOVER 3 38 39 /** 40 * RADIUS_CLIENT_MAX_ENTRIES - RADIUS client maximum pending messages 41 * 42 * Maximum number of entries in retransmit list (oldest entries will be 43 * removed, if this limit is exceeded). 44 */ 45 #define RADIUS_CLIENT_MAX_ENTRIES 30 46 47 /** 48 * RADIUS_CLIENT_NUM_FAILOVER - RADIUS client failover point 49 * 50 * The number of failed retry attempts after which the RADIUS server will be 51 * changed (if one of more backup servers are configured). 52 */ 53 #define RADIUS_CLIENT_NUM_FAILOVER 4 54 55 56 /** 57 * struct radius_rx_handler - RADIUS client RX handler 58 * 59 * This data structure is used internally inside the RADIUS client module to 60 * store registered RX handlers. These handlers are registered by calls to 61 * radius_client_register() and unregistered when the RADIUS client is 62 * deinitialized with a call to radius_client_deinit(). 63 */ 64 struct radius_rx_handler { 65 /** 66 * handler - Received RADIUS message handler 67 */ 68 RadiusRxResult (*handler)(struct radius_msg *msg, 69 struct radius_msg *req, 70 const u8 *shared_secret, 71 size_t shared_secret_len, 72 void *data); 73 74 /** 75 * data - Context data for the handler 76 */ 77 void *data; 78 }; 79 80 81 /** 82 * struct radius_msg_list - RADIUS client message retransmit list 83 * 84 * This data structure is used internally inside the RADIUS client module to 85 * store pending RADIUS requests that may still need to be retransmitted. 86 */ 87 struct radius_msg_list { 88 /** 89 * addr - STA/client address 90 * 91 * This is used to find RADIUS messages for the same STA. 92 */ 93 u8 addr[ETH_ALEN]; 94 95 /** 96 * msg - RADIUS message 97 */ 98 struct radius_msg *msg; 99 100 /** 101 * msg_type - Message type 102 */ 103 RadiusType msg_type; 104 105 /** 106 * first_try - Time of the first transmission attempt 107 */ 108 os_time_t first_try; 109 110 /** 111 * next_try - Time for the next transmission attempt 112 */ 113 os_time_t next_try; 114 115 /** 116 * attempts - Number of transmission attempts for one server 117 */ 118 int attempts; 119 120 /** 121 * accu_attempts - Number of accumulated attempts 122 */ 123 int accu_attempts; 124 125 /** 126 * next_wait - Next retransmission wait time in seconds 127 */ 128 int next_wait; 129 130 /** 131 * last_attempt - Time of the last transmission attempt 132 */ 133 struct os_reltime last_attempt; 134 135 /** 136 * shared_secret - Shared secret with the target RADIUS server 137 */ 138 const u8 *shared_secret; 139 140 /** 141 * shared_secret_len - shared_secret length in octets 142 */ 143 size_t shared_secret_len; 144 145 /* TODO: server config with failover to backup server(s) */ 146 147 /** 148 * next - Next message in the list 149 */ 150 struct radius_msg_list *next; 151 }; 152 153 154 /** 155 * struct radius_client_data - Internal RADIUS client data 156 * 157 * This data structure is used internally inside the RADIUS client module. 158 * External users allocate this by calling radius_client_init() and free it by 159 * calling radius_client_deinit(). The pointer to this opaque data is used in 160 * calls to other functions as an identifier for the RADIUS client instance. 161 */ 162 struct radius_client_data { 163 /** 164 * ctx - Context pointer for hostapd_logger() callbacks 165 */ 166 void *ctx; 167 168 /** 169 * conf - RADIUS client configuration (list of RADIUS servers to use) 170 */ 171 struct hostapd_radius_servers *conf; 172 173 /** 174 * auth_sock - Currently used socket for RADIUS authentication server 175 */ 176 int auth_sock; 177 178 /** 179 * auth_tls - Whether current authentication connection uses TLS 180 */ 181 bool auth_tls; 182 183 /** 184 * auth_tls_ready - Whether authentication TLS is ready 185 */ 186 bool auth_tls_ready; 187 188 /** 189 * acct_sock - Currently used socket for RADIUS accounting server 190 */ 191 int acct_sock; 192 193 /** 194 * acct_tls - Whether current accounting connection uses TLS 195 */ 196 bool acct_tls; 197 198 /** 199 * acct_tls_ready - Whether accounting TLS is ready 200 */ 201 bool acct_tls_ready; 202 203 /** 204 * auth_handlers - Authentication message handlers 205 */ 206 struct radius_rx_handler *auth_handlers; 207 208 /** 209 * num_auth_handlers - Number of handlers in auth_handlers 210 */ 211 size_t num_auth_handlers; 212 213 /** 214 * acct_handlers - Accounting message handlers 215 */ 216 struct radius_rx_handler *acct_handlers; 217 218 /** 219 * num_acct_handlers - Number of handlers in acct_handlers 220 */ 221 size_t num_acct_handlers; 222 223 /** 224 * msgs - Pending outgoing RADIUS messages 225 */ 226 struct radius_msg_list *msgs; 227 228 /** 229 * num_msgs - Number of pending messages in the msgs list 230 */ 231 size_t num_msgs; 232 233 /** 234 * next_radius_identifier - Next RADIUS message identifier to use 235 */ 236 u8 next_radius_identifier; 237 238 /** 239 * interim_error_cb - Interim accounting error callback 240 */ 241 void (*interim_error_cb)(const u8 *addr, void *ctx); 242 243 /** 244 * interim_error_cb_ctx - interim_error_cb() context data 245 */ 246 void *interim_error_cb_ctx; 247 248 #ifdef CONFIG_RADIUS_TLS 249 void *tls_ctx; 250 struct tls_connection *auth_tls_conn; 251 struct tls_connection *acct_tls_conn; 252 #endif /* CONFIG_RADIUS_TLS */ 253 }; 254 255 256 static int 257 radius_change_server(struct radius_client_data *radius, 258 struct hostapd_radius_server *nserv, 259 struct hostapd_radius_server *oserv, 260 int auth); 261 static int radius_client_init_acct(struct radius_client_data *radius); 262 static int radius_client_init_auth(struct radius_client_data *radius); 263 static void radius_client_auth_failover(struct radius_client_data *radius); 264 static void radius_client_acct_failover(struct radius_client_data *radius); 265 266 267 static void radius_client_msg_free(struct radius_msg_list *req) 268 { 269 radius_msg_free(req->msg); 270 os_free(req); 271 } 272 273 274 /** 275 * radius_client_register - Register a RADIUS client RX handler 276 * @radius: RADIUS client context from radius_client_init() 277 * @msg_type: RADIUS client type (RADIUS_AUTH or RADIUS_ACCT) 278 * @handler: Handler for received RADIUS messages 279 * @data: Context pointer for handler callbacks 280 * Returns: 0 on success, -1 on failure 281 * 282 * This function is used to register a handler for processing received RADIUS 283 * authentication and accounting messages. The handler() callback function will 284 * be called whenever a RADIUS message is received from the active server. 285 * 286 * There can be multiple registered RADIUS message handlers. The handlers will 287 * be called in order until one of them indicates that it has processed or 288 * queued the message. 289 */ 290 int radius_client_register(struct radius_client_data *radius, 291 RadiusType msg_type, 292 RadiusRxResult (*handler)(struct radius_msg *msg, 293 struct radius_msg *req, 294 const u8 *shared_secret, 295 size_t shared_secret_len, 296 void *data), 297 void *data) 298 { 299 struct radius_rx_handler **handlers, *newh; 300 size_t *num; 301 302 if (msg_type == RADIUS_ACCT) { 303 handlers = &radius->acct_handlers; 304 num = &radius->num_acct_handlers; 305 } else { 306 handlers = &radius->auth_handlers; 307 num = &radius->num_auth_handlers; 308 } 309 310 newh = os_realloc_array(*handlers, *num + 1, 311 sizeof(struct radius_rx_handler)); 312 if (newh == NULL) 313 return -1; 314 315 newh[*num].handler = handler; 316 newh[*num].data = data; 317 (*num)++; 318 *handlers = newh; 319 320 return 0; 321 } 322 323 324 /** 325 * radius_client_set_interim_erro_cb - Register an interim acct error callback 326 * @radius: RADIUS client context from radius_client_init() 327 * @addr: Station address from the failed message 328 * @cb: Handler for interim accounting errors 329 * @ctx: Context pointer for handler callbacks 330 * 331 * This function is used to register a handler for processing failed 332 * transmission attempts of interim accounting update messages. 333 */ 334 void radius_client_set_interim_error_cb(struct radius_client_data *radius, 335 void (*cb)(const u8 *addr, void *ctx), 336 void *ctx) 337 { 338 radius->interim_error_cb = cb; 339 radius->interim_error_cb_ctx = ctx; 340 } 341 342 343 /* 344 * Returns >0 if message queue was flushed (i.e., the message that triggered 345 * the error is not available anymore) 346 */ 347 static int radius_client_handle_send_error(struct radius_client_data *radius, 348 int s, RadiusType msg_type) 349 { 350 #ifndef CONFIG_NATIVE_WINDOWS 351 int _errno = errno; 352 wpa_printf(MSG_INFO, "send[RADIUS,s=%d]: %s", s, strerror(errno)); 353 if (_errno == ENOTCONN || _errno == EDESTADDRREQ || _errno == EINVAL || 354 _errno == EBADF || _errno == ENETUNREACH || _errno == EACCES) { 355 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 356 HOSTAPD_LEVEL_INFO, 357 "Send failed - maybe interface status changed -" 358 " try to connect again"); 359 if (msg_type == RADIUS_ACCT || 360 msg_type == RADIUS_ACCT_INTERIM) { 361 radius_client_init_acct(radius); 362 return 0; 363 } else { 364 radius_client_init_auth(radius); 365 return 1; 366 } 367 } 368 #endif /* CONFIG_NATIVE_WINDOWS */ 369 370 return 0; 371 } 372 373 374 static int radius_client_retransmit(struct radius_client_data *radius, 375 struct radius_msg_list *entry, 376 os_time_t now) 377 { 378 struct hostapd_radius_servers *conf = radius->conf; 379 int s; 380 struct wpabuf *buf; 381 size_t prev_num_msgs; 382 u8 *acct_delay_time; 383 size_t acct_delay_time_len; 384 int num_servers; 385 #ifdef CONFIG_RADIUS_TLS 386 struct wpabuf *out = NULL; 387 struct tls_connection *conn = NULL; 388 bool acct = false; 389 #endif /* CONFIG_RADIUS_TLS */ 390 391 if (entry->msg_type == RADIUS_ACCT || 392 entry->msg_type == RADIUS_ACCT_INTERIM) { 393 #ifdef CONFIG_RADIUS_TLS 394 acct = true; 395 if (radius->acct_tls) 396 conn = radius->acct_tls_conn; 397 #endif /* CONFIG_RADIUS_TLS */ 398 num_servers = conf->num_acct_servers; 399 if (radius->acct_sock < 0) 400 radius_client_init_acct(radius); 401 if (radius->acct_sock < 0 && conf->num_acct_servers > 1) { 402 prev_num_msgs = radius->num_msgs; 403 radius_client_acct_failover(radius); 404 if (prev_num_msgs != radius->num_msgs) 405 return 0; 406 } 407 s = radius->acct_sock; 408 if (entry->attempts == 0) 409 conf->acct_server->requests++; 410 else { 411 conf->acct_server->timeouts++; 412 conf->acct_server->retransmissions++; 413 } 414 } else { 415 #ifdef CONFIG_RADIUS_TLS 416 if (radius->auth_tls) 417 conn = radius->auth_tls_conn; 418 #endif /* CONFIG_RADIUS_TLS */ 419 num_servers = conf->num_auth_servers; 420 if (radius->auth_sock < 0) 421 radius_client_init_auth(radius); 422 if (radius->auth_sock < 0 && conf->num_auth_servers > 1) { 423 prev_num_msgs = radius->num_msgs; 424 radius_client_auth_failover(radius); 425 if (prev_num_msgs != radius->num_msgs) 426 return 0; 427 } 428 s = radius->auth_sock; 429 if (entry->attempts == 0) 430 conf->auth_server->requests++; 431 else { 432 conf->auth_server->timeouts++; 433 conf->auth_server->retransmissions++; 434 } 435 } 436 437 if (entry->msg_type == RADIUS_ACCT_INTERIM) { 438 wpa_printf(MSG_DEBUG, 439 "RADIUS: Failed to transmit interim accounting update to " 440 MACSTR " - drop message and request a new update", 441 MAC2STR(entry->addr)); 442 if (radius->interim_error_cb) 443 radius->interim_error_cb(entry->addr, 444 radius->interim_error_cb_ctx); 445 return 1; 446 } 447 448 if (s < 0) { 449 wpa_printf(MSG_INFO, 450 "RADIUS: No valid socket for retransmission"); 451 return 1; 452 } 453 454 #ifdef CONFIG_RADIUS_TLS 455 if ((acct && radius->acct_tls && !radius->acct_tls_ready) || 456 (!acct && radius->auth_tls && !radius->auth_tls_ready)) { 457 wpa_printf(MSG_DEBUG, 458 "RADIUS: TLS connection not yet ready for TX"); 459 goto not_ready; 460 } 461 #endif /* CONFIG_RADIUS_TLS */ 462 463 if (entry->msg_type == RADIUS_ACCT && 464 radius_msg_get_attr_ptr(entry->msg, RADIUS_ATTR_ACCT_DELAY_TIME, 465 &acct_delay_time, &acct_delay_time_len, 466 NULL) == 0 && 467 acct_delay_time_len == 4) { 468 struct radius_hdr *hdr; 469 u32 delay_time; 470 471 /* 472 * Need to assign a new identifier since attribute contents 473 * changes. 474 */ 475 hdr = radius_msg_get_hdr(entry->msg); 476 hdr->identifier = radius_client_get_id(radius); 477 478 /* Update Acct-Delay-Time to show wait time in queue */ 479 delay_time = now - entry->first_try; 480 WPA_PUT_BE32(acct_delay_time, delay_time); 481 482 wpa_printf(MSG_DEBUG, 483 "RADIUS: Updated Acct-Delay-Time to %u for retransmission", 484 delay_time); 485 radius_msg_finish_acct(entry->msg, entry->shared_secret, 486 entry->shared_secret_len); 487 if (radius->conf->msg_dumps) 488 radius_msg_dump(entry->msg); 489 } 490 491 /* retransmit; remove entry if too many attempts */ 492 if (entry->accu_attempts >= RADIUS_CLIENT_MAX_FAILOVER * 493 RADIUS_CLIENT_NUM_FAILOVER * num_servers) { 494 wpa_printf(MSG_INFO, 495 "RADIUS: Removing un-ACKed message due to too many failed retransmit attempts"); 496 return 1; 497 } 498 499 entry->attempts++; 500 entry->accu_attempts++; 501 hostapd_logger(radius->ctx, entry->addr, HOSTAPD_MODULE_RADIUS, 502 HOSTAPD_LEVEL_DEBUG, "Resending RADIUS message (id=%d)", 503 radius_msg_get_hdr(entry->msg)->identifier); 504 505 os_get_reltime(&entry->last_attempt); 506 buf = radius_msg_get_buf(entry->msg); 507 #ifdef CONFIG_RADIUS_TLS 508 if (conn) { 509 out = tls_connection_encrypt(radius->tls_ctx, conn, buf); 510 if (!out) { 511 wpa_printf(MSG_INFO, 512 "RADIUS: Failed to encrypt RADIUS message (TLS)"); 513 return -1; 514 } 515 wpa_printf(MSG_DEBUG, 516 "RADIUS: TLS encryption of %zu bytes of plaintext to %zu bytes of ciphertext", 517 wpabuf_len(buf), wpabuf_len(out)); 518 buf = out; 519 } 520 #endif /* CONFIG_RADIUS_TLS */ 521 522 wpa_printf(MSG_DEBUG, "RADIUS: Send %zu bytes to the server", 523 wpabuf_len(buf)); 524 if (send(s, wpabuf_head(buf), wpabuf_len(buf), 0) < 0) { 525 if (radius_client_handle_send_error(radius, s, entry->msg_type) 526 > 0) { 527 #ifdef CONFIG_RADIUS_TLS 528 wpabuf_free(out); 529 #endif /* CONFIG_RADIUS_TLS */ 530 return 0; 531 } 532 } 533 #ifdef CONFIG_RADIUS_TLS 534 wpabuf_free(out); 535 536 not_ready: 537 #endif /* CONFIG_RADIUS_TLS */ 538 539 entry->next_try = now + entry->next_wait; 540 entry->next_wait *= 2; 541 if (entry->next_wait > RADIUS_CLIENT_MAX_WAIT) 542 entry->next_wait = RADIUS_CLIENT_MAX_WAIT; 543 544 return 0; 545 } 546 547 548 static void radius_client_timer(void *eloop_ctx, void *timeout_ctx) 549 { 550 struct radius_client_data *radius = eloop_ctx; 551 struct os_reltime now; 552 os_time_t first; 553 struct radius_msg_list *entry, *prev, *tmp; 554 int auth_failover = 0, acct_failover = 0; 555 size_t prev_num_msgs; 556 int s; 557 558 entry = radius->msgs; 559 if (!entry) 560 return; 561 562 os_get_reltime(&now); 563 564 while (entry) { 565 if (now.sec >= entry->next_try) { 566 s = entry->msg_type == RADIUS_AUTH ? radius->auth_sock : 567 radius->acct_sock; 568 if (entry->attempts >= RADIUS_CLIENT_NUM_FAILOVER || 569 (s < 0 && entry->attempts > 0)) { 570 if (entry->msg_type == RADIUS_ACCT || 571 entry->msg_type == RADIUS_ACCT_INTERIM) 572 acct_failover++; 573 else 574 auth_failover++; 575 } 576 } 577 entry = entry->next; 578 } 579 580 if (auth_failover) 581 radius_client_auth_failover(radius); 582 583 if (acct_failover) 584 radius_client_acct_failover(radius); 585 586 entry = radius->msgs; 587 first = 0; 588 589 prev = NULL; 590 while (entry) { 591 prev_num_msgs = radius->num_msgs; 592 if (now.sec >= entry->next_try && 593 radius_client_retransmit(radius, entry, now.sec)) { 594 if (prev) 595 prev->next = entry->next; 596 else 597 radius->msgs = entry->next; 598 599 tmp = entry; 600 entry = entry->next; 601 radius_client_msg_free(tmp); 602 radius->num_msgs--; 603 continue; 604 } 605 606 if (prev_num_msgs != radius->num_msgs) { 607 wpa_printf(MSG_DEBUG, 608 "RADIUS: Message removed from queue - restart from beginning"); 609 entry = radius->msgs; 610 prev = NULL; 611 continue; 612 } 613 614 if (first == 0 || entry->next_try < first) 615 first = entry->next_try; 616 617 prev = entry; 618 entry = entry->next; 619 } 620 621 if (radius->msgs) { 622 if (first < now.sec) 623 first = now.sec; 624 eloop_cancel_timeout(radius_client_timer, radius, NULL); 625 eloop_register_timeout(first - now.sec, 0, 626 radius_client_timer, radius, NULL); 627 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 628 HOSTAPD_LEVEL_DEBUG, "Next RADIUS client " 629 "retransmit in %ld seconds", 630 (long int) (first - now.sec)); 631 } 632 } 633 634 635 static void radius_client_auth_failover(struct radius_client_data *radius) 636 { 637 struct hostapd_radius_servers *conf = radius->conf; 638 struct hostapd_radius_server *next, *old; 639 struct radius_msg_list *entry; 640 char abuf[50]; 641 642 old = conf->auth_server; 643 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 644 HOSTAPD_LEVEL_NOTICE, 645 "No response from Authentication server %s:%d - failover", 646 hostapd_ip_txt(&old->addr, abuf, sizeof(abuf)), 647 old->port); 648 649 for (entry = radius->msgs; entry; entry = entry->next) { 650 if (entry->msg_type == RADIUS_AUTH) 651 old->timeouts++; 652 } 653 654 next = old + 1; 655 if (next > &(conf->auth_servers[conf->num_auth_servers - 1])) 656 next = conf->auth_servers; 657 conf->auth_server = next; 658 radius_change_server(radius, next, old, 1); 659 } 660 661 662 static void radius_client_acct_failover(struct radius_client_data *radius) 663 { 664 struct hostapd_radius_servers *conf = radius->conf; 665 struct hostapd_radius_server *next, *old; 666 struct radius_msg_list *entry; 667 char abuf[50]; 668 669 old = conf->acct_server; 670 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 671 HOSTAPD_LEVEL_NOTICE, 672 "No response from Accounting server %s:%d - failover", 673 hostapd_ip_txt(&old->addr, abuf, sizeof(abuf)), 674 old->port); 675 676 for (entry = radius->msgs; entry; entry = entry->next) { 677 if (entry->msg_type == RADIUS_ACCT || 678 entry->msg_type == RADIUS_ACCT_INTERIM) 679 old->timeouts++; 680 } 681 682 next = old + 1; 683 if (next > &conf->acct_servers[conf->num_acct_servers - 1]) 684 next = conf->acct_servers; 685 conf->acct_server = next; 686 radius_change_server(radius, next, old, 0); 687 } 688 689 690 static void radius_client_update_timeout(struct radius_client_data *radius) 691 { 692 struct os_reltime now; 693 os_time_t first; 694 struct radius_msg_list *entry; 695 696 eloop_cancel_timeout(radius_client_timer, radius, NULL); 697 698 if (radius->msgs == NULL) { 699 return; 700 } 701 702 first = 0; 703 for (entry = radius->msgs; entry; entry = entry->next) { 704 if (first == 0 || entry->next_try < first) 705 first = entry->next_try; 706 } 707 708 os_get_reltime(&now); 709 if (first < now.sec) 710 first = now.sec; 711 eloop_register_timeout(first - now.sec, 0, radius_client_timer, radius, 712 NULL); 713 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 714 HOSTAPD_LEVEL_DEBUG, "Next RADIUS client retransmit in" 715 " %ld seconds", (long int) (first - now.sec)); 716 } 717 718 719 static void radius_client_list_add(struct radius_client_data *radius, 720 struct radius_msg *msg, 721 RadiusType msg_type, 722 const u8 *shared_secret, 723 size_t shared_secret_len, const u8 *addr) 724 { 725 struct radius_msg_list *entry, *prev; 726 727 if (eloop_terminated()) { 728 /* No point in adding entries to retransmit queue since event 729 * loop has already been terminated. */ 730 radius_msg_free(msg); 731 return; 732 } 733 734 entry = os_zalloc(sizeof(*entry)); 735 if (entry == NULL) { 736 wpa_printf(MSG_INFO, "RADIUS: Failed to add packet into retransmit list"); 737 radius_msg_free(msg); 738 return; 739 } 740 741 if (addr) 742 os_memcpy(entry->addr, addr, ETH_ALEN); 743 entry->msg = msg; 744 entry->msg_type = msg_type; 745 entry->shared_secret = shared_secret; 746 entry->shared_secret_len = shared_secret_len; 747 os_get_reltime(&entry->last_attempt); 748 entry->first_try = entry->last_attempt.sec; 749 entry->next_try = entry->first_try + RADIUS_CLIENT_FIRST_WAIT; 750 entry->attempts = 1; 751 entry->accu_attempts = 1; 752 entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2; 753 if (entry->next_wait > RADIUS_CLIENT_MAX_WAIT) 754 entry->next_wait = RADIUS_CLIENT_MAX_WAIT; 755 entry->next = radius->msgs; 756 radius->msgs = entry; 757 radius_client_update_timeout(radius); 758 759 if (radius->num_msgs >= RADIUS_CLIENT_MAX_ENTRIES) { 760 wpa_printf(MSG_INFO, "RADIUS: Removing the oldest un-ACKed packet due to retransmit list limits"); 761 prev = NULL; 762 while (entry->next) { 763 prev = entry; 764 entry = entry->next; 765 } 766 if (prev) { 767 prev->next = NULL; 768 radius_client_msg_free(entry); 769 } 770 } else 771 radius->num_msgs++; 772 } 773 774 775 static int radius_client_disable_pmtu_discovery(int s) 776 { 777 int r = -1; 778 #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) 779 /* Turn off Path MTU discovery on IPv4/UDP sockets. */ 780 int action = IP_PMTUDISC_DONT; 781 r = setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, &action, 782 sizeof(action)); 783 if (r == -1) 784 wpa_printf(MSG_ERROR, "RADIUS: Failed to set IP_MTU_DISCOVER: %s", 785 strerror(errno)); 786 #endif 787 return r; 788 } 789 790 791 static void radius_close_auth_socket(struct radius_client_data *radius) 792 { 793 if (radius->auth_sock >= 0) { 794 #ifdef CONFIG_RADIUS_TLS 795 if (radius->conf->auth_server->tls) 796 eloop_unregister_sock(radius->auth_sock, 797 EVENT_TYPE_WRITE); 798 #endif /* CONFIG_RADIUS_TLS */ 799 eloop_unregister_read_sock(radius->auth_sock); 800 close(radius->auth_sock); 801 radius->auth_sock = -1; 802 } 803 } 804 805 806 static void radius_close_acct_socket(struct radius_client_data *radius) 807 { 808 if (radius->acct_sock >= 0) { 809 #ifdef CONFIG_RADIUS_TLS 810 if (radius->conf->acct_server->tls) 811 eloop_unregister_sock(radius->acct_sock, 812 EVENT_TYPE_WRITE); 813 #endif /* CONFIG_RADIUS_TLS */ 814 eloop_unregister_read_sock(radius->acct_sock); 815 close(radius->acct_sock); 816 radius->acct_sock = -1; 817 } 818 } 819 820 821 /** 822 * radius_client_send - Send a RADIUS request 823 * @radius: RADIUS client context from radius_client_init() 824 * @msg: RADIUS message to be sent 825 * @msg_type: Message type (RADIUS_AUTH, RADIUS_ACCT, RADIUS_ACCT_INTERIM) 826 * @addr: MAC address of the device related to this message or %NULL 827 * Returns: 0 on success, -1 on failure 828 * 829 * This function is used to transmit a RADIUS authentication (RADIUS_AUTH) or 830 * accounting request (RADIUS_ACCT or RADIUS_ACCT_INTERIM). The only difference 831 * between accounting and interim accounting messages is that the interim 832 * message will not be retransmitted. Instead, a callback is used to indicate 833 * that the transmission failed for the specific station @addr so that a new 834 * interim accounting update message can be generated with up-to-date session 835 * data instead of trying to resend old information. 836 * 837 * The message is added on the retransmission queue and will be retransmitted 838 * automatically until a response is received or maximum number of retries 839 * (RADIUS_CLIENT_MAX_FAILOVER * RADIUS_CLIENT_NUM_FAILOVER) is reached. No 840 * such retries are used with RADIUS_ACCT_INTERIM, i.e., such a pending message 841 * is removed from the queue automatically on transmission failure. 842 * 843 * The related device MAC address can be used to identify pending messages that 844 * can be removed with radius_client_flush_auth(). 845 */ 846 int radius_client_send(struct radius_client_data *radius, 847 struct radius_msg *msg, RadiusType msg_type, 848 const u8 *addr) 849 { 850 struct hostapd_radius_servers *conf = radius->conf; 851 const u8 *shared_secret; 852 size_t shared_secret_len; 853 char *name; 854 int s, res; 855 struct wpabuf *buf; 856 #ifdef CONFIG_RADIUS_TLS 857 struct wpabuf *out = NULL; 858 struct tls_connection *conn = NULL; 859 bool acct = false; 860 #endif /* CONFIG_RADIUS_TLS */ 861 862 if (msg_type == RADIUS_ACCT || msg_type == RADIUS_ACCT_INTERIM) { 863 #ifdef CONFIG_RADIUS_TLS 864 acct = true; 865 if (radius->acct_tls) 866 conn = radius->acct_tls_conn; 867 #endif /* CONFIG_RADIUS_TLS */ 868 if (conf->acct_server && radius->acct_sock < 0) 869 radius_client_init_acct(radius); 870 871 if (conf->acct_server == NULL || radius->acct_sock < 0 || 872 conf->acct_server->shared_secret == NULL) { 873 hostapd_logger(radius->ctx, NULL, 874 HOSTAPD_MODULE_RADIUS, 875 HOSTAPD_LEVEL_INFO, 876 "No accounting server configured"); 877 return -1; 878 } 879 shared_secret = conf->acct_server->shared_secret; 880 shared_secret_len = conf->acct_server->shared_secret_len; 881 radius_msg_finish_acct(msg, shared_secret, shared_secret_len); 882 name = "accounting"; 883 s = radius->acct_sock; 884 conf->acct_server->requests++; 885 } else { 886 #ifdef CONFIG_RADIUS_TLS 887 if (radius->auth_tls) 888 conn = radius->auth_tls_conn; 889 #endif /* CONFIG_RADIUS_TLS */ 890 if (conf->auth_server && radius->auth_sock < 0) 891 radius_client_init_auth(radius); 892 893 if (conf->auth_server == NULL || radius->auth_sock < 0 || 894 conf->auth_server->shared_secret == NULL) { 895 hostapd_logger(radius->ctx, NULL, 896 HOSTAPD_MODULE_RADIUS, 897 HOSTAPD_LEVEL_INFO, 898 "No authentication server configured"); 899 return -1; 900 } 901 shared_secret = conf->auth_server->shared_secret; 902 shared_secret_len = conf->auth_server->shared_secret_len; 903 radius_msg_finish(msg, shared_secret, shared_secret_len); 904 name = "authentication"; 905 s = radius->auth_sock; 906 conf->auth_server->requests++; 907 } 908 909 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 910 HOSTAPD_LEVEL_DEBUG, "Sending RADIUS message to %s " 911 "server", name); 912 if (conf->msg_dumps) 913 radius_msg_dump(msg); 914 915 #ifdef CONFIG_RADIUS_TLS 916 if ((acct && radius->acct_tls && !radius->acct_tls_ready) || 917 (!acct && radius->auth_tls && !radius->auth_tls_ready)) { 918 wpa_printf(MSG_DEBUG, 919 "RADIUS: TLS connection not yet ready for TX"); 920 goto skip_send; 921 } 922 #endif /* CONFIG_RADIUS_TLS */ 923 924 buf = radius_msg_get_buf(msg); 925 #ifdef CONFIG_RADIUS_TLS 926 if (conn) { 927 out = tls_connection_encrypt(radius->tls_ctx, conn, buf); 928 if (!out) { 929 wpa_printf(MSG_INFO, 930 "RADIUS: Failed to encrypt RADIUS message (TLS)"); 931 return -1; 932 } 933 wpa_printf(MSG_DEBUG, 934 "RADIUS: TLS encryption of %zu bytes of plaintext to %zu bytes of ciphertext", 935 wpabuf_len(buf), wpabuf_len(out)); 936 buf = out; 937 } 938 #endif /* CONFIG_RADIUS_TLS */ 939 wpa_printf(MSG_DEBUG, "RADIUS: Send %zu bytes to the server", 940 wpabuf_len(buf)); 941 res = send(s, wpabuf_head(buf), wpabuf_len(buf), 0); 942 #ifdef CONFIG_RADIUS_TLS 943 wpabuf_free(out); 944 #endif /* CONFIG_RADIUS_TLS */ 945 if (res < 0) 946 radius_client_handle_send_error(radius, s, msg_type); 947 948 #ifdef CONFIG_RADIUS_TLS 949 skip_send: 950 #endif /* CONFIG_RADIUS_TLS */ 951 radius_client_list_add(radius, msg, msg_type, shared_secret, 952 shared_secret_len, addr); 953 954 return 0; 955 } 956 957 958 #ifdef CONFIG_RADIUS_TLS 959 960 static void radius_client_close_tcp(struct radius_client_data *radius, 961 int sock, RadiusType msg_type) 962 { 963 wpa_printf(MSG_DEBUG, "RADIUS: Closing TCP connection (sock %d)", 964 sock); 965 if (msg_type == RADIUS_ACCT) { 966 radius->acct_tls_ready = false; 967 radius_close_acct_socket(radius); 968 } else { 969 radius->auth_tls_ready = false; 970 radius_close_auth_socket(radius); 971 } 972 } 973 974 975 static void 976 radius_client_process_tls_handshake(struct radius_client_data *radius, 977 int sock, RadiusType msg_type, 978 u8 *buf, size_t len) 979 { 980 struct wpabuf *in, *out = NULL, *appl; 981 struct tls_connection *conn; 982 int res; 983 bool ready = false; 984 985 wpa_printf(MSG_DEBUG, 986 "RADIUS: Process %zu bytes of received TLS handshake message", 987 len); 988 989 if (msg_type == RADIUS_ACCT) 990 conn = radius->acct_tls_conn; 991 else 992 conn = radius->auth_tls_conn; 993 994 in = wpabuf_alloc_copy(buf, len); 995 if (!in) 996 return; 997 998 appl = NULL; 999 out = tls_connection_handshake(radius->tls_ctx, conn, in, &appl); 1000 wpabuf_free(in); 1001 if (!out) { 1002 wpa_printf(MSG_DEBUG, 1003 "RADIUS: Could not generate TLS handshake data"); 1004 goto fail; 1005 } 1006 1007 if (tls_connection_get_failed(radius->tls_ctx, conn)) { 1008 wpa_printf(MSG_INFO, "RADIUS: TLS handshake failed"); 1009 goto fail; 1010 } 1011 1012 if (tls_connection_established(radius->tls_ctx, conn)) { 1013 wpa_printf(MSG_DEBUG, 1014 "RADIUS: TLS connection established (sock=%d)", 1015 sock); 1016 if (msg_type == RADIUS_ACCT) 1017 radius->acct_tls_ready = true; 1018 else 1019 radius->auth_tls_ready = true; 1020 ready = true; 1021 } 1022 1023 wpa_printf(MSG_DEBUG, "RADIUS: Sending %zu bytes of TLS handshake", 1024 wpabuf_len(out)); 1025 res = send(sock, wpabuf_head(out), wpabuf_len(out), 0); 1026 if (res < 0) { 1027 wpa_printf(MSG_INFO, "RADIUS: send: %s", strerror(errno)); 1028 goto fail; 1029 } 1030 if ((size_t) res != wpabuf_len(out)) { 1031 wpa_printf(MSG_INFO, 1032 "RADIUS: Could not send all data for TLS handshake: only %d bytes sent", 1033 res); 1034 goto fail; 1035 } 1036 wpabuf_free(out); 1037 1038 if (ready) { 1039 struct radius_msg_list *entry, *prev, *tmp; 1040 struct os_reltime now; 1041 1042 /* Send all pending message of matching type since the TLS 1043 * tunnel has now been established. */ 1044 1045 os_get_reltime(&now); 1046 1047 entry = radius->msgs; 1048 prev = NULL; 1049 while (entry) { 1050 if (entry->msg_type != msg_type) { 1051 prev = entry; 1052 entry = entry->next; 1053 continue; 1054 } 1055 1056 if (radius_client_retransmit(radius, entry, now.sec)) { 1057 if (prev) 1058 prev->next = entry->next; 1059 else 1060 radius->msgs = entry->next; 1061 1062 tmp = entry; 1063 entry = entry->next; 1064 radius_client_msg_free(tmp); 1065 radius->num_msgs--; 1066 continue; 1067 } 1068 1069 prev = entry; 1070 entry = entry->next; 1071 } 1072 } 1073 1074 return; 1075 1076 fail: 1077 wpabuf_free(out); 1078 tls_connection_deinit(radius->tls_ctx, conn); 1079 if (msg_type == RADIUS_ACCT) 1080 radius->acct_tls_conn = NULL; 1081 else 1082 radius->auth_tls_conn = NULL; 1083 radius_client_close_tcp(radius, sock, msg_type); 1084 } 1085 1086 #endif /* CONFIG_RADIUS_TLS */ 1087 1088 1089 static void radius_client_receive(int sock, void *eloop_ctx, void *sock_ctx) 1090 { 1091 struct radius_client_data *radius = eloop_ctx; 1092 struct hostapd_radius_servers *conf = radius->conf; 1093 RadiusType msg_type = (uintptr_t) sock_ctx; 1094 int len, roundtrip; 1095 unsigned char buf[RADIUS_MAX_MSG_LEN]; 1096 struct msghdr msghdr = {0}; 1097 struct iovec iov; 1098 struct radius_msg *msg; 1099 struct radius_hdr *hdr; 1100 struct radius_rx_handler *handlers; 1101 size_t num_handlers, i; 1102 struct radius_msg_list *req, *prev_req; 1103 struct os_reltime now; 1104 struct hostapd_radius_server *rconf; 1105 int invalid_authenticator = 0; 1106 #ifdef CONFIG_RADIUS_TLS 1107 struct tls_connection *conn = NULL; 1108 bool tls, tls_ready; 1109 #endif /* CONFIG_RADIUS_TLS */ 1110 1111 if (msg_type == RADIUS_ACCT) { 1112 #ifdef CONFIG_RADIUS_TLS 1113 if (radius->acct_tls) 1114 conn = radius->acct_tls_conn; 1115 tls = radius->acct_tls; 1116 tls_ready = radius->acct_tls_ready; 1117 #endif /* CONFIG_RADIUS_TLS */ 1118 handlers = radius->acct_handlers; 1119 num_handlers = radius->num_acct_handlers; 1120 rconf = conf->acct_server; 1121 } else { 1122 #ifdef CONFIG_RADIUS_TLS 1123 if (radius->auth_tls) 1124 conn = radius->auth_tls_conn; 1125 tls = radius->auth_tls; 1126 tls_ready = radius->auth_tls_ready; 1127 #endif /* CONFIG_RADIUS_TLS */ 1128 handlers = radius->auth_handlers; 1129 num_handlers = radius->num_auth_handlers; 1130 rconf = conf->auth_server; 1131 } 1132 1133 iov.iov_base = buf; 1134 iov.iov_len = RADIUS_MAX_MSG_LEN; 1135 msghdr.msg_iov = &iov; 1136 msghdr.msg_iovlen = 1; 1137 msghdr.msg_flags = 0; 1138 len = recvmsg(sock, &msghdr, MSG_DONTWAIT); 1139 if (len < 0) { 1140 wpa_printf(MSG_INFO, "recvmsg[RADIUS]: %s", strerror(errno)); 1141 return; 1142 } 1143 #ifdef CONFIG_RADIUS_TLS 1144 if (tls && len == 0) { 1145 wpa_printf(MSG_DEBUG, "RADIUS: No TCP data available"); 1146 goto close_tcp; 1147 } 1148 1149 if (tls && !tls_ready) { 1150 radius_client_process_tls_handshake(radius, sock, msg_type, 1151 buf, len); 1152 return; 1153 } 1154 1155 if (conn) { 1156 struct wpabuf *out, *in; 1157 1158 in = wpabuf_alloc_copy(buf, len); 1159 if (!in) 1160 return; 1161 wpa_printf(MSG_DEBUG, 1162 "RADIUS: Process %d bytes of encrypted TLS data", 1163 len); 1164 out = tls_connection_decrypt(radius->tls_ctx, conn, in); 1165 wpabuf_free(in); 1166 if (!out) { 1167 wpa_printf(MSG_INFO, 1168 "RADIUS: Failed to decrypt TLS data"); 1169 goto close_tcp; 1170 } 1171 if (wpabuf_len(out) == 0) { 1172 wpa_printf(MSG_DEBUG, 1173 "RADIUS: Full message not yet received - continue waiting for additional TLS data"); 1174 wpabuf_free(out); 1175 return; 1176 } 1177 if (wpabuf_len(out) > RADIUS_MAX_MSG_LEN) { 1178 wpa_printf(MSG_INFO, 1179 "RADIUS: Too long RADIUS message from TLS: %zu", 1180 wpabuf_len(out)); 1181 wpabuf_free(out); 1182 goto close_tcp; 1183 } 1184 os_memcpy(buf, wpabuf_head(out), wpabuf_len(out)); 1185 len = wpabuf_len(out); 1186 wpabuf_free(out); 1187 } 1188 #endif /* CONFIG_RADIUS_TLS */ 1189 1190 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 1191 HOSTAPD_LEVEL_DEBUG, "Received %d bytes from RADIUS " 1192 "server", len); 1193 1194 if (msghdr.msg_flags & MSG_TRUNC) { 1195 wpa_printf(MSG_INFO, "RADIUS: Possibly too long UDP frame for our buffer - dropping it"); 1196 return; 1197 } 1198 1199 msg = radius_msg_parse(buf, len); 1200 if (msg == NULL) { 1201 wpa_printf(MSG_INFO, "RADIUS: Parsing incoming frame failed"); 1202 rconf->malformed_responses++; 1203 return; 1204 } 1205 hdr = radius_msg_get_hdr(msg); 1206 1207 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 1208 HOSTAPD_LEVEL_DEBUG, "Received RADIUS message"); 1209 if (conf->msg_dumps) 1210 radius_msg_dump(msg); 1211 1212 switch (hdr->code) { 1213 case RADIUS_CODE_ACCESS_ACCEPT: 1214 rconf->access_accepts++; 1215 break; 1216 case RADIUS_CODE_ACCESS_REJECT: 1217 rconf->access_rejects++; 1218 break; 1219 case RADIUS_CODE_ACCESS_CHALLENGE: 1220 rconf->access_challenges++; 1221 break; 1222 case RADIUS_CODE_ACCOUNTING_RESPONSE: 1223 rconf->responses++; 1224 break; 1225 } 1226 1227 prev_req = NULL; 1228 req = radius->msgs; 1229 while (req) { 1230 /* TODO: also match by src addr:port of the packet when using 1231 * alternative RADIUS servers (?) */ 1232 if ((req->msg_type == msg_type || 1233 (req->msg_type == RADIUS_ACCT_INTERIM && 1234 msg_type == RADIUS_ACCT)) && 1235 radius_msg_get_hdr(req->msg)->identifier == 1236 hdr->identifier) 1237 break; 1238 1239 prev_req = req; 1240 req = req->next; 1241 } 1242 1243 if (req == NULL) { 1244 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 1245 HOSTAPD_LEVEL_DEBUG, 1246 "No matching RADIUS request found (type=%d " 1247 "id=%d) - dropping packet", 1248 msg_type, hdr->identifier); 1249 goto fail; 1250 } 1251 1252 os_get_reltime(&now); 1253 roundtrip = (now.sec - req->last_attempt.sec) * 100 + 1254 (now.usec - req->last_attempt.usec) / 10000; 1255 hostapd_logger(radius->ctx, req->addr, HOSTAPD_MODULE_RADIUS, 1256 HOSTAPD_LEVEL_DEBUG, 1257 "Received RADIUS packet matched with a pending " 1258 "request, round trip time %d.%02d sec", 1259 roundtrip / 100, roundtrip % 100); 1260 rconf->round_trip_time = roundtrip; 1261 1262 /* Remove ACKed RADIUS packet from retransmit list */ 1263 if (prev_req) 1264 prev_req->next = req->next; 1265 else 1266 radius->msgs = req->next; 1267 radius->num_msgs--; 1268 1269 for (i = 0; i < num_handlers; i++) { 1270 RadiusRxResult res; 1271 res = handlers[i].handler(msg, req->msg, req->shared_secret, 1272 req->shared_secret_len, 1273 handlers[i].data); 1274 switch (res) { 1275 case RADIUS_RX_PROCESSED: 1276 radius_msg_free(msg); 1277 /* fall through */ 1278 case RADIUS_RX_QUEUED: 1279 radius_client_msg_free(req); 1280 return; 1281 case RADIUS_RX_INVALID_AUTHENTICATOR: 1282 invalid_authenticator++; 1283 /* fall through */ 1284 case RADIUS_RX_UNKNOWN: 1285 /* continue with next handler */ 1286 break; 1287 } 1288 } 1289 1290 if (invalid_authenticator) 1291 rconf->bad_authenticators++; 1292 else 1293 rconf->unknown_types++; 1294 hostapd_logger(radius->ctx, req->addr, HOSTAPD_MODULE_RADIUS, 1295 HOSTAPD_LEVEL_DEBUG, "No RADIUS RX handler found " 1296 "(type=%d code=%d id=%d)%s - dropping packet", 1297 msg_type, hdr->code, hdr->identifier, 1298 invalid_authenticator ? " [INVALID AUTHENTICATOR]" : 1299 ""); 1300 radius_client_msg_free(req); 1301 1302 fail: 1303 radius_msg_free(msg); 1304 return; 1305 1306 #ifdef CONFIG_RADIUS_TLS 1307 close_tcp: 1308 radius_client_close_tcp(radius, sock, msg_type); 1309 #endif /* CONFIG_RADIUS_TLS */ 1310 } 1311 1312 1313 #ifdef CONFIG_RADIUS_TLS 1314 static void radius_client_write_ready(int sock, void *eloop_ctx, void *sock_ctx) 1315 { 1316 struct radius_client_data *radius = eloop_ctx; 1317 RadiusType msg_type = (uintptr_t) sock_ctx; 1318 struct tls_connection *conn = NULL; 1319 struct wpabuf *in, *out = NULL, *appl; 1320 int res = -1; 1321 struct tls_connection_params params; 1322 struct hostapd_radius_server *server; 1323 1324 wpa_printf(MSG_DEBUG, "RADIUS: TCP connection established - start TLS handshake (sock=%d)", 1325 sock); 1326 1327 if (msg_type == RADIUS_ACCT) { 1328 eloop_unregister_sock(sock, EVENT_TYPE_WRITE); 1329 eloop_register_read_sock(sock, radius_client_receive, radius, 1330 (void *) RADIUS_ACCT); 1331 if (radius->acct_tls_conn) { 1332 wpa_printf(MSG_DEBUG, 1333 "RADIUS: Deinit previously used TLS connection"); 1334 tls_connection_deinit(radius->tls_ctx, 1335 radius->acct_tls_conn); 1336 radius->acct_tls_conn = NULL; 1337 } 1338 server = radius->conf->acct_server; 1339 } else { 1340 eloop_unregister_sock(sock, EVENT_TYPE_WRITE); 1341 eloop_register_read_sock(sock, radius_client_receive, radius, 1342 (void *) RADIUS_AUTH); 1343 if (radius->auth_tls_conn) { 1344 wpa_printf(MSG_DEBUG, 1345 "RADIUS: Deinit previously used TLS connection"); 1346 tls_connection_deinit(radius->tls_ctx, 1347 radius->auth_tls_conn); 1348 radius->auth_tls_conn = NULL; 1349 } 1350 server = radius->conf->auth_server; 1351 } 1352 1353 if (!server) 1354 goto fail; 1355 1356 conn = tls_connection_init(radius->tls_ctx); 1357 if (!conn) { 1358 wpa_printf(MSG_INFO, 1359 "RADIUS: Failed to initiate TLS connection"); 1360 goto fail; 1361 } 1362 1363 os_memset(¶ms, 0, sizeof(params)); 1364 params.ca_cert = server->ca_cert; 1365 params.client_cert = server->client_cert; 1366 params.private_key = server->private_key; 1367 params.private_key_passwd = server->private_key_passwd; 1368 params.flags = TLS_CONN_DISABLE_TLSv1_0 | TLS_CONN_DISABLE_TLSv1_1; 1369 if (tls_connection_set_params(radius->tls_ctx, conn, ¶ms)) { 1370 wpa_printf(MSG_INFO, 1371 "RADIUS: Failed to set TLS connection parameters"); 1372 goto fail; 1373 } 1374 1375 in = NULL; 1376 appl = NULL; 1377 out = tls_connection_handshake(radius->tls_ctx, conn, in, &appl); 1378 if (!out) { 1379 wpa_printf(MSG_DEBUG, 1380 "RADIUS: Could not generate TLS handshake data"); 1381 goto fail; 1382 } 1383 1384 if (tls_connection_get_failed(radius->tls_ctx, conn)) { 1385 wpa_printf(MSG_INFO, "RADIUS: TLS handshake failed"); 1386 goto fail; 1387 } 1388 1389 wpa_printf(MSG_DEBUG, "RADIUS: Sending %zu bytes of TLS handshake", 1390 wpabuf_len(out)); 1391 res = send(sock, wpabuf_head(out), wpabuf_len(out), 0); 1392 if (res < 0) { 1393 wpa_printf(MSG_INFO, "RADIUS: send: %s", strerror(errno)); 1394 goto fail; 1395 } 1396 if ((size_t) res != wpabuf_len(out)) { 1397 wpa_printf(MSG_INFO, 1398 "RADIUS: Could not send all data for TLS handshake: only %d bytes sent", 1399 res); 1400 goto fail; 1401 } 1402 wpabuf_free(out); 1403 1404 if (msg_type == RADIUS_ACCT) 1405 radius->acct_tls_conn = conn; 1406 else 1407 radius->auth_tls_conn = conn; 1408 return; 1409 1410 fail: 1411 wpa_printf(MSG_INFO, "RADIUS: Failed to perform TLS handshake"); 1412 tls_connection_deinit(radius->tls_ctx, conn); 1413 wpabuf_free(out); 1414 radius_client_close_tcp(radius, sock, msg_type); 1415 } 1416 #endif /* CONFIG_RADIUS_TLS */ 1417 1418 1419 /** 1420 * radius_client_get_id - Get an identifier for a new RADIUS message 1421 * @radius: RADIUS client context from radius_client_init() 1422 * Returns: Allocated identifier 1423 * 1424 * This function is used to fetch a unique (among pending requests) identifier 1425 * for a new RADIUS message. 1426 */ 1427 u8 radius_client_get_id(struct radius_client_data *radius) 1428 { 1429 struct radius_msg_list *entry, *prev, *_remove; 1430 u8 id = radius->next_radius_identifier++; 1431 1432 /* remove entries with matching id from retransmit list to avoid 1433 * using new reply from the RADIUS server with an old request */ 1434 entry = radius->msgs; 1435 prev = NULL; 1436 while (entry) { 1437 if (radius_msg_get_hdr(entry->msg)->identifier == id) { 1438 hostapd_logger(radius->ctx, entry->addr, 1439 HOSTAPD_MODULE_RADIUS, 1440 HOSTAPD_LEVEL_DEBUG, 1441 "Removing pending RADIUS message, " 1442 "since its id (%d) is reused", id); 1443 if (prev) 1444 prev->next = entry->next; 1445 else 1446 radius->msgs = entry->next; 1447 _remove = entry; 1448 } else { 1449 _remove = NULL; 1450 prev = entry; 1451 } 1452 entry = entry->next; 1453 1454 if (_remove) 1455 radius_client_msg_free(_remove); 1456 } 1457 1458 return id; 1459 } 1460 1461 1462 /** 1463 * radius_client_flush - Flush all pending RADIUS client messages 1464 * @radius: RADIUS client context from radius_client_init() 1465 * @only_auth: Whether only authentication messages are removed 1466 */ 1467 void radius_client_flush(struct radius_client_data *radius, int only_auth) 1468 { 1469 struct radius_msg_list *entry, *prev, *tmp; 1470 1471 if (!radius) 1472 return; 1473 1474 prev = NULL; 1475 entry = radius->msgs; 1476 1477 while (entry) { 1478 if (!only_auth || entry->msg_type == RADIUS_AUTH) { 1479 if (prev) 1480 prev->next = entry->next; 1481 else 1482 radius->msgs = entry->next; 1483 1484 tmp = entry; 1485 entry = entry->next; 1486 radius_client_msg_free(tmp); 1487 radius->num_msgs--; 1488 } else { 1489 prev = entry; 1490 entry = entry->next; 1491 } 1492 } 1493 1494 if (radius->msgs == NULL) 1495 eloop_cancel_timeout(radius_client_timer, radius, NULL); 1496 } 1497 1498 1499 static void radius_client_update_acct_msgs(struct radius_client_data *radius, 1500 const u8 *shared_secret, 1501 size_t shared_secret_len) 1502 { 1503 struct radius_msg_list *entry; 1504 1505 if (!radius) 1506 return; 1507 1508 for (entry = radius->msgs; entry; entry = entry->next) { 1509 if (entry->msg_type == RADIUS_ACCT) { 1510 entry->shared_secret = shared_secret; 1511 entry->shared_secret_len = shared_secret_len; 1512 radius_msg_finish_acct(entry->msg, shared_secret, 1513 shared_secret_len); 1514 } 1515 } 1516 } 1517 1518 1519 static int 1520 radius_change_server(struct radius_client_data *radius, 1521 struct hostapd_radius_server *nserv, 1522 struct hostapd_radius_server *oserv, 1523 int auth) 1524 { 1525 struct sockaddr_in serv, claddr; 1526 #ifdef CONFIG_IPV6 1527 struct sockaddr_in6 serv6, claddr6; 1528 #endif /* CONFIG_IPV6 */ 1529 struct sockaddr *addr, *cl_addr; 1530 socklen_t addrlen, claddrlen; 1531 char abuf[50]; 1532 int sel_sock; 1533 struct radius_msg_list *entry; 1534 struct hostapd_radius_servers *conf = radius->conf; 1535 int type = SOCK_DGRAM; 1536 bool tls = nserv->tls; 1537 1538 if (tls) { 1539 #ifdef CONFIG_RADIUS_TLS 1540 type = SOCK_STREAM; 1541 #else /* CONFIG_RADIUS_TLS */ 1542 wpa_printf(MSG_ERROR, "RADIUS: TLS not supported"); 1543 return -1; 1544 #endif /* CONFIG_RADIUS_TLS */ 1545 } 1546 1547 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 1548 HOSTAPD_LEVEL_INFO, 1549 "%s server %s:%d", 1550 auth ? "Authentication" : "Accounting", 1551 hostapd_ip_txt(&nserv->addr, abuf, sizeof(abuf)), 1552 nserv->port); 1553 1554 if (oserv && oserv == nserv) { 1555 /* Reconnect to same server, flush */ 1556 if (auth) 1557 radius_client_flush(radius, 1); 1558 } 1559 1560 if (oserv && oserv != nserv && 1561 (nserv->shared_secret_len != oserv->shared_secret_len || 1562 os_memcmp(nserv->shared_secret, oserv->shared_secret, 1563 nserv->shared_secret_len) != 0)) { 1564 /* Pending RADIUS packets used different shared secret, so 1565 * they need to be modified. Update accounting message 1566 * authenticators here. Authentication messages are removed 1567 * since they would require more changes and the new RADIUS 1568 * server may not be prepared to receive them anyway due to 1569 * missing state information. Client will likely retry 1570 * authentication, so this should not be an issue. */ 1571 if (auth) 1572 radius_client_flush(radius, 1); 1573 else { 1574 radius_client_update_acct_msgs( 1575 radius, nserv->shared_secret, 1576 nserv->shared_secret_len); 1577 } 1578 } 1579 1580 /* Reset retry counters */ 1581 for (entry = radius->msgs; oserv && entry; entry = entry->next) { 1582 if ((auth && entry->msg_type != RADIUS_AUTH) || 1583 (!auth && entry->msg_type != RADIUS_ACCT)) 1584 continue; 1585 entry->next_try = entry->first_try + RADIUS_CLIENT_FIRST_WAIT; 1586 entry->attempts = 0; 1587 entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2; 1588 } 1589 1590 if (radius->msgs) { 1591 eloop_cancel_timeout(radius_client_timer, radius, NULL); 1592 eloop_register_timeout(RADIUS_CLIENT_FIRST_WAIT, 0, 1593 radius_client_timer, radius, NULL); 1594 } 1595 1596 switch (nserv->addr.af) { 1597 case AF_INET: 1598 os_memset(&serv, 0, sizeof(serv)); 1599 serv.sin_family = AF_INET; 1600 serv.sin_addr.s_addr = nserv->addr.u.v4.s_addr; 1601 serv.sin_port = htons(nserv->port); 1602 addr = (struct sockaddr *) &serv; 1603 addrlen = sizeof(serv); 1604 sel_sock = socket(PF_INET, type, 0); 1605 if (sel_sock >= 0) 1606 radius_client_disable_pmtu_discovery(sel_sock); 1607 break; 1608 #ifdef CONFIG_IPV6 1609 case AF_INET6: 1610 os_memset(&serv6, 0, sizeof(serv6)); 1611 serv6.sin6_family = AF_INET6; 1612 os_memcpy(&serv6.sin6_addr, &nserv->addr.u.v6, 1613 sizeof(struct in6_addr)); 1614 serv6.sin6_port = htons(nserv->port); 1615 addr = (struct sockaddr *) &serv6; 1616 addrlen = sizeof(serv6); 1617 sel_sock = socket(PF_INET6, type, 0); 1618 break; 1619 #endif /* CONFIG_IPV6 */ 1620 default: 1621 return -1; 1622 } 1623 1624 if (sel_sock < 0) { 1625 wpa_printf(MSG_INFO, 1626 "RADIUS: Failed to open server socket (af=%d auth=%d)", 1627 nserv->addr.af, auth); 1628 return -1; 1629 } 1630 1631 #ifdef CONFIG_RADIUS_TLS 1632 if (tls && fcntl(sel_sock, F_SETFL, O_NONBLOCK) != 0) { 1633 wpa_printf(MSG_DEBUG, "RADIUS: fnctl(O_NONBLOCK) failed: %s", 1634 strerror(errno)); 1635 close(sel_sock); 1636 return -1; 1637 } 1638 #endif /* CONFIG_RADIUS_TLS */ 1639 1640 #ifdef __linux__ 1641 if (conf->force_client_dev && conf->force_client_dev[0]) { 1642 if (setsockopt(sel_sock, SOL_SOCKET, SO_BINDTODEVICE, 1643 conf->force_client_dev, 1644 os_strlen(conf->force_client_dev)) < 0) { 1645 wpa_printf(MSG_ERROR, 1646 "RADIUS: setsockopt[SO_BINDTODEVICE]: %s", 1647 strerror(errno)); 1648 /* Probably not a critical error; continue on and hope 1649 * for the best. */ 1650 } else { 1651 wpa_printf(MSG_DEBUG, 1652 "RADIUS: Bound client socket to device: %s", 1653 conf->force_client_dev); 1654 } 1655 } 1656 #endif /* __linux__ */ 1657 1658 if (conf->force_client_addr) { 1659 switch (conf->client_addr.af) { 1660 case AF_INET: 1661 os_memset(&claddr, 0, sizeof(claddr)); 1662 claddr.sin_family = AF_INET; 1663 claddr.sin_addr.s_addr = conf->client_addr.u.v4.s_addr; 1664 claddr.sin_port = htons(0); 1665 cl_addr = (struct sockaddr *) &claddr; 1666 claddrlen = sizeof(claddr); 1667 break; 1668 #ifdef CONFIG_IPV6 1669 case AF_INET6: 1670 os_memset(&claddr6, 0, sizeof(claddr6)); 1671 claddr6.sin6_family = AF_INET6; 1672 os_memcpy(&claddr6.sin6_addr, &conf->client_addr.u.v6, 1673 sizeof(struct in6_addr)); 1674 claddr6.sin6_port = htons(0); 1675 cl_addr = (struct sockaddr *) &claddr6; 1676 claddrlen = sizeof(claddr6); 1677 break; 1678 #endif /* CONFIG_IPV6 */ 1679 default: 1680 close(sel_sock); 1681 return -1; 1682 } 1683 1684 if (bind(sel_sock, cl_addr, claddrlen) < 0) { 1685 wpa_printf(MSG_INFO, "bind[radius]: %s", 1686 strerror(errno)); 1687 close(sel_sock); 1688 return -2; 1689 } 1690 } 1691 1692 if (connect(sel_sock, addr, addrlen) < 0) { 1693 if (nserv->tls && errno == EINPROGRESS) { 1694 wpa_printf(MSG_DEBUG, 1695 "RADIUS: TCP connection establishment in progress (sock %d)", 1696 sel_sock); 1697 } else { 1698 wpa_printf(MSG_INFO, "connect[radius]: %s", 1699 strerror(errno)); 1700 close(sel_sock); 1701 return -2; 1702 } 1703 } 1704 1705 #ifndef CONFIG_NATIVE_WINDOWS 1706 switch (nserv->addr.af) { 1707 case AF_INET: 1708 claddrlen = sizeof(claddr); 1709 if (getsockname(sel_sock, (struct sockaddr *) &claddr, 1710 &claddrlen) == 0) { 1711 wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u", 1712 inet_ntoa(claddr.sin_addr), 1713 ntohs(claddr.sin_port)); 1714 } 1715 break; 1716 #ifdef CONFIG_IPV6 1717 case AF_INET6: { 1718 claddrlen = sizeof(claddr6); 1719 if (getsockname(sel_sock, (struct sockaddr *) &claddr6, 1720 &claddrlen) == 0) { 1721 wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u", 1722 inet_ntop(AF_INET6, &claddr6.sin6_addr, 1723 abuf, sizeof(abuf)), 1724 ntohs(claddr6.sin6_port)); 1725 } 1726 break; 1727 } 1728 #endif /* CONFIG_IPV6 */ 1729 } 1730 #endif /* CONFIG_NATIVE_WINDOWS */ 1731 1732 if (auth) { 1733 radius_close_auth_socket(radius); 1734 radius->auth_sock = sel_sock; 1735 } else { 1736 radius_close_acct_socket(radius); 1737 radius->acct_sock = sel_sock; 1738 } 1739 1740 if (!tls) 1741 eloop_register_read_sock(sel_sock, radius_client_receive, 1742 radius, 1743 auth ? (void *) RADIUS_AUTH : 1744 (void *) RADIUS_ACCT); 1745 #ifdef CONFIG_RADIUS_TLS 1746 if (tls) 1747 eloop_register_sock(sel_sock, EVENT_TYPE_WRITE, 1748 radius_client_write_ready, radius, 1749 auth ? (void *) RADIUS_AUTH : 1750 (void *) RADIUS_ACCT); 1751 #endif /* CONFIG_RADIUS_TLS */ 1752 1753 if (auth) { 1754 radius->auth_tls = nserv->tls; 1755 radius->auth_tls_ready = false; 1756 } else { 1757 radius->acct_tls = nserv->tls; 1758 radius->acct_tls_ready = false; 1759 } 1760 1761 return 0; 1762 } 1763 1764 1765 static void radius_retry_primary_timer(void *eloop_ctx, void *timeout_ctx) 1766 { 1767 struct radius_client_data *radius = eloop_ctx; 1768 struct hostapd_radius_servers *conf = radius->conf; 1769 struct hostapd_radius_server *oserv; 1770 1771 if (radius->auth_sock >= 0 && conf->auth_servers && 1772 conf->auth_server != conf->auth_servers) { 1773 oserv = conf->auth_server; 1774 conf->auth_server = conf->auth_servers; 1775 if (radius_change_server(radius, conf->auth_server, oserv, 1776 1) < 0) { 1777 conf->auth_server = oserv; 1778 radius_change_server(radius, oserv, conf->auth_server, 1779 1); 1780 } 1781 } 1782 1783 if (radius->acct_sock >= 0 && conf->acct_servers && 1784 conf->acct_server != conf->acct_servers) { 1785 oserv = conf->acct_server; 1786 conf->acct_server = conf->acct_servers; 1787 if (radius_change_server(radius, conf->acct_server, oserv, 1788 0) < 0) { 1789 conf->acct_server = oserv; 1790 radius_change_server(radius, oserv, conf->acct_server, 1791 0); 1792 } 1793 } 1794 1795 if (conf->retry_primary_interval) 1796 eloop_register_timeout(conf->retry_primary_interval, 0, 1797 radius_retry_primary_timer, radius, 1798 NULL); 1799 } 1800 1801 1802 static int radius_client_init_auth(struct radius_client_data *radius) 1803 { 1804 radius_close_auth_socket(radius); 1805 return radius_change_server(radius, radius->conf->auth_server, NULL, 1); 1806 } 1807 1808 1809 static int radius_client_init_acct(struct radius_client_data *radius) 1810 { 1811 radius_close_acct_socket(radius); 1812 return radius_change_server(radius, radius->conf->acct_server, NULL, 0); 1813 } 1814 1815 1816 #ifdef CONFIG_RADIUS_TLS 1817 static void radius_tls_event_cb(void *ctx, enum tls_event ev, 1818 union tls_event_data *data) 1819 { 1820 wpa_printf(MSG_DEBUG, "RADIUS: TLS event %d", ev); 1821 } 1822 #endif /* CONFIG_RADIUS_TLS */ 1823 1824 1825 /** 1826 * radius_client_init - Initialize RADIUS client 1827 * @ctx: Callback context to be used in hostapd_logger() calls 1828 * @conf: RADIUS client configuration (RADIUS servers) 1829 * Returns: Pointer to private RADIUS client context or %NULL on failure 1830 * 1831 * The caller is responsible for keeping the configuration data available for 1832 * the lifetime of the RADIUS client, i.e., until radius_client_deinit() is 1833 * called for the returned context pointer. 1834 */ 1835 struct radius_client_data * 1836 radius_client_init(void *ctx, struct hostapd_radius_servers *conf) 1837 { 1838 struct radius_client_data *radius; 1839 1840 radius = os_zalloc(sizeof(struct radius_client_data)); 1841 if (radius == NULL) 1842 return NULL; 1843 1844 radius->ctx = ctx; 1845 radius->conf = conf; 1846 radius->auth_sock = radius->acct_sock = -1; 1847 1848 if (conf->auth_server && radius_client_init_auth(radius) == -1) { 1849 radius_client_deinit(radius); 1850 return NULL; 1851 } 1852 1853 if (conf->acct_server && radius_client_init_acct(radius) == -1) { 1854 radius_client_deinit(radius); 1855 return NULL; 1856 } 1857 1858 if (conf->retry_primary_interval) 1859 eloop_register_timeout(conf->retry_primary_interval, 0, 1860 radius_retry_primary_timer, radius, 1861 NULL); 1862 1863 #ifdef CONFIG_RADIUS_TLS 1864 if ((conf->auth_server && conf->auth_server->tls) || 1865 (conf->acct_server && conf->acct_server->tls)) { 1866 struct tls_config tls_conf; 1867 1868 os_memset(&tls_conf, 0, sizeof(tls_conf)); 1869 tls_conf.event_cb = radius_tls_event_cb; 1870 radius->tls_ctx = tls_init(&tls_conf); 1871 if (!radius->tls_ctx) { 1872 radius_client_deinit(radius); 1873 return NULL; 1874 } 1875 } 1876 #endif /* CONFIG_RADIUS_TLS */ 1877 1878 1879 return radius; 1880 } 1881 1882 1883 /** 1884 * radius_client_deinit - Deinitialize RADIUS client 1885 * @radius: RADIUS client context from radius_client_init() 1886 */ 1887 void radius_client_deinit(struct radius_client_data *radius) 1888 { 1889 if (!radius) 1890 return; 1891 1892 radius_close_auth_socket(radius); 1893 radius_close_acct_socket(radius); 1894 1895 eloop_cancel_timeout(radius_retry_primary_timer, radius, NULL); 1896 1897 radius_client_flush(radius, 0); 1898 os_free(radius->auth_handlers); 1899 os_free(radius->acct_handlers); 1900 #ifdef CONFIG_RADIUS_TLS 1901 if (radius->tls_ctx) { 1902 tls_connection_deinit(radius->tls_ctx, radius->auth_tls_conn); 1903 tls_connection_deinit(radius->tls_ctx, radius->acct_tls_conn); 1904 tls_deinit(radius->tls_ctx); 1905 } 1906 #endif /* CONFIG_RADIUS_TLS */ 1907 os_free(radius); 1908 } 1909 1910 1911 /** 1912 * radius_client_flush_auth - Flush pending RADIUS messages for an address 1913 * @radius: RADIUS client context from radius_client_init() 1914 * @addr: MAC address of the related device 1915 * 1916 * This function can be used to remove pending RADIUS authentication messages 1917 * that are related to a specific device. The addr parameter is matched with 1918 * the one used in radius_client_send() call that was used to transmit the 1919 * authentication request. 1920 */ 1921 void radius_client_flush_auth(struct radius_client_data *radius, 1922 const u8 *addr) 1923 { 1924 struct radius_msg_list *entry, *prev, *tmp; 1925 1926 prev = NULL; 1927 entry = radius->msgs; 1928 while (entry) { 1929 if (entry->msg_type == RADIUS_AUTH && 1930 ether_addr_equal(entry->addr, addr)) { 1931 hostapd_logger(radius->ctx, addr, 1932 HOSTAPD_MODULE_RADIUS, 1933 HOSTAPD_LEVEL_DEBUG, 1934 "Removing pending RADIUS authentication" 1935 " message for removed client"); 1936 1937 if (prev) 1938 prev->next = entry->next; 1939 else 1940 radius->msgs = entry->next; 1941 1942 tmp = entry; 1943 entry = entry->next; 1944 radius_client_msg_free(tmp); 1945 radius->num_msgs--; 1946 continue; 1947 } 1948 1949 prev = entry; 1950 entry = entry->next; 1951 } 1952 } 1953 1954 1955 static int radius_client_dump_auth_server(char *buf, size_t buflen, 1956 struct hostapd_radius_server *serv, 1957 struct radius_client_data *cli) 1958 { 1959 int pending = 0; 1960 struct radius_msg_list *msg; 1961 char abuf[50]; 1962 1963 if (cli) { 1964 for (msg = cli->msgs; msg; msg = msg->next) { 1965 if (msg->msg_type == RADIUS_AUTH) 1966 pending++; 1967 } 1968 } 1969 1970 return os_snprintf(buf, buflen, 1971 "radiusAuthServerIndex=%d\n" 1972 "radiusAuthServerAddress=%s\n" 1973 "radiusAuthClientServerPortNumber=%d\n" 1974 "radiusAuthClientRoundTripTime=%d\n" 1975 "radiusAuthClientAccessRequests=%u\n" 1976 "radiusAuthClientAccessRetransmissions=%u\n" 1977 "radiusAuthClientAccessAccepts=%u\n" 1978 "radiusAuthClientAccessRejects=%u\n" 1979 "radiusAuthClientAccessChallenges=%u\n" 1980 "radiusAuthClientMalformedAccessResponses=%u\n" 1981 "radiusAuthClientBadAuthenticators=%u\n" 1982 "radiusAuthClientPendingRequests=%u\n" 1983 "radiusAuthClientTimeouts=%u\n" 1984 "radiusAuthClientUnknownTypes=%u\n" 1985 "radiusAuthClientPacketsDropped=%u\n", 1986 serv->index, 1987 hostapd_ip_txt(&serv->addr, abuf, sizeof(abuf)), 1988 serv->port, 1989 serv->round_trip_time, 1990 serv->requests, 1991 serv->retransmissions, 1992 serv->access_accepts, 1993 serv->access_rejects, 1994 serv->access_challenges, 1995 serv->malformed_responses, 1996 serv->bad_authenticators, 1997 pending, 1998 serv->timeouts, 1999 serv->unknown_types, 2000 serv->packets_dropped); 2001 } 2002 2003 2004 static int radius_client_dump_acct_server(char *buf, size_t buflen, 2005 struct hostapd_radius_server *serv, 2006 struct radius_client_data *cli) 2007 { 2008 int pending = 0; 2009 struct radius_msg_list *msg; 2010 char abuf[50]; 2011 2012 if (cli) { 2013 for (msg = cli->msgs; msg; msg = msg->next) { 2014 if (msg->msg_type == RADIUS_ACCT || 2015 msg->msg_type == RADIUS_ACCT_INTERIM) 2016 pending++; 2017 } 2018 } 2019 2020 return os_snprintf(buf, buflen, 2021 "radiusAccServerIndex=%d\n" 2022 "radiusAccServerAddress=%s\n" 2023 "radiusAccClientServerPortNumber=%d\n" 2024 "radiusAccClientRoundTripTime=%d\n" 2025 "radiusAccClientRequests=%u\n" 2026 "radiusAccClientRetransmissions=%u\n" 2027 "radiusAccClientResponses=%u\n" 2028 "radiusAccClientMalformedResponses=%u\n" 2029 "radiusAccClientBadAuthenticators=%u\n" 2030 "radiusAccClientPendingRequests=%u\n" 2031 "radiusAccClientTimeouts=%u\n" 2032 "radiusAccClientUnknownTypes=%u\n" 2033 "radiusAccClientPacketsDropped=%u\n", 2034 serv->index, 2035 hostapd_ip_txt(&serv->addr, abuf, sizeof(abuf)), 2036 serv->port, 2037 serv->round_trip_time, 2038 serv->requests, 2039 serv->retransmissions, 2040 serv->responses, 2041 serv->malformed_responses, 2042 serv->bad_authenticators, 2043 pending, 2044 serv->timeouts, 2045 serv->unknown_types, 2046 serv->packets_dropped); 2047 } 2048 2049 2050 /** 2051 * radius_client_get_mib - Get RADIUS client MIB information 2052 * @radius: RADIUS client context from radius_client_init() 2053 * @buf: Buffer for returning MIB data in text format 2054 * @buflen: Maximum buf length in octets 2055 * Returns: Number of octets written into the buffer 2056 */ 2057 int radius_client_get_mib(struct radius_client_data *radius, char *buf, 2058 size_t buflen) 2059 { 2060 struct hostapd_radius_servers *conf; 2061 int i; 2062 struct hostapd_radius_server *serv; 2063 int count = 0; 2064 2065 if (!radius) 2066 return 0; 2067 2068 conf = radius->conf; 2069 2070 if (conf->auth_servers) { 2071 for (i = 0; i < conf->num_auth_servers; i++) { 2072 serv = &conf->auth_servers[i]; 2073 count += radius_client_dump_auth_server( 2074 buf + count, buflen - count, serv, 2075 serv == conf->auth_server ? 2076 radius : NULL); 2077 } 2078 } 2079 2080 if (conf->acct_servers) { 2081 for (i = 0; i < conf->num_acct_servers; i++) { 2082 serv = &conf->acct_servers[i]; 2083 count += radius_client_dump_acct_server( 2084 buf + count, buflen - count, serv, 2085 serv == conf->acct_server ? 2086 radius : NULL); 2087 } 2088 } 2089 2090 return count; 2091 } 2092 2093 2094 void radius_client_reconfig(struct radius_client_data *radius, 2095 struct hostapd_radius_servers *conf) 2096 { 2097 if (radius) 2098 radius->conf = conf; 2099 } 2100