From: Jouni Malinen Date: Thu, 9 Oct 2025 10:03:39 +0000 (+0300) Subject: Reduce debug logging of configuration file details in wpa_supplicant X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d20454f15a8d76575f29ac25d16ff02aa1c11c0f;p=thirdparty%2Fhostap.git 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 --- diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index 1feaff2c6..4aa54c24f 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 4e3997877..3feef1fcb 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 b1ba03ac5..fdc39a9d4 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 01e7aad44..ed1d86902 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 05e6e3794..67d4a3201 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 ebcc5d7ee..9f9cbde1e 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 e212235c5..5df941f9d 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 0c17aaea4..ca672c6eb 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 9229eb51f..5445f20da 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 f266ce4f4..67c716f93 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 672bbd876..c9257bc85 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 106964df9..dbdbb69c5 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);