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 radius_client_msg_free(struct radius_msg_list * req)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 */ radius_client_register(struct radius_client_data * radius,RadiusType msg_type,RadiusRxResult (* handler)(struct radius_msg * msg,struct radius_msg * req,const u8 * shared_secret,size_t shared_secret_len,void * data),void * data)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 */ radius_client_set_interim_error_cb(struct radius_client_data * radius,void (* cb)(const u8 * addr,void * ctx),void * ctx)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 */ radius_client_handle_send_error(struct radius_client_data * radius,int s,RadiusType msg_type)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 radius_client_retransmit(struct radius_client_data * radius,struct radius_msg_list * entry,os_time_t now)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 if (radius_msg_finish_acct(entry->msg, entry->shared_secret, 486 entry->shared_secret_len) < 0) { 487 wpa_printf(MSG_INFO, "Failed to build RADIUS message"); 488 return -1; 489 } 490 if (radius->conf->msg_dumps) 491 radius_msg_dump(entry->msg); 492 } 493 494 /* retransmit; remove entry if too many attempts */ 495 if (entry->accu_attempts >= RADIUS_CLIENT_MAX_FAILOVER * 496 RADIUS_CLIENT_NUM_FAILOVER * num_servers) { 497 wpa_printf(MSG_INFO, 498 "RADIUS: Removing un-ACKed message due to too many failed retransmit attempts"); 499 return 1; 500 } 501 502 entry->attempts++; 503 entry->accu_attempts++; 504 hostapd_logger(radius->ctx, entry->addr, HOSTAPD_MODULE_RADIUS, 505 HOSTAPD_LEVEL_DEBUG, "Resending RADIUS message (id=%d)", 506 radius_msg_get_hdr(entry->msg)->identifier); 507 508 os_get_reltime(&entry->last_attempt); 509 buf = radius_msg_get_buf(entry->msg); 510 #ifdef CONFIG_RADIUS_TLS 511 if (conn) { 512 out = tls_connection_encrypt(radius->tls_ctx, conn, buf); 513 if (!out) { 514 wpa_printf(MSG_INFO, 515 "RADIUS: Failed to encrypt RADIUS message (TLS)"); 516 return -1; 517 } 518 wpa_printf(MSG_DEBUG, 519 "RADIUS: TLS encryption of %zu bytes of plaintext to %zu bytes of ciphertext", 520 wpabuf_len(buf), wpabuf_len(out)); 521 buf = out; 522 } 523 #endif /* CONFIG_RADIUS_TLS */ 524 525 wpa_printf(MSG_DEBUG, "RADIUS: Send %zu bytes to the server", 526 wpabuf_len(buf)); 527 if (send(s, wpabuf_head(buf), wpabuf_len(buf), 0) < 0) { 528 if (radius_client_handle_send_error(radius, s, entry->msg_type) 529 > 0) { 530 #ifdef CONFIG_RADIUS_TLS 531 wpabuf_free(out); 532 #endif /* CONFIG_RADIUS_TLS */ 533 return 0; 534 } 535 } 536 #ifdef CONFIG_RADIUS_TLS 537 wpabuf_free(out); 538 539 not_ready: 540 #endif /* CONFIG_RADIUS_TLS */ 541 542 entry->next_try = now + entry->next_wait; 543 entry->next_wait *= 2; 544 if (entry->next_wait > RADIUS_CLIENT_MAX_WAIT) 545 entry->next_wait = RADIUS_CLIENT_MAX_WAIT; 546 547 return 0; 548 } 549 550 radius_client_timer(void * eloop_ctx,void * timeout_ctx)551 static void radius_client_timer(void *eloop_ctx, void *timeout_ctx) 552 { 553 struct radius_client_data *radius = eloop_ctx; 554 struct os_reltime now; 555 os_time_t first; 556 struct radius_msg_list *entry, *prev, *tmp; 557 int auth_failover = 0, acct_failover = 0; 558 size_t prev_num_msgs; 559 int s; 560 561 entry = radius->msgs; 562 if (!entry) 563 return; 564 565 os_get_reltime(&now); 566 567 while (entry) { 568 if (now.sec >= entry->next_try) { 569 s = entry->msg_type == RADIUS_AUTH ? radius->auth_sock : 570 radius->acct_sock; 571 if (entry->attempts >= RADIUS_CLIENT_NUM_FAILOVER || 572 (s < 0 && entry->attempts > 0)) { 573 if (entry->msg_type == RADIUS_ACCT || 574 entry->msg_type == RADIUS_ACCT_INTERIM) 575 acct_failover++; 576 else 577 auth_failover++; 578 } 579 } 580 entry = entry->next; 581 } 582 583 if (auth_failover) 584 radius_client_auth_failover(radius); 585 586 if (acct_failover) 587 radius_client_acct_failover(radius); 588 589 entry = radius->msgs; 590 first = 0; 591 592 prev = NULL; 593 while (entry) { 594 prev_num_msgs = radius->num_msgs; 595 if (now.sec >= entry->next_try && 596 radius_client_retransmit(radius, entry, now.sec)) { 597 if (prev) 598 prev->next = entry->next; 599 else 600 radius->msgs = entry->next; 601 602 tmp = entry; 603 entry = entry->next; 604 radius_client_msg_free(tmp); 605 radius->num_msgs--; 606 continue; 607 } 608 609 if (prev_num_msgs != radius->num_msgs) { 610 wpa_printf(MSG_DEBUG, 611 "RADIUS: Message removed from queue - restart from beginning"); 612 entry = radius->msgs; 613 prev = NULL; 614 continue; 615 } 616 617 if (first == 0 || entry->next_try < first) 618 first = entry->next_try; 619 620 prev = entry; 621 entry = entry->next; 622 } 623 624 if (radius->msgs) { 625 if (first < now.sec) 626 first = now.sec; 627 eloop_cancel_timeout(radius_client_timer, radius, NULL); 628 eloop_register_timeout(first - now.sec, 0, 629 radius_client_timer, radius, NULL); 630 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 631 HOSTAPD_LEVEL_DEBUG, "Next RADIUS client " 632 "retransmit in %ld seconds", 633 (long int) (first - now.sec)); 634 } 635 } 636 637 radius_client_auth_failover(struct radius_client_data * radius)638 static void radius_client_auth_failover(struct radius_client_data *radius) 639 { 640 struct hostapd_radius_servers *conf = radius->conf; 641 struct hostapd_radius_server *next, *old; 642 struct radius_msg_list *entry; 643 char abuf[50]; 644 645 old = conf->auth_server; 646 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 647 HOSTAPD_LEVEL_NOTICE, 648 "No response from Authentication server %s:%d - failover", 649 hostapd_ip_txt(&old->addr, abuf, sizeof(abuf)), 650 old->port); 651 652 for (entry = radius->msgs; entry; entry = entry->next) { 653 if (entry->msg_type == RADIUS_AUTH) 654 old->timeouts++; 655 } 656 657 next = old + 1; 658 if (next > &(conf->auth_servers[conf->num_auth_servers - 1])) 659 next = conf->auth_servers; 660 conf->auth_server = next; 661 radius_change_server(radius, next, old, 1); 662 } 663 664 radius_client_acct_failover(struct radius_client_data * radius)665 static void radius_client_acct_failover(struct radius_client_data *radius) 666 { 667 struct hostapd_radius_servers *conf = radius->conf; 668 struct hostapd_radius_server *next, *old; 669 struct radius_msg_list *entry; 670 char abuf[50]; 671 672 old = conf->acct_server; 673 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 674 HOSTAPD_LEVEL_NOTICE, 675 "No response from Accounting server %s:%d - failover", 676 hostapd_ip_txt(&old->addr, abuf, sizeof(abuf)), 677 old->port); 678 679 for (entry = radius->msgs; entry; entry = entry->next) { 680 if (entry->msg_type == RADIUS_ACCT || 681 entry->msg_type == RADIUS_ACCT_INTERIM) 682 old->timeouts++; 683 } 684 685 next = old + 1; 686 if (next > &conf->acct_servers[conf->num_acct_servers - 1]) 687 next = conf->acct_servers; 688 conf->acct_server = next; 689 radius_change_server(radius, next, old, 0); 690 } 691 692 radius_client_update_timeout(struct radius_client_data * radius)693 static void radius_client_update_timeout(struct radius_client_data *radius) 694 { 695 struct os_reltime now; 696 os_time_t first; 697 struct radius_msg_list *entry; 698 699 eloop_cancel_timeout(radius_client_timer, radius, NULL); 700 701 if (radius->msgs == NULL) { 702 return; 703 } 704 705 first = 0; 706 for (entry = radius->msgs; entry; entry = entry->next) { 707 if (first == 0 || entry->next_try < first) 708 first = entry->next_try; 709 } 710 711 os_get_reltime(&now); 712 if (first < now.sec) 713 first = now.sec; 714 eloop_register_timeout(first - now.sec, 0, radius_client_timer, radius, 715 NULL); 716 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 717 HOSTAPD_LEVEL_DEBUG, "Next RADIUS client retransmit in" 718 " %ld seconds", (long int) (first - now.sec)); 719 } 720 721 radius_client_list_add(struct radius_client_data * radius,struct radius_msg * msg,RadiusType msg_type,const u8 * shared_secret,size_t shared_secret_len,const u8 * addr)722 static void radius_client_list_add(struct radius_client_data *radius, 723 struct radius_msg *msg, 724 RadiusType msg_type, 725 const u8 *shared_secret, 726 size_t shared_secret_len, const u8 *addr) 727 { 728 struct radius_msg_list *entry, *prev; 729 730 if (eloop_terminated()) { 731 /* No point in adding entries to retransmit queue since event 732 * loop has already been terminated. */ 733 radius_msg_free(msg); 734 return; 735 } 736 737 entry = os_zalloc(sizeof(*entry)); 738 if (entry == NULL) { 739 wpa_printf(MSG_INFO, "RADIUS: Failed to add packet into retransmit list"); 740 radius_msg_free(msg); 741 return; 742 } 743 744 if (addr) 745 os_memcpy(entry->addr, addr, ETH_ALEN); 746 entry->msg = msg; 747 entry->msg_type = msg_type; 748 entry->shared_secret = shared_secret; 749 entry->shared_secret_len = shared_secret_len; 750 os_get_reltime(&entry->last_attempt); 751 entry->first_try = entry->last_attempt.sec; 752 entry->next_try = entry->first_try + RADIUS_CLIENT_FIRST_WAIT; 753 entry->attempts = 1; 754 entry->accu_attempts = 1; 755 entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2; 756 if (entry->next_wait > RADIUS_CLIENT_MAX_WAIT) 757 entry->next_wait = RADIUS_CLIENT_MAX_WAIT; 758 entry->next = radius->msgs; 759 radius->msgs = entry; 760 radius_client_update_timeout(radius); 761 762 if (radius->num_msgs >= RADIUS_CLIENT_MAX_ENTRIES) { 763 wpa_printf(MSG_INFO, "RADIUS: Removing the oldest un-ACKed packet due to retransmit list limits"); 764 prev = NULL; 765 while (entry->next) { 766 prev = entry; 767 entry = entry->next; 768 } 769 if (prev) { 770 prev->next = NULL; 771 radius_client_msg_free(entry); 772 } 773 } else 774 radius->num_msgs++; 775 } 776 777 radius_client_disable_pmtu_discovery(int s)778 static int radius_client_disable_pmtu_discovery(int s) 779 { 780 int r = -1; 781 #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) 782 /* Turn off Path MTU discovery on IPv4/UDP sockets. */ 783 int action = IP_PMTUDISC_DONT; 784 r = setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, &action, 785 sizeof(action)); 786 if (r == -1) 787 wpa_printf(MSG_ERROR, "RADIUS: Failed to set IP_MTU_DISCOVER: %s", 788 strerror(errno)); 789 #endif 790 return r; 791 } 792 793 radius_close_auth_socket(struct radius_client_data * radius)794 static void radius_close_auth_socket(struct radius_client_data *radius) 795 { 796 if (radius->auth_sock >= 0) { 797 #ifdef CONFIG_RADIUS_TLS 798 if (radius->conf->auth_server->tls) 799 eloop_unregister_sock(radius->auth_sock, 800 EVENT_TYPE_WRITE); 801 #endif /* CONFIG_RADIUS_TLS */ 802 eloop_unregister_read_sock(radius->auth_sock); 803 close(radius->auth_sock); 804 radius->auth_sock = -1; 805 } 806 } 807 808 radius_close_acct_socket(struct radius_client_data * radius)809 static void radius_close_acct_socket(struct radius_client_data *radius) 810 { 811 if (radius->acct_sock >= 0) { 812 #ifdef CONFIG_RADIUS_TLS 813 if (radius->conf->acct_server->tls) 814 eloop_unregister_sock(radius->acct_sock, 815 EVENT_TYPE_WRITE); 816 #endif /* CONFIG_RADIUS_TLS */ 817 eloop_unregister_read_sock(radius->acct_sock); 818 close(radius->acct_sock); 819 radius->acct_sock = -1; 820 } 821 } 822 823 824 /** 825 * radius_client_send - Send a RADIUS request 826 * @radius: RADIUS client context from radius_client_init() 827 * @msg: RADIUS message to be sent 828 * @msg_type: Message type (RADIUS_AUTH, RADIUS_ACCT, RADIUS_ACCT_INTERIM) 829 * @addr: MAC address of the device related to this message or %NULL 830 * Returns: 0 on success, -1 on failure 831 * 832 * This function is used to transmit a RADIUS authentication (RADIUS_AUTH) or 833 * accounting request (RADIUS_ACCT or RADIUS_ACCT_INTERIM). The only difference 834 * between accounting and interim accounting messages is that the interim 835 * message will not be retransmitted. Instead, a callback is used to indicate 836 * that the transmission failed for the specific station @addr so that a new 837 * interim accounting update message can be generated with up-to-date session 838 * data instead of trying to resend old information. 839 * 840 * The message is added on the retransmission queue and will be retransmitted 841 * automatically until a response is received or maximum number of retries 842 * (RADIUS_CLIENT_MAX_FAILOVER * RADIUS_CLIENT_NUM_FAILOVER) is reached. No 843 * such retries are used with RADIUS_ACCT_INTERIM, i.e., such a pending message 844 * is removed from the queue automatically on transmission failure. 845 * 846 * The related device MAC address can be used to identify pending messages that 847 * can be removed with radius_client_flush_auth(). 848 */ radius_client_send(struct radius_client_data * radius,struct radius_msg * msg,RadiusType msg_type,const u8 * addr)849 int radius_client_send(struct radius_client_data *radius, 850 struct radius_msg *msg, RadiusType msg_type, 851 const u8 *addr) 852 { 853 struct hostapd_radius_servers *conf = radius->conf; 854 const u8 *shared_secret; 855 size_t shared_secret_len; 856 char *name; 857 int s, res; 858 struct wpabuf *buf; 859 #ifdef CONFIG_RADIUS_TLS 860 struct wpabuf *out = NULL; 861 struct tls_connection *conn = NULL; 862 bool acct = false; 863 #endif /* CONFIG_RADIUS_TLS */ 864 865 if (msg_type == RADIUS_ACCT || msg_type == RADIUS_ACCT_INTERIM) { 866 #ifdef CONFIG_RADIUS_TLS 867 acct = true; 868 if (radius->acct_tls) 869 conn = radius->acct_tls_conn; 870 #endif /* CONFIG_RADIUS_TLS */ 871 if (conf->acct_server && radius->acct_sock < 0) 872 radius_client_init_acct(radius); 873 874 if (conf->acct_server == NULL || radius->acct_sock < 0 || 875 conf->acct_server->shared_secret == NULL) { 876 hostapd_logger(radius->ctx, NULL, 877 HOSTAPD_MODULE_RADIUS, 878 HOSTAPD_LEVEL_INFO, 879 "No accounting server configured"); 880 return -1; 881 } 882 shared_secret = conf->acct_server->shared_secret; 883 shared_secret_len = conf->acct_server->shared_secret_len; 884 if (radius_msg_finish_acct(msg, shared_secret, 885 shared_secret_len) < 0) { 886 hostapd_logger(radius->ctx, NULL, 887 HOSTAPD_MODULE_RADIUS, 888 HOSTAPD_LEVEL_INFO, 889 "Failed to build RADIUS accounting message"); 890 return -1; 891 } 892 name = "accounting"; 893 s = radius->acct_sock; 894 conf->acct_server->requests++; 895 } else { 896 #ifdef CONFIG_RADIUS_TLS 897 if (radius->auth_tls) 898 conn = radius->auth_tls_conn; 899 #endif /* CONFIG_RADIUS_TLS */ 900 if (conf->auth_server && radius->auth_sock < 0) 901 radius_client_init_auth(radius); 902 903 if (conf->auth_server == NULL || radius->auth_sock < 0 || 904 conf->auth_server->shared_secret == NULL) { 905 hostapd_logger(radius->ctx, NULL, 906 HOSTAPD_MODULE_RADIUS, 907 HOSTAPD_LEVEL_INFO, 908 "No authentication server configured"); 909 return -1; 910 } 911 shared_secret = conf->auth_server->shared_secret; 912 shared_secret_len = conf->auth_server->shared_secret_len; 913 if (radius_msg_finish(msg, shared_secret, shared_secret_len) < 914 0) { 915 hostapd_logger(radius->ctx, NULL, 916 HOSTAPD_MODULE_RADIUS, 917 HOSTAPD_LEVEL_INFO, 918 "Failed to build RADIUS authentication message"); 919 return -1; 920 } 921 name = "authentication"; 922 s = radius->auth_sock; 923 conf->auth_server->requests++; 924 } 925 926 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 927 HOSTAPD_LEVEL_DEBUG, "Sending RADIUS message to %s " 928 "server", name); 929 if (conf->msg_dumps) 930 radius_msg_dump(msg); 931 932 #ifdef CONFIG_RADIUS_TLS 933 if ((acct && radius->acct_tls && !radius->acct_tls_ready) || 934 (!acct && radius->auth_tls && !radius->auth_tls_ready)) { 935 wpa_printf(MSG_DEBUG, 936 "RADIUS: TLS connection not yet ready for TX"); 937 goto skip_send; 938 } 939 #endif /* CONFIG_RADIUS_TLS */ 940 941 buf = radius_msg_get_buf(msg); 942 #ifdef CONFIG_RADIUS_TLS 943 if (conn) { 944 out = tls_connection_encrypt(radius->tls_ctx, conn, buf); 945 if (!out) { 946 wpa_printf(MSG_INFO, 947 "RADIUS: Failed to encrypt RADIUS message (TLS)"); 948 return -1; 949 } 950 wpa_printf(MSG_DEBUG, 951 "RADIUS: TLS encryption of %zu bytes of plaintext to %zu bytes of ciphertext", 952 wpabuf_len(buf), wpabuf_len(out)); 953 buf = out; 954 } 955 #endif /* CONFIG_RADIUS_TLS */ 956 wpa_printf(MSG_DEBUG, "RADIUS: Send %zu bytes to the server", 957 wpabuf_len(buf)); 958 res = send(s, wpabuf_head(buf), wpabuf_len(buf), 0); 959 #ifdef CONFIG_RADIUS_TLS 960 wpabuf_free(out); 961 #endif /* CONFIG_RADIUS_TLS */ 962 if (res < 0) 963 radius_client_handle_send_error(radius, s, msg_type); 964 965 #ifdef CONFIG_RADIUS_TLS 966 skip_send: 967 #endif /* CONFIG_RADIUS_TLS */ 968 radius_client_list_add(radius, msg, msg_type, shared_secret, 969 shared_secret_len, addr); 970 971 return 0; 972 } 973 974 975 #ifdef CONFIG_RADIUS_TLS 976 radius_client_close_tcp(struct radius_client_data * radius,int sock,RadiusType msg_type)977 static void radius_client_close_tcp(struct radius_client_data *radius, 978 int sock, RadiusType msg_type) 979 { 980 wpa_printf(MSG_DEBUG, "RADIUS: Closing TCP connection (sock %d)", 981 sock); 982 if (msg_type == RADIUS_ACCT) { 983 radius->acct_tls_ready = false; 984 radius_close_acct_socket(radius); 985 } else { 986 radius->auth_tls_ready = false; 987 radius_close_auth_socket(radius); 988 } 989 } 990 991 992 static void radius_client_process_tls_handshake(struct radius_client_data * radius,int sock,RadiusType msg_type,u8 * buf,size_t len)993 radius_client_process_tls_handshake(struct radius_client_data *radius, 994 int sock, RadiusType msg_type, 995 u8 *buf, size_t len) 996 { 997 struct wpabuf *in, *out = NULL, *appl; 998 struct tls_connection *conn; 999 int res; 1000 bool ready = false; 1001 1002 wpa_printf(MSG_DEBUG, 1003 "RADIUS: Process %zu bytes of received TLS handshake message", 1004 len); 1005 1006 if (msg_type == RADIUS_ACCT) 1007 conn = radius->acct_tls_conn; 1008 else 1009 conn = radius->auth_tls_conn; 1010 1011 in = wpabuf_alloc_copy(buf, len); 1012 if (!in) 1013 return; 1014 1015 appl = NULL; 1016 out = tls_connection_handshake(radius->tls_ctx, conn, in, &appl); 1017 wpabuf_free(in); 1018 if (!out) { 1019 wpa_printf(MSG_DEBUG, 1020 "RADIUS: Could not generate TLS handshake data"); 1021 goto fail; 1022 } 1023 1024 if (tls_connection_get_failed(radius->tls_ctx, conn)) { 1025 wpa_printf(MSG_INFO, "RADIUS: TLS handshake failed"); 1026 goto fail; 1027 } 1028 1029 if (tls_connection_established(radius->tls_ctx, conn)) { 1030 wpa_printf(MSG_DEBUG, 1031 "RADIUS: TLS connection established (sock=%d)", 1032 sock); 1033 if (msg_type == RADIUS_ACCT) 1034 radius->acct_tls_ready = true; 1035 else 1036 radius->auth_tls_ready = true; 1037 ready = true; 1038 } 1039 1040 wpa_printf(MSG_DEBUG, "RADIUS: Sending %zu bytes of TLS handshake", 1041 wpabuf_len(out)); 1042 res = send(sock, wpabuf_head(out), wpabuf_len(out), 0); 1043 if (res < 0) { 1044 wpa_printf(MSG_INFO, "RADIUS: send: %s", strerror(errno)); 1045 goto fail; 1046 } 1047 if ((size_t) res != wpabuf_len(out)) { 1048 wpa_printf(MSG_INFO, 1049 "RADIUS: Could not send all data for TLS handshake: only %d bytes sent", 1050 res); 1051 goto fail; 1052 } 1053 wpabuf_free(out); 1054 1055 if (ready) { 1056 struct radius_msg_list *entry, *prev, *tmp; 1057 struct os_reltime now; 1058 1059 /* Send all pending message of matching type since the TLS 1060 * tunnel has now been established. */ 1061 1062 os_get_reltime(&now); 1063 1064 entry = radius->msgs; 1065 prev = NULL; 1066 while (entry) { 1067 if (entry->msg_type != msg_type) { 1068 prev = entry; 1069 entry = entry->next; 1070 continue; 1071 } 1072 1073 if (radius_client_retransmit(radius, entry, now.sec)) { 1074 if (prev) 1075 prev->next = entry->next; 1076 else 1077 radius->msgs = entry->next; 1078 1079 tmp = entry; 1080 entry = entry->next; 1081 radius_client_msg_free(tmp); 1082 radius->num_msgs--; 1083 continue; 1084 } 1085 1086 prev = entry; 1087 entry = entry->next; 1088 } 1089 } 1090 1091 return; 1092 1093 fail: 1094 wpabuf_free(out); 1095 tls_connection_deinit(radius->tls_ctx, conn); 1096 if (msg_type == RADIUS_ACCT) 1097 radius->acct_tls_conn = NULL; 1098 else 1099 radius->auth_tls_conn = NULL; 1100 radius_client_close_tcp(radius, sock, msg_type); 1101 } 1102 1103 #endif /* CONFIG_RADIUS_TLS */ 1104 1105 radius_client_receive(int sock,void * eloop_ctx,void * sock_ctx)1106 static void radius_client_receive(int sock, void *eloop_ctx, void *sock_ctx) 1107 { 1108 struct radius_client_data *radius = eloop_ctx; 1109 struct hostapd_radius_servers *conf = radius->conf; 1110 RadiusType msg_type = (uintptr_t) sock_ctx; 1111 int len, roundtrip; 1112 unsigned char buf[RADIUS_MAX_MSG_LEN]; 1113 struct msghdr msghdr = {0}; 1114 struct iovec iov; 1115 struct radius_msg *msg; 1116 struct radius_hdr *hdr; 1117 struct radius_rx_handler *handlers; 1118 size_t num_handlers, i; 1119 struct radius_msg_list *req, *prev_req, *r; 1120 struct os_reltime now; 1121 struct hostapd_radius_server *rconf; 1122 int invalid_authenticator = 0; 1123 #ifdef CONFIG_RADIUS_TLS 1124 struct tls_connection *conn = NULL; 1125 bool tls, tls_ready; 1126 #endif /* CONFIG_RADIUS_TLS */ 1127 1128 if (msg_type == RADIUS_ACCT) { 1129 #ifdef CONFIG_RADIUS_TLS 1130 if (radius->acct_tls) 1131 conn = radius->acct_tls_conn; 1132 tls = radius->acct_tls; 1133 tls_ready = radius->acct_tls_ready; 1134 #endif /* CONFIG_RADIUS_TLS */ 1135 handlers = radius->acct_handlers; 1136 num_handlers = radius->num_acct_handlers; 1137 rconf = conf->acct_server; 1138 } else { 1139 #ifdef CONFIG_RADIUS_TLS 1140 if (radius->auth_tls) 1141 conn = radius->auth_tls_conn; 1142 tls = radius->auth_tls; 1143 tls_ready = radius->auth_tls_ready; 1144 #endif /* CONFIG_RADIUS_TLS */ 1145 handlers = radius->auth_handlers; 1146 num_handlers = radius->num_auth_handlers; 1147 rconf = conf->auth_server; 1148 } 1149 1150 iov.iov_base = buf; 1151 iov.iov_len = RADIUS_MAX_MSG_LEN; 1152 msghdr.msg_iov = &iov; 1153 msghdr.msg_iovlen = 1; 1154 msghdr.msg_flags = 0; 1155 len = recvmsg(sock, &msghdr, MSG_DONTWAIT); 1156 if (len < 0) { 1157 wpa_printf(MSG_INFO, "recvmsg[RADIUS]: %s", strerror(errno)); 1158 return; 1159 } 1160 #ifdef CONFIG_RADIUS_TLS 1161 if (tls && len == 0) { 1162 wpa_printf(MSG_DEBUG, "RADIUS: No TCP data available"); 1163 goto close_tcp; 1164 } 1165 1166 if (tls && !tls_ready) { 1167 radius_client_process_tls_handshake(radius, sock, msg_type, 1168 buf, len); 1169 return; 1170 } 1171 1172 if (conn) { 1173 struct wpabuf *out, *in; 1174 1175 in = wpabuf_alloc_copy(buf, len); 1176 if (!in) 1177 return; 1178 wpa_printf(MSG_DEBUG, 1179 "RADIUS: Process %d bytes of encrypted TLS data", 1180 len); 1181 out = tls_connection_decrypt(radius->tls_ctx, conn, in); 1182 wpabuf_free(in); 1183 if (!out) { 1184 wpa_printf(MSG_INFO, 1185 "RADIUS: Failed to decrypt TLS data"); 1186 goto close_tcp; 1187 } 1188 if (wpabuf_len(out) == 0) { 1189 wpa_printf(MSG_DEBUG, 1190 "RADIUS: Full message not yet received - continue waiting for additional TLS data"); 1191 wpabuf_free(out); 1192 return; 1193 } 1194 if (wpabuf_len(out) > RADIUS_MAX_MSG_LEN) { 1195 wpa_printf(MSG_INFO, 1196 "RADIUS: Too long RADIUS message from TLS: %zu", 1197 wpabuf_len(out)); 1198 wpabuf_free(out); 1199 goto close_tcp; 1200 } 1201 os_memcpy(buf, wpabuf_head(out), wpabuf_len(out)); 1202 len = wpabuf_len(out); 1203 wpabuf_free(out); 1204 } 1205 #endif /* CONFIG_RADIUS_TLS */ 1206 1207 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 1208 HOSTAPD_LEVEL_DEBUG, "Received %d bytes from RADIUS " 1209 "server", len); 1210 1211 if (msghdr.msg_flags & MSG_TRUNC) { 1212 wpa_printf(MSG_INFO, "RADIUS: Possibly too long UDP frame for our buffer - dropping it"); 1213 return; 1214 } 1215 1216 msg = radius_msg_parse(buf, len); 1217 if (msg == NULL) { 1218 wpa_printf(MSG_INFO, "RADIUS: Parsing incoming frame failed"); 1219 rconf->malformed_responses++; 1220 return; 1221 } 1222 hdr = radius_msg_get_hdr(msg); 1223 1224 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 1225 HOSTAPD_LEVEL_DEBUG, "Received RADIUS message"); 1226 if (conf->msg_dumps) 1227 radius_msg_dump(msg); 1228 1229 switch (hdr->code) { 1230 case RADIUS_CODE_ACCESS_ACCEPT: 1231 rconf->access_accepts++; 1232 break; 1233 case RADIUS_CODE_ACCESS_REJECT: 1234 rconf->access_rejects++; 1235 break; 1236 case RADIUS_CODE_ACCESS_CHALLENGE: 1237 rconf->access_challenges++; 1238 break; 1239 case RADIUS_CODE_ACCOUNTING_RESPONSE: 1240 rconf->responses++; 1241 break; 1242 } 1243 1244 req = radius->msgs; 1245 while (req) { 1246 /* TODO: also match by src addr:port of the packet when using 1247 * alternative RADIUS servers (?) */ 1248 if ((req->msg_type == msg_type || 1249 (req->msg_type == RADIUS_ACCT_INTERIM && 1250 msg_type == RADIUS_ACCT)) && 1251 radius_msg_get_hdr(req->msg)->identifier == 1252 hdr->identifier) 1253 break; 1254 1255 req = req->next; 1256 } 1257 1258 if (req == NULL) { 1259 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 1260 HOSTAPD_LEVEL_DEBUG, 1261 "No matching RADIUS request found (type=%d " 1262 "id=%d) - dropping packet", 1263 msg_type, hdr->identifier); 1264 goto fail; 1265 } 1266 1267 os_get_reltime(&now); 1268 roundtrip = (now.sec - req->last_attempt.sec) * 100 + 1269 (now.usec - req->last_attempt.usec) / 10000; 1270 hostapd_logger(radius->ctx, req->addr, HOSTAPD_MODULE_RADIUS, 1271 HOSTAPD_LEVEL_DEBUG, 1272 "Received RADIUS packet matched with a pending " 1273 "request, round trip time %d.%02d sec", 1274 roundtrip / 100, roundtrip % 100); 1275 rconf->round_trip_time = roundtrip; 1276 1277 for (i = 0; i < num_handlers; i++) { 1278 RadiusRxResult res; 1279 res = handlers[i].handler(msg, req->msg, req->shared_secret, 1280 req->shared_secret_len, 1281 handlers[i].data); 1282 switch (res) { 1283 case RADIUS_RX_PROCESSED: 1284 radius_msg_free(msg); 1285 /* fall through */ 1286 case RADIUS_RX_QUEUED: 1287 /* Remove ACKed RADIUS packet from retransmit list */ 1288 prev_req = NULL; 1289 for (r = radius->msgs; r; r = r->next) { 1290 if (r == req) 1291 break; 1292 prev_req = r; 1293 } 1294 if (prev_req) 1295 prev_req->next = req->next; 1296 else 1297 radius->msgs = req->next; 1298 radius->num_msgs--; 1299 1300 radius_client_msg_free(req); 1301 return; 1302 case RADIUS_RX_INVALID_AUTHENTICATOR: 1303 invalid_authenticator++; 1304 /* fall through */ 1305 case RADIUS_RX_UNKNOWN: 1306 /* continue with next handler */ 1307 break; 1308 } 1309 } 1310 1311 if (invalid_authenticator) 1312 rconf->bad_authenticators++; 1313 else 1314 rconf->unknown_types++; 1315 hostapd_logger(radius->ctx, req->addr, HOSTAPD_MODULE_RADIUS, 1316 HOSTAPD_LEVEL_DEBUG, "No RADIUS RX handler found " 1317 "(type=%d code=%d id=%d)%s - dropping packet", 1318 msg_type, hdr->code, hdr->identifier, 1319 invalid_authenticator ? " [INVALID AUTHENTICATOR]" : 1320 ""); 1321 1322 fail: 1323 radius_msg_free(msg); 1324 return; 1325 1326 #ifdef CONFIG_RADIUS_TLS 1327 close_tcp: 1328 radius_client_close_tcp(radius, sock, msg_type); 1329 #endif /* CONFIG_RADIUS_TLS */ 1330 } 1331 1332 1333 #ifdef CONFIG_RADIUS_TLS radius_client_write_ready(int sock,void * eloop_ctx,void * sock_ctx)1334 static void radius_client_write_ready(int sock, void *eloop_ctx, void *sock_ctx) 1335 { 1336 struct radius_client_data *radius = eloop_ctx; 1337 RadiusType msg_type = (uintptr_t) sock_ctx; 1338 struct tls_connection *conn = NULL; 1339 struct wpabuf *in, *out = NULL, *appl; 1340 int res = -1; 1341 struct tls_connection_params params; 1342 struct hostapd_radius_server *server; 1343 1344 wpa_printf(MSG_DEBUG, "RADIUS: TCP connection established - start TLS handshake (sock=%d)", 1345 sock); 1346 1347 if (msg_type == RADIUS_ACCT) { 1348 eloop_unregister_sock(sock, EVENT_TYPE_WRITE); 1349 eloop_register_read_sock(sock, radius_client_receive, radius, 1350 (void *) RADIUS_ACCT); 1351 if (radius->acct_tls_conn) { 1352 wpa_printf(MSG_DEBUG, 1353 "RADIUS: Deinit previously used TLS connection"); 1354 tls_connection_deinit(radius->tls_ctx, 1355 radius->acct_tls_conn); 1356 radius->acct_tls_conn = NULL; 1357 } 1358 server = radius->conf->acct_server; 1359 } else { 1360 eloop_unregister_sock(sock, EVENT_TYPE_WRITE); 1361 eloop_register_read_sock(sock, radius_client_receive, radius, 1362 (void *) RADIUS_AUTH); 1363 if (radius->auth_tls_conn) { 1364 wpa_printf(MSG_DEBUG, 1365 "RADIUS: Deinit previously used TLS connection"); 1366 tls_connection_deinit(radius->tls_ctx, 1367 radius->auth_tls_conn); 1368 radius->auth_tls_conn = NULL; 1369 } 1370 server = radius->conf->auth_server; 1371 } 1372 1373 if (!server) 1374 goto fail; 1375 1376 conn = tls_connection_init(radius->tls_ctx); 1377 if (!conn) { 1378 wpa_printf(MSG_INFO, 1379 "RADIUS: Failed to initiate TLS connection"); 1380 goto fail; 1381 } 1382 1383 os_memset(¶ms, 0, sizeof(params)); 1384 params.ca_cert = server->ca_cert; 1385 params.client_cert = server->client_cert; 1386 params.private_key = server->private_key; 1387 params.private_key_passwd = server->private_key_passwd; 1388 params.flags = TLS_CONN_DISABLE_TLSv1_0 | TLS_CONN_DISABLE_TLSv1_1; 1389 if (tls_connection_set_params(radius->tls_ctx, conn, ¶ms)) { 1390 wpa_printf(MSG_INFO, 1391 "RADIUS: Failed to set TLS connection parameters"); 1392 goto fail; 1393 } 1394 1395 in = NULL; 1396 appl = NULL; 1397 out = tls_connection_handshake(radius->tls_ctx, conn, in, &appl); 1398 if (!out) { 1399 wpa_printf(MSG_DEBUG, 1400 "RADIUS: Could not generate TLS handshake data"); 1401 goto fail; 1402 } 1403 1404 if (tls_connection_get_failed(radius->tls_ctx, conn)) { 1405 wpa_printf(MSG_INFO, "RADIUS: TLS handshake failed"); 1406 goto fail; 1407 } 1408 1409 wpa_printf(MSG_DEBUG, "RADIUS: Sending %zu bytes of TLS handshake", 1410 wpabuf_len(out)); 1411 res = send(sock, wpabuf_head(out), wpabuf_len(out), 0); 1412 if (res < 0) { 1413 wpa_printf(MSG_INFO, "RADIUS: send: %s", strerror(errno)); 1414 goto fail; 1415 } 1416 if ((size_t) res != wpabuf_len(out)) { 1417 wpa_printf(MSG_INFO, 1418 "RADIUS: Could not send all data for TLS handshake: only %d bytes sent", 1419 res); 1420 goto fail; 1421 } 1422 wpabuf_free(out); 1423 1424 if (msg_type == RADIUS_ACCT) 1425 radius->acct_tls_conn = conn; 1426 else 1427 radius->auth_tls_conn = conn; 1428 return; 1429 1430 fail: 1431 wpa_printf(MSG_INFO, "RADIUS: Failed to perform TLS handshake"); 1432 tls_connection_deinit(radius->tls_ctx, conn); 1433 wpabuf_free(out); 1434 radius_client_close_tcp(radius, sock, msg_type); 1435 } 1436 #endif /* CONFIG_RADIUS_TLS */ 1437 1438 1439 /** 1440 * radius_client_get_id - Get an identifier for a new RADIUS message 1441 * @radius: RADIUS client context from radius_client_init() 1442 * Returns: Allocated identifier 1443 * 1444 * This function is used to fetch a unique (among pending requests) identifier 1445 * for a new RADIUS message. 1446 */ radius_client_get_id(struct radius_client_data * radius)1447 u8 radius_client_get_id(struct radius_client_data *radius) 1448 { 1449 struct radius_msg_list *entry, *prev, *_remove; 1450 u8 id = radius->next_radius_identifier++; 1451 1452 /* remove entries with matching id from retransmit list to avoid 1453 * using new reply from the RADIUS server with an old request */ 1454 entry = radius->msgs; 1455 prev = NULL; 1456 while (entry) { 1457 if (radius_msg_get_hdr(entry->msg)->identifier == id) { 1458 hostapd_logger(radius->ctx, entry->addr, 1459 HOSTAPD_MODULE_RADIUS, 1460 HOSTAPD_LEVEL_DEBUG, 1461 "Removing pending RADIUS message, " 1462 "since its id (%d) is reused", id); 1463 if (prev) 1464 prev->next = entry->next; 1465 else 1466 radius->msgs = entry->next; 1467 _remove = entry; 1468 } else { 1469 _remove = NULL; 1470 prev = entry; 1471 } 1472 entry = entry->next; 1473 1474 if (_remove) 1475 radius_client_msg_free(_remove); 1476 } 1477 1478 return id; 1479 } 1480 1481 1482 /** 1483 * radius_client_flush - Flush all pending RADIUS client messages 1484 * @radius: RADIUS client context from radius_client_init() 1485 * @only_auth: Whether only authentication messages are removed 1486 */ radius_client_flush(struct radius_client_data * radius,int only_auth)1487 void radius_client_flush(struct radius_client_data *radius, int only_auth) 1488 { 1489 struct radius_msg_list *entry, *prev, *tmp; 1490 1491 if (!radius) 1492 return; 1493 1494 prev = NULL; 1495 entry = radius->msgs; 1496 1497 while (entry) { 1498 if (!only_auth || entry->msg_type == RADIUS_AUTH) { 1499 if (prev) 1500 prev->next = entry->next; 1501 else 1502 radius->msgs = entry->next; 1503 1504 tmp = entry; 1505 entry = entry->next; 1506 radius_client_msg_free(tmp); 1507 radius->num_msgs--; 1508 } else { 1509 prev = entry; 1510 entry = entry->next; 1511 } 1512 } 1513 1514 if (radius->msgs == NULL) 1515 eloop_cancel_timeout(radius_client_timer, radius, NULL); 1516 } 1517 1518 radius_client_update_acct_msgs(struct radius_client_data * radius,const u8 * shared_secret,size_t shared_secret_len)1519 static void radius_client_update_acct_msgs(struct radius_client_data *radius, 1520 const u8 *shared_secret, 1521 size_t shared_secret_len) 1522 { 1523 struct radius_msg_list *entry; 1524 1525 if (!radius) 1526 return; 1527 1528 for (entry = radius->msgs; entry; entry = entry->next) { 1529 if (entry->msg_type == RADIUS_ACCT) { 1530 entry->shared_secret = shared_secret; 1531 entry->shared_secret_len = shared_secret_len; 1532 if (radius_msg_finish_acct(entry->msg, shared_secret, 1533 shared_secret_len) < 0) 1534 wpa_printf(MSG_INFO, 1535 "RADIUS: Failed to update accounting message"); 1536 } 1537 } 1538 } 1539 1540 1541 static int radius_change_server(struct radius_client_data * radius,struct hostapd_radius_server * nserv,struct hostapd_radius_server * oserv,int auth)1542 radius_change_server(struct radius_client_data *radius, 1543 struct hostapd_radius_server *nserv, 1544 struct hostapd_radius_server *oserv, 1545 int auth) 1546 { 1547 struct sockaddr_in serv, claddr; 1548 #ifdef CONFIG_IPV6 1549 struct sockaddr_in6 serv6, claddr6; 1550 #endif /* CONFIG_IPV6 */ 1551 struct sockaddr *addr, *cl_addr; 1552 socklen_t addrlen, claddrlen; 1553 char abuf[50]; 1554 int sel_sock; 1555 struct radius_msg_list *entry; 1556 struct hostapd_radius_servers *conf = radius->conf; 1557 int type = SOCK_DGRAM; 1558 bool tls = nserv->tls; 1559 1560 if (tls) { 1561 #ifdef CONFIG_RADIUS_TLS 1562 type = SOCK_STREAM; 1563 #else /* CONFIG_RADIUS_TLS */ 1564 wpa_printf(MSG_ERROR, "RADIUS: TLS not supported"); 1565 return -1; 1566 #endif /* CONFIG_RADIUS_TLS */ 1567 } 1568 1569 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 1570 HOSTAPD_LEVEL_INFO, 1571 "%s server %s:%d", 1572 auth ? "Authentication" : "Accounting", 1573 hostapd_ip_txt(&nserv->addr, abuf, sizeof(abuf)), 1574 nserv->port); 1575 1576 if (oserv && oserv == nserv) { 1577 /* Reconnect to same server, flush */ 1578 if (auth) 1579 radius_client_flush(radius, 1); 1580 } 1581 1582 if (oserv && oserv != nserv && 1583 (nserv->shared_secret_len != oserv->shared_secret_len || 1584 os_memcmp(nserv->shared_secret, oserv->shared_secret, 1585 nserv->shared_secret_len) != 0)) { 1586 /* Pending RADIUS packets used different shared secret, so 1587 * they need to be modified. Update accounting message 1588 * authenticators here. Authentication messages are removed 1589 * since they would require more changes and the new RADIUS 1590 * server may not be prepared to receive them anyway due to 1591 * missing state information. Client will likely retry 1592 * authentication, so this should not be an issue. */ 1593 if (auth) 1594 radius_client_flush(radius, 1); 1595 else { 1596 radius_client_update_acct_msgs( 1597 radius, nserv->shared_secret, 1598 nserv->shared_secret_len); 1599 } 1600 } 1601 1602 /* Reset retry counters */ 1603 for (entry = radius->msgs; oserv && entry; entry = entry->next) { 1604 if ((auth && entry->msg_type != RADIUS_AUTH) || 1605 (!auth && entry->msg_type != RADIUS_ACCT)) 1606 continue; 1607 entry->next_try = entry->first_try + RADIUS_CLIENT_FIRST_WAIT; 1608 entry->attempts = 0; 1609 entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2; 1610 } 1611 1612 if (radius->msgs) { 1613 eloop_cancel_timeout(radius_client_timer, radius, NULL); 1614 eloop_register_timeout(RADIUS_CLIENT_FIRST_WAIT, 0, 1615 radius_client_timer, radius, NULL); 1616 } 1617 1618 switch (nserv->addr.af) { 1619 case AF_INET: 1620 os_memset(&serv, 0, sizeof(serv)); 1621 serv.sin_family = AF_INET; 1622 serv.sin_addr.s_addr = nserv->addr.u.v4.s_addr; 1623 serv.sin_port = htons(nserv->port); 1624 addr = (struct sockaddr *) &serv; 1625 addrlen = sizeof(serv); 1626 sel_sock = socket(PF_INET, type, 0); 1627 if (sel_sock >= 0) 1628 radius_client_disable_pmtu_discovery(sel_sock); 1629 break; 1630 #ifdef CONFIG_IPV6 1631 case AF_INET6: 1632 os_memset(&serv6, 0, sizeof(serv6)); 1633 serv6.sin6_family = AF_INET6; 1634 os_memcpy(&serv6.sin6_addr, &nserv->addr.u.v6, 1635 sizeof(struct in6_addr)); 1636 serv6.sin6_port = htons(nserv->port); 1637 addr = (struct sockaddr *) &serv6; 1638 addrlen = sizeof(serv6); 1639 sel_sock = socket(PF_INET6, type, 0); 1640 break; 1641 #endif /* CONFIG_IPV6 */ 1642 default: 1643 return -1; 1644 } 1645 1646 if (sel_sock < 0) { 1647 wpa_printf(MSG_INFO, 1648 "RADIUS: Failed to open server socket (af=%d auth=%d)", 1649 nserv->addr.af, auth); 1650 return -1; 1651 } 1652 1653 #ifdef CONFIG_RADIUS_TLS 1654 if (tls && fcntl(sel_sock, F_SETFL, O_NONBLOCK) != 0) { 1655 wpa_printf(MSG_DEBUG, "RADIUS: fnctl(O_NONBLOCK) failed: %s", 1656 strerror(errno)); 1657 close(sel_sock); 1658 return -1; 1659 } 1660 #endif /* CONFIG_RADIUS_TLS */ 1661 1662 #ifdef __linux__ 1663 if (conf->force_client_dev && conf->force_client_dev[0]) { 1664 if (setsockopt(sel_sock, SOL_SOCKET, SO_BINDTODEVICE, 1665 conf->force_client_dev, 1666 os_strlen(conf->force_client_dev)) < 0) { 1667 wpa_printf(MSG_ERROR, 1668 "RADIUS: setsockopt[SO_BINDTODEVICE]: %s", 1669 strerror(errno)); 1670 /* Probably not a critical error; continue on and hope 1671 * for the best. */ 1672 } else { 1673 wpa_printf(MSG_DEBUG, 1674 "RADIUS: Bound client socket to device: %s", 1675 conf->force_client_dev); 1676 } 1677 } 1678 #endif /* __linux__ */ 1679 1680 if (conf->force_client_addr) { 1681 switch (conf->client_addr.af) { 1682 case AF_INET: 1683 os_memset(&claddr, 0, sizeof(claddr)); 1684 claddr.sin_family = AF_INET; 1685 claddr.sin_addr.s_addr = conf->client_addr.u.v4.s_addr; 1686 claddr.sin_port = htons(0); 1687 cl_addr = (struct sockaddr *) &claddr; 1688 claddrlen = sizeof(claddr); 1689 break; 1690 #ifdef CONFIG_IPV6 1691 case AF_INET6: 1692 os_memset(&claddr6, 0, sizeof(claddr6)); 1693 claddr6.sin6_family = AF_INET6; 1694 os_memcpy(&claddr6.sin6_addr, &conf->client_addr.u.v6, 1695 sizeof(struct in6_addr)); 1696 claddr6.sin6_port = htons(0); 1697 cl_addr = (struct sockaddr *) &claddr6; 1698 claddrlen = sizeof(claddr6); 1699 break; 1700 #endif /* CONFIG_IPV6 */ 1701 default: 1702 close(sel_sock); 1703 return -1; 1704 } 1705 1706 if (bind(sel_sock, cl_addr, claddrlen) < 0) { 1707 wpa_printf(MSG_INFO, "bind[radius]: %s", 1708 strerror(errno)); 1709 close(sel_sock); 1710 return -2; 1711 } 1712 } 1713 1714 if (connect(sel_sock, addr, addrlen) < 0) { 1715 if (nserv->tls && errno == EINPROGRESS) { 1716 wpa_printf(MSG_DEBUG, 1717 "RADIUS: TCP connection establishment in progress (sock %d)", 1718 sel_sock); 1719 } else { 1720 wpa_printf(MSG_INFO, "connect[radius]: %s", 1721 strerror(errno)); 1722 close(sel_sock); 1723 return -2; 1724 } 1725 } 1726 1727 #ifndef CONFIG_NATIVE_WINDOWS 1728 switch (nserv->addr.af) { 1729 case AF_INET: 1730 claddrlen = sizeof(claddr); 1731 if (getsockname(sel_sock, (struct sockaddr *) &claddr, 1732 &claddrlen) == 0) { 1733 wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u", 1734 inet_ntoa(claddr.sin_addr), 1735 ntohs(claddr.sin_port)); 1736 } 1737 break; 1738 #ifdef CONFIG_IPV6 1739 case AF_INET6: { 1740 claddrlen = sizeof(claddr6); 1741 if (getsockname(sel_sock, (struct sockaddr *) &claddr6, 1742 &claddrlen) == 0) { 1743 wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u", 1744 inet_ntop(AF_INET6, &claddr6.sin6_addr, 1745 abuf, sizeof(abuf)), 1746 ntohs(claddr6.sin6_port)); 1747 } 1748 break; 1749 } 1750 #endif /* CONFIG_IPV6 */ 1751 } 1752 #endif /* CONFIG_NATIVE_WINDOWS */ 1753 1754 if (auth) { 1755 radius_close_auth_socket(radius); 1756 radius->auth_sock = sel_sock; 1757 } else { 1758 radius_close_acct_socket(radius); 1759 radius->acct_sock = sel_sock; 1760 } 1761 1762 if (!tls) 1763 eloop_register_read_sock(sel_sock, radius_client_receive, 1764 radius, 1765 auth ? (void *) RADIUS_AUTH : 1766 (void *) RADIUS_ACCT); 1767 #ifdef CONFIG_RADIUS_TLS 1768 if (tls) 1769 eloop_register_sock(sel_sock, EVENT_TYPE_WRITE, 1770 radius_client_write_ready, radius, 1771 auth ? (void *) RADIUS_AUTH : 1772 (void *) RADIUS_ACCT); 1773 #endif /* CONFIG_RADIUS_TLS */ 1774 1775 if (auth) { 1776 radius->auth_tls = nserv->tls; 1777 radius->auth_tls_ready = false; 1778 } else { 1779 radius->acct_tls = nserv->tls; 1780 radius->acct_tls_ready = false; 1781 } 1782 1783 return 0; 1784 } 1785 1786 radius_retry_primary_timer(void * eloop_ctx,void * timeout_ctx)1787 static void radius_retry_primary_timer(void *eloop_ctx, void *timeout_ctx) 1788 { 1789 struct radius_client_data *radius = eloop_ctx; 1790 struct hostapd_radius_servers *conf = radius->conf; 1791 struct hostapd_radius_server *oserv; 1792 1793 if (radius->auth_sock >= 0 && conf->auth_servers && 1794 conf->auth_server != conf->auth_servers) { 1795 oserv = conf->auth_server; 1796 conf->auth_server = conf->auth_servers; 1797 if (radius_change_server(radius, conf->auth_server, oserv, 1798 1) < 0) { 1799 conf->auth_server = oserv; 1800 radius_change_server(radius, oserv, conf->auth_server, 1801 1); 1802 } 1803 } 1804 1805 if (radius->acct_sock >= 0 && conf->acct_servers && 1806 conf->acct_server != conf->acct_servers) { 1807 oserv = conf->acct_server; 1808 conf->acct_server = conf->acct_servers; 1809 if (radius_change_server(radius, conf->acct_server, oserv, 1810 0) < 0) { 1811 conf->acct_server = oserv; 1812 radius_change_server(radius, oserv, conf->acct_server, 1813 0); 1814 } 1815 } 1816 1817 if (conf->retry_primary_interval) 1818 eloop_register_timeout(conf->retry_primary_interval, 0, 1819 radius_retry_primary_timer, radius, 1820 NULL); 1821 } 1822 1823 radius_client_init_auth(struct radius_client_data * radius)1824 static int radius_client_init_auth(struct radius_client_data *radius) 1825 { 1826 radius_close_auth_socket(radius); 1827 return radius_change_server(radius, radius->conf->auth_server, NULL, 1); 1828 } 1829 1830 radius_client_init_acct(struct radius_client_data * radius)1831 static int radius_client_init_acct(struct radius_client_data *radius) 1832 { 1833 radius_close_acct_socket(radius); 1834 return radius_change_server(radius, radius->conf->acct_server, NULL, 0); 1835 } 1836 1837 1838 #ifdef CONFIG_RADIUS_TLS radius_tls_event_cb(void * ctx,enum tls_event ev,union tls_event_data * data)1839 static void radius_tls_event_cb(void *ctx, enum tls_event ev, 1840 union tls_event_data *data) 1841 { 1842 wpa_printf(MSG_DEBUG, "RADIUS: TLS event %d", ev); 1843 } 1844 #endif /* CONFIG_RADIUS_TLS */ 1845 1846 1847 /** 1848 * radius_client_init - Initialize RADIUS client 1849 * @ctx: Callback context to be used in hostapd_logger() calls 1850 * @conf: RADIUS client configuration (RADIUS servers) 1851 * Returns: Pointer to private RADIUS client context or %NULL on failure 1852 * 1853 * The caller is responsible for keeping the configuration data available for 1854 * the lifetime of the RADIUS client, i.e., until radius_client_deinit() is 1855 * called for the returned context pointer. 1856 */ 1857 struct radius_client_data * radius_client_init(void * ctx,struct hostapd_radius_servers * conf)1858 radius_client_init(void *ctx, struct hostapd_radius_servers *conf) 1859 { 1860 struct radius_client_data *radius; 1861 1862 radius = os_zalloc(sizeof(struct radius_client_data)); 1863 if (radius == NULL) 1864 return NULL; 1865 1866 radius->ctx = ctx; 1867 radius->conf = conf; 1868 radius->auth_sock = radius->acct_sock = -1; 1869 1870 if (conf->auth_server && radius_client_init_auth(radius) == -1) { 1871 radius_client_deinit(radius); 1872 return NULL; 1873 } 1874 1875 if (conf->acct_server && radius_client_init_acct(radius) == -1) { 1876 radius_client_deinit(radius); 1877 return NULL; 1878 } 1879 1880 if (conf->retry_primary_interval) 1881 eloop_register_timeout(conf->retry_primary_interval, 0, 1882 radius_retry_primary_timer, radius, 1883 NULL); 1884 1885 #ifdef CONFIG_RADIUS_TLS 1886 if ((conf->auth_server && conf->auth_server->tls) || 1887 (conf->acct_server && conf->acct_server->tls)) { 1888 struct tls_config tls_conf; 1889 1890 os_memset(&tls_conf, 0, sizeof(tls_conf)); 1891 tls_conf.event_cb = radius_tls_event_cb; 1892 radius->tls_ctx = tls_init(&tls_conf); 1893 if (!radius->tls_ctx) { 1894 radius_client_deinit(radius); 1895 return NULL; 1896 } 1897 } 1898 #endif /* CONFIG_RADIUS_TLS */ 1899 1900 1901 return radius; 1902 } 1903 1904 1905 /** 1906 * radius_client_deinit - Deinitialize RADIUS client 1907 * @radius: RADIUS client context from radius_client_init() 1908 */ radius_client_deinit(struct radius_client_data * radius)1909 void radius_client_deinit(struct radius_client_data *radius) 1910 { 1911 if (!radius) 1912 return; 1913 1914 radius_close_auth_socket(radius); 1915 radius_close_acct_socket(radius); 1916 1917 eloop_cancel_timeout(radius_retry_primary_timer, radius, NULL); 1918 1919 radius_client_flush(radius, 0); 1920 os_free(radius->auth_handlers); 1921 os_free(radius->acct_handlers); 1922 #ifdef CONFIG_RADIUS_TLS 1923 if (radius->tls_ctx) { 1924 tls_connection_deinit(radius->tls_ctx, radius->auth_tls_conn); 1925 tls_connection_deinit(radius->tls_ctx, radius->acct_tls_conn); 1926 tls_deinit(radius->tls_ctx); 1927 } 1928 #endif /* CONFIG_RADIUS_TLS */ 1929 os_free(radius); 1930 } 1931 1932 1933 /** 1934 * radius_client_flush_auth - Flush pending RADIUS messages for an address 1935 * @radius: RADIUS client context from radius_client_init() 1936 * @addr: MAC address of the related device 1937 * 1938 * This function can be used to remove pending RADIUS authentication messages 1939 * that are related to a specific device. The addr parameter is matched with 1940 * the one used in radius_client_send() call that was used to transmit the 1941 * authentication request. 1942 */ radius_client_flush_auth(struct radius_client_data * radius,const u8 * addr)1943 void radius_client_flush_auth(struct radius_client_data *radius, 1944 const u8 *addr) 1945 { 1946 struct radius_msg_list *entry, *prev, *tmp; 1947 1948 prev = NULL; 1949 entry = radius->msgs; 1950 while (entry) { 1951 if (entry->msg_type == RADIUS_AUTH && 1952 ether_addr_equal(entry->addr, addr)) { 1953 hostapd_logger(radius->ctx, addr, 1954 HOSTAPD_MODULE_RADIUS, 1955 HOSTAPD_LEVEL_DEBUG, 1956 "Removing pending RADIUS authentication" 1957 " message for removed client"); 1958 1959 if (prev) 1960 prev->next = entry->next; 1961 else 1962 radius->msgs = entry->next; 1963 1964 tmp = entry; 1965 entry = entry->next; 1966 radius_client_msg_free(tmp); 1967 radius->num_msgs--; 1968 continue; 1969 } 1970 1971 prev = entry; 1972 entry = entry->next; 1973 } 1974 } 1975 1976 radius_client_dump_auth_server(char * buf,size_t buflen,struct hostapd_radius_server * serv,struct radius_client_data * cli)1977 static int radius_client_dump_auth_server(char *buf, size_t buflen, 1978 struct hostapd_radius_server *serv, 1979 struct radius_client_data *cli) 1980 { 1981 int pending = 0; 1982 struct radius_msg_list *msg; 1983 char abuf[50]; 1984 1985 if (cli) { 1986 for (msg = cli->msgs; msg; msg = msg->next) { 1987 if (msg->msg_type == RADIUS_AUTH) 1988 pending++; 1989 } 1990 } 1991 1992 return os_snprintf(buf, buflen, 1993 "radiusAuthServerIndex=%d\n" 1994 "radiusAuthServerAddress=%s\n" 1995 "radiusAuthClientServerPortNumber=%d\n" 1996 "radiusAuthClientRoundTripTime=%d\n" 1997 "radiusAuthClientAccessRequests=%u\n" 1998 "radiusAuthClientAccessRetransmissions=%u\n" 1999 "radiusAuthClientAccessAccepts=%u\n" 2000 "radiusAuthClientAccessRejects=%u\n" 2001 "radiusAuthClientAccessChallenges=%u\n" 2002 "radiusAuthClientMalformedAccessResponses=%u\n" 2003 "radiusAuthClientBadAuthenticators=%u\n" 2004 "radiusAuthClientPendingRequests=%u\n" 2005 "radiusAuthClientTimeouts=%u\n" 2006 "radiusAuthClientUnknownTypes=%u\n" 2007 "radiusAuthClientPacketsDropped=%u\n", 2008 serv->index, 2009 hostapd_ip_txt(&serv->addr, abuf, sizeof(abuf)), 2010 serv->port, 2011 serv->round_trip_time, 2012 serv->requests, 2013 serv->retransmissions, 2014 serv->access_accepts, 2015 serv->access_rejects, 2016 serv->access_challenges, 2017 serv->malformed_responses, 2018 serv->bad_authenticators, 2019 pending, 2020 serv->timeouts, 2021 serv->unknown_types, 2022 serv->packets_dropped); 2023 } 2024 2025 radius_client_dump_acct_server(char * buf,size_t buflen,struct hostapd_radius_server * serv,struct radius_client_data * cli)2026 static int radius_client_dump_acct_server(char *buf, size_t buflen, 2027 struct hostapd_radius_server *serv, 2028 struct radius_client_data *cli) 2029 { 2030 int pending = 0; 2031 struct radius_msg_list *msg; 2032 char abuf[50]; 2033 2034 if (cli) { 2035 for (msg = cli->msgs; msg; msg = msg->next) { 2036 if (msg->msg_type == RADIUS_ACCT || 2037 msg->msg_type == RADIUS_ACCT_INTERIM) 2038 pending++; 2039 } 2040 } 2041 2042 return os_snprintf(buf, buflen, 2043 "radiusAccServerIndex=%d\n" 2044 "radiusAccServerAddress=%s\n" 2045 "radiusAccClientServerPortNumber=%d\n" 2046 "radiusAccClientRoundTripTime=%d\n" 2047 "radiusAccClientRequests=%u\n" 2048 "radiusAccClientRetransmissions=%u\n" 2049 "radiusAccClientResponses=%u\n" 2050 "radiusAccClientMalformedResponses=%u\n" 2051 "radiusAccClientBadAuthenticators=%u\n" 2052 "radiusAccClientPendingRequests=%u\n" 2053 "radiusAccClientTimeouts=%u\n" 2054 "radiusAccClientUnknownTypes=%u\n" 2055 "radiusAccClientPacketsDropped=%u\n", 2056 serv->index, 2057 hostapd_ip_txt(&serv->addr, abuf, sizeof(abuf)), 2058 serv->port, 2059 serv->round_trip_time, 2060 serv->requests, 2061 serv->retransmissions, 2062 serv->responses, 2063 serv->malformed_responses, 2064 serv->bad_authenticators, 2065 pending, 2066 serv->timeouts, 2067 serv->unknown_types, 2068 serv->packets_dropped); 2069 } 2070 2071 2072 /** 2073 * radius_client_get_mib - Get RADIUS client MIB information 2074 * @radius: RADIUS client context from radius_client_init() 2075 * @buf: Buffer for returning MIB data in text format 2076 * @buflen: Maximum buf length in octets 2077 * Returns: Number of octets written into the buffer 2078 */ radius_client_get_mib(struct radius_client_data * radius,char * buf,size_t buflen)2079 int radius_client_get_mib(struct radius_client_data *radius, char *buf, 2080 size_t buflen) 2081 { 2082 struct hostapd_radius_servers *conf; 2083 int i; 2084 struct hostapd_radius_server *serv; 2085 int count = 0; 2086 2087 if (!radius) 2088 return 0; 2089 2090 conf = radius->conf; 2091 2092 if (conf->auth_servers) { 2093 for (i = 0; i < conf->num_auth_servers; i++) { 2094 serv = &conf->auth_servers[i]; 2095 count += radius_client_dump_auth_server( 2096 buf + count, buflen - count, serv, 2097 serv == conf->auth_server ? 2098 radius : NULL); 2099 } 2100 } 2101 2102 if (conf->acct_servers) { 2103 for (i = 0; i < conf->num_acct_servers; i++) { 2104 serv = &conf->acct_servers[i]; 2105 count += radius_client_dump_acct_server( 2106 buf + count, buflen - count, serv, 2107 serv == conf->acct_server ? 2108 radius : NULL); 2109 } 2110 } 2111 2112 return count; 2113 } 2114 2115 radius_client_reconfig(struct radius_client_data * radius,struct hostapd_radius_servers * conf)2116 void radius_client_reconfig(struct radius_client_data *radius, 2117 struct hostapd_radius_servers *conf) 2118 { 2119 if (radius) 2120 radius->conf = conf; 2121 } 2122