[gdm] Store the face and dmrc files in a cache. Refer to bug #565151.
- From: Brian Cameron <bcameron src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gdm] Store the face and dmrc files in a cache. Refer to bug #565151.
- Date: Sat, 12 Sep 2009 01:28:08 +0000 (UTC)
commit c25ef9245be4e0be2126ef3d075df4401949b570
Author: Brian Cameron <Brian Cameron sun com>
Date: Fri Sep 11 20:27:27 2009 -0500
Store the face and dmrc files in a cache. Refer to bug #565151.
configure.ac | 1 +
daemon/Makefile.am | 1 +
daemon/gdm-session-settings.c | 7 +-
daemon/gdm-session-settings.h | 2 +-
daemon/gdm-session-worker.c | 265 +++++++++++++++++++++++++++++++++++-----
data/Makefile.am | 7 +
gui/simple-greeter/Makefile.am | 5 +-
gui/simple-greeter/gdm-user.c | 153 ++---------------------
8 files changed, 264 insertions(+), 177 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 5603865..250e453 100644
--- a/configure.ac
+++ b/configure.ac
@@ -69,6 +69,7 @@ AC_SUBST(COMMON_LIBS)
PKG_CHECK_MODULES(DAEMON,
dbus-glib-1 >= $DBUS_GLIB_REQUIRED_VERSION
gobject-2.0 >= $GLIB_REQUIRED_VERSION
+ gio-2.0 >= $GLIB_REQUIRED_VERSION
)
AC_SUBST(DAEMON_CFLAGS)
AC_SUBST(DAEMON_LIBS)
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 3daf924..a122a15 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -15,6 +15,7 @@ AM_CPPFLAGS = \
-DSBINDIR=\"$(sbindir)\" \
-DGNOMELOCALEDIR=\""$(datadir)/locale"\" \
-DGDM_XAUTH_DIR=\"$(GDM_XAUTH_DIR)\" \
+ -DGDM_CACHE_DIR=\""$(localstatedir)/cache/gdm"\" \
-DGDM_SESSION_DEFAULT_PATH=\"$(GDM_SESSION_DEFAULT_PATH)\" \
$(DISABLE_DEPRECATED_CFLAGS) \
$(DAEMON_CFLAGS) \
diff --git a/daemon/gdm-session-settings.c b/daemon/gdm-session-settings.c
index b6c04f7..421d87a 100644
--- a/daemon/gdm-session-settings.c
+++ b/daemon/gdm-session-settings.c
@@ -267,7 +267,7 @@ gdm_session_settings_is_loaded (GdmSessionSettings *settings)
gboolean
gdm_session_settings_load (GdmSessionSettings *settings,
- const char *home_directory,
+ const char *username,
GError **error)
{
GKeyFile *key_file;
@@ -279,9 +279,10 @@ gdm_session_settings_load (GdmSessionSettings *settings,
char *filename;
g_return_val_if_fail (settings != NULL, FALSE);
- g_return_val_if_fail (home_directory != NULL, FALSE);
+ g_return_val_if_fail (username != NULL, FALSE);
g_return_val_if_fail (!gdm_session_settings_is_loaded (settings), FALSE);
- filename = g_build_filename (home_directory, ".dmrc", NULL);
+
+ filename = g_build_filename (GDM_CACHE_DIR, username, "dmrc", NULL);
is_loaded = FALSE;
key_file = g_key_file_new ();
diff --git a/daemon/gdm-session-settings.h b/daemon/gdm-session-settings.h
index a546598..d579d4a 100644
--- a/daemon/gdm-session-settings.h
+++ b/daemon/gdm-session-settings.h
@@ -54,7 +54,7 @@ GType gdm_session_settings_get_type (void);
GdmSessionSettings *gdm_session_settings_new (void);
gboolean gdm_session_settings_load (GdmSessionSettings *settings,
- const char *home_directory,
+ const char *username,
GError **error);
gboolean gdm_session_settings_save (GdmSessionSettings *settings,
const char *home_directory,
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
index 13e08b1..7a1fafb 100644
--- a/daemon/gdm-session-worker.c
+++ b/daemon/gdm-session-worker.c
@@ -42,6 +42,7 @@
#include <glib/gi18n.h>
#include <glib/gstdio.h>
#include <glib-object.h>
+#include <gio/gio.h>
#define DBUS_API_SUBJECT_TO_CHANGE
#include <dbus/dbus.h>
#include <dbus/dbus-glib.h>
@@ -88,6 +89,8 @@
#define MESSAGE_REPLY_TIMEOUT (10 * 60 * 1000)
+#define MAX_FILE_SIZE 65536
+
enum {
GDM_SESSION_WORKER_STATE_NONE = 0,
GDM_SESSION_WORKER_STATE_SETUP_COMPLETE,
@@ -121,6 +124,7 @@ struct GdmSessionWorkerPrivate
char *hostname;
char *username;
uid_t uid;
+ gid_t gid;
gboolean password_is_required;
int cred_flags;
@@ -590,39 +594,9 @@ static void
attempt_to_load_user_settings (GdmSessionWorker *worker,
const char *username)
{
- struct passwd *passwd_entry;
- uid_t old_uid;
- gid_t old_gid;
-
- old_uid = geteuid ();
- old_gid = getegid ();
-
- passwd_entry = getpwnam (username);
-
- /* User input isn't a valid username
- */
- if (passwd_entry == NULL) {
- return;
- }
-
- /* We may get called late in the pam conversation after
- * the user has already been authenticated. This could
- * happen if for instance, the user's home directory isn't
- * available until late in the pam conversation so user
- * settings couldn't get loaded until late in the conversation.
- * If we get called late the seteuid/setgid calls here will fail,
- * but that's okay, because we'll already be the uid/gid we want
- * to be.
- */
- setegid (passwd_entry->pw_gid);
- seteuid (passwd_entry->pw_uid);
-
gdm_session_settings_load (worker->priv->user_settings,
- passwd_entry->pw_dir,
+ username,
NULL);
-
- seteuid (old_uid);
- setegid (old_gid);
}
static void
@@ -969,6 +943,219 @@ gdm_session_worker_stop_auditor (GdmSessionWorker *worker)
worker->priv->auditor = NULL;
}
+static gboolean
+check_user_copy_file (const char *srcfile,
+ const char *destfile,
+ uid_t user,
+ gssize max_file_size)
+{
+ struct stat srcfileinfo;
+ struct stat destfileinfo;
+
+ if (max_file_size < 0) {
+ max_file_size = G_MAXSIZE;
+ }
+
+ /* Exists/Readable? */
+ if (g_stat (srcfile, &srcfileinfo) < 0) {
+ g_debug ("File does not exist");
+ return FALSE;
+ }
+
+ /* Is newer than the file already in the cache? */
+ if (destfile != NULL && g_stat (destfile, &destfileinfo) == 0) {
+ if (srcfileinfo.st_mtime <= destfileinfo.st_mtime) {
+ g_debug ("Destination file is newer");
+ return FALSE;
+ }
+ }
+
+ /* Is a regular file */
+ if (G_UNLIKELY (!S_ISREG (srcfileinfo.st_mode))) {
+ g_debug ("File is not a regular file");
+ return FALSE;
+ }
+
+ /* Owned by user? */
+ if (G_UNLIKELY (srcfileinfo.st_uid != user)) {
+ g_debug ("File is not owned by user");
+ return FALSE;
+ }
+
+ /* Size is kosher? */
+ if (G_UNLIKELY (srcfileinfo.st_size > max_file_size)) {
+ g_debug ("File is too large");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+gdm_cache_copy_file (GdmSessionWorker *worker,
+ const char *userfilename,
+ const char *cachefilename)
+{
+ gboolean res;
+
+ g_debug ("Checking if %s should be copied to cache %s",
+ userfilename, cachefilename);
+
+ res = check_user_copy_file (userfilename,
+ cachefilename,
+ worker->priv->uid,
+ MAX_FILE_SIZE);
+
+ if (res) {
+ GFile *src_file;
+ GFile *dst_file;
+ GError *error;
+
+ src_file = g_file_new_for_path (userfilename);
+ dst_file = g_file_new_for_path (cachefilename);
+
+ error = NULL;
+ res = g_file_copy (src_file,
+ dst_file,
+ G_FILE_COPY_OVERWRITE |
+ G_FILE_COPY_NOFOLLOW_SYMLINKS,
+ NULL,
+ NULL,
+ NULL,
+ &error);
+
+ if (! res) {
+ g_warning ("Could not copy file to cache: %s",
+ error->message);
+ g_error_free (error);
+ } else {
+ chown (cachefilename,
+ worker->priv->uid,
+ worker->priv->gid);
+ g_chmod (cachefilename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ g_debug ("Copy successful");
+ }
+
+ g_object_unref (src_file);
+ g_object_unref (dst_file);
+ } else {
+ g_debug ("Not copying file %s to cache",
+ userfilename);
+ }
+ return res;
+}
+
+static char *
+gdm_session_worker_create_cachedir (GdmSessionWorker *worker)
+{
+ struct stat statbuf;
+ char *cachedir;
+ int r;
+
+ cachedir = g_build_filename (GDM_CACHE_DIR,
+ worker->priv->username,
+ NULL);
+
+ /* Verify user cache directory exists, create if needed */
+ r = g_stat (cachedir, &statbuf);
+ if (r < 0) {
+ g_debug ("Making user cache directory %s", cachedir);
+ g_mkdir (cachedir,
+ S_IRWXU | S_IXGRP | S_IRGRP | S_IXOTH | S_IROTH);
+ g_chmod (cachedir,
+ S_IRWXU | S_IXGRP | S_IRGRP | S_IXOTH | S_IROTH);
+ }
+ chown (cachedir, worker->priv->uid, worker->priv->gid);
+
+ return cachedir;
+}
+
+static void
+gdm_session_worker_cache_userfiles (GdmSessionWorker *worker)
+{
+ struct passwd *passwd_entry;
+ char *cachedir;
+ char *cachefile;
+ char *userfile;
+ gboolean res;
+
+ passwd_entry = getpwnam (worker->priv->username);
+ if (passwd_entry == NULL)
+ return;
+
+ cachedir = gdm_session_worker_create_cachedir (worker);
+
+ g_debug ("Copying user dmrc file to cache");
+ cachefile = g_build_filename (cachedir, "dmrc", NULL);
+ userfile = g_build_filename (passwd_entry->pw_dir, ".dmrc", NULL);
+
+ gdm_cache_copy_file (worker, userfile, cachefile);
+ g_free (cachefile);
+ g_free (userfile);
+
+ g_debug ("Copying user face file to cache");
+ cachefile = g_build_filename (cachedir,
+ "face",
+ NULL);
+
+ /* First, try "~/.face" */
+ userfile = g_build_filename (passwd_entry->pw_dir, ".face", NULL);
+ res = gdm_cache_copy_file (worker, userfile, cachefile);
+
+ /* Next, try "~/.face.icon" */
+ if (!res) {
+ g_free (userfile);
+ userfile = g_build_filename (passwd_entry->pw_dir,
+ ".face.icon",
+ NULL);
+ res = gdm_cache_copy_file (worker,
+ userfile,
+ cachefile);
+ }
+
+ /* Still nothing, try the user's personal GDM config */
+ if (!res) {
+ char *tempfilename;
+
+ tempfilename = g_build_filename (passwd_entry->pw_dir,
+ ".gnome",
+ "gdm",
+ NULL);
+
+ g_debug ("Checking user's ~/.gnome/gdm file");
+ res = check_user_copy_file (tempfilename,
+ NULL,
+ worker->priv->uid,
+ MAX_FILE_SIZE);
+ if (res) {
+ GKeyFile *keyfile;
+
+ g_free (userfile);
+
+ keyfile = g_key_file_new ();
+ g_key_file_load_from_file (keyfile,
+ userfile,
+ G_KEY_FILE_NONE,
+ NULL);
+
+ userfile = g_key_file_get_string (keyfile,
+ "face",
+ "picture",
+ NULL);
+ res = gdm_cache_copy_file (worker,
+ userfile,
+ cachefile);
+
+ g_key_file_free (keyfile);
+ }
+ g_free (tempfilename);
+ }
+
+ g_free (cachedir);
+ g_free (cachefile);
+ g_free (userfile);
+}
+
static void
gdm_session_worker_uninitialize_pam (GdmSessionWorker *worker,
int status)
@@ -979,6 +1166,7 @@ gdm_session_worker_uninitialize_pam (GdmSessionWorker *worker,
return;
if (worker->priv->state >= GDM_SESSION_WORKER_STATE_SESSION_OPENED) {
+ gdm_session_worker_cache_userfiles (worker);
pam_close_session (worker->priv->pam_handle, 0);
gdm_session_auditor_report_logout (worker->priv->auditor);
@@ -1345,6 +1533,7 @@ _change_user (GdmSessionWorker *worker,
}
#endif
worker->priv->uid = uid;
+ worker->priv->gid = gid;
if (setgid (gid) < 0) {
return FALSE;
@@ -1733,7 +1922,11 @@ _save_user_settings (GdmSessionWorker *worker,
GError *error;
if (!gdm_session_settings_is_loaded (worker->priv->user_settings)) {
- return;
+ /*
+ * Even if the user did not change the defaults, there may
+ * be files to cache
+ */
+ goto out;
}
error = NULL;
@@ -1743,6 +1936,9 @@ _save_user_settings (GdmSessionWorker *worker,
error->message);
g_error_free (error);
}
+
+out:
+ gdm_session_worker_cache_userfiles (worker);
}
static gboolean
@@ -1796,9 +1992,14 @@ gdm_session_worker_start_user_session (GdmSessionWorker *worker,
if (session_pid == 0) {
char **environment;
+ char *cachedirname;
char *home_dir;
int fd;
+ /* Make sure cachedir gets created before we drop to user */
+ cachedirname = gdm_session_worker_create_cachedir (worker);
+ g_free (cachedirname);
+
if (setuid (worker->priv->uid) < 0) {
g_debug ("GdmSessionWorker: could not reset uid - %s", g_strerror (errno));
_exit (1);
diff --git a/data/Makefile.am b/data/Makefile.am
index a317fdd..73fa106 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -13,6 +13,7 @@ predir = $(gdmconfdir)/PreSession
postlogindir = $(gdmconfdir)/PostLogin
workingdir = $(GDM_WORKING_DIR)
xauthdir = $(GDM_XAUTH_DIR)
+cachedir = $(localstatedir)/cache/gdm
Xsession: $(srcdir)/Xsession.in
sed -e 's,[ ]XSESSION_SHELL[@],$(XSESSION_SHELL),g' \
@@ -209,6 +210,12 @@ install-data-hook: gdm.conf-custom Xsession Init PostSession PreSession gconf.pa
chown root:gdm $(DESTDIR)$(workingdir) || : ; \
fi
+ if test '!' -d $(DESTDIR)$(cachedir); then \
+ $(mkinstalldirs) $(DESTDIR)$(cachedir); \
+ chmod 1755 $(DESTDIR)$(cachedir); \
+ chown root:gdm $(DESTDIR)$(cachedir) || : ; \
+ fi
+
$(INSTALL_DATA) $(srcdir)/gconf.path $(DESTDIR)$(workingdir)/.gconf.path
gconftool-2 --direct --config-source=xml:merged:$(DESTDIR)$(workingdir)/.gconf.mandatory --recursive-unset /
gconftool-2 --direct --config-source=xml:merged:$(DESTDIR)$(workingdir)/.gconf.mandatory --load $(srcdir)/session-setup.entries
diff --git a/gui/simple-greeter/Makefile.am b/gui/simple-greeter/Makefile.am
index b36aa28..8c9ae46 100644
--- a/gui/simple-greeter/Makefile.am
+++ b/gui/simple-greeter/Makefile.am
@@ -13,11 +13,12 @@ AM_CPPFLAGS = \
-DSYSCONFDIR=\""$(sysconfdir)"\" \
-DLIBLOCALEDIR=\""$(prefix)/lib/locale"\" \
-DGNOMELOCALEDIR=\""$(datadir)/locale"\" \
- -DGLADEDIR=\""$(pkgdatadir)"\" \
+ -DGLADEDIR=\""$(pkgdatadir)"\" \
-DLIBEXECDIR=\""$(libexecdir)"\" \
-DSBINDIR=\""$(sbindir)"\" \
+ -DGDM_CACHE_DIR=\""$(localstatedir)/cache/gdm"\" \
-DAT_SPI_REGISTRYD_DIR="\"$(AT_SPI_REGISTRYD_DIR)\"" \
- $(DISABLE_DEPRECATED_CFLAGS) \
+ $(DISABLE_DEPRECATED_CFLAGS) \
$(GTK_CFLAGS) \
$(SIMPLE_GREETER_CFLAGS) \
$(NULL)
diff --git a/gui/simple-greeter/gdm-user.c b/gui/simple-greeter/gdm-user.c
index c25cfa0..32d3d6a 100644
--- a/gui/simple-greeter/gdm-user.c
+++ b/gui/simple-greeter/gdm-user.c
@@ -41,8 +41,6 @@
#define MAX_ICON_SIZE 128
#define MAX_FILE_SIZE 65536
#define MINIMAL_UID 100
-#define RELAX_GROUP TRUE
-#define RELAX_OTHER TRUE
enum {
PROP_0,
@@ -764,10 +762,7 @@ gdm_user_collate (GdmUser *user1,
static gboolean
check_user_file (const char *filename,
- uid_t user,
- gssize max_file_size,
- gboolean relax_group,
- gboolean relax_other)
+ gssize max_file_size)
{
struct stat fileinfo;
@@ -777,31 +772,19 @@ check_user_file (const char *filename,
/* Exists/Readable? */
if (stat (filename, &fileinfo) < 0) {
+ g_debug ("File does not exist");
return FALSE;
}
/* Is a regular file */
if (G_UNLIKELY (!S_ISREG (fileinfo.st_mode))) {
- return FALSE;
- }
-
- /* Owned by user? */
- if (G_UNLIKELY (fileinfo.st_uid != user)) {
- return FALSE;
- }
-
- /* Group not writable or relax_group? */
- if (G_UNLIKELY ((fileinfo.st_mode & S_IWGRP) == S_IWGRP && !relax_group)) {
- return FALSE;
- }
-
- /* Other not writable or relax_other? */
- if (G_UNLIKELY ((fileinfo.st_mode & S_IWOTH) == S_IWOTH && !relax_other)) {
+ g_debug ("File is not a regular file");
return FALSE;
}
/* Size is kosher? */
if (G_UNLIKELY (fileinfo.st_size > max_file_size)) {
+ g_debug ("File is too large");
return FALSE;
}
@@ -842,133 +825,29 @@ get_filesystem_type (const char *path)
}
static GdkPixbuf *
-render_icon_from_home (GdmUser *user,
- int icon_size)
+render_icon_from_cache (GdmUser *user,
+ int icon_size)
{
GdkPixbuf *retval;
char *path;
- gboolean is_local;
gboolean is_autofs;
gboolean res;
char *filesystem_type;
- is_local = FALSE;
-
- /* special case: look at parent of home to detect autofs
- this is so we don't try to trigger an automount */
- path = g_path_get_dirname (user->home_dir);
- filesystem_type = get_filesystem_type (path);
- is_autofs = (filesystem_type != NULL && strcmp (filesystem_type, "autofs") == 0);
- g_free (filesystem_type);
- g_free (path);
-
- if (is_autofs) {
- return NULL;
- }
-
- /* now check that home dir itself is local */
- filesystem_type = get_filesystem_type (user->home_dir);
- is_local = ((filesystem_type != NULL) &&
- (strcmp (filesystem_type, "nfs") != 0) &&
- (strcmp (filesystem_type, "afs") != 0) &&
- (strcmp (filesystem_type, "autofs") != 0) &&
- (strcmp (filesystem_type, "unknown") != 0) &&
- (strcmp (filesystem_type, "ncpfs") != 0));
- g_free (filesystem_type);
-
- /* only look at local home directories so we don't try to
- read from remote (e.g. NFS) volumes */
- if (! is_local) {
- return NULL;
- }
-
- /* First, try "~/.face" */
- path = g_build_filename (user->home_dir, ".face", NULL);
+ path = g_build_filename (GDM_CACHE_DIR, user->user_name, "face", NULL);
res = check_user_file (path,
- user->uid,
- MAX_FILE_SIZE,
- RELAX_GROUP,
- RELAX_OTHER);
+ MAX_FILE_SIZE);
if (res) {
retval = gdk_pixbuf_new_from_file_at_size (path,
icon_size,
icon_size,
NULL);
} else {
+ g_debug ("Could not access face icon %s", path);
retval = NULL;
}
g_free (path);
- /* Next, try "~/.face.icon" */
- if (retval == NULL) {
- path = g_build_filename (user->home_dir,
- ".face.icon",
- NULL);
- res = check_user_file (path,
- user->uid,
- MAX_FILE_SIZE,
- RELAX_GROUP,
- RELAX_OTHER);
- if (res) {
- retval = gdk_pixbuf_new_from_file_at_size (path,
- icon_size,
- icon_size,
- NULL);
- } else {
- retval = NULL;
- }
-
- g_free (path);
- }
-
- /* Still nothing, try the user's personal GDM config */
- if (retval == NULL) {
- path = g_build_filename (user->home_dir,
- ".gnome",
- "gdm",
- NULL);
- res = check_user_file (path,
- user->uid,
- MAX_FILE_SIZE,
- RELAX_GROUP,
- RELAX_OTHER);
- if (res) {
- GKeyFile *keyfile;
- char *icon_path;
-
- keyfile = g_key_file_new ();
- g_key_file_load_from_file (keyfile,
- path,
- G_KEY_FILE_NONE,
- NULL);
-
- icon_path = g_key_file_get_string (keyfile,
- "face",
- "picture",
- NULL);
- res = check_user_file (icon_path,
- user->uid,
- MAX_FILE_SIZE,
- RELAX_GROUP,
- RELAX_OTHER);
- if (icon_path && res) {
- retval = gdk_pixbuf_new_from_file_at_size (path,
- icon_size,
- icon_size,
- NULL);
- } else {
- retval = NULL;
- }
-
- g_free (icon_path);
- g_key_file_free (keyfile);
- } else {
- retval = NULL;
- }
-
- g_free (path);
- }
-
return retval;
}
@@ -1218,7 +1097,7 @@ gdm_user_render_icon (GdmUser *user,
path = NULL;
- pixbuf = render_icon_from_home (user, icon_size);
+ pixbuf = render_icon_from_cache (user, icon_size);
if (pixbuf != NULL) {
goto out;
}
@@ -1226,16 +1105,14 @@ gdm_user_render_icon (GdmUser *user,
/* Try ${GlobalFaceDir}/${username} */
path = g_build_filename (GLOBAL_FACEDIR, user->user_name, NULL);
res = check_user_file (path,
- user->uid,
- MAX_FILE_SIZE,
- RELAX_GROUP,
- RELAX_OTHER);
+ MAX_FILE_SIZE);
if (res) {
pixbuf = gdk_pixbuf_new_from_file_at_size (path,
icon_size,
icon_size,
NULL);
} else {
+ g_debug ("Could not access global face icon %s", path);
pixbuf = NULL;
}
@@ -1249,16 +1126,14 @@ gdm_user_render_icon (GdmUser *user,
path = g_build_filename (GLOBAL_FACEDIR, tmp, NULL);
g_free (tmp);
res = check_user_file (path,
- user->uid,
- MAX_FILE_SIZE,
- RELAX_GROUP,
- RELAX_OTHER);
+ MAX_FILE_SIZE);
if (res) {
pixbuf = gdk_pixbuf_new_from_file_at_size (path,
icon_size,
icon_size,
NULL);
} else {
+ g_debug ("Could not access global face icon %s", path);
pixbuf = NULL;
}
g_free (path);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]