Use os_get_random() for Shared Key authentication challenge
[mech_eap.git] / src / ap / ieee802_11.c
index 01b514e..ca3065b 100644 (file)
@@ -207,16 +207,17 @@ static u16 auth_shared_key(struct hostapd_data *hapd, struct sta_info *sta,
                if (!sta->challenge) {
                        /* Generate a pseudo-random challenge */
                        u8 key[8];
-                       struct os_time now;
-                       int r;
+
                        sta->challenge = os_zalloc(WLAN_AUTH_CHALLENGE_LEN);
                        if (sta->challenge == NULL)
                                return WLAN_STATUS_UNSPECIFIED_FAILURE;
 
-                       os_get_time(&now);
-                       r = os_random();
-                       os_memcpy(key, &now.sec, 4);
-                       os_memcpy(key + 4, &r, 4);
+                       if (os_get_random(key, sizeof(key)) < 0) {
+                               os_free(sta->challenge);
+                               sta->challenge = NULL;
+                               return WLAN_STATUS_UNSPECIFIED_FAILURE;
+                       }
+
                        rc4_skip(key, sizeof(key), 0,
                                 sta->challenge, WLAN_AUTH_CHALLENGE_LEN);
                }
@@ -665,7 +666,7 @@ static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
                        wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
                        sta->sae->state = SAE_ACCEPTED;
                        wpa_auth_pmksa_add_sae(hapd->wpa_auth, sta->addr,
-                                              sta->sae->pmk);
+                                              sta->sae->pmk, sta->sae->pmkid);
                }
                break;
        case SAE_ACCEPTED:
@@ -886,7 +887,7 @@ static void handle_auth(struct hostapd_data *hapd,
        u16 fc;
        const u8 *challenge = NULL;
        u32 session_timeout, acct_interim_interval;
-       int vlan_id = 0;
+       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;
@@ -894,6 +895,8 @@ static void handle_auth(struct hostapd_data *hapd,
        char *radius_cui = NULL;
        u16 seq_ctrl;
 
+       os_memset(&vlan_id, 0, sizeof(vlan_id));
+
        if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) {
                wpa_printf(MSG_INFO, "handle_auth - too short payload (len=%lu)",
                           (unsigned long) len);
@@ -1067,13 +1070,22 @@ static void handle_auth(struct hostapd_data *hapd,
                                       seq_ctrl);
                        return;
                }
+#ifdef CONFIG_MESH
+               if ((hapd->conf->mesh & MESH_ENABLED) &&
+                   sta->plink_state == PLINK_BLOCKED) {
+                       wpa_printf(MSG_DEBUG, "Mesh peer " MACSTR
+                                  " is blocked - drop Authentication frame",
+                                  MAC2STR(mgmt->sa));
+                       return;
+               }
+#endif /* CONFIG_MESH */
        } else {
 #ifdef CONFIG_MESH
                if (hapd->conf->mesh & MESH_ENABLED) {
                        /* if the mesh peer is not available, we don't do auth.
                         */
                        wpa_printf(MSG_DEBUG, "Mesh peer " MACSTR
-                                  " not yet known - drop Authentiation frame",
+                                  " not yet known - drop Authentication frame",
                                   MAC2STR(mgmt->sa));
                        /*
                         * Save a copy of the frame so that it can be processed
@@ -1095,19 +1107,23 @@ static void handle_auth(struct hostapd_data *hapd,
        sta->last_seq_ctrl = seq_ctrl;
        sta->last_subtype = WLAN_FC_STYPE_AUTH;
 
-       if (vlan_id > 0) {
-               if (!hostapd_vlan_id_valid(hapd->conf->vlan, vlan_id)) {
-                       hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
-                                      HOSTAPD_LEVEL_INFO, "Invalid VLAN ID "
-                                      "%d received from RADIUS server",
-                                      vlan_id);
-                       resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
-                       goto fail;
-               }
-               sta->vlan_id = vlan_id;
+       if (vlan_id.notempty &&
+           !hostapd_vlan_valid(hapd->conf->vlan, &vlan_id)) {
                hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
-                              HOSTAPD_LEVEL_INFO, "VLAN ID %d", sta->vlan_id);
+                              HOSTAPD_LEVEL_INFO,
+                              "Invalid VLAN %d%s received from RADIUS server",
+                              vlan_id.untagged,
+                              vlan_id.tagged[0] ? "+" : "");
+               resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+               goto fail;
+       }
+       if (ap_sta_set_vlan(hapd, sta, &vlan_id) < 0) {
+               resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+               goto fail;
        }
+       if (sta->vlan_id)
+               hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
+                              HOSTAPD_LEVEL_INFO, "VLAN ID %d", sta->vlan_id);
 
        hostapd_free_psk_list(sta->psk);
        if (hapd->conf->wpa_psk_radius != PSK_RADIUS_IGNORED) {
@@ -1737,7 +1753,7 @@ static void send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
 #endif /* CONFIG_WPS */
 
 #ifdef CONFIG_P2P
-       if (sta->p2p_ie) {
+       if (sta->p2p_ie && hapd->p2p_group) {
                struct wpabuf *p2p_resp_ie;
                enum p2p_status_code status;
                switch (status_code) {
@@ -2010,7 +2026,7 @@ static void handle_disassoc(struct hostapd_data *hapd,
        /* Stop Accounting and IEEE 802.1X sessions, but leave the STA
         * authenticated. */
        accounting_sta_stop(hapd, sta);
-       ieee802_1x_free_station(sta);
+       ieee802_1x_free_station(hapd, sta);
        if (sta->ipaddr)
                hostapd_drv_br_delete_ip_neigh(hapd, 4, (u8 *) &sta->ipaddr);
        ap_sta_ip6addr_del(hapd, sta);