summaryrefslogtreecommitdiff
path: root/engine
diff options
context:
space:
mode:
authorAllison Ryan Lortie <desrt@desrt.ca>2015-11-11 09:23:18 -0500
committerAllison Ryan Lortie <desrt@desrt.ca>2015-11-11 09:23:18 -0500
commit4ef5a2a4c6ac349f51a1cd5f9013efe8c5f26f12 (patch)
tree7c2835b5eb731488eae3c04ecaeeaa8e1b0e8875 /engine
parent7c0beccf286a1dbd396fda7d40b438598a6ce7f4 (diff)
downloaddconf-4ef5a2a4c6ac349f51a1cd5f9013efe8c5f26f12.tar.gz
engine: add support for runtime profile selection
Add support to dconf-engine for opening "runtime" profiles. These profiles are intended to be symbolic links or plain files that will live either in XDG_RUNTIME_DIR/dconf/profile or /run/dconf/user/$(uid). This is intended to allow for a PAM module that makes complex decisions about application of a specific policy to a user and sets up the profile at login time, thus preventing the need for this complex decision to be a part of every program that uses dconf. This PAM module would not be part of dconf, but would rather be a part of a dconf-aware system administrator framework. In the case that the profile file is found in /run/dconf, then it will not be possible for the user to override the profile selection, including via the DCONF_PROFILE environment variable. This provides a mechanism for lockdown that is slightly more difficult for a user to circumvent. In theory, this is pointless since it can still be defeated with LD_PRELOAD, but in practice this raises the bar quite a bit. https://bugzilla.gnome.org/show_bug.cgi?id=751417
Diffstat (limited to 'engine')
-rw-r--r--engine/dconf-engine-profile.c89
1 files changed, 77 insertions, 12 deletions
diff --git a/engine/dconf-engine-profile.c b/engine/dconf-engine-profile.c
index d3163b5..cc9f83f 100644
--- a/engine/dconf-engine-profile.c
+++ b/engine/dconf-engine-profile.c
@@ -28,6 +28,9 @@
#include "dconf-engine-source.h"
+#define MANDATORY_DIR "/run/dconf/user/" /* + getuid () */
+#define RUNTIME_PROFILE /* XDG_RUNTIME_DIR + */ "/dconf/profile"
+
/* This comment attempts to document the exact semantics of
* profile-loading.
*
@@ -224,30 +227,92 @@ dconf_engine_open_profile_file (const gchar *profile)
return fp;
}
+static FILE *
+dconf_engine_open_mandatory_profile (void)
+{
+ gchar path[20 + sizeof MANDATORY_DIR];
+ gint mdlen = strlen (MANDATORY_DIR);
+
+ memcpy (path, MANDATORY_DIR, mdlen);
+ snprintf (path + mdlen, 20, "%u", (guint) getuid ());
+
+ return fopen (path, "r");
+}
+
+static FILE *
+dconf_engine_open_runtime_profile (void)
+{
+ const gchar *runtime_dir;
+ gchar *path;
+ gint rdlen;
+
+ runtime_dir = g_get_user_runtime_dir ();
+ rdlen = strlen (runtime_dir);
+
+ path = g_alloca (rdlen + sizeof RUNTIME_PROFILE);
+ memcpy (path, runtime_dir, rdlen);
+ memcpy (path + rdlen, RUNTIME_PROFILE, sizeof RUNTIME_PROFILE);
+
+ return fopen (path, "r");
+}
+
DConfEngineSource **
dconf_engine_profile_open (const gchar *profile,
gint *n_sources)
{
DConfEngineSource **sources;
- FILE *file;
+ FILE *file = NULL;
+
+ /* We must consider a few different possibilities for the dconf
+ * profile file. We proceed until we have either
+ *
+ * a) a profile name; or
+ *
+ * b) a profile file is open
+ *
+ * If we get a profile name, even if the file is missing, we will use
+ * that name rather than falling back to another possibility. In this
+ * case, we will issue a warning.
+ *
+ * Therefore, at each step, we ensure that there is no profile name or
+ * file yet open before checking the next possibility.
+ *
+ * Note that @profile is an argument to this function, so we will end
+ * up trying none of the five possibilities if that is given.
+ */
+ /* 1. Mandatory profile */
if (profile == NULL)
+ file = dconf_engine_open_mandatory_profile ();
+
+ /* 2. Environment variable */
+ if (profile == NULL && file == NULL)
profile = g_getenv ("DCONF_PROFILE");
- if (profile == NULL)
+ /* 3. Runtime profile */
+ if (profile == NULL && file == NULL)
+ file = dconf_engine_open_runtime_profile ();
+
+ /* 4. User profile */
+ if (profile == NULL && file == NULL)
+ file = dconf_engine_open_profile_file ("user");
+
+ /* 5. Default profile */
+ if (profile == NULL && file == NULL)
+ return dconf_engine_default_profile (n_sources);
+
+ /* At this point either we have a profile name or file open, but never
+ * both. If it's a profile name, we try to open it.
+ */
+ if (profile != NULL)
{
- file = dconf_engine_open_profile_file ("user");
+ g_assert (file == NULL);
- /* Only in the case that no profile was specified do we use this
- * fallback.
- */
- if (file == NULL)
- return dconf_engine_default_profile (n_sources);
+ if (profile[0] != '/')
+ file = dconf_engine_open_profile_file (profile);
+ else
+ file = fopen (profile, "r");
}
- else if (profile[0] != '/')
- file = dconf_engine_open_profile_file (profile);
- else
- file = fopen (profile, "r");
if (file != NULL)
{