]> git.ipfire.org Git - thirdparty/hostap.git/blobdiff - src/ap/wpa_auth.c
VLAN assignment based on used WPA/WPA2 passphrase/PSK
[thirdparty/hostap.git] / src / ap / wpa_auth.c
index 3021a8c9cad0a674b556468ec3298ebd223ad324..02f0ec6a7905a8a4f2c435abf7b259477dd561f2 100644 (file)
@@ -114,12 +114,13 @@ static inline int wpa_auth_get_eapol(struct wpa_authenticator *wpa_auth,
 static inline const u8 * wpa_auth_get_psk(struct wpa_authenticator *wpa_auth,
                                          const u8 *addr,
                                          const u8 *p2p_dev_addr,
-                                         const u8 *prev_psk, size_t *psk_len)
+                                         const u8 *prev_psk, size_t *psk_len,
+                                         int *vlan_id)
 {
        if (wpa_auth->cb->get_psk == NULL)
                return NULL;
        return wpa_auth->cb->get_psk(wpa_auth->cb_ctx, addr, p2p_dev_addr,
-                                    prev_psk, psk_len);
+                                    prev_psk, psk_len, vlan_id);
 }
 
 
@@ -251,6 +252,15 @@ static int wpa_channel_info(struct wpa_authenticator *wpa_auth,
 #endif /* CONFIG_OCV */
 
 
+static int wpa_auth_update_vlan(struct wpa_authenticator *wpa_auth,
+                               const u8 *addr, int vlan_id)
+{
+       if (!wpa_auth->cb->update_vlan)
+               return -1;
+       return wpa_auth->cb->update_vlan(wpa_auth->cb_ctx, addr, vlan_id);
+}
+
+
 static void wpa_rekey_gmk(void *eloop_ctx, void *timeout_ctx)
 {
        struct wpa_authenticator *wpa_auth = eloop_ctx;
@@ -852,13 +862,15 @@ static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data,
        int ok = 0;
        const u8 *pmk = NULL;
        size_t pmk_len;
+       int vlan_id = 0;
 
        os_memset(&PTK, 0, sizeof(PTK));
        for (;;) {
                if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
                    !wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
                        pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr,
-                                              sm->p2p_dev_addr, pmk, &pmk_len);
+                                              sm->p2p_dev_addr, pmk, &pmk_len,
+                                              &vlan_id);
                        if (pmk == NULL)
                                break;
 #ifdef CONFIG_IEEE80211R_AP
@@ -897,6 +909,11 @@ static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data,
        wpa_printf(MSG_DEBUG,
                   "WPA: Earlier SNonce resulted in matching MIC");
        sm->alt_snonce_valid = 0;
+
+       if (vlan_id && wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
+           wpa_auth_update_vlan(sm->wpa_auth, sm->addr, vlan_id) < 0)
+               return -1;
+
        os_memcpy(sm->SNonce, sm->alt_SNonce, WPA_NONCE_LEN);
        os_memcpy(&sm->PTK, &PTK, sizeof(PTK));
        sm->PTK_valid = TRUE;
@@ -2024,7 +2041,7 @@ SM_STATE(WPA_PTK, INITPSK)
 
        SM_ENTRY_MA(WPA_PTK, INITPSK, wpa_ptk);
        psk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr, NULL,
-                              &psk_len);
+                              &psk_len, NULL);
        if (psk) {
                os_memcpy(sm->PMK, psk, psk_len);
                sm->pmk_len = psk_len;
@@ -2712,6 +2729,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
        struct ieee802_1x_hdr *hdr;
        struct wpa_eapol_key *key;
        struct wpa_eapol_ie_parse kde;
+       int vlan_id;
 
        SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING, wpa_ptk);
        sm->EAPOLKeyReceived = FALSE;
@@ -2727,7 +2745,8 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
                if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
                    !wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
                        pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr,
-                                              sm->p2p_dev_addr, pmk, &pmk_len);
+                                              sm->p2p_dev_addr, pmk, &pmk_len,
+                                              &vlan_id);
                        if (pmk == NULL)
                                break;
                        psk_found = 1;
@@ -2896,6 +2915,13 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
        }
 #endif /* CONFIG_IEEE80211R_AP */
 
+       if (vlan_id && wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
+           wpa_auth_update_vlan(wpa_auth, sm->addr, vlan_id) < 0) {
+               wpa_sta_disconnect(wpa_auth, sm->addr,
+                                  WLAN_REASON_PREV_AUTH_NOT_VALID);
+               return;
+       }
+
        sm->pending_1_of_4_timeout = 0;
        eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm);
 
@@ -3335,7 +3361,7 @@ SM_STEP(WPA_PTK)
                break;
        case WPA_PTK_INITPSK:
                if (wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr,
-                                    NULL, NULL)) {
+                                    NULL, NULL, NULL)) {
                        SM_ENTER(WPA_PTK, PTKSTART);
 #ifdef CONFIG_SAE
                } else if (wpa_auth_uses_sae(sm) && sm->pmksa) {