]> git.ipfire.org Git - thirdparty/hostap.git/blobdiff - wpa_supplicant/interworking.c
tests: sigma_dut controlled STA and beacon protection
[thirdparty/hostap.git] / wpa_supplicant / interworking.c
index 15b1016c099727e2b2ebf3e84573cd5ca7ae49f5..49b9907b079cf1f33ce76af7edb1bd86e0a78af9 100644 (file)
@@ -148,6 +148,8 @@ static int cred_with_roaming_consortium(struct wpa_supplicant *wpa_s)
                        return 1;
                if (cred->required_roaming_consortium_len)
                        return 1;
+               if (cred->num_roaming_consortiums)
+                       return 1;
        }
        return 0;
 }
@@ -174,7 +176,7 @@ static int cred_with_nai_realm(struct wpa_supplicant *wpa_s)
                        continue;
                if (!cred->eap_method)
                        return 1;
-               if (cred->realm && cred->roaming_consortium_len == 0)
+               if (cred->realm)
                        return 1;
        }
        return 0;
@@ -301,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 */
@@ -312,7 +316,7 @@ static int interworking_anqp_send_req(struct wpa_supplicant *wpa_s,
        if (buf == NULL)
                return -1;
 
-       res = gas_query_req(wpa_s->gas, bss->bssid, bss->freq, buf,
+       res = gas_query_req(wpa_s->gas, bss->bssid, bss->freq, 0, buf,
                            interworking_anqp_resp_cb, wpa_s);
        if (res < 0) {
                wpa_msg(wpa_s, MSG_DEBUG, "ANQP: Failed to send Query Request");
@@ -954,6 +958,7 @@ static int interworking_set_hs20_params(struct wpa_supplicant *wpa_s,
                        "WPA-EAP WPA-EAP-SHA256" : "WPA-EAP";
        if (wpa_config_set(ssid, "key_mgmt", key_mgmt, 0) < 0 ||
            wpa_config_set(ssid, "proto", "RSN", 0) < 0 ||
+           wpa_config_set(ssid, "ieee80211w", "1", 0) < 0 ||
            wpa_config_set(ssid, "pairwise", "CCMP", 0) < 0)
                return -1;
        return 0;
@@ -1145,6 +1150,23 @@ static int roaming_consortium_match(const u8 *ie, const struct wpabuf *anqp,
 }
 
 
+static int cred_roaming_consortiums_match(const u8 *ie,
+                                         const struct wpabuf *anqp,
+                                         const struct wpa_cred *cred)
+{
+       unsigned int i;
+
+       for (i = 0; i < cred->num_roaming_consortiums; i++) {
+               if (roaming_consortium_match(ie, anqp,
+                                            cred->roaming_consortiums[i],
+                                            cred->roaming_consortiums_len[i]))
+                       return 1;
+       }
+
+       return 0;
+}
+
+
 static int cred_no_required_oi_match(struct wpa_cred *cred, struct wpa_bss *bss)
 {
        const u8 *ie;
@@ -1349,27 +1371,35 @@ static struct wpa_cred * interworking_credentials_available_roaming_consortium(
 {
        struct wpa_cred *cred, *selected = NULL;
        const u8 *ie;
+       const struct wpabuf *anqp;
        int is_excluded = 0;
 
        ie = wpa_bss_get_ie(bss, WLAN_EID_ROAMING_CONSORTIUM);
+       anqp = bss->anqp ? bss->anqp->roaming_consortium : NULL;
 
-       if (ie == NULL &&
-           (bss->anqp == NULL || bss->anqp->roaming_consortium == NULL))
+       if (!ie && !anqp)
                return NULL;
 
        if (wpa_s->conf->cred == NULL)
                return NULL;
 
        for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
-               if (cred->roaming_consortium_len == 0)
+               if (cred->roaming_consortium_len == 0 &&
+                   cred->num_roaming_consortiums == 0)
+                       continue;
+
+               if (!cred->eap_method)
                        continue;
 
-               if (!roaming_consortium_match(ie,
-                                             bss->anqp ?
-                                             bss->anqp->roaming_consortium :
-                                             NULL,
-                                             cred->roaming_consortium,
-                                             cred->roaming_consortium_len))
+               if ((cred->roaming_consortium_len == 0 ||
+                    !roaming_consortium_match(ie, anqp,
+                                              cred->roaming_consortium,
+                                              cred->roaming_consortium_len)) &&
+                   !cred_roaming_consortiums_match(ie, anqp, cred) &&
+                   (cred->required_roaming_consortium_len == 0 ||
+                    !roaming_consortium_match(
+                            ie, anqp, cred->required_roaming_consortium,
+                            cred->required_roaming_consortium_len)))
                        continue;
 
                if (cred_no_required_oi_match(cred, bss))
@@ -1524,7 +1554,7 @@ static int interworking_set_eap_params(struct wpa_ssid *ssid,
                                  cred->domain_suffix_match) < 0)
                return -1;
 
-       ssid->eap.ocsp = cred->ocsp;
+       ssid->eap.cert.ocsp = cred->ocsp;
 
        return 0;
 }
@@ -1535,6 +1565,9 @@ static int interworking_connect_roaming_consortium(
        struct wpa_bss *bss, int only_add)
 {
        struct wpa_ssid *ssid;
+       const u8 *ie;
+       const struct wpabuf *anqp;
+       unsigned int i;
 
        wpa_msg(wpa_s, MSG_DEBUG, "Interworking: Connect with " MACSTR
                " based on roaming consortium match", MAC2STR(bss->bssid));
@@ -1564,6 +1597,26 @@ static int interworking_connect_roaming_consortium(
        if (interworking_set_hs20_params(wpa_s, ssid) < 0)
                goto fail;
 
+       ie = wpa_bss_get_ie(bss, WLAN_EID_ROAMING_CONSORTIUM);
+       anqp = bss->anqp ? bss->anqp->roaming_consortium : NULL;
+       for (i = 0; (ie || anqp) && i < cred->num_roaming_consortiums; i++) {
+               if (!roaming_consortium_match(
+                           ie, anqp, cred->roaming_consortiums[i],
+                           cred->roaming_consortiums_len[i]))
+                       continue;
+
+               ssid->roaming_consortium_selection =
+                       os_malloc(cred->roaming_consortiums_len[i]);
+               if (!ssid->roaming_consortium_selection)
+                       goto fail;
+               os_memcpy(ssid->roaming_consortium_selection,
+                         cred->roaming_consortiums[i],
+                         cred->roaming_consortiums_len[i]);
+               ssid->roaming_consortium_selection_len =
+                       cred->roaming_consortiums_len[i];
+               break;
+       }
+
        if (cred->eap_method == NULL) {
                wpa_msg(wpa_s, MSG_DEBUG,
                        "Interworking: No EAP method set for credential using roaming consortium");
@@ -1897,7 +1950,7 @@ static struct wpa_cred * interworking_credentials_available_3gpp(
                size_t len;
                wpa_msg(wpa_s, MSG_DEBUG,
                        "Interworking: IMSI not available - try to read again through eap_proxy");
-               wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol,
+               wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
                                                             wpa_s->imsi,
                                                             &len);
                if (wpa_s->mnc_len > 0) {
@@ -2209,7 +2262,7 @@ int interworking_home_sp_cred(struct wpa_supplicant *wpa_s,
                        realm++;
                wpa_msg(wpa_s, MSG_DEBUG,
                        "Interworking: Search for match with SIM/USIM domain %s",
-                       realm);
+                       realm ? realm : "[NULL]");
                if (realm &&
                    domain_name_list_contains(domain_names, realm, 1))
                        return 1;
@@ -2580,7 +2633,6 @@ static void interworking_next_anqp_fetch(struct wpa_supplicant *wpa_s)
 {
        struct wpa_bss *bss;
        int found = 0;
-       const u8 *ie;
 
        wpa_printf(MSG_DEBUG, "Interworking: next_anqp_fetch - "
                   "fetch_anqp_in_progress=%d fetch_osu_icon_in_progress=%d",
@@ -2603,8 +2655,7 @@ static void interworking_next_anqp_fetch(struct wpa_supplicant *wpa_s)
        dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
                if (!(bss->caps & IEEE80211_CAP_ESS))
                        continue;
-               ie = wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB);
-               if (ie == NULL || ie[1] < 4 || !(ie[5] & 0x80))
+               if (!wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_INTERWORKING))
                        continue; /* AP does not support Interworking */
                if (disallowed_bssid(wpa_s, bss->bssid) ||
                    disallowed_ssid(wpa_s, bss->ssid, bss->ssid_len))
@@ -2625,7 +2676,8 @@ static void interworking_next_anqp_fetch(struct wpa_supplicant *wpa_s)
                        found++;
                        bss->flags |= WPA_BSS_ANQP_FETCH_TRIED;
                        wpa_msg(wpa_s, MSG_INFO, "Starting ANQP fetch for "
-                               MACSTR, MAC2STR(bss->bssid));
+                               MACSTR " (HESSID " MACSTR ")",
+                               MAC2STR(bss->bssid), MAC2STR(bss->hessid));
                        interworking_anqp_send_req(wpa_s, bss);
                        break;
                }
@@ -2738,6 +2790,7 @@ int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst,
                if (mbo) {
                        if (wpabuf_resize(&extra_buf, wpabuf_len(mbo))) {
                                wpabuf_free(extra_buf);
+                               wpabuf_free(mbo);
                                return -1;
                        }
                        wpabuf_put_buf(extra_buf, mbo);
@@ -2751,7 +2804,7 @@ int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst,
        if (buf == NULL)
                return -1;
 
-       res = gas_query_req(wpa_s->gas, dst, freq, buf, anqp_resp_cb, wpa_s);
+       res = gas_query_req(wpa_s->gas, dst, freq, 0, buf, anqp_resp_cb, wpa_s);
        if (res < 0) {
                wpa_msg(wpa_s, MSG_DEBUG, "ANQP: Failed to send Query Request");
                wpabuf_free(buf);
@@ -2800,6 +2853,31 @@ static void anqp_add_extra(struct wpa_supplicant *wpa_s,
 }
 
 
+static void interworking_parse_venue_url(struct wpa_supplicant *wpa_s,
+                                        const u8 *data, size_t len)
+{
+       const u8 *pos = data, *end = data + len;
+       char url[255];
+
+       while (end - pos >= 2) {
+               u8 slen, num;
+
+               slen = *pos++;
+               if (slen < 1 || slen > end - pos) {
+                       wpa_printf(MSG_DEBUG,
+                                  "ANQP: Truncated Venue URL Duple field");
+                       return;
+               }
+
+               num = *pos++;
+               os_memcpy(url, pos, slen - 1);
+               url[slen - 1] = '\0';
+               wpa_msg(wpa_s, MSG_INFO, RX_VENUE_URL "%u %s", num, url);
+               pos += slen - 1;
+       }
+}
+
+
 static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
                                            struct wpa_bss *bss, const u8 *sa,
                                            u16 info_id,
@@ -2906,6 +2984,18 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
                }
                break;
 #endif /* CONFIG_FILS */
+       case ANQP_VENUE_URL:
+               wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR " Venue URL",
+                       MAC2STR(sa));
+               anqp_add_extra(wpa_s, anqp, info_id, pos, slen);
+
+               if (!pmf_in_use(wpa_s, sa)) {
+                       wpa_printf(MSG_DEBUG,
+                                  "ANQP: Ignore Venue URL since PMF was not enabled");
+                       break;
+               }
+               interworking_parse_venue_url(wpa_s, pos, slen);
+               break;
        case ANQP_VENDOR_SPECIFIC:
                if (slen < 3)
                        return;
@@ -3153,7 +3243,7 @@ int gas_send_request(struct wpa_supplicant *wpa_s, const u8 *dst,
        } else
                wpabuf_put_le16(buf, 0);
 
-       res = gas_query_req(wpa_s->gas, dst, freq, buf, gas_resp_cb, wpa_s);
+       res = gas_query_req(wpa_s->gas, dst, freq, 0, buf, gas_resp_cb, wpa_s);
        if (res < 0) {
                wpa_msg(wpa_s, MSG_DEBUG, "GAS: Failed to send Query Request");
                wpabuf_free(buf);