[PATCH/RFC 11/18] auth: handle auth frames for mesh ifaces
Bob Copeland
me
Sun Jul 13 22:19:16 PDT 2014
From: Thomas Pedersen <thomas at noack.us>
Modify wpa_supplicant/hostapd logic to allow SAE auth on Mesh
interfaces.
Signed-off-by: Javier Lopez <jlopex at gmail.com>
Signed-off-by: Javier Cardona <javier at cozybit.com>
Signed-hostap: Thomas Pedersen <thomas at noack.us>
---
src/ap/ieee802_11.c | 96 +++++++++++++++++++++++++++++++++++++++++++++--------
src/ap/wpa_auth.c | 16 +++++++++
src/ap/wpa_auth.h | 3 ++
3 files changed, 101 insertions(+), 14 deletions(-)
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index de1ee5e..ac99eff 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -446,6 +446,7 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
{
u16 resp = WLAN_STATUS_SUCCESS;
struct wpabuf *data = NULL;
+ Boolean send_auth = 0;
if (!sta->sae) {
if (auth_transaction != 1)
@@ -456,12 +457,21 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
sta->sae->state = SAE_NOTHING;
}
+ if (sta->sae->state == SAE_ACCEPTED && auth_transaction == 1) {
+ wpa_printf(MSG_DEBUG, "SAE: remove the STA "
+ "(" MACSTR ") doing reauthentication",
+ MAC2STR(sta->addr));
+ ap_free_sta(hapd, sta);
+ return;
+ }
+
if (auth_transaction == 1) {
const u8 *token = NULL;
size_t token_len = 0;
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
"start SAE authentication (RX commit)");
+
resp = sae_parse_commit(sta->sae, mgmt->u.auth.variable,
((const u8 *) mgmt) + len -
mgmt->u.auth.variable, &token,
@@ -481,22 +491,45 @@ 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 {
+ goto reply;
+ }
+ if (sta->sae->state == SAE_NOTHING ||
+ sta->sae->state == SAE_CONFIRMED) {
+ /* (re)send commit to peer */
data = auth_process_sae_commit(hapd, sta);
if (data == NULL)
resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
- else
- sta->sae->state = SAE_COMMITTED;
+ sta->auth_alg = WLAN_AUTH_SAE;
+ send_auth_reply(hapd, mgmt->sa, mgmt->bssid,
+ WLAN_AUTH_SAE, 1, resp,
+ data ? wpabuf_head(data) : (u8 *) "",
+ data ? wpabuf_len(data) : 0);
+ wpabuf_free(data);
+ }
+ /* SAE_NOTHING / SAE_COMMITTED / SAE_CONFIRMED */
+ if (sae_process_commit(sta->sae) < 0) {
+ wpa_printf(MSG_DEBUG,
+ "SAE: process peer commit failed");
+ resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ } else {
+ /* send confirm and transition to CONFIRMED */
+ 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_NOTHING ||
+ sta->sae->state == SAE_COMMITTED) {
hostapd_logger(hapd, sta->addr,
HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
"SAE confirm before commit");
- resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
- goto failed;
+ return;
}
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
@@ -508,10 +541,17 @@ 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);
+ 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;
+ }
+
+ send_auth = 1;
data = auth_build_sae_confirm(hapd, sta);
if (data == NULL)
resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
@@ -527,14 +567,14 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
auth_transaction);
resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
}
-
-failed:
+reply:
sta->auth_alg = WLAN_AUTH_SAE;
-
send_auth_reply(hapd, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
auth_transaction, resp,
data ? wpabuf_head(data) : (u8 *) "",
data ? wpabuf_len(data) : 0);
+ if (send_auth)
+ wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
wpabuf_free(data);
}
#endif /* CONFIG_SAE */
@@ -649,10 +689,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 auth. */
+ 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) {
@@ -737,6 +787,21 @@ 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,
+ "SAE: 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 */
@@ -1758,6 +1823,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 2bb8aab..75d4607 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),
@@ -1519,6 +1528,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,
--
2.0.0.rc2
More information about the Hostap
mailing list