]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
OWE: Transition mode support on station side
authorJouni Malinen <jouni@qca.qualcomm.com>
Sun, 8 Oct 2017 09:32:02 +0000 (12:32 +0300)
committerJouni Malinen <j@w1.fi>
Sun, 8 Oct 2017 14:12:35 +0000 (17:12 +0300)
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>
wpa_supplicant/ctrl_iface.c
wpa_supplicant/events.c
wpa_supplicant/wpa_supplicant.c

index 40c0c458242a206577e2556d6a9492d7d5ecf919..0fc5642e9779eafff51998e8b208f95a0b3f711f 100644 (file)
@@ -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)) {
index 500e66c78797c9aad3a95109a19573b1422db2a5..65d453c3cb17e2539606f68b9068b4ded893cf86 100644 (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,
                                     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");
index ddfdaf71a70c414b5df5dc7092b7b513c1b5d593..e463709efd5925bfccc7b6e4cd3e33ba2862299f 100644 (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_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)