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