1 /* 2 * Copyright (c) 2009, Atheros Communications, Inc. 3 * Copyright (c) 2011-2013, Qualcomm Atheros, Inc. 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9 #include "includes.h" 10 #include <sys/stat.h> 11 12 #include "common.h" 13 #include "eloop.h" 14 #include "common/ieee802_11_common.h" 15 #include "common/ieee802_11_defs.h" 16 #include "common/gas.h" 17 #include "common/wpa_ctrl.h" 18 #include "rsn_supp/wpa.h" 19 #include "wpa_supplicant_i.h" 20 #include "driver_i.h" 21 #include "config.h" 22 #include "scan.h" 23 #include "bss.h" 24 #include "blacklist.h" 25 #include "gas_query.h" 26 #include "interworking.h" 27 #include "hs20_supplicant.h" 28 #include "base64.h" 29 30 31 #define OSU_MAX_ITEMS 10 32 33 struct osu_lang_string { 34 char lang[4]; 35 char text[253]; 36 }; 37 38 struct osu_icon { 39 u16 width; 40 u16 height; 41 char lang[4]; 42 char icon_type[256]; 43 char filename[256]; 44 unsigned int id; 45 unsigned int failed:1; 46 }; 47 48 struct osu_provider { 49 u8 bssid[ETH_ALEN]; 50 u8 osu_ssid[SSID_MAX_LEN]; 51 u8 osu_ssid_len; 52 u8 osu_ssid2[SSID_MAX_LEN]; 53 u8 osu_ssid2_len; 54 char server_uri[256]; 55 u32 osu_methods; /* bit 0 = OMA-DM, bit 1 = SOAP-XML SPP */ 56 char osu_nai[256]; 57 char osu_nai2[256]; 58 struct osu_lang_string friendly_name[OSU_MAX_ITEMS]; 59 size_t friendly_name_count; 60 struct osu_lang_string serv_desc[OSU_MAX_ITEMS]; 61 size_t serv_desc_count; 62 struct osu_icon icon[OSU_MAX_ITEMS]; 63 size_t icon_count; 64 }; 65 66 67 void hs20_configure_frame_filters(struct wpa_supplicant *wpa_s) 68 { 69 struct wpa_bss *bss = wpa_s->current_bss; 70 u8 *bssid = wpa_s->bssid; 71 const u8 *ie; 72 const u8 *ext_capa; 73 u32 filter = 0; 74 75 if (!bss || !is_hs20_network(wpa_s, wpa_s->current_ssid, bss)) { 76 wpa_printf(MSG_DEBUG, 77 "Not configuring frame filtering - BSS " MACSTR 78 " is not a Hotspot 2.0 network", MAC2STR(bssid)); 79 return; 80 } 81 82 ie = wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE); 83 84 /* Check if DGAF disabled bit is zero (5th byte in the IE) */ 85 if (!ie || ie[1] < 5) 86 wpa_printf(MSG_DEBUG, 87 "Not configuring frame filtering - Can't extract DGAF bit"); 88 else if (!(ie[6] & HS20_DGAF_DISABLED)) 89 filter |= WPA_DATA_FRAME_FILTER_FLAG_GTK; 90 91 ext_capa = wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB); 92 if (!ext_capa || ext_capa[1] < 2) { 93 wpa_printf(MSG_DEBUG, 94 "Not configuring frame filtering - Can't extract Proxy ARP bit"); 95 return; 96 } 97 98 /* Check if Proxy ARP is enabled (2nd byte in the IE) */ 99 if (ext_capa[3] & BIT(4)) 100 filter |= WPA_DATA_FRAME_FILTER_FLAG_ARP | 101 WPA_DATA_FRAME_FILTER_FLAG_NA; 102 103 wpa_drv_configure_frame_filters(wpa_s, filter); 104 } 105 106 107 void wpas_hs20_add_indication(struct wpabuf *buf, int pps_mo_id) 108 { 109 u8 conf; 110 111 wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC); 112 wpabuf_put_u8(buf, pps_mo_id >= 0 ? 7 : 5); 113 wpabuf_put_be24(buf, OUI_WFA); 114 wpabuf_put_u8(buf, HS20_INDICATION_OUI_TYPE); 115 conf = HS20_VERSION; 116 if (pps_mo_id >= 0) 117 conf |= HS20_PPS_MO_ID_PRESENT; 118 wpabuf_put_u8(buf, conf); 119 if (pps_mo_id >= 0) 120 wpabuf_put_le16(buf, pps_mo_id); 121 } 122 123 124 void wpas_hs20_add_roam_cons_sel(struct wpabuf *buf, 125 const struct wpa_ssid *ssid) 126 { 127 if (!ssid->roaming_consortium_selection || 128 !ssid->roaming_consortium_selection_len) 129 return; 130 131 wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC); 132 wpabuf_put_u8(buf, 4 + ssid->roaming_consortium_selection_len); 133 wpabuf_put_be24(buf, OUI_WFA); 134 wpabuf_put_u8(buf, HS20_ROAMING_CONS_SEL_OUI_TYPE); 135 wpabuf_put_data(buf, ssid->roaming_consortium_selection, 136 ssid->roaming_consortium_selection_len); 137 } 138 139 140 int is_hs20_network(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, 141 struct wpa_bss *bss) 142 { 143 if (!wpa_s->conf->hs20 || !ssid) 144 return 0; 145 146 if (ssid->parent_cred) 147 return 1; 148 149 if (bss && !wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) 150 return 0; 151 152 /* 153 * This may catch some non-Hotspot 2.0 cases, but it is safer to do that 154 * than cause Hotspot 2.0 connections without indication element getting 155 * added. Non-Hotspot 2.0 APs should ignore the unknown vendor element. 156 */ 157 158 if (!(ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X)) 159 return 0; 160 if (!(ssid->pairwise_cipher & WPA_CIPHER_CCMP)) 161 return 0; 162 if (ssid->proto != WPA_PROTO_RSN) 163 return 0; 164 165 return 1; 166 } 167 168 169 int hs20_get_pps_mo_id(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) 170 { 171 struct wpa_cred *cred; 172 173 if (ssid == NULL) 174 return 0; 175 176 if (ssid->update_identifier) 177 return ssid->update_identifier; 178 179 if (ssid->parent_cred == NULL) 180 return 0; 181 182 for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 183 if (ssid->parent_cred == cred) 184 return cred->update_identifier; 185 } 186 187 return 0; 188 } 189 190 191 void hs20_put_anqp_req(u32 stypes, const u8 *payload, size_t payload_len, 192 struct wpabuf *buf) 193 { 194 u8 *len_pos; 195 196 if (buf == NULL) 197 return; 198 199 len_pos = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC); 200 wpabuf_put_be24(buf, OUI_WFA); 201 wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE); 202 if (stypes == BIT(HS20_STYPE_NAI_HOME_REALM_QUERY)) { 203 wpabuf_put_u8(buf, HS20_STYPE_NAI_HOME_REALM_QUERY); 204 wpabuf_put_u8(buf, 0); /* Reserved */ 205 if (payload) 206 wpabuf_put_data(buf, payload, payload_len); 207 } else if (stypes == BIT(HS20_STYPE_ICON_REQUEST)) { 208 wpabuf_put_u8(buf, HS20_STYPE_ICON_REQUEST); 209 wpabuf_put_u8(buf, 0); /* Reserved */ 210 if (payload) 211 wpabuf_put_data(buf, payload, payload_len); 212 } else { 213 u8 i; 214 wpabuf_put_u8(buf, HS20_STYPE_QUERY_LIST); 215 wpabuf_put_u8(buf, 0); /* Reserved */ 216 for (i = 0; i < 32; i++) { 217 if (stypes & BIT(i)) 218 wpabuf_put_u8(buf, i); 219 } 220 } 221 gas_anqp_set_element_len(buf, len_pos); 222 223 gas_anqp_set_len(buf); 224 } 225 226 227 static struct wpabuf * hs20_build_anqp_req(u32 stypes, const u8 *payload, 228 size_t payload_len) 229 { 230 struct wpabuf *buf; 231 232 buf = gas_anqp_build_initial_req(0, 100 + payload_len); 233 if (buf == NULL) 234 return NULL; 235 236 hs20_put_anqp_req(stypes, payload, payload_len, buf); 237 238 return buf; 239 } 240 241 242 int hs20_anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, u32 stypes, 243 const u8 *payload, size_t payload_len, int inmem) 244 { 245 struct wpabuf *buf; 246 int ret = 0; 247 int freq; 248 struct wpa_bss *bss; 249 int res; 250 struct icon_entry *icon_entry; 251 252 bss = wpa_bss_get_bssid(wpa_s, dst); 253 if (!bss) { 254 wpa_printf(MSG_WARNING, 255 "ANQP: Cannot send query to unknown BSS " 256 MACSTR, MAC2STR(dst)); 257 return -1; 258 } 259 260 wpa_bss_anqp_unshare_alloc(bss); 261 freq = bss->freq; 262 263 wpa_printf(MSG_DEBUG, "HS20: ANQP Query Request to " MACSTR " for " 264 "subtypes 0x%x", MAC2STR(dst), stypes); 265 266 buf = hs20_build_anqp_req(stypes, payload, payload_len); 267 if (buf == NULL) 268 return -1; 269 270 res = gas_query_req(wpa_s->gas, dst, freq, 0, buf, anqp_resp_cb, wpa_s); 271 if (res < 0) { 272 wpa_printf(MSG_DEBUG, "ANQP: Failed to send Query Request"); 273 wpabuf_free(buf); 274 return -1; 275 } else 276 wpa_printf(MSG_DEBUG, "ANQP: Query started with dialog token " 277 "%u", res); 278 279 if (inmem) { 280 icon_entry = os_zalloc(sizeof(struct icon_entry)); 281 if (!icon_entry) 282 return -1; 283 os_memcpy(icon_entry->bssid, dst, ETH_ALEN); 284 icon_entry->file_name = os_malloc(payload_len + 1); 285 if (!icon_entry->file_name) { 286 os_free(icon_entry); 287 return -1; 288 } 289 os_memcpy(icon_entry->file_name, payload, payload_len); 290 icon_entry->file_name[payload_len] = '\0'; 291 icon_entry->dialog_token = res; 292 293 dl_list_add(&wpa_s->icon_head, &icon_entry->list); 294 } 295 296 return ret; 297 } 298 299 300 static struct icon_entry * hs20_find_icon(struct wpa_supplicant *wpa_s, 301 const u8 *bssid, 302 const char *file_name) 303 { 304 struct icon_entry *icon; 305 306 dl_list_for_each(icon, &wpa_s->icon_head, struct icon_entry, list) { 307 if (os_memcmp(icon->bssid, bssid, ETH_ALEN) == 0 && 308 os_strcmp(icon->file_name, file_name) == 0 && icon->image) 309 return icon; 310 } 311 312 return NULL; 313 } 314 315 316 int hs20_get_icon(struct wpa_supplicant *wpa_s, const u8 *bssid, 317 const char *file_name, size_t offset, size_t size, 318 char *reply, size_t buf_len) 319 { 320 struct icon_entry *icon; 321 size_t out_size; 322 unsigned char *b64; 323 size_t b64_size; 324 int reply_size; 325 326 wpa_printf(MSG_DEBUG, "HS20: Get icon " MACSTR " %s @ %u +%u (%u)", 327 MAC2STR(bssid), file_name, (unsigned int) offset, 328 (unsigned int) size, (unsigned int) buf_len); 329 330 icon = hs20_find_icon(wpa_s, bssid, file_name); 331 if (!icon || !icon->image || offset >= icon->image_len) 332 return -1; 333 if (size > icon->image_len - offset) 334 size = icon->image_len - offset; 335 out_size = buf_len - 3 /* max base64 padding */; 336 if (size * 4 > out_size * 3) 337 size = out_size * 3 / 4; 338 if (size == 0) 339 return -1; 340 341 b64 = base64_encode(&icon->image[offset], size, &b64_size); 342 if (b64 && buf_len >= b64_size) { 343 os_memcpy(reply, b64, b64_size); 344 reply_size = b64_size; 345 } else { 346 reply_size = -1; 347 } 348 os_free(b64); 349 return reply_size; 350 } 351 352 353 static void hs20_free_icon_entry(struct icon_entry *icon) 354 { 355 wpa_printf(MSG_DEBUG, "HS20: Free stored icon from " MACSTR 356 " dialog_token=%u file_name=%s image_len=%u", 357 MAC2STR(icon->bssid), icon->dialog_token, 358 icon->file_name ? icon->file_name : "N/A", 359 (unsigned int) icon->image_len); 360 os_free(icon->file_name); 361 os_free(icon->image); 362 os_free(icon); 363 } 364 365 366 int hs20_del_icon(struct wpa_supplicant *wpa_s, const u8 *bssid, 367 const char *file_name) 368 { 369 struct icon_entry *icon, *tmp; 370 int count = 0; 371 372 if (!bssid) 373 wpa_printf(MSG_DEBUG, "HS20: Delete all stored icons"); 374 else if (!file_name) 375 wpa_printf(MSG_DEBUG, "HS20: Delete all stored icons for " 376 MACSTR, MAC2STR(bssid)); 377 else 378 wpa_printf(MSG_DEBUG, "HS20: Delete stored icons for " 379 MACSTR " file name %s", MAC2STR(bssid), file_name); 380 381 dl_list_for_each_safe(icon, tmp, &wpa_s->icon_head, struct icon_entry, 382 list) { 383 if ((!bssid || os_memcmp(icon->bssid, bssid, ETH_ALEN) == 0) && 384 (!file_name || 385 os_strcmp(icon->file_name, file_name) == 0)) { 386 dl_list_del(&icon->list); 387 hs20_free_icon_entry(icon); 388 count++; 389 } 390 } 391 return count == 0 ? -1 : 0; 392 } 393 394 395 static void hs20_set_osu_access_permission(const char *osu_dir, 396 const char *fname) 397 { 398 struct stat statbuf; 399 400 /* Get OSU directory information */ 401 if (stat(osu_dir, &statbuf) < 0) { 402 wpa_printf(MSG_WARNING, "Cannot stat the OSU directory %s", 403 osu_dir); 404 return; 405 } 406 407 if (chmod(fname, statbuf.st_mode) < 0) { 408 wpa_printf(MSG_WARNING, 409 "Cannot change the permissions for %s", fname); 410 return; 411 } 412 413 if (chown(fname, statbuf.st_uid, statbuf.st_gid) < 0) { 414 wpa_printf(MSG_WARNING, "Cannot change the ownership for %s", 415 fname); 416 } 417 } 418 419 420 static void hs20_remove_duplicate_icons(struct wpa_supplicant *wpa_s, 421 struct icon_entry *new_icon) 422 { 423 struct icon_entry *icon, *tmp; 424 425 dl_list_for_each_safe(icon, tmp, &wpa_s->icon_head, struct icon_entry, 426 list) { 427 if (icon == new_icon) 428 continue; 429 if (os_memcmp(icon->bssid, new_icon->bssid, ETH_ALEN) == 0 && 430 os_strcmp(icon->file_name, new_icon->file_name) == 0) { 431 dl_list_del(&icon->list); 432 hs20_free_icon_entry(icon); 433 } 434 } 435 } 436 437 438 static int hs20_process_icon_binary_file(struct wpa_supplicant *wpa_s, 439 const u8 *sa, const u8 *pos, 440 size_t slen, u8 dialog_token) 441 { 442 char fname[256]; 443 int png; 444 FILE *f; 445 u16 data_len; 446 struct icon_entry *icon; 447 448 dl_list_for_each(icon, &wpa_s->icon_head, struct icon_entry, list) { 449 if (icon->dialog_token == dialog_token && !icon->image && 450 os_memcmp(icon->bssid, sa, ETH_ALEN) == 0) { 451 icon->image = os_memdup(pos, slen); 452 if (!icon->image) 453 return -1; 454 icon->image_len = slen; 455 hs20_remove_duplicate_icons(wpa_s, icon); 456 wpa_msg(wpa_s, MSG_INFO, 457 RX_HS20_ICON MACSTR " %s %u", 458 MAC2STR(sa), icon->file_name, 459 (unsigned int) icon->image_len); 460 return 0; 461 } 462 } 463 464 wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR " Icon Binary File", 465 MAC2STR(sa)); 466 467 if (slen < 4) { 468 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: Too short Icon Binary File " 469 "value from " MACSTR, MAC2STR(sa)); 470 return -1; 471 } 472 473 wpa_printf(MSG_DEBUG, "HS 2.0: Download Status Code %u", *pos); 474 if (*pos != 0) 475 return -1; 476 pos++; 477 slen--; 478 479 if ((size_t) 1 + pos[0] > slen) { 480 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: Too short Icon Binary File " 481 "value from " MACSTR, MAC2STR(sa)); 482 return -1; 483 } 484 wpa_hexdump_ascii(MSG_DEBUG, "Icon Type", pos + 1, pos[0]); 485 png = os_strncasecmp((char *) pos + 1, "image/png", 9) == 0; 486 slen -= 1 + pos[0]; 487 pos += 1 + pos[0]; 488 489 if (slen < 2) { 490 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: Too short Icon Binary File " 491 "value from " MACSTR, MAC2STR(sa)); 492 return -1; 493 } 494 data_len = WPA_GET_LE16(pos); 495 pos += 2; 496 slen -= 2; 497 498 if (data_len > slen) { 499 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: Too short Icon Binary File " 500 "value from " MACSTR, MAC2STR(sa)); 501 return -1; 502 } 503 504 wpa_printf(MSG_DEBUG, "Icon Binary Data: %u bytes", data_len); 505 if (wpa_s->conf->osu_dir == NULL) 506 return -1; 507 508 wpa_s->osu_icon_id++; 509 if (wpa_s->osu_icon_id == 0) 510 wpa_s->osu_icon_id++; 511 snprintf(fname, sizeof(fname), "%s/osu-icon-%u.%s", 512 wpa_s->conf->osu_dir, wpa_s->osu_icon_id, 513 png ? "png" : "icon"); 514 f = fopen(fname, "wb"); 515 if (f == NULL) 516 return -1; 517 518 hs20_set_osu_access_permission(wpa_s->conf->osu_dir, fname); 519 520 if (fwrite(pos, slen, 1, f) != 1) { 521 fclose(f); 522 unlink(fname); 523 return -1; 524 } 525 fclose(f); 526 527 wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP_ICON "%s", fname); 528 return 0; 529 } 530 531 532 static void hs20_continue_icon_fetch(void *eloop_ctx, void *sock_ctx) 533 { 534 struct wpa_supplicant *wpa_s = eloop_ctx; 535 if (wpa_s->fetch_osu_icon_in_progress) 536 hs20_next_osu_icon(wpa_s); 537 } 538 539 540 static void hs20_osu_icon_fetch_result(struct wpa_supplicant *wpa_s, int res) 541 { 542 size_t i, j; 543 struct os_reltime now, tmp; 544 int dur; 545 546 os_get_reltime(&now); 547 os_reltime_sub(&now, &wpa_s->osu_icon_fetch_start, &tmp); 548 dur = tmp.sec * 1000 + tmp.usec / 1000; 549 wpa_printf(MSG_DEBUG, "HS 2.0: Icon fetch dur=%d ms res=%d", 550 dur, res); 551 552 for (i = 0; i < wpa_s->osu_prov_count; i++) { 553 struct osu_provider *osu = &wpa_s->osu_prov[i]; 554 for (j = 0; j < osu->icon_count; j++) { 555 struct osu_icon *icon = &osu->icon[j]; 556 if (icon->id || icon->failed) 557 continue; 558 if (res < 0) 559 icon->failed = 1; 560 else 561 icon->id = wpa_s->osu_icon_id; 562 return; 563 } 564 } 565 } 566 567 568 void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s, 569 struct wpa_bss *bss, const u8 *sa, 570 const u8 *data, size_t slen, u8 dialog_token) 571 { 572 const u8 *pos = data; 573 u8 subtype; 574 struct wpa_bss_anqp *anqp = NULL; 575 int ret; 576 577 if (slen < 2) 578 return; 579 580 if (bss) 581 anqp = bss->anqp; 582 583 subtype = *pos++; 584 slen--; 585 586 pos++; /* Reserved */ 587 slen--; 588 589 switch (subtype) { 590 case HS20_STYPE_CAPABILITY_LIST: 591 wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR 592 " HS Capability List", MAC2STR(sa)); 593 wpa_hexdump_ascii(MSG_DEBUG, "HS Capability List", pos, slen); 594 if (anqp) { 595 wpabuf_free(anqp->hs20_capability_list); 596 anqp->hs20_capability_list = 597 wpabuf_alloc_copy(pos, slen); 598 } 599 break; 600 case HS20_STYPE_OPERATOR_FRIENDLY_NAME: 601 wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR 602 " Operator Friendly Name", MAC2STR(sa)); 603 wpa_hexdump_ascii(MSG_DEBUG, "oper friendly name", pos, slen); 604 if (anqp) { 605 wpabuf_free(anqp->hs20_operator_friendly_name); 606 anqp->hs20_operator_friendly_name = 607 wpabuf_alloc_copy(pos, slen); 608 } 609 break; 610 case HS20_STYPE_WAN_METRICS: 611 wpa_hexdump(MSG_DEBUG, "WAN Metrics", pos, slen); 612 if (slen < 13) { 613 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: Too short WAN " 614 "Metrics value from " MACSTR, MAC2STR(sa)); 615 break; 616 } 617 wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR 618 " WAN Metrics %02x:%u:%u:%u:%u:%u", MAC2STR(sa), 619 pos[0], WPA_GET_LE32(pos + 1), WPA_GET_LE32(pos + 5), 620 pos[9], pos[10], WPA_GET_LE16(pos + 11)); 621 if (anqp) { 622 wpabuf_free(anqp->hs20_wan_metrics); 623 anqp->hs20_wan_metrics = wpabuf_alloc_copy(pos, slen); 624 } 625 break; 626 case HS20_STYPE_CONNECTION_CAPABILITY: 627 wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR 628 " Connection Capability", MAC2STR(sa)); 629 wpa_hexdump_ascii(MSG_DEBUG, "conn capability", pos, slen); 630 if (anqp) { 631 wpabuf_free(anqp->hs20_connection_capability); 632 anqp->hs20_connection_capability = 633 wpabuf_alloc_copy(pos, slen); 634 } 635 break; 636 case HS20_STYPE_OPERATING_CLASS: 637 wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR 638 " Operating Class", MAC2STR(sa)); 639 wpa_hexdump_ascii(MSG_DEBUG, "Operating Class", pos, slen); 640 if (anqp) { 641 wpabuf_free(anqp->hs20_operating_class); 642 anqp->hs20_operating_class = 643 wpabuf_alloc_copy(pos, slen); 644 } 645 break; 646 case HS20_STYPE_OSU_PROVIDERS_LIST: 647 wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR 648 " OSU Providers list", MAC2STR(sa)); 649 wpa_s->num_prov_found++; 650 if (anqp) { 651 wpabuf_free(anqp->hs20_osu_providers_list); 652 anqp->hs20_osu_providers_list = 653 wpabuf_alloc_copy(pos, slen); 654 } 655 break; 656 case HS20_STYPE_ICON_BINARY_FILE: 657 ret = hs20_process_icon_binary_file(wpa_s, sa, pos, slen, 658 dialog_token); 659 if (wpa_s->fetch_osu_icon_in_progress) { 660 hs20_osu_icon_fetch_result(wpa_s, ret); 661 eloop_cancel_timeout(hs20_continue_icon_fetch, 662 wpa_s, NULL); 663 eloop_register_timeout(0, 0, hs20_continue_icon_fetch, 664 wpa_s, NULL); 665 } 666 break; 667 case HS20_STYPE_OPERATOR_ICON_METADATA: 668 wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR 669 " Operator Icon Metadata", MAC2STR(sa)); 670 wpa_hexdump(MSG_DEBUG, "Operator Icon Metadata", pos, slen); 671 if (anqp) { 672 wpabuf_free(anqp->hs20_operator_icon_metadata); 673 anqp->hs20_operator_icon_metadata = 674 wpabuf_alloc_copy(pos, slen); 675 } 676 break; 677 case HS20_STYPE_OSU_PROVIDERS_NAI_LIST: 678 wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR 679 " OSU Providers NAI List", MAC2STR(sa)); 680 if (anqp) { 681 wpabuf_free(anqp->hs20_osu_providers_nai_list); 682 anqp->hs20_osu_providers_nai_list = 683 wpabuf_alloc_copy(pos, slen); 684 } 685 break; 686 default: 687 wpa_printf(MSG_DEBUG, "HS20: Unsupported subtype %u", subtype); 688 break; 689 } 690 } 691 692 693 void hs20_notify_parse_done(struct wpa_supplicant *wpa_s) 694 { 695 if (!wpa_s->fetch_osu_icon_in_progress) 696 return; 697 if (eloop_is_timeout_registered(hs20_continue_icon_fetch, wpa_s, NULL)) 698 return; 699 /* 700 * We are going through icon fetch, but no icon response was received. 701 * Assume this means the current AP could not provide an answer to avoid 702 * getting stuck in fetch iteration. 703 */ 704 hs20_icon_fetch_failed(wpa_s); 705 } 706 707 708 static void hs20_free_osu_prov_entry(struct osu_provider *prov) 709 { 710 } 711 712 713 void hs20_free_osu_prov(struct wpa_supplicant *wpa_s) 714 { 715 size_t i; 716 for (i = 0; i < wpa_s->osu_prov_count; i++) 717 hs20_free_osu_prov_entry(&wpa_s->osu_prov[i]); 718 os_free(wpa_s->osu_prov); 719 wpa_s->osu_prov = NULL; 720 wpa_s->osu_prov_count = 0; 721 } 722 723 724 static void hs20_osu_fetch_done(struct wpa_supplicant *wpa_s) 725 { 726 char fname[256]; 727 FILE *f; 728 size_t i, j; 729 730 wpa_s->fetch_osu_info = 0; 731 wpa_s->fetch_osu_icon_in_progress = 0; 732 733 if (wpa_s->conf->osu_dir == NULL) { 734 hs20_free_osu_prov(wpa_s); 735 wpa_s->fetch_anqp_in_progress = 0; 736 return; 737 } 738 739 snprintf(fname, sizeof(fname), "%s/osu-providers.txt", 740 wpa_s->conf->osu_dir); 741 f = fopen(fname, "w"); 742 if (f == NULL) { 743 wpa_msg(wpa_s, MSG_INFO, 744 "Could not write OSU provider information"); 745 hs20_free_osu_prov(wpa_s); 746 wpa_s->fetch_anqp_in_progress = 0; 747 return; 748 } 749 750 hs20_set_osu_access_permission(wpa_s->conf->osu_dir, fname); 751 752 for (i = 0; i < wpa_s->osu_prov_count; i++) { 753 struct osu_provider *osu = &wpa_s->osu_prov[i]; 754 if (i > 0) 755 fprintf(f, "\n"); 756 fprintf(f, "OSU-PROVIDER " MACSTR "\n" 757 "uri=%s\n" 758 "methods=%08x\n", 759 MAC2STR(osu->bssid), osu->server_uri, osu->osu_methods); 760 if (osu->osu_ssid_len) { 761 fprintf(f, "osu_ssid=%s\n", 762 wpa_ssid_txt(osu->osu_ssid, 763 osu->osu_ssid_len)); 764 } 765 if (osu->osu_ssid2_len) { 766 fprintf(f, "osu_ssid2=%s\n", 767 wpa_ssid_txt(osu->osu_ssid2, 768 osu->osu_ssid2_len)); 769 } 770 if (osu->osu_nai[0]) 771 fprintf(f, "osu_nai=%s\n", osu->osu_nai); 772 if (osu->osu_nai2[0]) 773 fprintf(f, "osu_nai2=%s\n", osu->osu_nai2); 774 for (j = 0; j < osu->friendly_name_count; j++) { 775 fprintf(f, "friendly_name=%s:%s\n", 776 osu->friendly_name[j].lang, 777 osu->friendly_name[j].text); 778 } 779 for (j = 0; j < osu->serv_desc_count; j++) { 780 fprintf(f, "desc=%s:%s\n", 781 osu->serv_desc[j].lang, 782 osu->serv_desc[j].text); 783 } 784 for (j = 0; j < osu->icon_count; j++) { 785 struct osu_icon *icon = &osu->icon[j]; 786 if (icon->failed) 787 continue; /* could not fetch icon */ 788 fprintf(f, "icon=%u:%u:%u:%s:%s:%s\n", 789 icon->id, icon->width, icon->height, icon->lang, 790 icon->icon_type, icon->filename); 791 } 792 } 793 fclose(f); 794 hs20_free_osu_prov(wpa_s); 795 796 wpa_msg(wpa_s, MSG_INFO, "OSU provider fetch completed"); 797 wpa_s->fetch_anqp_in_progress = 0; 798 } 799 800 801 void hs20_next_osu_icon(struct wpa_supplicant *wpa_s) 802 { 803 size_t i, j; 804 805 wpa_printf(MSG_DEBUG, "HS 2.0: Ready to fetch next icon"); 806 807 for (i = 0; i < wpa_s->osu_prov_count; i++) { 808 struct osu_provider *osu = &wpa_s->osu_prov[i]; 809 for (j = 0; j < osu->icon_count; j++) { 810 struct osu_icon *icon = &osu->icon[j]; 811 if (icon->id || icon->failed) 812 continue; 813 814 wpa_printf(MSG_DEBUG, "HS 2.0: Try to fetch icon '%s' " 815 "from " MACSTR, icon->filename, 816 MAC2STR(osu->bssid)); 817 os_get_reltime(&wpa_s->osu_icon_fetch_start); 818 if (hs20_anqp_send_req(wpa_s, osu->bssid, 819 BIT(HS20_STYPE_ICON_REQUEST), 820 (u8 *) icon->filename, 821 os_strlen(icon->filename), 822 0) < 0) { 823 icon->failed = 1; 824 continue; 825 } 826 return; 827 } 828 } 829 830 wpa_printf(MSG_DEBUG, "HS 2.0: No more icons to fetch"); 831 hs20_osu_fetch_done(wpa_s); 832 } 833 834 835 static void hs20_osu_add_prov(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, 836 const u8 *osu_ssid, u8 osu_ssid_len, 837 const u8 *osu_ssid2, u8 osu_ssid2_len, 838 const u8 *pos, size_t len) 839 { 840 struct osu_provider *prov; 841 const u8 *end = pos + len; 842 u16 len2; 843 const u8 *pos2; 844 u8 uri_len, osu_method_len, osu_nai_len; 845 846 wpa_hexdump(MSG_DEBUG, "HS 2.0: Parsing OSU Provider", pos, len); 847 prov = os_realloc_array(wpa_s->osu_prov, 848 wpa_s->osu_prov_count + 1, 849 sizeof(*prov)); 850 if (prov == NULL) 851 return; 852 wpa_s->osu_prov = prov; 853 prov = &prov[wpa_s->osu_prov_count]; 854 os_memset(prov, 0, sizeof(*prov)); 855 856 os_memcpy(prov->bssid, bss->bssid, ETH_ALEN); 857 os_memcpy(prov->osu_ssid, osu_ssid, osu_ssid_len); 858 prov->osu_ssid_len = osu_ssid_len; 859 if (osu_ssid2) 860 os_memcpy(prov->osu_ssid2, osu_ssid2, osu_ssid2_len); 861 prov->osu_ssid2_len = osu_ssid2_len; 862 863 /* OSU Friendly Name Length */ 864 if (end - pos < 2) { 865 wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU " 866 "Friendly Name Length"); 867 return; 868 } 869 len2 = WPA_GET_LE16(pos); 870 pos += 2; 871 if (len2 > end - pos) { 872 wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU " 873 "Friendly Name Duples"); 874 return; 875 } 876 pos2 = pos; 877 pos += len2; 878 879 /* OSU Friendly Name Duples */ 880 while (pos - pos2 >= 4 && prov->friendly_name_count < OSU_MAX_ITEMS) { 881 struct osu_lang_string *f; 882 if (1 + pos2[0] > pos - pos2 || pos2[0] < 3) { 883 wpa_printf(MSG_DEBUG, "Invalid OSU Friendly Name"); 884 break; 885 } 886 f = &prov->friendly_name[prov->friendly_name_count++]; 887 os_memcpy(f->lang, pos2 + 1, 3); 888 os_memcpy(f->text, pos2 + 1 + 3, pos2[0] - 3); 889 pos2 += 1 + pos2[0]; 890 } 891 892 /* OSU Server URI */ 893 if (end - pos < 1) { 894 wpa_printf(MSG_DEBUG, 895 "HS 2.0: Not enough room for OSU Server URI length"); 896 return; 897 } 898 uri_len = *pos++; 899 if (uri_len > end - pos) { 900 wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU Server " 901 "URI"); 902 return; 903 } 904 os_memcpy(prov->server_uri, pos, uri_len); 905 pos += uri_len; 906 907 /* OSU Method list */ 908 if (end - pos < 1) { 909 wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU Method " 910 "list length"); 911 return; 912 } 913 osu_method_len = pos[0]; 914 if (osu_method_len > end - pos - 1) { 915 wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU Method " 916 "list"); 917 return; 918 } 919 pos2 = pos + 1; 920 pos += 1 + osu_method_len; 921 while (pos2 < pos) { 922 if (*pos2 < 32) 923 prov->osu_methods |= BIT(*pos2); 924 pos2++; 925 } 926 927 /* Icons Available Length */ 928 if (end - pos < 2) { 929 wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for Icons " 930 "Available Length"); 931 return; 932 } 933 len2 = WPA_GET_LE16(pos); 934 pos += 2; 935 if (len2 > end - pos) { 936 wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for Icons " 937 "Available"); 938 return; 939 } 940 pos2 = pos; 941 pos += len2; 942 943 /* Icons Available */ 944 while (pos2 < pos) { 945 struct osu_icon *icon = &prov->icon[prov->icon_count]; 946 u8 flen; 947 948 if (2 + 2 + 3 + 1 + 1 > pos - pos2) { 949 wpa_printf(MSG_DEBUG, "HS 2.0: Invalid Icon Metadata"); 950 break; 951 } 952 953 icon->width = WPA_GET_LE16(pos2); 954 pos2 += 2; 955 icon->height = WPA_GET_LE16(pos2); 956 pos2 += 2; 957 os_memcpy(icon->lang, pos2, 3); 958 pos2 += 3; 959 960 flen = *pos2++; 961 if (flen > pos - pos2) { 962 wpa_printf(MSG_DEBUG, "HS 2.0: Not room for Icon Type"); 963 break; 964 } 965 os_memcpy(icon->icon_type, pos2, flen); 966 pos2 += flen; 967 968 if (pos - pos2 < 1) { 969 wpa_printf(MSG_DEBUG, "HS 2.0: Not room for Icon " 970 "Filename length"); 971 break; 972 } 973 flen = *pos2++; 974 if (flen > pos - pos2) { 975 wpa_printf(MSG_DEBUG, "HS 2.0: Not room for Icon " 976 "Filename"); 977 break; 978 } 979 os_memcpy(icon->filename, pos2, flen); 980 pos2 += flen; 981 982 prov->icon_count++; 983 } 984 985 /* OSU_NAI */ 986 if (end - pos < 1) { 987 wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU_NAI"); 988 return; 989 } 990 osu_nai_len = *pos++; 991 if (osu_nai_len > end - pos) { 992 wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU_NAI"); 993 return; 994 } 995 os_memcpy(prov->osu_nai, pos, osu_nai_len); 996 pos += osu_nai_len; 997 998 /* OSU Service Description Length */ 999 if (end - pos < 2) { 1000 wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU " 1001 "Service Description Length"); 1002 return; 1003 } 1004 len2 = WPA_GET_LE16(pos); 1005 pos += 2; 1006 if (len2 > end - pos) { 1007 wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU " 1008 "Service Description Duples"); 1009 return; 1010 } 1011 pos2 = pos; 1012 pos += len2; 1013 1014 /* OSU Service Description Duples */ 1015 while (pos - pos2 >= 4 && prov->serv_desc_count < OSU_MAX_ITEMS) { 1016 struct osu_lang_string *f; 1017 u8 descr_len; 1018 1019 descr_len = *pos2++; 1020 if (descr_len > pos - pos2 || descr_len < 3) { 1021 wpa_printf(MSG_DEBUG, "Invalid OSU Service " 1022 "Description"); 1023 break; 1024 } 1025 f = &prov->serv_desc[prov->serv_desc_count++]; 1026 os_memcpy(f->lang, pos2, 3); 1027 os_memcpy(f->text, pos2 + 3, descr_len - 3); 1028 pos2 += descr_len; 1029 } 1030 1031 wpa_printf(MSG_DEBUG, "HS 2.0: Added OSU Provider through " MACSTR, 1032 MAC2STR(bss->bssid)); 1033 wpa_s->osu_prov_count++; 1034 } 1035 1036 1037 void hs20_osu_icon_fetch(struct wpa_supplicant *wpa_s) 1038 { 1039 struct wpa_bss *bss; 1040 struct wpabuf *prov_anqp; 1041 const u8 *pos, *end; 1042 u16 len; 1043 const u8 *osu_ssid, *osu_ssid2; 1044 u8 osu_ssid_len, osu_ssid2_len; 1045 u8 num_providers; 1046 1047 hs20_free_osu_prov(wpa_s); 1048 1049 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { 1050 struct wpa_ie_data data; 1051 const u8 *ie; 1052 1053 if (bss->anqp == NULL) 1054 continue; 1055 prov_anqp = bss->anqp->hs20_osu_providers_list; 1056 if (prov_anqp == NULL) 1057 continue; 1058 ie = wpa_bss_get_ie(bss, WLAN_EID_RSN); 1059 if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &data) == 0 && 1060 (data.key_mgmt & WPA_KEY_MGMT_OSEN)) { 1061 osu_ssid2 = bss->ssid; 1062 osu_ssid2_len = bss->ssid_len; 1063 } else { 1064 osu_ssid2 = NULL; 1065 osu_ssid2_len = 0; 1066 } 1067 wpa_printf(MSG_DEBUG, "HS 2.0: Parsing OSU Providers list from " 1068 MACSTR, MAC2STR(bss->bssid)); 1069 wpa_hexdump_buf(MSG_DEBUG, "HS 2.0: OSU Providers list", 1070 prov_anqp); 1071 pos = wpabuf_head(prov_anqp); 1072 end = pos + wpabuf_len(prov_anqp); 1073 1074 /* OSU SSID */ 1075 if (end - pos < 1) 1076 continue; 1077 if (1 + pos[0] > end - pos) { 1078 wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for " 1079 "OSU SSID"); 1080 continue; 1081 } 1082 osu_ssid_len = *pos++; 1083 if (osu_ssid_len > SSID_MAX_LEN) { 1084 wpa_printf(MSG_DEBUG, "HS 2.0: Invalid OSU SSID " 1085 "Length %u", osu_ssid_len); 1086 continue; 1087 } 1088 osu_ssid = pos; 1089 pos += osu_ssid_len; 1090 1091 if (end - pos < 1) { 1092 wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for " 1093 "Number of OSU Providers"); 1094 continue; 1095 } 1096 num_providers = *pos++; 1097 wpa_printf(MSG_DEBUG, "HS 2.0: Number of OSU Providers: %u", 1098 num_providers); 1099 1100 /* OSU Providers */ 1101 while (end - pos > 2 && num_providers > 0) { 1102 num_providers--; 1103 len = WPA_GET_LE16(pos); 1104 pos += 2; 1105 if (len > (unsigned int) (end - pos)) 1106 break; 1107 hs20_osu_add_prov(wpa_s, bss, osu_ssid, 1108 osu_ssid_len, osu_ssid2, 1109 osu_ssid2_len, pos, len); 1110 pos += len; 1111 } 1112 1113 if (pos != end) { 1114 wpa_printf(MSG_DEBUG, "HS 2.0: Ignored %d bytes of " 1115 "extra data after OSU Providers", 1116 (int) (end - pos)); 1117 } 1118 1119 prov_anqp = bss->anqp->hs20_osu_providers_nai_list; 1120 if (!prov_anqp) 1121 continue; 1122 wpa_printf(MSG_DEBUG, 1123 "HS 2.0: Parsing OSU Providers NAI List from " 1124 MACSTR, MAC2STR(bss->bssid)); 1125 wpa_hexdump_buf(MSG_DEBUG, "HS 2.0: OSU Providers NAI List", 1126 prov_anqp); 1127 pos = wpabuf_head(prov_anqp); 1128 end = pos + wpabuf_len(prov_anqp); 1129 num_providers = 0; 1130 while (end - pos > 0) { 1131 len = *pos++; 1132 if (end - pos < len) { 1133 wpa_printf(MSG_DEBUG, 1134 "HS 2.0: Not enough room for OSU_NAI"); 1135 break; 1136 } 1137 if (num_providers >= wpa_s->osu_prov_count) { 1138 wpa_printf(MSG_DEBUG, 1139 "HS 2.0: Ignore unexpected OSU Provider NAI List entries"); 1140 break; 1141 } 1142 os_memcpy(wpa_s->osu_prov[num_providers].osu_nai2, 1143 pos, len); 1144 pos += len; 1145 num_providers++; 1146 } 1147 } 1148 1149 wpa_s->fetch_osu_icon_in_progress = 1; 1150 hs20_next_osu_icon(wpa_s); 1151 } 1152 1153 1154 static void hs20_osu_scan_res_handler(struct wpa_supplicant *wpa_s, 1155 struct wpa_scan_results *scan_res) 1156 { 1157 wpa_printf(MSG_DEBUG, "OSU provisioning fetch scan completed"); 1158 if (!wpa_s->fetch_osu_waiting_scan) { 1159 wpa_printf(MSG_DEBUG, "OSU fetch have been canceled"); 1160 return; 1161 } 1162 wpa_s->network_select = 0; 1163 wpa_s->fetch_all_anqp = 1; 1164 wpa_s->fetch_osu_info = 1; 1165 wpa_s->fetch_osu_icon_in_progress = 0; 1166 1167 interworking_start_fetch_anqp(wpa_s); 1168 } 1169 1170 1171 int hs20_fetch_osu(struct wpa_supplicant *wpa_s, int skip_scan) 1172 { 1173 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) { 1174 wpa_printf(MSG_DEBUG, "HS 2.0: Cannot start fetch_osu - " 1175 "interface disabled"); 1176 return -1; 1177 } 1178 1179 if (wpa_s->scanning) { 1180 wpa_printf(MSG_DEBUG, "HS 2.0: Cannot start fetch_osu - " 1181 "scanning"); 1182 return -1; 1183 } 1184 1185 if (wpa_s->conf->osu_dir == NULL) { 1186 wpa_printf(MSG_DEBUG, "HS 2.0: Cannot start fetch_osu - " 1187 "osu_dir not configured"); 1188 return -1; 1189 } 1190 1191 if (wpa_s->fetch_anqp_in_progress || wpa_s->network_select) { 1192 wpa_printf(MSG_DEBUG, "HS 2.0: Cannot start fetch_osu - " 1193 "fetch in progress (%d, %d)", 1194 wpa_s->fetch_anqp_in_progress, 1195 wpa_s->network_select); 1196 return -1; 1197 } 1198 1199 wpa_msg(wpa_s, MSG_INFO, "Starting OSU provisioning information fetch"); 1200 wpa_s->num_osu_scans = 0; 1201 wpa_s->num_prov_found = 0; 1202 if (skip_scan) { 1203 wpa_s->network_select = 0; 1204 wpa_s->fetch_all_anqp = 1; 1205 wpa_s->fetch_osu_info = 1; 1206 wpa_s->fetch_osu_icon_in_progress = 0; 1207 1208 interworking_start_fetch_anqp(wpa_s); 1209 } else { 1210 hs20_start_osu_scan(wpa_s); 1211 } 1212 1213 return 0; 1214 } 1215 1216 1217 void hs20_start_osu_scan(struct wpa_supplicant *wpa_s) 1218 { 1219 wpa_s->fetch_osu_waiting_scan = 1; 1220 wpa_s->num_osu_scans++; 1221 wpa_s->scan_req = MANUAL_SCAN_REQ; 1222 wpa_s->scan_res_handler = hs20_osu_scan_res_handler; 1223 wpa_supplicant_req_scan(wpa_s, 0, 0); 1224 } 1225 1226 1227 void hs20_cancel_fetch_osu(struct wpa_supplicant *wpa_s) 1228 { 1229 wpa_printf(MSG_DEBUG, "Cancel OSU fetch"); 1230 interworking_stop_fetch_anqp(wpa_s); 1231 wpa_s->fetch_osu_waiting_scan = 0; 1232 wpa_s->network_select = 0; 1233 wpa_s->fetch_osu_info = 0; 1234 wpa_s->fetch_osu_icon_in_progress = 0; 1235 } 1236 1237 1238 void hs20_icon_fetch_failed(struct wpa_supplicant *wpa_s) 1239 { 1240 hs20_osu_icon_fetch_result(wpa_s, -1); 1241 eloop_cancel_timeout(hs20_continue_icon_fetch, wpa_s, NULL); 1242 eloop_register_timeout(0, 0, hs20_continue_icon_fetch, wpa_s, NULL); 1243 } 1244 1245 1246 void hs20_rx_subscription_remediation(struct wpa_supplicant *wpa_s, 1247 const char *url, u8 osu_method) 1248 { 1249 if (url) 1250 wpa_msg(wpa_s, MSG_INFO, HS20_SUBSCRIPTION_REMEDIATION "%u %s", 1251 osu_method, url); 1252 else 1253 wpa_msg(wpa_s, MSG_INFO, HS20_SUBSCRIPTION_REMEDIATION); 1254 } 1255 1256 1257 void hs20_rx_deauth_imminent_notice(struct wpa_supplicant *wpa_s, u8 code, 1258 u16 reauth_delay, const char *url) 1259 { 1260 if (!wpa_sm_pmf_enabled(wpa_s->wpa)) { 1261 wpa_printf(MSG_DEBUG, "HS 2.0: Ignore deauthentication imminent notice since PMF was not enabled"); 1262 return; 1263 } 1264 1265 wpa_msg(wpa_s, MSG_INFO, HS20_DEAUTH_IMMINENT_NOTICE "%u %u %s", 1266 code, reauth_delay, url); 1267 1268 if (code == HS20_DEAUTH_REASON_CODE_BSS) { 1269 wpa_printf(MSG_DEBUG, "HS 2.0: Add BSS to blacklist"); 1270 wpa_blacklist_add(wpa_s, wpa_s->bssid); 1271 /* TODO: For now, disable full ESS since some drivers may not 1272 * support disabling per BSS. */ 1273 if (wpa_s->current_ssid) { 1274 struct os_reltime now; 1275 os_get_reltime(&now); 1276 if (now.sec + reauth_delay <= 1277 wpa_s->current_ssid->disabled_until.sec) 1278 return; 1279 wpa_printf(MSG_DEBUG, "HS 2.0: Disable network for %u seconds (BSS)", 1280 reauth_delay); 1281 wpa_s->current_ssid->disabled_until.sec = 1282 now.sec + reauth_delay; 1283 } 1284 } 1285 1286 if (code == HS20_DEAUTH_REASON_CODE_ESS && wpa_s->current_ssid) { 1287 struct os_reltime now; 1288 os_get_reltime(&now); 1289 if (now.sec + reauth_delay <= 1290 wpa_s->current_ssid->disabled_until.sec) 1291 return; 1292 wpa_printf(MSG_DEBUG, "HS 2.0: Disable network for %u seconds", 1293 reauth_delay); 1294 wpa_s->current_ssid->disabled_until.sec = 1295 now.sec + reauth_delay; 1296 } 1297 } 1298 1299 1300 void hs20_rx_t_c_acceptance(struct wpa_supplicant *wpa_s, const char *url) 1301 { 1302 if (!wpa_sm_pmf_enabled(wpa_s->wpa)) { 1303 wpa_printf(MSG_DEBUG, 1304 "HS 2.0: Ignore Terms and Conditions Acceptance since PMF was not enabled"); 1305 return; 1306 } 1307 1308 wpa_msg(wpa_s, MSG_INFO, HS20_T_C_ACCEPTANCE "%s", url); 1309 } 1310 1311 1312 void hs20_init(struct wpa_supplicant *wpa_s) 1313 { 1314 dl_list_init(&wpa_s->icon_head); 1315 } 1316 1317 1318 void hs20_deinit(struct wpa_supplicant *wpa_s) 1319 { 1320 eloop_cancel_timeout(hs20_continue_icon_fetch, wpa_s, NULL); 1321 hs20_free_osu_prov(wpa_s); 1322 if (wpa_s->icon_head.next) 1323 hs20_del_icon(wpa_s, NULL, NULL); 1324 } 1325