]> git.ipfire.org Git - thirdparty/hostap.git/blobdiff - src/ap/ieee802_11.c
Introduce and add key_flag
[thirdparty/hostap.git] / src / ap / ieee802_11.c
index 401f907f47348278c087238cc11ad923306fe1af..cd61077944a9624c5a59c82ca53dad5e3d5b6353 100644 (file)
@@ -98,7 +98,8 @@ u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid)
                num++;
        if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht)
                num++;
-       if (hapd->conf->sae_pwe == 1)
+       if (hapd->conf->sae_pwe == 1 &&
+           wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt))
                num++;
        if (num > 8) {
                /* rest of the rates are encoded in Extended supported
@@ -126,7 +127,9 @@ u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid)
                *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY;
        }
 
-       if (hapd->conf->sae_pwe == 1 && count < 8) {
+       if (hapd->conf->sae_pwe == 1 &&
+           wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
+           count < 8) {
                count++;
                *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_SAE_H2E_ONLY;
        }
@@ -148,7 +151,8 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
                num++;
        if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht)
                num++;
-       if (hapd->conf->sae_pwe == 1)
+       if (hapd->conf->sae_pwe == 1 &&
+           wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt))
                num++;
        if (num <= 8)
                return eid;
@@ -179,7 +183,8 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
                        *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY;
        }
 
-       if (hapd->conf->sae_pwe == 1) {
+       if (hapd->conf->sae_pwe == 1 &&
+           wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt)) {
                count++;
                if (count > 8)
                        *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_SAE_H2E_ONLY;
@@ -311,7 +316,7 @@ static u16 auth_shared_key(struct hostapd_data *hapd, struct sta_info *sta,
 #endif /* CONFIG_NO_RC4 */
 
 
-static int send_auth_reply(struct hostapd_data *hapd,
+static int send_auth_reply(struct hostapd_data *hapd, struct sta_info *sta,
                           const u8 *dst, const u8 *bssid,
                           u16 auth_alg, u16 auth_transaction, u16 resp,
                           const u8 *ies, size_t ies_len, const char *dbg)
@@ -344,7 +349,37 @@ static int send_auth_reply(struct hostapd_data *hapd,
                   " auth_alg=%d auth_transaction=%d resp=%d (IE len=%lu) (dbg=%s)",
                   MAC2STR(dst), auth_alg, auth_transaction,
                   resp, (unsigned long) ies_len, dbg);
-       if (hostapd_drv_send_mlme(hapd, reply, rlen, 0) < 0)
+#ifdef CONFIG_TESTING_OPTIONS
+#ifdef CONFIG_SAE
+       if (hapd->conf->sae_confirm_immediate == 2 &&
+           auth_alg == WLAN_AUTH_SAE) {
+               if (auth_transaction == 1 &&
+                   (resp == WLAN_STATUS_SUCCESS ||
+                    resp == WLAN_STATUS_SAE_HASH_TO_ELEMENT)) {
+                       wpa_printf(MSG_DEBUG,
+                                  "TESTING: Postpone SAE Commit transmission until Confirm is ready");
+                       os_free(sta->sae_postponed_commit);
+                       sta->sae_postponed_commit = buf;
+                       sta->sae_postponed_commit_len = rlen;
+                       return WLAN_STATUS_SUCCESS;
+               }
+
+               if (auth_transaction == 2 && sta && sta->sae_postponed_commit) {
+                       wpa_printf(MSG_DEBUG,
+                                  "TESTING: Send postponed SAE Commit first, immediately followed by SAE Confirm");
+                       if (hostapd_drv_send_mlme(hapd,
+                                                 sta->sae_postponed_commit,
+                                                 sta->sae_postponed_commit_len,
+                                                 0, NULL, 0, 0) < 0)
+                               wpa_printf(MSG_INFO, "send_auth_reply: send failed");
+                       os_free(sta->sae_postponed_commit);
+                       sta->sae_postponed_commit = NULL;
+                       sta->sae_postponed_commit_len = 0;
+               }
+       }
+#endif /* CONFIG_SAE */
+#endif /* CONFIG_TESTING_OPTIONS */
+       if (hostapd_drv_send_mlme(hapd, reply, rlen, 0, NULL, 0, 0) < 0)
                wpa_printf(MSG_INFO, "send_auth_reply: send failed");
        else
                reply_res = WLAN_STATUS_SUCCESS;
@@ -364,7 +399,7 @@ static void handle_auth_ft_finish(void *ctx, const u8 *dst, const u8 *bssid,
        struct sta_info *sta;
        int reply_res;
 
-       reply_res = send_auth_reply(hapd, dst, bssid, WLAN_AUTH_FT,
+       reply_res = send_auth_reply(hapd, NULL, dst, bssid, WLAN_AUTH_FT,
                                    auth_transaction, status, ies, ies_len,
                                    "auth-ft-finish");
 
@@ -403,7 +438,8 @@ static void sae_set_state(struct sta_info *sta, enum sae_state state,
 
 
 static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd,
-                                            struct sta_info *sta, int update)
+                                            struct sta_info *sta, int update,
+                                            int status_code)
 {
        struct wpabuf *buf;
        const char *password = NULL;
@@ -417,6 +453,11 @@ static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd,
                use_pt = sta->sae->tmp->h2e;
        }
 
+       if (status_code == WLAN_STATUS_SUCCESS)
+               use_pt = 0;
+       else if (status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT)
+               use_pt = 1;
+
        for (pw = hapd->conf->sae_passwords; pw; pw = pw->next) {
                if (!is_broadcast_ether_addr(pw->peer_addr) &&
                    os_memcmp(pw->peer_addr, sta->addr, ETH_ALEN) != 0)
@@ -489,13 +530,13 @@ static struct wpabuf * auth_build_sae_confirm(struct hostapd_data *hapd,
 
 static int auth_sae_send_commit(struct hostapd_data *hapd,
                                struct sta_info *sta,
-                               const u8 *bssid, int update)
+                               const u8 *bssid, int update, int status_code)
 {
        struct wpabuf *data;
        int reply_res;
        u16 status;
 
-       data = auth_build_sae_commit(hapd, sta, update);
+       data = auth_build_sae_commit(hapd, sta, update, status_code);
        if (!data && sta->sae->tmp && sta->sae->tmp->pw_id)
                return WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER;
        if (data == NULL)
@@ -503,7 +544,8 @@ static int auth_sae_send_commit(struct hostapd_data *hapd,
 
        status = (sta->sae->tmp && sta->sae->tmp->h2e) ?
                WLAN_STATUS_SAE_HASH_TO_ELEMENT : WLAN_STATUS_SUCCESS;
-       reply_res = send_auth_reply(hapd, sta->addr, bssid, WLAN_AUTH_SAE, 1,
+       reply_res = send_auth_reply(hapd, sta, sta->addr, bssid,
+                                   WLAN_AUTH_SAE, 1,
                                    status, wpabuf_head(data),
                                    wpabuf_len(data), "sae-send-commit");
 
@@ -524,7 +566,8 @@ static int auth_sae_send_confirm(struct hostapd_data *hapd,
        if (data == NULL)
                return WLAN_STATUS_UNSPECIFIED_FAILURE;
 
-       reply_res = send_auth_reply(hapd, sta->addr, bssid, WLAN_AUTH_SAE, 2,
+       reply_res = send_auth_reply(hapd, sta, sta->addr, bssid,
+                                   WLAN_AUTH_SAE, 2,
                                    WLAN_STATUS_SUCCESS, wpabuf_head(data),
                                    wpabuf_len(data), "sae-send-confirm");
 
@@ -693,7 +736,7 @@ static void auth_sae_retransmit_timer(void *eloop_ctx, void *eloop_data)
 
        switch (sta->sae->state) {
        case SAE_COMMITTED:
-               ret = auth_sae_send_commit(hapd, sta, hapd->own_addr, 0);
+               ret = auth_sae_send_commit(hapd, sta, hapd->own_addr, 0, -1);
                eloop_register_timeout(0,
                                       hapd->dot11RSNASAERetransPeriod * 1000,
                                       auth_sae_retransmit_timer, hapd, sta);
@@ -811,7 +854,7 @@ static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
                                sta->sae->tmp->h2e = status_code ==
                                        WLAN_STATUS_SAE_HASH_TO_ELEMENT;
                        ret = auth_sae_send_commit(hapd, sta, bssid,
-                                                  !allow_reuse);
+                                                  !allow_reuse, status_code);
                        if (ret)
                                return ret;
                        sae_set_state(sta, SAE_COMMITTED, "Sent Commit");
@@ -881,7 +924,8 @@ static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
                                return WLAN_STATUS_SUCCESS;
                        sta->sae->sync++;
 
-                       ret = auth_sae_send_commit(hapd, sta, bssid, 0);
+                       ret = auth_sae_send_commit(hapd, sta, bssid, 0,
+                                                  status_code);
                        if (ret)
                                return ret;
 
@@ -914,7 +958,8 @@ static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
                                return WLAN_STATUS_SUCCESS;
                        sta->sae->sync++;
 
-                       ret = auth_sae_send_commit(hapd, sta, bssid, 1);
+                       ret = auth_sae_send_commit(hapd, sta, bssid, 1,
+                                                  status_code);
                        if (ret)
                                return ret;
 
@@ -942,7 +987,8 @@ static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
                        *sta_removed = 1;
                } else if (auth_transaction == 1) {
                        wpa_printf(MSG_DEBUG, "SAE: Start reauthentication");
-                       ret = auth_sae_send_commit(hapd, sta, bssid, 1);
+                       ret = auth_sae_send_commit(hapd, sta, bssid, 1,
+                                                  status_code);
                        if (ret)
                                return ret;
                        sae_set_state(sta, SAE_COMMITTED, "Sent Commit");
@@ -1089,7 +1135,7 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
                wpa_printf(MSG_DEBUG, "SAE: TESTING - reflection attack");
                pos = mgmt->u.auth.variable;
                end = ((const u8 *) mgmt) + len;
-               send_auth_reply(hapd, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
+               send_auth_reply(hapd, sta, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
                                auth_transaction, resp, pos, end - pos,
                                "auth-sae-reflection-attack");
                goto remove_sta;
@@ -1097,7 +1143,7 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
 
        if (hapd->conf->sae_commit_override && auth_transaction == 1) {
                wpa_printf(MSG_DEBUG, "SAE: TESTING - commit override");
-               send_auth_reply(hapd, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
+               send_auth_reply(hapd, sta, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
                                auth_transaction, resp,
                                wpabuf_head(hapd->conf->sae_commit_override),
                                wpabuf_len(hapd->conf->sae_commit_override),
@@ -1108,8 +1154,10 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
        if (!sta->sae) {
                if (auth_transaction != 1 ||
                    !sae_status_success(hapd, status_code)) {
-                       resp = -1;
-                       goto remove_sta;
+                       wpa_printf(MSG_DEBUG, "SAE: Unexpected Status Code %u",
+                                  status_code);
+                       resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+                       goto reply;
                }
                sta->sae = os_zalloc(sizeof(*sta->sae));
                if (!sta->sae) {
@@ -1174,7 +1222,8 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
                         * Authentication frame, and the commit-scalar and
                         * COMMIT-ELEMENT previously sent.
                         */
-                       resp = auth_sae_send_commit(hapd, sta, mgmt->bssid, 0);
+                       resp = auth_sae_send_commit(hapd, sta, mgmt->bssid, 0,
+                                                   status_code);
                        if (resp != WLAN_STATUS_SUCCESS) {
                                wpa_printf(MSG_ERROR,
                                           "SAE: Failed to send commit message");
@@ -1263,9 +1312,9 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
 
                if (sta->sae->tmp &&
                    check_sae_rejected_groups(
-                           hapd, sta->sae->tmp->peer_rejected_groups) < 0) {
+                           hapd, sta->sae->tmp->peer_rejected_groups)) {
                        resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
-                       goto remove_sta;
+                       goto reply;
                }
 
                if (!token && use_sae_anti_clogging(hapd) && !allow_reuse) {
@@ -1348,7 +1397,7 @@ reply:
                        data = wpabuf_alloc_copy(pos, 2);
 
                sae_sme_send_external_auth_status(hapd, sta, resp);
-               send_auth_reply(hapd, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
+               send_auth_reply(hapd, sta, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
                                auth_transaction, resp,
                                data ? wpabuf_head(data) : (u8 *) "",
                                data ? wpabuf_len(data) : 0, "auth-sae");
@@ -1385,7 +1434,7 @@ int auth_sae_init_committed(struct hostapd_data *hapd, struct sta_info *sta)
        if (sta->sae->state != SAE_NOTHING)
                return -1;
 
-       ret = auth_sae_send_commit(hapd, sta, hapd->own_addr, 0);
+       ret = auth_sae_send_commit(hapd, sta, hapd->own_addr, 0, -1);
        if (ret)
                return -1;
 
@@ -1654,6 +1703,8 @@ void handle_auth_fils(struct hostapd_data *hapd, struct sta_info *sta,
        res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
                                  hapd->iface->freq,
                                  elems.rsn_ie - 2, elems.rsn_ie_len + 2,
+                                 elems.rsnxe ? elems.rsnxe - 2 : NULL,
+                                 elems.rsnxe ? elems.rsnxe_len + 2 : 0,
                                  elems.mdie, elems.mdie_len, NULL, 0);
        resp = wpa_res_to_status_code(res);
        if (resp != WLAN_STATUS_SUCCESS)
@@ -1987,7 +2038,7 @@ static void handle_auth_fils_finish(struct hostapd_data *hapd,
        auth_alg = (pub ||
                    resp == WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) ?
                WLAN_AUTH_FILS_SK_PFS : WLAN_AUTH_FILS_SK;
-       send_auth_reply(hapd, sta->addr, hapd->own_addr, auth_alg, 2, resp,
+       send_auth_reply(hapd, sta, sta->addr, hapd->own_addr, auth_alg, 2, resp,
                        data ? wpabuf_head(data) : (u8 *) "",
                        data ? wpabuf_len(data) : 0, "auth-fils-finish");
        wpabuf_free(data);
@@ -2031,28 +2082,18 @@ void ieee802_11_finish_fils_auth(struct hostapd_data *hapd,
 #endif /* CONFIG_FILS */
 
 
-int
-ieee802_11_allowed_address(struct hostapd_data *hapd, const u8 *addr,
-                          const u8 *msg, size_t len, u32 *session_timeout,
-                          u32 *acct_interim_interval,
-                          struct vlan_description *vlan_id,
-                          struct hostapd_sta_wpa_psk_short **psk,
-                          char **identity, char **radius_cui, int is_probe_req)
+static int ieee802_11_allowed_address(struct hostapd_data *hapd, const u8 *addr,
+                                     const u8 *msg, size_t len,
+                                     struct radius_sta *info)
 {
        int res;
 
-       os_memset(vlan_id, 0, sizeof(*vlan_id));
-       res = hostapd_allowed_address(hapd, addr, msg, len,
-                                     session_timeout, acct_interim_interval,
-                                     vlan_id, psk, identity, radius_cui,
-                                     is_probe_req);
+       res = hostapd_allowed_address(hapd, addr, msg, len, info, 0);
 
        if (res == HOSTAPD_ACL_REJECT) {
-               if (!is_probe_req)
-                       wpa_printf(MSG_DEBUG,
-                                  "Station " MACSTR
-                                  " not allowed to authenticate",
-                                  MAC2STR(addr));
+               wpa_printf(MSG_DEBUG, "Station " MACSTR
+                          " not allowed to authenticate",
+                          MAC2STR(addr));
                return HOSTAPD_ACL_REJECT;
        }
 
@@ -2072,12 +2113,15 @@ ieee802_11_allowed_address(struct hostapd_data *hapd, const u8 *addr,
 
 static int
 ieee802_11_set_radius_info(struct hostapd_data *hapd, struct sta_info *sta,
-                          int res, u32 session_timeout,
-                          u32 acct_interim_interval,
-                          struct vlan_description *vlan_id,
-                          struct hostapd_sta_wpa_psk_short **psk,
-                          char **identity, char **radius_cui)
+                          int res, struct radius_sta *info)
 {
+       u32 session_timeout = info->session_timeout;
+       u32 acct_interim_interval = info->acct_interim_interval;
+       struct vlan_description *vlan_id = &info->vlan_id;
+       struct hostapd_sta_wpa_psk_short *psk = info->psk;
+       char *identity = info->identity;
+       char *radius_cui = info->radius_cui;
+
        if (vlan_id->notempty &&
            !hostapd_vlan_valid(hapd->conf->vlan, vlan_id)) {
                hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
@@ -2094,20 +2138,22 @@ ieee802_11_set_radius_info(struct hostapd_data *hapd, struct sta_info *sta,
                               HOSTAPD_LEVEL_INFO, "VLAN ID %d", sta->vlan_id);
 
        hostapd_free_psk_list(sta->psk);
-       if (hapd->conf->wpa_psk_radius != PSK_RADIUS_IGNORED) {
-               sta->psk = *psk;
-               *psk = NULL;
-       } else {
+       if (hapd->conf->wpa_psk_radius != PSK_RADIUS_IGNORED)
+               hostapd_copy_psk_list(&sta->psk, psk);
+       else
                sta->psk = NULL;
-       }
 
        os_free(sta->identity);
-       sta->identity = *identity;
-       *identity = NULL;
+       if (identity)
+               sta->identity = os_strdup(identity);
+       else
+               sta->identity = NULL;
 
        os_free(sta->radius_cui);
-       sta->radius_cui = *radius_cui;
-       *radius_cui = NULL;
+       if (radius_cui)
+               sta->radius_cui = os_strdup(radius_cui);
+       else
+               sta->radius_cui = NULL;
 
        if (hapd->conf->acct_interim_interval == 0 && acct_interim_interval)
                sta->acct_interim_interval = acct_interim_interval;
@@ -2135,14 +2181,10 @@ static void handle_auth(struct hostapd_data *hapd,
        int res, reply_res;
        u16 fc;
        const u8 *challenge = NULL;
-       u32 session_timeout, acct_interim_interval;
-       struct vlan_description vlan_id;
-       struct hostapd_sta_wpa_psk_short *psk = NULL;
        u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN];
        size_t resp_ies_len = 0;
-       char *identity = NULL;
-       char *radius_cui = NULL;
        u16 seq_ctrl;
+       struct radius_sta rad_info;
 
        if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) {
                wpa_printf(MSG_INFO, "handle_auth - too short payload (len=%lu)",
@@ -2293,10 +2335,8 @@ static void handle_auth(struct hostapd_data *hapd,
                }
        }
 
-       res = ieee802_11_allowed_address(
-               hapd, mgmt->sa, (const u8 *) mgmt, len, &session_timeout,
-               &acct_interim_interval, &vlan_id, &psk, &identity, &radius_cui,
-               0);
+       res = ieee802_11_allowed_address(hapd, mgmt->sa, (const u8 *) mgmt, len,
+                                        &rad_info);
        if (res == HOSTAPD_ACL_REJECT) {
                wpa_msg(hapd->msg_ctx, MSG_DEBUG,
                        "Ignore Authentication frame from " MACSTR
@@ -2379,9 +2419,7 @@ static void handle_auth(struct hostapd_data *hapd,
        sta->auth_rssi = rssi;
 #endif /* CONFIG_MBO */
 
-       res = ieee802_11_set_radius_info(
-               hapd, sta, res, session_timeout, acct_interim_interval,
-               &vlan_id, &psk, &identity, &radius_cui);
+       res = ieee802_11_set_radius_info(hapd, sta, res, &rad_info);
        if (res) {
                wpa_printf(MSG_DEBUG, "ieee802_11_set_radius_info() failed");
                resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
@@ -2523,11 +2561,7 @@ static void handle_auth(struct hostapd_data *hapd,
        }
 
  fail:
-       os_free(identity);
-       os_free(radius_cui);
-       hostapd_free_psk_list(psk);
-
-       reply_res = send_auth_reply(hapd, mgmt->sa, mgmt->bssid, auth_alg,
+       reply_res = send_auth_reply(hapd, sta, mgmt->sa, mgmt->bssid, auth_alg,
                                    auth_transaction + 1, resp, resp_ies,
                                    resp_ies_len, "handle-auth");
 
@@ -2965,7 +2999,7 @@ u16 owe_process_rsn_ie(struct hostapd_data *hapd,
        rsn_ie_len += 2;
        res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
                                  hapd->iface->freq, rsn_ie, rsn_ie_len,
-                                 NULL, 0, owe_dh, owe_dh_len);
+                                 NULL, 0, NULL, 0, owe_dh, owe_dh_len);
        status = wpa_res_to_status_code(res);
        if (status != WLAN_STATUS_SUCCESS)
                goto end;
@@ -3173,6 +3207,8 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
                res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
                                          hapd->iface->freq,
                                          wpa_ie, wpa_ie_len,
+                                         elems.rsnxe ? elems.rsnxe - 2 : NULL,
+                                         elems.rsnxe ? elems.rsnxe_len + 2 : 0,
                                          elems.mdie, elems.mdie_len,
                                          elems.owe_dh, elems.owe_dh_len);
                resp = wpa_res_to_status_code(res);
@@ -3248,6 +3284,17 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
                                   MAC2STR(sta->addr), sta->auth_alg);
                        return WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
                }
+
+               if (hapd->conf->sae_pwe == 2 &&
+                   sta->auth_alg == WLAN_AUTH_SAE &&
+                   sta->sae && sta->sae->tmp && !sta->sae->tmp->h2e &&
+                   elems.rsnxe && elems.rsnxe_len >= 1 &&
+                   (elems.rsnxe[0] & BIT(WLAN_RSNX_CAPAB_SAE_H2E))) {
+                       wpa_printf(MSG_INFO, "SAE: " MACSTR
+                                  " indicates support for SAE H2E, but did not use it",
+                                  MAC2STR(sta->addr));
+                       return WLAN_STATUS_UNSPECIFIED_FAILURE;
+               }
 #endif /* CONFIG_SAE */
 
 #ifdef CONFIG_OWE
@@ -3447,7 +3494,7 @@ static void send_deauth(struct hostapd_data *hapd, const u8 *addr,
        send_len = IEEE80211_HDRLEN + sizeof(reply.u.deauth);
        reply.u.deauth.reason_code = host_to_le16(reason_code);
 
-       if (hostapd_drv_send_mlme(hapd, &reply, send_len, 0) < 0)
+       if (hostapd_drv_send_mlme(hapd, &reply, send_len, 0, NULL, 0, 0) < 0)
                wpa_printf(MSG_INFO, "Failed to send deauth: %s",
                           strerror(errno));
 }
@@ -3702,6 +3749,8 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
        }
 #endif /* CONFIG_FST */
 
+       p = hostapd_eid_rsnxe(hapd, p, buf + buflen - p);
+
 #ifdef CONFIG_OWE
        if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) &&
            sta && sta->owe_ecdh && status_code == WLAN_STATUS_SUCCESS &&
@@ -3831,7 +3880,7 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
        }
 #endif /* CONFIG_FILS */
 
-       if (hostapd_drv_send_mlme(hapd, reply, send_len, 0) < 0) {
+       if (hostapd_drv_send_mlme(hapd, reply, send_len, 0, NULL, 0, 0) < 0) {
                wpa_printf(MSG_INFO, "Failed to send assoc resp: %s",
                           strerror(errno));
                res = WLAN_STATUS_UNSPECIFIED_FAILURE;
@@ -3963,9 +4012,6 @@ static void handle_assoc(struct hostapd_data *hapd,
        int left, i;
        struct sta_info *sta;
        u8 *tmp = NULL;
-       struct hostapd_sta_wpa_psk_short *psk = NULL;
-       char *identity = NULL;
-       char *radius_cui = NULL;
 #ifdef CONFIG_FILS
        int delay_assoc = 0;
 #endif /* CONFIG_FILS */
@@ -4045,13 +4091,11 @@ static void handle_assoc(struct hostapd_data *hapd,
                    hapd->iface->current_mode->mode ==
                        HOSTAPD_MODE_IEEE80211AD) {
                        int acl_res;
-                       u32 session_timeout, acct_interim_interval;
-                       struct vlan_description vlan_id;
+                       struct radius_sta info;
 
-                       acl_res = ieee802_11_allowed_address(
-                               hapd, mgmt->sa, (const u8 *) mgmt, len,
-                               &session_timeout, &acct_interim_interval,
-                               &vlan_id, &psk, &identity, &radius_cui, 0);
+                       acl_res = ieee802_11_allowed_address(hapd, mgmt->sa,
+                                                            (const u8 *) mgmt,
+                                                            len, &info);
                        if (acl_res == HOSTAPD_ACL_REJECT) {
                                wpa_msg(hapd->msg_ctx, MSG_DEBUG,
                                        "Ignore Association Request frame from "
@@ -4076,9 +4120,7 @@ static void handle_assoc(struct hostapd_data *hapd,
                        }
 
                        acl_res = ieee802_11_set_radius_info(
-                               hapd, sta, acl_res, session_timeout,
-                               acct_interim_interval, &vlan_id, &psk,
-                               &identity, &radius_cui);
+                               hapd, sta, acl_res, &info);
                        if (acl_res) {
                                resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
                                goto fail;
@@ -4279,9 +4321,6 @@ static void handle_assoc(struct hostapd_data *hapd,
 #endif /* CONFIG_FILS */
 
  fail:
-       os_free(identity);
-       os_free(radius_cui);
-       hostapd_free_psk_list(psk);
 
        /*
         * In case of a successful response, add the station to the driver.
@@ -4671,7 +4710,7 @@ static int handle_action(struct hostapd_data *hapd,
                os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN);
                resp->u.action.category |= 0x80;
 
-               if (hostapd_drv_send_mlme(hapd, resp, len, 0) < 0) {
+               if (hostapd_drv_send_mlme(hapd, resp, len, 0, NULL, 0, 0) < 0) {
                        wpa_printf(MSG_ERROR, "IEEE 802.11: Failed to send "
                                   "Action frame");
                }
@@ -4872,8 +4911,11 @@ static void hostapd_set_wds_encryption(struct hostapd_data *hapd,
        for (i = 0; i < 4; i++) {
                if (ssid->wep.key[i] &&
                    hostapd_drv_set_key(ifname_wds, hapd, WPA_ALG_WEP, NULL, i,
-                                       i == ssid->wep.idx, NULL, 0,
-                                       ssid->wep.key[i], ssid->wep.len[i])) {
+                                       0, i == ssid->wep.idx, NULL, 0,
+                                       ssid->wep.key[i], ssid->wep.len[i],
+                                       i == ssid->wep.idx ?
+                                       KEY_FLAG_GROUP_RX_TX_DEFAULT :
+                                       KEY_FLAG_GROUP_RX_TX)) {
                        wpa_printf(MSG_WARNING,
                                   "Could not set WEP keys for WDS interface; %s",
                                   ifname_wds);