If a commit message with a different but known password ID is received,
switch to this ID.
Signed-off-by: Peter Astrand <peter.astrand@xxxxxxxxxxxx>
---
src/ap/ieee802_11.c | 69 ++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 65 insertions(+), 4 deletions(-)
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 114d1f574..4d9787e12 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -459,6 +459,20 @@ static void handle_auth_ft_finish(void *ctx, const u8 *dst, const u8 *bssid,
#ifdef CONFIG_SAE
+static bool str_eq_or_null(const char *s1, const char *s2)
+{
+ if (s1) {
+ if (s2) {
+ return os_strcmp(s1, s2) == 0;
+ }
+ return false;
+ }
+ if (s2) {
+ return false;
+ }
+ return true;
+}
+
static void sae_set_state(struct sta_info *sta, enum sae_state state,
const char *reason)
{
@@ -502,10 +516,7 @@ static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd,
if (!is_broadcast_ether_addr(pw->peer_addr) &&
os_memcmp(pw->peer_addr, sta->addr, ETH_ALEN) != 0)
continue;
- if ((rx_id && !pw->identifier) || (!rx_id && pw->identifier))
- continue;
- if (rx_id && pw->identifier &&
- os_strcmp(rx_id, pw->identifier) != 0)
+ if (!str_eq_or_null(rx_id, pw->identifier))
continue;
password = pw->password;
pt = pw->pt;
@@ -1234,6 +1245,7 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
int default_groups[] = { 19, 0 };
const u8 *pos, *end;
int sta_removed = 0;
+ char *saved_pw_id = NULL;
if (!groups)
groups = default_groups;
@@ -1385,12 +1397,61 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
}
}
+ /* With the sae.c API, it is not possible to acquire
+ the incoming id when unknown-identifier is
+ returned. Also, unknown-identifier is not returned
+ if "tmp" had no ID, but the incoming packet
+ has. Clear pw_id and manually check.
+ unknown-identifier will not be returned. */
+ if (hapd->conf->mesh & MESH_ENABLED && sta->sae->tmp && sta->sae->tmp->pw_id) {
+ saved_pw_id = os_strdup(sta->sae->tmp->pw_id);
+ os_free(sta->sae->tmp->pw_id);
+ sta->sae->tmp->pw_id = NULL;
+ }
+
resp = sae_parse_commit(sta->sae, mgmt->u.auth.variable,
((const u8 *) mgmt) + len -
mgmt->u.auth.variable, &token,
&token_len, groups, status_code ==
WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
status_code == WLAN_STATUS_SAE_PK);
+
+ if (hapd->conf->mesh & MESH_ENABLED &&
+ resp == WLAN_STATUS_SUCCESS && !str_eq_or_null(saved_pw_id, sta->sae->tmp->pw_id)) {
+ /* Password identifier mismatch */
+ struct sae_password_entry *pw;
+
+ /* id has been updated. If known, send new commit with this id */
+ for (pw = hapd->conf->sae_passwords; pw; pw = pw->next) {
+ if (str_eq_or_null(pw->identifier, sta->sae->tmp->pw_id))
+ break;
+ }
+ if (pw) {
+ resp = auth_sae_send_commit(hapd, sta, mgmt->bssid, 1,
+ status_code);
+ if (resp != WLAN_STATUS_SUCCESS) {
+ wpa_printf(MSG_ERROR,
+ "SAE: Failed to send commit message");
+ os_free(saved_pw_id);
+ goto remove_sta;
+ }
+ sae_set_state(sta, SAE_COMMITTED,
+ "Sent Commit (Switching Password ID)");
+ } else {
+ wpa_msg(hapd->msg_ctx, MSG_INFO,
+ WPA_EVENT_SAE_UNKNOWN_PASSWORD_IDENTIFIER
+ MACSTR, MAC2STR(sta->addr));
+ if (saved_pw_id) {
+ os_free(sta->sae->tmp->pw_id);
+ sta->sae->tmp->pw_id = os_strdup(saved_pw_id);
+ }
+ }
+ os_free(saved_pw_id);
+ return;
+ }
+
+ os_free(saved_pw_id);
+
if (resp == SAE_SILENTLY_DISCARD) {
wpa_printf(MSG_DEBUG,
"SAE: Drop commit message from " MACSTR " due to reflection attack",
--
2.17.1
Br,
Peter Åstrand
_______________________________________________
Hostap mailing list
Hostap@xxxxxxxxxxxxxxxxxxx
http://lists.infradead.org/mailman/listinfo/hostap