X-Git-Url: http://www.project-moonshot.org/gitweb/?p=mech_eap.git;a=blobdiff_plain;f=libeap%2Fwpa_supplicant%2Fconfig_file.c;h=fb438ea43e13f07b110b7004632f49e16f522a92;hp=0f343fd04cb22994582610fd723de31066c7f759;hb=4f319dde67a76fe0aaf33f6d2788968012584ada;hpb=ed09b5e64dd485851310307979d5eed14678087b diff --git a/libeap/wpa_supplicant/config_file.c b/libeap/wpa_supplicant/config_file.c index 0f343fd..fb438ea 100644 --- a/libeap/wpa_supplicant/config_file.c +++ b/libeap/wpa_supplicant/config_file.c @@ -1,15 +1,9 @@ /* * WPA Supplicant / Configuration backend: text file - * Copyright (c) 2003-2008, Jouni Malinen + * Copyright (c) 2003-2012, Jouni Malinen * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. + * This software may be distributed under the terms of the BSD license. + * See README for more details. * * This file implements a configuration backend for text files. All the * configuration information is stored in a text file that uses a format @@ -17,11 +11,40 @@ */ #include "includes.h" +#ifdef ANDROID +#include +#endif /* ANDROID */ #include "common.h" #include "config.h" #include "base64.h" #include "uuid.h" +#include "p2p/p2p.h" +#include "eap_peer/eap_methods.h" +#include "eap_peer/eap.h" + + +static int newline_terminated(const char *buf, size_t buflen) +{ + size_t len = os_strlen(buf); + if (len == 0) + return 0; + if (len == buflen - 1 && buf[buflen - 1] != '\r' && + buf[len - 1] != '\n') + return 0; + return 1; +} + + +static void skip_line_end(FILE *stream) +{ + char buf[100]; + while (fgets(buf, sizeof(buf), stream)) { + buf[sizeof(buf) - 1] = '\0'; + if (newline_terminated(buf, sizeof(buf))) + return; + } +} /** @@ -46,6 +69,15 @@ static char * wpa_config_get_line(char *s, int size, FILE *stream, int *line, while (fgets(s, size, stream)) { (*line)++; s[size - 1] = '\0'; + if (!newline_terminated(s, size)) { + /* + * The line was truncated - skip rest of it to avoid + * confusing error messages. + */ + wpa_printf(MSG_INFO, "Long line in configuration file " + "truncated"); + skip_line_end(stream); + } pos = s; /* Skip white space from the beginning of line. */ @@ -104,14 +136,6 @@ static int wpa_config_validate_network(struct wpa_ssid *ssid, int line) wpa_config_update_psk(ssid); } - if ((ssid->key_mgmt & (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK | - WPA_KEY_MGMT_PSK_SHA256)) && - !ssid->psk_set) { - wpa_printf(MSG_ERROR, "Line %d: WPA-PSK accepted for key " - "management, but no PSK configured.", line); - errors++; - } - if ((ssid->group_cipher & WPA_CIPHER_CCMP) && !(ssid->pairwise_cipher & WPA_CIPHER_CCMP) && !(ssid->pairwise_cipher & WPA_CIPHER_NONE)) { @@ -122,6 +146,15 @@ static int wpa_config_validate_network(struct wpa_ssid *ssid, int line) ssid->group_cipher &= ~WPA_CIPHER_CCMP; } + if (ssid->mode == WPAS_MODE_MESH && + (ssid->key_mgmt != WPA_KEY_MGMT_NONE && + ssid->key_mgmt != WPA_KEY_MGMT_SAE)) { + wpa_printf(MSG_ERROR, + "Line %d: key_mgmt for mesh network should be open or SAE", + line); + errors++; + } + return errors; } @@ -130,13 +163,14 @@ static struct wpa_ssid * wpa_config_read_network(FILE *f, int *line, int id) { struct wpa_ssid *ssid; int errors = 0, end = 0; - char buf[256], *pos, *pos2; + char buf[2000], *pos, *pos2; wpa_printf(MSG_MSGDUMP, "Line: %d - start of a new network block", *line); ssid = os_zalloc(sizeof(*ssid)); if (ssid == NULL) return NULL; + dl_list_init(&ssid->psk_list); ssid->id = id; wpa_config_set_network_defaults(ssid); @@ -186,6 +220,62 @@ static struct wpa_ssid * wpa_config_read_network(FILE *f, int *line, int id) } +static struct wpa_cred * wpa_config_read_cred(FILE *f, int *line, int id) +{ + struct wpa_cred *cred; + int errors = 0, end = 0; + char buf[256], *pos, *pos2; + + wpa_printf(MSG_MSGDUMP, "Line: %d - start of a new cred block", *line); + cred = os_zalloc(sizeof(*cred)); + if (cred == NULL) + return NULL; + cred->id = id; + cred->sim_num = DEFAULT_USER_SELECTED_SIM; + + while (wpa_config_get_line(buf, sizeof(buf), f, line, &pos)) { + if (os_strcmp(pos, "}") == 0) { + end = 1; + break; + } + + pos2 = os_strchr(pos, '='); + if (pos2 == NULL) { + wpa_printf(MSG_ERROR, "Line %d: Invalid cred line " + "'%s'.", *line, pos); + errors++; + continue; + } + + *pos2++ = '\0'; + if (*pos2 == '"') { + if (os_strchr(pos2 + 1, '"') == NULL) { + wpa_printf(MSG_ERROR, "Line %d: invalid " + "quotation '%s'.", *line, pos2); + errors++; + continue; + } + } + + if (wpa_config_set_cred(cred, pos, pos2, *line) < 0) + errors++; + } + + if (!end) { + wpa_printf(MSG_ERROR, "Line %d: cred block was not " + "terminated properly.", *line); + errors++; + } + + if (errors) { + wpa_config_free_cred(cred); + cred = NULL; + } + + return cred; +} + + #ifndef CONFIG_NO_CONFIG_BLOBS static struct wpa_config_blob * wpa_config_read_blob(FILE *f, int *line, const char *name) @@ -269,21 +359,40 @@ static int wpa_config_process_blob(struct wpa_config *config, FILE *f, #endif /* CONFIG_NO_CONFIG_BLOBS */ -struct wpa_config * wpa_config_read(const char *name) +struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp) { FILE *f; - char buf[256], *pos; + char buf[512], *pos; int errors = 0, line = 0; - struct wpa_ssid *ssid, *tail = NULL, *head = NULL; + struct wpa_ssid *ssid, *tail, *head; + struct wpa_cred *cred, *cred_tail, *cred_head; struct wpa_config *config; int id = 0; + int cred_id = 0; - config = wpa_config_alloc_empty(NULL, NULL); - if (config == NULL) + if (name == NULL) + return NULL; + if (cfgp) + config = cfgp; + else + config = wpa_config_alloc_empty(NULL, NULL); + if (config == NULL) { + wpa_printf(MSG_ERROR, "Failed to allocate config file " + "structure"); return NULL; + } + tail = head = config->ssid; + while (tail && tail->next) + tail = tail->next; + cred_tail = cred_head = config->cred; + while (cred_tail && cred_tail->next) + cred_tail = cred_tail->next; + wpa_printf(MSG_DEBUG, "Reading configuration file '%s'", name); f = fopen(name, "r"); if (f == NULL) { + wpa_printf(MSG_ERROR, "Failed to open config file '%s', " + "error: %s", name, strerror(errno)); os_free(config); return NULL; } @@ -310,10 +419,26 @@ struct wpa_config * wpa_config_read(const char *name) errors++; continue; } + } else if (os_strcmp(pos, "cred={") == 0) { + cred = wpa_config_read_cred(f, &line, cred_id++); + if (cred == NULL) { + wpa_printf(MSG_ERROR, "Line %d: failed to " + "parse cred block.", line); + errors++; + continue; + } + if (cred_head == NULL) { + cred_head = cred_tail = cred; + } else { + cred_tail->next = cred; + cred_tail = cred; + } #ifndef CONFIG_NO_CONFIG_BLOBS } else if (os_strncmp(pos, "blob-base64-", 12) == 0) { if (wpa_config_process_blob(config, f, &line, pos + 12) < 0) { + wpa_printf(MSG_ERROR, "Line %d: failed to " + "process blob.", line); errors++; continue; } @@ -330,12 +455,15 @@ struct wpa_config * wpa_config_read(const char *name) config->ssid = head; wpa_config_debug_dump_networks(config); + config->cred = cred_head; +#ifndef WPA_IGNORE_CONFIG_ERRORS if (errors) { wpa_config_free(config); config = NULL; head = NULL; } +#endif /* WPA_IGNORE_CONFIG_ERRORS */ return config; } @@ -373,7 +501,12 @@ static void write_bssid(FILE *f, struct wpa_ssid *ssid) 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); @@ -483,7 +616,7 @@ static void write_wep_key(FILE *f, int idx, struct wpa_ssid *ssid) int res; res = os_snprintf(field, sizeof(field), "wep_key%d", idx); - if (res < 0 || (size_t) res >= sizeof(field)) + if (os_snprintf_error(sizeof(field), res)) return; value = wpa_config_get(ssid, field); if (value) { @@ -493,6 +626,42 @@ static void write_wep_key(FILE *f, int idx, struct wpa_ssid *ssid) } +#ifdef CONFIG_P2P + +static void write_go_p2p_dev_addr(FILE *f, struct wpa_ssid *ssid) +{ + char *value = wpa_config_get(ssid, "go_p2p_dev_addr"); + if (value == NULL) + return; + fprintf(f, "\tgo_p2p_dev_addr=%s\n", value); + os_free(value); +} + +static void write_p2p_client_list(FILE *f, struct wpa_ssid *ssid) +{ + char *value = wpa_config_get(ssid, "p2p_client_list"); + if (value == NULL) + return; + fprintf(f, "\tp2p_client_list=%s\n", value); + os_free(value); +} + + +static void write_psk_list(FILE *f, struct wpa_ssid *ssid) +{ + struct psk_list_entry *psk; + char hex[32 * 2 + 1]; + + dl_list_for_each(psk, &ssid->psk_list, struct psk_list_entry, list) { + wpa_snprintf_hex(hex, sizeof(hex), psk->psk, sizeof(psk->psk)); + fprintf(f, "\tpsk_list=%s" MACSTR "-%s\n", + psk->p2p ? "P2P-" : "", MAC2STR(psk->addr), hex); + } +} + +#endif /* CONFIG_P2P */ + + static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) { int i; @@ -506,12 +675,19 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) STR(ssid); INT(scan_ssid); write_bssid(f, ssid); + write_str(f, "bssid_blacklist", ssid); + write_str(f, "bssid_whitelist", ssid); write_psk(f, ssid); + INT(mem_only_psk); 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_auth_alg(f, ssid); + STR(bgscan); + STR(autoscan); + STR(scan_freq); #ifdef IEEE8021X_EAPOL write_eap(f, ssid); STR(identity); @@ -525,6 +701,8 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) STR(dh_file); STR(subject_match); STR(altsubject_match); + STR(domain_suffix_match); + STR(domain_match); STR(ca_cert2); STR(ca_path2); STR(client_cert2); @@ -533,6 +711,8 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) STR(dh_file2); STR(subject_match2); STR(altsubject_match2); + STR(domain_suffix_match2); + STR(domain_match2); STR(phase1); STR(phase2); STR(pcsc); @@ -549,6 +729,8 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) INTe(engine); INTe(engine2); INT_DEF(eapol_flags, DEFAULT_EAPOL_FLAGS); + STR(openssl_ciphers); + INTe(erp); #endif /* IEEE8021X_EAPOL */ for (i = 0; i < 4; i++) write_wep_key(f, i, ssid); @@ -558,15 +740,78 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) 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); #endif /* IEEE8021X_EAPOL */ INT(mode); - INT(proactive_key_caching); + INT(no_auto_peer); + INT(frequency); + INT(fixed_freq); + write_int(f, "proactive_key_caching", ssid->proactive_key_caching, -1); INT(disabled); INT(peerkey); + INT(mixed_cell); #ifdef CONFIG_IEEE80211W - INT(ieee80211w); + 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); + write_p2p_client_list(f, ssid); + write_psk_list(f, ssid); +#endif /* CONFIG_P2P */ + INT(ap_max_inactivity); + INT(dtim_period); + INT(beacon_int); +#ifdef CONFIG_MACSEC + INT(macsec_policy); +#endif /* CONFIG_MACSEC */ +#ifdef CONFIG_HS20 + INT(update_identifier); +#endif /* CONFIG_HS20 */ + write_int(f, "mac_addr", ssid->mac_addr, -1); +#ifdef CONFIG_MESH + STR(mesh_basic_rates); + INT_DEF(dot11MeshMaxRetries, DEFAULT_MESH_MAX_RETRIES); + INT_DEF(dot11MeshRetryTimeout, DEFAULT_MESH_RETRY_TIMEOUT); + INT_DEF(dot11MeshConfirmTimeout, DEFAULT_MESH_CONFIRM_TIMEOUT); + INT_DEF(dot11MeshHoldingTimeout, DEFAULT_MESH_HOLDING_TIMEOUT); +#endif /* CONFIG_MESH */ + INT(wpa_ptk_rekey); + INT(ignore_broadcast_ssid); +#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(disable_max_amsdu, DEFAULT_DISABLE_MAX_AMSDU); + INT_DEF(ampdu_factor, DEFAULT_AMPDU_FACTOR); + INT_DEF(ampdu_density, DEFAULT_AMPDU_DENSITY); + STR(ht_mcs); +#endif /* CONFIG_HT_OVERRIDES */ +#ifdef CONFIG_VHT_OVERRIDES + INT(disable_vht); + INT(vht_capa); + INT(vht_capa_mask); + INT_DEF(vht_rx_mcs_nss_1, -1); + INT_DEF(vht_rx_mcs_nss_2, -1); + INT_DEF(vht_rx_mcs_nss_3, -1); + INT_DEF(vht_rx_mcs_nss_4, -1); + INT_DEF(vht_rx_mcs_nss_5, -1); + INT_DEF(vht_rx_mcs_nss_6, -1); + INT_DEF(vht_rx_mcs_nss_7, -1); + INT_DEF(vht_rx_mcs_nss_8, -1); + INT_DEF(vht_tx_mcs_nss_1, -1); + INT_DEF(vht_tx_mcs_nss_2, -1); + INT_DEF(vht_tx_mcs_nss_3, -1); + INT_DEF(vht_tx_mcs_nss_4, -1); + INT_DEF(vht_tx_mcs_nss_5, -1); + INT_DEF(vht_tx_mcs_nss_6, -1); + INT_DEF(vht_tx_mcs_nss_7, -1); + INT_DEF(vht_tx_mcs_nss_8, -1); +#endif /* CONFIG_VHT_OVERRIDES */ #undef STR #undef INT @@ -574,6 +819,134 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) } +static void wpa_config_write_cred(FILE *f, struct wpa_cred *cred) +{ + size_t i; + + if (cred->priority) + fprintf(f, "\tpriority=%d\n", cred->priority); + if (cred->pcsc) + fprintf(f, "\tpcsc=%d\n", cred->pcsc); + if (cred->realm) + fprintf(f, "\trealm=\"%s\"\n", cred->realm); + if (cred->username) + fprintf(f, "\tusername=\"%s\"\n", cred->username); + if (cred->password && cred->ext_password) + fprintf(f, "\tpassword=ext:%s\n", cred->password); + else if (cred->password) + fprintf(f, "\tpassword=\"%s\"\n", cred->password); + if (cred->ca_cert) + fprintf(f, "\tca_cert=\"%s\"\n", cred->ca_cert); + if (cred->client_cert) + fprintf(f, "\tclient_cert=\"%s\"\n", cred->client_cert); + if (cred->private_key) + fprintf(f, "\tprivate_key=\"%s\"\n", cred->private_key); + if (cred->private_key_passwd) + fprintf(f, "\tprivate_key_passwd=\"%s\"\n", + cred->private_key_passwd); + if (cred->imsi) + fprintf(f, "\timsi=\"%s\"\n", cred->imsi); + if (cred->milenage) + fprintf(f, "\tmilenage=\"%s\"\n", cred->milenage); + for (i = 0; i < cred->num_domain; i++) + fprintf(f, "\tdomain=\"%s\"\n", cred->domain[i]); + if (cred->domain_suffix_match) + fprintf(f, "\tdomain_suffix_match=\"%s\"\n", + cred->domain_suffix_match); + if (cred->roaming_consortium_len) { + fprintf(f, "\troaming_consortium="); + for (i = 0; i < cred->roaming_consortium_len; i++) + fprintf(f, "%02x", cred->roaming_consortium[i]); + fprintf(f, "\n"); + } + if (cred->eap_method) { + const char *name; + name = eap_get_name(cred->eap_method[0].vendor, + cred->eap_method[0].method); + if (name) + fprintf(f, "\teap=%s\n", name); + } + if (cred->phase1) + fprintf(f, "\tphase1=\"%s\"\n", cred->phase1); + if (cred->phase2) + fprintf(f, "\tphase2=\"%s\"\n", cred->phase2); + if (cred->excluded_ssid) { + size_t j; + for (i = 0; i < cred->num_excluded_ssid; i++) { + struct excluded_ssid *e = &cred->excluded_ssid[i]; + fprintf(f, "\texcluded_ssid="); + for (j = 0; j < e->ssid_len; j++) + fprintf(f, "%02x", e->ssid[j]); + fprintf(f, "\n"); + } + } + if (cred->roaming_partner) { + for (i = 0; i < cred->num_roaming_partner; i++) { + struct roaming_partner *p = &cred->roaming_partner[i]; + fprintf(f, "\troaming_partner=\"%s,%d,%u,%s\"\n", + p->fqdn, p->exact_match, p->priority, + p->country); + } + } + if (cred->update_identifier) + fprintf(f, "\tupdate_identifier=%d\n", cred->update_identifier); + + if (cred->provisioning_sp) + fprintf(f, "\tprovisioning_sp=\"%s\"\n", cred->provisioning_sp); + if (cred->sp_priority) + fprintf(f, "\tsp_priority=%d\n", cred->sp_priority); + + if (cred->min_dl_bandwidth_home) + fprintf(f, "\tmin_dl_bandwidth_home=%u\n", + cred->min_dl_bandwidth_home); + if (cred->min_ul_bandwidth_home) + fprintf(f, "\tmin_ul_bandwidth_home=%u\n", + cred->min_ul_bandwidth_home); + if (cred->min_dl_bandwidth_roaming) + fprintf(f, "\tmin_dl_bandwidth_roaming=%u\n", + cred->min_dl_bandwidth_roaming); + if (cred->min_ul_bandwidth_roaming) + fprintf(f, "\tmin_ul_bandwidth_roaming=%u\n", + cred->min_ul_bandwidth_roaming); + + if (cred->max_bss_load) + fprintf(f, "\tmax_bss_load=%u\n", + cred->max_bss_load); + + if (cred->ocsp) + fprintf(f, "\tocsp=%d\n", cred->ocsp); + + if (cred->num_req_conn_capab) { + for (i = 0; i < cred->num_req_conn_capab; i++) { + int *ports; + + fprintf(f, "\treq_conn_capab=%u", + cred->req_conn_capab_proto[i]); + ports = cred->req_conn_capab_port[i]; + if (ports) { + int j; + for (j = 0; ports[j] != -1; j++) { + fprintf(f, "%s%d", j > 0 ? "," : ":", + ports[j]); + } + } + fprintf(f, "\n"); + } + } + + if (cred->required_roaming_consortium_len) { + fprintf(f, "\trequired_roaming_consortium="); + for (i = 0; i < cred->required_roaming_consortium_len; i++) + fprintf(f, "%02x", + cred->required_roaming_consortium[i]); + fprintf(f, "\n"); + } + + if (cred->sim_num != DEFAULT_USER_SELECTED_SIM) + fprintf(f, "\tsim_num=%d\n", cred->sim_num); +} + + #ifndef CONFIG_NO_CONFIG_BLOBS static int wpa_config_write_blob(FILE *f, struct wpa_config_blob *blob) { @@ -590,6 +963,23 @@ static int wpa_config_write_blob(FILE *f, struct wpa_config_blob *blob) #endif /* CONFIG_NO_CONFIG_BLOBS */ +static void write_global_bin(FILE *f, const char *field, + const struct wpabuf *val) +{ + size_t i; + const u8 *pos; + + if (val == NULL) + return; + + fprintf(f, "%s=", field); + pos = wpabuf_head(val); + for (i = 0; i < wpabuf_len(val); i++) + fprintf(f, "%02X", *pos++); + fprintf(f, "\n"); +} + + static void wpa_config_write_global(FILE *f, struct wpa_config *config) { #ifdef CONFIG_CTRL_IFACE @@ -603,6 +993,9 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config) fprintf(f, "eapol_version=%d\n", config->eapol_version); if (config->ap_scan != DEFAULT_AP_SCAN) fprintf(f, "ap_scan=%d\n", config->ap_scan); + if (config->disable_scan_offload) + fprintf(f, "disable_scan_offload=%d\n", + config->disable_scan_offload); if (config->fast_reauth != DEFAULT_FAST_REAUTH) fprintf(f, "fast_reauth=%d\n", config->fast_reauth); if (config->opensc_engine_path) @@ -614,16 +1007,22 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config) if (config->pkcs11_module_path) fprintf(f, "pkcs11_module_path=%s\n", config->pkcs11_module_path); + if (config->openssl_ciphers) + fprintf(f, "openssl_ciphers=%s\n", config->openssl_ciphers); + if (config->pcsc_reader) + fprintf(f, "pcsc_reader=%s\n", config->pcsc_reader); + if (config->pcsc_pin) + fprintf(f, "pcsc_pin=%s\n", config->pcsc_pin); 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); @@ -643,8 +1042,13 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config) fprintf(f, "model_number=%s\n", config->model_number); if (config->serial_number) fprintf(f, "serial_number=%s\n", config->serial_number); - if (config->device_type) - fprintf(f, "device_type=%s\n", config->device_type); + { + char _buf[WPS_DEV_TYPE_BUFSIZE], *buf; + buf = wps_dev_type_bin2str(config->device_type, + _buf, sizeof(_buf)); + if (os_strcmp(buf, "0-00000000-0") != 0) + fprintf(f, "device_type=%s\n", buf); + } if (WPA_GET_BE32(config->os_version)) fprintf(f, "os_version=%08x\n", WPA_GET_BE32(config->os_version)); @@ -653,29 +1057,85 @@ 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_vendor_ext_m1) { + int i, len = wpabuf_len(config->wps_vendor_ext_m1); + const u8 *p = wpabuf_head_u8(config->wps_vendor_ext_m1); + if (len > 0) { + fprintf(f, "wps_vendor_ext_m1="); + for (i = 0; i < len; i++) + fprintf(f, "%02x", *p++); + fprintf(f, "\n"); + } + } #endif /* CONFIG_WPS */ #ifdef CONFIG_P2P 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=%d\n", config->p2p_group_idle); + if (config->p2p_passphrase_len) + fprintf(f, "p2p_passphrase_len=%u\n", + config->p2p_passphrase_len); + if (config->p2p_pref_chan) { + unsigned int i; + fprintf(f, "p2p_pref_chan="); + for (i = 0; i < config->num_p2p_pref_chan; i++) { + fprintf(f, "%s%u:%u", i > 0 ? "," : "", + config->p2p_pref_chan[i].op_class, + config->p2p_pref_chan[i].chan); + } + fprintf(f, "\n"); + } + if (config->p2p_no_go_freq.num) { + char *val = freq_range_list_str(&config->p2p_no_go_freq); + if (val) { + fprintf(f, "p2p_no_go_freq=%s\n", val); + os_free(val); + } + } + if (config->p2p_add_cli_chan) + fprintf(f, "p2p_add_cli_chan=%d\n", config->p2p_add_cli_chan); + if (config->p2p_optimize_listen_chan != + DEFAULT_P2P_OPTIMIZE_LISTEN_CHAN) + fprintf(f, "p2p_optimize_listen_chan=%d\n", + config->p2p_optimize_listen_chan); + if (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=%d\n", config->p2p_go_vht); + 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=%d\n", config->p2p_disabled); + if (config->p2p_no_group_iface) + 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=%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); #endif /* CONFIG_P2P */ if (config->country[0] && config->country[1]) { fprintf(f, "country=%c%c\n", @@ -683,8 +1143,162 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config) } if (config->bss_max_count != DEFAULT_BSS_MAX_COUNT) fprintf(f, "bss_max_count=%u\n", config->bss_max_count); + if (config->bss_expiration_age != DEFAULT_BSS_EXPIRATION_AGE) + fprintf(f, "bss_expiration_age=%u\n", + config->bss_expiration_age); + if (config->bss_expiration_scan_count != + DEFAULT_BSS_EXPIRATION_SCAN_COUNT) + fprintf(f, "bss_expiration_scan_count=%u\n", + config->bss_expiration_scan_count); if (config->filter_ssids) fprintf(f, "filter_ssids=%d\n", config->filter_ssids); + if (config->max_num_sta != DEFAULT_MAX_NUM_STA) + fprintf(f, "max_num_sta=%u\n", config->max_num_sta); + if (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=%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); +#endif /* CONFIG_INTERWORKING */ + if (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", + config->wps_nfc_dev_pw_id); + write_global_bin(f, "wps_nfc_dh_pubkey", + config->wps_nfc_dh_pubkey); + write_global_bin(f, "wps_nfc_dh_privkey", + config->wps_nfc_dh_privkey); + write_global_bin(f, "wps_nfc_dev_pw", config->wps_nfc_dev_pw); + } + + if (config->ext_password_backend) + fprintf(f, "ext_password_backend=%s\n", + config->ext_password_backend); + if (config->p2p_go_max_inactivity != DEFAULT_P2P_GO_MAX_INACTIVITY) + fprintf(f, "p2p_go_max_inactivity=%d\n", + config->p2p_go_max_inactivity); + if (config->auto_interworking) + fprintf(f, "auto_interworking=%d\n", + config->auto_interworking); + if (config->okc) + fprintf(f, "okc=%d\n", config->okc); + if (config->pmf) + fprintf(f, "pmf=%d\n", config->pmf); + if (config->dtim_period) + fprintf(f, "dtim_period=%d\n", config->dtim_period); + if (config->beacon_int) + fprintf(f, "beacon_int=%d\n", config->beacon_int); + + if (config->sae_groups) { + int i; + fprintf(f, "sae_groups="); + for (i = 0; config->sae_groups[i] >= 0; i++) { + fprintf(f, "%s%d", i > 0 ? " " : "", + config->sae_groups[i]); + } + fprintf(f, "\n"); + } + + if (config->ap_vendor_elements) { + int i, len = wpabuf_len(config->ap_vendor_elements); + const u8 *p = wpabuf_head_u8(config->ap_vendor_elements); + if (len > 0) { + fprintf(f, "ap_vendor_elements="); + for (i = 0; i < len; i++) + fprintf(f, "%02x", *p++); + fprintf(f, "\n"); + } + } + + if (config->ignore_old_scan_res) + fprintf(f, "ignore_old_scan_res=%d\n", + config->ignore_old_scan_res); + + if (config->freq_list && config->freq_list[0]) { + int i; + fprintf(f, "freq_list="); + for (i = 0; config->freq_list[i]; i++) { + fprintf(f, "%s%d", i > 0 ? " " : "", + config->freq_list[i]); + } + fprintf(f, "\n"); + } + if (config->scan_cur_freq != DEFAULT_SCAN_CUR_FREQ) + fprintf(f, "scan_cur_freq=%d\n", config->scan_cur_freq); + + if (config->sched_scan_interval) + fprintf(f, "sched_scan_interval=%u\n", + config->sched_scan_interval); + + if (config->external_sim) + fprintf(f, "external_sim=%d\n", config->external_sim); + + if (config->tdls_external_control) + fprintf(f, "tdls_external_control=%d\n", + config->tdls_external_control); + + if (config->wowlan_triggers) + fprintf(f, "wowlan_triggers=%s\n", + config->wowlan_triggers); + + if (config->bgscan) + fprintf(f, "bgscan=\"%s\"\n", config->bgscan); + + if (config->p2p_search_delay != DEFAULT_P2P_SEARCH_DELAY) + fprintf(f, "p2p_search_delay=%u\n", + config->p2p_search_delay); + + if (config->mac_addr) + fprintf(f, "mac_addr=%d\n", config->mac_addr); + + if (config->rand_addr_lifetime != DEFAULT_RAND_ADDR_LIFETIME) + fprintf(f, "rand_addr_lifetime=%u\n", + config->rand_addr_lifetime); + + if (config->preassoc_mac_addr) + 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=%d\n", config->key_mgmt_offload); + + if (config->user_mpm != DEFAULT_USER_MPM) + fprintf(f, "user_mpm=%d\n", config->user_mpm); + + if (config->max_peer_links != DEFAULT_MAX_PEER_LINKS) + fprintf(f, "max_peer_links=%d\n", config->max_peer_links); + + if (config->cert_in_cb != DEFAULT_CERT_IN_CB) + fprintf(f, "cert_in_cb=%d\n", config->cert_in_cb); + + if (config->mesh_max_inactivity != DEFAULT_MESH_MAX_INACTIVITY) + 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); } #endif /* CONFIG_NO_CONFIG_WRITE */ @@ -695,24 +1309,45 @@ int wpa_config_write(const char *name, struct wpa_config *config) #ifndef CONFIG_NO_CONFIG_WRITE FILE *f; struct wpa_ssid *ssid; + struct wpa_cred *cred; #ifndef CONFIG_NO_CONFIG_BLOBS struct wpa_config_blob *blob; #endif /* CONFIG_NO_CONFIG_BLOBS */ int ret = 0; + const char *orig_name = name; + int tmp_len = os_strlen(name) + 5; /* allow space for .tmp suffix */ + char *tmp_name = os_malloc(tmp_len); + + if (tmp_name) { + os_snprintf(tmp_name, tmp_len, "%s.tmp", name); + name = tmp_name; + } wpa_printf(MSG_DEBUG, "Writing configuration file '%s'", name); f = fopen(name, "w"); if (f == NULL) { wpa_printf(MSG_DEBUG, "Failed to open '%s' for writing", name); + os_free(tmp_name); return -1; } wpa_config_write_global(f, config); + for (cred = config->cred; cred; cred = cred->next) { + if (cred->temporary) + continue; + fprintf(f, "\ncred={\n"); + wpa_config_write_cred(f, cred); + fprintf(f, "}\n"); + } + for (ssid = config->ssid; ssid; ssid = ssid->next) { if (ssid->key_mgmt == WPA_KEY_MGMT_WPS || ssid->temporary) continue; /* do not save temporary networks */ + if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set && + !ssid->passphrase) + continue; /* do not save invalid network */ fprintf(f, "\nnetwork={\n"); wpa_config_write_network(f, ssid); fprintf(f, "}\n"); @@ -726,10 +1361,25 @@ int wpa_config_write(const char *name, struct wpa_config *config) } #endif /* CONFIG_NO_CONFIG_BLOBS */ + os_fdatasync(f); + fclose(f); + if (tmp_name) { + int chmod_ret = 0; + +#ifdef ANDROID + chmod_ret = chmod(tmp_name, + S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); +#endif /* ANDROID */ + if (chmod_ret != 0 || rename(tmp_name, orig_name) != 0) + ret = -1; + + os_free(tmp_name); + } + wpa_printf(MSG_DEBUG, "Configuration file '%s' written %ssuccessfully", - name, ret ? "un" : ""); + orig_name, ret ? "un" : ""); return ret; #else /* CONFIG_NO_CONFIG_WRITE */ return -1;