From baf4c8637988f77009392935541fcb7f1c6344a7 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 5 Oct 2018 20:51:51 +0300 Subject: [PATCH] HS 2.0: Request and process OSU Providers NAI List ANQP-element Extend wpa_supplicant to use a separate OSU_NAI information from OSU Providers NAI List ANQP-element instead of the OSU_NAI information from OSU Providers list ANQP-element when connecting to the shared BSS (Single SSID) for OSU. Signed-off-by: Jouni Malinen --- wpa_supplicant/bss.c | 2 ++ wpa_supplicant/bss.h | 1 + wpa_supplicant/ctrl_iface.c | 2 ++ wpa_supplicant/hs20_supplicant.c | 41 ++++++++++++++++++++++++++++++++ wpa_supplicant/interworking.c | 4 +++- 5 files changed, 49 insertions(+), 1 deletion(-) diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c index 5aa07eac4..3a41db98e 100644 --- a/wpa_supplicant/bss.c +++ b/wpa_supplicant/bss.c @@ -103,6 +103,7 @@ static struct wpa_bss_anqp * wpa_bss_anqp_clone(struct wpa_bss_anqp *anqp) ANQP_DUP(hs20_operating_class); ANQP_DUP(hs20_osu_providers_list); ANQP_DUP(hs20_operator_icon_metadata); + ANQP_DUP(hs20_osu_providers_nai_list); #endif /* CONFIG_HS20 */ #undef ANQP_DUP @@ -187,6 +188,7 @@ static void wpa_bss_anqp_free(struct wpa_bss_anqp *anqp) wpabuf_free(anqp->hs20_operating_class); wpabuf_free(anqp->hs20_osu_providers_list); wpabuf_free(anqp->hs20_operator_icon_metadata); + wpabuf_free(anqp->hs20_osu_providers_nai_list); #endif /* CONFIG_HS20 */ os_free(anqp); diff --git a/wpa_supplicant/bss.h b/wpa_supplicant/bss.h index 917938502..5251b2c35 100644 --- a/wpa_supplicant/bss.h +++ b/wpa_supplicant/bss.h @@ -51,6 +51,7 @@ struct wpa_bss_anqp { struct wpabuf *hs20_operating_class; struct wpabuf *hs20_osu_providers_list; struct wpabuf *hs20_operator_icon_metadata; + struct wpabuf *hs20_osu_providers_nai_list; #endif /* CONFIG_HS20 */ }; diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index fe39c25b7..945ab9c4d 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -4809,6 +4809,8 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, anqp->hs20_osu_providers_list); pos = anqp_add_hex(pos, end, "hs20_operator_icon_metadata", anqp->hs20_operator_icon_metadata); + pos = anqp_add_hex(pos, end, "hs20_osu_providers_nai_list", + anqp->hs20_osu_providers_nai_list); #endif /* CONFIG_HS20 */ dl_list_for_each(elem, &anqp->anqp_elems, diff --git a/wpa_supplicant/hs20_supplicant.c b/wpa_supplicant/hs20_supplicant.c index e00c5afa3..f4187900e 100644 --- a/wpa_supplicant/hs20_supplicant.c +++ b/wpa_supplicant/hs20_supplicant.c @@ -54,6 +54,7 @@ struct osu_provider { char server_uri[256]; u32 osu_methods; /* bit 0 = OMA-DM, bit 1 = SOAP-XML SPP */ char osu_nai[256]; + char osu_nai2[256]; struct osu_lang_string friendly_name[OSU_MAX_ITEMS]; size_t friendly_name_count; struct osu_lang_string serv_desc[OSU_MAX_ITEMS]; @@ -673,6 +674,15 @@ void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s, wpabuf_alloc_copy(pos, slen); } break; + case HS20_STYPE_OSU_PROVIDERS_NAI_LIST: + wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR + " OSU Providers NAI List", MAC2STR(sa)); + if (anqp) { + wpabuf_free(anqp->hs20_osu_providers_nai_list); + anqp->hs20_osu_providers_nai_list = + wpabuf_alloc_copy(pos, slen); + } + break; default: wpa_printf(MSG_DEBUG, "HS20: Unsupported subtype %u", subtype); break; @@ -759,6 +769,8 @@ static void hs20_osu_fetch_done(struct wpa_supplicant *wpa_s) } if (osu->osu_nai[0]) fprintf(f, "osu_nai=%s\n", osu->osu_nai); + if (osu->osu_nai2[0]) + fprintf(f, "osu_nai2=%s\n", osu->osu_nai2); for (j = 0; j < osu->friendly_name_count; j++) { fprintf(f, "friendly_name=%s:%s\n", osu->friendly_name[j].lang, @@ -1103,6 +1115,35 @@ void hs20_osu_icon_fetch(struct wpa_supplicant *wpa_s) "extra data after OSU Providers", (int) (end - pos)); } + + prov_anqp = bss->anqp->hs20_osu_providers_nai_list; + if (!prov_anqp) + continue; + wpa_printf(MSG_DEBUG, + "HS 2.0: Parsing OSU Providers NAI List from " + MACSTR, MAC2STR(bss->bssid)); + wpa_hexdump_buf(MSG_DEBUG, "HS 2.0: OSU Providers NAI List", + prov_anqp); + pos = wpabuf_head(prov_anqp); + end = pos + wpabuf_len(prov_anqp); + num_providers = 0; + while (end - pos > 0) { + len = *pos++; + if (end - pos < len) { + wpa_printf(MSG_DEBUG, + "HS 2.0: Not enough room for OSU_NAI"); + break; + } + if (num_providers >= wpa_s->osu_prov_count) { + wpa_printf(MSG_DEBUG, + "HS 2.0: Ignore unexpected OSU Provider NAI List entries"); + break; + } + os_memcpy(wpa_s->osu_prov[num_providers].osu_nai2, + pos, len); + pos += len; + num_providers++; + } } wpa_s->fetch_osu_icon_in_progress = 1; diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c index f3f88d391..60c8be9a6 100644 --- a/wpa_supplicant/interworking.c +++ b/wpa_supplicant/interworking.c @@ -303,8 +303,10 @@ static int interworking_anqp_send_req(struct wpa_supplicant *wpa_s, wpabuf_put_u8(extra, HS20_STYPE_CONNECTION_CAPABILITY); if (all) wpabuf_put_u8(extra, HS20_STYPE_OPERATING_CLASS); - if (all) + if (all) { wpabuf_put_u8(extra, HS20_STYPE_OSU_PROVIDERS_LIST); + wpabuf_put_u8(extra, HS20_STYPE_OSU_PROVIDERS_NAI_LIST); + } gas_anqp_set_element_len(extra, len_pos); } #endif /* CONFIG_HS20 */