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)