1 /* 2 * RADIUS authentication server 3 * Copyright (c) 2005-2009, 2011-2019, Jouni Malinen <j@w1.fi> 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9 #include "includes.h" 10 #include <net/if.h> 11 #ifdef CONFIG_SQLITE 12 #include <sqlite3.h> 13 #endif /* CONFIG_SQLITE */ 14 15 #include "common.h" 16 #include "radius.h" 17 #include "eloop.h" 18 #include "eap_server/eap.h" 19 #include "ap/ap_config.h" 20 #include "crypto/tls.h" 21 #include "radius_server.h" 22 23 /** 24 * RADIUS_SESSION_TIMEOUT - Session timeout in seconds 25 */ 26 #define RADIUS_SESSION_TIMEOUT 60 27 28 /** 29 * RADIUS_SESSION_MAINTAIN - Completed session expiration timeout in seconds 30 */ 31 #define RADIUS_SESSION_MAINTAIN 5 32 33 /** 34 * RADIUS_MAX_SESSION - Maximum number of active sessions 35 */ 36 #define RADIUS_MAX_SESSION 1000 37 38 static const struct eapol_callbacks radius_server_eapol_cb; 39 40 struct radius_client; 41 struct radius_server_data; 42 43 /** 44 * struct radius_server_counters - RADIUS server statistics counters 45 */ 46 struct radius_server_counters { 47 u32 access_requests; 48 u32 invalid_requests; 49 u32 dup_access_requests; 50 u32 access_accepts; 51 u32 access_rejects; 52 u32 access_challenges; 53 u32 malformed_access_requests; 54 u32 bad_authenticators; 55 u32 packets_dropped; 56 u32 unknown_types; 57 58 u32 acct_requests; 59 u32 invalid_acct_requests; 60 u32 acct_responses; 61 u32 malformed_acct_requests; 62 u32 acct_bad_authenticators; 63 u32 unknown_acct_types; 64 }; 65 66 /** 67 * struct radius_session - Internal RADIUS server data for a session 68 */ 69 struct radius_session { 70 struct radius_session *next; 71 struct radius_client *client; 72 struct radius_server_data *server; 73 unsigned int sess_id; 74 struct eap_sm *eap; 75 struct eap_eapol_interface *eap_if; 76 char *username; /* from User-Name attribute */ 77 char *nas_ip; 78 u8 mac_addr[ETH_ALEN]; /* from Calling-Station-Id attribute */ 79 80 struct radius_msg *last_msg; 81 char *last_from_addr; 82 int last_from_port; 83 struct sockaddr_storage last_from; 84 socklen_t last_fromlen; 85 u8 last_identifier; 86 struct radius_msg *last_reply; 87 u8 last_authenticator[16]; 88 89 unsigned int macacl:1; 90 unsigned int t_c_filtering:1; 91 92 struct hostapd_radius_attr *accept_attr; 93 94 u32 t_c_timestamp; /* Last read T&C timestamp from user DB */ 95 }; 96 97 /** 98 * struct radius_client - Internal RADIUS server data for a client 99 */ 100 struct radius_client { 101 struct radius_client *next; 102 struct in_addr addr; 103 struct in_addr mask; 104 #ifdef CONFIG_IPV6 105 struct in6_addr addr6; 106 struct in6_addr mask6; 107 #endif /* CONFIG_IPV6 */ 108 char *shared_secret; 109 int shared_secret_len; 110 struct radius_session *sessions; 111 struct radius_server_counters counters; 112 113 u8 next_dac_identifier; 114 struct radius_msg *pending_dac_coa_req; 115 u8 pending_dac_coa_id; 116 u8 pending_dac_coa_addr[ETH_ALEN]; 117 struct radius_msg *pending_dac_disconnect_req; 118 u8 pending_dac_disconnect_id; 119 u8 pending_dac_disconnect_addr[ETH_ALEN]; 120 }; 121 122 /** 123 * struct radius_server_data - Internal RADIUS server data 124 */ 125 struct radius_server_data { 126 /** 127 * auth_sock - Socket for RADIUS authentication messages 128 */ 129 int auth_sock; 130 131 /** 132 * acct_sock - Socket for RADIUS accounting messages 133 */ 134 int acct_sock; 135 136 /** 137 * clients - List of authorized RADIUS clients 138 */ 139 struct radius_client *clients; 140 141 /** 142 * next_sess_id - Next session identifier 143 */ 144 unsigned int next_sess_id; 145 146 /** 147 * conf_ctx - Context pointer for callbacks 148 * 149 * This is used as the ctx argument in get_eap_user() and acct_req_cb() 150 * calls. 151 */ 152 void *conf_ctx; 153 154 /** 155 * num_sess - Number of active sessions 156 */ 157 int num_sess; 158 159 const char *erp_domain; 160 161 struct dl_list erp_keys; /* struct eap_server_erp_key */ 162 163 /** 164 * ipv6 - Whether to enable IPv6 support in the RADIUS server 165 */ 166 int ipv6; 167 168 /** 169 * start_time - Timestamp of server start 170 */ 171 struct os_reltime start_time; 172 173 /** 174 * counters - Statistics counters for server operations 175 * 176 * These counters are the sum over all clients. 177 */ 178 struct radius_server_counters counters; 179 180 /** 181 * get_eap_user - Callback for fetching EAP user information 182 * @ctx: Context data from conf_ctx 183 * @identity: User identity 184 * @identity_len: identity buffer length in octets 185 * @phase2: Whether this is for Phase 2 identity 186 * @user: Data structure for filling in the user information 187 * Returns: 0 on success, -1 on failure 188 * 189 * This is used to fetch information from user database. The callback 190 * will fill in information about allowed EAP methods and the user 191 * password. The password field will be an allocated copy of the 192 * password data and RADIUS server will free it after use. 193 */ 194 int (*get_eap_user)(void *ctx, const u8 *identity, size_t identity_len, 195 int phase2, struct eap_user *user); 196 197 /** 198 * acct_req_cb - Callback for processing received RADIUS accounting 199 * requests 200 * @ctx: Context data from conf_ctx 201 * @msg: Received RADIUS accounting request 202 * @status_type: Status type from the message (parsed Acct-Status-Type 203 * attribute) 204 * Returns: 0 on success, -1 on failure 205 * 206 * This can be used to log accounting information into file, database, 207 * syslog server, etc. 208 * Callback should not modify the message. 209 * If 0 is returned, response is automatically created. Otherwise, 210 * no response is created. 211 * 212 * acct_req_cb can be set to null to omit any custom processing of 213 * account requests. Statistics counters will be incremented in any 214 * case. 215 */ 216 int (*acct_req_cb)(void *ctx, struct radius_msg *msg, u32 status_type); 217 218 /** 219 * eap_req_id_text - Optional data for EAP-Request/Identity 220 * 221 * This can be used to configure an optional, displayable message that 222 * will be sent in EAP-Request/Identity. This string can contain an 223 * ASCII-0 character (nul) to separate network infromation per RFC 224 * 4284. The actual string length is explicit provided in 225 * eap_req_id_text_len since nul character will not be used as a string 226 * terminator. 227 */ 228 char *eap_req_id_text; 229 230 /** 231 * eap_req_id_text_len - Length of eap_req_id_text buffer in octets 232 */ 233 size_t eap_req_id_text_len; 234 235 #ifdef CONFIG_RADIUS_TEST 236 char *dump_msk_file; 237 #endif /* CONFIG_RADIUS_TEST */ 238 239 char *t_c_server_url; 240 241 #ifdef CONFIG_SQLITE 242 sqlite3 *db; 243 #endif /* CONFIG_SQLITE */ 244 245 const struct eap_config *eap_cfg; 246 }; 247 248 249 #define RADIUS_DEBUG(args...) \ 250 wpa_printf(MSG_DEBUG, "RADIUS SRV: " args) 251 #define RADIUS_ERROR(args...) \ 252 wpa_printf(MSG_ERROR, "RADIUS SRV: " args) 253 #define RADIUS_DUMP(args...) \ 254 wpa_hexdump(MSG_MSGDUMP, "RADIUS SRV: " args) 255 #define RADIUS_DUMP_ASCII(args...) \ 256 wpa_hexdump_ascii(MSG_MSGDUMP, "RADIUS SRV: " args) 257 258 259 static void radius_server_session_timeout(void *eloop_ctx, void *timeout_ctx); 260 static void radius_server_session_remove_timeout(void *eloop_ctx, 261 void *timeout_ctx); 262 263 void srv_log(struct radius_session *sess, const char *fmt, ...) 264 PRINTF_FORMAT(2, 3); 265 srv_log(struct radius_session * sess,const char * fmt,...)266 void srv_log(struct radius_session *sess, const char *fmt, ...) 267 { 268 va_list ap; 269 char *buf; 270 int buflen; 271 272 va_start(ap, fmt); 273 buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 274 va_end(ap); 275 276 buf = os_malloc(buflen); 277 if (buf == NULL) 278 return; 279 va_start(ap, fmt); 280 vsnprintf(buf, buflen, fmt, ap); 281 va_end(ap); 282 283 RADIUS_DEBUG("[0x%x %s] %s", sess->sess_id, sess->nas_ip, buf); 284 285 #ifdef CONFIG_SQLITE 286 if (sess->server->db) { 287 char *sql; 288 sql = sqlite3_mprintf("INSERT INTO authlog" 289 "(timestamp,session,nas_ip,username,note)" 290 " VALUES (" 291 "strftime('%%Y-%%m-%%d %%H:%%M:%%f'," 292 "'now'),%u,%Q,%Q,%Q)", 293 sess->sess_id, sess->nas_ip, 294 sess->username, buf); 295 if (sql) { 296 if (sqlite3_exec(sess->server->db, sql, NULL, NULL, 297 NULL) != SQLITE_OK) { 298 RADIUS_ERROR("Failed to add authlog entry into sqlite database: %s", 299 sqlite3_errmsg(sess->server->db)); 300 } 301 sqlite3_free(sql); 302 } 303 } 304 #endif /* CONFIG_SQLITE */ 305 306 os_free(buf); 307 } 308 309 310 static struct radius_client * radius_server_get_client(struct radius_server_data * data,struct in_addr * addr,int ipv6)311 radius_server_get_client(struct radius_server_data *data, struct in_addr *addr, 312 int ipv6) 313 { 314 struct radius_client *client = data->clients; 315 316 while (client) { 317 #ifdef CONFIG_IPV6 318 if (ipv6) { 319 struct in6_addr *addr6; 320 int i; 321 322 addr6 = (struct in6_addr *) addr; 323 for (i = 0; i < 16; i++) { 324 if ((addr6->s6_addr[i] & 325 client->mask6.s6_addr[i]) != 326 (client->addr6.s6_addr[i] & 327 client->mask6.s6_addr[i])) { 328 i = 17; 329 break; 330 } 331 } 332 if (i == 16) { 333 break; 334 } 335 } 336 #endif /* CONFIG_IPV6 */ 337 if (!ipv6 && (client->addr.s_addr & client->mask.s_addr) == 338 (addr->s_addr & client->mask.s_addr)) { 339 break; 340 } 341 342 client = client->next; 343 } 344 345 return client; 346 } 347 348 349 static struct radius_session * radius_server_get_session(struct radius_client * client,unsigned int sess_id)350 radius_server_get_session(struct radius_client *client, unsigned int sess_id) 351 { 352 struct radius_session *sess = client->sessions; 353 354 while (sess) { 355 if (sess->sess_id == sess_id) { 356 break; 357 } 358 sess = sess->next; 359 } 360 361 return sess; 362 } 363 364 radius_server_session_free(struct radius_server_data * data,struct radius_session * sess)365 static void radius_server_session_free(struct radius_server_data *data, 366 struct radius_session *sess) 367 { 368 eloop_cancel_timeout(radius_server_session_timeout, data, sess); 369 eloop_cancel_timeout(radius_server_session_remove_timeout, data, sess); 370 eap_server_sm_deinit(sess->eap); 371 radius_msg_free(sess->last_msg); 372 os_free(sess->last_from_addr); 373 radius_msg_free(sess->last_reply); 374 os_free(sess->username); 375 os_free(sess->nas_ip); 376 os_free(sess); 377 data->num_sess--; 378 } 379 380 radius_server_session_remove(struct radius_server_data * data,struct radius_session * sess)381 static void radius_server_session_remove(struct radius_server_data *data, 382 struct radius_session *sess) 383 { 384 struct radius_client *client = sess->client; 385 struct radius_session *session, *prev; 386 387 eloop_cancel_timeout(radius_server_session_remove_timeout, data, sess); 388 389 prev = NULL; 390 session = client->sessions; 391 while (session) { 392 if (session == sess) { 393 if (prev == NULL) { 394 client->sessions = sess->next; 395 } else { 396 prev->next = sess->next; 397 } 398 radius_server_session_free(data, sess); 399 break; 400 } 401 prev = session; 402 session = session->next; 403 } 404 } 405 406 radius_server_session_remove_timeout(void * eloop_ctx,void * timeout_ctx)407 static void radius_server_session_remove_timeout(void *eloop_ctx, 408 void *timeout_ctx) 409 { 410 struct radius_server_data *data = eloop_ctx; 411 struct radius_session *sess = timeout_ctx; 412 RADIUS_DEBUG("Removing completed session 0x%x", sess->sess_id); 413 radius_server_session_remove(data, sess); 414 } 415 416 radius_server_session_timeout(void * eloop_ctx,void * timeout_ctx)417 static void radius_server_session_timeout(void *eloop_ctx, void *timeout_ctx) 418 { 419 struct radius_server_data *data = eloop_ctx; 420 struct radius_session *sess = timeout_ctx; 421 422 RADIUS_DEBUG("Timing out authentication session 0x%x", sess->sess_id); 423 radius_server_session_remove(data, sess); 424 } 425 426 427 static struct radius_session * radius_server_new_session(struct radius_server_data * data,struct radius_client * client)428 radius_server_new_session(struct radius_server_data *data, 429 struct radius_client *client) 430 { 431 struct radius_session *sess; 432 433 if (data->num_sess >= RADIUS_MAX_SESSION) { 434 RADIUS_DEBUG("Maximum number of existing session - no room " 435 "for a new session"); 436 return NULL; 437 } 438 439 sess = os_zalloc(sizeof(*sess)); 440 if (sess == NULL) 441 return NULL; 442 443 sess->server = data; 444 sess->client = client; 445 sess->sess_id = data->next_sess_id++; 446 sess->next = client->sessions; 447 client->sessions = sess; 448 eloop_register_timeout(RADIUS_SESSION_TIMEOUT, 0, 449 radius_server_session_timeout, data, sess); 450 data->num_sess++; 451 return sess; 452 } 453 454 455 #ifdef CONFIG_TESTING_OPTIONS radius_server_testing_options_tls(struct radius_session * sess,const char * tls,struct eap_session_data * eap_conf)456 static void radius_server_testing_options_tls(struct radius_session *sess, 457 const char *tls, 458 struct eap_session_data *eap_conf) 459 { 460 int test = atoi(tls); 461 462 switch (test) { 463 case 1: 464 srv_log(sess, "TLS test - break VerifyData"); 465 eap_conf->tls_test_flags = TLS_BREAK_VERIFY_DATA; 466 break; 467 case 2: 468 srv_log(sess, "TLS test - break ServerKeyExchange ServerParams hash"); 469 eap_conf->tls_test_flags = TLS_BREAK_SRV_KEY_X_HASH; 470 break; 471 case 3: 472 srv_log(sess, "TLS test - break ServerKeyExchange ServerParams Signature"); 473 eap_conf->tls_test_flags = TLS_BREAK_SRV_KEY_X_SIGNATURE; 474 break; 475 case 4: 476 srv_log(sess, "TLS test - RSA-DHE using a short 511-bit prime"); 477 eap_conf->tls_test_flags = TLS_DHE_PRIME_511B; 478 break; 479 case 5: 480 srv_log(sess, "TLS test - RSA-DHE using a short 767-bit prime"); 481 eap_conf->tls_test_flags = TLS_DHE_PRIME_767B; 482 break; 483 case 6: 484 srv_log(sess, "TLS test - RSA-DHE using a bogus 15 \"prime\""); 485 eap_conf->tls_test_flags = TLS_DHE_PRIME_15; 486 break; 487 case 7: 488 srv_log(sess, "TLS test - RSA-DHE using a short 58-bit prime in long container"); 489 eap_conf->tls_test_flags = TLS_DHE_PRIME_58B; 490 break; 491 case 8: 492 srv_log(sess, "TLS test - RSA-DHE using a non-prime"); 493 eap_conf->tls_test_flags = TLS_DHE_NON_PRIME; 494 break; 495 default: 496 srv_log(sess, "Unrecognized TLS test"); 497 break; 498 } 499 } 500 #endif /* CONFIG_TESTING_OPTIONS */ 501 radius_server_testing_options(struct radius_session * sess,struct eap_session_data * eap_conf)502 static void radius_server_testing_options(struct radius_session *sess, 503 struct eap_session_data *eap_conf) 504 { 505 #ifdef CONFIG_TESTING_OPTIONS 506 const char *pos; 507 508 pos = os_strstr(sess->username, "@test-"); 509 if (pos == NULL) 510 return; 511 pos += 6; 512 if (os_strncmp(pos, "tls-", 4) == 0) 513 radius_server_testing_options_tls(sess, pos + 4, eap_conf); 514 else 515 srv_log(sess, "Unrecognized test: %s", pos); 516 #endif /* CONFIG_TESTING_OPTIONS */ 517 } 518 519 520 #ifdef CONFIG_ERP 521 static struct eap_server_erp_key * radius_server_erp_find_key(struct radius_server_data * data,const char * keyname)522 radius_server_erp_find_key(struct radius_server_data *data, const char *keyname) 523 { 524 struct eap_server_erp_key *erp; 525 526 dl_list_for_each(erp, &data->erp_keys, struct eap_server_erp_key, 527 list) { 528 if (os_strcmp(erp->keyname_nai, keyname) == 0) 529 return erp; 530 } 531 532 return NULL; 533 } 534 #endif /* CONFIG_ERP */ 535 536 537 static struct radius_session * radius_server_get_new_session(struct radius_server_data * data,struct radius_client * client,struct radius_msg * msg,const char * from_addr)538 radius_server_get_new_session(struct radius_server_data *data, 539 struct radius_client *client, 540 struct radius_msg *msg, const char *from_addr) 541 { 542 u8 *user, *id; 543 size_t user_len, id_len; 544 int res; 545 struct radius_session *sess; 546 struct eap_session_data eap_sess; 547 struct eap_user *tmp; 548 549 RADIUS_DEBUG("Creating a new session"); 550 551 if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_USER_NAME, &user, 552 &user_len, NULL) < 0) { 553 RADIUS_DEBUG("Could not get User-Name"); 554 return NULL; 555 } 556 RADIUS_DUMP_ASCII("User-Name", user, user_len); 557 558 tmp = os_zalloc(sizeof(*tmp)); 559 if (!tmp) 560 return NULL; 561 562 res = data->get_eap_user(data->conf_ctx, user, user_len, 0, tmp); 563 #ifdef CONFIG_ERP 564 if (res != 0 && data->eap_cfg->erp) { 565 char *username; 566 567 username = os_zalloc(user_len + 1); 568 if (username) { 569 os_memcpy(username, user, user_len); 570 if (radius_server_erp_find_key(data, username)) 571 res = 0; 572 os_free(username); 573 } 574 } 575 #endif /* CONFIG_ERP */ 576 if (res != 0) { 577 RADIUS_DEBUG("User-Name not found from user database"); 578 eap_user_free(tmp); 579 return NULL; 580 } 581 582 RADIUS_DEBUG("Matching user entry found"); 583 sess = radius_server_new_session(data, client); 584 if (sess == NULL) { 585 RADIUS_DEBUG("Failed to create a new session"); 586 eap_user_free(tmp); 587 return NULL; 588 } 589 sess->accept_attr = tmp->accept_attr; 590 sess->macacl = tmp->macacl; 591 eap_user_free(tmp); 592 593 sess->username = os_malloc(user_len * 4 + 1); 594 if (sess->username == NULL) { 595 radius_server_session_remove(data, sess); 596 return NULL; 597 } 598 printf_encode(sess->username, user_len * 4 + 1, user, user_len); 599 600 sess->nas_ip = os_strdup(from_addr); 601 if (sess->nas_ip == NULL) { 602 radius_server_session_remove(data, sess); 603 return NULL; 604 } 605 606 if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_CALLING_STATION_ID, &id, 607 &id_len, NULL) == 0) { 608 char buf[3 * ETH_ALEN]; 609 610 os_memset(buf, 0, sizeof(buf)); 611 if (id_len >= sizeof(buf)) 612 id_len = sizeof(buf) - 1; 613 os_memcpy(buf, id, id_len); 614 if (hwaddr_aton2(buf, sess->mac_addr) < 0) 615 os_memset(sess->mac_addr, 0, ETH_ALEN); 616 else 617 RADIUS_DEBUG("Calling-Station-Id: " MACSTR, 618 MAC2STR(sess->mac_addr)); 619 } 620 621 srv_log(sess, "New session created"); 622 623 os_memset(&eap_sess, 0, sizeof(eap_sess)); 624 radius_server_testing_options(sess, &eap_sess); 625 sess->eap = eap_server_sm_init(sess, &radius_server_eapol_cb, 626 data->eap_cfg, &eap_sess); 627 if (sess->eap == NULL) { 628 RADIUS_DEBUG("Failed to initialize EAP state machine for the " 629 "new session"); 630 radius_server_session_remove(data, sess); 631 return NULL; 632 } 633 sess->eap_if = eap_get_interface(sess->eap); 634 sess->eap_if->eapRestart = true; 635 sess->eap_if->portEnabled = true; 636 637 RADIUS_DEBUG("New session 0x%x initialized", sess->sess_id); 638 639 return sess; 640 } 641 642 643 #ifdef CONFIG_HS20 radius_srv_hs20_t_c_pending(struct radius_session * sess)644 static void radius_srv_hs20_t_c_pending(struct radius_session *sess) 645 { 646 #ifdef CONFIG_SQLITE 647 char *sql; 648 char addr[3 * ETH_ALEN], *id_str; 649 const u8 *id; 650 size_t id_len; 651 652 if (!sess->server->db || !sess->eap || 653 is_zero_ether_addr(sess->mac_addr)) 654 return; 655 656 os_snprintf(addr, sizeof(addr), MACSTR, MAC2STR(sess->mac_addr)); 657 658 id = eap_get_identity(sess->eap, &id_len); 659 if (!id) 660 return; 661 id_str = os_malloc(id_len + 1); 662 if (!id_str) 663 return; 664 os_memcpy(id_str, id, id_len); 665 id_str[id_len] = '\0'; 666 667 sql = sqlite3_mprintf("INSERT OR REPLACE INTO pending_tc (mac_addr,identity) VALUES (%Q,%Q)", 668 addr, id_str); 669 os_free(id_str); 670 if (!sql) 671 return; 672 673 if (sqlite3_exec(sess->server->db, sql, NULL, NULL, NULL) != 674 SQLITE_OK) { 675 RADIUS_ERROR("Failed to add pending_tc entry into sqlite database: %s", 676 sqlite3_errmsg(sess->server->db)); 677 } 678 sqlite3_free(sql); 679 #endif /* CONFIG_SQLITE */ 680 } 681 #endif /* CONFIG_HS20 */ 682 683 radius_server_add_session(struct radius_session * sess)684 static void radius_server_add_session(struct radius_session *sess) 685 { 686 #ifdef CONFIG_SQLITE 687 char *sql; 688 char addr_txt[ETH_ALEN * 3]; 689 struct os_time now; 690 691 if (!sess->server->db) 692 return; 693 694 695 os_snprintf(addr_txt, sizeof(addr_txt), MACSTR, 696 MAC2STR(sess->mac_addr)); 697 698 os_get_time(&now); 699 sql = sqlite3_mprintf("INSERT OR REPLACE INTO current_sessions(mac_addr,identity,start_time,nas,hs20_t_c_filtering) VALUES (%Q,%Q,%d,%Q,%u)", 700 addr_txt, sess->username, now.sec, 701 sess->nas_ip, sess->t_c_filtering); 702 if (sql) { 703 if (sqlite3_exec(sess->server->db, sql, NULL, NULL, 704 NULL) != SQLITE_OK) { 705 RADIUS_ERROR("Failed to add current_sessions entry into sqlite database: %s", 706 sqlite3_errmsg(sess->server->db)); 707 } 708 sqlite3_free(sql); 709 } 710 #endif /* CONFIG_SQLITE */ 711 } 712 713 db_update_last_msk(struct radius_session * sess,const char * msk)714 static void db_update_last_msk(struct radius_session *sess, const char *msk) 715 { 716 #ifdef CONFIG_RADIUS_TEST 717 #ifdef CONFIG_SQLITE 718 char *sql = NULL; 719 char *id_str = NULL; 720 const u8 *id; 721 size_t id_len; 722 const char *serial_num; 723 724 if (!sess->server->db) 725 return; 726 727 serial_num = eap_get_serial_num(sess->eap); 728 if (serial_num) { 729 id_len = 5 + os_strlen(serial_num) + 1; 730 id_str = os_malloc(id_len); 731 if (!id_str) 732 return; 733 os_snprintf(id_str, id_len, "cert-%s", serial_num); 734 } else { 735 id = eap_get_identity(sess->eap, &id_len); 736 if (!id) 737 return; 738 id_str = os_malloc(id_len + 1); 739 if (!id_str) 740 return; 741 os_memcpy(id_str, id, id_len); 742 id_str[id_len] = '\0'; 743 } 744 745 sql = sqlite3_mprintf("UPDATE users SET last_msk=%Q WHERE identity=%Q", 746 msk, id_str); 747 os_free(id_str); 748 if (!sql) 749 return; 750 751 if (sqlite3_exec(sess->server->db, sql, NULL, NULL, NULL) != 752 SQLITE_OK) { 753 RADIUS_DEBUG("Failed to update last_msk: %s", 754 sqlite3_errmsg(sess->server->db)); 755 } 756 sqlite3_free(sql); 757 #endif /* CONFIG_SQLITE */ 758 #endif /* CONFIG_RADIUS_TEST */ 759 } 760 761 762 static struct radius_msg * radius_server_encapsulate_eap(struct radius_server_data * data,struct radius_client * client,struct radius_session * sess,struct radius_msg * request)763 radius_server_encapsulate_eap(struct radius_server_data *data, 764 struct radius_client *client, 765 struct radius_session *sess, 766 struct radius_msg *request) 767 { 768 struct radius_msg *msg; 769 int code; 770 unsigned int sess_id; 771 struct radius_hdr *hdr = radius_msg_get_hdr(request); 772 u16 reason = WLAN_REASON_IEEE_802_1X_AUTH_FAILED; 773 774 if (sess->eap_if->eapFail) { 775 sess->eap_if->eapFail = false; 776 code = RADIUS_CODE_ACCESS_REJECT; 777 } else if (sess->eap_if->eapSuccess) { 778 sess->eap_if->eapSuccess = false; 779 code = RADIUS_CODE_ACCESS_ACCEPT; 780 } else { 781 sess->eap_if->eapReq = false; 782 code = RADIUS_CODE_ACCESS_CHALLENGE; 783 } 784 785 msg = radius_msg_new(code, hdr->identifier); 786 if (msg == NULL) { 787 RADIUS_DEBUG("Failed to allocate reply message"); 788 return NULL; 789 } 790 791 if (!radius_msg_add_msg_auth(msg)) { 792 radius_msg_free(msg); 793 return NULL; 794 } 795 796 sess_id = htonl(sess->sess_id); 797 if (code == RADIUS_CODE_ACCESS_CHALLENGE && 798 !radius_msg_add_attr(msg, RADIUS_ATTR_STATE, 799 (u8 *) &sess_id, sizeof(sess_id))) { 800 RADIUS_DEBUG("Failed to add State attribute"); 801 } 802 803 if (sess->eap_if->eapReqData && 804 !radius_msg_add_eap(msg, wpabuf_head(sess->eap_if->eapReqData), 805 wpabuf_len(sess->eap_if->eapReqData))) { 806 RADIUS_DEBUG("Failed to add EAP-Message attribute"); 807 } 808 809 if (code == RADIUS_CODE_ACCESS_ACCEPT && sess->eap_if->eapKeyData) { 810 int len; 811 #ifdef CONFIG_RADIUS_TEST 812 char buf[2 * 64 + 1]; 813 814 len = sess->eap_if->eapKeyDataLen; 815 if (len > 64) 816 len = 64; 817 len = wpa_snprintf_hex(buf, sizeof(buf), 818 sess->eap_if->eapKeyData, len); 819 buf[len] = '\0'; 820 821 if (data->dump_msk_file) { 822 FILE *f; 823 824 f = fopen(data->dump_msk_file, "a"); 825 if (f) { 826 len = sess->eap_if->eapKeyDataLen; 827 if (len > 64) 828 len = 64; 829 len = wpa_snprintf_hex( 830 buf, sizeof(buf), 831 sess->eap_if->eapKeyData, len); 832 buf[len] = '\0'; 833 fprintf(f, "%s\n", buf); 834 fclose(f); 835 } 836 } 837 838 db_update_last_msk(sess, buf); 839 #endif /* CONFIG_RADIUS_TEST */ 840 if (sess->eap_if->eapKeyDataLen > 64) { 841 len = 32; 842 } else { 843 len = sess->eap_if->eapKeyDataLen / 2; 844 } 845 if (!radius_msg_add_mppe_keys(msg, hdr->authenticator, 846 (u8 *) client->shared_secret, 847 client->shared_secret_len, 848 sess->eap_if->eapKeyData + len, 849 len, sess->eap_if->eapKeyData, 850 len)) { 851 RADIUS_DEBUG("Failed to add MPPE key attributes"); 852 } 853 854 if (sess->eap_if->eapSessionId && 855 !radius_msg_add_attr(msg, RADIUS_ATTR_EAP_KEY_NAME, 856 sess->eap_if->eapSessionId, 857 sess->eap_if->eapSessionIdLen)) { 858 RADIUS_DEBUG("Failed to add EAP-Key-Name attribute"); 859 } 860 } 861 862 #ifdef CONFIG_HS20 863 if (code == RADIUS_CODE_ACCESS_ACCEPT && sess->t_c_filtering) { 864 u8 buf[4] = { 0x01, 0x00, 0x00, 0x00 }; /* E=1 */ 865 const char *url = data->t_c_server_url, *pos; 866 char *url2, *end2, *pos2; 867 size_t url_len; 868 869 if (!radius_msg_add_wfa( 870 msg, RADIUS_VENDOR_ATTR_WFA_HS20_T_C_FILTERING, 871 buf, sizeof(buf))) { 872 RADIUS_DEBUG("Failed to add WFA-HS20-T-C-Filtering"); 873 radius_msg_free(msg); 874 return NULL; 875 } 876 877 if (!url) { 878 RADIUS_DEBUG("No t_c_server_url configured"); 879 radius_msg_free(msg); 880 return NULL; 881 } 882 883 pos = os_strstr(url, "@1@"); 884 if (!pos) { 885 RADIUS_DEBUG("No @1@ macro in t_c_server_url"); 886 radius_msg_free(msg); 887 return NULL; 888 } 889 890 url_len = os_strlen(url) + ETH_ALEN * 3 - 1 - 3; 891 url2 = os_malloc(url_len + 1); 892 if (!url2) { 893 RADIUS_DEBUG("Failed to allocate room for T&C Server URL"); 894 os_free(url2); 895 radius_msg_free(msg); 896 return NULL; 897 } 898 pos2 = url2; 899 end2 = url2 + url_len + 1; 900 os_memcpy(pos2, url, pos - url); 901 pos2 += pos - url; 902 os_snprintf(pos2, end2 - pos2, MACSTR, MAC2STR(sess->mac_addr)); 903 pos2 += ETH_ALEN * 3 - 1; 904 os_memcpy(pos2, pos + 3, os_strlen(pos + 3)); 905 if (!radius_msg_add_wfa(msg, 906 RADIUS_VENDOR_ATTR_WFA_HS20_T_C_URL, 907 (const u8 *) url2, url_len)) { 908 RADIUS_DEBUG("Failed to add WFA-HS20-T-C-URL"); 909 os_free(url2); 910 radius_msg_free(msg); 911 return NULL; 912 } 913 os_free(url2); 914 915 radius_srv_hs20_t_c_pending(sess); 916 } 917 #endif /* CONFIG_HS20 */ 918 919 if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) { 920 RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)"); 921 radius_msg_free(msg); 922 return NULL; 923 } 924 925 if (code == RADIUS_CODE_ACCESS_ACCEPT) { 926 struct hostapd_radius_attr *attr; 927 for (attr = sess->accept_attr; attr; attr = attr->next) { 928 if (!radius_msg_add_attr(msg, attr->type, 929 wpabuf_head(attr->val), 930 wpabuf_len(attr->val))) { 931 wpa_printf(MSG_ERROR, "Could not add RADIUS attribute"); 932 radius_msg_free(msg); 933 return NULL; 934 } 935 } 936 } 937 938 if (code == RADIUS_CODE_ACCESS_REJECT) { 939 if (radius_msg_add_attr_int32(msg, RADIUS_ATTR_WLAN_REASON_CODE, 940 reason) < 0) { 941 RADIUS_DEBUG("Failed to add WLAN-Reason-Code attribute"); 942 radius_msg_free(msg); 943 return NULL; 944 } 945 } 946 947 if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret, 948 client->shared_secret_len, 949 hdr->authenticator) < 0) { 950 RADIUS_DEBUG("Failed to add Message-Authenticator attribute"); 951 radius_msg_free(msg); 952 return NULL; 953 } 954 955 if (code == RADIUS_CODE_ACCESS_ACCEPT) 956 radius_server_add_session(sess); 957 958 return msg; 959 } 960 961 962 static struct radius_msg * radius_server_macacl(struct radius_server_data * data,struct radius_client * client,struct radius_session * sess,struct radius_msg * request)963 radius_server_macacl(struct radius_server_data *data, 964 struct radius_client *client, 965 struct radius_session *sess, 966 struct radius_msg *request) 967 { 968 struct radius_msg *msg; 969 int code; 970 struct radius_hdr *hdr = radius_msg_get_hdr(request); 971 u8 *pw; 972 size_t pw_len; 973 974 code = RADIUS_CODE_ACCESS_ACCEPT; 975 976 if (radius_msg_get_attr_ptr(request, RADIUS_ATTR_USER_PASSWORD, &pw, 977 &pw_len, NULL) < 0) { 978 RADIUS_DEBUG("Could not get User-Password"); 979 code = RADIUS_CODE_ACCESS_REJECT; 980 } else { 981 int res; 982 struct eap_user tmp; 983 984 os_memset(&tmp, 0, sizeof(tmp)); 985 res = data->get_eap_user(data->conf_ctx, (u8 *) sess->username, 986 os_strlen(sess->username), 0, &tmp); 987 if (res || !tmp.macacl || tmp.password == NULL) { 988 RADIUS_DEBUG("No MAC ACL user entry"); 989 bin_clear_free(tmp.password, tmp.password_len); 990 code = RADIUS_CODE_ACCESS_REJECT; 991 } else { 992 u8 buf[128]; 993 res = radius_user_password_hide( 994 request, tmp.password, tmp.password_len, 995 (u8 *) client->shared_secret, 996 client->shared_secret_len, 997 buf, sizeof(buf)); 998 bin_clear_free(tmp.password, tmp.password_len); 999 1000 if (res < 0 || pw_len != (size_t) res || 1001 os_memcmp_const(pw, buf, res) != 0) { 1002 RADIUS_DEBUG("Incorrect User-Password"); 1003 code = RADIUS_CODE_ACCESS_REJECT; 1004 } 1005 } 1006 } 1007 1008 msg = radius_msg_new(code, hdr->identifier); 1009 if (msg == NULL) { 1010 RADIUS_DEBUG("Failed to allocate reply message"); 1011 return NULL; 1012 } 1013 1014 if (!radius_msg_add_msg_auth(msg)) { 1015 radius_msg_free(msg); 1016 return NULL; 1017 } 1018 1019 if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) { 1020 RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)"); 1021 radius_msg_free(msg); 1022 return NULL; 1023 } 1024 1025 if (code == RADIUS_CODE_ACCESS_ACCEPT) { 1026 struct hostapd_radius_attr *attr; 1027 for (attr = sess->accept_attr; attr; attr = attr->next) { 1028 if (!radius_msg_add_attr(msg, attr->type, 1029 wpabuf_head(attr->val), 1030 wpabuf_len(attr->val))) { 1031 wpa_printf(MSG_ERROR, "Could not add RADIUS attribute"); 1032 radius_msg_free(msg); 1033 return NULL; 1034 } 1035 } 1036 } 1037 1038 if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret, 1039 client->shared_secret_len, 1040 hdr->authenticator) < 0) { 1041 RADIUS_DEBUG("Failed to add Message-Authenticator attribute"); 1042 radius_msg_free(msg); 1043 return NULL; 1044 } 1045 1046 return msg; 1047 } 1048 1049 radius_server_reject(struct radius_server_data * data,struct radius_client * client,struct radius_msg * request,struct sockaddr * from,socklen_t fromlen,const char * from_addr,int from_port)1050 static int radius_server_reject(struct radius_server_data *data, 1051 struct radius_client *client, 1052 struct radius_msg *request, 1053 struct sockaddr *from, socklen_t fromlen, 1054 const char *from_addr, int from_port) 1055 { 1056 struct radius_msg *msg; 1057 int ret = 0; 1058 struct eap_hdr eapfail; 1059 struct wpabuf *buf; 1060 struct radius_hdr *hdr = radius_msg_get_hdr(request); 1061 1062 RADIUS_DEBUG("Reject invalid request from %s:%d", 1063 from_addr, from_port); 1064 1065 msg = radius_msg_new(RADIUS_CODE_ACCESS_REJECT, hdr->identifier); 1066 if (msg == NULL) { 1067 return -1; 1068 } 1069 1070 if (!radius_msg_add_msg_auth(msg)) { 1071 radius_msg_free(msg); 1072 return -1; 1073 } 1074 1075 os_memset(&eapfail, 0, sizeof(eapfail)); 1076 eapfail.code = EAP_CODE_FAILURE; 1077 eapfail.identifier = 0; 1078 eapfail.length = host_to_be16(sizeof(eapfail)); 1079 1080 if (!radius_msg_add_eap(msg, (u8 *) &eapfail, sizeof(eapfail))) { 1081 RADIUS_DEBUG("Failed to add EAP-Message attribute"); 1082 } 1083 1084 if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) { 1085 RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)"); 1086 radius_msg_free(msg); 1087 return -1; 1088 } 1089 1090 if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret, 1091 client->shared_secret_len, 1092 hdr->authenticator) < 1093 0) { 1094 RADIUS_DEBUG("Failed to add Message-Authenticator attribute"); 1095 radius_msg_free(msg); 1096 return -1; 1097 } 1098 1099 if (wpa_debug_level <= MSG_MSGDUMP) { 1100 radius_msg_dump(msg); 1101 } 1102 1103 data->counters.access_rejects++; 1104 client->counters.access_rejects++; 1105 buf = radius_msg_get_buf(msg); 1106 if (sendto(data->auth_sock, wpabuf_head(buf), wpabuf_len(buf), 0, 1107 (struct sockaddr *) from, sizeof(*from)) < 0) { 1108 wpa_printf(MSG_INFO, "sendto[RADIUS SRV]: %s", strerror(errno)); 1109 ret = -1; 1110 } 1111 1112 radius_msg_free(msg); 1113 1114 return ret; 1115 } 1116 1117 radius_server_hs20_t_c_check(struct radius_session * sess,struct radius_msg * msg)1118 static void radius_server_hs20_t_c_check(struct radius_session *sess, 1119 struct radius_msg *msg) 1120 { 1121 #ifdef CONFIG_HS20 1122 u8 *buf, *pos, *end, type, sublen, *timestamp = NULL; 1123 size_t len; 1124 1125 buf = NULL; 1126 for (;;) { 1127 if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_VENDOR_SPECIFIC, 1128 &buf, &len, buf) < 0) 1129 break; 1130 if (len < 6) 1131 continue; 1132 pos = buf; 1133 end = buf + len; 1134 if (WPA_GET_BE32(pos) != RADIUS_VENDOR_ID_WFA) 1135 continue; 1136 pos += 4; 1137 1138 type = *pos++; 1139 sublen = *pos++; 1140 if (sublen < 2) 1141 continue; /* invalid length */ 1142 sublen -= 2; /* skip header */ 1143 if (pos + sublen > end) 1144 continue; /* invalid WFA VSA */ 1145 1146 if (type == RADIUS_VENDOR_ATTR_WFA_HS20_TIMESTAMP && len >= 4) { 1147 timestamp = pos; 1148 break; 1149 } 1150 } 1151 1152 if (!timestamp) 1153 return; 1154 RADIUS_DEBUG("HS20-Timestamp: %u", WPA_GET_BE32(timestamp)); 1155 if (sess->t_c_timestamp != WPA_GET_BE32(timestamp)) { 1156 RADIUS_DEBUG("Last read T&C timestamp does not match HS20-Timestamp --> require filtering"); 1157 sess->t_c_filtering = 1; 1158 } 1159 #endif /* CONFIG_HS20 */ 1160 } 1161 1162 radius_server_request(struct radius_server_data * data,struct radius_msg * msg,struct sockaddr * from,socklen_t fromlen,struct radius_client * client,const char * from_addr,int from_port,struct radius_session * force_sess)1163 static int radius_server_request(struct radius_server_data *data, 1164 struct radius_msg *msg, 1165 struct sockaddr *from, socklen_t fromlen, 1166 struct radius_client *client, 1167 const char *from_addr, int from_port, 1168 struct radius_session *force_sess) 1169 { 1170 struct wpabuf *eap = NULL; 1171 int res, state_included = 0; 1172 u8 statebuf[4]; 1173 unsigned int state; 1174 struct radius_session *sess; 1175 struct radius_msg *reply; 1176 int is_complete = 0; 1177 1178 if (force_sess) 1179 sess = force_sess; 1180 else { 1181 res = radius_msg_get_attr(msg, RADIUS_ATTR_STATE, statebuf, 1182 sizeof(statebuf)); 1183 state_included = res >= 0; 1184 if (res == sizeof(statebuf)) { 1185 state = WPA_GET_BE32(statebuf); 1186 sess = radius_server_get_session(client, state); 1187 } else { 1188 sess = NULL; 1189 } 1190 } 1191 1192 if (sess) { 1193 RADIUS_DEBUG("Request for session 0x%x", sess->sess_id); 1194 } else if (state_included) { 1195 RADIUS_DEBUG("State attribute included but no session found"); 1196 radius_server_reject(data, client, msg, from, fromlen, 1197 from_addr, from_port); 1198 return -1; 1199 } else { 1200 sess = radius_server_get_new_session(data, client, msg, 1201 from_addr); 1202 if (sess == NULL) { 1203 RADIUS_DEBUG("Could not create a new session"); 1204 radius_server_reject(data, client, msg, from, fromlen, 1205 from_addr, from_port); 1206 return -1; 1207 } 1208 } 1209 1210 if (sess->last_from_port == from_port && 1211 sess->last_identifier == radius_msg_get_hdr(msg)->identifier && 1212 os_memcmp(sess->last_authenticator, 1213 radius_msg_get_hdr(msg)->authenticator, 16) == 0) { 1214 RADIUS_DEBUG("Duplicate message from %s", from_addr); 1215 data->counters.dup_access_requests++; 1216 client->counters.dup_access_requests++; 1217 1218 if (sess->last_reply) { 1219 struct wpabuf *buf; 1220 buf = radius_msg_get_buf(sess->last_reply); 1221 res = sendto(data->auth_sock, wpabuf_head(buf), 1222 wpabuf_len(buf), 0, 1223 (struct sockaddr *) from, fromlen); 1224 if (res < 0) { 1225 wpa_printf(MSG_INFO, "sendto[RADIUS SRV]: %s", 1226 strerror(errno)); 1227 } 1228 return 0; 1229 } 1230 1231 RADIUS_DEBUG("No previous reply available for duplicate " 1232 "message"); 1233 return -1; 1234 } 1235 1236 eap = radius_msg_get_eap(msg); 1237 if (eap == NULL && sess->macacl) { 1238 reply = radius_server_macacl(data, client, sess, msg); 1239 if (reply == NULL) 1240 return -1; 1241 goto send_reply; 1242 } 1243 if (eap == NULL) { 1244 RADIUS_DEBUG("No EAP-Message in RADIUS packet from %s", 1245 from_addr); 1246 data->counters.packets_dropped++; 1247 client->counters.packets_dropped++; 1248 return -1; 1249 } 1250 1251 RADIUS_DUMP("Received EAP data", wpabuf_head(eap), wpabuf_len(eap)); 1252 1253 /* FIX: if Code is Request, Success, or Failure, send Access-Reject; 1254 * RFC3579 Sect. 2.6.2. 1255 * Include EAP-Response/Nak with no preferred method if 1256 * code == request. 1257 * If code is not 1-4, discard the packet silently. 1258 * Or is this already done by the EAP state machine? */ 1259 1260 wpabuf_free(sess->eap_if->eapRespData); 1261 sess->eap_if->eapRespData = eap; 1262 sess->eap_if->eapResp = true; 1263 eap_server_sm_step(sess->eap); 1264 1265 if ((sess->eap_if->eapReq || sess->eap_if->eapSuccess || 1266 sess->eap_if->eapFail) && sess->eap_if->eapReqData) { 1267 RADIUS_DUMP("EAP data from the state machine", 1268 wpabuf_head(sess->eap_if->eapReqData), 1269 wpabuf_len(sess->eap_if->eapReqData)); 1270 } else if (sess->eap_if->eapFail) { 1271 RADIUS_DEBUG("No EAP data from the state machine, but eapFail " 1272 "set"); 1273 } else if (eap_sm_method_pending(sess->eap)) { 1274 radius_msg_free(sess->last_msg); 1275 sess->last_msg = msg; 1276 sess->last_from_port = from_port; 1277 os_free(sess->last_from_addr); 1278 sess->last_from_addr = os_strdup(from_addr); 1279 sess->last_fromlen = fromlen; 1280 os_memcpy(&sess->last_from, from, fromlen); 1281 return -2; 1282 } else { 1283 RADIUS_DEBUG("No EAP data from the state machine - ignore this" 1284 " Access-Request silently (assuming it was a " 1285 "duplicate)"); 1286 data->counters.packets_dropped++; 1287 client->counters.packets_dropped++; 1288 return -1; 1289 } 1290 1291 if (sess->eap_if->eapSuccess || sess->eap_if->eapFail) 1292 is_complete = 1; 1293 if (sess->eap_if->eapFail) { 1294 srv_log(sess, "EAP authentication failed"); 1295 db_update_last_msk(sess, "FAIL"); 1296 } else if (sess->eap_if->eapSuccess) { 1297 srv_log(sess, "EAP authentication succeeded"); 1298 } 1299 1300 if (sess->eap_if->eapSuccess) 1301 radius_server_hs20_t_c_check(sess, msg); 1302 1303 reply = radius_server_encapsulate_eap(data, client, sess, msg); 1304 1305 send_reply: 1306 if (reply) { 1307 struct wpabuf *buf; 1308 struct radius_hdr *hdr; 1309 1310 RADIUS_DEBUG("Reply to %s:%d", from_addr, from_port); 1311 if (wpa_debug_level <= MSG_MSGDUMP) { 1312 radius_msg_dump(reply); 1313 } 1314 1315 switch (radius_msg_get_hdr(reply)->code) { 1316 case RADIUS_CODE_ACCESS_ACCEPT: 1317 srv_log(sess, "Sending Access-Accept"); 1318 data->counters.access_accepts++; 1319 client->counters.access_accepts++; 1320 break; 1321 case RADIUS_CODE_ACCESS_REJECT: 1322 srv_log(sess, "Sending Access-Reject"); 1323 data->counters.access_rejects++; 1324 client->counters.access_rejects++; 1325 break; 1326 case RADIUS_CODE_ACCESS_CHALLENGE: 1327 data->counters.access_challenges++; 1328 client->counters.access_challenges++; 1329 break; 1330 } 1331 buf = radius_msg_get_buf(reply); 1332 res = sendto(data->auth_sock, wpabuf_head(buf), 1333 wpabuf_len(buf), 0, 1334 (struct sockaddr *) from, fromlen); 1335 if (res < 0) { 1336 wpa_printf(MSG_INFO, "sendto[RADIUS SRV]: %s", 1337 strerror(errno)); 1338 } 1339 radius_msg_free(sess->last_reply); 1340 sess->last_reply = reply; 1341 sess->last_from_port = from_port; 1342 hdr = radius_msg_get_hdr(msg); 1343 sess->last_identifier = hdr->identifier; 1344 os_memcpy(sess->last_authenticator, hdr->authenticator, 16); 1345 } else { 1346 data->counters.packets_dropped++; 1347 client->counters.packets_dropped++; 1348 } 1349 1350 if (is_complete) { 1351 RADIUS_DEBUG("Removing completed session 0x%x after timeout", 1352 sess->sess_id); 1353 eloop_cancel_timeout(radius_server_session_remove_timeout, 1354 data, sess); 1355 eloop_register_timeout(RADIUS_SESSION_MAINTAIN, 0, 1356 radius_server_session_remove_timeout, 1357 data, sess); 1358 } 1359 1360 return 0; 1361 } 1362 1363 1364 static void radius_server_receive_disconnect_resp(struct radius_server_data * data,struct radius_client * client,struct radius_msg * msg,int ack)1365 radius_server_receive_disconnect_resp(struct radius_server_data *data, 1366 struct radius_client *client, 1367 struct radius_msg *msg, int ack) 1368 { 1369 struct radius_hdr *hdr; 1370 1371 if (!client->pending_dac_disconnect_req) { 1372 RADIUS_DEBUG("Ignore unexpected Disconnect response"); 1373 radius_msg_free(msg); 1374 return; 1375 } 1376 1377 hdr = radius_msg_get_hdr(msg); 1378 if (hdr->identifier != client->pending_dac_disconnect_id) { 1379 RADIUS_DEBUG("Ignore unexpected Disconnect response with unexpected identifier %u (expected %u)", 1380 hdr->identifier, 1381 client->pending_dac_disconnect_id); 1382 radius_msg_free(msg); 1383 return; 1384 } 1385 1386 if (radius_msg_verify(msg, (const u8 *) client->shared_secret, 1387 client->shared_secret_len, 1388 client->pending_dac_disconnect_req, 0)) { 1389 RADIUS_DEBUG("Ignore Disconnect response with invalid authenticator"); 1390 radius_msg_free(msg); 1391 return; 1392 } 1393 1394 RADIUS_DEBUG("Disconnect-%s received for " MACSTR, 1395 ack ? "ACK" : "NAK", 1396 MAC2STR(client->pending_dac_disconnect_addr)); 1397 1398 radius_msg_free(msg); 1399 radius_msg_free(client->pending_dac_disconnect_req); 1400 client->pending_dac_disconnect_req = NULL; 1401 } 1402 1403 radius_server_receive_coa_resp(struct radius_server_data * data,struct radius_client * client,struct radius_msg * msg,int ack)1404 static void radius_server_receive_coa_resp(struct radius_server_data *data, 1405 struct radius_client *client, 1406 struct radius_msg *msg, int ack) 1407 { 1408 struct radius_hdr *hdr; 1409 #ifdef CONFIG_SQLITE 1410 char addrtxt[3 * ETH_ALEN]; 1411 char *sql; 1412 int res; 1413 #endif /* CONFIG_SQLITE */ 1414 1415 if (!client->pending_dac_coa_req) { 1416 RADIUS_DEBUG("Ignore unexpected CoA response"); 1417 radius_msg_free(msg); 1418 return; 1419 } 1420 1421 hdr = radius_msg_get_hdr(msg); 1422 if (hdr->identifier != client->pending_dac_coa_id) { 1423 RADIUS_DEBUG("Ignore unexpected CoA response with unexpected identifier %u (expected %u)", 1424 hdr->identifier, 1425 client->pending_dac_coa_id); 1426 radius_msg_free(msg); 1427 return; 1428 } 1429 1430 if (radius_msg_verify(msg, (const u8 *) client->shared_secret, 1431 client->shared_secret_len, 1432 client->pending_dac_coa_req, 0)) { 1433 RADIUS_DEBUG("Ignore CoA response with invalid authenticator"); 1434 radius_msg_free(msg); 1435 return; 1436 } 1437 1438 RADIUS_DEBUG("CoA-%s received for " MACSTR, 1439 ack ? "ACK" : "NAK", 1440 MAC2STR(client->pending_dac_coa_addr)); 1441 1442 radius_msg_free(msg); 1443 radius_msg_free(client->pending_dac_coa_req); 1444 client->pending_dac_coa_req = NULL; 1445 1446 #ifdef CONFIG_SQLITE 1447 if (!data->db) 1448 return; 1449 1450 os_snprintf(addrtxt, sizeof(addrtxt), MACSTR, 1451 MAC2STR(client->pending_dac_coa_addr)); 1452 1453 if (ack) { 1454 sql = sqlite3_mprintf("UPDATE current_sessions SET hs20_t_c_filtering=0, waiting_coa_ack=0, coa_ack_received=1 WHERE mac_addr=%Q", 1455 addrtxt); 1456 } else { 1457 sql = sqlite3_mprintf("UPDATE current_sessions SET waiting_coa_ack=0 WHERE mac_addr=%Q", 1458 addrtxt); 1459 } 1460 if (!sql) 1461 return; 1462 1463 res = sqlite3_exec(data->db, sql, NULL, NULL, NULL); 1464 sqlite3_free(sql); 1465 if (res != SQLITE_OK) { 1466 RADIUS_ERROR("Failed to update current_sessions entry: %s", 1467 sqlite3_errmsg(data->db)); 1468 return; 1469 } 1470 #endif /* CONFIG_SQLITE */ 1471 } 1472 1473 radius_server_receive_auth(int sock,void * eloop_ctx,void * sock_ctx)1474 static void radius_server_receive_auth(int sock, void *eloop_ctx, 1475 void *sock_ctx) 1476 { 1477 struct radius_server_data *data = eloop_ctx; 1478 u8 *buf = NULL; 1479 union { 1480 struct sockaddr_storage ss; 1481 struct sockaddr_in sin; 1482 #ifdef CONFIG_IPV6 1483 struct sockaddr_in6 sin6; 1484 #endif /* CONFIG_IPV6 */ 1485 } from; 1486 socklen_t fromlen; 1487 int len; 1488 struct radius_client *client = NULL; 1489 struct radius_msg *msg = NULL; 1490 char abuf[50]; 1491 int from_port = 0; 1492 1493 buf = os_malloc(RADIUS_MAX_MSG_LEN); 1494 if (buf == NULL) { 1495 goto fail; 1496 } 1497 1498 fromlen = sizeof(from); 1499 len = recvfrom(sock, buf, RADIUS_MAX_MSG_LEN, 0, 1500 (struct sockaddr *) &from.ss, &fromlen); 1501 if (len < 0) { 1502 wpa_printf(MSG_INFO, "recvfrom[radius_server]: %s", 1503 strerror(errno)); 1504 goto fail; 1505 } 1506 1507 #ifdef CONFIG_IPV6 1508 if (data->ipv6) { 1509 if (inet_ntop(AF_INET6, &from.sin6.sin6_addr, abuf, 1510 sizeof(abuf)) == NULL) 1511 abuf[0] = '\0'; 1512 from_port = ntohs(from.sin6.sin6_port); 1513 RADIUS_DEBUG("Received %d bytes from %s:%d", 1514 len, abuf, from_port); 1515 1516 client = radius_server_get_client(data, 1517 (struct in_addr *) 1518 &from.sin6.sin6_addr, 1); 1519 } 1520 #endif /* CONFIG_IPV6 */ 1521 1522 if (!data->ipv6) { 1523 os_strlcpy(abuf, inet_ntoa(from.sin.sin_addr), sizeof(abuf)); 1524 from_port = ntohs(from.sin.sin_port); 1525 RADIUS_DEBUG("Received %d bytes from %s:%d", 1526 len, abuf, from_port); 1527 1528 client = radius_server_get_client(data, &from.sin.sin_addr, 0); 1529 } 1530 1531 RADIUS_DUMP("Received data", buf, len); 1532 1533 if (client == NULL) { 1534 RADIUS_DEBUG("Unknown client %s - packet ignored", abuf); 1535 data->counters.invalid_requests++; 1536 goto fail; 1537 } 1538 1539 msg = radius_msg_parse(buf, len); 1540 if (msg == NULL) { 1541 RADIUS_DEBUG("Parsing incoming RADIUS frame failed"); 1542 data->counters.malformed_access_requests++; 1543 client->counters.malformed_access_requests++; 1544 goto fail; 1545 } 1546 1547 os_free(buf); 1548 buf = NULL; 1549 1550 if (wpa_debug_level <= MSG_MSGDUMP) { 1551 radius_msg_dump(msg); 1552 } 1553 1554 if (radius_msg_get_hdr(msg)->code == RADIUS_CODE_DISCONNECT_ACK) { 1555 radius_server_receive_disconnect_resp(data, client, msg, 1); 1556 return; 1557 } 1558 1559 if (radius_msg_get_hdr(msg)->code == RADIUS_CODE_DISCONNECT_NAK) { 1560 radius_server_receive_disconnect_resp(data, client, msg, 0); 1561 return; 1562 } 1563 1564 if (radius_msg_get_hdr(msg)->code == RADIUS_CODE_COA_ACK) { 1565 radius_server_receive_coa_resp(data, client, msg, 1); 1566 return; 1567 } 1568 1569 if (radius_msg_get_hdr(msg)->code == RADIUS_CODE_COA_NAK) { 1570 radius_server_receive_coa_resp(data, client, msg, 0); 1571 return; 1572 } 1573 1574 if (radius_msg_get_hdr(msg)->code != RADIUS_CODE_ACCESS_REQUEST) { 1575 RADIUS_DEBUG("Unexpected RADIUS code %d", 1576 radius_msg_get_hdr(msg)->code); 1577 data->counters.unknown_types++; 1578 client->counters.unknown_types++; 1579 goto fail; 1580 } 1581 1582 data->counters.access_requests++; 1583 client->counters.access_requests++; 1584 1585 if (radius_msg_verify_msg_auth(msg, (u8 *) client->shared_secret, 1586 client->shared_secret_len, NULL)) { 1587 RADIUS_DEBUG("Invalid Message-Authenticator from %s", abuf); 1588 data->counters.bad_authenticators++; 1589 client->counters.bad_authenticators++; 1590 goto fail; 1591 } 1592 1593 if (radius_server_request(data, msg, (struct sockaddr *) &from, 1594 fromlen, client, abuf, from_port, NULL) == 1595 -2) 1596 return; /* msg was stored with the session */ 1597 1598 fail: 1599 radius_msg_free(msg); 1600 os_free(buf); 1601 } 1602 1603 radius_server_receive_acct(int sock,void * eloop_ctx,void * sock_ctx)1604 static void radius_server_receive_acct(int sock, void *eloop_ctx, 1605 void *sock_ctx) 1606 { 1607 struct radius_server_data *data = eloop_ctx; 1608 u8 *buf = NULL; 1609 union { 1610 struct sockaddr_storage ss; 1611 struct sockaddr_in sin; 1612 #ifdef CONFIG_IPV6 1613 struct sockaddr_in6 sin6; 1614 #endif /* CONFIG_IPV6 */ 1615 } from; 1616 socklen_t fromlen; 1617 int len, res; 1618 struct radius_client *client = NULL; 1619 struct radius_msg *msg = NULL, *resp = NULL; 1620 char abuf[50]; 1621 int from_port = 0; 1622 struct radius_hdr *hdr; 1623 struct wpabuf *rbuf; 1624 u32 status_type; 1625 1626 buf = os_malloc(RADIUS_MAX_MSG_LEN); 1627 if (buf == NULL) { 1628 goto fail; 1629 } 1630 1631 fromlen = sizeof(from); 1632 len = recvfrom(sock, buf, RADIUS_MAX_MSG_LEN, 0, 1633 (struct sockaddr *) &from.ss, &fromlen); 1634 if (len < 0) { 1635 wpa_printf(MSG_INFO, "recvfrom[radius_server]: %s", 1636 strerror(errno)); 1637 goto fail; 1638 } 1639 1640 #ifdef CONFIG_IPV6 1641 if (data->ipv6) { 1642 if (inet_ntop(AF_INET6, &from.sin6.sin6_addr, abuf, 1643 sizeof(abuf)) == NULL) 1644 abuf[0] = '\0'; 1645 from_port = ntohs(from.sin6.sin6_port); 1646 RADIUS_DEBUG("Received %d bytes from %s:%d", 1647 len, abuf, from_port); 1648 1649 client = radius_server_get_client(data, 1650 (struct in_addr *) 1651 &from.sin6.sin6_addr, 1); 1652 } 1653 #endif /* CONFIG_IPV6 */ 1654 1655 if (!data->ipv6) { 1656 os_strlcpy(abuf, inet_ntoa(from.sin.sin_addr), sizeof(abuf)); 1657 from_port = ntohs(from.sin.sin_port); 1658 RADIUS_DEBUG("Received %d bytes from %s:%d", 1659 len, abuf, from_port); 1660 1661 client = radius_server_get_client(data, &from.sin.sin_addr, 0); 1662 } 1663 1664 RADIUS_DUMP("Received data", buf, len); 1665 1666 if (client == NULL) { 1667 RADIUS_DEBUG("Unknown client %s - packet ignored", abuf); 1668 data->counters.invalid_acct_requests++; 1669 goto fail; 1670 } 1671 1672 msg = radius_msg_parse(buf, len); 1673 if (msg == NULL) { 1674 RADIUS_DEBUG("Parsing incoming RADIUS frame failed"); 1675 data->counters.malformed_acct_requests++; 1676 client->counters.malformed_acct_requests++; 1677 goto fail; 1678 } 1679 1680 os_free(buf); 1681 buf = NULL; 1682 1683 if (wpa_debug_level <= MSG_MSGDUMP) { 1684 radius_msg_dump(msg); 1685 } 1686 1687 if (radius_msg_get_hdr(msg)->code != RADIUS_CODE_ACCOUNTING_REQUEST) { 1688 RADIUS_DEBUG("Unexpected RADIUS code %d", 1689 radius_msg_get_hdr(msg)->code); 1690 data->counters.unknown_acct_types++; 1691 client->counters.unknown_acct_types++; 1692 goto fail; 1693 } 1694 1695 data->counters.acct_requests++; 1696 client->counters.acct_requests++; 1697 1698 if (radius_msg_verify_acct_req(msg, (u8 *) client->shared_secret, 1699 client->shared_secret_len)) { 1700 RADIUS_DEBUG("Invalid Authenticator from %s", abuf); 1701 data->counters.acct_bad_authenticators++; 1702 client->counters.acct_bad_authenticators++; 1703 goto fail; 1704 } 1705 1706 /* Parse Acct-Status-Type from Accounting-Request */ 1707 if (radius_msg_get_attr_int32(msg, RADIUS_ATTR_ACCT_STATUS_TYPE, 1708 &status_type) != 0) { 1709 RADIUS_DEBUG("Unable to parse Acct-Status-Type from %s", abuf); 1710 goto fail; 1711 } 1712 1713 /* Process accounting information by configured callback */ 1714 if (data->acct_req_cb && 1715 data->acct_req_cb(data->conf_ctx, msg, status_type) != 0) { 1716 RADIUS_DEBUG("Accounting request callback returned non-zero code indicating processing failure (from %s)", 1717 abuf); 1718 goto fail; 1719 } 1720 1721 hdr = radius_msg_get_hdr(msg); 1722 1723 resp = radius_msg_new(RADIUS_CODE_ACCOUNTING_RESPONSE, hdr->identifier); 1724 if (resp == NULL) 1725 goto fail; 1726 1727 if (radius_msg_finish_acct_resp(resp, (u8 *) client->shared_secret, 1728 client->shared_secret_len, 1729 hdr->authenticator) < 0) { 1730 RADIUS_ERROR("Failed to add Message-Authenticator attribute"); 1731 goto fail; 1732 } 1733 1734 RADIUS_DEBUG("Reply to %s:%d", abuf, from_port); 1735 if (wpa_debug_level <= MSG_MSGDUMP) { 1736 radius_msg_dump(resp); 1737 } 1738 rbuf = radius_msg_get_buf(resp); 1739 data->counters.acct_responses++; 1740 client->counters.acct_responses++; 1741 res = sendto(data->acct_sock, wpabuf_head(rbuf), wpabuf_len(rbuf), 0, 1742 (struct sockaddr *) &from.ss, fromlen); 1743 if (res < 0) { 1744 wpa_printf(MSG_INFO, "sendto[RADIUS SRV]: %s", 1745 strerror(errno)); 1746 } 1747 1748 fail: 1749 radius_msg_free(resp); 1750 radius_msg_free(msg); 1751 os_free(buf); 1752 } 1753 1754 radius_server_disable_pmtu_discovery(int s)1755 static int radius_server_disable_pmtu_discovery(int s) 1756 { 1757 int r = -1; 1758 #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) 1759 /* Turn off Path MTU discovery on IPv4/UDP sockets. */ 1760 int action = IP_PMTUDISC_DONT; 1761 r = setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, &action, 1762 sizeof(action)); 1763 if (r == -1) 1764 wpa_printf(MSG_ERROR, "Failed to set IP_MTU_DISCOVER: " 1765 "%s", strerror(errno)); 1766 #endif 1767 return r; 1768 } 1769 1770 radius_server_open_socket(int port)1771 static int radius_server_open_socket(int port) 1772 { 1773 int s; 1774 struct sockaddr_in addr; 1775 1776 s = socket(PF_INET, SOCK_DGRAM, 0); 1777 if (s < 0) { 1778 wpa_printf(MSG_INFO, "RADIUS: socket: %s", strerror(errno)); 1779 return -1; 1780 } 1781 1782 radius_server_disable_pmtu_discovery(s); 1783 1784 os_memset(&addr, 0, sizeof(addr)); 1785 addr.sin_family = AF_INET; 1786 addr.sin_port = htons(port); 1787 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 1788 wpa_printf(MSG_INFO, "RADIUS: bind: %s", strerror(errno)); 1789 close(s); 1790 return -1; 1791 } 1792 1793 return s; 1794 } 1795 1796 1797 #ifdef CONFIG_IPV6 radius_server_open_socket6(int port)1798 static int radius_server_open_socket6(int port) 1799 { 1800 int s; 1801 struct sockaddr_in6 addr; 1802 1803 s = socket(PF_INET6, SOCK_DGRAM, 0); 1804 if (s < 0) { 1805 wpa_printf(MSG_INFO, "RADIUS: socket[IPv6]: %s", 1806 strerror(errno)); 1807 return -1; 1808 } 1809 1810 os_memset(&addr, 0, sizeof(addr)); 1811 addr.sin6_family = AF_INET6; 1812 os_memcpy(&addr.sin6_addr, &in6addr_any, sizeof(in6addr_any)); 1813 addr.sin6_port = htons(port); 1814 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 1815 wpa_printf(MSG_INFO, "RADIUS: bind: %s", strerror(errno)); 1816 close(s); 1817 return -1; 1818 } 1819 1820 return s; 1821 } 1822 #endif /* CONFIG_IPV6 */ 1823 1824 radius_server_free_sessions(struct radius_server_data * data,struct radius_session * sessions)1825 static void radius_server_free_sessions(struct radius_server_data *data, 1826 struct radius_session *sessions) 1827 { 1828 struct radius_session *session, *prev; 1829 1830 session = sessions; 1831 while (session) { 1832 prev = session; 1833 session = session->next; 1834 radius_server_session_free(data, prev); 1835 } 1836 } 1837 1838 radius_server_free_clients(struct radius_server_data * data,struct radius_client * clients)1839 static void radius_server_free_clients(struct radius_server_data *data, 1840 struct radius_client *clients) 1841 { 1842 struct radius_client *client, *prev; 1843 1844 client = clients; 1845 while (client) { 1846 prev = client; 1847 client = client->next; 1848 1849 radius_server_free_sessions(data, prev->sessions); 1850 os_free(prev->shared_secret); 1851 radius_msg_free(prev->pending_dac_coa_req); 1852 radius_msg_free(prev->pending_dac_disconnect_req); 1853 os_free(prev); 1854 } 1855 } 1856 1857 1858 static struct radius_client * radius_server_read_clients(const char * client_file,int ipv6)1859 radius_server_read_clients(const char *client_file, int ipv6) 1860 { 1861 FILE *f; 1862 const int buf_size = 1024; 1863 char *buf, *pos; 1864 struct radius_client *clients, *tail, *entry; 1865 int line = 0, mask, failed = 0, i; 1866 struct in_addr addr; 1867 #ifdef CONFIG_IPV6 1868 struct in6_addr addr6; 1869 #endif /* CONFIG_IPV6 */ 1870 unsigned int val; 1871 1872 f = fopen(client_file, "r"); 1873 if (f == NULL) { 1874 RADIUS_ERROR("Could not open client file '%s'", client_file); 1875 return NULL; 1876 } 1877 1878 buf = os_malloc(buf_size); 1879 if (buf == NULL) { 1880 fclose(f); 1881 return NULL; 1882 } 1883 1884 clients = tail = NULL; 1885 while (fgets(buf, buf_size, f)) { 1886 /* Configuration file format: 1887 * 192.168.1.0/24 secret 1888 * 192.168.1.2 secret 1889 * fe80::211:22ff:fe33:4455/64 secretipv6 1890 */ 1891 line++; 1892 buf[buf_size - 1] = '\0'; 1893 pos = buf; 1894 while (*pos != '\0' && *pos != '\n') 1895 pos++; 1896 if (*pos == '\n') 1897 *pos = '\0'; 1898 if (*buf == '\0' || *buf == '#') 1899 continue; 1900 1901 pos = buf; 1902 while ((*pos >= '0' && *pos <= '9') || *pos == '.' || 1903 (*pos >= 'a' && *pos <= 'f') || *pos == ':' || 1904 (*pos >= 'A' && *pos <= 'F')) { 1905 pos++; 1906 } 1907 1908 if (*pos == '\0') { 1909 failed = 1; 1910 break; 1911 } 1912 1913 if (*pos == '/') { 1914 char *end; 1915 *pos++ = '\0'; 1916 mask = strtol(pos, &end, 10); 1917 if ((pos == end) || 1918 (mask < 0 || mask > (ipv6 ? 128 : 32))) { 1919 failed = 1; 1920 break; 1921 } 1922 pos = end; 1923 } else { 1924 mask = ipv6 ? 128 : 32; 1925 *pos++ = '\0'; 1926 } 1927 1928 if (!ipv6 && inet_aton(buf, &addr) == 0) { 1929 failed = 1; 1930 break; 1931 } 1932 #ifdef CONFIG_IPV6 1933 if (ipv6 && inet_pton(AF_INET6, buf, &addr6) <= 0) { 1934 if (inet_pton(AF_INET, buf, &addr) <= 0) { 1935 failed = 1; 1936 break; 1937 } 1938 /* Convert IPv4 address to IPv6 */ 1939 if (mask <= 32) 1940 mask += (128 - 32); 1941 os_memset(addr6.s6_addr, 0, 10); 1942 addr6.s6_addr[10] = 0xff; 1943 addr6.s6_addr[11] = 0xff; 1944 os_memcpy(addr6.s6_addr + 12, (char *) &addr.s_addr, 1945 4); 1946 } 1947 #endif /* CONFIG_IPV6 */ 1948 1949 while (*pos == ' ' || *pos == '\t') { 1950 pos++; 1951 } 1952 1953 if (*pos == '\0') { 1954 failed = 1; 1955 break; 1956 } 1957 1958 entry = os_zalloc(sizeof(*entry)); 1959 if (entry == NULL) { 1960 failed = 1; 1961 break; 1962 } 1963 entry->shared_secret = os_strdup(pos); 1964 if (entry->shared_secret == NULL) { 1965 failed = 1; 1966 os_free(entry); 1967 break; 1968 } 1969 entry->shared_secret_len = os_strlen(entry->shared_secret); 1970 if (!ipv6) { 1971 entry->addr.s_addr = addr.s_addr; 1972 val = 0; 1973 for (i = 0; i < mask; i++) 1974 val |= 1U << (31 - i); 1975 entry->mask.s_addr = htonl(val); 1976 } 1977 #ifdef CONFIG_IPV6 1978 if (ipv6) { 1979 int offset = mask / 8; 1980 1981 os_memcpy(entry->addr6.s6_addr, addr6.s6_addr, 16); 1982 os_memset(entry->mask6.s6_addr, 0xff, offset); 1983 val = 0; 1984 for (i = 0; i < (mask % 8); i++) 1985 val |= 1 << (7 - i); 1986 if (offset < 16) 1987 entry->mask6.s6_addr[offset] = val; 1988 } 1989 #endif /* CONFIG_IPV6 */ 1990 1991 if (tail == NULL) { 1992 clients = tail = entry; 1993 } else { 1994 tail->next = entry; 1995 tail = entry; 1996 } 1997 } 1998 1999 if (failed) { 2000 RADIUS_ERROR("Invalid line %d in '%s'", line, client_file); 2001 radius_server_free_clients(NULL, clients); 2002 clients = NULL; 2003 } 2004 2005 os_free(buf); 2006 fclose(f); 2007 2008 return clients; 2009 } 2010 2011 2012 /** 2013 * radius_server_init - Initialize RADIUS server 2014 * @conf: Configuration for the RADIUS server 2015 * Returns: Pointer to private RADIUS server context or %NULL on failure 2016 * 2017 * This initializes a RADIUS server instance and returns a context pointer that 2018 * will be used in other calls to the RADIUS server module. The server can be 2019 * deinitialize by calling radius_server_deinit(). 2020 */ 2021 struct radius_server_data * radius_server_init(struct radius_server_conf * conf)2022 radius_server_init(struct radius_server_conf *conf) 2023 { 2024 struct radius_server_data *data; 2025 2026 #ifndef CONFIG_IPV6 2027 if (conf->ipv6) { 2028 wpa_printf(MSG_ERROR, "RADIUS server compiled without IPv6 support"); 2029 return NULL; 2030 } 2031 #endif /* CONFIG_IPV6 */ 2032 2033 data = os_zalloc(sizeof(*data)); 2034 if (data == NULL) 2035 return NULL; 2036 2037 data->eap_cfg = conf->eap_cfg; 2038 data->auth_sock = -1; 2039 data->acct_sock = -1; 2040 dl_list_init(&data->erp_keys); 2041 os_get_reltime(&data->start_time); 2042 data->conf_ctx = conf->conf_ctx; 2043 conf->eap_cfg->backend_auth = true; 2044 conf->eap_cfg->eap_server = 1; 2045 data->ipv6 = conf->ipv6; 2046 data->get_eap_user = conf->get_eap_user; 2047 data->acct_req_cb = conf->acct_req_cb; 2048 if (conf->eap_req_id_text) { 2049 data->eap_req_id_text = os_malloc(conf->eap_req_id_text_len); 2050 if (!data->eap_req_id_text) 2051 goto fail; 2052 os_memcpy(data->eap_req_id_text, conf->eap_req_id_text, 2053 conf->eap_req_id_text_len); 2054 data->eap_req_id_text_len = conf->eap_req_id_text_len; 2055 } 2056 data->erp_domain = conf->erp_domain; 2057 2058 if (conf->t_c_server_url) { 2059 data->t_c_server_url = os_strdup(conf->t_c_server_url); 2060 if (!data->t_c_server_url) 2061 goto fail; 2062 } 2063 2064 #ifdef CONFIG_SQLITE 2065 if (conf->sqlite_file) { 2066 if (sqlite3_open(conf->sqlite_file, &data->db)) { 2067 RADIUS_ERROR("Could not open SQLite file '%s'", 2068 conf->sqlite_file); 2069 goto fail; 2070 } 2071 } 2072 #endif /* CONFIG_SQLITE */ 2073 2074 #ifdef CONFIG_RADIUS_TEST 2075 if (conf->dump_msk_file) 2076 data->dump_msk_file = os_strdup(conf->dump_msk_file); 2077 #endif /* CONFIG_RADIUS_TEST */ 2078 2079 data->clients = radius_server_read_clients(conf->client_file, 2080 conf->ipv6); 2081 if (data->clients == NULL) { 2082 wpa_printf(MSG_ERROR, "No RADIUS clients configured"); 2083 goto fail; 2084 } 2085 2086 #ifdef CONFIG_IPV6 2087 if (conf->ipv6) 2088 data->auth_sock = radius_server_open_socket6(conf->auth_port); 2089 else 2090 #endif /* CONFIG_IPV6 */ 2091 data->auth_sock = radius_server_open_socket(conf->auth_port); 2092 if (data->auth_sock < 0) { 2093 wpa_printf(MSG_ERROR, "Failed to open UDP socket for RADIUS authentication server"); 2094 goto fail; 2095 } 2096 if (eloop_register_read_sock(data->auth_sock, 2097 radius_server_receive_auth, 2098 data, NULL)) { 2099 goto fail; 2100 } 2101 2102 if (conf->acct_port) { 2103 #ifdef CONFIG_IPV6 2104 if (conf->ipv6) 2105 data->acct_sock = radius_server_open_socket6( 2106 conf->acct_port); 2107 else 2108 #endif /* CONFIG_IPV6 */ 2109 data->acct_sock = radius_server_open_socket(conf->acct_port); 2110 if (data->acct_sock < 0) { 2111 wpa_printf(MSG_ERROR, "Failed to open UDP socket for RADIUS accounting server"); 2112 goto fail; 2113 } 2114 if (eloop_register_read_sock(data->acct_sock, 2115 radius_server_receive_acct, 2116 data, NULL)) 2117 goto fail; 2118 } else { 2119 data->acct_sock = -1; 2120 } 2121 2122 return data; 2123 fail: 2124 radius_server_deinit(data); 2125 return NULL; 2126 } 2127 2128 2129 /** 2130 * radius_server_erp_flush - Flush all ERP keys 2131 * @data: RADIUS server context from radius_server_init() 2132 */ radius_server_erp_flush(struct radius_server_data * data)2133 void radius_server_erp_flush(struct radius_server_data *data) 2134 { 2135 struct eap_server_erp_key *erp; 2136 2137 if (data == NULL) 2138 return; 2139 while ((erp = dl_list_first(&data->erp_keys, struct eap_server_erp_key, 2140 list)) != NULL) { 2141 dl_list_del(&erp->list); 2142 bin_clear_free(erp, sizeof(*erp)); 2143 } 2144 } 2145 2146 2147 /** 2148 * radius_server_deinit - Deinitialize RADIUS server 2149 * @data: RADIUS server context from radius_server_init() 2150 */ radius_server_deinit(struct radius_server_data * data)2151 void radius_server_deinit(struct radius_server_data *data) 2152 { 2153 if (data == NULL) 2154 return; 2155 2156 if (data->auth_sock >= 0) { 2157 eloop_unregister_read_sock(data->auth_sock); 2158 close(data->auth_sock); 2159 } 2160 2161 if (data->acct_sock >= 0) { 2162 eloop_unregister_read_sock(data->acct_sock); 2163 close(data->acct_sock); 2164 } 2165 2166 radius_server_free_clients(data, data->clients); 2167 2168 os_free(data->eap_req_id_text); 2169 #ifdef CONFIG_RADIUS_TEST 2170 os_free(data->dump_msk_file); 2171 #endif /* CONFIG_RADIUS_TEST */ 2172 os_free(data->t_c_server_url); 2173 2174 #ifdef CONFIG_SQLITE 2175 if (data->db) 2176 sqlite3_close(data->db); 2177 #endif /* CONFIG_SQLITE */ 2178 2179 radius_server_erp_flush(data); 2180 2181 os_free(data); 2182 } 2183 2184 2185 /** 2186 * radius_server_get_mib - Get RADIUS server MIB information 2187 * @data: RADIUS server context from radius_server_init() 2188 * @buf: Buffer for returning the MIB data in text format 2189 * @buflen: buf length in octets 2190 * Returns: Number of octets written into buf 2191 */ radius_server_get_mib(struct radius_server_data * data,char * buf,size_t buflen)2192 int radius_server_get_mib(struct radius_server_data *data, char *buf, 2193 size_t buflen) 2194 { 2195 int ret, uptime; 2196 unsigned int idx; 2197 char *end, *pos; 2198 struct os_reltime now; 2199 struct radius_client *cli; 2200 2201 /* RFC 2619 - RADIUS Authentication Server MIB */ 2202 2203 if (data == NULL || buflen == 0) 2204 return 0; 2205 2206 pos = buf; 2207 end = buf + buflen; 2208 2209 os_get_reltime(&now); 2210 uptime = (now.sec - data->start_time.sec) * 100 + 2211 ((now.usec - data->start_time.usec) / 10000) % 100; 2212 ret = os_snprintf(pos, end - pos, 2213 "RADIUS-AUTH-SERVER-MIB\n" 2214 "radiusAuthServIdent=hostapd\n" 2215 "radiusAuthServUpTime=%d\n" 2216 "radiusAuthServResetTime=0\n" 2217 "radiusAuthServConfigReset=4\n", 2218 uptime); 2219 if (os_snprintf_error(end - pos, ret)) { 2220 *pos = '\0'; 2221 return pos - buf; 2222 } 2223 pos += ret; 2224 2225 ret = os_snprintf(pos, end - pos, 2226 "radiusAuthServTotalAccessRequests=%u\n" 2227 "radiusAuthServTotalInvalidRequests=%u\n" 2228 "radiusAuthServTotalDupAccessRequests=%u\n" 2229 "radiusAuthServTotalAccessAccepts=%u\n" 2230 "radiusAuthServTotalAccessRejects=%u\n" 2231 "radiusAuthServTotalAccessChallenges=%u\n" 2232 "radiusAuthServTotalMalformedAccessRequests=%u\n" 2233 "radiusAuthServTotalBadAuthenticators=%u\n" 2234 "radiusAuthServTotalPacketsDropped=%u\n" 2235 "radiusAuthServTotalUnknownTypes=%u\n" 2236 "radiusAccServTotalRequests=%u\n" 2237 "radiusAccServTotalInvalidRequests=%u\n" 2238 "radiusAccServTotalResponses=%u\n" 2239 "radiusAccServTotalMalformedRequests=%u\n" 2240 "radiusAccServTotalBadAuthenticators=%u\n" 2241 "radiusAccServTotalUnknownTypes=%u\n", 2242 data->counters.access_requests, 2243 data->counters.invalid_requests, 2244 data->counters.dup_access_requests, 2245 data->counters.access_accepts, 2246 data->counters.access_rejects, 2247 data->counters.access_challenges, 2248 data->counters.malformed_access_requests, 2249 data->counters.bad_authenticators, 2250 data->counters.packets_dropped, 2251 data->counters.unknown_types, 2252 data->counters.acct_requests, 2253 data->counters.invalid_acct_requests, 2254 data->counters.acct_responses, 2255 data->counters.malformed_acct_requests, 2256 data->counters.acct_bad_authenticators, 2257 data->counters.unknown_acct_types); 2258 if (os_snprintf_error(end - pos, ret)) { 2259 *pos = '\0'; 2260 return pos - buf; 2261 } 2262 pos += ret; 2263 2264 for (cli = data->clients, idx = 0; cli; cli = cli->next, idx++) { 2265 char abuf[50], mbuf[50]; 2266 #ifdef CONFIG_IPV6 2267 if (data->ipv6) { 2268 if (inet_ntop(AF_INET6, &cli->addr6, abuf, 2269 sizeof(abuf)) == NULL) 2270 abuf[0] = '\0'; 2271 if (inet_ntop(AF_INET6, &cli->mask6, mbuf, 2272 sizeof(mbuf)) == NULL) 2273 mbuf[0] = '\0'; 2274 } 2275 #endif /* CONFIG_IPV6 */ 2276 if (!data->ipv6) { 2277 os_strlcpy(abuf, inet_ntoa(cli->addr), sizeof(abuf)); 2278 os_strlcpy(mbuf, inet_ntoa(cli->mask), sizeof(mbuf)); 2279 } 2280 2281 ret = os_snprintf(pos, end - pos, 2282 "radiusAuthClientIndex=%u\n" 2283 "radiusAuthClientAddress=%s/%s\n" 2284 "radiusAuthServAccessRequests=%u\n" 2285 "radiusAuthServDupAccessRequests=%u\n" 2286 "radiusAuthServAccessAccepts=%u\n" 2287 "radiusAuthServAccessRejects=%u\n" 2288 "radiusAuthServAccessChallenges=%u\n" 2289 "radiusAuthServMalformedAccessRequests=%u\n" 2290 "radiusAuthServBadAuthenticators=%u\n" 2291 "radiusAuthServPacketsDropped=%u\n" 2292 "radiusAuthServUnknownTypes=%u\n" 2293 "radiusAccServTotalRequests=%u\n" 2294 "radiusAccServTotalInvalidRequests=%u\n" 2295 "radiusAccServTotalResponses=%u\n" 2296 "radiusAccServTotalMalformedRequests=%u\n" 2297 "radiusAccServTotalBadAuthenticators=%u\n" 2298 "radiusAccServTotalUnknownTypes=%u\n", 2299 idx, 2300 abuf, mbuf, 2301 cli->counters.access_requests, 2302 cli->counters.dup_access_requests, 2303 cli->counters.access_accepts, 2304 cli->counters.access_rejects, 2305 cli->counters.access_challenges, 2306 cli->counters.malformed_access_requests, 2307 cli->counters.bad_authenticators, 2308 cli->counters.packets_dropped, 2309 cli->counters.unknown_types, 2310 cli->counters.acct_requests, 2311 cli->counters.invalid_acct_requests, 2312 cli->counters.acct_responses, 2313 cli->counters.malformed_acct_requests, 2314 cli->counters.acct_bad_authenticators, 2315 cli->counters.unknown_acct_types); 2316 if (os_snprintf_error(end - pos, ret)) { 2317 *pos = '\0'; 2318 return pos - buf; 2319 } 2320 pos += ret; 2321 } 2322 2323 return pos - buf; 2324 } 2325 2326 radius_server_get_eap_user(void * ctx,const u8 * identity,size_t identity_len,int phase2,struct eap_user * user)2327 static int radius_server_get_eap_user(void *ctx, const u8 *identity, 2328 size_t identity_len, int phase2, 2329 struct eap_user *user) 2330 { 2331 struct radius_session *sess = ctx; 2332 struct radius_server_data *data = sess->server; 2333 int ret; 2334 2335 ret = data->get_eap_user(data->conf_ctx, identity, identity_len, 2336 phase2, user); 2337 if (ret == 0 && user) { 2338 sess->accept_attr = user->accept_attr; 2339 sess->macacl = user->macacl; 2340 sess->t_c_timestamp = user->t_c_timestamp; 2341 } 2342 2343 if (ret) { 2344 RADIUS_DEBUG("%s: User-Name not found from user database", 2345 __func__); 2346 } 2347 2348 return ret; 2349 } 2350 2351 radius_server_get_eap_req_id_text(void * ctx,size_t * len)2352 static const char * radius_server_get_eap_req_id_text(void *ctx, size_t *len) 2353 { 2354 struct radius_session *sess = ctx; 2355 struct radius_server_data *data = sess->server; 2356 *len = data->eap_req_id_text_len; 2357 return data->eap_req_id_text; 2358 } 2359 2360 radius_server_log_msg(void * ctx,const char * msg)2361 static void radius_server_log_msg(void *ctx, const char *msg) 2362 { 2363 struct radius_session *sess = ctx; 2364 srv_log(sess, "EAP: %s", msg); 2365 } 2366 2367 2368 #ifdef CONFIG_ERP 2369 radius_server_get_erp_domain(void * ctx)2370 static const char * radius_server_get_erp_domain(void *ctx) 2371 { 2372 struct radius_session *sess = ctx; 2373 struct radius_server_data *data = sess->server; 2374 2375 return data->erp_domain; 2376 } 2377 2378 2379 static struct eap_server_erp_key * radius_server_erp_get_key(void * ctx,const char * keyname)2380 radius_server_erp_get_key(void *ctx, const char *keyname) 2381 { 2382 struct radius_session *sess = ctx; 2383 struct radius_server_data *data = sess->server; 2384 2385 return radius_server_erp_find_key(data, keyname); 2386 } 2387 2388 radius_server_erp_add_key(void * ctx,struct eap_server_erp_key * erp)2389 static int radius_server_erp_add_key(void *ctx, struct eap_server_erp_key *erp) 2390 { 2391 struct radius_session *sess = ctx; 2392 struct radius_server_data *data = sess->server; 2393 2394 dl_list_add(&data->erp_keys, &erp->list); 2395 return 0; 2396 } 2397 2398 #endif /* CONFIG_ERP */ 2399 2400 2401 static const struct eapol_callbacks radius_server_eapol_cb = 2402 { 2403 .get_eap_user = radius_server_get_eap_user, 2404 .get_eap_req_id_text = radius_server_get_eap_req_id_text, 2405 .log_msg = radius_server_log_msg, 2406 #ifdef CONFIG_ERP 2407 .get_erp_send_reauth_start = NULL, 2408 .get_erp_domain = radius_server_get_erp_domain, 2409 .erp_get_key = radius_server_erp_get_key, 2410 .erp_add_key = radius_server_erp_add_key, 2411 #endif /* CONFIG_ERP */ 2412 }; 2413 2414 2415 /** 2416 * radius_server_eap_pending_cb - Pending EAP data notification 2417 * @data: RADIUS server context from radius_server_init() 2418 * @ctx: Pending EAP context pointer 2419 * 2420 * This function is used to notify EAP server module that a pending operation 2421 * has been completed and processing of the EAP session can proceed. 2422 */ radius_server_eap_pending_cb(struct radius_server_data * data,void * ctx)2423 void radius_server_eap_pending_cb(struct radius_server_data *data, void *ctx) 2424 { 2425 struct radius_client *cli; 2426 struct radius_session *s, *sess = NULL; 2427 struct radius_msg *msg; 2428 2429 if (data == NULL) 2430 return; 2431 2432 for (cli = data->clients; cli; cli = cli->next) { 2433 for (s = cli->sessions; s; s = s->next) { 2434 if (s->eap == ctx && s->last_msg) { 2435 sess = s; 2436 break; 2437 } 2438 } 2439 if (sess) 2440 break; 2441 } 2442 2443 if (sess == NULL) { 2444 RADIUS_DEBUG("No session matched callback ctx"); 2445 return; 2446 } 2447 2448 msg = sess->last_msg; 2449 sess->last_msg = NULL; 2450 eap_sm_pending_cb(sess->eap); 2451 if (radius_server_request(data, msg, 2452 (struct sockaddr *) &sess->last_from, 2453 sess->last_fromlen, cli, 2454 sess->last_from_addr, 2455 sess->last_from_port, sess) == -2) 2456 return; /* msg was stored with the session */ 2457 2458 radius_msg_free(msg); 2459 } 2460 2461 2462 #ifdef CONFIG_SQLITE 2463 2464 struct db_session_fields { 2465 char *identity; 2466 char *nas; 2467 int hs20_t_c_filtering; 2468 int waiting_coa_ack; 2469 int coa_ack_received; 2470 }; 2471 2472 get_db_session_fields(void * ctx,int argc,char * argv[],char * col[])2473 static int get_db_session_fields(void *ctx, int argc, char *argv[], char *col[]) 2474 { 2475 struct db_session_fields *fields = ctx; 2476 int i; 2477 2478 for (i = 0; i < argc; i++) { 2479 if (!argv[i]) 2480 continue; 2481 2482 RADIUS_DEBUG("Session DB: %s=%s", col[i], argv[i]); 2483 2484 if (os_strcmp(col[i], "identity") == 0) { 2485 os_free(fields->identity); 2486 fields->identity = os_strdup(argv[i]); 2487 } else if (os_strcmp(col[i], "nas") == 0) { 2488 os_free(fields->nas); 2489 fields->nas = os_strdup(argv[i]); 2490 } else if (os_strcmp(col[i], "hs20_t_c_filtering") == 0) { 2491 fields->hs20_t_c_filtering = atoi(argv[i]); 2492 } else if (os_strcmp(col[i], "waiting_coa_ack") == 0) { 2493 fields->waiting_coa_ack = atoi(argv[i]); 2494 } else if (os_strcmp(col[i], "coa_ack_received") == 0) { 2495 fields->coa_ack_received = atoi(argv[i]); 2496 } 2497 } 2498 2499 return 0; 2500 } 2501 2502 free_db_session_fields(struct db_session_fields * fields)2503 static void free_db_session_fields(struct db_session_fields *fields) 2504 { 2505 os_free(fields->identity); 2506 fields->identity = NULL; 2507 os_free(fields->nas); 2508 fields->nas = NULL; 2509 } 2510 2511 #endif /* CONFIG_SQLITE */ 2512 2513 radius_server_dac_request(struct radius_server_data * data,const char * req)2514 int radius_server_dac_request(struct radius_server_data *data, const char *req) 2515 { 2516 #ifdef CONFIG_SQLITE 2517 char *sql; 2518 int res; 2519 int disconnect; 2520 const char *pos = req; 2521 u8 addr[ETH_ALEN]; 2522 char addrtxt[3 * ETH_ALEN]; 2523 int t_c_clear = 0; 2524 struct db_session_fields fields; 2525 struct sockaddr_in das; 2526 struct radius_client *client; 2527 struct radius_msg *msg; 2528 struct wpabuf *buf; 2529 u8 identifier; 2530 struct os_time now; 2531 2532 if (!data) 2533 return -1; 2534 2535 /* req: <disconnect|coa> <MAC Address> [t_c_clear] */ 2536 2537 if (os_strncmp(pos, "disconnect ", 11) == 0) { 2538 disconnect = 1; 2539 pos += 11; 2540 } else if (os_strncmp(req, "coa ", 4) == 0) { 2541 disconnect = 0; 2542 pos += 4; 2543 } else { 2544 return -1; 2545 } 2546 2547 if (hwaddr_aton(pos, addr)) 2548 return -1; 2549 pos = os_strchr(pos, ' '); 2550 if (pos) { 2551 if (os_strstr(pos, "t_c_clear")) 2552 t_c_clear = 1; 2553 } 2554 2555 if (!disconnect && !t_c_clear) { 2556 RADIUS_ERROR("DAC request for CoA without any authorization change"); 2557 return -1; 2558 } 2559 2560 if (!data->db) { 2561 RADIUS_ERROR("SQLite database not in use"); 2562 return -1; 2563 } 2564 2565 os_snprintf(addrtxt, sizeof(addrtxt), MACSTR, MAC2STR(addr)); 2566 2567 sql = sqlite3_mprintf("SELECT * FROM current_sessions WHERE mac_addr=%Q", 2568 addrtxt); 2569 if (!sql) 2570 return -1; 2571 2572 os_memset(&fields, 0, sizeof(fields)); 2573 res = sqlite3_exec(data->db, sql, get_db_session_fields, &fields, NULL); 2574 sqlite3_free(sql); 2575 if (res != SQLITE_OK) { 2576 RADIUS_ERROR("Failed to find matching current_sessions entry from sqlite database: %s", 2577 sqlite3_errmsg(data->db)); 2578 free_db_session_fields(&fields); 2579 return -1; 2580 } 2581 2582 if (!fields.nas) { 2583 RADIUS_ERROR("No NAS information found from current_sessions"); 2584 free_db_session_fields(&fields); 2585 return -1; 2586 } 2587 2588 os_memset(&das, 0, sizeof(das)); 2589 das.sin_family = AF_INET; 2590 das.sin_addr.s_addr = inet_addr(fields.nas); 2591 das.sin_port = htons(3799); 2592 2593 free_db_session_fields(&fields); 2594 2595 client = radius_server_get_client(data, &das.sin_addr, 0); 2596 if (!client) { 2597 RADIUS_ERROR("No NAS information available to protect the packet"); 2598 return -1; 2599 } 2600 2601 identifier = client->next_dac_identifier++; 2602 2603 msg = radius_msg_new(disconnect ? RADIUS_CODE_DISCONNECT_REQUEST : 2604 RADIUS_CODE_COA_REQUEST, identifier); 2605 if (!msg) 2606 return -1; 2607 2608 os_snprintf(addrtxt, sizeof(addrtxt), RADIUS_802_1X_ADDR_FORMAT, 2609 MAC2STR(addr)); 2610 if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID, 2611 (u8 *) addrtxt, os_strlen(addrtxt))) { 2612 RADIUS_ERROR("Could not add Calling-Station-Id"); 2613 radius_msg_free(msg); 2614 return -1; 2615 } 2616 2617 if (!disconnect && t_c_clear) { 2618 u8 val[4] = { 0x00, 0x00, 0x00, 0x00 }; /* E=0 */ 2619 2620 if (!radius_msg_add_wfa( 2621 msg, RADIUS_VENDOR_ATTR_WFA_HS20_T_C_FILTERING, 2622 val, sizeof(val))) { 2623 RADIUS_DEBUG("Failed to add WFA-HS20-T-C-Filtering"); 2624 radius_msg_free(msg); 2625 return -1; 2626 } 2627 } 2628 2629 os_get_time(&now); 2630 if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_EVENT_TIMESTAMP, 2631 now.sec)) { 2632 RADIUS_ERROR("Failed to add Event-Timestamp attribute"); 2633 radius_msg_free(msg); 2634 return -1; 2635 } 2636 2637 if (radius_msg_finish_acct(msg, (u8 *) client->shared_secret, 2638 client->shared_secret_len) < 0) { 2639 RADIUS_ERROR("Failed to add Message-Authenticator attribute"); 2640 radius_msg_free(msg); 2641 return -1; 2642 } 2643 2644 if (wpa_debug_level <= MSG_MSGDUMP) 2645 radius_msg_dump(msg); 2646 2647 buf = radius_msg_get_buf(msg); 2648 if (sendto(data->auth_sock, wpabuf_head(buf), wpabuf_len(buf), 0, 2649 (struct sockaddr *) &das, sizeof(das)) < 0) { 2650 RADIUS_ERROR("Failed to send packet - sendto: %s", 2651 strerror(errno)); 2652 radius_msg_free(msg); 2653 return -1; 2654 } 2655 2656 if (disconnect) { 2657 radius_msg_free(client->pending_dac_disconnect_req); 2658 client->pending_dac_disconnect_req = msg; 2659 client->pending_dac_disconnect_id = identifier; 2660 os_memcpy(client->pending_dac_disconnect_addr, addr, ETH_ALEN); 2661 } else { 2662 radius_msg_free(client->pending_dac_coa_req); 2663 client->pending_dac_coa_req = msg; 2664 client->pending_dac_coa_id = identifier; 2665 os_memcpy(client->pending_dac_coa_addr, addr, ETH_ALEN); 2666 } 2667 2668 return 0; 2669 #else /* CONFIG_SQLITE */ 2670 return -1; 2671 #endif /* CONFIG_SQLITE */ 2672 } 2673