diff options
author | Allison Ryan Lortie <desrt@desrt.ca> | 2015-11-11 09:23:18 -0500 |
---|---|---|
committer | Allison Ryan Lortie <desrt@desrt.ca> | 2015-11-11 09:23:18 -0500 |
commit | 4ef5a2a4c6ac349f51a1cd5f9013efe8c5f26f12 (patch) | |
tree | 7c2835b5eb731488eae3c04ecaeeaa8e1b0e8875 /engine | |
parent | 7c0beccf286a1dbd396fda7d40b438598a6ce7f4 (diff) | |
download | dconf-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.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) { |