diff mbox series

[5/6] mesh: Support for multiple SAE passwords

Message ID 5e7e6035-40fb-42b3-41ea-615d976a6d5c@lysator.liu.se
State Changes Requested
Headers show
Series [1/6] mesh: Set BSS sae_pwe from config | expand

Commit Message

Peter ├ůstrand Jan. 22, 2021, 2:59 p.m. UTC
If a commit message with a different but known password ID is received,
switch to this ID.

Signed-off-by: Peter Astrand <peter.astrand@etteplan.com>
---
 src/ap/ieee802_11.c | 69 ++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 65 insertions(+), 4 deletions(-)
diff mbox series

Patch

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",