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