]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Reduce debug logging of configuration file details in wpa_supplicant
authorJouni Malinen <jouni.malinen@oss.qualcomm.com>
Thu, 9 Oct 2025 10:03:39 +0000 (13:03 +0300)
committerJouni Malinen <j@w1.fi>
Thu, 9 Oct 2025 13:55:12 +0000 (16:55 +0300)
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 <jouni.malinen@oss.qualcomm.com>
12 files changed:
wpa_supplicant/config.c
wpa_supplicant/config.h
wpa_supplicant/config_file.c
wpa_supplicant/config_none.c
wpa_supplicant/config_winreg.c
wpa_supplicant/ctrl_iface.c
wpa_supplicant/dbus/dbus_new_handlers.c
wpa_supplicant/eapol_test.c
wpa_supplicant/main.c
wpa_supplicant/preauth_test.c
wpa_supplicant/wpa_supplicant.c
wpa_supplicant/wpa_supplicant_i.h

index 1feaff2c663435e8c2d669c9a131937b7051fa34..4aa54c24f1b2584b98a8ae9bbaace53ec2500a03 100644 (file)
@@ -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;
        }
 
index 4e3997877aad49ff07ddfd5459e542211361447b..3feef1fcb23774d3c7fc4da3ac58fe3e9c063c48 100644 (file)
@@ -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
index b1ba03ac5a7199c538dd1a3032a3bf2a389b3d94..fdc39a9d4d9a24cf4b2f06f25a231ade518b5648 100644 (file)
@@ -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;
                }
index 01e7aad44bd9c5687d993d5b506cb58b2d8571a2..ed1d8690292fbef633456a598098f375d87a149a 100644 (file)
@@ -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;
 
index 05e6e37944bba36739b6d9393e74ed768efcc0c6..67d4a3201b1711d3f680573ccc25a023402fece5 100644 (file)
@@ -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;
index ebcc5d7ee4d2864703d0ecaadc1994a63593a20b..9f9cbde1e12b72410954ad5e475c46632112d760 100644 (file)
@@ -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)
index e212235c5979c4fe2b6a3e5976a220dab53ba010..5df941f9d1d16c8a40eece24adbb21f725d77ee8 100644 (file)
@@ -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",
index 0c17aaea418ccff95df3745788b3b58969514a20..ca672c6eb9a0ed821fd07a5f81e62c0a552a3f24 100644 (file)
@@ -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) {
index 9229eb51f3908a9f95a6135da6fca41a3cd8b4e8..5445f20da71626dcb0edc5cb3fe5fbe65c02089f 100644 (file)
@@ -32,10 +32,10 @@ static void usage(void)
 #ifdef CONFIG_CTRL_IFACE_DBUS_NEW
               "u"
 #endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
-              "vW] [-P<pid file>] "
+              "vWy] [-P<pid file>] "
               "[-g<global ctrl>] \\\n"
               "        [-G<group>] \\\n"
-              "        -i<ifname> -c<config file> [-C<ctrl>] [-D<driver>] "
+              "        [-i<ifname>] -c<config file> [-C<ctrl>] [-D<driver>] "
               "[-p<driver_param>] \\\n"
               "        [-b<br_ifname>] [-e<entropy file>]"
 #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;
        }
index f266ce4f409ac53d5c62a8cc4d902115db9ffaf6..67c716f93830a235fc1bea2adcea96eaba96d111 100644 (file)
@@ -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;
index 672bbd876afa21d3b003727e3b038d3acadd620a..c9257bc853f2c0003061b2eec1ac4ead7f820441 100644 (file)
@@ -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) &&
index 106964df9f9d3e31435c0fadb9f1ae5d355c5dc0..dbdbb69c55f312bc4703364dde44a117c775f339 100644 (file)
@@ -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);