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 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 (end - pos < 3) { 366 wpa_printf(MSG_DEBUG, "No room for EAP Method fixed fields"); 367 return NULL; 368 } 369 370 elen = *pos++; 371 if (elen > end - pos || 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 (end - pos < 2) { 385 wpa_printf(MSG_DEBUG, 386 "No room for Authentication Parameter subfield header"); 387 return NULL; 388 } 389 390 id = *pos++; 391 len = *pos++; 392 if (len > end - pos) { 393 wpa_printf(MSG_DEBUG, 394 "No room for Authentication Parameter subfield"); 395 return NULL; 396 } 397 398 switch (id) { 399 case NAI_REALM_EAP_AUTH_NON_EAP_INNER_AUTH: 400 if (len < 1) 401 break; 402 e->inner_non_eap = *pos; 403 if (e->method != EAP_TYPE_TTLS) 404 break; 405 switch (*pos) { 406 case NAI_REALM_INNER_NON_EAP_PAP: 407 wpa_printf(MSG_DEBUG, "EAP-TTLS/PAP"); 408 break; 409 case NAI_REALM_INNER_NON_EAP_CHAP: 410 wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP"); 411 break; 412 case NAI_REALM_INNER_NON_EAP_MSCHAP: 413 wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP"); 414 break; 415 case NAI_REALM_INNER_NON_EAP_MSCHAPV2: 416 wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2"); 417 break; 418 } 419 break; 420 case NAI_REALM_EAP_AUTH_INNER_AUTH_EAP_METHOD: 421 if (len < 1) 422 break; 423 e->inner_method = *pos; 424 wpa_printf(MSG_DEBUG, "Inner EAP method: %u", 425 e->inner_method); 426 break; 427 case NAI_REALM_EAP_AUTH_CRED_TYPE: 428 if (len < 1) 429 break; 430 e->cred_type = *pos; 431 wpa_printf(MSG_DEBUG, "Credential Type: %u", 432 e->cred_type); 433 break; 434 case NAI_REALM_EAP_AUTH_TUNNELED_CRED_TYPE: 435 if (len < 1) 436 break; 437 e->tunneled_cred_type = *pos; 438 wpa_printf(MSG_DEBUG, "Tunneled EAP Method Credential " 439 "Type: %u", e->tunneled_cred_type); 440 break; 441 default: 442 wpa_printf(MSG_DEBUG, "Unsupported Authentication " 443 "Parameter: id=%u len=%u", id, len); 444 wpa_hexdump(MSG_DEBUG, "Authentication Parameter " 445 "Value", pos, len); 446 break; 447 } 448 449 pos += len; 450 } 451 452 return e_end; 453 } 454 455 456 static const u8 * nai_realm_parse_realm(struct nai_realm *r, const u8 *pos, 457 const u8 *end) 458 { 459 u16 len; 460 const u8 *f_end; 461 u8 realm_len, e; 462 463 if (end - pos < 4) { 464 wpa_printf(MSG_DEBUG, "No room for NAI Realm Data " 465 "fixed fields"); 466 return NULL; 467 } 468 469 len = WPA_GET_LE16(pos); /* NAI Realm Data field Length */ 470 pos += 2; 471 if (len > end - pos || len < 3) { 472 wpa_printf(MSG_DEBUG, "No room for NAI Realm Data " 473 "(len=%u; left=%u)", 474 len, (unsigned int) (end - pos)); 475 return NULL; 476 } 477 f_end = pos + len; 478 479 r->encoding = *pos++; 480 realm_len = *pos++; 481 if (realm_len > f_end - pos) { 482 wpa_printf(MSG_DEBUG, "No room for NAI Realm " 483 "(len=%u; left=%u)", 484 realm_len, (unsigned int) (f_end - pos)); 485 return NULL; 486 } 487 wpa_hexdump_ascii(MSG_DEBUG, "NAI Realm", pos, realm_len); 488 r->realm = dup_binstr(pos, realm_len); 489 if (r->realm == NULL) 490 return NULL; 491 pos += realm_len; 492 493 if (f_end - pos < 1) { 494 wpa_printf(MSG_DEBUG, "No room for EAP Method Count"); 495 return NULL; 496 } 497 r->eap_count = *pos++; 498 wpa_printf(MSG_DEBUG, "EAP Count: %u", r->eap_count); 499 if (r->eap_count * 3 > f_end - pos) { 500 wpa_printf(MSG_DEBUG, "No room for EAP Methods"); 501 return NULL; 502 } 503 r->eap = os_calloc(r->eap_count, sizeof(struct nai_realm_eap)); 504 if (r->eap == NULL) 505 return NULL; 506 507 for (e = 0; e < r->eap_count; e++) { 508 pos = nai_realm_parse_eap(&r->eap[e], pos, f_end); 509 if (pos == NULL) 510 return NULL; 511 } 512 513 return f_end; 514 } 515 516 517 static struct nai_realm * nai_realm_parse(struct wpabuf *anqp, u16 *count) 518 { 519 struct nai_realm *realm; 520 const u8 *pos, *end; 521 u16 i, num; 522 size_t left; 523 524 if (anqp == NULL) 525 return NULL; 526 left = wpabuf_len(anqp); 527 if (left < 2) 528 return NULL; 529 530 pos = wpabuf_head_u8(anqp); 531 end = pos + left; 532 num = WPA_GET_LE16(pos); 533 wpa_printf(MSG_DEBUG, "NAI Realm Count: %u", num); 534 pos += 2; 535 left -= 2; 536 537 if (num > left / 5) { 538 wpa_printf(MSG_DEBUG, "Invalid NAI Realm Count %u - not " 539 "enough data (%u octets) for that many realms", 540 num, (unsigned int) left); 541 return NULL; 542 } 543 544 realm = os_calloc(num, sizeof(struct nai_realm)); 545 if (realm == NULL) 546 return NULL; 547 548 for (i = 0; i < num; i++) { 549 pos = nai_realm_parse_realm(&realm[i], pos, end); 550 if (pos == NULL) { 551 nai_realm_free(realm, num); 552 return NULL; 553 } 554 } 555 556 *count = num; 557 return realm; 558 } 559 560 561 static int nai_realm_match(struct nai_realm *realm, const char *home_realm) 562 { 563 char *tmp, *pos, *end; 564 int match = 0; 565 566 if (realm->realm == NULL || home_realm == NULL) 567 return 0; 568 569 if (os_strchr(realm->realm, ';') == NULL) 570 return os_strcasecmp(realm->realm, home_realm) == 0; 571 572 tmp = os_strdup(realm->realm); 573 if (tmp == NULL) 574 return 0; 575 576 pos = tmp; 577 while (*pos) { 578 end = os_strchr(pos, ';'); 579 if (end) 580 *end = '\0'; 581 if (os_strcasecmp(pos, home_realm) == 0) { 582 match = 1; 583 break; 584 } 585 if (end == NULL) 586 break; 587 pos = end + 1; 588 } 589 590 os_free(tmp); 591 592 return match; 593 } 594 595 596 static int nai_realm_cred_username(struct wpa_supplicant *wpa_s, 597 struct nai_realm_eap *eap) 598 { 599 if (eap_get_name(EAP_VENDOR_IETF, eap->method) == NULL) { 600 wpa_msg(wpa_s, MSG_DEBUG, 601 "nai-realm-cred-username: EAP method not supported: %d", 602 eap->method); 603 return 0; /* method not supported */ 604 } 605 606 if (eap->method != EAP_TYPE_TTLS && eap->method != EAP_TYPE_PEAP && 607 eap->method != EAP_TYPE_FAST) { 608 /* Only tunneled methods with username/password supported */ 609 wpa_msg(wpa_s, MSG_DEBUG, 610 "nai-realm-cred-username: Method: %d is not TTLS, PEAP, or FAST", 611 eap->method); 612 return 0; 613 } 614 615 if (eap->method == EAP_TYPE_PEAP || eap->method == EAP_TYPE_FAST) { 616 if (eap->inner_method && 617 eap_get_name(EAP_VENDOR_IETF, eap->inner_method) == NULL) { 618 wpa_msg(wpa_s, MSG_DEBUG, 619 "nai-realm-cred-username: PEAP/FAST: Inner method not supported: %d", 620 eap->inner_method); 621 return 0; 622 } 623 if (!eap->inner_method && 624 eap_get_name(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2) == NULL) { 625 wpa_msg(wpa_s, MSG_DEBUG, 626 "nai-realm-cred-username: MSCHAPv2 not supported"); 627 return 0; 628 } 629 } 630 631 if (eap->method == EAP_TYPE_TTLS) { 632 if (eap->inner_method == 0 && eap->inner_non_eap == 0) 633 return 1; /* Assume TTLS/MSCHAPv2 is used */ 634 if (eap->inner_method && 635 eap_get_name(EAP_VENDOR_IETF, eap->inner_method) == NULL) { 636 wpa_msg(wpa_s, MSG_DEBUG, 637 "nai-realm-cred-username: TTLS, but inner not supported: %d", 638 eap->inner_method); 639 return 0; 640 } 641 if (eap->inner_non_eap && 642 eap->inner_non_eap != NAI_REALM_INNER_NON_EAP_PAP && 643 eap->inner_non_eap != NAI_REALM_INNER_NON_EAP_CHAP && 644 eap->inner_non_eap != NAI_REALM_INNER_NON_EAP_MSCHAP && 645 eap->inner_non_eap != NAI_REALM_INNER_NON_EAP_MSCHAPV2) { 646 wpa_msg(wpa_s, MSG_DEBUG, 647 "nai-realm-cred-username: TTLS, inner-non-eap not supported: %d", 648 eap->inner_non_eap); 649 return 0; 650 } 651 } 652 653 if (eap->inner_method && 654 eap->inner_method != EAP_TYPE_GTC && 655 eap->inner_method != EAP_TYPE_MSCHAPV2) { 656 wpa_msg(wpa_s, MSG_DEBUG, 657 "nai-realm-cred-username: inner-method not GTC or MSCHAPv2: %d", 658 eap->inner_method); 659 return 0; 660 } 661 662 return 1; 663 } 664 665 666 static int nai_realm_cred_cert(struct wpa_supplicant *wpa_s, 667 struct nai_realm_eap *eap) 668 { 669 if (eap_get_name(EAP_VENDOR_IETF, eap->method) == NULL) { 670 wpa_msg(wpa_s, MSG_DEBUG, 671 "nai-realm-cred-cert: Method not supported: %d", 672 eap->method); 673 return 0; /* method not supported */ 674 } 675 676 if (eap->method != EAP_TYPE_TLS) { 677 /* Only EAP-TLS supported for credential authentication */ 678 wpa_msg(wpa_s, MSG_DEBUG, 679 "nai-realm-cred-cert: Method not TLS: %d", 680 eap->method); 681 return 0; 682 } 683 684 return 1; 685 } 686 687 688 static struct nai_realm_eap * nai_realm_find_eap(struct wpa_supplicant *wpa_s, 689 struct wpa_cred *cred, 690 struct nai_realm *realm) 691 { 692 u8 e; 693 694 if (cred->username == NULL || 695 cred->username[0] == '\0' || 696 ((cred->password == NULL || 697 cred->password[0] == '\0') && 698 (cred->private_key == NULL || 699 cred->private_key[0] == '\0'))) { 700 wpa_msg(wpa_s, MSG_DEBUG, 701 "nai-realm-find-eap: incomplete cred info: username: %s password: %s private_key: %s", 702 cred->username ? cred->username : "NULL", 703 cred->password ? cred->password : "NULL", 704 cred->private_key ? cred->private_key : "NULL"); 705 return NULL; 706 } 707 708 for (e = 0; e < realm->eap_count; e++) { 709 struct nai_realm_eap *eap = &realm->eap[e]; 710 if (cred->password && cred->password[0] && 711 nai_realm_cred_username(wpa_s, eap)) 712 return eap; 713 if (cred->private_key && cred->private_key[0] && 714 nai_realm_cred_cert(wpa_s, eap)) 715 return eap; 716 } 717 718 return NULL; 719 } 720 721 722 #ifdef INTERWORKING_3GPP 723 724 static int plmn_id_match(struct wpabuf *anqp, const char *imsi, int mnc_len) 725 { 726 u8 plmn[3], plmn2[3]; 727 const u8 *pos, *end; 728 u8 udhl; 729 730 /* 731 * See Annex A of 3GPP TS 24.234 v8.1.0 for description. The network 732 * operator is allowed to include only two digits of the MNC, so allow 733 * matches based on both two and three digit MNC assumptions. Since some 734 * SIM/USIM cards may not expose MNC length conveniently, we may be 735 * provided the default MNC length 3 here and as such, checking with MNC 736 * length 2 is justifiable even though 3GPP TS 24.234 does not mention 737 * that case. Anyway, MCC/MNC pair where both 2 and 3 digit MNC is used 738 * with otherwise matching values would not be good idea in general, so 739 * this should not result in selecting incorrect networks. 740 */ 741 /* Match with 3 digit MNC */ 742 plmn[0] = (imsi[0] - '0') | ((imsi[1] - '0') << 4); 743 plmn[1] = (imsi[2] - '0') | ((imsi[5] - '0') << 4); 744 plmn[2] = (imsi[3] - '0') | ((imsi[4] - '0') << 4); 745 /* Match with 2 digit MNC */ 746 plmn2[0] = (imsi[0] - '0') | ((imsi[1] - '0') << 4); 747 plmn2[1] = (imsi[2] - '0') | 0xf0; 748 plmn2[2] = (imsi[3] - '0') | ((imsi[4] - '0') << 4); 749 750 if (anqp == NULL) 751 return 0; 752 pos = wpabuf_head_u8(anqp); 753 end = pos + wpabuf_len(anqp); 754 if (end - pos < 2) 755 return 0; 756 if (*pos != 0) { 757 wpa_printf(MSG_DEBUG, "Unsupported GUD version 0x%x", *pos); 758 return 0; 759 } 760 pos++; 761 udhl = *pos++; 762 if (udhl > end - pos) { 763 wpa_printf(MSG_DEBUG, "Invalid UDHL"); 764 return 0; 765 } 766 end = pos + udhl; 767 768 wpa_printf(MSG_DEBUG, "Interworking: Matching against MCC/MNC alternatives: %02x:%02x:%02x or %02x:%02x:%02x (IMSI %s, MNC length %d)", 769 plmn[0], plmn[1], plmn[2], plmn2[0], plmn2[1], plmn2[2], 770 imsi, mnc_len); 771 772 while (end - pos >= 2) { 773 u8 iei, len; 774 const u8 *l_end; 775 iei = *pos++; 776 len = *pos++ & 0x7f; 777 if (len > end - pos) 778 break; 779 l_end = pos + len; 780 781 if (iei == 0 && len > 0) { 782 /* PLMN List */ 783 u8 num, i; 784 wpa_hexdump(MSG_DEBUG, "Interworking: PLMN List information element", 785 pos, len); 786 num = *pos++; 787 for (i = 0; i < num; i++) { 788 if (l_end - pos < 3) 789 break; 790 if (os_memcmp(pos, plmn, 3) == 0 || 791 os_memcmp(pos, plmn2, 3) == 0) 792 return 1; /* Found matching PLMN */ 793 pos += 3; 794 } 795 } else { 796 wpa_hexdump(MSG_DEBUG, "Interworking: Unrecognized 3GPP information element", 797 pos, len); 798 } 799 800 pos = l_end; 801 } 802 803 return 0; 804 } 805 806 807 static int build_root_nai(char *nai, size_t nai_len, const char *imsi, 808 size_t mnc_len, char prefix) 809 { 810 const char *sep, *msin; 811 char *end, *pos; 812 size_t msin_len, plmn_len; 813 814 /* 815 * TS 23.003, Clause 14 (3GPP to WLAN Interworking) 816 * Root NAI: 817 * <aka:0|sim:1><IMSI>@wlan.mnc<MNC>.mcc<MCC>.3gppnetwork.org 818 * <MNC> is zero-padded to three digits in case two-digit MNC is used 819 */ 820 821 if (imsi == NULL || os_strlen(imsi) > 16) { 822 wpa_printf(MSG_DEBUG, "No valid IMSI available"); 823 return -1; 824 } 825 sep = os_strchr(imsi, '-'); 826 if (sep) { 827 plmn_len = sep - imsi; 828 msin = sep + 1; 829 } else if (mnc_len && os_strlen(imsi) >= 3 + mnc_len) { 830 plmn_len = 3 + mnc_len; 831 msin = imsi + plmn_len; 832 } else 833 return -1; 834 if (plmn_len != 5 && plmn_len != 6) 835 return -1; 836 msin_len = os_strlen(msin); 837 838 pos = nai; 839 end = nai + nai_len; 840 if (prefix) 841 *pos++ = prefix; 842 os_memcpy(pos, imsi, plmn_len); 843 pos += plmn_len; 844 os_memcpy(pos, msin, msin_len); 845 pos += msin_len; 846 pos += os_snprintf(pos, end - pos, "@wlan.mnc"); 847 if (plmn_len == 5) { 848 *pos++ = '0'; 849 *pos++ = imsi[3]; 850 *pos++ = imsi[4]; 851 } else { 852 *pos++ = imsi[3]; 853 *pos++ = imsi[4]; 854 *pos++ = imsi[5]; 855 } 856 os_snprintf(pos, end - pos, ".mcc%c%c%c.3gppnetwork.org", 857 imsi[0], imsi[1], imsi[2]); 858 859 return 0; 860 } 861 862 863 static int set_root_nai(struct wpa_ssid *ssid, const char *imsi, char prefix) 864 { 865 char nai[100]; 866 if (build_root_nai(nai, sizeof(nai), imsi, 0, prefix) < 0) 867 return -1; 868 return wpa_config_set_quoted(ssid, "identity", nai); 869 } 870 871 #endif /* INTERWORKING_3GPP */ 872 873 874 static int already_connected(struct wpa_supplicant *wpa_s, 875 struct wpa_cred *cred, struct wpa_bss *bss) 876 { 877 struct wpa_ssid *ssid, *sel_ssid; 878 struct wpa_bss *selected; 879 880 if (wpa_s->wpa_state < WPA_ASSOCIATED || wpa_s->current_ssid == NULL) 881 return 0; 882 883 ssid = wpa_s->current_ssid; 884 if (ssid->parent_cred != cred) 885 return 0; 886 887 if (ssid->ssid_len != bss->ssid_len || 888 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) != 0) 889 return 0; 890 891 sel_ssid = NULL; 892 selected = wpa_supplicant_pick_network(wpa_s, &sel_ssid); 893 if (selected && sel_ssid && sel_ssid->priority > ssid->priority) 894 return 0; /* higher priority network in scan results */ 895 896 return 1; 897 } 898 899 900 static void remove_duplicate_network(struct wpa_supplicant *wpa_s, 901 struct wpa_cred *cred, 902 struct wpa_bss *bss) 903 { 904 struct wpa_ssid *ssid; 905 906 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { 907 if (ssid->parent_cred != cred) 908 continue; 909 if (ssid->ssid_len != bss->ssid_len || 910 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) != 0) 911 continue; 912 913 break; 914 } 915 916 if (ssid == NULL) 917 return; 918 919 wpa_printf(MSG_DEBUG, "Interworking: Remove duplicate network entry for the same credential"); 920 921 if (ssid == wpa_s->current_ssid) { 922 wpa_sm_set_config(wpa_s->wpa, NULL); 923 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); 924 wpa_s->own_disconnect_req = 1; 925 wpa_supplicant_deauthenticate(wpa_s, 926 WLAN_REASON_DEAUTH_LEAVING); 927 } 928 929 wpas_notify_network_removed(wpa_s, ssid); 930 wpa_config_remove_network(wpa_s->conf, ssid->id); 931 } 932 933 934 static int interworking_set_hs20_params(struct wpa_supplicant *wpa_s, 935 struct wpa_ssid *ssid) 936 { 937 const char *key_mgmt = NULL; 938 #ifdef CONFIG_IEEE80211R 939 int res; 940 struct wpa_driver_capa capa; 941 942 res = wpa_drv_get_capa(wpa_s, &capa); 943 if (res == 0 && capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT) { 944 key_mgmt = wpa_s->conf->pmf != NO_MGMT_FRAME_PROTECTION ? 945 "WPA-EAP WPA-EAP-SHA256 FT-EAP" : 946 "WPA-EAP FT-EAP"; 947 } 948 #endif /* CONFIG_IEEE80211R */ 949 950 if (!key_mgmt) 951 key_mgmt = wpa_s->conf->pmf != NO_MGMT_FRAME_PROTECTION ? 952 "WPA-EAP WPA-EAP-SHA256" : "WPA-EAP"; 953 if (wpa_config_set(ssid, "key_mgmt", key_mgmt, 0) < 0) 954 return -1; 955 if (wpa_config_set(ssid, "proto", "RSN", 0) < 0) 956 return -1; 957 if (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 static int interworking_connect_helper(struct wpa_supplicant *wpa_s, 1594 struct wpa_bss *bss, int allow_excluded, 1595 int only_add) 1596 { 1597 struct wpa_cred *cred, *cred_rc, *cred_3gpp; 1598 struct wpa_ssid *ssid; 1599 struct nai_realm *realm; 1600 struct nai_realm_eap *eap = NULL; 1601 u16 count, i; 1602 char buf[100]; 1603 int excluded = 0, *excl = allow_excluded ? &excluded : NULL; 1604 const char *name; 1605 1606 if (wpa_s->conf->cred == NULL || bss == NULL) 1607 return -1; 1608 if (disallowed_bssid(wpa_s, bss->bssid) || 1609 disallowed_ssid(wpa_s, bss->ssid, bss->ssid_len)) { 1610 wpa_msg(wpa_s, MSG_DEBUG, 1611 "Interworking: Reject connection to disallowed BSS " 1612 MACSTR, MAC2STR(bss->bssid)); 1613 return -1; 1614 } 1615 1616 wpa_printf(MSG_DEBUG, "Interworking: Considering BSS " MACSTR 1617 " for connection (allow_excluded=%d)", 1618 MAC2STR(bss->bssid), allow_excluded); 1619 1620 if (!wpa_bss_get_ie(bss, WLAN_EID_RSN)) { 1621 /* 1622 * We currently support only HS 2.0 networks and those are 1623 * required to use WPA2-Enterprise. 1624 */ 1625 wpa_msg(wpa_s, MSG_DEBUG, 1626 "Interworking: Network does not use RSN"); 1627 return -1; 1628 } 1629 1630 cred_rc = interworking_credentials_available_roaming_consortium( 1631 wpa_s, bss, 0, excl); 1632 if (cred_rc) { 1633 wpa_msg(wpa_s, MSG_DEBUG, 1634 "Interworking: Highest roaming consortium matching credential priority %d sp_priority %d", 1635 cred_rc->priority, cred_rc->sp_priority); 1636 if (allow_excluded && excl && !(*excl)) 1637 excl = NULL; 1638 } 1639 1640 cred = interworking_credentials_available_realm(wpa_s, bss, 0, excl); 1641 if (cred) { 1642 wpa_msg(wpa_s, MSG_DEBUG, 1643 "Interworking: Highest NAI Realm list matching credential priority %d sp_priority %d", 1644 cred->priority, cred->sp_priority); 1645 if (allow_excluded && excl && !(*excl)) 1646 excl = NULL; 1647 } 1648 1649 cred_3gpp = interworking_credentials_available_3gpp(wpa_s, bss, 0, 1650 excl); 1651 if (cred_3gpp) { 1652 wpa_msg(wpa_s, MSG_DEBUG, 1653 "Interworking: Highest 3GPP matching credential priority %d sp_priority %d", 1654 cred_3gpp->priority, cred_3gpp->sp_priority); 1655 if (allow_excluded && excl && !(*excl)) 1656 excl = NULL; 1657 } 1658 1659 if (!cred_rc && !cred && !cred_3gpp) { 1660 wpa_msg(wpa_s, MSG_DEBUG, 1661 "Interworking: No full credential matches - consider options without BW(etc.) limits"); 1662 cred_rc = interworking_credentials_available_roaming_consortium( 1663 wpa_s, bss, 1, excl); 1664 if (cred_rc) { 1665 wpa_msg(wpa_s, MSG_DEBUG, 1666 "Interworking: Highest roaming consortium matching credential priority %d sp_priority %d (ignore BW)", 1667 cred_rc->priority, cred_rc->sp_priority); 1668 if (allow_excluded && excl && !(*excl)) 1669 excl = NULL; 1670 } 1671 1672 cred = interworking_credentials_available_realm(wpa_s, bss, 1, 1673 excl); 1674 if (cred) { 1675 wpa_msg(wpa_s, MSG_DEBUG, 1676 "Interworking: Highest NAI Realm list matching credential priority %d sp_priority %d (ignore BW)", 1677 cred->priority, cred->sp_priority); 1678 if (allow_excluded && excl && !(*excl)) 1679 excl = NULL; 1680 } 1681 1682 cred_3gpp = interworking_credentials_available_3gpp(wpa_s, bss, 1683 1, excl); 1684 if (cred_3gpp) { 1685 wpa_msg(wpa_s, MSG_DEBUG, 1686 "Interworking: Highest 3GPP matching credential priority %d sp_priority %d (ignore BW)", 1687 cred_3gpp->priority, cred_3gpp->sp_priority); 1688 if (allow_excluded && excl && !(*excl)) 1689 excl = NULL; 1690 } 1691 } 1692 1693 if (cred_rc && 1694 (cred == NULL || cred_prio_cmp(cred_rc, cred) >= 0) && 1695 (cred_3gpp == NULL || cred_prio_cmp(cred_rc, cred_3gpp) >= 0)) 1696 return interworking_connect_roaming_consortium(wpa_s, cred_rc, 1697 bss, only_add); 1698 1699 if (cred_3gpp && 1700 (cred == NULL || cred_prio_cmp(cred_3gpp, cred) >= 0)) { 1701 return interworking_connect_3gpp(wpa_s, cred_3gpp, bss, 1702 only_add); 1703 } 1704 1705 if (cred == NULL) { 1706 wpa_msg(wpa_s, MSG_DEBUG, 1707 "Interworking: No matching credentials found for " 1708 MACSTR, MAC2STR(bss->bssid)); 1709 return -1; 1710 } 1711 1712 realm = nai_realm_parse(bss->anqp ? bss->anqp->nai_realm : NULL, 1713 &count); 1714 if (realm == NULL) { 1715 wpa_msg(wpa_s, MSG_DEBUG, 1716 "Interworking: Could not parse NAI Realm list from " 1717 MACSTR, MAC2STR(bss->bssid)); 1718 return -1; 1719 } 1720 1721 for (i = 0; i < count; i++) { 1722 if (!nai_realm_match(&realm[i], cred->realm)) 1723 continue; 1724 eap = nai_realm_find_eap(wpa_s, cred, &realm[i]); 1725 if (eap) 1726 break; 1727 } 1728 1729 if (!eap) { 1730 wpa_msg(wpa_s, MSG_DEBUG, 1731 "Interworking: No matching credentials and EAP method found for " 1732 MACSTR, MAC2STR(bss->bssid)); 1733 nai_realm_free(realm, count); 1734 return -1; 1735 } 1736 1737 wpa_msg(wpa_s, MSG_DEBUG, "Interworking: Connect with " MACSTR, 1738 MAC2STR(bss->bssid)); 1739 1740 if (already_connected(wpa_s, cred, bss)) { 1741 wpa_msg(wpa_s, MSG_INFO, INTERWORKING_ALREADY_CONNECTED MACSTR, 1742 MAC2STR(bss->bssid)); 1743 nai_realm_free(realm, count); 1744 return 0; 1745 } 1746 1747 remove_duplicate_network(wpa_s, cred, bss); 1748 1749 ssid = wpa_config_add_network(wpa_s->conf); 1750 if (ssid == NULL) { 1751 nai_realm_free(realm, count); 1752 return -1; 1753 } 1754 ssid->parent_cred = cred; 1755 wpas_notify_network_added(wpa_s, ssid); 1756 wpa_config_set_network_defaults(ssid); 1757 ssid->priority = cred->priority; 1758 ssid->temporary = 1; 1759 ssid->ssid = os_zalloc(bss->ssid_len + 1); 1760 if (ssid->ssid == NULL) 1761 goto fail; 1762 os_memcpy(ssid->ssid, bss->ssid, bss->ssid_len); 1763 ssid->ssid_len = bss->ssid_len; 1764 1765 if (interworking_set_hs20_params(wpa_s, ssid) < 0) 1766 goto fail; 1767 1768 if (wpa_config_set(ssid, "eap", eap_get_name(EAP_VENDOR_IETF, 1769 eap->method), 0) < 0) 1770 goto fail; 1771 1772 switch (eap->method) { 1773 case EAP_TYPE_TTLS: 1774 if (eap->inner_method) { 1775 os_snprintf(buf, sizeof(buf), "\"autheap=%s\"", 1776 eap_get_name(EAP_VENDOR_IETF, 1777 eap->inner_method)); 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 int interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, 1854 int only_add) 1855 { 1856 return interworking_connect_helper(wpa_s, bss, 1, only_add); 1857 } 1858 1859 1860 #ifdef PCSC_FUNCS 1861 static int interworking_pcsc_read_imsi(struct wpa_supplicant *wpa_s) 1862 { 1863 size_t len; 1864 1865 if (wpa_s->imsi[0] && wpa_s->mnc_len) 1866 return 0; 1867 1868 len = sizeof(wpa_s->imsi) - 1; 1869 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) { 1870 scard_deinit(wpa_s->scard); 1871 wpa_s->scard = NULL; 1872 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI"); 1873 return -1; 1874 } 1875 wpa_s->imsi[len] = '\0'; 1876 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard); 1877 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)", 1878 wpa_s->imsi, wpa_s->mnc_len); 1879 1880 return 0; 1881 } 1882 #endif /* PCSC_FUNCS */ 1883 1884 1885 static struct wpa_cred * interworking_credentials_available_3gpp( 1886 struct wpa_supplicant *wpa_s, struct wpa_bss *bss, int ignore_bw, 1887 int *excluded) 1888 { 1889 struct wpa_cred *selected = NULL; 1890 #ifdef INTERWORKING_3GPP 1891 struct wpa_cred *cred; 1892 int ret; 1893 int is_excluded = 0; 1894 1895 if (bss->anqp == NULL || bss->anqp->anqp_3gpp == NULL) { 1896 wpa_msg(wpa_s, MSG_DEBUG, 1897 "interworking-avail-3gpp: not avail, anqp: %p anqp_3gpp: %p", 1898 bss->anqp, bss->anqp ? bss->anqp->anqp_3gpp : NULL); 1899 return NULL; 1900 } 1901 1902 #ifdef CONFIG_EAP_PROXY 1903 if (!wpa_s->imsi[0]) { 1904 size_t len; 1905 wpa_msg(wpa_s, MSG_DEBUG, 1906 "Interworking: IMSI not available - try to read again through eap_proxy"); 1907 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, 1908 wpa_s->imsi, 1909 &len); 1910 if (wpa_s->mnc_len > 0) { 1911 wpa_s->imsi[len] = '\0'; 1912 wpa_msg(wpa_s, MSG_DEBUG, 1913 "eap_proxy: IMSI %s (MNC length %d)", 1914 wpa_s->imsi, wpa_s->mnc_len); 1915 } else { 1916 wpa_msg(wpa_s, MSG_DEBUG, 1917 "eap_proxy: IMSI not available"); 1918 } 1919 } 1920 #endif /* CONFIG_EAP_PROXY */ 1921 1922 for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 1923 char *sep; 1924 const char *imsi; 1925 int mnc_len; 1926 char imsi_buf[16]; 1927 size_t msin_len; 1928 1929 #ifdef PCSC_FUNCS 1930 if (cred->pcsc && wpa_s->scard) { 1931 if (interworking_pcsc_read_imsi(wpa_s) < 0) 1932 continue; 1933 imsi = wpa_s->imsi; 1934 mnc_len = wpa_s->mnc_len; 1935 goto compare; 1936 } 1937 #endif /* PCSC_FUNCS */ 1938 #ifdef CONFIG_EAP_PROXY 1939 if (cred->pcsc && wpa_s->mnc_len > 0 && wpa_s->imsi[0]) { 1940 imsi = wpa_s->imsi; 1941 mnc_len = wpa_s->mnc_len; 1942 goto compare; 1943 } 1944 #endif /* CONFIG_EAP_PROXY */ 1945 1946 if (cred->imsi == NULL || !cred->imsi[0] || 1947 (!wpa_s->conf->external_sim && 1948 (cred->milenage == NULL || !cred->milenage[0]))) 1949 continue; 1950 1951 sep = os_strchr(cred->imsi, '-'); 1952 if (sep == NULL || 1953 (sep - cred->imsi != 5 && sep - cred->imsi != 6)) 1954 continue; 1955 mnc_len = sep - cred->imsi - 3; 1956 os_memcpy(imsi_buf, cred->imsi, 3 + mnc_len); 1957 sep++; 1958 msin_len = os_strlen(cred->imsi); 1959 if (3 + mnc_len + msin_len >= sizeof(imsi_buf) - 1) 1960 msin_len = sizeof(imsi_buf) - 3 - mnc_len - 1; 1961 os_memcpy(&imsi_buf[3 + mnc_len], sep, msin_len); 1962 imsi_buf[3 + mnc_len + msin_len] = '\0'; 1963 imsi = imsi_buf; 1964 1965 #if defined(PCSC_FUNCS) || defined(CONFIG_EAP_PROXY) 1966 compare: 1967 #endif /* PCSC_FUNCS || CONFIG_EAP_PROXY */ 1968 wpa_msg(wpa_s, MSG_DEBUG, 1969 "Interworking: Parsing 3GPP info from " MACSTR, 1970 MAC2STR(bss->bssid)); 1971 ret = plmn_id_match(bss->anqp->anqp_3gpp, imsi, mnc_len); 1972 wpa_msg(wpa_s, MSG_DEBUG, "PLMN match %sfound", 1973 ret ? "" : "not "); 1974 if (ret) { 1975 if (cred_no_required_oi_match(cred, bss)) 1976 continue; 1977 if (!ignore_bw && 1978 cred_below_min_backhaul(wpa_s, cred, bss)) 1979 continue; 1980 if (!ignore_bw && 1981 cred_over_max_bss_load(wpa_s, cred, bss)) 1982 continue; 1983 if (!ignore_bw && 1984 cred_conn_capab_missing(wpa_s, cred, bss)) 1985 continue; 1986 if (cred_excluded_ssid(cred, bss)) { 1987 if (excluded == NULL) 1988 continue; 1989 if (selected == NULL) { 1990 selected = cred; 1991 is_excluded = 1; 1992 } 1993 } else { 1994 if (selected == NULL || is_excluded || 1995 cred_prio_cmp(selected, cred) < 0) { 1996 selected = cred; 1997 is_excluded = 0; 1998 } 1999 } 2000 } 2001 } 2002 2003 if (excluded) 2004 *excluded = is_excluded; 2005 #endif /* INTERWORKING_3GPP */ 2006 return selected; 2007 } 2008 2009 2010 static struct wpa_cred * interworking_credentials_available_realm( 2011 struct wpa_supplicant *wpa_s, struct wpa_bss *bss, int ignore_bw, 2012 int *excluded) 2013 { 2014 struct wpa_cred *cred, *selected = NULL; 2015 struct nai_realm *realm; 2016 u16 count, i; 2017 int is_excluded = 0; 2018 2019 if (bss->anqp == NULL || bss->anqp->nai_realm == NULL) 2020 return NULL; 2021 2022 if (wpa_s->conf->cred == NULL) 2023 return NULL; 2024 2025 wpa_msg(wpa_s, MSG_DEBUG, "Interworking: Parsing NAI Realm list from " 2026 MACSTR, MAC2STR(bss->bssid)); 2027 realm = nai_realm_parse(bss->anqp->nai_realm, &count); 2028 if (realm == NULL) { 2029 wpa_msg(wpa_s, MSG_DEBUG, 2030 "Interworking: Could not parse NAI Realm list from " 2031 MACSTR, MAC2STR(bss->bssid)); 2032 return NULL; 2033 } 2034 2035 for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 2036 if (cred->realm == NULL) 2037 continue; 2038 2039 for (i = 0; i < count; i++) { 2040 if (!nai_realm_match(&realm[i], cred->realm)) 2041 continue; 2042 if (nai_realm_find_eap(wpa_s, cred, &realm[i])) { 2043 if (cred_no_required_oi_match(cred, bss)) 2044 continue; 2045 if (!ignore_bw && 2046 cred_below_min_backhaul(wpa_s, cred, bss)) 2047 continue; 2048 if (!ignore_bw && 2049 cred_over_max_bss_load(wpa_s, cred, bss)) 2050 continue; 2051 if (!ignore_bw && 2052 cred_conn_capab_missing(wpa_s, cred, bss)) 2053 continue; 2054 if (cred_excluded_ssid(cred, bss)) { 2055 if (excluded == NULL) 2056 continue; 2057 if (selected == NULL) { 2058 selected = cred; 2059 is_excluded = 1; 2060 } 2061 } else { 2062 if (selected == NULL || is_excluded || 2063 cred_prio_cmp(selected, cred) < 0) 2064 { 2065 selected = cred; 2066 is_excluded = 0; 2067 } 2068 } 2069 break; 2070 } else { 2071 wpa_msg(wpa_s, MSG_DEBUG, 2072 "Interworking: realm-find-eap returned false"); 2073 } 2074 } 2075 } 2076 2077 nai_realm_free(realm, count); 2078 2079 if (excluded) 2080 *excluded = is_excluded; 2081 2082 return selected; 2083 } 2084 2085 2086 static struct wpa_cred * interworking_credentials_available_helper( 2087 struct wpa_supplicant *wpa_s, struct wpa_bss *bss, int ignore_bw, 2088 int *excluded) 2089 { 2090 struct wpa_cred *cred, *cred2; 2091 int excluded1, excluded2 = 0; 2092 2093 if (disallowed_bssid(wpa_s, bss->bssid) || 2094 disallowed_ssid(wpa_s, bss->ssid, bss->ssid_len)) { 2095 wpa_printf(MSG_DEBUG, "Interworking: Ignore disallowed BSS " 2096 MACSTR, MAC2STR(bss->bssid)); 2097 return NULL; 2098 } 2099 2100 cred = interworking_credentials_available_realm(wpa_s, bss, ignore_bw, 2101 &excluded1); 2102 cred2 = interworking_credentials_available_3gpp(wpa_s, bss, ignore_bw, 2103 &excluded2); 2104 if (cred && cred2 && 2105 (cred_prio_cmp(cred2, cred) >= 0 || (!excluded2 && excluded1))) { 2106 cred = cred2; 2107 excluded1 = excluded2; 2108 } 2109 if (!cred) { 2110 cred = cred2; 2111 excluded1 = excluded2; 2112 } 2113 2114 cred2 = interworking_credentials_available_roaming_consortium( 2115 wpa_s, bss, ignore_bw, &excluded2); 2116 if (cred && cred2 && 2117 (cred_prio_cmp(cred2, cred) >= 0 || (!excluded2 && excluded1))) { 2118 cred = cred2; 2119 excluded1 = excluded2; 2120 } 2121 if (!cred) { 2122 cred = cred2; 2123 excluded1 = excluded2; 2124 } 2125 2126 if (excluded) 2127 *excluded = excluded1; 2128 return cred; 2129 } 2130 2131 2132 static struct wpa_cred * interworking_credentials_available( 2133 struct wpa_supplicant *wpa_s, struct wpa_bss *bss, int *excluded) 2134 { 2135 struct wpa_cred *cred; 2136 2137 if (excluded) 2138 *excluded = 0; 2139 cred = interworking_credentials_available_helper(wpa_s, bss, 0, 2140 excluded); 2141 if (cred) 2142 return cred; 2143 return interworking_credentials_available_helper(wpa_s, bss, 1, 2144 excluded); 2145 } 2146 2147 2148 int domain_name_list_contains(struct wpabuf *domain_names, 2149 const char *domain, int exact_match) 2150 { 2151 const u8 *pos, *end; 2152 size_t len; 2153 2154 len = os_strlen(domain); 2155 pos = wpabuf_head(domain_names); 2156 end = pos + wpabuf_len(domain_names); 2157 2158 while (end - pos > 1) { 2159 u8 elen; 2160 2161 elen = *pos++; 2162 if (elen > end - pos) 2163 break; 2164 2165 wpa_hexdump_ascii(MSG_DEBUG, "Interworking: AP domain name", 2166 pos, elen); 2167 if (elen == len && 2168 os_strncasecmp(domain, (const char *) pos, len) == 0) 2169 return 1; 2170 if (!exact_match && elen > len && pos[elen - len - 1] == '.') { 2171 const char *ap = (const char *) pos; 2172 int offset = elen - len; 2173 2174 if (os_strncasecmp(domain, ap + offset, len) == 0) 2175 return 1; 2176 } 2177 2178 pos += elen; 2179 } 2180 2181 return 0; 2182 } 2183 2184 2185 int interworking_home_sp_cred(struct wpa_supplicant *wpa_s, 2186 struct wpa_cred *cred, 2187 struct wpabuf *domain_names) 2188 { 2189 size_t i; 2190 int ret = -1; 2191 #ifdef INTERWORKING_3GPP 2192 char nai[100], *realm; 2193 2194 char *imsi = NULL; 2195 int mnc_len = 0; 2196 if (cred->imsi) 2197 imsi = cred->imsi; 2198 #ifdef PCSC_FUNCS 2199 else if (cred->pcsc && wpa_s->scard) { 2200 if (interworking_pcsc_read_imsi(wpa_s) < 0) 2201 return -1; 2202 imsi = wpa_s->imsi; 2203 mnc_len = wpa_s->mnc_len; 2204 } 2205 #endif /* PCSC_FUNCS */ 2206 #ifdef CONFIG_EAP_PROXY 2207 else if (cred->pcsc && wpa_s->mnc_len > 0 && wpa_s->imsi[0]) { 2208 imsi = wpa_s->imsi; 2209 mnc_len = wpa_s->mnc_len; 2210 } 2211 #endif /* CONFIG_EAP_PROXY */ 2212 if (domain_names && 2213 imsi && build_root_nai(nai, sizeof(nai), imsi, mnc_len, 0) == 0) { 2214 realm = os_strchr(nai, '@'); 2215 if (realm) 2216 realm++; 2217 wpa_msg(wpa_s, MSG_DEBUG, 2218 "Interworking: Search for match with SIM/USIM domain %s", 2219 realm); 2220 if (realm && 2221 domain_name_list_contains(domain_names, realm, 1)) 2222 return 1; 2223 if (realm) 2224 ret = 0; 2225 } 2226 #endif /* INTERWORKING_3GPP */ 2227 2228 if (domain_names == NULL || cred->domain == NULL) 2229 return ret; 2230 2231 for (i = 0; i < cred->num_domain; i++) { 2232 wpa_msg(wpa_s, MSG_DEBUG, 2233 "Interworking: Search for match with home SP FQDN %s", 2234 cred->domain[i]); 2235 if (domain_name_list_contains(domain_names, cred->domain[i], 1)) 2236 return 1; 2237 } 2238 2239 return 0; 2240 } 2241 2242 2243 static int interworking_home_sp(struct wpa_supplicant *wpa_s, 2244 struct wpabuf *domain_names) 2245 { 2246 struct wpa_cred *cred; 2247 2248 if (domain_names == NULL || wpa_s->conf->cred == NULL) 2249 return -1; 2250 2251 for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 2252 int res = interworking_home_sp_cred(wpa_s, cred, domain_names); 2253 if (res) 2254 return res; 2255 } 2256 2257 return 0; 2258 } 2259 2260 2261 static int interworking_find_network_match(struct wpa_supplicant *wpa_s) 2262 { 2263 struct wpa_bss *bss; 2264 struct wpa_ssid *ssid; 2265 2266 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { 2267 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { 2268 if (wpas_network_disabled(wpa_s, ssid) || 2269 ssid->mode != WPAS_MODE_INFRA) 2270 continue; 2271 if (ssid->ssid_len != bss->ssid_len || 2272 os_memcmp(ssid->ssid, bss->ssid, ssid->ssid_len) != 2273 0) 2274 continue; 2275 /* 2276 * TODO: Consider more accurate matching of security 2277 * configuration similarly to what is done in events.c 2278 */ 2279 return 1; 2280 } 2281 } 2282 2283 return 0; 2284 } 2285 2286 2287 static int roaming_partner_match(struct wpa_supplicant *wpa_s, 2288 struct roaming_partner *partner, 2289 struct wpabuf *domain_names) 2290 { 2291 wpa_printf(MSG_DEBUG, "Interworking: Comparing roaming_partner info fqdn='%s' exact_match=%d priority=%u country='%s'", 2292 partner->fqdn, partner->exact_match, partner->priority, 2293 partner->country); 2294 wpa_hexdump_ascii(MSG_DEBUG, "Interworking: Domain names", 2295 wpabuf_head(domain_names), 2296 wpabuf_len(domain_names)); 2297 if (!domain_name_list_contains(domain_names, partner->fqdn, 2298 partner->exact_match)) 2299 return 0; 2300 /* TODO: match Country */ 2301 return 1; 2302 } 2303 2304 2305 static u8 roaming_prio(struct wpa_supplicant *wpa_s, struct wpa_cred *cred, 2306 struct wpa_bss *bss) 2307 { 2308 size_t i; 2309 2310 if (bss->anqp == NULL || bss->anqp->domain_name == NULL) { 2311 wpa_printf(MSG_DEBUG, "Interworking: No ANQP domain name info -> use default roaming partner priority 128"); 2312 return 128; /* cannot check preference with domain name */ 2313 } 2314 2315 if (interworking_home_sp_cred(wpa_s, cred, bss->anqp->domain_name) > 0) 2316 { 2317 wpa_printf(MSG_DEBUG, "Interworking: Determined to be home SP -> use maximum preference 0 as roaming partner priority"); 2318 return 0; /* max preference for home SP network */ 2319 } 2320 2321 for (i = 0; i < cred->num_roaming_partner; i++) { 2322 if (roaming_partner_match(wpa_s, &cred->roaming_partner[i], 2323 bss->anqp->domain_name)) { 2324 wpa_printf(MSG_DEBUG, "Interworking: Roaming partner preference match - priority %u", 2325 cred->roaming_partner[i].priority); 2326 return cred->roaming_partner[i].priority; 2327 } 2328 } 2329 2330 wpa_printf(MSG_DEBUG, "Interworking: No roaming partner preference match - use default roaming partner priority 128"); 2331 return 128; 2332 } 2333 2334 2335 static struct wpa_bss * pick_best_roaming_partner(struct wpa_supplicant *wpa_s, 2336 struct wpa_bss *selected, 2337 struct wpa_cred *cred) 2338 { 2339 struct wpa_bss *bss; 2340 u8 best_prio, prio; 2341 struct wpa_cred *cred2; 2342 2343 /* 2344 * Check if any other BSS is operated by a more preferred roaming 2345 * partner. 2346 */ 2347 2348 best_prio = roaming_prio(wpa_s, cred, selected); 2349 wpa_printf(MSG_DEBUG, "Interworking: roaming_prio=%u for selected BSS " 2350 MACSTR " (cred=%d)", best_prio, MAC2STR(selected->bssid), 2351 cred->id); 2352 2353 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { 2354 if (bss == selected) 2355 continue; 2356 cred2 = interworking_credentials_available(wpa_s, bss, NULL); 2357 if (!cred2) 2358 continue; 2359 if (!wpa_bss_get_ie(bss, WLAN_EID_RSN)) 2360 continue; 2361 prio = roaming_prio(wpa_s, cred2, bss); 2362 wpa_printf(MSG_DEBUG, "Interworking: roaming_prio=%u for BSS " 2363 MACSTR " (cred=%d)", prio, MAC2STR(bss->bssid), 2364 cred2->id); 2365 if (prio < best_prio) { 2366 int bh1, bh2, load1, load2, conn1, conn2; 2367 bh1 = cred_below_min_backhaul(wpa_s, cred, selected); 2368 load1 = cred_over_max_bss_load(wpa_s, cred, selected); 2369 conn1 = cred_conn_capab_missing(wpa_s, cred, selected); 2370 bh2 = cred_below_min_backhaul(wpa_s, cred2, bss); 2371 load2 = cred_over_max_bss_load(wpa_s, cred2, bss); 2372 conn2 = cred_conn_capab_missing(wpa_s, cred2, bss); 2373 wpa_printf(MSG_DEBUG, "Interworking: old: %d %d %d new: %d %d %d", 2374 bh1, load1, conn1, bh2, load2, conn2); 2375 if (bh1 || load1 || conn1 || !(bh2 || load2 || conn2)) { 2376 wpa_printf(MSG_DEBUG, "Interworking: Better roaming partner " MACSTR " selected", MAC2STR(bss->bssid)); 2377 best_prio = prio; 2378 selected = bss; 2379 } 2380 } 2381 } 2382 2383 return selected; 2384 } 2385 2386 2387 static void interworking_select_network(struct wpa_supplicant *wpa_s) 2388 { 2389 struct wpa_bss *bss, *selected = NULL, *selected_home = NULL; 2390 struct wpa_bss *selected2 = NULL, *selected2_home = NULL; 2391 unsigned int count = 0; 2392 const char *type; 2393 int res; 2394 struct wpa_cred *cred, *selected_cred = NULL; 2395 struct wpa_cred *selected_home_cred = NULL; 2396 struct wpa_cred *selected2_cred = NULL; 2397 struct wpa_cred *selected2_home_cred = NULL; 2398 2399 wpa_s->network_select = 0; 2400 2401 wpa_printf(MSG_DEBUG, "Interworking: Select network (auto_select=%d)", 2402 wpa_s->auto_select); 2403 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { 2404 int excluded = 0; 2405 int bh, bss_load, conn_capab; 2406 cred = interworking_credentials_available(wpa_s, bss, 2407 &excluded); 2408 if (!cred) 2409 continue; 2410 2411 if (!wpa_bss_get_ie(bss, WLAN_EID_RSN)) { 2412 /* 2413 * We currently support only HS 2.0 networks and those 2414 * are required to use WPA2-Enterprise. 2415 */ 2416 wpa_msg(wpa_s, MSG_DEBUG, 2417 "Interworking: Credential match with " MACSTR 2418 " but network does not use RSN", 2419 MAC2STR(bss->bssid)); 2420 continue; 2421 } 2422 if (!excluded) 2423 count++; 2424 res = interworking_home_sp(wpa_s, bss->anqp ? 2425 bss->anqp->domain_name : NULL); 2426 if (res > 0) 2427 type = "home"; 2428 else if (res == 0) 2429 type = "roaming"; 2430 else 2431 type = "unknown"; 2432 bh = cred_below_min_backhaul(wpa_s, cred, bss); 2433 bss_load = cred_over_max_bss_load(wpa_s, cred, bss); 2434 conn_capab = cred_conn_capab_missing(wpa_s, cred, bss); 2435 wpa_msg(wpa_s, MSG_INFO, "%s" MACSTR " type=%s%s%s%s id=%d priority=%d sp_priority=%d", 2436 excluded ? INTERWORKING_BLACKLISTED : INTERWORKING_AP, 2437 MAC2STR(bss->bssid), type, 2438 bh ? " below_min_backhaul=1" : "", 2439 bss_load ? " over_max_bss_load=1" : "", 2440 conn_capab ? " conn_capab_missing=1" : "", 2441 cred->id, cred->priority, cred->sp_priority); 2442 if (excluded) 2443 continue; 2444 if (wpa_s->auto_select || 2445 (wpa_s->conf->auto_interworking && 2446 wpa_s->auto_network_select)) { 2447 if (bh || bss_load || conn_capab) { 2448 if (selected2_cred == NULL || 2449 cred_prio_cmp(cred, selected2_cred) > 0) { 2450 wpa_printf(MSG_DEBUG, "Interworking: Mark as selected2"); 2451 selected2 = bss; 2452 selected2_cred = cred; 2453 } 2454 if (res > 0 && 2455 (selected2_home_cred == NULL || 2456 cred_prio_cmp(cred, selected2_home_cred) > 2457 0)) { 2458 wpa_printf(MSG_DEBUG, "Interworking: Mark as selected2_home"); 2459 selected2_home = bss; 2460 selected2_home_cred = cred; 2461 } 2462 } else { 2463 if (selected_cred == NULL || 2464 cred_prio_cmp(cred, selected_cred) > 0) { 2465 wpa_printf(MSG_DEBUG, "Interworking: Mark as selected"); 2466 selected = bss; 2467 selected_cred = cred; 2468 } 2469 if (res > 0 && 2470 (selected_home_cred == NULL || 2471 cred_prio_cmp(cred, selected_home_cred) > 2472 0)) { 2473 wpa_printf(MSG_DEBUG, "Interworking: Mark as selected_home"); 2474 selected_home = bss; 2475 selected_home_cred = cred; 2476 } 2477 } 2478 } 2479 } 2480 2481 if (selected_home && selected_home != selected && 2482 selected_home_cred && 2483 (selected_cred == NULL || 2484 cred_prio_cmp(selected_home_cred, selected_cred) >= 0)) { 2485 /* Prefer network operated by the Home SP */ 2486 wpa_printf(MSG_DEBUG, "Interworking: Overrided selected with selected_home"); 2487 selected = selected_home; 2488 selected_cred = selected_home_cred; 2489 } 2490 2491 if (!selected) { 2492 if (selected2_home) { 2493 wpa_printf(MSG_DEBUG, "Interworking: Use home BSS with BW limit mismatch since no other network could be selected"); 2494 selected = selected2_home; 2495 selected_cred = selected2_home_cred; 2496 } else if (selected2) { 2497 wpa_printf(MSG_DEBUG, "Interworking: Use visited BSS with BW limit mismatch since no other network could be selected"); 2498 selected = selected2; 2499 selected_cred = selected2_cred; 2500 } 2501 } 2502 2503 if (count == 0) { 2504 /* 2505 * No matching network was found based on configured 2506 * credentials. Check whether any of the enabled network blocks 2507 * have matching APs. 2508 */ 2509 if (interworking_find_network_match(wpa_s)) { 2510 wpa_msg(wpa_s, MSG_DEBUG, 2511 "Interworking: Possible BSS match for enabled network configurations"); 2512 if (wpa_s->auto_select) { 2513 interworking_reconnect(wpa_s); 2514 return; 2515 } 2516 } 2517 2518 if (wpa_s->auto_network_select) { 2519 wpa_msg(wpa_s, MSG_DEBUG, 2520 "Interworking: Continue scanning after ANQP fetch"); 2521 wpa_supplicant_req_scan(wpa_s, wpa_s->scan_interval, 2522 0); 2523 return; 2524 } 2525 2526 wpa_msg(wpa_s, MSG_INFO, INTERWORKING_NO_MATCH "No network " 2527 "with matching credentials found"); 2528 if (wpa_s->wpa_state == WPA_SCANNING) 2529 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); 2530 } 2531 2532 if (selected) { 2533 wpa_printf(MSG_DEBUG, "Interworking: Selected " MACSTR, 2534 MAC2STR(selected->bssid)); 2535 selected = pick_best_roaming_partner(wpa_s, selected, 2536 selected_cred); 2537 wpa_printf(MSG_DEBUG, "Interworking: Selected " MACSTR 2538 " (after best roaming partner selection)", 2539 MAC2STR(selected->bssid)); 2540 wpa_msg(wpa_s, MSG_INFO, INTERWORKING_SELECTED MACSTR, 2541 MAC2STR(selected->bssid)); 2542 interworking_connect(wpa_s, selected, 0); 2543 } 2544 } 2545 2546 2547 static struct wpa_bss_anqp * 2548 interworking_match_anqp_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss) 2549 { 2550 struct wpa_bss *other; 2551 2552 if (is_zero_ether_addr(bss->hessid)) 2553 return NULL; /* Cannot be in the same homegenous ESS */ 2554 2555 dl_list_for_each(other, &wpa_s->bss, struct wpa_bss, list) { 2556 if (other == bss) 2557 continue; 2558 if (other->anqp == NULL) 2559 continue; 2560 if (other->anqp->roaming_consortium == NULL && 2561 other->anqp->nai_realm == NULL && 2562 other->anqp->anqp_3gpp == NULL && 2563 other->anqp->domain_name == NULL) 2564 continue; 2565 if (!(other->flags & WPA_BSS_ANQP_FETCH_TRIED)) 2566 continue; 2567 if (os_memcmp(bss->hessid, other->hessid, ETH_ALEN) != 0) 2568 continue; 2569 if (bss->ssid_len != other->ssid_len || 2570 os_memcmp(bss->ssid, other->ssid, bss->ssid_len) != 0) 2571 continue; 2572 2573 wpa_msg(wpa_s, MSG_DEBUG, 2574 "Interworking: Share ANQP data with already fetched BSSID " 2575 MACSTR " and " MACSTR, 2576 MAC2STR(other->bssid), MAC2STR(bss->bssid)); 2577 other->anqp->users++; 2578 return other->anqp; 2579 } 2580 2581 return NULL; 2582 } 2583 2584 2585 static void interworking_next_anqp_fetch(struct wpa_supplicant *wpa_s) 2586 { 2587 struct wpa_bss *bss; 2588 int found = 0; 2589 const u8 *ie; 2590 2591 wpa_printf(MSG_DEBUG, "Interworking: next_anqp_fetch - " 2592 "fetch_anqp_in_progress=%d fetch_osu_icon_in_progress=%d", 2593 wpa_s->fetch_anqp_in_progress, 2594 wpa_s->fetch_osu_icon_in_progress); 2595 2596 if (eloop_terminated() || !wpa_s->fetch_anqp_in_progress) { 2597 wpa_printf(MSG_DEBUG, "Interworking: Stop next-ANQP-fetch"); 2598 return; 2599 } 2600 2601 #ifdef CONFIG_HS20 2602 if (wpa_s->fetch_osu_icon_in_progress) { 2603 wpa_printf(MSG_DEBUG, "Interworking: Next icon (in progress)"); 2604 hs20_next_osu_icon(wpa_s); 2605 return; 2606 } 2607 #endif /* CONFIG_HS20 */ 2608 2609 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { 2610 if (!(bss->caps & IEEE80211_CAP_ESS)) 2611 continue; 2612 ie = wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB); 2613 if (ie == NULL || ie[1] < 4 || !(ie[5] & 0x80)) 2614 continue; /* AP does not support Interworking */ 2615 if (disallowed_bssid(wpa_s, bss->bssid) || 2616 disallowed_ssid(wpa_s, bss->ssid, bss->ssid_len)) 2617 continue; /* Disallowed BSS */ 2618 2619 if (!(bss->flags & WPA_BSS_ANQP_FETCH_TRIED)) { 2620 if (bss->anqp == NULL) { 2621 bss->anqp = interworking_match_anqp_info(wpa_s, 2622 bss); 2623 if (bss->anqp) { 2624 /* Shared data already fetched */ 2625 continue; 2626 } 2627 bss->anqp = wpa_bss_anqp_alloc(); 2628 if (bss->anqp == NULL) 2629 break; 2630 } 2631 found++; 2632 bss->flags |= WPA_BSS_ANQP_FETCH_TRIED; 2633 wpa_msg(wpa_s, MSG_INFO, "Starting ANQP fetch for " 2634 MACSTR, MAC2STR(bss->bssid)); 2635 interworking_anqp_send_req(wpa_s, bss); 2636 break; 2637 } 2638 } 2639 2640 if (found == 0) { 2641 #ifdef CONFIG_HS20 2642 if (wpa_s->fetch_osu_info) { 2643 if (wpa_s->num_prov_found == 0 && 2644 wpa_s->fetch_osu_waiting_scan && 2645 wpa_s->num_osu_scans < 3) { 2646 wpa_printf(MSG_DEBUG, "HS 2.0: No OSU providers seen - try to scan again"); 2647 hs20_start_osu_scan(wpa_s); 2648 return; 2649 } 2650 wpa_printf(MSG_DEBUG, "Interworking: Next icon"); 2651 hs20_osu_icon_fetch(wpa_s); 2652 return; 2653 } 2654 #endif /* CONFIG_HS20 */ 2655 wpa_msg(wpa_s, MSG_INFO, "ANQP fetch completed"); 2656 wpa_s->fetch_anqp_in_progress = 0; 2657 if (wpa_s->network_select) 2658 interworking_select_network(wpa_s); 2659 } 2660 } 2661 2662 2663 void interworking_start_fetch_anqp(struct wpa_supplicant *wpa_s) 2664 { 2665 struct wpa_bss *bss; 2666 2667 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) 2668 bss->flags &= ~WPA_BSS_ANQP_FETCH_TRIED; 2669 2670 wpa_s->fetch_anqp_in_progress = 1; 2671 2672 /* 2673 * Start actual ANQP operation from eloop call to make sure the loop 2674 * does not end up using excessive recursion. 2675 */ 2676 eloop_register_timeout(0, 0, interworking_continue_anqp, wpa_s, NULL); 2677 } 2678 2679 2680 int interworking_fetch_anqp(struct wpa_supplicant *wpa_s) 2681 { 2682 if (wpa_s->fetch_anqp_in_progress || wpa_s->network_select) 2683 return 0; 2684 2685 wpa_s->network_select = 0; 2686 wpa_s->fetch_all_anqp = 1; 2687 wpa_s->fetch_osu_info = 0; 2688 2689 interworking_start_fetch_anqp(wpa_s); 2690 2691 return 0; 2692 } 2693 2694 2695 void interworking_stop_fetch_anqp(struct wpa_supplicant *wpa_s) 2696 { 2697 if (!wpa_s->fetch_anqp_in_progress) 2698 return; 2699 2700 wpa_s->fetch_anqp_in_progress = 0; 2701 } 2702 2703 2704 int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, 2705 u16 info_ids[], size_t num_ids, u32 subtypes) 2706 { 2707 struct wpabuf *buf; 2708 struct wpabuf *hs20_buf = NULL; 2709 int ret = 0; 2710 int freq; 2711 struct wpa_bss *bss; 2712 int res; 2713 2714 bss = wpa_bss_get_bssid(wpa_s, dst); 2715 if (!bss) { 2716 wpa_printf(MSG_WARNING, 2717 "ANQP: Cannot send query to unknown BSS " 2718 MACSTR, MAC2STR(dst)); 2719 return -1; 2720 } 2721 2722 wpa_bss_anqp_unshare_alloc(bss); 2723 freq = bss->freq; 2724 2725 wpa_msg(wpa_s, MSG_DEBUG, 2726 "ANQP: Query Request to " MACSTR " for %u id(s)", 2727 MAC2STR(dst), (unsigned int) num_ids); 2728 2729 #ifdef CONFIG_HS20 2730 if (subtypes != 0) { 2731 hs20_buf = wpabuf_alloc(100); 2732 if (hs20_buf == NULL) 2733 return -1; 2734 hs20_put_anqp_req(subtypes, NULL, 0, hs20_buf); 2735 } 2736 #endif /* CONFIG_HS20 */ 2737 2738 buf = anqp_build_req(info_ids, num_ids, hs20_buf); 2739 wpabuf_free(hs20_buf); 2740 if (buf == NULL) 2741 return -1; 2742 2743 res = gas_query_req(wpa_s->gas, dst, freq, buf, anqp_resp_cb, wpa_s); 2744 if (res < 0) { 2745 wpa_msg(wpa_s, MSG_DEBUG, "ANQP: Failed to send Query Request"); 2746 wpabuf_free(buf); 2747 ret = -1; 2748 } else { 2749 wpa_msg(wpa_s, MSG_DEBUG, 2750 "ANQP: Query started with dialog token %u", res); 2751 } 2752 2753 return ret; 2754 } 2755 2756 2757 static void anqp_add_extra(struct wpa_supplicant *wpa_s, 2758 struct wpa_bss_anqp *anqp, u16 info_id, 2759 const u8 *data, size_t slen) 2760 { 2761 struct wpa_bss_anqp_elem *tmp, *elem = NULL; 2762 2763 if (!anqp) 2764 return; 2765 2766 dl_list_for_each(tmp, &anqp->anqp_elems, struct wpa_bss_anqp_elem, 2767 list) { 2768 if (tmp->infoid == info_id) { 2769 elem = tmp; 2770 break; 2771 } 2772 } 2773 2774 if (!elem) { 2775 elem = os_zalloc(sizeof(*elem)); 2776 if (!elem) 2777 return; 2778 elem->infoid = info_id; 2779 dl_list_add(&anqp->anqp_elems, &elem->list); 2780 } else { 2781 wpabuf_free(elem->payload); 2782 } 2783 2784 elem->payload = wpabuf_alloc_copy(data, slen); 2785 if (!elem->payload) { 2786 dl_list_del(&elem->list); 2787 os_free(elem); 2788 } 2789 } 2790 2791 2792 static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s, 2793 struct wpa_bss *bss, const u8 *sa, 2794 u16 info_id, 2795 const u8 *data, size_t slen, 2796 u8 dialog_token) 2797 { 2798 const u8 *pos = data; 2799 struct wpa_bss_anqp *anqp = NULL; 2800 #ifdef CONFIG_HS20 2801 u8 type; 2802 #endif /* CONFIG_HS20 */ 2803 2804 if (bss) 2805 anqp = bss->anqp; 2806 2807 switch (info_id) { 2808 case ANQP_CAPABILITY_LIST: 2809 wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR 2810 " ANQP Capability list", MAC2STR(sa)); 2811 wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Capability list", 2812 pos, slen); 2813 if (anqp) { 2814 wpabuf_free(anqp->capability_list); 2815 anqp->capability_list = wpabuf_alloc_copy(pos, slen); 2816 } 2817 break; 2818 case ANQP_VENUE_NAME: 2819 wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR 2820 " Venue Name", MAC2STR(sa)); 2821 wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Venue Name", pos, slen); 2822 if (anqp) { 2823 wpabuf_free(anqp->venue_name); 2824 anqp->venue_name = wpabuf_alloc_copy(pos, slen); 2825 } 2826 break; 2827 case ANQP_NETWORK_AUTH_TYPE: 2828 wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR 2829 " Network Authentication Type information", 2830 MAC2STR(sa)); 2831 wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Network Authentication " 2832 "Type", pos, slen); 2833 if (anqp) { 2834 wpabuf_free(anqp->network_auth_type); 2835 anqp->network_auth_type = wpabuf_alloc_copy(pos, slen); 2836 } 2837 break; 2838 case ANQP_ROAMING_CONSORTIUM: 2839 wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR 2840 " Roaming Consortium list", MAC2STR(sa)); 2841 wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Roaming Consortium", 2842 pos, slen); 2843 if (anqp) { 2844 wpabuf_free(anqp->roaming_consortium); 2845 anqp->roaming_consortium = wpabuf_alloc_copy(pos, slen); 2846 } 2847 break; 2848 case ANQP_IP_ADDR_TYPE_AVAILABILITY: 2849 wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR 2850 " IP Address Type Availability information", 2851 MAC2STR(sa)); 2852 wpa_hexdump(MSG_MSGDUMP, "ANQP: IP Address Availability", 2853 pos, slen); 2854 if (anqp) { 2855 wpabuf_free(anqp->ip_addr_type_availability); 2856 anqp->ip_addr_type_availability = 2857 wpabuf_alloc_copy(pos, slen); 2858 } 2859 break; 2860 case ANQP_NAI_REALM: 2861 wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR 2862 " NAI Realm list", MAC2STR(sa)); 2863 wpa_hexdump_ascii(MSG_DEBUG, "ANQP: NAI Realm", pos, slen); 2864 if (anqp) { 2865 wpabuf_free(anqp->nai_realm); 2866 anqp->nai_realm = wpabuf_alloc_copy(pos, slen); 2867 } 2868 break; 2869 case ANQP_3GPP_CELLULAR_NETWORK: 2870 wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR 2871 " 3GPP Cellular Network information", MAC2STR(sa)); 2872 wpa_hexdump_ascii(MSG_DEBUG, "ANQP: 3GPP Cellular Network", 2873 pos, slen); 2874 if (anqp) { 2875 wpabuf_free(anqp->anqp_3gpp); 2876 anqp->anqp_3gpp = wpabuf_alloc_copy(pos, slen); 2877 } 2878 break; 2879 case ANQP_DOMAIN_NAME: 2880 wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR 2881 " Domain Name list", MAC2STR(sa)); 2882 wpa_hexdump_ascii(MSG_MSGDUMP, "ANQP: Domain Name", pos, slen); 2883 if (anqp) { 2884 wpabuf_free(anqp->domain_name); 2885 anqp->domain_name = wpabuf_alloc_copy(pos, slen); 2886 } 2887 break; 2888 case ANQP_VENDOR_SPECIFIC: 2889 if (slen < 3) 2890 return; 2891 2892 switch (WPA_GET_BE24(pos)) { 2893 #ifdef CONFIG_HS20 2894 case OUI_WFA: 2895 pos += 3; 2896 slen -= 3; 2897 2898 if (slen < 1) 2899 return; 2900 type = *pos++; 2901 slen--; 2902 2903 switch (type) { 2904 case HS20_ANQP_OUI_TYPE: 2905 hs20_parse_rx_hs20_anqp_resp(wpa_s, bss, sa, 2906 pos, slen, 2907 dialog_token); 2908 break; 2909 default: 2910 wpa_msg(wpa_s, MSG_DEBUG, 2911 "HS20: Unsupported ANQP vendor type %u", 2912 type); 2913 break; 2914 } 2915 break; 2916 #endif /* CONFIG_HS20 */ 2917 default: 2918 wpa_msg(wpa_s, MSG_DEBUG, 2919 "Interworking: Unsupported vendor-specific ANQP OUI %06x", 2920 WPA_GET_BE24(pos)); 2921 return; 2922 } 2923 break; 2924 default: 2925 wpa_msg(wpa_s, MSG_DEBUG, 2926 "Interworking: Unsupported ANQP Info ID %u", info_id); 2927 anqp_add_extra(wpa_s, anqp, info_id, data, slen); 2928 break; 2929 } 2930 } 2931 2932 2933 void anqp_resp_cb(void *ctx, const u8 *dst, u8 dialog_token, 2934 enum gas_query_result result, 2935 const struct wpabuf *adv_proto, 2936 const struct wpabuf *resp, u16 status_code) 2937 { 2938 struct wpa_supplicant *wpa_s = ctx; 2939 const u8 *pos; 2940 const u8 *end; 2941 u16 info_id; 2942 u16 slen; 2943 struct wpa_bss *bss = NULL, *tmp; 2944 const char *anqp_result = "SUCCESS"; 2945 2946 wpa_printf(MSG_DEBUG, "Interworking: anqp_resp_cb dst=" MACSTR 2947 " dialog_token=%u result=%d status_code=%u", 2948 MAC2STR(dst), dialog_token, result, status_code); 2949 if (result != GAS_QUERY_SUCCESS) { 2950 #ifdef CONFIG_HS20 2951 if (wpa_s->fetch_osu_icon_in_progress) 2952 hs20_icon_fetch_failed(wpa_s); 2953 #endif /* CONFIG_HS20 */ 2954 anqp_result = "FAILURE"; 2955 goto out; 2956 } 2957 2958 pos = wpabuf_head(adv_proto); 2959 if (wpabuf_len(adv_proto) < 4 || pos[0] != WLAN_EID_ADV_PROTO || 2960 pos[1] < 2 || pos[3] != ACCESS_NETWORK_QUERY_PROTOCOL) { 2961 wpa_msg(wpa_s, MSG_DEBUG, 2962 "ANQP: Unexpected Advertisement Protocol in response"); 2963 #ifdef CONFIG_HS20 2964 if (wpa_s->fetch_osu_icon_in_progress) 2965 hs20_icon_fetch_failed(wpa_s); 2966 #endif /* CONFIG_HS20 */ 2967 anqp_result = "INVALID_FRAME"; 2968 goto out; 2969 } 2970 2971 /* 2972 * If possible, select the BSS entry based on which BSS entry was used 2973 * for the request. This can help in cases where multiple BSS entries 2974 * may exist for the same AP. 2975 */ 2976 dl_list_for_each_reverse(tmp, &wpa_s->bss, struct wpa_bss, list) { 2977 if (tmp == wpa_s->interworking_gas_bss && 2978 os_memcmp(tmp->bssid, dst, ETH_ALEN) == 0) { 2979 bss = tmp; 2980 break; 2981 } 2982 } 2983 if (bss == NULL) 2984 bss = wpa_bss_get_bssid(wpa_s, dst); 2985 2986 pos = wpabuf_head(resp); 2987 end = pos + wpabuf_len(resp); 2988 2989 while (pos < end) { 2990 unsigned int left = end - pos; 2991 2992 if (left < 4) { 2993 wpa_msg(wpa_s, MSG_DEBUG, "ANQP: Invalid element"); 2994 anqp_result = "INVALID_FRAME"; 2995 goto out_parse_done; 2996 } 2997 info_id = WPA_GET_LE16(pos); 2998 pos += 2; 2999 slen = WPA_GET_LE16(pos); 3000 pos += 2; 3001 left -= 4; 3002 if (left < slen) { 3003 wpa_msg(wpa_s, MSG_DEBUG, 3004 "ANQP: Invalid element length for Info ID %u", 3005 info_id); 3006 anqp_result = "INVALID_FRAME"; 3007 goto out_parse_done; 3008 } 3009 interworking_parse_rx_anqp_resp(wpa_s, bss, dst, info_id, pos, 3010 slen, dialog_token); 3011 pos += slen; 3012 } 3013 3014 out_parse_done: 3015 #ifdef CONFIG_HS20 3016 hs20_notify_parse_done(wpa_s); 3017 #endif /* CONFIG_HS20 */ 3018 out: 3019 wpa_msg(wpa_s, MSG_INFO, ANQP_QUERY_DONE "addr=" MACSTR " result=%s", 3020 MAC2STR(dst), anqp_result); 3021 } 3022 3023 3024 static void interworking_scan_res_handler(struct wpa_supplicant *wpa_s, 3025 struct wpa_scan_results *scan_res) 3026 { 3027 wpa_msg(wpa_s, MSG_DEBUG, 3028 "Interworking: Scan results available - start ANQP fetch"); 3029 interworking_start_fetch_anqp(wpa_s); 3030 } 3031 3032 3033 int interworking_select(struct wpa_supplicant *wpa_s, int auto_select, 3034 int *freqs) 3035 { 3036 interworking_stop_fetch_anqp(wpa_s); 3037 wpa_s->network_select = 1; 3038 wpa_s->auto_network_select = 0; 3039 wpa_s->auto_select = !!auto_select; 3040 wpa_s->fetch_all_anqp = 0; 3041 wpa_s->fetch_osu_info = 0; 3042 wpa_msg(wpa_s, MSG_DEBUG, 3043 "Interworking: Start scan for network selection"); 3044 wpa_s->scan_res_handler = interworking_scan_res_handler; 3045 wpa_s->normal_scans = 0; 3046 wpa_s->scan_req = MANUAL_SCAN_REQ; 3047 os_free(wpa_s->manual_scan_freqs); 3048 wpa_s->manual_scan_freqs = freqs; 3049 wpa_s->after_wps = 0; 3050 wpa_s->known_wps_freq = 0; 3051 wpa_supplicant_req_scan(wpa_s, 0, 0); 3052 3053 return 0; 3054 } 3055 3056 3057 static void gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token, 3058 enum gas_query_result result, 3059 const struct wpabuf *adv_proto, 3060 const struct wpabuf *resp, u16 status_code) 3061 { 3062 struct wpa_supplicant *wpa_s = ctx; 3063 struct wpabuf *n; 3064 3065 wpa_msg(wpa_s, MSG_INFO, GAS_RESPONSE_INFO "addr=" MACSTR 3066 " dialog_token=%d status_code=%d resp_len=%d", 3067 MAC2STR(addr), dialog_token, status_code, 3068 resp ? (int) wpabuf_len(resp) : -1); 3069 if (!resp) 3070 return; 3071 3072 n = wpabuf_dup(resp); 3073 if (n == NULL) 3074 return; 3075 wpabuf_free(wpa_s->prev_gas_resp); 3076 wpa_s->prev_gas_resp = wpa_s->last_gas_resp; 3077 os_memcpy(wpa_s->prev_gas_addr, wpa_s->last_gas_addr, ETH_ALEN); 3078 wpa_s->prev_gas_dialog_token = wpa_s->last_gas_dialog_token; 3079 wpa_s->last_gas_resp = n; 3080 os_memcpy(wpa_s->last_gas_addr, addr, ETH_ALEN); 3081 wpa_s->last_gas_dialog_token = dialog_token; 3082 } 3083 3084 3085 int gas_send_request(struct wpa_supplicant *wpa_s, const u8 *dst, 3086 const struct wpabuf *adv_proto, 3087 const struct wpabuf *query) 3088 { 3089 struct wpabuf *buf; 3090 int ret = 0; 3091 int freq; 3092 struct wpa_bss *bss; 3093 int res; 3094 size_t len; 3095 u8 query_resp_len_limit = 0; 3096 3097 freq = wpa_s->assoc_freq; 3098 bss = wpa_bss_get_bssid(wpa_s, dst); 3099 if (bss) 3100 freq = bss->freq; 3101 if (freq <= 0) 3102 return -1; 3103 3104 wpa_msg(wpa_s, MSG_DEBUG, "GAS request to " MACSTR " (freq %d MHz)", 3105 MAC2STR(dst), freq); 3106 wpa_hexdump_buf(MSG_DEBUG, "Advertisement Protocol ID", adv_proto); 3107 wpa_hexdump_buf(MSG_DEBUG, "GAS Query", query); 3108 3109 len = 3 + wpabuf_len(adv_proto) + 2; 3110 if (query) 3111 len += wpabuf_len(query); 3112 buf = gas_build_initial_req(0, len); 3113 if (buf == NULL) 3114 return -1; 3115 3116 /* Advertisement Protocol IE */ 3117 wpabuf_put_u8(buf, WLAN_EID_ADV_PROTO); 3118 wpabuf_put_u8(buf, 1 + wpabuf_len(adv_proto)); /* Length */ 3119 wpabuf_put_u8(buf, query_resp_len_limit & 0x7f); 3120 wpabuf_put_buf(buf, adv_proto); 3121 3122 /* GAS Query */ 3123 if (query) { 3124 wpabuf_put_le16(buf, wpabuf_len(query)); 3125 wpabuf_put_buf(buf, query); 3126 } else 3127 wpabuf_put_le16(buf, 0); 3128 3129 res = gas_query_req(wpa_s->gas, dst, freq, buf, gas_resp_cb, wpa_s); 3130 if (res < 0) { 3131 wpa_msg(wpa_s, MSG_DEBUG, "GAS: Failed to send Query Request"); 3132 wpabuf_free(buf); 3133 ret = -1; 3134 } else 3135 wpa_msg(wpa_s, MSG_DEBUG, 3136 "GAS: Query started with dialog token %u", res); 3137 3138 return ret; 3139 } 3140