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 <jouni@qca.qualcomm.com>
This commit is contained in:
Jouni Malinen 2017-10-08 12:32:02 +03:00 committed by Jouni Malinen
parent 675112df1b
commit e8b9649012
3 changed files with 147 additions and 6 deletions

View file

@ -2745,7 +2745,7 @@ static int wpa_supplicant_ctrl_iface_scan_result(
{ {
char *pos, *end; char *pos, *end;
int ret; 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); mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID);
p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE); 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) if (osen_ie)
pos = wpa_supplicant_ie_txt(pos, end, "OSEN", pos = wpa_supplicant_ie_txt(pos, end, "OSEN",
osen_ie, 2 + osen_ie[1]); 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); pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
if (!ie && !ie2 && !osen_ie && (bss->caps & IEEE80211_CAP_PRIVACY)) { if (!ie && !ie2 && !osen_ie && (bss->caps & IEEE80211_CAP_PRIVACY)) {
ret = os_snprintf(pos, end - pos, "[WEP]"); 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; size_t i;
int ret; int ret;
char *pos, *end; char *pos, *end;
const u8 *ie, *ie2, *osen_ie, *mesh; const u8 *ie, *ie2, *osen_ie, *mesh, *owe;
pos = buf; pos = buf;
end = buf + buflen; end = buf + buflen;
@ -4576,6 +4584,15 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
if (osen_ie) if (osen_ie)
pos = wpa_supplicant_ie_txt(pos, end, "OSEN", pos = wpa_supplicant_ie_txt(pos, end, "OSEN",
osen_ie, 2 + osen_ie[1]); 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); pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
if (!ie && !ie2 && !osen_ie && if (!ie && !ie2 && !osen_ie &&
(bss->caps & IEEE80211_CAP_PRIVACY)) { (bss->caps & IEEE80211_CAP_PRIVACY)) {

View file

@ -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, struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
int i, struct wpa_bss *bss, int i, struct wpa_bss *bss,
struct wpa_ssid *group, struct wpa_ssid *group,
@ -893,6 +967,8 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
#ifdef CONFIG_MBO #ifdef CONFIG_MBO
const u8 *assoc_disallow; const u8 *assoc_disallow;
#endif /* CONFIG_MBO */ #endif /* CONFIG_MBO */
const u8 *match_ssid;
size_t match_ssid_len;
ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
wpa_ie_len = ie ? ie[1] : 0; 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) if (debug_print)
wpa_dbg(wpa_s, MSG_DEBUG, " skip - SSID not known"); wpa_dbg(wpa_s, MSG_DEBUG, " skip - SSID not known");
return NULL; return NULL;
@ -954,7 +1034,7 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
return NULL; 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) if (debug_print)
wpa_dbg(wpa_s, MSG_DEBUG, " skip - SSID disallowed"); wpa_dbg(wpa_s, MSG_DEBUG, " skip - SSID disallowed");
return NULL; return NULL;
@ -1009,8 +1089,8 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
check_ssid = 0; check_ssid = 0;
if (check_ssid && if (check_ssid &&
(bss->ssid_len != ssid->ssid_len || (match_ssid_len != ssid->ssid_len ||
os_memcmp(bss->ssid, ssid->ssid, bss->ssid_len) != 0)) { os_memcmp(match_ssid, ssid->ssid, match_ssid_len) != 0)) {
if (debug_print) if (debug_print)
wpa_dbg(wpa_s, MSG_DEBUG, wpa_dbg(wpa_s, MSG_DEBUG,
" skip - SSID mismatch"); " skip - SSID mismatch");

View file

@ -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_supplicant_get_ssid - Get a pointer to the current network structure
* @wpa_s: Pointer to wpa_supplicant data * @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; return entry;
#endif /* CONFIG_WPS */ #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 && if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
entry->ssid_len == 0 && entry->ssid_len == 0 &&
os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0) os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)