1 /* 2 * Interworking (IEEE 802.11u) 3 * Copyright (c) 2011-2013, Qualcomm Atheros, Inc. 4 * Copyright (c) 2011-2014, Jouni Malinen <j (at) w1.fi> 5 * 6 * This software may be distributed under the terms of the BSD license. 7 * See README for more details. 8 */ 9 10 #include "includes.h" 11 12 #include "common.h" 13 #include "common/ieee802_11_defs.h" 14 #include "common/gas.h" 15 #include "common/wpa_ctrl.h" 16 #include "utils/pcsc_funcs.h" 17 #include "utils/eloop.h" 18 #include "drivers/driver.h" 19 #include "eap_common/eap_defs.h" 20 #include "eap_peer/eap.h" 21 #include "eap_peer/eap_methods.h" 22 #include "eapol_supp/eapol_supp_sm.h" 23 #include "rsn_supp/wpa.h" 24 #include "wpa_supplicant_i.h" 25 #include "config.h" 26 #include "config_ssid.h" 27 #include "bss.h" 28 #include "scan.h" 29 #include "notify.h" 30 #include "driver_i.h" 31 #include "gas_query.h" 32 #include "hs20_supplicant.h" 33 #include "interworking.h" 34 35 36 #if defined(EAP_SIM) | defined(EAP_SIM_DYNAMIC) 37 #define INTERWORKING_3GPP 38 #else 39 #if defined(EAP_AKA) | defined(EAP_AKA_DYNAMIC) 40 #define INTERWORKING_3GPP 41 #else 42 #if defined(EAP_AKA_PRIME) | defined(EAP_AKA_PRIME_DYNAMIC) 43 #define INTERWORKING_3GPP 44 #endif 45 #endif 46 #endif 47 48 static void interworking_next_anqp_fetch(struct wpa_supplicant *wpa_s); 49 static struct wpa_cred * interworking_credentials_available_realm( 50 struct wpa_supplicant *wpa_s, struct wpa_bss *bss, int ignore_bw, 51 int *excluded); 52 static struct wpa_cred * interworking_credentials_available_3gpp( 53 struct wpa_supplicant *wpa_s, struct wpa_bss *bss, int ignore_bw, 54 int *excluded); 55 56 57 static int cred_prio_cmp(const struct wpa_cred *a, const struct wpa_cred *b) 58 { 59 if (a->priority > b->priority) 60 return 1; 61 if (a->priority < b->priority) 62 return -1; 63 if (a->provisioning_sp == NULL || b->provisioning_sp == NULL || 64 os_strcmp(a->provisioning_sp, b->provisioning_sp) != 0) 65 return 0; 66 if (a->sp_priority < b->sp_priority) 67 return 1; 68 if (a->sp_priority > b->sp_priority) 69 return -1; 70 return 0; 71 } 72 73 74 static void interworking_reconnect(struct wpa_supplicant *wpa_s) 75 { 76 unsigned int tried; 77 78 if (wpa_s->wpa_state >= WPA_AUTHENTICATING) { 79 wpa_supplicant_cancel_sched_scan(wpa_s); 80 wpa_s->own_disconnect_req = 1; 81 wpa_supplicant_deauthenticate(wpa_s, 82 WLAN_REASON_DEAUTH_LEAVING); 83 } 84 wpa_s->disconnected = 0; 85 wpa_s->reassociate = 1; 86 tried = wpa_s->interworking_fast_assoc_tried; 87 wpa_s->interworking_fast_assoc_tried = 1; 88 89 if (!tried && wpa_supplicant_fast_associate(wpa_s) >= 0) 90 return; 91 92 wpa_s->interworking_fast_assoc_tried = 0; 93 wpa_supplicant_req_scan(wpa_s, 0, 0); 94 } 95 96 97 static struct wpabuf * anqp_build_req(u16 info_ids[], size_t num_ids, 98 struct wpabuf *extra) 99 { 100 struct wpabuf *buf; 101 size_t i; 102 u8 *len_pos; 103 104 buf = gas_anqp_build_initial_req(0, 4 + num_ids * 2 + 105 (extra ? wpabuf_len(extra) : 0)); 106 if (buf == NULL) 107 return NULL; 108 109 if (num_ids > 0) { 110 len_pos = gas_anqp_add_element(buf, ANQP_QUERY_LIST); 111 for (i = 0; i < num_ids; i++) 112 wpabuf_put_le16(buf, info_ids[i]); 113 gas_anqp_set_element_len(buf, len_pos); 114 } 115 if (extra) 116 wpabuf_put_buf(buf, extra); 117 118 gas_anqp_set_len(buf); 119 120 return buf; 121 } 122 123 124 static void interworking_anqp_resp_cb(void *ctx, const u8 *dst, 125 u8 dialog_token, 126 enum gas_query_result result, 127 const struct wpabuf *adv_proto, 128 const struct wpabuf *resp, 129 u16 status_code) 130 { 131 struct wpa_supplicant *wpa_s = ctx; 132 133 wpa_printf(MSG_DEBUG, "ANQP: Response callback dst=" MACSTR 134 " dialog_token=%u result=%d status_code=%u", 135 MAC2STR(dst), dialog_token, result, status_code); 136 anqp_resp_cb(wpa_s, dst, dialog_token, result, adv_proto, resp, 137 status_code); 138 interworking_next_anqp_fetch(wpa_s); 139 } 140 141 142 static int cred_with_roaming_consortium(struct wpa_supplicant *wpa_s) 143 { 144 struct wpa_cred *cred; 145 146 for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 147 if (cred->roaming_consortium_len) 148 return 1; 149 if (cred->required_roaming_consortium_len) 150 return 1; 151 } 152 return 0; 153 } 154 155 156 static int cred_with_3gpp(struct wpa_supplicant *wpa_s) 157 { 158 struct wpa_cred *cred; 159 160 for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 161 if (cred->pcsc || cred->imsi) 162 return 1; 163 } 164 return 0; 165 } 166 167 168 static int cred_with_nai_realm(struct wpa_supplicant *wpa_s) 169 { 170 struct wpa_cred *cred; 171 172 for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 173 if (cred->pcsc || cred->imsi) 174 continue; 175 if (!cred->eap_method) 176 return 1; 177 if (cred->realm && cred->roaming_consortium_len == 0) 178 return 1; 179 } 180 return 0; 181 } 182 183 184 static int cred_with_domain(struct wpa_supplicant *wpa_s) 185 { 186 struct wpa_cred *cred; 187 188 for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 189 if (cred->domain || cred->pcsc || cred->imsi || 190 cred->roaming_partner) 191 return 1; 192 } 193 return 0; 194 } 195 196 197 #ifdef CONFIG_HS20 198 199 static int cred_with_min_backhaul(struct wpa_supplicant *wpa_s) 200 { 201 struct wpa_cred *cred; 202 203 for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 204 if (cred->min_dl_bandwidth_home || 205 cred->min_ul_bandwidth_home || 206 cred->min_dl_bandwidth_roaming || 207 cred->min_ul_bandwidth_roaming) 208 return 1; 209 } 210 return 0; 211 } 212 213 214 static int cred_with_conn_capab(struct wpa_supplicant *wpa_s) 215 { 216 struct wpa_cred *cred; 217 218 for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 219 if (cred->num_req_conn_capab) 220 return 1; 221 } 222 return 0; 223 } 224 225 #endif /* CONFIG_HS20 */ 226 227 228 static int additional_roaming_consortiums(struct wpa_bss *bss) 229 { 230 const u8 *ie; 231 ie = wpa_bss_get_ie(bss, WLAN_EID_ROAMING_CONSORTIUM); 232 if (ie == NULL || ie[1] == 0) 233 return 0; 234 return ie[2]; /* Number of ANQP OIs */ 235 } 236 237 238 static void interworking_continue_anqp(void *eloop_ctx, void *sock_ctx) 239 { 240 struct wpa_supplicant *wpa_s = eloop_ctx; 241 interworking_next_anqp_fetch(wpa_s); 242 } 243 244 245 static int interworking_anqp_send_req(struct wpa_supplicant *wpa_s, 246 struct wpa_bss *bss) 247 { 248 struct wpabuf *buf; 249 int ret = 0; 250 int res; 251 u16 info_ids[8]; 252 size_t num_info_ids = 0; 253 struct wpabuf *extra = NULL; 254 int all = wpa_s->fetch_all_anqp; 255 256 wpa_msg(wpa_s, MSG_DEBUG, "Interworking: ANQP Query Request to " MACSTR, 257 MAC2STR(bss->bssid)); 258 wpa_s->interworking_gas_bss = bss; 259 260 info_ids[num_info_ids++] = ANQP_CAPABILITY_LIST; 261 if (all) { 262 info_ids[num_info_ids++] = ANQP_VENUE_NAME; 263 info_ids[num_info_ids++] = ANQP_NETWORK_AUTH_TYPE; 264 } 265 if (all || (cred_with_roaming_consortium(wpa_s) && 266 additional_roaming_consortiums(bss))) 267 info_ids[num_info_ids++] = ANQP_ROAMING_CONSORTIUM; 268 if (all) 269 info_ids[num_info_ids++] = ANQP_IP_ADDR_TYPE_AVAILABILITY; 270 if (all || cred_with_nai_realm(wpa_s)) 271 info_ids[num_info_ids++] = ANQP_NAI_REALM; 272 if (all || cred_with_3gpp(wpa_s)) { 273 info_ids[num_info_ids++] = ANQP_3GPP_CELLULAR_NETWORK; 274 wpa_supplicant_scard_init(wpa_s, NULL); 275 } 276 if (all || cred_with_domain(wpa_s)) 277 info_ids[num_info_ids++] = ANQP_DOMAIN_NAME; 278 wpa_hexdump(MSG_DEBUG, "Interworking: ANQP Query info", 279 (u8 *) info_ids, num_info_ids * 2); 280 281 #ifdef CONFIG_HS20 282 if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) { 283 u8 *len_pos; 284 285 extra = wpabuf_alloc(100); 286 if (!extra) 287 return -1; 288 289 len_pos = gas_anqp_add_element(extra, ANQP_VENDOR_SPECIFIC); 290 wpabuf_put_be24(extra, OUI_WFA); 291 wpabuf_put_u8(extra, HS20_ANQP_OUI_TYPE); 292 wpabuf_put_u8(extra, HS20_STYPE_QUERY_LIST); 293 wpabuf_put_u8(extra, 0); /* Reserved */ 294 wpabuf_put_u8(extra, HS20_STYPE_CAPABILITY_LIST); 295 if (all) 296 wpabuf_put_u8(extra, 297 HS20_STYPE_OPERATOR_FRIENDLY_NAME); 298 if (all || cred_with_min_backhaul(wpa_s)) 299 wpabuf_put_u8(extra, HS20_STYPE_WAN_METRICS); 300 if (all || cred_with_conn_capab(wpa_s)) 301 wpabuf_put_u8(extra, HS20_STYPE_CONNECTION_CAPABILITY); 302 if (all) 303 wpabuf_put_u8(extra, HS20_STYPE_OPERATING_CLASS); 304 if (all) 305 wpabuf_put_u8(extra, HS20_STYPE_OSU_PROVIDERS_LIST); 306 gas_anqp_set_element_len(extra, len_pos); 307 } 308 #endif /* CONFIG_HS20 */ 309 310 buf = anqp_build_req(info_ids, num_info_ids, extra); 311 wpabuf_free(extra); 312 if (buf == NULL) 313 return -1; 314 315 res = gas_query_req(wpa_s->gas, bss->bssid, bss->freq, buf, 316 interworking_anqp_resp_cb, wpa_s); 317 if (res < 0) { 318 wpa_msg(wpa_s, MSG_DEBUG, "ANQP: Failed to send Query Request"); 319 wpabuf_free(buf); 320 ret = -1; 321 eloop_register_timeout(0, 0, interworking_continue_anqp, wpa_s, 322 NULL); 323 } else 324 wpa_msg(wpa_s, MSG_DEBUG, 325 "ANQP: Query started with dialog token %u", res); 326 327 return ret; 328 } 329 330 331 struct nai_realm_eap { 332 u8 method; 333 u8 inner_method; 334 enum nai_realm_eap_auth_inner_non_eap inner_non_eap; 335 u8 cred_type; 336 u8 tunneled_cred_type; 337 }; 338 339 struct nai_realm { 340 u8 encoding; 341 char *realm; 342 u8 eap_count; 343 struct nai_realm_eap *eap; 344 }; 345 346 347 static void nai_realm_free(struct nai_realm *realms, u16 count) 348 { 349 u16 i; 350 351 if (realms == NULL) 352 return; 353 for (i = 0; i < count; i++) { 354 os_free(realms[i].eap); 355 os_free(realms[i].realm); 356 } 357 os_free(realms); 358 } 359 360 361 static const u8 * nai_realm_parse_eap(struct nai_realm_eap *e, const u8 *pos, 362 const u8 *end) 363 { 364 u8 elen, auth_count, a; 365 const u8 *e_end; 366 367 if (end - pos < 3) { 368 wpa_printf(MSG_DEBUG, "No room for EAP Method fixed fields"); 369 return NULL; 370 } 371 372 elen = *pos++; 373 if (elen > end - pos || elen < 2) { 374 wpa_printf(MSG_DEBUG, "No room for EAP Method subfield"); 375 return NULL; 376 } 377 e_end = pos + elen; 378 e->method = *pos++; 379 auth_count = *pos++; 380 wpa_printf(MSG_DEBUG, "EAP Method: len=%u method=%u auth_count=%u", 381 elen, e->method, auth_count); 382 383 for (a = 0; a < auth_count; a++) { 384 u8 id, len; 385 386 if (end - pos < 2) { 387 wpa_printf(MSG_DEBUG, 388 "No room for Authentication Parameter subfield header"); 389 return NULL; 390 } 391 392 id = *pos++; 393 len = *pos++; 394 if (len > end - pos) { 395 wpa_printf(MSG_DEBUG, 396 "No room for Authentication Parameter subfield"); 397 return NULL; 398 } 399 400 switch (id) { 401 case NAI_REALM_EAP_AUTH_NON_EAP_INNER_AUTH: 402 if (len < 1) 403 break; 404 e->inner_non_eap = *pos; 405 if (e->method != EAP_TYPE_TTLS) 406 break; 407 switch (*pos) { 408 case NAI_REALM_INNER_NON_EAP_PAP: 409 wpa_printf(MSG_DEBUG, "EAP-TTLS/PAP"); 410 break; 411 case NAI_REALM_INNER_NON_EAP_CHAP: 412 wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP"); 413 break; 414 case NAI_REALM_INNER_NON_EAP_MSCHAP: 415 wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP"); 416 break; 417 case NAI_REALM_INNER_NON_EAP_MSCHAPV2: 418 wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2"); 419 break; 420 } 421 break; 422 case NAI_REALM_EAP_AUTH_INNER_AUTH_EAP_METHOD: 423 if (len < 1) 424 break; 425 e->inner_method = *pos; 426 wpa_printf(MSG_DEBUG, "Inner EAP method: %u", 427 e->inner_method); 428 break; 429 case NAI_REALM_EAP_AUTH_CRED_TYPE: 430 if (len < 1) 431 break; 432 e->cred_type = *pos; 433 wpa_printf(MSG_DEBUG, "Credential Type: %u", 434 e->cred_type); 435 break; 436 case NAI_REALM_EAP_AUTH_TUNNELED_CRED_TYPE: 437 if (len < 1) 438 break; 439 e->tunneled_cred_type = *pos; 440 wpa_printf(MSG_DEBUG, "Tunneled EAP Method Credential " 441 "Type: %u", e->tunneled_cred_type); 442 break; 443 default: 444 wpa_printf(MSG_DEBUG, "Unsupported Authentication " 445 "Parameter: id=%u len=%u", id, len); 446 wpa_hexdump(MSG_DEBUG, "Authentication Parameter " 447 "Value", pos, len); 448 break; 449 } 450 451 pos += len; 452 } 453 454 return e_end; 455 } 456 457 458 static const u8 * nai_realm_parse_realm(struct nai_realm *r, const u8 *pos, 459 const u8 *end) 460 { 461 u16 len; 462 const u8 *f_end; 463 u8 realm_len, e; 464 465 if (end - pos < 4) { 466 wpa_printf(MSG_DEBUG, "No room for NAI Realm Data " 467 "fixed fields"); 468 return NULL; 469 } 470 471 len = WPA_GET_LE16(pos); /* NAI Realm Data field Length */ 472 pos += 2; 473 if (len > end - pos || len < 3) { 474 wpa_printf(MSG_DEBUG, "No room for NAI Realm Data " 475 "(len=%u; left=%u)", 476 len, (unsigned int) (end - pos)); 477 return NULL; 478 } 479 f_end = pos + len; 480 481 r->encoding = *pos++; 482 realm_len = *pos++; 483 if (realm_len > f_end - pos) { 484 wpa_printf(MSG_DEBUG, "No room for NAI Realm " 485 "(len=%u; left=%u)", 486 realm_len, (unsigned int) (f_end - pos)); 487 return NULL; 488 } 489 wpa_hexdump_ascii(MSG_DEBUG, "NAI Realm", pos, realm_len); 490 r->realm = dup_binstr(pos, realm_len); 491 if (r->realm == NULL) 492 return NULL; 493 pos += realm_len; 494 495 if (f_end - pos < 1) { 496 wpa_printf(MSG_DEBUG, "No room for EAP Method Count"); 497 return NULL; 498 } 499 r->eap_count = *pos++; 500 wpa_printf(MSG_DEBUG, "EAP Count: %u", r->eap_count); 501 if (r->eap_count * 3 > f_end - pos) { 502 wpa_printf(MSG_DEBUG, "No room for EAP Methods"); 503 return NULL; 504 } 505 r->eap = os_calloc(r->eap_count, sizeof(struct nai_realm_eap)); 506 if (r->eap == NULL) 507 return NULL; 508 509 for (e = 0; e < r->eap_count; e++) { 510 pos = nai_realm_parse_eap(&r->eap[e], pos, f_end); 511 if (pos == NULL) 512 return NULL; 513 } 514 515 return f_end; 516 } 517 518 519 static struct nai_realm * nai_realm_parse(struct wpabuf *anqp, u16 *count) 520 { 521 struct nai_realm *realm; 522 const u8 *pos, *end; 523 u16 i, num; 524 size_t left; 525 526 if (anqp == NULL) 527 return NULL; 528 left = wpabuf_len(anqp); 529 if (left < 2) 530 return NULL; 531 532 pos = wpabuf_head_u8(anqp); 533 end = pos + left; 534 num = WPA_GET_LE16(pos); 535 wpa_printf(MSG_DEBUG, "NAI Realm Count: %u", num); 536 pos += 2; 537 left -= 2; 538 539 if (num > left / 5) { 540 wpa_printf(MSG_DEBUG, "Invalid NAI Realm Count %u - not " 541 "enough data (%u octets) for that many realms", 542 num, (unsigned int) left); 543 return NULL; 544 } 545 546 realm = os_calloc(num, sizeof(struct nai_realm)); 547 if (realm == NULL) 548 return NULL; 549 550 for (i = 0; i < num; i++) { 551 pos = nai_realm_parse_realm(&realm[i], pos, end); 552 if (pos == NULL) { 553 nai_realm_free(realm, num); 554 return NULL; 555 } 556 } 557 558 *count = num; 559 return realm; 560 } 561 562 563 static int nai_realm_match(struct nai_realm *realm, const char *home_realm) 564 { 565 char *tmp, *pos, *end; 566 int match = 0; 567 568 if (realm->realm == NULL || home_realm == NULL) 569 return 0; 570 571 if (os_strchr(realm->realm, ';') == NULL) 572 return os_strcasecmp(realm->realm, home_realm) == 0; 573 574 tmp = os_strdup(realm->realm); 575 if (tmp == NULL) 576 return 0; 577 578 pos = tmp; 579 while (*pos) { 580 end = os_strchr(pos, ';'); 581 if (end) 582 *end = '\0'; 583 if (os_strcasecmp(pos, home_realm) == 0) { 584 match = 1; 585 break; 586 } 587 if (end == NULL) 588 break; 589 pos = end + 1; 590 } 591 592 os_free(tmp); 593 594 return match; 595 } 596 597 598 static int nai_realm_cred_username(struct wpa_supplicant *wpa_s, 599 struct nai_realm_eap *eap) 600 { 601 if (eap_get_name(EAP_VENDOR_IETF, eap->method) == NULL) { 602 wpa_msg(wpa_s, MSG_DEBUG, 603 "nai-realm-cred-username: EAP method not supported: %d", 604 eap->method); 605 return 0; /* method not supported */ 606 } 607 608 if (eap->method != EAP_TYPE_TTLS && eap->method != EAP_TYPE_PEAP && 609 eap->method != EAP_TYPE_FAST) { 610 /* Only tunneled methods with username/password supported */ 611 wpa_msg(wpa_s, MSG_DEBUG, 612 "nai-realm-cred-username: Method: %d is not TTLS, PEAP, or FAST", 613 eap->method); 614 return 0; 615 } 616 617 if (eap->method == EAP_TYPE_PEAP || eap->method == EAP_TYPE_FAST) { 618 if (eap->inner_method && 619 eap_get_name(EAP_VENDOR_IETF, eap->inner_method) == NULL) { 620 wpa_msg(wpa_s, MSG_DEBUG, 621 "nai-realm-cred-username: PEAP/FAST: Inner method not supported: %d", 622 eap->inner_method); 623 return 0; 624 } 625 if (!eap->inner_method && 626 eap_get_name(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2) == NULL) { 627 wpa_msg(wpa_s, MSG_DEBUG, 628 "nai-realm-cred-username: MSCHAPv2 not supported"); 629 return 0; 630 } 631 } 632 633 if (eap->method == EAP_TYPE_TTLS) { 634 if (eap->inner_method == 0 && eap->inner_non_eap == 0) 635 return 1; /* Assume TTLS/MSCHAPv2 is used */ 636 if (eap->inner_method && 637 eap_get_name(EAP_VENDOR_IETF, eap->inner_method) == NULL) { 638 wpa_msg(wpa_s, MSG_DEBUG, 639 "nai-realm-cred-username: TTLS, but inner not supported: %d", 640 eap->inner_method); 641 return 0; 642 } 643 if (eap->inner_non_eap && 644 eap->inner_non_eap != NAI_REALM_INNER_NON_EAP_PAP && 645 eap->inner_non_eap != NAI_REALM_INNER_NON_EAP_CHAP && 646 eap->inner_non_eap != NAI_REALM_INNER_NON_EAP_MSCHAP && 647 eap->inner_non_eap != NAI_REALM_INNER_NON_EAP_MSCHAPV2) { 648 wpa_msg(wpa_s, MSG_DEBUG, 649 "nai-realm-cred-username: TTLS, inner-non-eap not supported: %d", 650 eap->inner_non_eap); 651 return 0; 652 } 653 } 654 655 if (eap->inner_method && 656 eap->inner_method != EAP_TYPE_GTC && 657 eap->inner_method != EAP_TYPE_MSCHAPV2) { 658 wpa_msg(wpa_s, MSG_DEBUG, 659 "nai-realm-cred-username: inner-method not GTC or MSCHAPv2: %d", 660 eap->inner_method); 661 return 0; 662 } 663 664 return 1; 665 } 666 667 668 static int nai_realm_cred_cert(struct wpa_supplicant *wpa_s, 669 struct nai_realm_eap *eap) 670 { 671 if (eap_get_name(EAP_VENDOR_IETF, eap->method) == NULL) { 672 wpa_msg(wpa_s, MSG_DEBUG, 673 "nai-realm-cred-cert: Method not supported: %d", 674 eap->method); 675 return 0; /* method not supported */ 676 } 677 678 if (eap->method != EAP_TYPE_TLS) { 679 /* Only EAP-TLS supported for credential authentication */ 680 wpa_msg(wpa_s, MSG_DEBUG, 681 "nai-realm-cred-cert: Method not TLS: %d", 682 eap->method); 683 return 0; 684 } 685 686 return 1; 687 } 688 689 690 static struct nai_realm_eap * nai_realm_find_eap(struct wpa_supplicant *wpa_s, 691 struct wpa_cred *cred, 692 struct nai_realm *realm) 693 { 694 u8 e; 695 696 if (cred->username == NULL || 697 cred->username[0] == '\0' || 698 ((cred->password == NULL || 699 cred->password[0] == '\0') && 700 (cred->private_key == NULL || 701 cred->private_key[0] == '\0'))) { 702 wpa_msg(wpa_s, MSG_DEBUG, 703 "nai-realm-find-eap: incomplete cred info: username: %s password: %s private_key: %s", 704 cred->username ? cred->username : "NULL", 705 cred->password ? cred->password : "NULL", 706 cred->private_key ? cred->private_key : "NULL"); 707 return NULL; 708 } 709 710 for (e = 0; e < realm->eap_count; e++) { 711 struct nai_realm_eap *eap = &realm->eap[e]; 712 if (cred->password && cred->password[0] && 713 nai_realm_cred_username(wpa_s, eap)) 714 return eap; 715 if (cred->private_key && cred->private_key[0] && 716 nai_realm_cred_cert(wpa_s, eap)) 717 return eap; 718 } 719 720 return NULL; 721 } 722 723 724 #ifdef INTERWORKING_3GPP 725 726 static int plmn_id_match(struct wpabuf *anqp, const char *imsi, int mnc_len) 727 { 728 u8 plmn[3], plmn2[3]; 729 const u8 *pos, *end; 730 u8 udhl; 731 732 /* 733 * See Annex A of 3GPP TS 24.234 v8.1.0 for description. The network 734 * operator is allowed to include only two digits of the MNC, so allow 735 * matches based on both two and three digit MNC assumptions. Since some 736 * SIM/USIM cards may not expose MNC length conveniently, we may be 737 * provided the default MNC length 3 here and as such, checking with MNC 738 * length 2 is justifiable even though 3GPP TS 24.234 does not mention 739 * that case. Anyway, MCC/MNC pair where both 2 and 3 digit MNC is used 740 * with otherwise matching values would not be good idea in general, so 741 * this should not result in selecting incorrect networks. 742 */ 743 /* Match with 3 digit MNC */ 744 plmn[0] = (imsi[0] - '0') | ((imsi[1] - '0') << 4); 745 plmn[1] = (imsi[2] - '0') | ((imsi[5] - '0') << 4); 746 plmn[2] = (imsi[3] - '0') | ((imsi[4] - '0') << 4); 747 /* Match with 2 digit MNC */ 748 plmn2[0] = (imsi[0] - '0') | ((imsi[1] - '0') << 4); 749 plmn2[1] = (imsi[2] - '0') | 0xf0; 750 plmn2[2] = (imsi[3] - '0') | ((imsi[4] - '0') << 4); 751 752 if (anqp == NULL) 753 return 0; 754 pos = wpabuf_head_u8(anqp); 755 end = pos + wpabuf_len(anqp); 756 if (end - pos < 2) 757 return 0; 758 if (*pos != 0) { 759 wpa_printf(MSG_DEBUG, "Unsupported GUD version 0x%x", *pos); 760 return 0; 761 } 762 pos++; 763 udhl = *pos++; 764 if (udhl > end - pos) { 765 wpa_printf(MSG_DEBUG, "Invalid UDHL"); 766 return 0; 767 } 768 end = pos + udhl; 769 770 wpa_printf(MSG_DEBUG, "Interworking: Matching against MCC/MNC alternatives: %02x:%02x:%02x or %02x:%02x:%02x (IMSI %s, MNC length %d)", 771 plmn[0], plmn[1], plmn[2], plmn2[0], plmn2[1], plmn2[2], 772 imsi, mnc_len); 773 774 while (end - pos >= 2) { 775 u8 iei, len; 776 const u8 *l_end; 777 iei = *pos++; 778 len = *pos++ & 0x7f; 779 if (len > end - pos) 780 break; 781 l_end = pos + len; 782 783 if (iei == 0 && len > 0) { 784 /* PLMN List */ 785 u8 num, i; 786 wpa_hexdump(MSG_DEBUG, "Interworking: PLMN List information element", 787 pos, len); 788 num = *pos++; 789 for (i = 0; i < num; i++) { 790 if (l_end - pos < 3) 791 break; 792 if (os_memcmp(pos, plmn, 3) == 0 || 793 os_memcmp(pos, plmn2, 3) == 0) 794 return 1; /* Found matching PLMN */ 795 pos += 3; 796 } 797 } else { 798 wpa_hexdump(MSG_DEBUG, "Interworking: Unrecognized 3GPP information element", 799 pos, len); 800 } 801 802 pos = l_end; 803 } 804 805 return 0; 806 } 807 808 809 static int build_root_nai(char *nai, size_t nai_len, const char *imsi, 810 size_t mnc_len, char prefix) 811 { 812 const char *sep, *msin; 813 char *end, *pos; 814 size_t msin_len, plmn_len; 815 816 /* 817 * TS 23.003, Clause 14 (3GPP to WLAN Interworking) 818 * Root NAI: 819 * <aka:0|sim:1><IMSI>@wlan.mnc<MNC>.mcc<MCC>.3gppnetwork.org 820 * <MNC> is zero-padded to three digits in case two-digit MNC is used 821 */ 822 823 if (imsi == NULL || os_strlen(imsi) > 16) { 824 wpa_printf(MSG_DEBUG, "No valid IMSI available"); 825 return -1; 826 } 827 sep = os_strchr(imsi, '-'); 828 if (sep) { 829 plmn_len = sep - imsi; 830 msin = sep + 1; 831 } else if (mnc_len && os_strlen(imsi) >= 3 + mnc_len) { 832 plmn_len = 3 + mnc_len; 833 msin = imsi + plmn_len; 834 } else 835 return -1; 836 if (plmn_len != 5 && plmn_len != 6) 837 return -1; 838 msin_len = os_strlen(msin); 839 840 pos = nai; 841 end = nai + nai_len; 842 if (prefix) 843 *pos++ = prefix; 844 os_memcpy(pos, imsi, plmn_len); 845 pos += plmn_len; 846 os_memcpy(pos, msin, msin_len); 847 pos += msin_len; 848 pos += os_snprintf(pos, end - pos, "@wlan.mnc"); 849 if (plmn_len == 5) { 850 *pos++ = '0'; 851 *pos++ = imsi[3]; 852 *pos++ = imsi[4]; 853 } else { 854 *pos++ = imsi[3]; 855 *pos++ = imsi[4]; 856 *pos++ = imsi[5]; 857 } 858 os_snprintf(pos, end - pos, ".mcc%c%c%c.3gppnetwork.org", 859 imsi[0], imsi[1], imsi[2]); 860 861 return 0; 862 } 863 864 865 static int set_root_nai(struct wpa_ssid *ssid, const char *imsi, char prefix) 866 { 867 char nai[100]; 868 if (build_root_nai(nai, sizeof(nai), imsi, 0, prefix) < 0) 869 return -1; 870 return wpa_config_set_quoted(ssid, "identity", nai); 871 } 872 873 #endif /* INTERWORKING_3GPP */ 874 875 876 static int already_connected(struct wpa_supplicant *wpa_s, 877 struct wpa_cred *cred, struct wpa_bss *bss) 878 { 879 struct wpa_ssid *ssid, *sel_ssid; 880 struct wpa_bss *selected; 881 882 if (wpa_s->wpa_state < WPA_ASSOCIATED || wpa_s->current_ssid == NULL) 883 return 0; 884 885 ssid = wpa_s->current_ssid; 886 if (ssid->parent_cred != cred) 887 return 0; 888 889 if (ssid->ssid_len != bss->ssid_len || 890 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) != 0) 891 return 0; 892 893 sel_ssid = NULL; 894 selected = wpa_supplicant_pick_network(wpa_s, &sel_ssid); 895 if (selected && sel_ssid && sel_ssid->priority > ssid->priority) 896 return 0; /* higher priority network in scan results */ 897 898 return 1; 899 } 900 901 902 static void remove_duplicate_network(struct wpa_supplicant *wpa_s, 903 struct wpa_cred *cred, 904 struct wpa_bss *bss) 905 { 906 struct wpa_ssid *ssid; 907 908 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { 909 if (ssid->parent_cred != cred) 910 continue; 911 if (ssid->ssid_len != bss->ssid_len || 912 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) != 0) 913 continue; 914 915 break; 916 } 917 918 if (ssid == NULL) 919 return; 920 921 wpa_printf(MSG_DEBUG, "Interworking: Remove duplicate network entry for the same credential"); 922 923 if (ssid == wpa_s->current_ssid) { 924 wpa_sm_set_config(wpa_s->wpa, NULL); 925 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); 926 wpa_s->own_disconnect_req = 1; 927 wpa_supplicant_deauthenticate(wpa_s, 928 WLAN_REASON_DEAUTH_LEAVING); 929 } 930 931 wpas_notify_network_removed(wpa_s, ssid); 932 wpa_config_remove_network(wpa_s->conf, ssid->id); 933 } 934 935 936 static int interworking_set_hs20_params(struct wpa_supplicant *wpa_s, 937 struct wpa_ssid *ssid) 938 { 939 const char *key_mgmt = NULL; 940 #ifdef CONFIG_IEEE80211R 941 int res; 942 struct wpa_driver_capa capa; 943 944 res = wpa_drv_get_capa(wpa_s, &capa); 945 if (res == 0 && capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT) { 946 key_mgmt = wpa_s->conf->pmf != NO_MGMT_FRAME_PROTECTION ? 947 "WPA-EAP WPA-EAP-SHA256 FT-EAP" : 948 "WPA-EAP FT-EAP"; 949 } 950 #endif /* CONFIG_IEEE80211R */ 951 952 if (!key_mgmt) 953 key_mgmt = wpa_s->conf->pmf != NO_MGMT_FRAME_PROTECTION ? 954 "WPA-EAP WPA-EAP-SHA256" : "WPA-EAP"; 955 if (wpa_config_set(ssid, "key_mgmt", key_mgmt, 0) < 0 || 956 wpa_config_set(ssid, "proto", "RSN", 0) < 0 || 957 wpa_config_set(ssid, "pairwise", "CCMP", 0) < 0) 958 return -1; 959 return 0; 960 } 961 962 963 static int interworking_connect_3gpp(struct wpa_supplicant *wpa_s, 964 struct wpa_cred *cred, 965 struct wpa_bss *bss, int only_add) 966 { 967 #ifdef INTERWORKING_3GPP 968 struct wpa_ssid *ssid; 969 int eap_type; 970 int res; 971 char prefix; 972 973 if (bss->anqp == NULL || bss->anqp->anqp_3gpp == NULL) 974 return -1; 975 976 wpa_msg(wpa_s, MSG_DEBUG, "Interworking: Connect with " MACSTR 977 " (3GPP)", MAC2STR(bss->bssid)); 978 979 if (already_connected(wpa_s, cred, bss)) { 980 wpa_msg(wpa_s, MSG_INFO, INTERWORKING_ALREADY_CONNECTED MACSTR, 981 MAC2STR(bss->bssid)); 982 return wpa_s->current_ssid->id; 983 } 984 985 remove_duplicate_network(wpa_s, cred, bss); 986 987 ssid = wpa_config_add_network(wpa_s->conf); 988 if (ssid == NULL) 989 return -1; 990 ssid->parent_cred = cred; 991 992 wpas_notify_network_added(wpa_s, ssid); 993 wpa_config_set_network_defaults(ssid); 994 ssid->priority = cred->priority; 995 ssid->temporary = 1; 996 ssid->ssid = os_zalloc(bss->ssid_len + 1); 997 if (ssid->ssid == NULL) 998 goto fail; 999 os_memcpy(ssid->ssid, bss->ssid, bss->ssid_len); 1000 ssid->ssid_len = bss->ssid_len; 1001 ssid->eap.sim_num = cred->sim_num; 1002 1003 if (interworking_set_hs20_params(wpa_s, ssid) < 0) 1004 goto fail; 1005 1006 eap_type = EAP_TYPE_SIM; 1007 if (cred->pcsc && wpa_s->scard && scard_supports_umts(wpa_s->scard)) 1008 eap_type = EAP_TYPE_AKA; 1009 if (cred->eap_method && cred->eap_method[0].vendor == EAP_VENDOR_IETF) { 1010 if (cred->eap_method[0].method == EAP_TYPE_SIM || 1011 cred->eap_method[0].method == EAP_TYPE_AKA || 1012 cred->eap_method[0].method == EAP_TYPE_AKA_PRIME) 1013 eap_type = cred->eap_method[0].method; 1014 } 1015 1016 switch (eap_type) { 1017 case EAP_TYPE_SIM: 1018 prefix = '1'; 1019 res = wpa_config_set(ssid, "eap", "SIM", 0); 1020 break; 1021 case EAP_TYPE_AKA: 1022 prefix = '0'; 1023 res = wpa_config_set(ssid, "eap", "AKA", 0); 1024 break; 1025 case EAP_TYPE_AKA_PRIME: 1026 prefix = '6'; 1027 res = wpa_config_set(ssid, "eap", "AKA'", 0); 1028 break; 1029 default: 1030 res = -1; 1031 break; 1032 } 1033 if (res < 0) { 1034 wpa_msg(wpa_s, MSG_DEBUG, 1035 "Selected EAP method (%d) not supported", eap_type); 1036 goto fail; 1037 } 1038 1039 if (!cred->pcsc && set_root_nai(ssid, cred->imsi, prefix) < 0) { 1040 wpa_msg(wpa_s, MSG_DEBUG, "Failed to set Root NAI"); 1041 goto fail; 1042 } 1043 1044 if (cred->milenage && cred->milenage[0]) { 1045 if (wpa_config_set_quoted(ssid, "password", 1046 cred->milenage) < 0) 1047 goto fail; 1048 } else if (cred->pcsc) { 1049 if (wpa_config_set_quoted(ssid, "pcsc", "") < 0) 1050 goto fail; 1051 if (wpa_s->conf->pcsc_pin && 1052 wpa_config_set_quoted(ssid, "pin", wpa_s->conf->pcsc_pin) 1053 < 0) 1054 goto fail; 1055 } 1056 1057 wpa_s->next_ssid = ssid; 1058 wpa_config_update_prio_list(wpa_s->conf); 1059 if (!only_add) 1060 interworking_reconnect(wpa_s); 1061 1062 return ssid->id; 1063 1064 fail: 1065 wpas_notify_network_removed(wpa_s, ssid); 1066 wpa_config_remove_network(wpa_s->conf, ssid->id); 1067 #endif /* INTERWORKING_3GPP */ 1068 return -1; 1069 } 1070 1071 1072 static int roaming_consortium_element_match(const u8 *ie, const u8 *rc_id, 1073 size_t rc_len) 1074 { 1075 const u8 *pos, *end; 1076 u8 lens; 1077 1078 if (ie == NULL) 1079 return 0; 1080 1081 pos = ie + 2; 1082 end = ie + 2 + ie[1]; 1083 1084 /* Roaming Consortium element: 1085 * Number of ANQP OIs 1086 * OI #1 and #2 lengths 1087 * OI #1, [OI #2], [OI #3] 1088 */ 1089 1090 if (end - pos < 2) 1091 return 0; 1092 1093 pos++; /* skip Number of ANQP OIs */ 1094 lens = *pos++; 1095 if ((lens & 0x0f) + (lens >> 4) > end - pos) 1096 return 0; 1097 1098 if ((lens & 0x0f) == rc_len && os_memcmp(pos, rc_id, rc_len) == 0) 1099 return 1; 1100 pos += lens & 0x0f; 1101 1102 if ((lens >> 4) == rc_len && os_memcmp(pos, rc_id, rc_len) == 0) 1103 return 1; 1104 pos += lens >> 4; 1105 1106 if (pos < end && (size_t) (end - pos) == rc_len && 1107 os_memcmp(pos, rc_id, rc_len) == 0) 1108 return 1; 1109 1110 return 0; 1111 } 1112 1113 1114 static int roaming_consortium_anqp_match(const struct wpabuf *anqp, 1115 const u8 *rc_id, size_t rc_len) 1116 { 1117 const u8 *pos, *end; 1118 u8 len; 1119 1120 if (anqp == NULL) 1121 return 0; 1122 1123 pos = wpabuf_head(anqp); 1124 end = pos + wpabuf_len(anqp); 1125 1126 /* Set of <OI Length, OI> duples */ 1127 while (pos < end) { 1128 len = *pos++; 1129 if (len > end - pos) 1130 break; 1131 if (len == rc_len && os_memcmp(pos, rc_id, rc_len) == 0) 1132 return 1; 1133 pos += len; 1134 } 1135 1136 return 0; 1137 } 1138 1139 1140 static int roaming_consortium_match(const u8 *ie, const struct wpabuf *anqp, 1141 const u8 *rc_id, size_t rc_len) 1142 { 1143 return roaming_consortium_element_match(ie, rc_id, rc_len) || 1144 roaming_consortium_anqp_match(anqp, rc_id, rc_len); 1145 } 1146 1147 1148 static int cred_no_required_oi_match(struct wpa_cred *cred, struct wpa_bss *bss) 1149 { 1150 const u8 *ie; 1151 1152 if (cred->required_roaming_consortium_len == 0) 1153 return 0; 1154 1155 ie = wpa_bss_get_ie(bss, WLAN_EID_ROAMING_CONSORTIUM); 1156 1157 if (ie == NULL && 1158 (bss->anqp == NULL || bss->anqp->roaming_consortium == NULL)) 1159 return 1; 1160 1161 return !roaming_consortium_match(ie, 1162 bss->anqp ? 1163 bss->anqp->roaming_consortium : NULL, 1164 cred->required_roaming_consortium, 1165 cred->required_roaming_consortium_len); 1166 } 1167 1168 1169 static int cred_excluded_ssid(struct wpa_cred *cred, struct wpa_bss *bss) 1170 { 1171 size_t i; 1172 1173 if (!cred->excluded_ssid) 1174 return 0; 1175 1176 for (i = 0; i < cred->num_excluded_ssid; i++) { 1177 struct excluded_ssid *e = &cred->excluded_ssid[i]; 1178 if (bss->ssid_len == e->ssid_len && 1179 os_memcmp(bss->ssid, e->ssid, e->ssid_len) == 0) 1180 return 1; 1181 } 1182 1183 return 0; 1184 } 1185 1186 1187 static int cred_below_min_backhaul(struct wpa_supplicant *wpa_s, 1188 struct wpa_cred *cred, struct wpa_bss *bss) 1189 { 1190 #ifdef CONFIG_HS20 1191 int res; 1192 unsigned int dl_bandwidth, ul_bandwidth; 1193 const u8 *wan; 1194 u8 wan_info, dl_load, ul_load; 1195 u16 lmd; 1196 u32 ul_speed, dl_speed; 1197 1198 if (!cred->min_dl_bandwidth_home && 1199 !cred->min_ul_bandwidth_home && 1200 !cred->min_dl_bandwidth_roaming && 1201 !cred->min_ul_bandwidth_roaming) 1202 return 0; /* No bandwidth constraint specified */ 1203 1204 if (bss->anqp == NULL || bss->anqp->hs20_wan_metrics == NULL) 1205 return 0; /* No WAN Metrics known - ignore constraint */ 1206 1207 wan = wpabuf_head(bss->anqp->hs20_wan_metrics); 1208 wan_info = wan[0]; 1209 if (wan_info & BIT(3)) 1210 return 1; /* WAN link at capacity */ 1211 lmd = WPA_GET_LE16(wan + 11); 1212 if (lmd == 0) 1213 return 0; /* Downlink/Uplink Load was not measured */ 1214 dl_speed = WPA_GET_LE32(wan + 1); 1215 ul_speed = WPA_GET_LE32(wan + 5); 1216 dl_load = wan[9]; 1217 ul_load = wan[10]; 1218 1219 if (dl_speed >= 0xffffff) 1220 dl_bandwidth = dl_speed / 255 * (255 - dl_load); 1221 else 1222 dl_bandwidth = dl_speed * (255 - dl_load) / 255; 1223 1224 if (ul_speed >= 0xffffff) 1225 ul_bandwidth = ul_speed / 255 * (255 - ul_load); 1226 else 1227 ul_bandwidth = ul_speed * (255 - ul_load) / 255; 1228 1229 res = interworking_home_sp_cred(wpa_s, cred, bss->anqp ? 1230 bss->anqp->domain_name : NULL); 1231 if (res > 0) { 1232 if (cred->min_dl_bandwidth_home > dl_bandwidth) 1233 return 1; 1234 if (cred->min_ul_bandwidth_home > ul_bandwidth) 1235 return 1; 1236 } else { 1237 if (cred->min_dl_bandwidth_roaming > dl_bandwidth) 1238 return 1; 1239 if (cred->min_ul_bandwidth_roaming > ul_bandwidth) 1240 return 1; 1241 } 1242 #endif /* CONFIG_HS20 */ 1243 1244 return 0; 1245 } 1246 1247 1248 static int cred_over_max_bss_load(struct wpa_supplicant *wpa_s, 1249 struct wpa_cred *cred, struct wpa_bss *bss) 1250 { 1251 const u8 *ie; 1252 int res; 1253 1254 if (!cred->max_bss_load) 1255 return 0; /* No BSS Load constraint specified */ 1256 1257 ie = wpa_bss_get_ie(bss, WLAN_EID_BSS_LOAD); 1258 if (ie == NULL || ie[1] < 3) 1259 return 0; /* No BSS Load advertised */ 1260 1261 res = interworking_home_sp_cred(wpa_s, cred, bss->anqp ? 1262 bss->anqp->domain_name : NULL); 1263 if (res <= 0) 1264 return 0; /* Not a home network */ 1265 1266 return ie[4] > cred->max_bss_load; 1267 } 1268 1269 1270 #ifdef CONFIG_HS20 1271 1272 static int has_proto_match(const u8 *pos, const u8 *end, u8 proto) 1273 { 1274 while (end - pos >= 4) { 1275 if (pos[0] == proto && pos[3] == 1 /* Open */) 1276 return 1; 1277 pos += 4; 1278 } 1279 1280 return 0; 1281 } 1282 1283 1284 static int has_proto_port_match(const u8 *pos, const u8 *end, u8 proto, 1285 u16 port) 1286 { 1287 while (end - pos >= 4) { 1288 if (pos[0] == proto && WPA_GET_LE16(&pos[1]) == port && 1289 pos[3] == 1 /* Open */) 1290 return 1; 1291 pos += 4; 1292 } 1293 1294 return 0; 1295 } 1296 1297 #endif /* CONFIG_HS20 */ 1298 1299 1300 static int cred_conn_capab_missing(struct wpa_supplicant *wpa_s, 1301 struct wpa_cred *cred, struct wpa_bss *bss) 1302 { 1303 #ifdef CONFIG_HS20 1304 int res; 1305 const u8 *capab, *end; 1306 unsigned int i, j; 1307 int *ports; 1308 1309 if (!cred->num_req_conn_capab) 1310 return 0; /* No connection capability constraint specified */ 1311 1312 if (bss->anqp == NULL || bss->anqp->hs20_connection_capability == NULL) 1313 return 0; /* No Connection Capability known - ignore constraint 1314 */ 1315 1316 res = interworking_home_sp_cred(wpa_s, cred, bss->anqp ? 1317 bss->anqp->domain_name : NULL); 1318 if (res > 0) 1319 return 0; /* No constraint in home network */ 1320 1321 capab = wpabuf_head(bss->anqp->hs20_connection_capability); 1322 end = capab + wpabuf_len(bss->anqp->hs20_connection_capability); 1323 1324 for (i = 0; i < cred->num_req_conn_capab; i++) { 1325 ports = cred->req_conn_capab_port[i]; 1326 if (!ports) { 1327 if (!has_proto_match(capab, end, 1328 cred->req_conn_capab_proto[i])) 1329 return 1; 1330 } else { 1331 for (j = 0; ports[j] > -1; j++) { 1332 if (!has_proto_port_match( 1333 capab, end, 1334 cred->req_conn_capab_proto[i], 1335 ports[j])) 1336 return 1; 1337 } 1338 } 1339 } 1340 #endif /* CONFIG_HS20 */ 1341 1342 return 0; 1343 } 1344 1345 1346 static struct wpa_cred * interworking_credentials_available_roaming_consortium( 1347 struct wpa_supplicant *wpa_s, struct wpa_bss *bss, int ignore_bw, 1348 int *excluded) 1349 { 1350 struct wpa_cred *cred, *selected = NULL; 1351 const u8 *ie; 1352 int is_excluded = 0; 1353 1354 ie = wpa_bss_get_ie(bss, WLAN_EID_ROAMING_CONSORTIUM); 1355 1356 if (ie == NULL && 1357 (bss->anqp == NULL || bss->anqp->roaming_consortium == NULL)) 1358 return NULL; 1359 1360 if (wpa_s->conf->cred == NULL) 1361 return NULL; 1362 1363 for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 1364 if (cred->roaming_consortium_len == 0) 1365 continue; 1366 1367 if (!roaming_consortium_match(ie, 1368 bss->anqp ? 1369 bss->anqp->roaming_consortium : 1370 NULL, 1371 cred->roaming_consortium, 1372 cred->roaming_consortium_len)) 1373 continue; 1374 1375 if (cred_no_required_oi_match(cred, bss)) 1376 continue; 1377 if (!ignore_bw && cred_below_min_backhaul(wpa_s, cred, bss)) 1378 continue; 1379 if (!ignore_bw && cred_over_max_bss_load(wpa_s, cred, bss)) 1380 continue; 1381 if (!ignore_bw && cred_conn_capab_missing(wpa_s, cred, bss)) 1382 continue; 1383 if (cred_excluded_ssid(cred, bss)) { 1384 if (excluded == NULL) 1385 continue; 1386 if (selected == NULL) { 1387 selected = cred; 1388 is_excluded = 1; 1389 } 1390 } else { 1391 if (selected == NULL || is_excluded || 1392 cred_prio_cmp(selected, cred) < 0) { 1393 selected = cred; 1394 is_excluded = 0; 1395 } 1396 } 1397 } 1398 1399 if (excluded) 1400 *excluded = is_excluded; 1401 1402 return selected; 1403 } 1404 1405 1406 static int interworking_set_eap_params(struct wpa_ssid *ssid, 1407 struct wpa_cred *cred, int ttls) 1408 { 1409 if (cred->eap_method) { 1410 ttls = cred->eap_method->vendor == EAP_VENDOR_IETF && 1411 cred->eap_method->method == EAP_TYPE_TTLS; 1412 1413 os_free(ssid->eap.eap_methods); 1414 ssid->eap.eap_methods = 1415 os_malloc(sizeof(struct eap_method_type) * 2); 1416 if (ssid->eap.eap_methods == NULL) 1417 return -1; 1418 os_memcpy(ssid->eap.eap_methods, cred->eap_method, 1419 sizeof(*cred->eap_method)); 1420 ssid->eap.eap_methods[1].vendor = EAP_VENDOR_IETF; 1421 ssid->eap.eap_methods[1].method = EAP_TYPE_NONE; 1422 } 1423 1424 if (ttls && cred->username && cred->username[0]) { 1425 const char *pos; 1426 char *anon; 1427 /* Use anonymous NAI in Phase 1 */ 1428 pos = os_strchr(cred->username, '@'); 1429 if (pos) { 1430 size_t buflen = 9 + os_strlen(pos) + 1; 1431 anon = os_malloc(buflen); 1432 if (anon == NULL) 1433 return -1; 1434 os_snprintf(anon, buflen, "anonymous%s", pos); 1435 } else if (cred->realm) { 1436 size_t buflen = 10 + os_strlen(cred->realm) + 1; 1437 anon = os_malloc(buflen); 1438 if (anon == NULL) 1439 return -1; 1440 os_snprintf(anon, buflen, "anonymous@%s", cred->realm); 1441 } else { 1442 anon = os_strdup("anonymous"); 1443 if (anon == NULL) 1444 return -1; 1445 } 1446 if (wpa_config_set_quoted(ssid, "anonymous_identity", anon) < 1447 0) { 1448 os_free(anon); 1449 return -1; 1450 } 1451 os_free(anon); 1452 } 1453 1454 if (!ttls && cred->username && cred->username[0] && cred->realm && 1455 !os_strchr(cred->username, '@')) { 1456 char *id; 1457 size_t buflen; 1458 int res; 1459 1460 buflen = os_strlen(cred->username) + 1 + 1461 os_strlen(cred->realm) + 1; 1462 1463 id = os_malloc(buflen); 1464 if (!id) 1465 return -1; 1466 os_snprintf(id, buflen, "%s@%s", cred->username, cred->realm); 1467 res = wpa_config_set_quoted(ssid, "identity", id); 1468 os_free(id); 1469 if (res < 0) 1470 return -1; 1471 } else if (cred->username && cred->username[0] && 1472 wpa_config_set_quoted(ssid, "identity", cred->username) < 0) 1473 return -1; 1474 1475 if (cred->password && cred->password[0]) { 1476 if (cred->ext_password && 1477 wpa_config_set(ssid, "password", cred->password, 0) < 0) 1478 return -1; 1479 if (!cred->ext_password && 1480 wpa_config_set_quoted(ssid, "password", cred->password) < 1481 0) 1482 return -1; 1483 } 1484 1485 if (cred->client_cert && cred->client_cert[0] && 1486 wpa_config_set_quoted(ssid, "client_cert", cred->client_cert) < 0) 1487 return -1; 1488 1489 #ifdef ANDROID 1490 if (cred->private_key && 1491 os_strncmp(cred->private_key, "keystore://", 11) == 0) { 1492 /* Use OpenSSL engine configuration for Android keystore */ 1493 if (wpa_config_set_quoted(ssid, "engine_id", "keystore") < 0 || 1494 wpa_config_set_quoted(ssid, "key_id", 1495 cred->private_key + 11) < 0 || 1496 wpa_config_set(ssid, "engine", "1", 0) < 0) 1497 return -1; 1498 } else 1499 #endif /* ANDROID */ 1500 if (cred->private_key && cred->private_key[0] && 1501 wpa_config_set_quoted(ssid, "private_key", cred->private_key) < 0) 1502 return -1; 1503 1504 if (cred->private_key_passwd && cred->private_key_passwd[0] && 1505 wpa_config_set_quoted(ssid, "private_key_passwd", 1506 cred->private_key_passwd) < 0) 1507 return -1; 1508 1509 if (cred->phase1) { 1510 os_free(ssid->eap.phase1); 1511 ssid->eap.phase1 = os_strdup(cred->phase1); 1512 } 1513 if (cred->phase2) { 1514 os_free(ssid->eap.phase2); 1515 ssid->eap.phase2 = os_strdup(cred->phase2); 1516 } 1517 1518 if (cred->ca_cert && cred->ca_cert[0] && 1519 wpa_config_set_quoted(ssid, "ca_cert", cred->ca_cert) < 0) 1520 return -1; 1521 1522 if (cred->domain_suffix_match && cred->domain_suffix_match[0] && 1523 wpa_config_set_quoted(ssid, "domain_suffix_match", 1524 cred->domain_suffix_match) < 0) 1525 return -1; 1526 1527 ssid->eap.ocsp = cred->ocsp; 1528 1529 return 0; 1530 } 1531 1532 1533 static int interworking_connect_roaming_consortium( 1534 struct wpa_supplicant *wpa_s, struct wpa_cred *cred, 1535 struct wpa_bss *bss, int only_add) 1536 { 1537 struct wpa_ssid *ssid; 1538 1539 wpa_msg(wpa_s, MSG_DEBUG, "Interworking: Connect with " MACSTR 1540 " based on roaming consortium match", MAC2STR(bss->bssid)); 1541 1542 if (already_connected(wpa_s, cred, bss)) { 1543 wpa_msg(wpa_s, MSG_INFO, INTERWORKING_ALREADY_CONNECTED MACSTR, 1544 MAC2STR(bss->bssid)); 1545 return wpa_s->current_ssid->id; 1546 } 1547 1548 remove_duplicate_network(wpa_s, cred, bss); 1549 1550 ssid = wpa_config_add_network(wpa_s->conf); 1551 if (ssid == NULL) 1552 return -1; 1553 ssid->parent_cred = cred; 1554 wpas_notify_network_added(wpa_s, ssid); 1555 wpa_config_set_network_defaults(ssid); 1556 ssid->priority = cred->priority; 1557 ssid->temporary = 1; 1558 ssid->ssid = os_zalloc(bss->ssid_len + 1); 1559 if (ssid->ssid == NULL) 1560 goto fail; 1561 os_memcpy(ssid->ssid, bss->ssid, bss->ssid_len); 1562 ssid->ssid_len = bss->ssid_len; 1563 1564 if (interworking_set_hs20_params(wpa_s, ssid) < 0) 1565 goto fail; 1566 1567 if (cred->eap_method == NULL) { 1568 wpa_msg(wpa_s, MSG_DEBUG, 1569 "Interworking: No EAP method set for credential using roaming consortium"); 1570 goto fail; 1571 } 1572 1573 if (interworking_set_eap_params( 1574 ssid, cred, 1575 cred->eap_method->vendor == EAP_VENDOR_IETF && 1576 cred->eap_method->method == EAP_TYPE_TTLS) < 0) 1577 goto fail; 1578 1579 wpa_s->next_ssid = ssid; 1580 wpa_config_update_prio_list(wpa_s->conf); 1581 if (!only_add) 1582 interworking_reconnect(wpa_s); 1583 1584 return ssid->id; 1585 1586 fail: 1587 wpas_notify_network_removed(wpa_s, ssid); 1588 wpa_config_remove_network(wpa_s->conf, ssid->id); 1589 return -1; 1590 } 1591 1592 1593 int interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, 1594 int only_add) 1595 { 1596 struct wpa_cred *cred, *cred_rc, *cred_3gpp; 1597 struct wpa_ssid *ssid; 1598 struct nai_realm *realm; 1599 struct nai_realm_eap *eap = NULL; 1600 u16 count, i; 1601 char buf[100]; 1602 int excluded = 0, *excl = &excluded; 1603 const char *name; 1604 1605 if (wpa_s->conf->cred == NULL || bss == NULL) 1606 return -1; 1607 if (disallowed_bssid(wpa_s, bss->bssid) || 1608 disallowed_ssid(wpa_s, bss->ssid, bss->ssid_len)) { 1609 wpa_msg(wpa_s, MSG_DEBUG, 1610 "Interworking: Reject connection to disallowed BSS " 1611 MACSTR, MAC2STR(bss->bssid)); 1612 return -1; 1613 } 1614 1615 wpa_printf(MSG_DEBUG, "Interworking: Considering BSS " MACSTR 1616 " for connection", 1617 MAC2STR(bss->bssid)); 1618 1619 if (!wpa_bss_get_ie(bss, WLAN_EID_RSN)) { 1620 /* 1621 * We currently support only HS 2.0 networks and those are 1622 * required to use WPA2-Enterprise. 1623 */ 1624 wpa_msg(wpa_s, MSG_DEBUG, 1625 "Interworking: Network does not use RSN"); 1626 return -1; 1627 } 1628 1629 cred_rc = interworking_credentials_available_roaming_consortium( 1630 wpa_s, bss, 0, excl); 1631 if (cred_rc) { 1632 wpa_msg(wpa_s, MSG_DEBUG, 1633 "Interworking: Highest roaming consortium matching credential priority %d sp_priority %d", 1634 cred_rc->priority, cred_rc->sp_priority); 1635 if (excl && !(*excl)) 1636 excl = NULL; 1637 } 1638 1639 cred = interworking_credentials_available_realm(wpa_s, bss, 0, excl); 1640 if (cred) { 1641 wpa_msg(wpa_s, MSG_DEBUG, 1642 "Interworking: Highest NAI Realm list matching credential priority %d sp_priority %d", 1643 cred->priority, cred->sp_priority); 1644 if (excl && !(*excl)) 1645 excl = NULL; 1646 } 1647 1648 cred_3gpp = interworking_credentials_available_3gpp(wpa_s, bss, 0, 1649 excl); 1650 if (cred_3gpp) { 1651 wpa_msg(wpa_s, MSG_DEBUG, 1652 "Interworking: Highest 3GPP matching credential priority %d sp_priority %d", 1653 cred_3gpp->priority, cred_3gpp->sp_priority); 1654 if (excl && !(*excl)) 1655 excl = NULL; 1656 } 1657 1658 if (!cred_rc && !cred && !cred_3gpp) { 1659 wpa_msg(wpa_s, MSG_DEBUG, 1660 "Interworking: No full credential matches - consider options without BW(etc.) limits"); 1661 cred_rc = interworking_credentials_available_roaming_consortium( 1662 wpa_s, bss, 1, excl); 1663 if (cred_rc) { 1664 wpa_msg(wpa_s, MSG_DEBUG, 1665 "Interworking: Highest roaming consortium matching credential priority %d sp_priority %d (ignore BW)", 1666 cred_rc->priority, cred_rc->sp_priority); 1667 if (excl && !(*excl)) 1668 excl = NULL; 1669 } 1670 1671 cred = interworking_credentials_available_realm(wpa_s, bss, 1, 1672 excl); 1673 if (cred) { 1674 wpa_msg(wpa_s, MSG_DEBUG, 1675 "Interworking: Highest NAI Realm list matching credential priority %d sp_priority %d (ignore BW)", 1676 cred->priority, cred->sp_priority); 1677 if (excl && !(*excl)) 1678 excl = NULL; 1679 } 1680 1681 cred_3gpp = interworking_credentials_available_3gpp(wpa_s, bss, 1682 1, excl); 1683 if (cred_3gpp) { 1684 wpa_msg(wpa_s, MSG_DEBUG, 1685 "Interworking: Highest 3GPP matching credential priority %d sp_priority %d (ignore BW)", 1686 cred_3gpp->priority, cred_3gpp->sp_priority); 1687 if (excl && !(*excl)) 1688 excl = NULL; 1689 } 1690 } 1691 1692 if (cred_rc && 1693 (cred == NULL || cred_prio_cmp(cred_rc, cred) >= 0) && 1694 (cred_3gpp == NULL || cred_prio_cmp(cred_rc, cred_3gpp) >= 0)) 1695 return interworking_connect_roaming_consortium(wpa_s, cred_rc, 1696 bss, only_add); 1697 1698 if (cred_3gpp && 1699 (cred == NULL || cred_prio_cmp(cred_3gpp, cred) >= 0)) { 1700 return interworking_connect_3gpp(wpa_s, cred_3gpp, bss, 1701 only_add); 1702 } 1703 1704 if (cred == NULL) { 1705 wpa_msg(wpa_s, MSG_DEBUG, 1706 "Interworking: No matching credentials found for " 1707 MACSTR, MAC2STR(bss->bssid)); 1708 return -1; 1709 } 1710 1711 realm = nai_realm_parse(bss->anqp ? bss->anqp->nai_realm : NULL, 1712 &count); 1713 if (realm == NULL) { 1714 wpa_msg(wpa_s, MSG_DEBUG, 1715 "Interworking: Could not parse NAI Realm list from " 1716 MACSTR, MAC2STR(bss->bssid)); 1717 return -1; 1718 } 1719 1720 for (i = 0; i < count; i++) { 1721 if (!nai_realm_match(&realm[i], cred->realm)) 1722 continue; 1723 eap = nai_realm_find_eap(wpa_s, cred, &realm[i]); 1724 if (eap) 1725 break; 1726 } 1727 1728 if (!eap) { 1729 wpa_msg(wpa_s, MSG_DEBUG, 1730 "Interworking: No matching credentials and EAP method found for " 1731 MACSTR, MAC2STR(bss->bssid)); 1732 nai_realm_free(realm, count); 1733 return -1; 1734 } 1735 1736 wpa_msg(wpa_s, MSG_DEBUG, "Interworking: Connect with " MACSTR, 1737 MAC2STR(bss->bssid)); 1738 1739 if (already_connected(wpa_s, cred, bss)) { 1740 wpa_msg(wpa_s, MSG_INFO, INTERWORKING_ALREADY_CONNECTED MACSTR, 1741 MAC2STR(bss->bssid)); 1742 nai_realm_free(realm, count); 1743 return 0; 1744 } 1745 1746 remove_duplicate_network(wpa_s, cred, bss); 1747 1748 ssid = wpa_config_add_network(wpa_s->conf); 1749 if (ssid == NULL) { 1750 nai_realm_free(realm, count); 1751 return -1; 1752 } 1753 ssid->parent_cred = cred; 1754 wpas_notify_network_added(wpa_s, ssid); 1755 wpa_config_set_network_defaults(ssid); 1756 ssid->priority = cred->priority; 1757 ssid->temporary = 1; 1758 ssid->ssid = os_zalloc(bss->ssid_len + 1); 1759 if (ssid->ssid == NULL) 1760 goto fail; 1761 os_memcpy(ssid->ssid, bss->ssid, bss->ssid_len); 1762 ssid->ssid_len = bss->ssid_len; 1763 1764 if (interworking_set_hs20_params(wpa_s, ssid) < 0) 1765 goto fail; 1766 1767 if (wpa_config_set(ssid, "eap", eap_get_name(EAP_VENDOR_IETF, 1768 eap->method), 0) < 0) 1769 goto fail; 1770 1771 switch (eap->method) { 1772 case EAP_TYPE_TTLS: 1773 if (eap->inner_method) { 1774 name = eap_get_name(EAP_VENDOR_IETF, eap->inner_method); 1775 if (!name) 1776 goto fail; 1777 os_snprintf(buf, sizeof(buf), "\"autheap=%s\"", name); 1778 if (wpa_config_set(ssid, "phase2", buf, 0) < 0) 1779 goto fail; 1780 break; 1781 } 1782 switch (eap->inner_non_eap) { 1783 case NAI_REALM_INNER_NON_EAP_PAP: 1784 if (wpa_config_set(ssid, "phase2", "\"auth=PAP\"", 0) < 1785 0) 1786 goto fail; 1787 break; 1788 case NAI_REALM_INNER_NON_EAP_CHAP: 1789 if (wpa_config_set(ssid, "phase2", "\"auth=CHAP\"", 0) 1790 < 0) 1791 goto fail; 1792 break; 1793 case NAI_REALM_INNER_NON_EAP_MSCHAP: 1794 if (wpa_config_set(ssid, "phase2", "\"auth=MSCHAP\"", 1795 0) < 0) 1796 goto fail; 1797 break; 1798 case NAI_REALM_INNER_NON_EAP_MSCHAPV2: 1799 if (wpa_config_set(ssid, "phase2", "\"auth=MSCHAPV2\"", 1800 0) < 0) 1801 goto fail; 1802 break; 1803 default: 1804 /* EAP params were not set - assume TTLS/MSCHAPv2 */ 1805 if (wpa_config_set(ssid, "phase2", "\"auth=MSCHAPV2\"", 1806 0) < 0) 1807 goto fail; 1808 break; 1809 } 1810 break; 1811 case EAP_TYPE_PEAP: 1812 case EAP_TYPE_FAST: 1813 if (wpa_config_set(ssid, "phase1", "\"fast_provisioning=2\"", 1814 0) < 0) 1815 goto fail; 1816 if (wpa_config_set(ssid, "pac_file", 1817 "\"blob://pac_interworking\"", 0) < 0) 1818 goto fail; 1819 name = eap_get_name(EAP_VENDOR_IETF, 1820 eap->inner_method ? eap->inner_method : 1821 EAP_TYPE_MSCHAPV2); 1822 if (name == NULL) 1823 goto fail; 1824 os_snprintf(buf, sizeof(buf), "\"auth=%s\"", name); 1825 if (wpa_config_set(ssid, "phase2", buf, 0) < 0) 1826 goto fail; 1827 break; 1828 case EAP_TYPE_TLS: 1829 break; 1830 } 1831 1832 if (interworking_set_eap_params(ssid, cred, 1833 eap->method == EAP_TYPE_TTLS) < 0) 1834 goto fail; 1835 1836 nai_realm_free(realm, count); 1837 1838 wpa_s->next_ssid = ssid; 1839 wpa_config_update_prio_list(wpa_s->conf); 1840 if (!only_add) 1841 interworking_reconnect(wpa_s); 1842 1843 return ssid->id; 1844 1845 fail: 1846 wpas_notify_network_removed(wpa_s, ssid); 1847 wpa_config_remove_network(wpa_s->conf, ssid->id); 1848 nai_realm_free(realm, count); 1849 return -1; 1850 } 1851 1852 1853 #ifdef PCSC_FUNCS 1854 static int interworking_pcsc_read_imsi(struct wpa_supplicant *wpa_s) 1855 { 1856 size_t len; 1857 1858 if (wpa_s->imsi[0] && wpa_s->mnc_len) 1859 return 0; 1860 1861 len = sizeof(wpa_s->imsi) - 1; 1862 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) { 1863 scard_deinit(wpa_s->scard); 1864 wpa_s->scard = NULL; 1865 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI"); 1866 return -1; 1867 } 1868 wpa_s->imsi[len] = '\0'; 1869 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard); 1870 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)", 1871 wpa_s->imsi, wpa_s->mnc_len); 1872 1873 return 0; 1874 } 1875 #endif /* PCSC_FUNCS */ 1876 1877 1878 static struct wpa_cred * interworking_credentials_available_3gpp( 1879 struct wpa_supplicant *wpa_s, struct wpa_bss *bss, int ignore_bw, 1880 int *excluded) 1881 { 1882 struct wpa_cred *selected = NULL; 1883 #ifdef INTERWORKING_3GPP 1884 struct wpa_cred *cred; 1885 int ret; 1886 int is_excluded = 0; 1887 1888 if (bss->anqp == NULL || bss->anqp->anqp_3gpp == NULL) { 1889 wpa_msg(wpa_s, MSG_DEBUG, 1890 "interworking-avail-3gpp: not avail, anqp: %p anqp_3gpp: %p", 1891 bss->anqp, bss->anqp ? bss->anqp->anqp_3gpp : NULL); 1892 return NULL; 1893 } 1894 1895 #ifdef CONFIG_EAP_PROXY 1896 if (!wpa_s->imsi[0]) { 1897 size_t len; 1898 wpa_msg(wpa_s, MSG_DEBUG, 1899 "Interworking: IMSI not available - try to read again through eap_proxy"); 1900 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1, 1901 wpa_s->imsi, 1902 &len); 1903 if (wpa_s->mnc_len > 0) { 1904 wpa_s->imsi[len] = '\0'; 1905 wpa_msg(wpa_s, MSG_DEBUG, 1906 "eap_proxy: IMSI %s (MNC length %d)", 1907 wpa_s->imsi, wpa_s->mnc_len); 1908 } else { 1909 wpa_msg(wpa_s, MSG_DEBUG, 1910 "eap_proxy: IMSI not available"); 1911 } 1912 } 1913 #endif /* CONFIG_EAP_PROXY */ 1914 1915 for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 1916 char *sep; 1917 const char *imsi; 1918 int mnc_len; 1919 char imsi_buf[16]; 1920 size_t msin_len; 1921 1922 #ifdef PCSC_FUNCS 1923 if (cred->pcsc && wpa_s->scard) { 1924 if (interworking_pcsc_read_imsi(wpa_s) < 0) 1925 continue; 1926 imsi = wpa_s->imsi; 1927 mnc_len = wpa_s->mnc_len; 1928 goto compare; 1929 } 1930 #endif /* PCSC_FUNCS */ 1931 #ifdef CONFIG_EAP_PROXY 1932 if (cred->pcsc && wpa_s->mnc_len > 0 && wpa_s->imsi[0]) { 1933 imsi = wpa_s->imsi; 1934 mnc_len = wpa_s->mnc_len; 1935 goto compare; 1936 } 1937 #endif /* CONFIG_EAP_PROXY */ 1938 1939 if (cred->imsi == NULL || !cred->imsi[0] || 1940 (!wpa_s->conf->external_sim && 1941 (cred->milenage == NULL || !cred->milenage[0]))) 1942 continue; 1943 1944 sep = os_strchr(cred->imsi, '-'); 1945 if (sep == NULL || 1946 (sep - cred->imsi != 5 && sep - cred->imsi != 6)) 1947 continue; 1948 mnc_len = sep - cred->imsi - 3; 1949 os_memcpy(imsi_buf, cred->imsi, 3 + mnc_len); 1950 sep++; 1951 msin_len = os_strlen(cred->imsi); 1952 if (3 + mnc_len + msin_len >= sizeof(imsi_buf) - 1) 1953 msin_len = sizeof(imsi_buf) - 3 - mnc_len - 1; 1954 os_memcpy(&imsi_buf[3 + mnc_len], sep, msin_len); 1955 imsi_buf[3 + mnc_len + msin_len] = '\0'; 1956 imsi = imsi_buf; 1957 1958 #if defined(PCSC_FUNCS) || defined(CONFIG_EAP_PROXY) 1959 compare: 1960 #endif /* PCSC_FUNCS || CONFIG_EAP_PROXY */ 1961 wpa_msg(wpa_s, MSG_DEBUG, 1962 "Interworking: Parsing 3GPP info from " MACSTR, 1963 MAC2STR(bss->bssid)); 1964 ret = plmn_id_match(bss->anqp->anqp_3gpp, imsi, mnc_len); 1965 wpa_msg(wpa_s, MSG_DEBUG, "PLMN match %sfound", 1966 ret ? "" : "not "); 1967 if (ret) { 1968 if (cred_no_required_oi_match(cred, bss)) 1969 continue; 1970 if (!ignore_bw && 1971 cred_below_min_backhaul(wpa_s, cred, bss)) 1972 continue; 1973 if (!ignore_bw && 1974 cred_over_max_bss_load(wpa_s, cred, bss)) 1975 continue; 1976 if (!ignore_bw && 1977 cred_conn_capab_missing(wpa_s, cred, bss)) 1978 continue; 1979 if (cred_excluded_ssid(cred, bss)) { 1980 if (excluded == NULL) 1981 continue; 1982 if (selected == NULL) { 1983 selected = cred; 1984 is_excluded = 1; 1985 } 1986 } else { 1987 if (selected == NULL || is_excluded || 1988 cred_prio_cmp(selected, cred) < 0) { 1989 selected = cred; 1990 is_excluded = 0; 1991 } 1992 } 1993 } 1994 } 1995 1996 if (excluded) 1997 *excluded = is_excluded; 1998 #endif /* INTERWORKING_3GPP */ 1999 return selected; 2000 } 2001 2002 2003 static struct wpa_cred * interworking_credentials_available_realm( 2004 struct wpa_supplicant *wpa_s, struct wpa_bss *bss, int ignore_bw, 2005 int *excluded) 2006 { 2007 struct wpa_cred *cred, *selected = NULL; 2008 struct nai_realm *realm; 2009 u16 count, i; 2010 int is_excluded = 0; 2011 2012 if (bss->anqp == NULL || bss->anqp->nai_realm == NULL) 2013 return NULL; 2014 2015 if (wpa_s->conf->cred == NULL) 2016 return NULL; 2017 2018 wpa_msg(wpa_s, MSG_DEBUG, "Interworking: Parsing NAI Realm list from " 2019 MACSTR, MAC2STR(bss->bssid)); 2020 realm = nai_realm_parse(bss->anqp->nai_realm, &count); 2021 if (realm == NULL) { 2022 wpa_msg(wpa_s, MSG_DEBUG, 2023 "Interworking: Could not parse NAI Realm list from " 2024 MACSTR, MAC2STR(bss->bssid)); 2025 return NULL; 2026 } 2027 2028 for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 2029 if (cred->realm == NULL) 2030 continue; 2031 2032 for (i = 0; i < count; i++) { 2033 if (!nai_realm_match(&realm[i], cred->realm)) 2034 continue; 2035 if (nai_realm_find_eap(wpa_s, cred, &realm[i])) { 2036 if (cred_no_required_oi_match(cred, bss)) 2037 continue; 2038 if (!ignore_bw && 2039 cred_below_min_backhaul(wpa_s, cred, bss)) 2040 continue; 2041 if (!ignore_bw && 2042 cred_over_max_bss_load(wpa_s, cred, bss)) 2043 continue; 2044 if (!ignore_bw && 2045 cred_conn_capab_missing(wpa_s, cred, bss)) 2046 continue; 2047 if (cred_excluded_ssid(cred, bss)) { 2048 if (excluded == NULL) 2049 continue; 2050 if (selected == NULL) { 2051 selected = cred; 2052 is_excluded = 1; 2053 } 2054 } else { 2055 if (selected == NULL || is_excluded || 2056 cred_prio_cmp(selected, cred) < 0) 2057 { 2058 selected = cred; 2059 is_excluded = 0; 2060 } 2061 } 2062 break; 2063 } else { 2064 wpa_msg(wpa_s, MSG_DEBUG, 2065 "Interworking: realm-find-eap returned false"); 2066 } 2067 } 2068 } 2069 2070 nai_realm_free(realm, count); 2071 2072 if (excluded) 2073 *excluded = is_excluded; 2074 2075 return selected; 2076 } 2077 2078 2079 static struct wpa_cred * interworking_credentials_available_helper( 2080 struct wpa_supplicant *wpa_s, struct wpa_bss *bss, int ignore_bw, 2081 int *excluded) 2082 { 2083 struct wpa_cred *cred, *cred2; 2084 int excluded1, excluded2 = 0; 2085 2086 if (disallowed_bssid(wpa_s, bss->bssid) || 2087 disallowed_ssid(wpa_s, bss->ssid, bss->ssid_len)) { 2088 wpa_printf(MSG_DEBUG, "Interworking: Ignore disallowed BSS " 2089 MACSTR, MAC2STR(bss->bssid)); 2090 return NULL; 2091 } 2092 2093 cred = interworking_credentials_available_realm(wpa_s, bss, ignore_bw, 2094 &excluded1); 2095 cred2 = interworking_credentials_available_3gpp(wpa_s, bss, ignore_bw, 2096 &excluded2); 2097 if (cred && cred2 && 2098 (cred_prio_cmp(cred2, cred) >= 0 || (!excluded2 && excluded1))) { 2099 cred = cred2; 2100 excluded1 = excluded2; 2101 } 2102 if (!cred) { 2103 cred = cred2; 2104 excluded1 = excluded2; 2105 } 2106 2107 cred2 = interworking_credentials_available_roaming_consortium( 2108 wpa_s, bss, ignore_bw, &excluded2); 2109 if (cred && cred2 && 2110 (cred_prio_cmp(cred2, cred) >= 0 || (!excluded2 && excluded1))) { 2111 cred = cred2; 2112 excluded1 = excluded2; 2113 } 2114 if (!cred) { 2115 cred = cred2; 2116 excluded1 = excluded2; 2117 } 2118 2119 if (excluded) 2120 *excluded = excluded1; 2121 return cred; 2122 } 2123 2124 2125 static struct wpa_cred * interworking_credentials_available( 2126 struct wpa_supplicant *wpa_s, struct wpa_bss *bss, int *excluded) 2127 { 2128 struct wpa_cred *cred; 2129 2130 if (excluded) 2131 *excluded = 0; 2132 cred = interworking_credentials_available_helper(wpa_s, bss, 0, 2133 excluded); 2134 if (cred) 2135 return cred; 2136 return interworking_credentials_available_helper(wpa_s, bss, 1, 2137 excluded); 2138 } 2139 2140 2141 int domain_name_list_contains(struct wpabuf *domain_names, 2142 const char *domain, int exact_match) 2143 { 2144 const u8 *pos, *end; 2145 size_t len; 2146 2147 len = os_strlen(domain); 2148 pos = wpabuf_head(domain_names); 2149 end = pos + wpabuf_len(domain_names); 2150 2151 while (end - pos > 1) { 2152 u8 elen; 2153 2154 elen = *pos++; 2155 if (elen > end - pos) 2156 break; 2157 2158 wpa_hexdump_ascii(MSG_DEBUG, "Interworking: AP domain name", 2159 pos, elen); 2160 if (elen == len && 2161 os_strncasecmp(domain, (const char *) pos, len) == 0) 2162 return 1; 2163 if (!exact_match && elen > len && pos[elen - len - 1] == '.') { 2164 const char *ap = (const char *) pos; 2165 int offset = elen - len; 2166 2167 if (os_strncasecmp(domain, ap + offset, len) == 0) 2168 return 1; 2169 } 2170 2171 pos += elen; 2172 } 2173 2174 return 0; 2175 } 2176 2177 2178 int interworking_home_sp_cred(struct wpa_supplicant *wpa_s, 2179 struct wpa_cred *cred, 2180 struct wpabuf *domain_names) 2181 { 2182 size_t i; 2183 int ret = -1; 2184 #ifdef INTERWORKING_3GPP 2185 char nai[100], *realm; 2186 2187 char *imsi = NULL; 2188 int mnc_len = 0; 2189 if (cred->imsi) 2190 imsi = cred->imsi; 2191 #ifdef PCSC_FUNCS 2192 else if (cred->pcsc && wpa_s->scard) { 2193 if (interworking_pcsc_read_imsi(wpa_s) < 0) 2194 return -1; 2195 imsi = wpa_s->imsi; 2196 mnc_len = wpa_s->mnc_len; 2197 } 2198 #endif /* PCSC_FUNCS */ 2199 #ifdef CONFIG_EAP_PROXY 2200 else if (cred->pcsc && wpa_s->mnc_len > 0 && wpa_s->imsi[0]) { 2201 imsi = wpa_s->imsi; 2202 mnc_len = wpa_s->mnc_len; 2203 } 2204 #endif /* CONFIG_EAP_PROXY */ 2205 if (domain_names && 2206 imsi && build_root_nai(nai, sizeof(nai), imsi, mnc_len, 0) == 0) { 2207 realm = os_strchr(nai, '@'); 2208 if (realm) 2209 realm++; 2210 wpa_msg(wpa_s, MSG_DEBUG, 2211 "Interworking: Search for match with SIM/USIM domain %s", 2212 realm); 2213 if (realm && 2214 domain_name_list_contains(domain_names, realm, 1)) 2215 return 1; 2216 if (realm) 2217 ret = 0; 2218 } 2219 #endif /* INTERWORKING_3GPP */ 2220 2221 if (domain_names == NULL || cred->domain == NULL) 2222 return ret; 2223 2224 for (i = 0; i < cred->num_domain; i++) { 2225 wpa_msg(wpa_s, MSG_DEBUG, 2226 "Interworking: Search for match with home SP FQDN %s", 2227 cred->domain[i]); 2228 if (domain_name_list_contains(domain_names, cred->domain[i], 1)) 2229 return 1; 2230 } 2231 2232 return 0; 2233 } 2234 2235 2236 static int interworking_home_sp(struct wpa_supplicant *wpa_s, 2237 struct wpabuf *domain_names) 2238 { 2239 struct wpa_cred *cred; 2240 2241 if (domain_names == NULL || wpa_s->conf->cred == NULL) 2242 return -1; 2243 2244 for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 2245 int res = interworking_home_sp_cred(wpa_s, cred, domain_names); 2246 if (res) 2247 return res; 2248 } 2249 2250 return 0; 2251 } 2252 2253 2254 static int interworking_find_network_match(struct wpa_supplicant *wpa_s) 2255 { 2256 struct wpa_bss *bss; 2257 struct wpa_ssid *ssid; 2258 2259 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { 2260 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { 2261 if (wpas_network_disabled(wpa_s, ssid) || 2262 ssid->mode != WPAS_MODE_INFRA) 2263 continue; 2264 if (ssid->ssid_len != bss->ssid_len || 2265 os_memcmp(ssid->ssid, bss->ssid, ssid->ssid_len) != 2266 0) 2267 continue; 2268 /* 2269 * TODO: Consider more accurate matching of security 2270 * configuration similarly to what is done in events.c 2271 */ 2272 return 1; 2273 } 2274 } 2275 2276 return 0; 2277 } 2278 2279 2280 static int roaming_partner_match(struct wpa_supplicant *wpa_s, 2281 struct roaming_partner *partner, 2282 struct wpabuf *domain_names) 2283 { 2284 wpa_printf(MSG_DEBUG, "Interworking: Comparing roaming_partner info fqdn='%s' exact_match=%d priority=%u country='%s'", 2285 partner->fqdn, partner->exact_match, partner->priority, 2286 partner->country); 2287 wpa_hexdump_ascii(MSG_DEBUG, "Interworking: Domain names", 2288 wpabuf_head(domain_names), 2289 wpabuf_len(domain_names)); 2290 if (!domain_name_list_contains(domain_names, partner->fqdn, 2291 partner->exact_match)) 2292 return 0; 2293 /* TODO: match Country */ 2294 return 1; 2295 } 2296 2297 2298 static u8 roaming_prio(struct wpa_supplicant *wpa_s, struct wpa_cred *cred, 2299 struct wpa_bss *bss) 2300 { 2301 size_t i; 2302 2303 if (bss->anqp == NULL || bss->anqp->domain_name == NULL) { 2304 wpa_printf(MSG_DEBUG, "Interworking: No ANQP domain name info -> use default roaming partner priority 128"); 2305 return 128; /* cannot check preference with domain name */ 2306 } 2307 2308 if (interworking_home_sp_cred(wpa_s, cred, bss->anqp->domain_name) > 0) 2309 { 2310 wpa_printf(MSG_DEBUG, "Interworking: Determined to be home SP -> use maximum preference 0 as roaming partner priority"); 2311 return 0; /* max preference for home SP network */ 2312 } 2313 2314 for (i = 0; i < cred->num_roaming_partner; i++) { 2315 if (roaming_partner_match(wpa_s, &cred->roaming_partner[i], 2316 bss->anqp->domain_name)) { 2317 wpa_printf(MSG_DEBUG, "Interworking: Roaming partner preference match - priority %u", 2318 cred->roaming_partner[i].priority); 2319 return cred->roaming_partner[i].priority; 2320 } 2321 } 2322 2323 wpa_printf(MSG_DEBUG, "Interworking: No roaming partner preference match - use default roaming partner priority 128"); 2324 return 128; 2325 } 2326 2327 2328 static struct wpa_bss * pick_best_roaming_partner(struct wpa_supplicant *wpa_s, 2329 struct wpa_bss *selected, 2330 struct wpa_cred *cred) 2331 { 2332 struct wpa_bss *bss; 2333 u8 best_prio, prio; 2334 struct wpa_cred *cred2; 2335 2336 /* 2337 * Check if any other BSS is operated by a more preferred roaming 2338 * partner. 2339 */ 2340 2341 best_prio = roaming_prio(wpa_s, cred, selected); 2342 wpa_printf(MSG_DEBUG, "Interworking: roaming_prio=%u for selected BSS " 2343 MACSTR " (cred=%d)", best_prio, MAC2STR(selected->bssid), 2344 cred->id); 2345 2346 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { 2347 if (bss == selected) 2348 continue; 2349 cred2 = interworking_credentials_available(wpa_s, bss, NULL); 2350 if (!cred2) 2351 continue; 2352 if (!wpa_bss_get_ie(bss, WLAN_EID_RSN)) 2353 continue; 2354 prio = roaming_prio(wpa_s, cred2, bss); 2355 wpa_printf(MSG_DEBUG, "Interworking: roaming_prio=%u for BSS " 2356 MACSTR " (cred=%d)", prio, MAC2STR(bss->bssid), 2357 cred2->id); 2358 if (prio < best_prio) { 2359 int bh1, bh2, load1, load2, conn1, conn2; 2360 bh1 = cred_below_min_backhaul(wpa_s, cred, selected); 2361 load1 = cred_over_max_bss_load(wpa_s, cred, selected); 2362 conn1 = cred_conn_capab_missing(wpa_s, cred, selected); 2363 bh2 = cred_below_min_backhaul(wpa_s, cred2, bss); 2364 load2 = cred_over_max_bss_load(wpa_s, cred2, bss); 2365 conn2 = cred_conn_capab_missing(wpa_s, cred2, bss); 2366 wpa_printf(MSG_DEBUG, "Interworking: old: %d %d %d new: %d %d %d", 2367 bh1, load1, conn1, bh2, load2, conn2); 2368 if (bh1 || load1 || conn1 || !(bh2 || load2 || conn2)) { 2369 wpa_printf(MSG_DEBUG, "Interworking: Better roaming partner " MACSTR " selected", MAC2STR(bss->bssid)); 2370 best_prio = prio; 2371 selected = bss; 2372 } 2373 } 2374 } 2375 2376 return selected; 2377 } 2378 2379 2380 static void interworking_select_network(struct wpa_supplicant *wpa_s) 2381 { 2382 struct wpa_bss *bss, *selected = NULL, *selected_home = NULL; 2383 struct wpa_bss *selected2 = NULL, *selected2_home = NULL; 2384 unsigned int count = 0; 2385 const char *type; 2386 int res; 2387 struct wpa_cred *cred, *selected_cred = NULL; 2388 struct wpa_cred *selected_home_cred = NULL; 2389 struct wpa_cred *selected2_cred = NULL; 2390 struct wpa_cred *selected2_home_cred = NULL; 2391 2392 wpa_s->network_select = 0; 2393 2394 wpa_printf(MSG_DEBUG, "Interworking: Select network (auto_select=%d)", 2395 wpa_s->auto_select); 2396 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { 2397 int excluded = 0; 2398 int bh, bss_load, conn_capab; 2399 cred = interworking_credentials_available(wpa_s, bss, 2400 &excluded); 2401 if (!cred) 2402 continue; 2403 2404 if (!wpa_bss_get_ie(bss, WLAN_EID_RSN)) { 2405 /* 2406 * We currently support only HS 2.0 networks and those 2407 * are required to use WPA2-Enterprise. 2408 */ 2409 wpa_msg(wpa_s, MSG_DEBUG, 2410 "Interworking: Credential match with " MACSTR 2411 " but network does not use RSN", 2412 MAC2STR(bss->bssid)); 2413 continue; 2414 } 2415 if (!excluded) 2416 count++; 2417 res = interworking_home_sp(wpa_s, bss->anqp ? 2418 bss->anqp->domain_name : NULL); 2419 if (res > 0) 2420 type = "home"; 2421 else if (res == 0) 2422 type = "roaming"; 2423 else 2424 type = "unknown"; 2425 bh = cred_below_min_backhaul(wpa_s, cred, bss); 2426 bss_load = cred_over_max_bss_load(wpa_s, cred, bss); 2427 conn_capab = cred_conn_capab_missing(wpa_s, cred, bss); 2428 wpa_msg(wpa_s, MSG_INFO, "%s" MACSTR " type=%s%s%s%s id=%d priority=%d sp_priority=%d", 2429 excluded ? INTERWORKING_BLACKLISTED : INTERWORKING_AP, 2430 MAC2STR(bss->bssid), type, 2431 bh ? " below_min_backhaul=1" : "", 2432 bss_load ? " over_max_bss_load=1" : "", 2433 conn_capab ? " conn_capab_missing=1" : "", 2434 cred->id, cred->priority, cred->sp_priority); 2435 if (excluded) 2436 continue; 2437 if (wpa_s->auto_select || 2438 (wpa_s->conf->auto_interworking && 2439 wpa_s->auto_network_select)) { 2440 if (bh || bss_load || conn_capab) { 2441 if (selected2_cred == NULL || 2442 cred_prio_cmp(cred, selected2_cred) > 0) { 2443 wpa_printf(MSG_DEBUG, "Interworking: Mark as selected2"); 2444 selected2 = bss; 2445 selected2_cred = cred; 2446 } 2447 if (res > 0 && 2448 (selected2_home_cred == NULL || 2449 cred_prio_cmp(cred, selected2_home_cred) > 2450 0)) { 2451 wpa_printf(MSG_DEBUG, "Interworking: Mark as selected2_home"); 2452 selected2_home = bss; 2453 selected2_home_cred = cred; 2454 } 2455 } else { 2456 if (selected_cred == NULL || 2457 cred_prio_cmp(cred, selected_cred) > 0) { 2458 wpa_printf(MSG_DEBUG, "Interworking: Mark as selected"); 2459 selected = bss; 2460 selected_cred = cred; 2461 } 2462 if (res > 0 && 2463 (selected_home_cred == NULL || 2464 cred_prio_cmp(cred, selected_home_cred) > 2465 0)) { 2466 wpa_printf(MSG_DEBUG, "Interworking: Mark as selected_home"); 2467 selected_home = bss; 2468 selected_home_cred = cred; 2469 } 2470 } 2471 } 2472 } 2473 2474 if (selected_home && selected_home != selected && 2475 selected_home_cred && 2476 (selected_cred == NULL || 2477 cred_prio_cmp(selected_home_cred, selected_cred) >= 0)) { 2478 /* Prefer network operated by the Home SP */ 2479 wpa_printf(MSG_DEBUG, "Interworking: Overrided selected with selected_home"); 2480 selected = selected_home; 2481 selected_cred = selected_home_cred; 2482 } 2483 2484 if (!selected) { 2485 if (selected2_home) { 2486 wpa_printf(MSG_DEBUG, "Interworking: Use home BSS with BW limit mismatch since no other network could be selected"); 2487 selected = selected2_home; 2488 selected_cred = selected2_home_cred; 2489 } else if (selected2) { 2490 wpa_printf(MSG_DEBUG, "Interworking: Use visited BSS with BW limit mismatch since no other network could be selected"); 2491 selected = selected2; 2492 selected_cred = selected2_cred; 2493 } 2494 } 2495 2496 if (count == 0) { 2497 /* 2498 * No matching network was found based on configured 2499 * credentials. Check whether any of the enabled network blocks 2500 * have matching APs. 2501 */ 2502 if (interworking_find_network_match(wpa_s)) { 2503 wpa_msg(wpa_s, MSG_DEBUG, 2504 "Interworking: Possible BSS match for enabled network configurations"); 2505 if (wpa_s->auto_select) { 2506 interworking_reconnect(wpa_s); 2507 return; 2508 } 2509 } 2510 2511 if (wpa_s->auto_network_select) { 2512 wpa_msg(wpa_s, MSG_DEBUG, 2513 "Interworking: Continue scanning after ANQP fetch"); 2514 wpa_supplicant_req_scan(wpa_s, wpa_s->scan_interval, 2515 0); 2516 return; 2517 } 2518 2519 wpa_msg(wpa_s, MSG_INFO, INTERWORKING_NO_MATCH "No network " 2520 "with matching credentials found"); 2521 if (wpa_s->wpa_state == WPA_SCANNING) 2522 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); 2523 } 2524 2525 if (selected) { 2526 wpa_printf(MSG_DEBUG, "Interworking: Selected " MACSTR, 2527 MAC2STR(selected->bssid)); 2528 selected = pick_best_roaming_partner(wpa_s, selected, 2529 selected_cred); 2530 wpa_printf(MSG_DEBUG, "Interworking: Selected " MACSTR 2531 " (after best roaming partner selection)", 2532 MAC2STR(selected->bssid)); 2533 wpa_msg(wpa_s, MSG_INFO, INTERWORKING_SELECTED MACSTR, 2534 MAC2STR(selected->bssid)); 2535 interworking_connect(wpa_s, selected, 0); 2536 } else if (wpa_s->wpa_state == WPA_SCANNING) 2537 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); 2538 } 2539 2540 2541 static struct wpa_bss_anqp * 2542 interworking_match_anqp_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss) 2543 { 2544 struct wpa_bss *other; 2545 2546 if (is_zero_ether_addr(bss->hessid)) 2547 return NULL; /* Cannot be in the same homegenous ESS */ 2548 2549 dl_list_for_each(other, &wpa_s->bss, struct wpa_bss, list) { 2550 if (other == bss) 2551 continue; 2552 if (other->anqp == NULL) 2553 continue; 2554 if (other->anqp->roaming_consortium == NULL && 2555 other->anqp->nai_realm == NULL && 2556 other->anqp->anqp_3gpp == NULL && 2557 other->anqp->domain_name == NULL) 2558 continue; 2559 if (!(other->flags & WPA_BSS_ANQP_FETCH_TRIED)) 2560 continue; 2561 if (os_memcmp(bss->hessid, other->hessid, ETH_ALEN) != 0) 2562 continue; 2563 if (bss->ssid_len != other->ssid_len || 2564 os_memcmp(bss->ssid, other->ssid, bss->ssid_len) != 0) 2565 continue; 2566 2567 wpa_msg(wpa_s, MSG_DEBUG, 2568 "Interworking: Share ANQP data with already fetched BSSID " 2569 MACSTR " and " MACSTR, 2570 MAC2STR(other->bssid), MAC2STR(bss->bssid)); 2571 other->anqp->users++; 2572 return other->anqp; 2573 } 2574 2575 return NULL; 2576 } 2577 2578 2579 static void interworking_next_anqp_fetch(struct wpa_supplicant *wpa_s) 2580 { 2581 struct wpa_bss *bss; 2582 int found = 0; 2583 const u8 *ie; 2584 2585 wpa_printf(MSG_DEBUG, "Interworking: next_anqp_fetch - " 2586 "fetch_anqp_in_progress=%d fetch_osu_icon_in_progress=%d", 2587 wpa_s->fetch_anqp_in_progress, 2588 wpa_s->fetch_osu_icon_in_progress); 2589 2590 if (eloop_terminated() || !wpa_s->fetch_anqp_in_progress) { 2591 wpa_printf(MSG_DEBUG, "Interworking: Stop next-ANQP-fetch"); 2592 return; 2593 } 2594 2595 #ifdef CONFIG_HS20 2596 if (wpa_s->fetch_osu_icon_in_progress) { 2597 wpa_printf(MSG_DEBUG, "Interworking: Next icon (in progress)"); 2598 hs20_next_osu_icon(wpa_s); 2599 return; 2600 } 2601 #endif /* CONFIG_HS20 */ 2602 2603 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { 2604 if (!(bss->caps & IEEE80211_CAP_ESS)) 2605 continue; 2606 ie = wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB); 2607 if (ie == NULL || ie[1] < 4 || !(ie[5] & 0x80)) 2608 continue; /* AP does not support Interworking */ 2609 if (disallowed_bssid(wpa_s, bss->bssid) || 2610 disallowed_ssid(wpa_s, bss->ssid, bss->ssid_len)) 2611 continue; /* Disallowed BSS */ 2612 2613 if (!(bss->flags & WPA_BSS_ANQP_FETCH_TRIED)) { 2614 if (bss->anqp == NULL) { 2615 bss->anqp = interworking_match_anqp_info(wpa_s, 2616 bss); 2617 if (bss->anqp) { 2618 /* Shared data already fetched */ 2619 continue; 2620 } 2621 bss->anqp = wpa_bss_anqp_alloc(); 2622 if (bss->anqp == NULL) 2623 break; 2624 } 2625 found++; 2626 bss->flags |= WPA_BSS_ANQP_FETCH_TRIED; 2627 wpa_msg(wpa_s, MSG_INFO, "Starting ANQP fetch for " 2628 MACSTR, MAC2STR(bss->bssid)); 2629 interworking_anqp_send_req(wpa_s, bss); 2630 break; 2631 } 2632 } 2633 2634 if (found == 0) { 2635 #ifdef CONFIG_HS20 2636 if (wpa_s->fetch_osu_info) { 2637 if (wpa_s->num_prov_found == 0 && 2638 wpa_s->fetch_osu_waiting_scan && 2639 wpa_s->num_osu_scans < 3) { 2640 wpa_printf(MSG_DEBUG, "HS 2.0: No OSU providers seen - try to scan again"); 2641 hs20_start_osu_scan(wpa_s); 2642 return; 2643 } 2644 wpa_printf(MSG_DEBUG, "Interworking: Next icon"); 2645 hs20_osu_icon_fetch(wpa_s); 2646 return; 2647 } 2648 #endif /* CONFIG_HS20 */ 2649 wpa_msg(wpa_s, MSG_INFO, "ANQP fetch completed"); 2650 wpa_s->fetch_anqp_in_progress = 0; 2651 if (wpa_s->network_select) 2652 interworking_select_network(wpa_s); 2653 } 2654 } 2655 2656 2657 void interworking_start_fetch_anqp(struct wpa_supplicant *wpa_s) 2658 { 2659 struct wpa_bss *bss; 2660 2661 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) 2662 bss->flags &= ~WPA_BSS_ANQP_FETCH_TRIED; 2663 2664 wpa_s->fetch_anqp_in_progress = 1; 2665 2666 /* 2667 * Start actual ANQP operation from eloop call to make sure the loop 2668 * does not end up using excessive recursion. 2669 */ 2670 eloop_register_timeout(0, 0, interworking_continue_anqp, wpa_s, NULL); 2671 } 2672 2673 2674 int interworking_fetch_anqp(struct wpa_supplicant *wpa_s) 2675 { 2676 if (wpa_s->fetch_anqp_in_progress || wpa_s->network_select) 2677 return 0; 2678 2679 wpa_s->network_select = 0; 2680 wpa_s->fetch_all_anqp = 1; 2681 wpa_s->fetch_osu_info = 0; 2682 2683 interworking_start_fetch_anqp(wpa_s); 2684 2685 return 0; 2686 } 2687 2688 2689 void interworking_stop_fetch_anqp(struct wpa_supplicant *wpa_s) 2690 { 2691 if (!wpa_s->fetch_anqp_in_progress) 2692 return; 2693 2694 wpa_s->fetch_anqp_in_progress = 0; 2695 } 2696 2697 2698 int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, 2699 u16 info_ids[], size_t num_ids, u32 subtypes, 2700 u32 mbo_subtypes) 2701 { 2702 struct wpabuf *buf; 2703 struct wpabuf *extra_buf = NULL; 2704 int ret = 0; 2705 int freq; 2706 struct wpa_bss *bss; 2707 int res; 2708 2709 bss = wpa_bss_get_bssid(wpa_s, dst); 2710 if (!bss) { 2711 wpa_printf(MSG_WARNING, 2712 "ANQP: Cannot send query to unknown BSS " 2713 MACSTR, MAC2STR(dst)); 2714 return -1; 2715 } 2716 2717 wpa_bss_anqp_unshare_alloc(bss); 2718 freq = bss->freq; 2719 2720 wpa_msg(wpa_s, MSG_DEBUG, 2721 "ANQP: Query Request to " MACSTR " for %u id(s)", 2722 MAC2STR(dst), (unsigned int) num_ids); 2723 2724 #ifdef CONFIG_HS20 2725 if (subtypes != 0) { 2726 extra_buf = wpabuf_alloc(100); 2727 if (extra_buf == NULL) 2728 return -1; 2729 hs20_put_anqp_req(subtypes, NULL, 0, extra_buf); 2730 } 2731 #endif /* CONFIG_HS20 */ 2732 2733 #ifdef CONFIG_MBO 2734 if (mbo_subtypes) { 2735 struct wpabuf *mbo; 2736 2737 mbo = mbo_build_anqp_buf(wpa_s, bss, mbo_subtypes); 2738 if (mbo) { 2739 if (wpabuf_resize(&extra_buf, wpabuf_len(mbo))) { 2740 wpabuf_free(extra_buf); 2741 wpabuf_free(mbo); 2742 return -1; 2743 } 2744 wpabuf_put_buf(extra_buf, mbo); 2745 wpabuf_free(mbo); 2746 } 2747 } 2748 #endif /* CONFIG_MBO */ 2749 2750 buf = anqp_build_req(info_ids, num_ids, extra_buf); 2751 wpabuf_free(extra_buf); 2752 if (buf == NULL) 2753 return -1; 2754 2755 res = gas_query_req(wpa_s->gas, dst, freq, buf, anqp_resp_cb, wpa_s); 2756 if (res < 0) { 2757 wpa_msg(wpa_s, MSG_DEBUG, "ANQP: Failed to send Query Request"); 2758 wpabuf_free(buf); 2759 ret = -1; 2760 } else { 2761 wpa_msg(wpa_s, MSG_DEBUG, 2762 "ANQP: Query started with dialog token %u", res); 2763 } 2764 2765 return ret; 2766 } 2767 2768 2769 static void anqp_add_extra(struct wpa_supplicant *wpa_s, 2770 struct wpa_bss_anqp *anqp, u16 info_id, 2771 const u8 *data, size_t slen) 2772 { 2773 struct wpa_bss_anqp_elem *tmp, *elem = NULL; 2774 2775 if (!anqp) 2776 return; 2777 2778 dl_list_for_each(tmp, &anqp->anqp_elems, struct wpa_bss_anqp_elem, 2779 list) { 2780 if (tmp->infoid == info_id) { 2781 elem = tmp; 2782 break; 2783 } 2784 } 2785 2786 if (!elem) { 2787 elem = os_zalloc(sizeof(*elem)); 2788 if (!elem) 2789 return; 2790 elem->infoid = info_id; 2791 dl_list_add(&anqp->anqp_elems, &elem->list); 2792 } else { 2793 wpabuf_free(elem->payload); 2794 } 2795 2796 elem->payload = wpabuf_alloc_copy(data, slen); 2797 if (!elem->payload) { 2798 dl_list_del(&elem->list); 2799 os_free(elem); 2800 } 2801 } 2802 2803 2804 static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s, 2805 struct wpa_bss *bss, const u8 *sa, 2806 u16 info_id, 2807 const u8 *data, size_t slen, 2808 u8 dialog_token) 2809 { 2810 const u8 *pos = data; 2811 struct wpa_bss_anqp *anqp = NULL; 2812 u8 type; 2813 2814 if (bss) 2815 anqp = bss->anqp; 2816 2817 switch (info_id) { 2818 case ANQP_CAPABILITY_LIST: 2819 wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR 2820 " ANQP Capability list", MAC2STR(sa)); 2821 wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Capability list", 2822 pos, slen); 2823 if (anqp) { 2824 wpabuf_free(anqp->capability_list); 2825 anqp->capability_list = wpabuf_alloc_copy(pos, slen); 2826 } 2827 break; 2828 case ANQP_VENUE_NAME: 2829 wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR 2830 " Venue Name", MAC2STR(sa)); 2831 wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Venue Name", pos, slen); 2832 if (anqp) { 2833 wpabuf_free(anqp->venue_name); 2834 anqp->venue_name = wpabuf_alloc_copy(pos, slen); 2835 } 2836 break; 2837 case ANQP_NETWORK_AUTH_TYPE: 2838 wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR 2839 " Network Authentication Type information", 2840 MAC2STR(sa)); 2841 wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Network Authentication " 2842 "Type", pos, slen); 2843 if (anqp) { 2844 wpabuf_free(anqp->network_auth_type); 2845 anqp->network_auth_type = wpabuf_alloc_copy(pos, slen); 2846 } 2847 break; 2848 case ANQP_ROAMING_CONSORTIUM: 2849 wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR 2850 " Roaming Consortium list", MAC2STR(sa)); 2851 wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Roaming Consortium", 2852 pos, slen); 2853 if (anqp) { 2854 wpabuf_free(anqp->roaming_consortium); 2855 anqp->roaming_consortium = wpabuf_alloc_copy(pos, slen); 2856 } 2857 break; 2858 case ANQP_IP_ADDR_TYPE_AVAILABILITY: 2859 wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR 2860 " IP Address Type Availability information", 2861 MAC2STR(sa)); 2862 wpa_hexdump(MSG_MSGDUMP, "ANQP: IP Address Availability", 2863 pos, slen); 2864 if (anqp) { 2865 wpabuf_free(anqp->ip_addr_type_availability); 2866 anqp->ip_addr_type_availability = 2867 wpabuf_alloc_copy(pos, slen); 2868 } 2869 break; 2870 case ANQP_NAI_REALM: 2871 wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR 2872 " NAI Realm list", MAC2STR(sa)); 2873 wpa_hexdump_ascii(MSG_DEBUG, "ANQP: NAI Realm", pos, slen); 2874 if (anqp) { 2875 wpabuf_free(anqp->nai_realm); 2876 anqp->nai_realm = wpabuf_alloc_copy(pos, slen); 2877 } 2878 break; 2879 case ANQP_3GPP_CELLULAR_NETWORK: 2880 wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR 2881 " 3GPP Cellular Network information", MAC2STR(sa)); 2882 wpa_hexdump_ascii(MSG_DEBUG, "ANQP: 3GPP Cellular Network", 2883 pos, slen); 2884 if (anqp) { 2885 wpabuf_free(anqp->anqp_3gpp); 2886 anqp->anqp_3gpp = wpabuf_alloc_copy(pos, slen); 2887 } 2888 break; 2889 case ANQP_DOMAIN_NAME: 2890 wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR 2891 " Domain Name list", MAC2STR(sa)); 2892 wpa_hexdump_ascii(MSG_MSGDUMP, "ANQP: Domain Name", pos, slen); 2893 if (anqp) { 2894 wpabuf_free(anqp->domain_name); 2895 anqp->domain_name = wpabuf_alloc_copy(pos, slen); 2896 } 2897 break; 2898 #ifdef CONFIG_FILS 2899 case ANQP_FILS_REALM_INFO: 2900 wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR 2901 " FILS Realm Information", MAC2STR(sa)); 2902 wpa_hexdump_ascii(MSG_MSGDUMP, "ANQP: FILS Realm Information", 2903 pos, slen); 2904 if (anqp) { 2905 wpabuf_free(anqp->fils_realm_info); 2906 anqp->fils_realm_info = wpabuf_alloc_copy(pos, slen); 2907 } 2908 break; 2909 #endif /* CONFIG_FILS */ 2910 case ANQP_VENDOR_SPECIFIC: 2911 if (slen < 3) 2912 return; 2913 2914 switch (WPA_GET_BE24(pos)) { 2915 case OUI_WFA: 2916 pos += 3; 2917 slen -= 3; 2918 2919 if (slen < 1) 2920 return; 2921 type = *pos++; 2922 slen--; 2923 2924 switch (type) { 2925 #ifdef CONFIG_HS20 2926 case HS20_ANQP_OUI_TYPE: 2927 hs20_parse_rx_hs20_anqp_resp(wpa_s, bss, sa, 2928 pos, slen, 2929 dialog_token); 2930 break; 2931 #endif /* CONFIG_HS20 */ 2932 #ifdef CONFIG_MBO 2933 case MBO_ANQP_OUI_TYPE: 2934 mbo_parse_rx_anqp_resp(wpa_s, bss, sa, 2935 pos, slen); 2936 break; 2937 #endif /* CONFIG_MBO */ 2938 default: 2939 wpa_msg(wpa_s, MSG_DEBUG, 2940 "ANQP: Unsupported ANQP vendor type %u", 2941 type); 2942 break; 2943 } 2944 break; 2945 default: 2946 wpa_msg(wpa_s, MSG_DEBUG, 2947 "Interworking: Unsupported vendor-specific ANQP OUI %06x", 2948 WPA_GET_BE24(pos)); 2949 return; 2950 } 2951 break; 2952 default: 2953 wpa_msg(wpa_s, MSG_DEBUG, 2954 "Interworking: Unsupported ANQP Info ID %u", info_id); 2955 anqp_add_extra(wpa_s, anqp, info_id, data, slen); 2956 break; 2957 } 2958 } 2959 2960 2961 void anqp_resp_cb(void *ctx, const u8 *dst, u8 dialog_token, 2962 enum gas_query_result result, 2963 const struct wpabuf *adv_proto, 2964 const struct wpabuf *resp, u16 status_code) 2965 { 2966 struct wpa_supplicant *wpa_s = ctx; 2967 const u8 *pos; 2968 const u8 *end; 2969 u16 info_id; 2970 u16 slen; 2971 struct wpa_bss *bss = NULL, *tmp; 2972 const char *anqp_result = "SUCCESS"; 2973 2974 wpa_printf(MSG_DEBUG, "Interworking: anqp_resp_cb dst=" MACSTR 2975 " dialog_token=%u result=%d status_code=%u", 2976 MAC2STR(dst), dialog_token, result, status_code); 2977 if (result != GAS_QUERY_SUCCESS) { 2978 #ifdef CONFIG_HS20 2979 if (wpa_s->fetch_osu_icon_in_progress) 2980 hs20_icon_fetch_failed(wpa_s); 2981 #endif /* CONFIG_HS20 */ 2982 anqp_result = "FAILURE"; 2983 goto out; 2984 } 2985 2986 pos = wpabuf_head(adv_proto); 2987 if (wpabuf_len(adv_proto) < 4 || pos[0] != WLAN_EID_ADV_PROTO || 2988 pos[1] < 2 || pos[3] != ACCESS_NETWORK_QUERY_PROTOCOL) { 2989 wpa_msg(wpa_s, MSG_DEBUG, 2990 "ANQP: Unexpected Advertisement Protocol in response"); 2991 #ifdef CONFIG_HS20 2992 if (wpa_s->fetch_osu_icon_in_progress) 2993 hs20_icon_fetch_failed(wpa_s); 2994 #endif /* CONFIG_HS20 */ 2995 anqp_result = "INVALID_FRAME"; 2996 goto out; 2997 } 2998 2999 /* 3000 * If possible, select the BSS entry based on which BSS entry was used 3001 * for the request. This can help in cases where multiple BSS entries 3002 * may exist for the same AP. 3003 */ 3004 dl_list_for_each_reverse(tmp, &wpa_s->bss, struct wpa_bss, list) { 3005 if (tmp == wpa_s->interworking_gas_bss && 3006 os_memcmp(tmp->bssid, dst, ETH_ALEN) == 0) { 3007 bss = tmp; 3008 break; 3009 } 3010 } 3011 if (bss == NULL) 3012 bss = wpa_bss_get_bssid(wpa_s, dst); 3013 3014 pos = wpabuf_head(resp); 3015 end = pos + wpabuf_len(resp); 3016 3017 while (pos < end) { 3018 unsigned int left = end - pos; 3019 3020 if (left < 4) { 3021 wpa_msg(wpa_s, MSG_DEBUG, "ANQP: Invalid element"); 3022 anqp_result = "INVALID_FRAME"; 3023 goto out_parse_done; 3024 } 3025 info_id = WPA_GET_LE16(pos); 3026 pos += 2; 3027 slen = WPA_GET_LE16(pos); 3028 pos += 2; 3029 left -= 4; 3030 if (left < slen) { 3031 wpa_msg(wpa_s, MSG_DEBUG, 3032 "ANQP: Invalid element length for Info ID %u", 3033 info_id); 3034 anqp_result = "INVALID_FRAME"; 3035 goto out_parse_done; 3036 } 3037 interworking_parse_rx_anqp_resp(wpa_s, bss, dst, info_id, pos, 3038 slen, dialog_token); 3039 pos += slen; 3040 } 3041 3042 out_parse_done: 3043 #ifdef CONFIG_HS20 3044 hs20_notify_parse_done(wpa_s); 3045 #endif /* CONFIG_HS20 */ 3046 out: 3047 wpa_msg(wpa_s, MSG_INFO, ANQP_QUERY_DONE "addr=" MACSTR " result=%s", 3048 MAC2STR(dst), anqp_result); 3049 wpas_notify_anqp_query_done(wpa_s, dst, anqp_result, bss ? bss->anqp : NULL); 3050 } 3051 3052 3053 static void interworking_scan_res_handler(struct wpa_supplicant *wpa_s, 3054 struct wpa_scan_results *scan_res) 3055 { 3056 wpa_msg(wpa_s, MSG_DEBUG, 3057 "Interworking: Scan results available - start ANQP fetch"); 3058 interworking_start_fetch_anqp(wpa_s); 3059 } 3060 3061 3062 int interworking_select(struct wpa_supplicant *wpa_s, int auto_select, 3063 int *freqs) 3064 { 3065 interworking_stop_fetch_anqp(wpa_s); 3066 wpa_s->network_select = 1; 3067 wpa_s->auto_network_select = 0; 3068 wpa_s->auto_select = !!auto_select; 3069 wpa_s->fetch_all_anqp = 0; 3070 wpa_s->fetch_osu_info = 0; 3071 wpa_msg(wpa_s, MSG_DEBUG, 3072 "Interworking: Start scan for network selection"); 3073 wpa_s->scan_res_handler = interworking_scan_res_handler; 3074 wpa_s->normal_scans = 0; 3075 wpa_s->scan_req = MANUAL_SCAN_REQ; 3076 os_free(wpa_s->manual_scan_freqs); 3077 wpa_s->manual_scan_freqs = freqs; 3078 wpa_s->after_wps = 0; 3079 wpa_s->known_wps_freq = 0; 3080 wpa_supplicant_req_scan(wpa_s, 0, 0); 3081 3082 return 0; 3083 } 3084 3085 3086 static void gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token, 3087 enum gas_query_result result, 3088 const struct wpabuf *adv_proto, 3089 const struct wpabuf *resp, u16 status_code) 3090 { 3091 struct wpa_supplicant *wpa_s = ctx; 3092 struct wpabuf *n; 3093 3094 wpa_msg(wpa_s, MSG_INFO, GAS_RESPONSE_INFO "addr=" MACSTR 3095 " dialog_token=%d status_code=%d resp_len=%d", 3096 MAC2STR(addr), dialog_token, status_code, 3097 resp ? (int) wpabuf_len(resp) : -1); 3098 if (!resp) 3099 return; 3100 3101 n = wpabuf_dup(resp); 3102 if (n == NULL) 3103 return; 3104 wpabuf_free(wpa_s->prev_gas_resp); 3105 wpa_s->prev_gas_resp = wpa_s->last_gas_resp; 3106 os_memcpy(wpa_s->prev_gas_addr, wpa_s->last_gas_addr, ETH_ALEN); 3107 wpa_s->prev_gas_dialog_token = wpa_s->last_gas_dialog_token; 3108 wpa_s->last_gas_resp = n; 3109 os_memcpy(wpa_s->last_gas_addr, addr, ETH_ALEN); 3110 wpa_s->last_gas_dialog_token = dialog_token; 3111 } 3112 3113 3114 int gas_send_request(struct wpa_supplicant *wpa_s, const u8 *dst, 3115 const struct wpabuf *adv_proto, 3116 const struct wpabuf *query) 3117 { 3118 struct wpabuf *buf; 3119 int ret = 0; 3120 int freq; 3121 struct wpa_bss *bss; 3122 int res; 3123 size_t len; 3124 u8 query_resp_len_limit = 0; 3125 3126 freq = wpa_s->assoc_freq; 3127 bss = wpa_bss_get_bssid(wpa_s, dst); 3128 if (bss) 3129 freq = bss->freq; 3130 if (freq <= 0) 3131 return -1; 3132 3133 wpa_msg(wpa_s, MSG_DEBUG, "GAS request to " MACSTR " (freq %d MHz)", 3134 MAC2STR(dst), freq); 3135 wpa_hexdump_buf(MSG_DEBUG, "Advertisement Protocol ID", adv_proto); 3136 wpa_hexdump_buf(MSG_DEBUG, "GAS Query", query); 3137 3138 len = 3 + wpabuf_len(adv_proto) + 2; 3139 if (query) 3140 len += wpabuf_len(query); 3141 buf = gas_build_initial_req(0, len); 3142 if (buf == NULL) 3143 return -1; 3144 3145 /* Advertisement Protocol IE */ 3146 wpabuf_put_u8(buf, WLAN_EID_ADV_PROTO); 3147 wpabuf_put_u8(buf, 1 + wpabuf_len(adv_proto)); /* Length */ 3148 wpabuf_put_u8(buf, query_resp_len_limit & 0x7f); 3149 wpabuf_put_buf(buf, adv_proto); 3150 3151 /* GAS Query */ 3152 if (query) { 3153 wpabuf_put_le16(buf, wpabuf_len(query)); 3154 wpabuf_put_buf(buf, query); 3155 } else 3156 wpabuf_put_le16(buf, 0); 3157 3158 res = gas_query_req(wpa_s->gas, dst, freq, buf, gas_resp_cb, wpa_s); 3159 if (res < 0) { 3160 wpa_msg(wpa_s, MSG_DEBUG, "GAS: Failed to send Query Request"); 3161 wpabuf_free(buf); 3162 ret = -1; 3163 } else 3164 wpa_msg(wpa_s, MSG_DEBUG, 3165 "GAS: Query started with dialog token %u", res); 3166 3167 return ret; 3168 } 3169