[dconf] engine: add support for runtime profile selection
- From: Ryan Lortie <desrt src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [dconf] engine: add support for runtime profile selection
- Date: Wed, 11 Nov 2015 14:24:50 +0000 (UTC)
commit 4ef5a2a4c6ac349f51a1cd5f9013efe8c5f26f12
Author: Allison Ryan Lortie <desrt desrt ca>
Date: Wed Nov 11 09:23:18 2015 -0500
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
engine/dconf-engine-profile.c | 89 +++++++++++++++++++++++++++++++++++------
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)
{
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]