From e8b96490122cc53d54a06433e0284061b63700ac Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 8 Oct 2017 12:32:02 +0300 Subject: [PATCH] OWE: Transition mode support on station side Add support for using the OWE Transition Mode element to determine the hidden SSID for an OWE BSS that is used in transition mode. Signed-off-by: Jouni Malinen --- wpa_supplicant/ctrl_iface.c | 21 +++++++- wpa_supplicant/events.c | 88 +++++++++++++++++++++++++++++++-- wpa_supplicant/wpa_supplicant.c | 44 +++++++++++++++++ 3 files changed, 147 insertions(+), 6 deletions(-) diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 40c0c4582..0fc5642e9 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -2745,7 +2745,7 @@ static int wpa_supplicant_ctrl_iface_scan_result( { char *pos, *end; int ret; - const u8 *ie, *ie2, *osen_ie, *p2p, *mesh; + const u8 *ie, *ie2, *osen_ie, *p2p, *mesh, *owe; mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID); p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE); @@ -2776,6 +2776,14 @@ static int wpa_supplicant_ctrl_iface_scan_result( if (osen_ie) pos = wpa_supplicant_ie_txt(pos, end, "OSEN", osen_ie, 2 + osen_ie[1]); + owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE); + if (owe) { + ret = os_snprintf(pos, end - pos, + ie2 ? "[OWE-TRANS]" : "[OWE-TRANS-OPEN]"); + if (os_snprintf_error(end - pos, ret)) + return -1; + pos += ret; + } pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss); if (!ie && !ie2 && !osen_ie && (bss->caps & IEEE80211_CAP_PRIVACY)) { ret = os_snprintf(pos, end - pos, "[WEP]"); @@ -4452,7 +4460,7 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, size_t i; int ret; char *pos, *end; - const u8 *ie, *ie2, *osen_ie, *mesh; + const u8 *ie, *ie2, *osen_ie, *mesh, *owe; pos = buf; end = buf + buflen; @@ -4576,6 +4584,15 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, if (osen_ie) pos = wpa_supplicant_ie_txt(pos, end, "OSEN", osen_ie, 2 + osen_ie[1]); + owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE); + if (owe) { + ret = os_snprintf( + pos, end - pos, + ie2 ? "[OWE-TRANS]" : "[OWE-TRANS-OPEN]"); + if (os_snprintf_error(end - pos, ret)) + return 0; + pos += ret; + } pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss); if (!ie && !ie2 && !osen_ie && (bss->caps & IEEE80211_CAP_PRIVACY)) { diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 500e66c78..65d453c3c 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -879,6 +879,80 @@ static int addr_in_list(const u8 *addr, const u8 *list, size_t num) } +static void owe_trans_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, + const u8 **ret_ssid, size_t *ret_ssid_len) +{ +#ifdef CONFIG_OWE + const u8 *owe, *pos, *end, *bssid; + u8 ssid_len; + struct wpa_bss *open_bss; + + owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE); + if (!owe || !wpa_bss_get_ie(bss, WLAN_EID_RSN)) + return; + + pos = owe + 6; + end = owe + 2 + owe[1]; + + if (end - pos < ETH_ALEN + 1) + return; + bssid = pos; + pos += ETH_ALEN; + ssid_len = *pos++; + if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN) + return; + + /* Match the profile SSID against the OWE transition mode SSID on the + * open network. */ + wpa_dbg(wpa_s, MSG_DEBUG, "OWE: transition mode BSSID: " MACSTR + " SSID: %s", MAC2STR(bssid), wpa_ssid_txt(pos, ssid_len)); + *ret_ssid = pos; + *ret_ssid_len = ssid_len; + + if (bss->ssid_len > 0) + return; + + open_bss = wpa_bss_get_bssid_latest(wpa_s, bssid); + if (!open_bss) + return; + if (ssid_len != open_bss->ssid_len || + os_memcmp(pos, open_bss->ssid, ssid_len) != 0) { + wpa_dbg(wpa_s, MSG_DEBUG, + "OWE: transition mode SSID mismatch: %s", + wpa_ssid_txt(open_bss->ssid, open_bss->ssid_len)); + return; + } + + owe = wpa_bss_get_vendor_ie(open_bss, OWE_IE_VENDOR_TYPE); + if (!owe || wpa_bss_get_ie(open_bss, WLAN_EID_RSN)) { + wpa_dbg(wpa_s, MSG_DEBUG, + "OWE: transition mode open BSS unexpected info"); + return; + } + + pos = owe + 6; + end = owe + 2 + owe[1]; + + if (end - pos < ETH_ALEN + 1) + return; + if (os_memcmp(pos, bss->bssid, ETH_ALEN) != 0) { + wpa_dbg(wpa_s, MSG_DEBUG, + "OWE: transition mode BSSID mismatch: " MACSTR, + MAC2STR(pos)); + return; + } + pos += ETH_ALEN; + ssid_len = *pos++; + if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN) + return; + wpa_dbg(wpa_s, MSG_DEBUG, "OWE: learned transition mode OWE SSID: %s", + wpa_ssid_txt(pos, ssid_len)); + os_memcpy(bss->ssid, pos, ssid_len); + bss->ssid_len = ssid_len; +#endif /* CONFIG_OWE */ +} + + struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, int i, struct wpa_bss *bss, struct wpa_ssid *group, @@ -893,6 +967,8 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, #ifdef CONFIG_MBO const u8 *assoc_disallow; #endif /* CONFIG_MBO */ + const u8 *match_ssid; + size_t match_ssid_len; ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); wpa_ie_len = ie ? ie[1] : 0; @@ -942,7 +1018,11 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, } } - if (bss->ssid_len == 0) { + match_ssid = bss->ssid; + match_ssid_len = bss->ssid_len; + owe_trans_ssid(wpa_s, bss, &match_ssid, &match_ssid_len); + + if (match_ssid_len == 0) { if (debug_print) wpa_dbg(wpa_s, MSG_DEBUG, " skip - SSID not known"); return NULL; @@ -954,7 +1034,7 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, return NULL; } - if (disallowed_ssid(wpa_s, bss->ssid, bss->ssid_len)) { + if (disallowed_ssid(wpa_s, match_ssid, match_ssid_len)) { if (debug_print) wpa_dbg(wpa_s, MSG_DEBUG, " skip - SSID disallowed"); return NULL; @@ -1009,8 +1089,8 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, check_ssid = 0; if (check_ssid && - (bss->ssid_len != ssid->ssid_len || - os_memcmp(bss->ssid, ssid->ssid, bss->ssid_len) != 0)) { + (match_ssid_len != ssid->ssid_len || + os_memcmp(match_ssid, ssid->ssid, match_ssid_len) != 0)) { if (debug_print) wpa_dbg(wpa_s, MSG_DEBUG, " skip - SSID mismatch"); diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index ddfdaf71a..e463709ef 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -3533,6 +3533,41 @@ int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level, } +#ifdef CONFIG_OWE +static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid, + const u8 *entry_ssid, size_t entry_ssid_len) +{ + const u8 *owe, *pos, *end; + u8 ssid_len; + struct wpa_bss *bss; + + /* Check network profile SSID aganst the SSID in the + * OWE Transition Mode element. */ + + bss = wpa_bss_get_bssid_latest(wpa_s, bssid); + if (!bss) + return 0; + + owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE); + if (!owe) + return 0; + + pos = owe + 6; + end = owe + 2 + owe[1]; + + if (end - pos < ETH_ALEN + 1) + return 0; + pos += ETH_ALEN; + ssid_len = *pos++; + if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN) + return 0; + + return entry_ssid_len == ssid_len && + os_memcmp(pos, entry_ssid, ssid_len) == 0; +} +#endif /* CONFIG_OWE */ + + /** * wpa_supplicant_get_ssid - Get a pointer to the current network structure * @wpa_s: Pointer to wpa_supplicant data @@ -3581,6 +3616,15 @@ struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s) return entry; #endif /* CONFIG_WPS */ +#ifdef CONFIG_OWE + if (!wpas_network_disabled(wpa_s, entry) && + owe_trans_ssid_match(wpa_s, bssid, entry->ssid, + entry->ssid_len) && + (!entry->bssid_set || + os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)) + return entry; +#endif /* CONFIG_OWE */ + if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set && entry->ssid_len == 0 && os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)