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