diff --git a/contrib/fwupd.spec.in b/contrib/fwupd.spec.in index b011292b1b8..42ea2024a88 100644 --- a/contrib/fwupd.spec.in +++ b/contrib/fwupd.spec.in @@ -326,6 +326,9 @@ for fn in /etc/fwupd/remotes.d/*.conf; do fi done +# ensure this is private +chmod 0660 /etc/fwupd/redfish.conf + %preun %systemd_preun fwupd.service diff --git a/libfwupdplugin/fu-plugin.c b/libfwupdplugin/fu-plugin.c index 9744af9d608..b431f6d4187 100644 --- a/libfwupdplugin/fu-plugin.c +++ b/libfwupdplugin/fu-plugin.c @@ -9,6 +9,7 @@ #include "config.h" #include +#include #include #include #include @@ -2417,6 +2418,46 @@ fu_plugin_set_config_value(FuPlugin *self, const gchar *key, const gchar *value, return g_key_file_save_to_file(keyfile, conf_path, error); } +#if !GLIB_CHECK_VERSION(2, 66, 0) + +#define G_FILE_SET_CONTENTS_CONSISTENT 0 +typedef guint GFileSetContentsFlags; +static gboolean +g_file_set_contents_full(const gchar *filename, + const gchar *contents, + gssize length, + GFileSetContentsFlags flags, + int mode, + GError **error) +{ + gint fd; + gssize wrote; + + if (length < 0) + length = strlen(contents); + fd = g_open(filename, O_CREAT, mode); + if (fd <= 0) { + g_set_error(error, + G_IO_ERROR, + G_IO_ERROR_FAILED, + "could not open %s file", + filename); + return FALSE; + } + wrote = write(fd, contents, length); + if (wrote != length) { + g_set_error(error, + G_IO_ERROR, + G_IO_ERROR_FAILED, + "did not write %s file", + filename); + g_close(fd, NULL); + return FALSE; + } + return g_close(fd, error); +} +#endif + /** * fu_plugin_set_secure_config_value: * @self: a #FuPlugin @@ -2438,7 +2479,8 @@ fu_plugin_set_secure_config_value(FuPlugin *self, GError **error) { g_autofree gchar *conf_path = fu_plugin_get_config_filename(self); - gint ret; + g_autofree gchar *data = NULL; + g_autoptr(GKeyFile) keyfile = g_key_file_new(); g_return_val_if_fail(FU_IS_PLUGIN(self), FALSE); g_return_val_if_fail(error == NULL || *error == NULL, FALSE); @@ -2447,17 +2489,18 @@ fu_plugin_set_secure_config_value(FuPlugin *self, g_set_error(error, FWUPD_ERROR, FWUPD_ERROR_NOT_FOUND, "%s is missing", conf_path); return FALSE; } - ret = g_chmod(conf_path, 0660); - if (ret == -1) { - g_set_error(error, - FWUPD_ERROR, - FWUPD_ERROR_INTERNAL, - "failed to set permissions on %s", - conf_path); + if (!g_key_file_load_from_file(keyfile, conf_path, G_KEY_FILE_KEEP_COMMENTS, error)) return FALSE; - } - - return fu_plugin_set_config_value(self, key, value, error); + g_key_file_set_string(keyfile, fu_plugin_get_name(self), key, value); + data = g_key_file_to_data(keyfile, NULL, error); + if (data == NULL) + return FALSE; + return g_file_set_contents_full(conf_path, + data, + -1, + G_FILE_SET_CONTENTS_CONSISTENT, + 0660, + error); } /** diff --git a/libfwupdplugin/fu-self-test.c b/libfwupdplugin/fu-self-test.c index 2dbc9c94ff8..aaf49c172b1 100644 --- a/libfwupdplugin/fu-self-test.c +++ b/libfwupdplugin/fu-self-test.c @@ -674,6 +674,62 @@ _plugin_device_added_cb(FuPlugin *plugin, FuDevice *device, gpointer user_data) fu_test_loop_quit(); } +static void +fu_plugin_config_func(void) +{ + GStatBuf statbuf = {0}; + gboolean ret; + gint rc; + g_autofree gchar *conf_dir = NULL; + g_autofree gchar *conf_file = NULL; + g_autofree gchar *fn = NULL; + g_autofree gchar *testdatadir = NULL; + g_autofree gchar *value = NULL; + g_autoptr(FuPlugin) plugin = fu_plugin_new(NULL); + g_autoptr(GError) error = NULL; + + /* this is a build file */ + testdatadir = g_test_build_filename(G_TEST_BUILT, "tests", NULL); + (void)g_setenv("FWUPD_SYSCONFDIR", testdatadir, TRUE); + conf_dir = fu_path_from_kind(FU_PATH_KIND_SYSCONFDIR_PKG); + + /* remove existing file */ + fu_plugin_set_name(plugin, "test"); + conf_file = g_strdup_printf("%s.conf", fu_plugin_get_name(plugin)); + fn = g_build_filename(conf_dir, conf_file, NULL); + ret = fu_path_mkdir_parent(fn, &error); + g_assert_no_error(error); + g_assert_true(ret); + g_remove(fn); + ret = g_file_set_contents(fn, "", -1, &error); + g_assert_no_error(error); + g_assert_true(ret); + + /* set a value */ + ret = fu_plugin_set_config_value(plugin, "Key", "True", &error); + g_assert_no_error(error); + g_assert_true(ret); + g_assert_true(g_file_test(fn, G_FILE_TEST_EXISTS)); + + /* check it is world readable */ + rc = g_stat(fn, &statbuf); + g_assert_cmpint(rc, ==, 0); + g_assert_cmpint(statbuf.st_mode & 0777, ==, 0644); + + /* read back the value */ + value = fu_plugin_get_config_value(plugin, "Key"); + g_assert_cmpstr(value, ==, "True"); + g_assert_true(fu_plugin_get_config_value_boolean(plugin, "Key")); + + /* check it is private, i.e. only readable by the user/group */ + ret = fu_plugin_set_secure_config_value(plugin, "Key", "False", &error); + g_assert_no_error(error); + g_assert_true(ret); + rc = g_stat(fn, &statbuf); + g_assert_cmpint(rc, ==, 0); + g_assert_cmpint(statbuf.st_mode & 0777, ==, 0640); +} + static void fu_plugin_devices_func(void) { @@ -3598,6 +3654,7 @@ main(int argc, char **argv) g_test_add_func("/fwupd/progress{finish}", fu_progress_finish_func); g_test_add_func("/fwupd/bios-attrs{load}", fu_bios_settings_load_func); g_test_add_func("/fwupd/security-attrs{hsi}", fu_security_attrs_hsi_func); + g_test_add_func("/fwupd/plugin{config}", fu_plugin_config_func); g_test_add_func("/fwupd/plugin{devices}", fu_plugin_devices_func); g_test_add_func("/fwupd/plugin{device-inhibit-children}", fu_plugin_device_inhibit_children_func);