]> git.ipfire.org Git - thirdparty/hostap.git/blobdiff - wpa_supplicant/config_file.c
wpa_supplicant configuration for Beacon protection
[thirdparty/hostap.git] / wpa_supplicant / config_file.c
index 06936e7279401b884da399fa16862a6ac4b830d2..29bd81f0a8ff6286fb3fd0ccdeca87af1c434043 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / Configuration backend: text file
- * Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2019, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -19,6 +19,7 @@
 #include "config.h"
 #include "base64.h"
 #include "uuid.h"
+#include "common/ieee802_1x_defs.h"
 #include "p2p/p2p.h"
 #include "eap_peer/eap_methods.h"
 #include "eap_peer/eap.h"
@@ -136,9 +137,13 @@ static int wpa_config_validate_network(struct wpa_ssid *ssid, int line)
                wpa_config_update_psk(ssid);
        }
 
+       if (ssid->disabled == 2)
+               ssid->p2p_persistent_group = 1;
+
        if ((ssid->group_cipher & WPA_CIPHER_CCMP) &&
-           !(ssid->pairwise_cipher & WPA_CIPHER_CCMP) &&
-           !(ssid->pairwise_cipher & WPA_CIPHER_NONE)) {
+           !(ssid->pairwise_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_CCMP_256 |
+                                      WPA_CIPHER_GCMP | WPA_CIPHER_GCMP_256 |
+                                      WPA_CIPHER_NONE))) {
                /* Group cipher cannot be stronger than the pairwise cipher. */
                wpa_printf(MSG_DEBUG, "Line %d: removed CCMP from group cipher"
                           " list since it was not allowed for pairwise "
@@ -155,6 +160,15 @@ static int wpa_config_validate_network(struct wpa_ssid *ssid, int line)
                errors++;
        }
 
+#ifdef CONFIG_OCV
+       if (ssid->ocv && ssid->ieee80211w == NO_MGMT_FRAME_PROTECTION) {
+               wpa_printf(MSG_ERROR,
+                          "Line %d: PMF needs to be enabled whenever using OCV",
+                          line);
+               errors++;
+       }
+#endif /* CONFIG_OCV */
+
        return errors;
 }
 
@@ -282,7 +296,7 @@ static struct wpa_config_blob * wpa_config_read_blob(FILE *f, int *line,
 {
        struct wpa_config_blob *blob;
        char buf[256], *pos;
-       unsigned char *encoded = NULL, *nencoded;
+       char *encoded = NULL, *nencoded;
        int end = 0;
        size_t encoded_len = 0, len;
 
@@ -308,7 +322,7 @@ static struct wpa_config_blob * wpa_config_read_blob(FILE *f, int *line,
                encoded_len += len;
        }
 
-       if (!end) {
+       if (!end || !encoded) {
                wpa_printf(MSG_ERROR, "Line %d: blob was not terminated "
                           "properly", *line);
                os_free(encoded);
@@ -393,7 +407,8 @@ struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp)
        if (f == NULL) {
                wpa_printf(MSG_ERROR, "Failed to open config file '%s', "
                           "error: %s", name, strerror(errno));
-               os_free(config);
+               if (config != cfgp)
+                       os_free(config);
                return NULL;
        }
 
@@ -459,7 +474,8 @@ struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp)
 
 #ifndef WPA_IGNORE_CONFIG_ERRORS
        if (errors) {
-               wpa_config_free(config);
+               if (config != cfgp)
+                       wpa_config_free(config);
                config = NULL;
                head = NULL;
        }
@@ -477,7 +493,7 @@ static void write_str(FILE *f, const char *field, struct wpa_ssid *ssid)
        if (value == NULL)
                return;
        fprintf(f, "\t%s=%s\n", field, value);
-       os_free(value);
+       str_clear_free(value);
 }
 
 
@@ -499,9 +515,25 @@ static void write_bssid(FILE *f, struct wpa_ssid *ssid)
 }
 
 
+static void write_bssid_hint(FILE *f, struct wpa_ssid *ssid)
+{
+       char *value = wpa_config_get(ssid, "bssid_hint");
+
+       if (!value)
+               return;
+       fprintf(f, "\tbssid_hint=%s\n", value);
+       os_free(value);
+}
+
+
 static void write_psk(FILE *f, struct wpa_ssid *ssid)
 {
-       char *value = wpa_config_get(ssid, "psk");
+       char *value;
+
+       if (ssid->mem_only_psk)
+               return;
+
+       value = wpa_config_get(ssid, "psk");
        if (value == NULL)
                return;
        fprintf(f, "\tpsk=%s\n", value);
@@ -573,6 +605,22 @@ static void write_group(FILE *f, struct wpa_ssid *ssid)
 }
 
 
+static void write_group_mgmt(FILE *f, struct wpa_ssid *ssid)
+{
+       char *value;
+
+       if (!ssid->group_mgmt_cipher)
+               return;
+
+       value = wpa_config_get(ssid, "group_mgmt");
+       if (!value)
+               return;
+       if (value[0])
+               fprintf(f, "\tgroup_mgmt=%s\n", value);
+       os_free(value);
+}
+
+
 static void write_auth_alg(FILE *f, struct wpa_ssid *ssid)
 {
        char *value;
@@ -657,27 +705,66 @@ static void write_psk_list(FILE *f, struct wpa_ssid *ssid)
 #endif /* CONFIG_P2P */
 
 
+#ifdef CONFIG_MACSEC
+
+static void write_mka_cak(FILE *f, struct wpa_ssid *ssid)
+{
+       char *value;
+
+       if (!(ssid->mka_psk_set & MKA_PSK_SET_CAK))
+               return;
+
+       value = wpa_config_get(ssid, "mka_cak");
+       if (!value)
+               return;
+       fprintf(f, "\tmka_cak=%s\n", value);
+       os_free(value);
+}
+
+
+static void write_mka_ckn(FILE *f, struct wpa_ssid *ssid)
+{
+       char *value;
+
+       if (!(ssid->mka_psk_set & MKA_PSK_SET_CKN))
+               return;
+
+       value = wpa_config_get(ssid, "mka_ckn");
+       if (!value)
+               return;
+       fprintf(f, "\tmka_ckn=%s\n", value);
+       os_free(value);
+}
+
+#endif /* CONFIG_MACSEC */
+
+
 static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
 {
        int i;
 
 #define STR(t) write_str(f, #t, ssid)
 #define INT(t) write_int(f, #t, ssid->t, 0)
-#define INTe(t) write_int(f, #t, ssid->eap.t, 0)
+#define INTe(t, m) write_int(f, #t, ssid->eap.m, 0)
 #define INT_DEF(t, def) write_int(f, #t, ssid->t, def)
-#define INT_DEFe(t, def) write_int(f, #t, ssid->eap.t, def)
+#define INT_DEFe(t, m, def) write_int(f, #t, ssid->eap.m, def)
 
        STR(ssid);
        INT(scan_ssid);
        write_bssid(f, ssid);
+       write_bssid_hint(f, ssid);
        write_str(f, "bssid_blacklist", ssid);
        write_str(f, "bssid_whitelist", ssid);
        write_psk(f, ssid);
+       INT(mem_only_psk);
+       STR(sae_password);
+       STR(sae_password_id);
        write_proto(f, ssid);
        write_key_mgmt(f, ssid);
        INT_DEF(bg_scan_period, DEFAULT_BG_SCAN_PERIOD);
        write_pairwise(f, ssid);
        write_group(f, ssid);
+       write_group_mgmt(f, ssid);
        write_auth_alg(f, ssid);
        STR(bgscan);
        STR(autoscan);
@@ -686,7 +773,10 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
        write_eap(f, ssid);
        STR(identity);
        STR(anonymous_identity);
+       STR(imsi_identity);
+       STR(machine_identity);
        STR(password);
+       STR(machine_password);
        STR(ca_cert);
        STR(ca_path);
        STR(client_cert);
@@ -694,6 +784,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
        STR(private_key_passwd);
        STR(dh_file);
        STR(subject_match);
+       STR(check_cert_subject);
        STR(altsubject_match);
        STR(domain_suffix_match);
        STR(domain_match);
@@ -704,11 +795,24 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
        STR(private_key2_passwd);
        STR(dh_file2);
        STR(subject_match2);
+       STR(check_cert_subject2);
        STR(altsubject_match2);
        STR(domain_suffix_match2);
        STR(domain_match2);
+       STR(machine_ca_cert);
+       STR(machine_ca_path);
+       STR(machine_client_cert);
+       STR(machine_private_key);
+       STR(machine_private_key_passwd);
+       STR(machine_dh_file);
+       STR(machine_subject_match);
+       STR(machine_check_cert_subject);
+       STR(machine_altsubject_match);
+       STR(machine_domain_suffix_match);
+       STR(machine_domain_match);
        STR(phase1);
        STR(phase2);
+       STR(machine_phase2);
        STR(pcsc);
        STR(pin);
        STR(engine_id);
@@ -720,11 +824,12 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
        STR(engine2_id);
        STR(cert2_id);
        STR(ca_cert2_id);
-       INTe(engine);
-       INTe(engine2);
+       INTe(engine, cert.engine);
+       INTe(engine2, phase2_cert.engine);
+       INTe(machine_engine, machine_cert.engine);
        INT_DEF(eapol_flags, DEFAULT_EAPOL_FLAGS);
        STR(openssl_ciphers);
-       INTe(erp);
+       INTe(erp, erp);
 #endif /* IEEE8021X_EAPOL */
        for (i = 0; i < 4; i++)
                write_wep_key(f, i, ssid);
@@ -733,22 +838,35 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
 #ifdef IEEE8021X_EAPOL
        INT_DEF(eap_workaround, DEFAULT_EAP_WORKAROUND);
        STR(pac_file);
-       INT_DEFe(fragment_size, DEFAULT_FRAGMENT_SIZE);
-       INTe(ocsp);
-       INT_DEFe(sim_num, DEFAULT_USER_SELECTED_SIM);
+       INT_DEFe(fragment_size, fragment_size, DEFAULT_FRAGMENT_SIZE);
+       INTe(ocsp, cert.ocsp);
+       INTe(ocsp2, phase2_cert.ocsp);
+       INTe(machine_ocsp, machine_cert.ocsp);
+       INT_DEFe(sim_num, sim_num, DEFAULT_USER_SELECTED_SIM);
 #endif /* IEEE8021X_EAPOL */
        INT(mode);
        INT(no_auto_peer);
        INT(frequency);
+       INT(enable_edmg);
+       INT(edmg_channel);
        INT(fixed_freq);
+#ifdef CONFIG_ACS
+       INT(acs);
+#endif /* CONFIG_ACS */
        write_int(f, "proactive_key_caching", ssid->proactive_key_caching, -1);
        INT(disabled);
-       INT(peerkey);
        INT(mixed_cell);
-#ifdef CONFIG_IEEE80211W
+       INT(vht);
+       INT_DEF(ht, 1);
+       INT(ht40);
+       INT_DEF(max_oper_chwidth, DEFAULT_MAX_OPER_CHWIDTH);
+       INT(vht_center_freq1);
+       INT(vht_center_freq2);
+       INT(pbss);
+       INT(wps_disabled);
+       INT(fils_dh_group);
        write_int(f, "ieee80211w", ssid->ieee80211w,
                  MGMT_FRAME_PROTECTION_DEFAULT);
-#endif /* CONFIG_IEEE80211W */
        STR(id_str);
 #ifdef CONFIG_P2P
        write_go_p2p_dev_addr(f, ssid);
@@ -760,9 +878,17 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
        INT(beacon_int);
 #ifdef CONFIG_MACSEC
        INT(macsec_policy);
+       write_mka_cak(f, ssid);
+       write_mka_ckn(f, ssid);
+       INT(macsec_integ_only);
+       INT(macsec_replay_protect);
+       INT(macsec_replay_window);
+       INT(macsec_port);
+       INT_DEF(mka_priority, DEFAULT_PRIO_NOT_KEY_SERVER);
 #endif /* CONFIG_MACSEC */
 #ifdef CONFIG_HS20
        INT(update_identifier);
+       STR(roaming_consortium_selection);
 #endif /* CONFIG_HS20 */
        write_int(f, "mac_addr", ssid->mac_addr, -1);
 #ifdef CONFIG_MESH
@@ -771,15 +897,31 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
        INT_DEF(dot11MeshRetryTimeout, DEFAULT_MESH_RETRY_TIMEOUT);
        INT_DEF(dot11MeshConfirmTimeout, DEFAULT_MESH_CONFIRM_TIMEOUT);
        INT_DEF(dot11MeshHoldingTimeout, DEFAULT_MESH_HOLDING_TIMEOUT);
+       INT_DEF(mesh_rssi_threshold, DEFAULT_MESH_RSSI_THRESHOLD);
 #endif /* CONFIG_MESH */
        INT(wpa_ptk_rekey);
+       INT(group_rekey);
        INT(ignore_broadcast_ssid);
+#ifdef CONFIG_DPP
+       STR(dpp_connector);
+       STR(dpp_netaccesskey);
+       INT(dpp_netaccesskey_expiry);
+       STR(dpp_csign);
+#endif /* CONFIG_DPP */
+       INT(owe_group);
+       INT(owe_only);
+       INT(owe_ptk_workaround);
+       INT(multi_ap_backhaul_sta);
+       INT(ft_eap_pmksa_caching);
+       INT(beacon_prot);
 #ifdef CONFIG_HT_OVERRIDES
        INT_DEF(disable_ht, DEFAULT_DISABLE_HT);
        INT_DEF(disable_ht40, DEFAULT_DISABLE_HT40);
        INT_DEF(disable_sgi, DEFAULT_DISABLE_SGI);
        INT_DEF(disable_ldpc, DEFAULT_DISABLE_LDPC);
        INT(ht40_intolerant);
+       INT_DEF(tx_stbc, DEFAULT_TX_STBC);
+       INT_DEF(rx_stbc, DEFAULT_RX_STBC);
        INT_DEF(disable_max_amsdu, DEFAULT_DISABLE_MAX_AMSDU);
        INT_DEF(ampdu_factor, DEFAULT_AMPDU_FACTOR);
        INT_DEF(ampdu_density, DEFAULT_AMPDU_DENSITY);
@@ -936,6 +1078,20 @@ static void wpa_config_write_cred(FILE *f, struct wpa_cred *cred)
                fprintf(f, "\n");
        }
 
+       if (cred->num_roaming_consortiums) {
+               size_t j;
+
+               fprintf(f, "\troaming_consortiums=\"");
+               for (i = 0; i < cred->num_roaming_consortiums; i++) {
+                       if (i > 0)
+                               fprintf(f, ",");
+                       for (j = 0; j < cred->roaming_consortiums_len[i]; j++)
+                               fprintf(f, "%02x",
+                                       cred->roaming_consortiums[i][j]);
+               }
+               fprintf(f, "\"\n");
+       }
+
        if (cred->sim_num != DEFAULT_USER_SELECTED_SIM)
                fprintf(f, "\tsim_num=%d\n", cred->sim_num);
 }
@@ -944,7 +1100,7 @@ static void wpa_config_write_cred(FILE *f, struct wpa_cred *cred)
 #ifndef CONFIG_NO_CONFIG_BLOBS
 static int wpa_config_write_blob(FILE *f, struct wpa_config_blob *blob)
 {
-       unsigned char *encoded;
+       char *encoded;
 
        encoded = base64_encode(blob->data, blob->len, NULL);
        if (encoded == NULL)
@@ -1010,13 +1166,13 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
        if (config->driver_param)
                fprintf(f, "driver_param=%s\n", config->driver_param);
        if (config->dot11RSNAConfigPMKLifetime)
-               fprintf(f, "dot11RSNAConfigPMKLifetime=%d\n",
+               fprintf(f, "dot11RSNAConfigPMKLifetime=%u\n",
                        config->dot11RSNAConfigPMKLifetime);
        if (config->dot11RSNAConfigPMKReauthThreshold)
-               fprintf(f, "dot11RSNAConfigPMKReauthThreshold=%d\n",
+               fprintf(f, "dot11RSNAConfigPMKReauthThreshold=%u\n",
                        config->dot11RSNAConfigPMKReauthThreshold);
        if (config->dot11RSNAConfigSATimeout)
-               fprintf(f, "dot11RSNAConfigSATimeout=%d\n",
+               fprintf(f, "dot11RSNAConfigSATimeout=%u\n",
                        config->dot11RSNAConfigSATimeout);
        if (config->update_config)
                fprintf(f, "update_config=%d\n", config->update_config);
@@ -1026,6 +1182,8 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
                uuid_bin2str(config->uuid, buf, sizeof(buf));
                fprintf(f, "uuid=%s\n", buf);
        }
+       if (config->auto_uuid)
+               fprintf(f, "auto_uuid=%d\n", config->auto_uuid);
        if (config->device_name)
                fprintf(f, "device_name=%s\n", config->device_name);
        if (config->manufacturer)
@@ -1051,6 +1209,9 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
        if (config->wps_cred_processing)
                fprintf(f, "wps_cred_processing=%d\n",
                        config->wps_cred_processing);
+       if (config->wps_cred_add_sae)
+               fprintf(f, "wps_cred_add_sae=%d\n",
+                       config->wps_cred_add_sae);
        if (config->wps_vendor_ext_m1) {
                int i, len = wpabuf_len(config->wps_vendor_ext_m1);
                const u8 *p = wpabuf_head_u8(config->wps_vendor_ext_m1);
@@ -1063,28 +1224,39 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
        }
 #endif /* CONFIG_WPS */
 #ifdef CONFIG_P2P
+       {
+               int i;
+               char _buf[WPS_DEV_TYPE_BUFSIZE], *buf;
+
+               for (i = 0; i < config->num_sec_device_types; i++) {
+                       buf = wps_dev_type_bin2str(config->sec_device_type[i],
+                                                  _buf, sizeof(_buf));
+                       if (buf)
+                               fprintf(f, "sec_device_type=%s\n", buf);
+               }
+       }
        if (config->p2p_listen_reg_class)
-               fprintf(f, "p2p_listen_reg_class=%u\n",
+               fprintf(f, "p2p_listen_reg_class=%d\n",
                        config->p2p_listen_reg_class);
        if (config->p2p_listen_channel)
-               fprintf(f, "p2p_listen_channel=%u\n",
+               fprintf(f, "p2p_listen_channel=%d\n",
                        config->p2p_listen_channel);
        if (config->p2p_oper_reg_class)
-               fprintf(f, "p2p_oper_reg_class=%u\n",
+               fprintf(f, "p2p_oper_reg_class=%d\n",
                        config->p2p_oper_reg_class);
        if (config->p2p_oper_channel)
-               fprintf(f, "p2p_oper_channel=%u\n", config->p2p_oper_channel);
+               fprintf(f, "p2p_oper_channel=%d\n", config->p2p_oper_channel);
        if (config->p2p_go_intent != DEFAULT_P2P_GO_INTENT)
-               fprintf(f, "p2p_go_intent=%u\n", config->p2p_go_intent);
+               fprintf(f, "p2p_go_intent=%d\n", config->p2p_go_intent);
        if (config->p2p_ssid_postfix)
                fprintf(f, "p2p_ssid_postfix=%s\n", config->p2p_ssid_postfix);
        if (config->persistent_reconnect)
-               fprintf(f, "persistent_reconnect=%u\n",
+               fprintf(f, "persistent_reconnect=%d\n",
                        config->persistent_reconnect);
        if (config->p2p_intra_bss != DEFAULT_P2P_INTRA_BSS)
-               fprintf(f, "p2p_intra_bss=%u\n", config->p2p_intra_bss);
+               fprintf(f, "p2p_intra_bss=%d\n", config->p2p_intra_bss);
        if (config->p2p_group_idle)
-               fprintf(f, "p2p_group_idle=%u\n", config->p2p_group_idle);
+               fprintf(f, "p2p_group_idle=%d\n", config->p2p_group_idle);
        if (config->p2p_passphrase_len)
                fprintf(f, "p2p_passphrase_len=%u\n",
                        config->p2p_passphrase_len);
@@ -1112,17 +1284,44 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
                fprintf(f, "p2p_optimize_listen_chan=%d\n",
                        config->p2p_optimize_listen_chan);
        if (config->p2p_go_ht40)
-               fprintf(f, "p2p_go_ht40=%u\n", config->p2p_go_ht40);
+               fprintf(f, "p2p_go_ht40=%d\n", config->p2p_go_ht40);
        if (config->p2p_go_vht)
-               fprintf(f, "p2p_go_vht=%u\n", config->p2p_go_vht);
+               fprintf(f, "p2p_go_vht=%d\n", config->p2p_go_vht);
+       if (config->p2p_go_he)
+               fprintf(f, "p2p_go_he=%d\n", config->p2p_go_he);
+       if (config->p2p_go_edmg)
+               fprintf(f, "p2p_go_edmg=%d\n", config->p2p_go_edmg);
+       if (config->p2p_go_ctwindow != DEFAULT_P2P_GO_CTWINDOW)
+               fprintf(f, "p2p_go_ctwindow=%d\n", config->p2p_go_ctwindow);
        if (config->p2p_disabled)
-               fprintf(f, "p2p_disabled=%u\n", config->p2p_disabled);
+               fprintf(f, "p2p_disabled=%d\n", config->p2p_disabled);
        if (config->p2p_no_group_iface)
-               fprintf(f, "p2p_no_group_iface=%u\n",
+               fprintf(f, "p2p_no_group_iface=%d\n",
                        config->p2p_no_group_iface);
        if (config->p2p_ignore_shared_freq)
-               fprintf(f, "p2p_ignore_shared_freq=%u\n",
+               fprintf(f, "p2p_ignore_shared_freq=%d\n",
                        config->p2p_ignore_shared_freq);
+       if (config->p2p_cli_probe)
+               fprintf(f, "p2p_cli_probe=%d\n", config->p2p_cli_probe);
+       if (config->p2p_go_freq_change_policy != DEFAULT_P2P_GO_FREQ_MOVE)
+               fprintf(f, "p2p_go_freq_change_policy=%u\n",
+                       config->p2p_go_freq_change_policy);
+       if (WPA_GET_BE32(config->ip_addr_go))
+               fprintf(f, "ip_addr_go=%u.%u.%u.%u\n",
+                       config->ip_addr_go[0], config->ip_addr_go[1],
+                       config->ip_addr_go[2], config->ip_addr_go[3]);
+       if (WPA_GET_BE32(config->ip_addr_mask))
+               fprintf(f, "ip_addr_mask=%u.%u.%u.%u\n",
+                       config->ip_addr_mask[0], config->ip_addr_mask[1],
+                       config->ip_addr_mask[2], config->ip_addr_mask[3]);
+       if (WPA_GET_BE32(config->ip_addr_start))
+               fprintf(f, "ip_addr_start=%u.%u.%u.%u\n",
+                       config->ip_addr_start[0], config->ip_addr_start[1],
+                       config->ip_addr_start[2], config->ip_addr_start[3]);
+       if (WPA_GET_BE32(config->ip_addr_end))
+               fprintf(f, "ip_addr_end=%u.%u.%u.%u\n",
+                       config->ip_addr_end[0], config->ip_addr_end[1],
+                       config->ip_addr_end[2], config->ip_addr_end[3]);
 #endif /* CONFIG_P2P */
        if (config->country[0] && config->country[1]) {
                fprintf(f, "country=%c%c\n",
@@ -1139,25 +1338,40 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
                        config->bss_expiration_scan_count);
        if (config->filter_ssids)
                fprintf(f, "filter_ssids=%d\n", config->filter_ssids);
+       if (config->filter_rssi)
+               fprintf(f, "filter_rssi=%d\n", config->filter_rssi);
        if (config->max_num_sta != DEFAULT_MAX_NUM_STA)
                fprintf(f, "max_num_sta=%u\n", config->max_num_sta);
+       if (config->ap_isolate != DEFAULT_AP_ISOLATE)
+               fprintf(f, "ap_isolate=%u\n", config->ap_isolate);
        if (config->disassoc_low_ack)
-               fprintf(f, "disassoc_low_ack=%u\n", config->disassoc_low_ack);
+               fprintf(f, "disassoc_low_ack=%d\n", config->disassoc_low_ack);
 #ifdef CONFIG_HS20
        if (config->hs20)
                fprintf(f, "hs20=1\n");
 #endif /* CONFIG_HS20 */
 #ifdef CONFIG_INTERWORKING
        if (config->interworking)
-               fprintf(f, "interworking=%u\n", config->interworking);
+               fprintf(f, "interworking=%d\n", config->interworking);
        if (!is_zero_ether_addr(config->hessid))
                fprintf(f, "hessid=" MACSTR "\n", MAC2STR(config->hessid));
        if (config->access_network_type != DEFAULT_ACCESS_NETWORK_TYPE)
                fprintf(f, "access_network_type=%d\n",
                        config->access_network_type);
+       if (config->go_interworking)
+               fprintf(f, "go_interworking=%d\n", config->go_interworking);
+       if (config->go_access_network_type)
+               fprintf(f, "go_access_network_type=%d\n",
+                       config->go_access_network_type);
+       if (config->go_internet)
+               fprintf(f, "go_internet=%d\n", config->go_internet);
+       if (config->go_venue_group)
+               fprintf(f, "go_venue_group=%d\n", config->go_venue_group);
+       if (config->go_venue_type)
+               fprintf(f, "go_venue_type=%d\n", config->go_venue_type);
 #endif /* CONFIG_INTERWORKING */
        if (config->pbc_in_m1)
-               fprintf(f, "pbc_in_m1=%u\n", config->pbc_in_m1);
+               fprintf(f, "pbc_in_m1=%d\n", config->pbc_in_m1);
        if (config->wps_nfc_pw_from_config) {
                if (config->wps_nfc_dev_pw_id)
                        fprintf(f, "wps_nfc_dev_pw_id=%d\n",
@@ -1190,13 +1404,20 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
        if (config->sae_groups) {
                int i;
                fprintf(f, "sae_groups=");
-               for (i = 0; config->sae_groups[i] >= 0; i++) {
+               for (i = 0; config->sae_groups[i] > 0; i++) {
                        fprintf(f, "%s%d", i > 0 ? " " : "",
                                config->sae_groups[i]);
                }
                fprintf(f, "\n");
        }
 
+       if (config->sae_pwe)
+               fprintf(f, "sae_pwe=%d\n", config->sae_pwe);
+
+       if (config->sae_pmkid_in_assoc)
+               fprintf(f, "sae_pmkid_in_assoc=%d\n",
+                       config->sae_pmkid_in_assoc);
+
        if (config->ap_vendor_elements) {
                int i, len = wpabuf_len(config->ap_vendor_elements);
                const u8 *p = wpabuf_head_u8(config->ap_vendor_elements);
@@ -1216,7 +1437,7 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
                int i;
                fprintf(f, "freq_list=");
                for (i = 0; config->freq_list[i]; i++) {
-                       fprintf(f, "%s%u", i > 0 ? " " : "",
+                       fprintf(f, "%s%d", i > 0 ? " " : "",
                                config->freq_list[i]);
                }
                fprintf(f, "\n");
@@ -1228,6 +1449,10 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
                fprintf(f, "sched_scan_interval=%u\n",
                        config->sched_scan_interval);
 
+       if (config->sched_scan_start_delay)
+               fprintf(f, "sched_scan_start_delay=%u\n",
+                       config->sched_scan_start_delay);
+
        if (config->external_sim)
                fprintf(f, "external_sim=%d\n", config->external_sim);
 
@@ -1242,6 +1467,9 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
        if (config->bgscan)
                fprintf(f, "bgscan=\"%s\"\n", config->bgscan);
 
+       if (config->autoscan)
+               fprintf(f, "autoscan=%s\n", config->autoscan);
+
        if (config->p2p_search_delay != DEFAULT_P2P_SEARCH_DELAY)
                fprintf(f, "p2p_search_delay=%u\n",
                        config->p2p_search_delay);
@@ -1257,7 +1485,7 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
                fprintf(f, "preassoc_mac_addr=%d\n", config->preassoc_mac_addr);
 
        if (config->key_mgmt_offload != DEFAULT_KEY_MGMT_OFFLOAD)
-               fprintf(f, "key_mgmt_offload=%u\n", config->key_mgmt_offload);
+               fprintf(f, "key_mgmt_offload=%d\n", config->key_mgmt_offload);
 
        if (config->user_mpm != DEFAULT_USER_MPM)
                fprintf(f, "user_mpm=%d\n", config->user_mpm);
@@ -1272,12 +1500,81 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
                fprintf(f, "mesh_max_inactivity=%d\n",
                        config->mesh_max_inactivity);
 
+       if (config->dot11RSNASAERetransPeriod !=
+           DEFAULT_DOT11_RSNA_SAE_RETRANS_PERIOD)
+               fprintf(f, "dot11RSNASAERetransPeriod=%d\n",
+                       config->dot11RSNASAERetransPeriod);
+
        if (config->passive_scan)
                fprintf(f, "passive_scan=%d\n", config->passive_scan);
 
        if (config->reassoc_same_bss_optim)
                fprintf(f, "reassoc_same_bss_optim=%d\n",
                        config->reassoc_same_bss_optim);
+
+       if (config->wps_priority)
+               fprintf(f, "wps_priority=%d\n", config->wps_priority);
+
+       if (config->wpa_rsc_relaxation != DEFAULT_WPA_RSC_RELAXATION)
+               fprintf(f, "wpa_rsc_relaxation=%d\n",
+                       config->wpa_rsc_relaxation);
+
+       if (config->sched_scan_plans)
+               fprintf(f, "sched_scan_plans=%s\n", config->sched_scan_plans);
+
+#ifdef CONFIG_MBO
+       if (config->non_pref_chan)
+               fprintf(f, "non_pref_chan=%s\n", config->non_pref_chan);
+       if (config->mbo_cell_capa != DEFAULT_MBO_CELL_CAPA)
+               fprintf(f, "mbo_cell_capa=%u\n", config->mbo_cell_capa);
+       if (config->disassoc_imminent_rssi_threshold !=
+           DEFAULT_DISASSOC_IMMINENT_RSSI_THRESHOLD)
+               fprintf(f, "disassoc_imminent_rssi_threshold=%d\n",
+                       config->disassoc_imminent_rssi_threshold);
+       if (config->oce != DEFAULT_OCE_SUPPORT)
+               fprintf(f, "oce=%u\n", config->oce);
+#endif /* CONFIG_MBO */
+
+       if (config->gas_address3)
+               fprintf(f, "gas_address3=%d\n", config->gas_address3);
+
+       if (config->ftm_responder)
+               fprintf(f, "ftm_responder=%d\n", config->ftm_responder);
+       if (config->ftm_initiator)
+               fprintf(f, "ftm_initiator=%d\n", config->ftm_initiator);
+
+       if (config->osu_dir)
+               fprintf(f, "osu_dir=%s\n", config->osu_dir);
+
+       if (config->fst_group_id)
+               fprintf(f, "fst_group_id=%s\n", config->fst_group_id);
+       if (config->fst_priority)
+               fprintf(f, "fst_priority=%d\n", config->fst_priority);
+       if (config->fst_llt)
+               fprintf(f, "fst_llt=%d\n", config->fst_llt);
+
+       if (config->gas_rand_addr_lifetime != DEFAULT_RAND_ADDR_LIFETIME)
+               fprintf(f, "gas_rand_addr_lifetime=%u\n",
+                       config->gas_rand_addr_lifetime);
+       if (config->gas_rand_mac_addr)
+               fprintf(f, "gas_rand_mac_addr=%d\n", config->gas_rand_mac_addr);
+       if (config->dpp_config_processing)
+               fprintf(f, "dpp_config_processing=%d\n",
+                       config->dpp_config_processing);
+       if (config->coloc_intf_reporting)
+               fprintf(f, "coloc_intf_reporting=%d\n",
+                       config->coloc_intf_reporting);
+       if (config->p2p_device_random_mac_addr)
+               fprintf(f, "p2p_device_random_mac_addr=%d\n",
+                       config->p2p_device_random_mac_addr);
+       if (!is_zero_ether_addr(config->p2p_device_persistent_mac_addr))
+               fprintf(f, "p2p_device_persistent_mac_addr=" MACSTR "\n",
+                       MAC2STR(config->p2p_device_persistent_mac_addr));
+       if (config->p2p_interface_random_mac_addr)
+               fprintf(f, "p2p_interface_random_mac_addr=%d\n",
+                       config->p2p_interface_random_mac_addr);
+       if (config->disable_btm)
+               fprintf(f, "disable_btm=1\n");
 }
 
 #endif /* CONFIG_NO_CONFIG_WRITE */
@@ -1340,6 +1637,8 @@ int wpa_config_write(const char *name, struct wpa_config *config)
        }
 #endif /* CONFIG_NO_CONFIG_BLOBS */
 
+       os_fdatasync(f);
+
        fclose(f);
 
        if (tmp_name) {