]> git.ipfire.org Git - thirdparty/hostap.git/blobdiff - wpa_supplicant/config.c
wpa_supplicant configuration for Beacon protection
[thirdparty/hostap.git] / wpa_supplicant / config.c
index b4e9952feee2e837ae9a2bca7dd1384a78d102e2..9dad4ff7231d9667313de1de2d3e5bc80851aa29 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / Configuration parser and common functions
- * Copyright (c) 2003-2018, 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.
@@ -12,6 +12,7 @@
 #include "utils/uuid.h"
 #include "utils/ip_addr.h"
 #include "common/ieee802_1x_defs.h"
+#include "common/sae.h"
 #include "crypto/sha1.h"
 #include "rsn_supp/wpa.h"
 #include "eap_peer/eap.h"
@@ -740,12 +741,10 @@ static int wpa_config_parse_key_mgmt(const struct parse_data *data,
                        val |= WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
 #endif /* CONFIG_SHA384 */
 #endif /* CONFIG_IEEE80211R */
-#ifdef CONFIG_IEEE80211W
                else if (os_strcmp(start, "WPA-PSK-SHA256") == 0)
                        val |= WPA_KEY_MGMT_PSK_SHA256;
                else if (os_strcmp(start, "WPA-EAP-SHA256") == 0)
                        val |= WPA_KEY_MGMT_IEEE8021X_SHA256;
-#endif /* CONFIG_IEEE80211W */
 #ifdef CONFIG_WPS
                else if (os_strcmp(start, "WPS") == 0)
                        val |= WPA_KEY_MGMT_WPS;
@@ -910,7 +909,6 @@ static char * wpa_config_write_key_mgmt(const struct parse_data *data,
 #endif /* CONFIG_SHA384 */
 #endif /* CONFIG_IEEE80211R */
 
-#ifdef CONFIG_IEEE80211W
        if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
                ret = os_snprintf(pos, end - pos, "%sWPA-PSK-SHA256",
                                  pos == buf ? "" : " ");
@@ -930,7 +928,6 @@ static char * wpa_config_write_key_mgmt(const struct parse_data *data,
                }
                pos += ret;
        }
-#endif /* CONFIG_IEEE80211W */
 
 #ifdef CONFIG_WPS
        if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
@@ -1614,7 +1611,7 @@ static int wpa_config_parse_password(const struct parse_data *data,
 #ifdef CONFIG_EXT_PASSWORD
        if (os_strncmp(value, "ext:", 4) == 0) {
                char *name = os_strdup(value + 4);
-               if (name == NULL)
+               if (!name)
                        return -1;
                bin_clear_free(ssid->eap.password, ssid->eap.password_len);
                ssid->eap.password = (u8 *) name;
@@ -1630,9 +1627,9 @@ static int wpa_config_parse_password(const struct parse_data *data,
                size_t res_len;
 
                tmp = wpa_config_parse_string(value, &res_len);
-               if (tmp == NULL) {
-                       wpa_printf(MSG_ERROR, "Line %d: failed to parse "
-                                  "password.", line);
+               if (!tmp) {
+                       wpa_printf(MSG_ERROR,
+                                  "Line %d: failed to parse password.", line);
                        return -1;
                }
                wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name,
@@ -1650,13 +1647,14 @@ static int wpa_config_parse_password(const struct parse_data *data,
 
        /* NtPasswordHash: hash:<32 hex digits> */
        if (os_strlen(value + 5) != 2 * 16) {
-               wpa_printf(MSG_ERROR, "Line %d: Invalid password hash length "
-                          "(expected 32 hex digits)", line);
+               wpa_printf(MSG_ERROR,
+                          "Line %d: Invalid password hash length (expected 32 hex digits)",
+                          line);
                return -1;
        }
 
        hash = os_malloc(16);
-       if (hash == NULL)
+       if (!hash)
                return -1;
 
        if (hexstr2bin(value + 5, hash, 16)) {
@@ -1683,19 +1681,118 @@ static int wpa_config_parse_password(const struct parse_data *data,
 }
 
 
+static int wpa_config_parse_machine_password(const struct parse_data *data,
+                                            struct wpa_ssid *ssid, int line,
+                                            const char *value)
+{
+       u8 *hash;
+
+       if (os_strcmp(value, "NULL") == 0) {
+               if (!ssid->eap.machine_password)
+                       return 1; /* Already unset */
+               wpa_printf(MSG_DEBUG,
+                          "Unset configuration string 'machine_password'");
+               bin_clear_free(ssid->eap.machine_password,
+                              ssid->eap.machine_password_len);
+               ssid->eap.machine_password = NULL;
+               ssid->eap.machine_password_len = 0;
+               return 0;
+       }
+
+#ifdef CONFIG_EXT_PASSWORD
+       if (os_strncmp(value, "ext:", 4) == 0) {
+               char *name = os_strdup(value + 4);
+
+               if (!name)
+                       return -1;
+               bin_clear_free(ssid->eap.machine_password,
+                              ssid->eap.machine_password_len);
+               ssid->eap.machine_password = (u8 *) name;
+               ssid->eap.machine_password_len = os_strlen(name);
+               ssid->eap.flags &= ~EAP_CONFIG_FLAGS_MACHINE_PASSWORD_NTHASH;
+               ssid->eap.flags |= EAP_CONFIG_FLAGS_EXT_MACHINE_PASSWORD;
+               return 0;
+       }
+#endif /* CONFIG_EXT_PASSWORD */
+
+       if (os_strncmp(value, "hash:", 5) != 0) {
+               char *tmp;
+               size_t res_len;
+
+               tmp = wpa_config_parse_string(value, &res_len);
+               if (!tmp) {
+                       wpa_printf(MSG_ERROR,
+                                  "Line %d: failed to parse machine_password.",
+                                  line);
+                       return -1;
+               }
+               wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name,
+                                     (u8 *) tmp, res_len);
+
+               bin_clear_free(ssid->eap.machine_password,
+                              ssid->eap.machine_password_len);
+               ssid->eap.machine_password = (u8 *) tmp;
+               ssid->eap.machine_password_len = res_len;
+               ssid->eap.flags &= ~EAP_CONFIG_FLAGS_MACHINE_PASSWORD_NTHASH;
+               ssid->eap.flags &= ~EAP_CONFIG_FLAGS_EXT_MACHINE_PASSWORD;
+
+               return 0;
+       }
+
+
+       /* NtPasswordHash: hash:<32 hex digits> */
+       if (os_strlen(value + 5) != 2 * 16) {
+               wpa_printf(MSG_ERROR,
+                          "Line %d: Invalid machine_password hash length (expected 32 hex digits)",
+                          line);
+               return -1;
+       }
+
+       hash = os_malloc(16);
+       if (!hash)
+               return -1;
+
+       if (hexstr2bin(value + 5, hash, 16)) {
+               os_free(hash);
+               wpa_printf(MSG_ERROR, "Line %d: Invalid machine_password hash",
+                          line);
+               return -1;
+       }
+
+       wpa_hexdump_key(MSG_MSGDUMP, data->name, hash, 16);
+
+       if (ssid->eap.machine_password &&
+           ssid->eap.machine_password_len == 16 &&
+           os_memcmp(ssid->eap.machine_password, hash, 16) == 0 &&
+           (ssid->eap.flags & EAP_CONFIG_FLAGS_MACHINE_PASSWORD_NTHASH)) {
+               bin_clear_free(hash, 16);
+               return 1;
+       }
+       bin_clear_free(ssid->eap.machine_password,
+                      ssid->eap.machine_password_len);
+       ssid->eap.machine_password = hash;
+       ssid->eap.machine_password_len = 16;
+       ssid->eap.flags |= EAP_CONFIG_FLAGS_MACHINE_PASSWORD_NTHASH;
+       ssid->eap.flags &= ~EAP_CONFIG_FLAGS_EXT_MACHINE_PASSWORD;
+
+       return 0;
+}
+
+
 #ifndef NO_CONFIG_WRITE
+
 static char * wpa_config_write_password(const struct parse_data *data,
                                        struct wpa_ssid *ssid)
 {
        char *buf;
 
-       if (ssid->eap.password == NULL)
+       if (!ssid->eap.password)
                return NULL;
 
 #ifdef CONFIG_EXT_PASSWORD
        if (ssid->eap.flags & EAP_CONFIG_FLAGS_EXT_PASSWORD) {
                buf = os_zalloc(4 + ssid->eap.password_len + 1);
-               if (buf == NULL)
+               if (!buf)
                        return NULL;
                os_memcpy(buf, "ext:", 4);
                os_memcpy(buf + 4, ssid->eap.password, ssid->eap.password_len);
@@ -1709,7 +1806,7 @@ static char * wpa_config_write_password(const struct parse_data *data,
        }
 
        buf = os_malloc(5 + 32 + 1);
-       if (buf == NULL)
+       if (!buf)
                return NULL;
 
        os_memcpy(buf, "hash:", 5);
@@ -1717,6 +1814,44 @@ static char * wpa_config_write_password(const struct parse_data *data,
 
        return buf;
 }
+
+
+static char * wpa_config_write_machine_password(const struct parse_data *data,
+                                               struct wpa_ssid *ssid)
+{
+       char *buf;
+
+       if (!ssid->eap.machine_password)
+               return NULL;
+
+#ifdef CONFIG_EXT_PASSWORD
+       if (ssid->eap.flags & EAP_CONFIG_FLAGS_EXT_MACHINE_PASSWORD) {
+               buf = os_zalloc(4 + ssid->eap.machine_password_len + 1);
+               if (!buf)
+                       return NULL;
+               os_memcpy(buf, "ext:", 4);
+               os_memcpy(buf + 4, ssid->eap.machine_password,
+                         ssid->eap.machine_password_len);
+               return buf;
+       }
+#endif /* CONFIG_EXT_PASSWORD */
+
+       if (!(ssid->eap.flags & EAP_CONFIG_FLAGS_MACHINE_PASSWORD_NTHASH)) {
+               return wpa_config_write_string(
+                       ssid->eap.machine_password,
+                       ssid->eap.machine_password_len);
+       }
+
+       buf = os_malloc(5 + 32 + 1);
+       if (!buf)
+               return NULL;
+
+       os_memcpy(buf, "hash:", 5);
+       wpa_snprintf_hex(buf + 5, 32 + 1, ssid->eap.machine_password, 16);
+
+       return buf;
+}
+
 #endif /* NO_CONFIG_WRITE */
 #endif /* IEEE8021X_EAPOL */
 
@@ -2141,23 +2276,24 @@ static char * wpa_config_write_peerkey(const struct parse_data *data,
 /* STR: Define a string variable for an ASCII string; f = field name */
 #ifdef NO_CONFIG_WRITE
 #define _STR(f) #f, wpa_config_parse_str, OFFSET(f)
-#define _STRe(f) #f, wpa_config_parse_str, OFFSET(eap.f)
+#define _STRe(f, m) #f, wpa_config_parse_str, OFFSET(eap.m)
 #else /* NO_CONFIG_WRITE */
 #define _STR(f) #f, wpa_config_parse_str, wpa_config_write_str, OFFSET(f)
-#define _STRe(f) #f, wpa_config_parse_str, wpa_config_write_str, OFFSET(eap.f)
+#define _STRe(f, m) #f, wpa_config_parse_str, wpa_config_write_str, \
+               OFFSET(eap.m)
 #endif /* NO_CONFIG_WRITE */
 #define STR(f) _STR(f), NULL, NULL, NULL, 0
-#define STRe(f) _STRe(f), NULL, NULL, NULL, 0
+#define STRe(f, m) _STRe(f, m), NULL, NULL, NULL, 0
 #define STR_KEY(f) _STR(f), NULL, NULL, NULL, 1
-#define STR_KEYe(f) _STRe(f), NULL, NULL, NULL, 1
+#define STR_KEYe(f, m) _STRe(f, m), NULL, NULL, NULL, 1
 
 /* STR_LEN: Define a string variable with a separate variable for storing the
  * data length. Unlike STR(), this can be used to store arbitrary binary data
  * (i.e., even nul termination character). */
 #define _STR_LEN(f) _STR(f), OFFSET(f ## _len)
-#define _STR_LENe(f) _STRe(f), OFFSET(eap.f ## _len)
+#define _STR_LENe(f, m) _STRe(f, m), OFFSET(eap.m ## _len)
 #define STR_LEN(f) _STR_LEN(f), NULL, NULL, 0
-#define STR_LENe(f) _STR_LENe(f), NULL, NULL, 0
+#define STR_LENe(f, m) _STR_LENe(f, m), NULL, NULL, 0
 #define STR_LEN_KEY(f) _STR_LEN(f), NULL, NULL, 1
 
 /* STR_RANGE: Like STR_LEN(), but with minimum and maximum allowed length
@@ -2168,17 +2304,17 @@ static char * wpa_config_write_peerkey(const struct parse_data *data,
 
 #ifdef NO_CONFIG_WRITE
 #define _INT(f) #f, wpa_config_parse_int, OFFSET(f), (void *) 0
-#define _INTe(f) #f, wpa_config_parse_int, OFFSET(eap.f), (void *) 0
+#define _INTe(f, m) #f, wpa_config_parse_int, OFFSET(eap.m), (void *) 0
 #else /* NO_CONFIG_WRITE */
 #define _INT(f) #f, wpa_config_parse_int, wpa_config_write_int, \
        OFFSET(f), (void *) 0
-#define _INTe(f) #f, wpa_config_parse_int, wpa_config_write_int, \
-       OFFSET(eap.f), (void *) 0
+#define _INTe(f, m) #f, wpa_config_parse_int, wpa_config_write_int,    \
+       OFFSET(eap.m), (void *) 0
 #endif /* NO_CONFIG_WRITE */
 
 /* INT: Define an integer variable */
 #define INT(f) _INT(f), NULL, NULL, 0
-#define INTe(f) _INTe(f), NULL, NULL, 0
+#define INTe(f, m) _INTe(f, m), NULL, NULL, 0
 
 /* INT_RANGE: Define an integer variable with allowed value range */
 #define INT_RANGE(f, min, max) _INT(f), (void *) (min), (void *) (max), 0
@@ -2240,55 +2376,80 @@ static const struct parse_data ssid_fields[] = {
        { INT_RANGE(ht, 0, 1) },
        { INT_RANGE(vht, 0, 1) },
        { INT_RANGE(ht40, -1, 1) },
-       { INT_RANGE(max_oper_chwidth, VHT_CHANWIDTH_USE_HT,
-                   VHT_CHANWIDTH_80P80MHZ) },
+       { INT_RANGE(max_oper_chwidth, CHANWIDTH_USE_HT,
+                   CHANWIDTH_80P80MHZ) },
        { INT(vht_center_freq1) },
        { INT(vht_center_freq2) },
 #ifdef IEEE8021X_EAPOL
        { FUNC(eap) },
-       { STR_LENe(identity) },
-       { STR_LENe(anonymous_identity) },
-       { STR_LENe(imsi_identity) },
+       { STR_LENe(identity, identity) },
+       { STR_LENe(anonymous_identity, anonymous_identity) },
+       { STR_LENe(imsi_identity, imsi_identity) },
+       { STR_LENe(machine_identity, machine_identity) },
        { FUNC_KEY(password) },
-       { STRe(ca_cert) },
-       { STRe(ca_path) },
-       { STRe(client_cert) },
-       { STRe(private_key) },
-       { STR_KEYe(private_key_passwd) },
-       { STRe(dh_file) },
-       { STRe(subject_match) },
-       { STRe(altsubject_match) },
-       { STRe(domain_suffix_match) },
-       { STRe(domain_match) },
-       { STRe(ca_cert2) },
-       { STRe(ca_path2) },
-       { STRe(client_cert2) },
-       { STRe(private_key2) },
-       { STR_KEYe(private_key2_passwd) },
-       { STRe(dh_file2) },
-       { STRe(subject_match2) },
-       { STRe(altsubject_match2) },
-       { STRe(domain_suffix_match2) },
-       { STRe(domain_match2) },
-       { STRe(phase1) },
-       { STRe(phase2) },
-       { STRe(pcsc) },
-       { STR_KEYe(pin) },
-       { STRe(engine_id) },
-       { STRe(key_id) },
-       { STRe(cert_id) },
-       { STRe(ca_cert_id) },
-       { STR_KEYe(pin2) },
-       { STRe(engine2_id) },
-       { STRe(key2_id) },
-       { STRe(cert2_id) },
-       { STRe(ca_cert2_id) },
-       { INTe(engine) },
-       { INTe(engine2) },
+       { FUNC_KEY(machine_password) },
+       { STRe(ca_cert, cert.ca_cert) },
+       { STRe(ca_path, cert.ca_path) },
+       { STRe(client_cert, cert.client_cert) },
+       { STRe(private_key, cert.private_key) },
+       { STR_KEYe(private_key_passwd, cert.private_key_passwd) },
+       { STRe(dh_file, cert.dh_file) },
+       { STRe(subject_match, cert.subject_match) },
+       { STRe(check_cert_subject, cert.check_cert_subject) },
+       { STRe(altsubject_match, cert.altsubject_match) },
+       { STRe(domain_suffix_match, cert.domain_suffix_match) },
+       { STRe(domain_match, cert.domain_match) },
+       { STRe(ca_cert2, phase2_cert.ca_cert) },
+       { STRe(ca_path2, phase2_cert.ca_path) },
+       { STRe(client_cert2, phase2_cert.client_cert) },
+       { STRe(private_key2, phase2_cert.private_key) },
+       { STR_KEYe(private_key2_passwd, phase2_cert.private_key_passwd) },
+       { STRe(dh_file2, phase2_cert.dh_file) },
+       { STRe(subject_match2, phase2_cert.subject_match) },
+       { STRe(check_cert_subject2, phase2_cert.check_cert_subject) },
+       { STRe(altsubject_match2, phase2_cert.altsubject_match) },
+       { STRe(domain_suffix_match2, phase2_cert.domain_suffix_match) },
+       { STRe(domain_match2, phase2_cert.domain_match) },
+       { STRe(phase1, phase1) },
+       { STRe(phase2, phase2) },
+       { STRe(machine_phase2, machine_phase2) },
+       { STRe(pcsc, pcsc) },
+       { STR_KEYe(pin, cert.pin) },
+       { STRe(engine_id, cert.engine_id) },
+       { STRe(key_id, cert.key_id) },
+       { STRe(cert_id, cert.cert_id) },
+       { STRe(ca_cert_id, cert.ca_cert_id) },
+       { STR_KEYe(pin2, phase2_cert.pin) },
+       { STRe(engine_id2, phase2_cert.engine_id) },
+       { STRe(key_id2, phase2_cert.key_id) },
+       { STRe(cert_id2, phase2_cert.cert_id) },
+       { STRe(ca_cert_id2, phase2_cert.ca_cert_id) },
+       { INTe(engine, cert.engine) },
+       { INTe(engine2, phase2_cert.engine) },
+       { STRe(machine_ca_cert, machine_cert.ca_cert) },
+       { STRe(machine_ca_path, machine_cert.ca_path) },
+       { STRe(machine_client_cert, machine_cert.client_cert) },
+       { STRe(machine_private_key, machine_cert.private_key) },
+       { STR_KEYe(machine_private_key_passwd,
+                  machine_cert.private_key_passwd) },
+       { STRe(machine_dh_file, machine_cert.dh_file) },
+       { STRe(machine_subject_match, machine_cert.subject_match) },
+       { STRe(machine_check_cert_subject, machine_cert.check_cert_subject) },
+       { STRe(machine_altsubject_match, machine_cert.altsubject_match) },
+       { STRe(machine_domain_suffix_match,
+              machine_cert.domain_suffix_match) },
+       { STRe(machine_domain_match, machine_cert.domain_match) },
+       { STR_KEYe(machine_pin, machine_cert.pin) },
+       { STRe(machine_engine_id, machine_cert.engine_id) },
+       { STRe(machine_key_id, machine_cert.key_id) },
+       { STRe(machine_cert_id, machine_cert.cert_id) },
+       { STRe(machine_ca_cert_id, machine_cert.ca_cert_id) },
+       { INTe(machine_engine, machine_cert.engine) },
+       { INTe(machine_ocsp, machine_cert.ocsp) },
        { INT(eapol_flags) },
-       { INTe(sim_num) },
-       { STRe(openssl_ciphers) },
-       { INTe(erp) },
+       { INTe(sim_num, sim_num) },
+       { STRe(openssl_ciphers, openssl_ciphers) },
+       { INTe(erp, erp) },
 #endif /* IEEE8021X_EAPOL */
        { FUNC_KEY(wep_key0) },
        { FUNC_KEY(wep_key1) },
@@ -2298,9 +2459,10 @@ static const struct parse_data ssid_fields[] = {
        { INT(priority) },
 #ifdef IEEE8021X_EAPOL
        { INT(eap_workaround) },
-       { STRe(pac_file) },
-       { INTe(fragment_size) },
-       { INTe(ocsp) },
+       { STRe(pac_file, pac_file) },
+       { INTe(fragment_size, fragment_size) },
+       { INTe(ocsp, cert.ocsp) },
+       { INTe(ocsp2, phase2_cert.ocsp) },
 #endif /* IEEE8021X_EAPOL */
 #ifdef CONFIG_MESH
        { INT_RANGE(mode, 0, 5) },
@@ -2312,16 +2474,16 @@ static const struct parse_data ssid_fields[] = {
        { INT_RANGE(proactive_key_caching, 0, 1) },
        { INT_RANGE(disabled, 0, 2) },
        { STR(id_str) },
-#ifdef CONFIG_IEEE80211W
        { INT_RANGE(ieee80211w, 0, 2) },
-#endif /* CONFIG_IEEE80211W */
 #ifdef CONFIG_OCV
        { FUNC(ocv) },
 #endif /* CONFIG_OCV */
        { FUNC(peerkey) /* obsolete - removed */ },
        { INT_RANGE(mixed_cell, 0, 1) },
-       { INT_RANGE(frequency, 0, 65000) },
+       { INT_RANGE(frequency, 0, 70200) },
        { INT_RANGE(fixed_freq, 0, 1) },
+       { INT_RANGE(enable_edmg, 0, 1) },
+       { INT_RANGE(edmg_channel, 9, 13) },
 #ifdef CONFIG_ACS
        { INT_RANGE(acs, 0, 1) },
 #endif /* CONFIG_ACS */
@@ -2404,7 +2566,10 @@ static const struct parse_data ssid_fields[] = {
 #endif /* CONFIG_DPP */
        { INT_RANGE(owe_group, 0, 65535) },
        { INT_RANGE(owe_only, 0, 1) },
+       { INT_RANGE(owe_ptk_workaround, 0, 1) },
        { INT_RANGE(multi_ap_backhaul_sta, 0, 1) },
+       { INT_RANGE(ft_eap_pmksa_caching, 0, 1) },
+       { INT_RANGE(beacon_prot, 0, 1) },
 };
 
 #undef OFFSET
@@ -2511,46 +2676,44 @@ int wpa_config_update_prio_list(struct wpa_config *config)
 
 
 #ifdef IEEE8021X_EAPOL
+
+static void eap_peer_config_free_cert(struct eap_peer_cert_config *cert)
+{
+       os_free(cert->ca_cert);
+       os_free(cert->ca_path);
+       os_free(cert->client_cert);
+       os_free(cert->private_key);
+       str_clear_free(cert->private_key_passwd);
+       os_free(cert->dh_file);
+       os_free(cert->subject_match);
+       os_free(cert->check_cert_subject);
+       os_free(cert->altsubject_match);
+       os_free(cert->domain_suffix_match);
+       os_free(cert->domain_match);
+       str_clear_free(cert->pin);
+       os_free(cert->engine_id);
+       os_free(cert->key_id);
+       os_free(cert->cert_id);
+       os_free(cert->ca_cert_id);
+}
+
+
 static void eap_peer_config_free(struct eap_peer_config *eap)
 {
        os_free(eap->eap_methods);
        bin_clear_free(eap->identity, eap->identity_len);
        os_free(eap->anonymous_identity);
        os_free(eap->imsi_identity);
+       os_free(eap->machine_identity);
        bin_clear_free(eap->password, eap->password_len);
-       os_free(eap->ca_cert);
-       os_free(eap->ca_path);
-       os_free(eap->client_cert);
-       os_free(eap->private_key);
-       str_clear_free(eap->private_key_passwd);
-       os_free(eap->dh_file);
-       os_free(eap->subject_match);
-       os_free(eap->altsubject_match);
-       os_free(eap->domain_suffix_match);
-       os_free(eap->domain_match);
-       os_free(eap->ca_cert2);
-       os_free(eap->ca_path2);
-       os_free(eap->client_cert2);
-       os_free(eap->private_key2);
-       str_clear_free(eap->private_key2_passwd);
-       os_free(eap->dh_file2);
-       os_free(eap->subject_match2);
-       os_free(eap->altsubject_match2);
-       os_free(eap->domain_suffix_match2);
-       os_free(eap->domain_match2);
+       bin_clear_free(eap->machine_password, eap->machine_password_len);
+       eap_peer_config_free_cert(&eap->cert);
+       eap_peer_config_free_cert(&eap->phase2_cert);
+       eap_peer_config_free_cert(&eap->machine_cert);
        os_free(eap->phase1);
        os_free(eap->phase2);
+       os_free(eap->machine_phase2);
        os_free(eap->pcsc);
-       str_clear_free(eap->pin);
-       os_free(eap->engine_id);
-       os_free(eap->key_id);
-       os_free(eap->cert_id);
-       os_free(eap->ca_cert_id);
-       os_free(eap->key2_id);
-       os_free(eap->cert2_id);
-       os_free(eap->ca_cert2_id);
-       str_clear_free(eap->pin2);
-       os_free(eap->engine2_id);
        os_free(eap->otp);
        os_free(eap->pending_req_otp);
        os_free(eap->pac_file);
@@ -2558,6 +2721,7 @@ static void eap_peer_config_free(struct eap_peer_config *eap)
        str_clear_free(eap->external_sim_resp);
        os_free(eap->openssl_ciphers);
 }
+
 #endif /* IEEE8021X_EAPOL */
 
 
@@ -2604,6 +2768,9 @@ void wpa_config_free_ssid(struct wpa_ssid *ssid)
                dl_list_del(&psk->list);
                bin_clear_free(psk, sizeof(*psk));
        }
+#ifdef CONFIG_SAE
+       sae_deinit_pt(ssid->pt);
+#endif /* CONFIG_SAE */
        bin_clear_free(ssid, sizeof(*ssid));
 }
 
@@ -2722,6 +2889,8 @@ void wpa_config_free(struct wpa_config *config)
 #ifdef CONFIG_MBO
        os_free(config->non_pref_chan);
 #endif /* CONFIG_MBO */
+       os_free(config->dpp_name);
+       os_free(config->dpp_mud_url);
 
        os_free(config);
 }
@@ -2896,9 +3065,7 @@ void wpa_config_set_network_defaults(struct wpa_ssid *ssid)
        ssid->vht_tx_mcs_nss_8 = -1;
 #endif /* CONFIG_VHT_OVERRIDES */
        ssid->proactive_key_caching = -1;
-#ifdef CONFIG_IEEE80211W
        ssid->ieee80211w = MGMT_FRAME_PROTECTION_DEFAULT;
-#endif /* CONFIG_IEEE80211W */
 #ifdef CONFIG_MACSEC
        ssid->mka_priority = DEFAULT_PRIO_NOT_KEY_SERVER;
 #endif /* CONFIG_MACSEC */
@@ -2943,6 +3110,15 @@ int wpa_config_set(struct wpa_ssid *ssid, const char *var, const char *value,
                        }
                        ret = -1;
                }
+#ifdef CONFIG_SAE
+               if (os_strcmp(var, "ssid") == 0 ||
+                   os_strcmp(var, "psk") == 0 ||
+                   os_strcmp(var, "sae_password") == 0 ||
+                   os_strcmp(var, "sae_password_id") == 0) {
+                       sae_deinit_pt(ssid->pt);
+                       ssid->pt = NULL;
+               }
+#endif /* CONFIG_SAE */
                break;
        }
        if (i == NUM_SSID_FIELDS) {
@@ -4753,6 +4929,7 @@ static const struct global_parse_data global_fields[] = {
        { FUNC(os_version), CFG_CHANGED_OS_VERSION },
        { STR(config_methods), CFG_CHANGED_CONFIG_METHODS },
        { INT_RANGE(wps_cred_processing, 0, 2), 0 },
+       { INT_RANGE(wps_cred_add_sae, 0, 1), 0 },
        { FUNC(wps_vendor_ext_m1), CFG_CHANGED_VENDOR_EXTENSION },
 #endif /* CONFIG_WPS */
 #ifdef CONFIG_P2P
@@ -4776,6 +4953,7 @@ static const struct global_parse_data global_fields[] = {
        { INT(p2p_go_ht40), 0 },
        { INT(p2p_go_vht), 0 },
        { INT(p2p_go_he), 0 },
+       { INT(p2p_go_edmg), 0 },
        { INT(p2p_disabled), 0 },
        { INT_RANGE(p2p_go_ctwindow, 0, 127), 0 },
        { INT(p2p_no_group_iface), 0 },
@@ -4822,6 +5000,8 @@ static const struct global_parse_data global_fields[] = {
        { INT(okc), 0 },
        { INT(pmf), 0 },
        { FUNC(sae_groups), 0 },
+       { INT_RANGE(sae_pwe, 0, 3), 0 },
+       { INT_RANGE(sae_pmkid_in_assoc, 0, 1), 0 },
        { INT(dtim_period), 0 },
        { INT(beacon_int), 0 },
        { FUNC(ap_vendor_elements), 0 },
@@ -4861,8 +5041,15 @@ static const struct global_parse_data global_fields[] = {
        { INT_RANGE(ftm_initiator, 0, 1), 0 },
        { INT(gas_rand_addr_lifetime), 0 },
        { INT_RANGE(gas_rand_mac_addr, 0, 2), 0 },
+#ifdef CONFIG_DPP
        { INT_RANGE(dpp_config_processing, 0, 2), 0 },
+       { STR(dpp_name), 0 },
+       { STR(dpp_mud_url), 0 },
+#endif /* CONFIG_DPP */
        { INT_RANGE(coloc_intf_reporting, 0, 1), 0 },
+#ifdef CONFIG_WNM
+       { INT_RANGE(disable_btm, 0, 1), CFG_CHANGED_DISABLE_BTM },
+#endif /* CONFIG_WNM */
 };
 
 #undef FUNC
@@ -4978,6 +5165,7 @@ int wpa_config_process_global(struct wpa_config *config, char *pos, int line)
                                           "AC item", line);
                                return -1;
                        }
+                       return ret;
                }
 #endif /* CONFIG_AP */
                if (line < 0)