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