From d20454f15a8d76575f29ac25d16ff02aa1c11c0f Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 9 Oct 2025 13:03:39 +0300 Subject: [PATCH] Reduce debug logging of configuration file details in wpa_supplicant Avoid printing some of the details about parsing failures and invalid data read from a configuration file when parsing it for normal wpa_supplicant operation. This helps in reducing risk for leaking information about files that the wpa_supplicant process itself might be able to read, but the process requesting a new interface to be added (e.g., though a control interface operation) might not have privileges to read. This does not remove all the prints in all cases, but reduces debug prints significantly for cases where the specified configuration file is does not use the same syntax as a valid wpa_supplicant configuration file would. The previously available level of detailed parsing information is available for debugging purposes by running wpa_supplicant separately for this without requesting any actual operation to be started. This can be done, e.g., with the following command: wpa_supplicant -c /tmp/test.conf -d In addition to the debug information printed to stdout, the return code from the process indicates whether the full configuration file was parsed successfully. It is also possible to explicitly request the parsing details to be included in the debug log from normal operation by adding -y to the command line. This is meant only for systems here the debug log is not exposed to users that do not have access to the same set of files as the wpa_supplicant process has. Signed-off-by: Jouni Malinen --- wpa_supplicant/config.c | 37 ++++++++++++++++--------- wpa_supplicant/config.h | 6 ++-- wpa_supplicant/config_file.c | 22 +++++++++++---- wpa_supplicant/config_none.c | 2 +- wpa_supplicant/config_winreg.c | 2 +- wpa_supplicant/ctrl_iface.c | 16 +++++++---- wpa_supplicant/dbus/dbus_new_handlers.c | 2 +- wpa_supplicant/eapol_test.c | 2 +- wpa_supplicant/main.c | 31 ++++++++++++++++----- wpa_supplicant/preauth_test.c | 2 +- wpa_supplicant/wpa_supplicant.c | 32 ++++++++++++++++++--- wpa_supplicant/wpa_supplicant_i.h | 6 ++++ 12 files changed, 118 insertions(+), 42 deletions(-) diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index 1feaff2c66..4aa54c24f1 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -5880,6 +5880,7 @@ const char * wpa_config_get_global_field_name(unsigned int i, int *no_var) * @config: Pointer to global configuration data * @pos: Name and value in the format "{name}={value}" * @line: Line number in configuration file or 0 if not used + * @show_details: Whether to show parsing errors and other details in debug log * Returns: 0 on success with a possible change in value, 1 on success with no * change to previously configured value, or -1 on failure * @@ -5888,7 +5889,8 @@ const char * wpa_config_get_global_field_name(unsigned int i, int *no_var) * parameter must be in the same format as the text-based configuration file is * using. For example, strings are using double quotation marks. */ -int wpa_config_process_global(struct wpa_config *config, char *pos, int line) +int wpa_config_process_global(struct wpa_config *config, char *pos, int line, + bool show_details) { size_t i; int ret = 0; @@ -5902,8 +5904,10 @@ int wpa_config_process_global(struct wpa_config *config, char *pos, int line) ret = field->parser(field, config, line, pos + flen + 1); if (ret < 0) { - wpa_printf(MSG_ERROR, "Line %d: failed to " - "parse '%s'.", line, pos); + if (show_details) + wpa_printf(MSG_ERROR, + "Line %d: failed to parse '%s'.", + line, pos); ret = -1; } if (ret == 1) @@ -5919,7 +5923,7 @@ int wpa_config_process_global(struct wpa_config *config, char *pos, int line) char *tmp = os_strchr(pos, '='); if (!tmp) { - if (line < 0) + if (show_details) wpa_printf(MSG_ERROR, "Line %d: invalid line %s", line, pos); @@ -5928,9 +5932,10 @@ int wpa_config_process_global(struct wpa_config *config, char *pos, int line) *tmp++ = '\0'; if (hostapd_config_tx_queue(config->tx_queue, pos, tmp)) { - wpa_printf(MSG_ERROR, - "Line %d: invalid TX queue item", - line); + if (show_details) + wpa_printf(MSG_ERROR, + "Line %d: invalid TX queue item", + line); return -1; } return ret; @@ -5941,15 +5946,19 @@ int wpa_config_process_global(struct wpa_config *config, char *pos, int line) if (tmp == NULL) { if (line < 0) return -1; - wpa_printf(MSG_ERROR, "Line %d: invalid line " - "'%s'", line, pos); + if (show_details) + wpa_printf(MSG_ERROR, + "Line %d: invalid line '%s'", + line, pos); return -1; } *tmp++ = '\0'; if (hostapd_config_wmm_ac(config->wmm_ac_params, pos, tmp)) { - wpa_printf(MSG_ERROR, "Line %d: invalid WMM " - "AC item", line); + if (show_details) + wpa_printf(MSG_ERROR, + "Line %d: invalid WMM AC item", + line); return -1; } return ret; @@ -5957,8 +5966,10 @@ int wpa_config_process_global(struct wpa_config *config, char *pos, int line) #endif /* CONFIG_AP */ if (line < 0) return -1; - wpa_printf(MSG_ERROR, "Line %d: unknown global field '%s'.", - line, pos); + if (show_details) + wpa_printf(MSG_ERROR, + "Line %d: unknown global field '%s'.", + line, pos); ret = -1; } diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h index 4e3997877a..3feef1fcb2 100644 --- a/wpa_supplicant/config.h +++ b/wpa_supplicant/config.h @@ -1973,7 +1973,8 @@ void wpa_config_debug_dump_networks(struct wpa_config *config); /* Prototypes for common functions from config.c */ -int wpa_config_process_global(struct wpa_config *config, char *pos, int line); +int wpa_config_process_global(struct wpa_config *config, char *pos, int line, + bool show_details); int wpa_config_get_num_global_field_names(void); @@ -1987,6 +1988,7 @@ const char * wpa_config_get_global_field_name(unsigned int i, int *no_var); * configuration file) * @cfgp: Pointer to previously allocated configuration data or %NULL if none * @ro: Whether to mark networks from this configuration as read-only + * @show_details: Whether to show parsing errors and other details in debug log * Returns: Pointer to allocated configuration data or %NULL on failure * * This function reads configuration data, parses its contents, and allocates @@ -1996,7 +1998,7 @@ const char * wpa_config_get_global_field_name(unsigned int i, int *no_var); * Each configuration backend needs to implement this function. */ struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp, - bool ro); + bool ro, bool show_details); /** * wpa_config_write - Write or update configuration data diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index b1ba03ac5a..fdc39a9d4d 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -356,7 +356,7 @@ static struct wpa_dev_ik * wpa_config_read_identity(FILE *f, int *line, int id) struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp, - bool ro) + bool ro, bool show_details) { FILE *f; char buf[1024], *pos; @@ -393,14 +393,21 @@ struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp, 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)); + if (show_details) + wpa_printf(MSG_ERROR, + "Failed to open config file '%s', error: %s", + name, strerror(errno)); if (config != cfgp) os_free(config); return NULL; } while (wpa_config_get_line(buf, sizeof(buf), f, &line, &pos)) { +#ifndef WPA_IGNORE_CONFIG_ERRORS + if (errors && !show_details) + break; +#endif /* WPA_IGNORE_CONFIG_ERRORS */ + if (os_strcmp(pos, "network={") == 0) { ssid = wpa_config_read_network(f, &line, id++); if (ssid == NULL) { @@ -463,9 +470,12 @@ struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp, identity_tail->next = identity; identity_tail = identity; } - } else if (wpa_config_process_global(config, pos, line) < 0) { - wpa_printf(MSG_ERROR, "Line %d: Invalid configuration " - "line '%s'.", line, pos); + } else if (wpa_config_process_global(config, pos, line, + show_details) < 0) { + if (show_details) + wpa_printf(MSG_ERROR, + "Line %d: Invalid configuration line '%s'.", + line, pos); errors++; continue; } diff --git a/wpa_supplicant/config_none.c b/wpa_supplicant/config_none.c index 01e7aad44b..ed1d869029 100644 --- a/wpa_supplicant/config_none.c +++ b/wpa_supplicant/config_none.c @@ -18,7 +18,7 @@ struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp, - bool ro) + bool ro, bool show_details) { struct wpa_config *config; diff --git a/wpa_supplicant/config_winreg.c b/wpa_supplicant/config_winreg.c index 05e6e37944..67d4a3201b 100644 --- a/wpa_supplicant/config_winreg.c +++ b/wpa_supplicant/config_winreg.c @@ -447,7 +447,7 @@ static int wpa_config_read_networks(struct wpa_config *config, HKEY hk) struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp, - bool ro) + bool ro, bool show_details) { TCHAR buf[256]; int errors = 0; diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index ebcc5d7ee4..9f9cbde1e1 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -534,7 +534,8 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, ret = -1; } else { value[-1] = '='; - wpa_config_process_global(wpa_s->conf, cmd, -1); + wpa_config_process_global(wpa_s->conf, cmd, -1, + true); } } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") == 0) { @@ -543,7 +544,8 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, ret = -1; } else { value[-1] = '='; - wpa_config_process_global(wpa_s->conf, cmd, -1); + wpa_config_process_global(wpa_s->conf, cmd, -1, + true); } } else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) { if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, @@ -551,7 +553,8 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, ret = -1; } else { value[-1] = '='; - wpa_config_process_global(wpa_s->conf, cmd, -1); + wpa_config_process_global(wpa_s->conf, cmd, -1, + true); } } else if (os_strcasecmp(cmd, "wps_fragment_size") == 0) { wpa_s->wps_fragment_size = atoi(value); @@ -918,7 +921,8 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, ret = wpas_mbo_update_non_pref_chan(wpa_s, value); if (ret == 0) { value[-1] = '='; - wpa_config_process_global(wpa_s->conf, cmd, -1); + wpa_config_process_global(wpa_s->conf, cmd, -1, + true); } } else if (os_strcasecmp(cmd, "mbo_cell_capa") == 0) { int val = atoi(value); @@ -987,7 +991,9 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, #endif /* CONFIG_PASN */ } else { value[-1] = '='; - ret = wpa_config_process_global(wpa_s->conf, cmd, -1); + ret = wpa_config_process_global( + wpa_s->conf, cmd, -1, + wpa_s->global->params.show_details); if (ret == 0) wpa_supplicant_update_config(wpa_s); else if (ret == 1) diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c index e212235c59..5df941f9d1 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.c +++ b/wpa_supplicant/dbus/dbus_new_handlers.c @@ -4672,7 +4672,7 @@ dbus_bool_t wpas_dbus_setter_iface_global( return FALSE; } - ret = wpa_config_process_global(wpa_s->conf, buf, -1); + ret = wpa_config_process_global(wpa_s->conf, buf, -1, false); if (ret < 0) { dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "Failed to set interface property %s", diff --git a/wpa_supplicant/eapol_test.c b/wpa_supplicant/eapol_test.c index 0c17aaea41..ca672c6eb9 100644 --- a/wpa_supplicant/eapol_test.c +++ b/wpa_supplicant/eapol_test.c @@ -1530,7 +1530,7 @@ int main(int argc, char *argv[]) dl_list_init(&wpa_s.bss); dl_list_init(&wpa_s.bss_id); if (conf) - wpa_s.conf = wpa_config_read(conf, NULL, false); + wpa_s.conf = wpa_config_read(conf, NULL, false, true); else wpa_s.conf = wpa_config_alloc_empty(ctrl_iface, NULL); if (wpa_s.conf == NULL) { diff --git a/wpa_supplicant/main.c b/wpa_supplicant/main.c index 9229eb51f3..5445f20da7 100644 --- a/wpa_supplicant/main.c +++ b/wpa_supplicant/main.c @@ -32,10 +32,10 @@ static void usage(void) #ifdef CONFIG_CTRL_IFACE_DBUS_NEW "u" #endif /* CONFIG_CTRL_IFACE_DBUS_NEW */ - "vW] [-P] " + "vWy] [-P] " "[-g] \\\n" " [-G] \\\n" - " -i -c [-C] [-D] " + " [-i] -c [-C] [-D] " "[-p] \\\n" " [-b] [-e]" #ifdef CONFIG_DEBUG_FILE @@ -103,11 +103,15 @@ static void usage(void) " -u = enable DBus control interface\n" #endif /* CONFIG_CTRL_IFACE_DBUS_NEW */ " -v = show version\n" - " -W = wait for a control interface monitor before starting\n"); + " -W = wait for a control interface monitor before starting\n" + " -y = show configuration parsing details in debug log\n"); printf("example:\n" " wpa_supplicant -D%s -iwlan0 -c/etc/wpa_supplicant.conf\n", wpa_drivers[0] ? wpa_drivers[0]->name : "nl80211"); + printf("\nIf run without specifying a network interface or control interface, the a\n" + "configuration file is parsed without starting any operation.\n" + "This can be used to check whether a configuration file has valid contents.\n"); #endif /* CONFIG_NO_STDOUT_DEBUG */ } @@ -202,7 +206,7 @@ int main(int argc, char *argv[]) for (;;) { c = getopt(argc, argv, - "b:Bc:C:D:de:f:g:G:hi:I:KLMm:No:O:p:P:qsTtuvW"); + "b:Bc:C:D:de:f:g:G:hi:I:KLMm:No:O:p:P:qsTtuvWy"); if (c < 0) break; switch (c) { @@ -332,6 +336,9 @@ int main(int argc, char *argv[]) iface = &ifaces[iface_count - 1]; os_memset(iface, 0, sizeof(*iface)); break; + case 'y': + params.show_details = true; + break; default: usage(); exitcode = 0; @@ -345,13 +352,23 @@ int main(int argc, char *argv[]) wpa_printf(MSG_ERROR, "Failed to initialize wpa_supplicant"); exitcode = -1; goto out; - } else { - wpa_printf(MSG_INFO, "Successfully initialized " - "wpa_supplicant"); } + if (iface_count == 1 && ifaces[0].confname && !ifaces[0].ifname && +#ifdef CONFIG_MATCH_IFACE + !params.match_iface_count && +#endif /* CONFIG_MATCH_IFACE */ + !ifaces[0].ctrl_interface && !params.dbus_ctrl_interface) { + exitcode = wpa_supplicant_parse_config(ifaces[0].confname); + wpa_supplicant_deinit(global); + goto out; + } + + wpa_printf(MSG_INFO, "Successfully initialized wpa_supplicant"); + if (fst_global_init()) { wpa_printf(MSG_ERROR, "Failed to initialize FST"); + wpa_supplicant_deinit(global); exitcode = -1; goto out; } diff --git a/wpa_supplicant/preauth_test.c b/wpa_supplicant/preauth_test.c index f266ce4f40..67c716f938 100644 --- a/wpa_supplicant/preauth_test.c +++ b/wpa_supplicant/preauth_test.c @@ -318,7 +318,7 @@ int main(int argc, char *argv[]) } os_memset(&wpa_s, 0, sizeof(wpa_s)); - wpa_s.conf = wpa_config_read(argv[1], NULL, false); + wpa_s.conf = wpa_config_read(argv[1], NULL, false, true); if (wpa_s.conf == NULL) { printf("Failed to parse configuration file '%s'.\n", argv[1]); return -1; diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 672bbd876a..c9257bc853 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -1407,14 +1407,16 @@ int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s) if (wpa_s->confname == NULL) return -1; - conf = wpa_config_read(wpa_s->confname, NULL, false); + conf = wpa_config_read(wpa_s->confname, NULL, false, + wpa_s->global->params.show_details); if (conf == NULL) { wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration " "file '%s' - exiting", wpa_s->confname); return -1; } if (wpa_s->confanother && - !wpa_config_read(wpa_s->confanother, conf, true)) { + !wpa_config_read(wpa_s->confanother, conf, true, + wpa_s->global->params.show_details)) { wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration file '%s' - exiting", wpa_s->confanother); @@ -7652,7 +7654,9 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, #else /* CONFIG_BACKEND_FILE */ wpa_s->confname = os_strdup(iface->confname); #endif /* CONFIG_BACKEND_FILE */ - wpa_s->conf = wpa_config_read(wpa_s->confname, NULL, false); + wpa_s->conf = wpa_config_read( + wpa_s->confname, NULL, false, + wpa_s->global->params.show_details); if (wpa_s->conf == NULL) { wpa_printf(MSG_ERROR, "Failed to read or parse " "configuration '%s'.", wpa_s->confname); @@ -7660,7 +7664,8 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, } wpa_s->confanother = os_rel2abs_path(iface->confanother); if (wpa_s->confanother && - !wpa_config_read(wpa_s->confanother, wpa_s->conf, true)) { + !wpa_config_read(wpa_s->confanother, wpa_s->conf, true, + wpa_s->global->params.show_details)) { wpa_printf(MSG_ERROR, "Failed to read or parse configuration '%s'.", wpa_s->confanother); @@ -8473,6 +8478,7 @@ struct wpa_global * wpa_supplicant_init(struct wpa_params *params) global->params.daemonize = params->daemonize; global->params.wait_for_monitor = params->wait_for_monitor; global->params.dbus_ctrl_interface = params->dbus_ctrl_interface; + global->params.show_details = params->show_details; if (params->pid_file) { global->params.pid_file = os_strdup(params->pid_file); @@ -8712,6 +8718,24 @@ void wpa_supplicant_deinit(struct wpa_global *global) } +int wpa_supplicant_parse_config(const char *fname) +{ + struct wpa_config *conf; + int ret = -1; + + wpa_printf(MSG_INFO, "Validating parsing of %s", fname); + conf = wpa_config_read(fname, NULL, false, true); + if (conf) { + wpa_printf(MSG_INFO, "Parsing succeeded"); + ret = 0; + wpa_config_free(conf); + } else { + wpa_printf(MSG_INFO, "Parsing failed"); + } + return ret; +} + + void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s) { if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) && diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 106964df9f..dbdbb69c55 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -258,6 +258,11 @@ struct wpa_params { */ int match_iface_count; #endif /* CONFIG_MATCH_IFACE */ + + /** + * show_details - Whether to show config parsing details in debug log + */ + bool show_details; }; struct p2p_srv_bonjour { @@ -1730,6 +1735,7 @@ struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global, struct wpa_global * wpa_supplicant_init(struct wpa_params *params); int wpa_supplicant_run(struct wpa_global *global); void wpa_supplicant_deinit(struct wpa_global *global); +int wpa_supplicant_parse_config(const char *fname); int wpa_supplicant_scard_init(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid); -- 2.47.3