From: Thomas Pedersen <tho...@noack.us>

Modify wpa_supplicant/hostapd logic to allow SAE auth on Mesh
interfaces.

Signed-off-by: Javier Lopez <jlo...@gmail.com>
Signed-off-by: Javier Cardona <jav...@cozybit.com>
Signed-hostap: Thomas Pedersen <tho...@noack.us>
---
Still TODO: pick up Chun-Yeow Yeoh's changes

 src/ap/ieee802_11.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++-----
 src/ap/wpa_auth.c   | 16 +++++++++++
 src/ap/wpa_auth.h   |  3 +++
 3 files changed, 88 insertions(+), 7 deletions(-)

diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 14fb567..b1b4ffb 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -447,6 +447,7 @@ static void handle_auth_sae(struct hostapd_data *hapd, 
struct sta_info *sta,
 {
        u16 resp = WLAN_STATUS_SUCCESS;
        struct wpabuf *data = NULL;
+       int start_ampe = 0;
 
        if (!sta->sae) {
                if (auth_transaction != 1)
@@ -457,6 +458,18 @@ static void handle_auth_sae(struct hostapd_data *hapd, 
struct sta_info *sta,
                sta->sae->state = SAE_NOTHING;
        }
 
+#ifdef CONFIG_MESH
+       if (sta->sae->state == SAE_ACCEPTED) {
+               if (auth_transaction == 1 || auth_transaction == 2) {
+                       wpa_printf(MSG_DEBUG, "SAE: remove the STA "
+                                  "(" MACSTR ") doing reauthentication",
+                                  MAC2STR(sta->addr));
+                       ap_free_sta(hapd, sta);
+               }
+               return;
+       }
+#endif /* CONFIG_MESH */
+
        if (auth_transaction == 1) {
                const u8 *token = NULL;
                size_t token_len = 0;
@@ -482,16 +495,29 @@ static void handle_auth_sae(struct hostapd_data *hapd, 
struct sta_info *sta,
                                           MAC2STR(sta->addr));
                                data = auth_build_token_req(hapd, sta->addr);
                                resp = WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ;
-                       } else {
+                       } else if (sta->sae->state != SAE_COMMITTED) {
                                data = auth_process_sae_commit(hapd, sta);
                                if (data == NULL)
                                        resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
                                else
                                        sta->sae->state = SAE_COMMITTED;
+                       } else if (sae_process_commit(sta->sae) < 0) {
+                                       wpa_printf(MSG_DEBUG,
+                                        "SAE: Failed to process peer commit");
+                                       resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+                       } else {
+                               data = auth_build_sae_confirm(hapd, sta);
+                               if (data == NULL)
+                                       resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+                               else {
+                                       sta->sae->state = SAE_CONFIRMED;
+                                       auth_transaction = 2;
+                               }
                        }
                }
        } else if (auth_transaction == 2) {
-               if (sta->sae->state != SAE_COMMITTED) {
+               if (sta->sae->state != SAE_COMMITTED &&
+                   sta->sae->state != SAE_CONFIRMED) {
                        hostapd_logger(hapd, sta->addr,
                                       HOSTAPD_MODULE_IEEE80211,
                                       HOSTAPD_LEVEL_DEBUG,
@@ -509,10 +535,18 @@ static void handle_auth_sae(struct hostapd_data *hapd, 
struct sta_info *sta,
                } else {
                        resp = WLAN_STATUS_SUCCESS;
                        sta->flags |= WLAN_STA_AUTH;
-                       wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
                        sta->auth_alg = WLAN_AUTH_SAE;
                        mlme_authenticate_indication(hapd, sta);
 
+                       /* already confirmed */
+                       if (sta->sae->state == SAE_CONFIRMED) {
+                               sta->sae->state = SAE_ACCEPTED;
+                               sae_clear_temp_data(sta->sae);
+                               wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
+                               return;
+                       }
+
+                       start_ampe = 1;
                        data = auth_build_sae_confirm(hapd, sta);
                        if (data == NULL)
                                resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
@@ -536,6 +570,8 @@ failed:
                        auth_transaction, resp,
                        data ? wpabuf_head(data) : (u8 *) "",
                        data ? wpabuf_len(data) : 0);
+       if (start_ampe)
+               wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
        wpabuf_free(data);
 }
 #endif /* CONFIG_SAE */
@@ -650,10 +686,20 @@ static void handle_auth(struct hostapd_data *hapd,
                return;
        }
 
-       sta = ap_sta_add(hapd, mgmt->sa);
-       if (!sta) {
-               resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
-               goto fail;
+#ifdef CONFIG_MESH
+       if (hapd->conf->mesh & MESH_ENABLED) {
+               /* if the mesh peer is not available, we don't do 
authentication. */
+               sta = ap_get_sta(hapd, mgmt->sa);
+               if (!sta)
+                       return;
+       } else
+#endif /* CONFIG_MESH */
+       {
+               sta = ap_sta_add(hapd, mgmt->sa);
+               if (!sta) {
+                       resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
+                       goto fail;
+               }
        }
 
        if (vlan_id > 0) {
@@ -738,6 +784,19 @@ static void handle_auth(struct hostapd_data *hapd,
 #endif /* CONFIG_IEEE80211R */
 #ifdef CONFIG_SAE
        case WLAN_AUTH_SAE:
+#ifdef CONFIG_MESH
+               if (hapd->conf->mesh & MESH_ENABLED) {
+                       if (sta->wpa_sm == NULL)
+                               sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
+                                                               sta->addr, 
NULL);
+                       if (sta->wpa_sm == NULL) {
+                               wpa_printf(MSG_DEBUG, "FT: Failed to initialize 
WPA "
+                                          "state machine");
+                               resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+                               goto fail;
+                       }
+               }
+#endif /* CONFIG_MESH */
                handle_auth_sae(hapd, sta, mgmt, len, auth_transaction);
                return;
 #endif /* CONFIG_SAE */
@@ -1749,6 +1808,9 @@ int ieee802_11_mgmt(struct hostapd_data *hapd, const u8 
*buf, size_t len,
            !((hapd->conf->p2p & P2P_GROUP_OWNER) &&
              stype == WLAN_FC_STYPE_ACTION) &&
 #endif /* CONFIG_P2P */
+#ifdef CONFIG_MESH
+           !(hapd->conf->mesh & MESH_ENABLED) &&
+#endif /* CONFIG_MESH */
            os_memcmp(mgmt->bssid, hapd->own_addr, ETH_ALEN) != 0) {
                wpa_printf(MSG_INFO, "MGMT: BSSID=" MACSTR " not our address",
                           MAC2STR(mgmt->bssid));
diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index 77e7858..7bc9d94 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -134,6 +134,15 @@ wpa_auth_send_eapol(struct wpa_authenticator *wpa_auth, 
const u8 *addr,
                                       encrypt);
 }
 
+#ifdef CONFIG_MESH
+static inline int wpa_auth_start_ampe(struct wpa_authenticator *wpa_auth,
+                                     const u8 *addr)
+{
+       if (wpa_auth->cb.start_ampe == NULL)
+               return -1;
+       return wpa_auth->cb.start_ampe(wpa_auth->cb.ctx, addr);
+}
+#endif /* CONFIG_MESH */
 
 int wpa_auth_for_each_sta(struct wpa_authenticator *wpa_auth,
                          int (*cb)(struct wpa_state_machine *sm, void *ctx),
@@ -1517,6 +1526,13 @@ int wpa_auth_sm_event(struct wpa_state_machine *sm, 
wpa_event event)
 
        switch (event) {
        case WPA_AUTH:
+#ifdef CONFIG_MESH
+               /* PTKs are derived through AMPE */
+               if (wpa_auth_start_ampe(sm->wpa_auth, sm->addr))
+                       /* not mesh */
+                       break;
+               return 0;
+#endif /* CONFIG_MESH */
        case WPA_ASSOC:
                break;
        case WPA_DEAUTH:
diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
index 929a253..d3e9d4c 100644
--- a/src/ap/wpa_auth.h
+++ b/src/ap/wpa_auth.h
@@ -213,6 +213,9 @@ struct wpa_auth_callbacks {
        int (*add_tspec)(void *ctx, const u8 *sta_addr, u8 *tspec_ie,
                         size_t tspec_ielen);
 #endif /* CONFIG_IEEE80211R */
+#ifdef CONFIG_MESH
+       int (*start_ampe)(void *ctx, const u8 *sta_addr);
+#endif /* CONFIG_MESH */
 };
 
 struct wpa_authenticator * wpa_init(const u8 *addr,
-- 
1.9.2

_______________________________________________
Devel mailing list
Devel@lists.open80211s.org
http://lists.open80211s.org/cgi-bin/mailman/listinfo/devel

Reply via email to