SAE: Check Status Code in Authentication frames

While other authentication algorithms mark Status Code as being Reserved
in the case of the transaction number 1, SAE does not. Check that the
Status Code indicates success before creating SAE state. In addition,
fix the mesh anti-clogging token request parsing on big endian CPUs.

Transaction number 2 (confirm) can also have non-zero Status Code to
report an error. Those should be processed, but not replied to with yet
another error message. This could happen in mesh case. Avoid a loop of
error messages by dropping the non-success case without additional
response.

In addition, don't reply to unknown transaction numbers if the status
code is non-zero. This avoids a loop of error messages if an invalid
frame where to be injected (or unlikely corruption were to occur).

Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2014-12-14 23:52:02 +02:00
parent d48b64ba6c
commit afa2ffb413

View file

@ -620,13 +620,13 @@ static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
const struct ieee80211_mgmt *mgmt, size_t len,
u8 auth_transaction)
u16 auth_transaction, u16 status_code)
{
u16 resp = WLAN_STATUS_SUCCESS;
struct wpabuf *data = NULL;
if (!sta->sae) {
if (auth_transaction != 1)
if (auth_transaction != 1 || status_code != WLAN_STATUS_SUCCESS)
return;
sta->sae = os_zalloc(sizeof(*sta->sae));
if (sta->sae == NULL)
@ -639,11 +639,12 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
size_t token_len = 0;
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
"start SAE authentication (RX commit)");
"start SAE authentication (RX commit, status=%u)",
status_code);
if ((hapd->conf->mesh & MESH_ENABLED) &&
mgmt->u.auth.status_code ==
WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ && sta->sae->tmp) {
status_code == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ &&
sta->sae->tmp) {
pos = mgmt->u.auth.variable;
end = ((const u8 *) mgmt) + len;
if (pos + sizeof(le16) > end) {
@ -687,6 +688,9 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
return;
}
if (status_code != WLAN_STATUS_SUCCESS)
return;
resp = sae_parse_commit(sta->sae, mgmt->u.auth.variable,
((const u8 *) mgmt) + len -
mgmt->u.auth.variable, &token,
@ -718,7 +722,10 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
} else if (auth_transaction == 2) {
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
"SAE authentication (RX confirm)");
"SAE authentication (RX confirm, status=%u)",
status_code);
if (status_code != WLAN_STATUS_SUCCESS)
return;
if (sta->sae->state >= SAE_CONFIRMED ||
!(hapd->conf->mesh & MESH_ENABLED)) {
if (sae_check_confirm(sta->sae, mgmt->u.auth.variable,
@ -729,12 +736,13 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
}
}
resp = sae_sm_step(hapd, sta, mgmt->bssid, auth_transaction);
} else {
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
"unexpected SAE authentication transaction %u",
auth_transaction);
"unexpected SAE authentication transaction %u (status=%u)",
auth_transaction, status_code);
if (status_code != WLAN_STATUS_SUCCESS)
return;
resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
}
@ -977,7 +985,8 @@ static void handle_auth(struct hostapd_data *hapd,
#ifdef CONFIG_SAE
case WLAN_AUTH_SAE:
#ifdef CONFIG_MESH
if (hapd->conf->mesh & MESH_ENABLED) {
if (status_code == WLAN_STATUS_SUCCESS &&
hapd->conf->mesh & MESH_ENABLED) {
if (sta->wpa_sm == NULL)
sta->wpa_sm =
wpa_auth_sta_init(hapd->wpa_auth,
@ -990,7 +999,8 @@ static void handle_auth(struct hostapd_data *hapd,
}
}
#endif /* CONFIG_MESH */
handle_auth_sae(hapd, sta, mgmt, len, auth_transaction);
handle_auth_sae(hapd, sta, mgmt, len, auth_transaction,
status_code);
return;
#endif /* CONFIG_SAE */
}