From 9bc29dcdfdee2233b2786f9f0d3959478f1e8eb2 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 26 Aug 2025 12:37:12 +0300 Subject: [PATCH] SAE: Default password binding through control interface Allow sae_track_password information to be configured through the hostapd control interface to enable synchronization across BSSs. Signed-off-by: Jouni Malinen --- hostapd/ctrl_iface.c | 24 ++++++++++++++++++ src/ap/ieee802_11.c | 60 ++++++++++++++++++++++++++++++++------------ src/ap/ieee802_11.h | 2 ++ 3 files changed, 70 insertions(+), 16 deletions(-) diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index 45c498a34..e6ea1dc3a 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -4070,6 +4070,25 @@ fail: #endif /* CONFIG_NAN_USD */ +#ifdef CONFIG_SAE +static int hostapd_ctrl_iface_sae_password_bind(struct hostapd_data *hapd, + const char *cmd) +{ + u8 addr[ETH_ALEN]; + const char *password; + + if (hwaddr_aton(cmd, addr)) + return -1; + password = os_strchr(cmd, ' '); + if (!password) + return -1; + password++; + + return sae_password_bind(hapd, addr, password); +} +#endif /* CONFIG_SAE */ + + static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd, char *buf, char *reply, int reply_size, @@ -4673,6 +4692,11 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd, reply_len = -1; #endif /* CONFIG_TESTING_OPTIONS */ #endif /* CONFIG_IEEE80211BE */ +#ifdef CONFIG_SAE + } else if (os_strncmp(buf, "SAE_PASSWORD_BIND ", 18) == 0) { + if (hostapd_ctrl_iface_sae_password_bind(hapd, buf + 18)) + reply_len = -1; +#endif /* CONFIG_SAE */ } else { os_memcpy(reply, "UNKNOWN COMMAND\n", 16); reply_len = 16; diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 9f27ba87c..f157c9492 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -560,6 +560,28 @@ static bool has_sae_success_seen(struct hostapd_data *hapd, } +static int sae_password_mark_success(struct hostapd_data *hapd, + struct sae_password_entry *pw, + const u8 *addr) +{ + if (in_mac_addr_list(pw->success_mac, pw->num_success_mac, addr)) + return 0; + + if (!pw->success_mac) { + pw->success_mac = os_zalloc(hapd->conf->sae_track_password * + ETH_ALEN); + if (!pw->success_mac) + return -1; + pw->num_success_mac = hapd->conf->sae_track_password; + } + + os_memcpy(&pw->success_mac[pw->next_success_mac * ETH_ALEN], addr, + ETH_ALEN); + pw->next_success_mac = (pw->next_success_mac + 1) % pw->num_success_mac; + return 0; +} + + static void sae_password_track_success(struct hostapd_data *hapd, struct sta_info *sta) { @@ -572,22 +594,7 @@ static void sae_password_track_success(struct hostapd_data *hapd, if (!pw) return; - if (in_mac_addr_list(pw->success_mac, - pw->num_success_mac, - sta->addr)) - return; - - if (!pw->success_mac) { - pw->success_mac = os_zalloc(hapd->conf->sae_track_password * - ETH_ALEN); - if (!pw->success_mac) - return; - pw->num_success_mac = hapd->conf->sae_track_password; - } - - os_memcpy(&pw->success_mac[pw->next_success_mac * ETH_ALEN], sta->addr, - ETH_ALEN); - pw->next_success_mac = (pw->next_success_mac + 1) % pw->num_success_mac; + sae_password_mark_success(hapd, pw, sta->addr); } @@ -624,6 +631,27 @@ static bool sae_password_track_fail(struct hostapd_data *hapd, } +int sae_password_bind(struct hostapd_data *hapd, const u8 *addr, + const char *password) +{ + struct sae_password_entry *pw; + + if (!hapd->conf->sae_track_password) + return -1; + + for (pw = hapd->conf->sae_passwords; pw; pw = pw->next) { + if (pw->identifier || + !is_broadcast_ether_addr(pw->peer_addr) || + os_strcmp(password, pw->password) != 0) + continue; + + return sae_password_mark_success(hapd, pw, addr); + } + + return -1; +} + + const char * sae_get_password(struct hostapd_data *hapd, struct sta_info *sta, const char *rx_id, diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h index 31bc0249b..a2bd583be 100644 --- a/src/ap/ieee802_11.h +++ b/src/ap/ieee802_11.h @@ -290,6 +290,8 @@ u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end, const u8 *known_bss, size_t known_bss_len, u8 *rnr_eid, u8 *rnr_count, u8 **rnr_offset, size_t rnr_len); bool hostapd_is_multiple_link_mld(struct hostapd_data *hapd); +int sae_password_bind(struct hostapd_data *hapd, const u8 *addr, + const char *password); const char * sae_get_password(struct hostapd_data *hapd, struct sta_info *sta, const char *rx_id, struct sae_password_entry **pw_entry, -- 2.47.3