wifi-scripts: wifi-station SAE passwords with a user's file

iface_sae_stations() wrote the wifi-station SAE passwords to
/var/run/hostapd-<ifname>.sae and named that file only where the user
had not set sae_password_file. With a user's file, hostapd read that
file alone, and the wifi-station passwords never reached it.

hostapd's parse_sae_password_file() adds each line of the file to the
SAE password list, and each sae_password_file line reads one more file,
so two lines would work for hostapd. The hostapd service keeps one hash
per file option (file_fields in hostapd.uc), though, and a second line
would replace the hash of the first, so a change in one of the files
could go unnoticed. Copy the lines of the user's file into the generated
file instead, before the wifi-station entries, and always name the
generated file. Where the user's file cannot be read, keep naming it, so
hostapd reports it as before.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
Felix Fietkau committed 2026-10-08 09:50:39 +02:00
1 parent a89d1c9d7e
commit 79cb1d926f
1 file changed
+9 -1
@@ -473,10 +473,18 @@ function iface_wpa_stations(config, stas) {
set_default(config, 'wpa_psk_file', path);
}
/* the hostapd service hashes one file per option, so the user's file is
* copied */
function iface_sae_stations(config, stas) {
let path = `/var/run/hostapd-${config.ifname}.sae`;
let user_entries = config.sae_password_file ? fs.readfile(config.sae_password_file) : null;
if (config.sae_password_file && user_entries == null)
return;
let file = fs.open(path, 'w');
if (length(user_entries))
file.write(rtrim(user_entries, '\n') + '\n');
for (let k, sta in stas)
if (sta.config.mac && sta.config.key) {
for (let mac in sta.config.mac) {
@@ -492,7 +500,7 @@ function iface_sae_stations(config, stas) {
}
file.close();
set_default(config, 'sae_password_file', path);
config.sae_password_file = path;
}
function iface_eap_server(config) {