diff options
author | Michael Terry <michael.terry@canonical.com> | 2014-02-04 17:55:32 -0500 |
---|---|---|
committer | Michael Terry <michael.terry@canonical.com> | 2014-02-04 17:55:32 -0500 |
commit | 5ba3bc15922902272de7009e02650d39a40da834 (patch) | |
tree | df40f0c89c23902abefe7a83b3a3188489c12b58 | |
parent | d5bf5930e9c60fb08c04904fe5befc7ca1a36aa9 (diff) | |
download | lightdm-5ba3bc15922902272de7009e02650d39a40da834.tar.gz |
And convert accounts.c to use new sharable CommonUser class too
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | common/Makefile.am | 23 | ||||
-rw-r--r-- | common/configuration.c (renamed from src/configuration.c) | 0 | ||||
-rw-r--r-- | common/configuration.h (renamed from src/configuration.h) | 0 | ||||
-rw-r--r-- | common/dmrc.c (renamed from src/dmrc.c) | 59 | ||||
-rw-r--r-- | common/dmrc.h (renamed from src/dmrc.h) | 5 | ||||
-rw-r--r-- | common/privileges.c (renamed from src/privileges.c) | 18 | ||||
-rw-r--r-- | common/privileges.h (renamed from src/privileges.h) | 4 | ||||
-rw-r--r-- | common/user-list.c | 499 | ||||
-rw-r--r-- | common/user-list.h | 11 | ||||
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | liblightdm-gobject/Makefile.am | 6 | ||||
-rw-r--r-- | liblightdm-gobject/session.c | 11 | ||||
-rw-r--r-- | liblightdm-gobject/user.c | 2 | ||||
-rw-r--r-- | src/Makefile.am | 8 | ||||
-rw-r--r-- | src/accounts.c | 374 | ||||
-rw-r--r-- | src/accounts.h | 4 | ||||
-rw-r--r-- | src/session-child.c | 4 | ||||
-rw-r--r-- | tests/src/test-gobject-greeter.c | 5 | ||||
-rw-r--r-- | tests/src/test-runner.c | 15 |
20 files changed, 486 insertions, 565 deletions
diff --git a/Makefile.am b/Makefile.am index 73c6788e..106e891e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = +SUBDIRS = common if COMPILE_LIBLIGHTDM_GOBJECT SUBDIRS += liblightdm-gobject endif diff --git a/common/Makefile.am b/common/Makefile.am new file mode 100644 index 00000000..f289e6ac --- /dev/null +++ b/common/Makefile.am @@ -0,0 +1,23 @@ +# -*- Mode: Automake; indent-tabs-mode: t; tab-width: 4 -*- + +noinst_LTLIBRARIES = libcommon.la + +libcommon_la_SOURCES = \ + configuration.c \ + configuration.h \ + dmrc.c \ + dmrc.h \ + privileges.c \ + privileges.h \ + user-list.c \ + user-list.h + +libcommon_la_CFLAGS = \ + $(WARN_CFLAGS) \ + $(GLIB_CFLAGS) + +libcommon_la_LIBADD = \ + $(GLIB_LDFLAGS) + +DISTCLEANFILES = \ + Makefile.in diff --git a/src/configuration.c b/common/configuration.c index 5268c8d9..5268c8d9 100644 --- a/src/configuration.c +++ b/common/configuration.c diff --git a/src/configuration.h b/common/configuration.h index cae56912..cae56912 100644 --- a/src/configuration.h +++ b/common/configuration.h diff --git a/src/dmrc.c b/common/dmrc.c index ccde1bf1..e7121ef7 100644 --- a/src/dmrc.c +++ b/common/dmrc.c @@ -15,34 +15,26 @@ #include "dmrc.h" #include "configuration.h" -#include "accounts.h" #include "privileges.h" +#include "user-list.h" GKeyFile * -dmrc_load (const gchar *username) +dmrc_load (CommonUser *user) { - User *user; GKeyFile *dmrc_file; gchar *path; gboolean have_dmrc, drop_privileges; dmrc_file = g_key_file_new (); - user = accounts_get_user_by_name (username); - if (!user) - { - g_warning ("Cannot load .dmrc file, unable to get information on user %s", username); - return dmrc_file; - } - /* Load from the user directory, if this fails (e.g. the user directory * is not yet mounted) then load from the cache */ - path = g_build_filename (user_get_home_directory (user), ".dmrc", NULL); + path = g_build_filename (common_user_get_home_directory (user), ".dmrc", NULL); /* Guard against privilege escalation through symlinks, etc. */ drop_privileges = geteuid () == 0; if (drop_privileges) - privileges_drop (user); + privileges_drop (common_user_get_uid (user), common_user_get_gid (user)); have_dmrc = g_key_file_load_from_file (dmrc_file, path, G_KEY_FILE_KEEP_COMMENTS, NULL); if (drop_privileges) privileges_reclaim (); @@ -53,7 +45,7 @@ dmrc_load (const gchar *username) { gchar *filename, *cache_dir; - filename = g_strdup_printf ("%s.dmrc", user_get_name (user)); + filename = g_strdup_printf ("%s.dmrc", common_user_get_name (user)); cache_dir = config_get_string (config_get_instance (), "LightDM", "cache-directory"); path = g_build_filename (cache_dir, "dmrc", filename, NULL); g_free (filename); @@ -63,46 +55,32 @@ dmrc_load (const gchar *username) g_free (path); } - g_object_unref (user); - return dmrc_file; } void -dmrc_save (GKeyFile *dmrc_file, const gchar *username) +dmrc_save (GKeyFile *dmrc_file, CommonUser *user) { - User *user; gchar *path, *filename, *cache_dir, *dmrc_cache_dir; gchar *data; gsize length; - - user = accounts_get_user_by_name (username); - if (!user) - { - g_warning ("Not saving DMRC file - unable to get information on user %s", username); - return; - } + gboolean drop_privileges; data = g_key_file_to_data (dmrc_file, &length, NULL); /* Update the users .dmrc */ - if (user) - { - gboolean drop_privileges; - - path = g_build_filename (user_get_home_directory (user), ".dmrc", NULL); + path = g_build_filename (common_user_get_home_directory (user), ".dmrc", NULL); - /* Guard against privilege escalation through symlinks, etc. */ - drop_privileges = geteuid () == 0; - if (drop_privileges) - privileges_drop (user); - g_debug ("Writing %s", path); - g_file_set_contents (path, data, length, NULL); - if (drop_privileges) - privileges_reclaim (); + /* Guard against privilege escalation through symlinks, etc. */ + drop_privileges = geteuid () == 0; + if (drop_privileges) + privileges_drop (common_user_get_uid (user), common_user_get_gid (user)); + g_debug ("Writing %s", path); + g_file_set_contents (path, data, length, NULL); + if (drop_privileges) + privileges_reclaim (); - g_free (path); - } + g_free (path); /* Update the .dmrc cache */ cache_dir = config_get_string (config_get_instance (), "LightDM", "cache-directory"); @@ -110,12 +88,11 @@ dmrc_save (GKeyFile *dmrc_file, const gchar *username) if (g_mkdir_with_parents (dmrc_cache_dir, 0700) < 0) g_warning ("Failed to make DMRC cache directory %s: %s", dmrc_cache_dir, strerror (errno)); - filename = g_strdup_printf ("%s.dmrc", username); + filename = g_strdup_printf ("%s.dmrc", common_user_get_name (user)); path = g_build_filename (dmrc_cache_dir, filename, NULL); g_file_set_contents (path, data, length, NULL); g_free (dmrc_cache_dir); g_free (path); g_free (filename); - g_object_unref (user); } diff --git a/src/dmrc.h b/common/dmrc.h index 5e93d2f7..ed1381cc 100644 --- a/src/dmrc.h +++ b/common/dmrc.h @@ -13,12 +13,13 @@ #define DMRC_H_ #include <glib.h> +#include "user-list.h" G_BEGIN_DECLS -GKeyFile *dmrc_load (const gchar *username); +GKeyFile *dmrc_load (CommonUser *user); -void dmrc_save (GKeyFile *dmrc_file, const gchar *username); +void dmrc_save (GKeyFile *dmrc_file, CommonUser *user); G_END_DECLS diff --git a/src/privileges.c b/common/privileges.c index 7165b8de..11f34001 100644 --- a/src/privileges.c +++ b/common/privileges.c @@ -13,24 +13,24 @@ #define _GNU_SOURCE #include <config.h> +#include <glib.h> +#include <unistd.h> #include "privileges.h" void -privileges_drop (User *user) +privileges_drop (uid_t uid, gid_t gid) { - g_return_if_fail (user != NULL); - #ifdef HAVE_SETRESGID - g_assert (setresgid (user_get_gid (user), user_get_gid (user), -1) == 0); + g_assert (setresgid (gid, gid, -1) == 0); #else - g_assert (setgid (user_get_gid (user)) == 0); - g_assert (setegid (user_get_gid (user)) == 0); + g_assert (setgid (gid) == 0); + g_assert (setegid (gid) == 0); #endif #ifdef HAVE_SETRESUID - g_assert (setresuid (user_get_uid (user), user_get_uid (user), -1) == 0); + g_assert (setresuid (uid, uid, -1) == 0); #else - g_assert (setuid (user_get_uid (user)) == 0); - g_assert (seteuid (user_get_uid (user)) == 0); + g_assert (setuid (uid) == 0); + g_assert (seteuid (uid) == 0); #endif } diff --git a/src/privileges.h b/common/privileges.h index bc407abd..448b0350 100644 --- a/src/privileges.h +++ b/common/privileges.h @@ -12,9 +12,9 @@ #ifndef PRIVILEGES_H_ #define PRIVILEGES_H_ -#include "accounts.h" +#include <sys/types.h> -void privileges_drop (User *user); +void privileges_drop (uid_t uid, gid_t gid); void privileges_reclaim (void); diff --git a/common/user-list.c b/common/user-list.c index 58c96aca..d64e615f 100644 --- a/common/user-list.c +++ b/common/user-list.c @@ -19,6 +19,7 @@ #include <pwd.h> #include <gio/gio.h> +#include "dmrc.h" #include "user-list.h" enum @@ -35,6 +36,7 @@ enum USER_PROP_REAL_NAME, USER_PROP_DISPLAY_NAME, USER_PROP_HOME_DIRECTORY, + USER_PROP_SHELL, USER_PROP_IMAGE, USER_PROP_BACKGROUND, USER_PROP_LANGUAGE, @@ -42,7 +44,9 @@ enum USER_PROP_LAYOUTS, USER_PROP_SESSION, USER_PROP_LOGGED_IN, - USER_PROP_HAS_MESSAGES + USER_PROP_HAS_MESSAGES, + USER_PROP_UID, + USER_PROP_GID, }; enum @@ -98,9 +102,6 @@ typedef struct /* Accounts service path */ gchar *path; - /* DMRC file */ - GKeyFile *dmrc_file; - /* Update signal from accounts service */ guint changed_signal; @@ -113,6 +114,9 @@ typedef struct /* Home directory of user */ gchar *home_directory; + /* Shell for user */ + gchar *shell; + /* Image for user */ gchar *image; @@ -122,6 +126,12 @@ typedef struct /* TRUE if this user has messages available */ gboolean has_messages; + /* UID of user */ + guint64 uid; + + /* GID of user */ + guint64 gid; + /* User chosen language */ gchar *language; @@ -137,18 +147,18 @@ typedef struct GObject parent_instance; gchar *path; gchar *username; -} Session; +} CommonSession; typedef struct { GObjectClass parent_class; -} SessionClass; +} CommonSessionClass; G_DEFINE_TYPE (CommonUserList, common_user_list, G_TYPE_OBJECT); G_DEFINE_TYPE (CommonUser, common_user, G_TYPE_OBJECT); -#define SESSION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), session_get_type (), Session)) -GType session_get_type (void); -G_DEFINE_TYPE (Session, session, G_TYPE_OBJECT); +#define COMMON_SESSION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), common_session_get_type (), CommonSession)) +GType common_session_get_type (void); +G_DEFINE_TYPE (CommonSession, common_session, G_TYPE_OBJECT); #define GET_LIST_PRIVATE(obj) G_TYPE_INSTANCE_GET_PRIVATE ((obj), COMMON_TYPE_USER_LIST, CommonUserListPrivate) #define GET_USER_PRIVATE(obj) G_TYPE_INSTANCE_GET_PRIVATE ((obj), COMMON_TYPE_USER, CommonUserPrivate) @@ -213,13 +223,14 @@ compare_user (gconstpointer a, gconstpointer b) } static gboolean -update_passwd_user (CommonUser *user, const gchar *real_name, const gchar *home_directory, const gchar *image) +update_passwd_user (CommonUser *user, const gchar *real_name, const gchar *home_directory, const gchar *shell, const gchar *image) { CommonUserPrivate *priv = GET_USER_PRIVATE (user); /* Skip if already set to this */ if (g_strcmp0 (common_user_get_real_name (user), real_name) == 0 && g_strcmp0 (common_user_get_home_directory (user), home_directory) == 0 && + g_strcmp0 (common_user_get_shell (user), shell) == 0 && g_strcmp0 (common_user_get_image (user), image) == 0) return FALSE; @@ -227,6 +238,8 @@ update_passwd_user (CommonUser *user, const gchar *real_name, const gchar *home_ priv->real_name = g_strdup (real_name); g_free (priv->home_directory); priv->home_directory = g_strdup (home_directory); + g_free (priv->shell); + priv->shell = g_strdup (shell); g_free (priv->image); priv->image = g_strdup (image); @@ -239,6 +252,45 @@ user_changed_cb (CommonUser *user) g_signal_emit (GET_USER_PRIVATE (user)->user_list, list_signals[USER_CHANGED], 0, user); } +static CommonUser * +make_passwd_user (CommonUserList *user_list, struct passwd *entry) +{ + CommonUser *user = g_object_new (COMMON_TYPE_USER, NULL); + CommonUserPrivate *priv = GET_USER_PRIVATE (user); + char **tokens; + gchar *real_name, *image; + + tokens = g_strsplit (entry->pw_gecos, ",", -1); + if (tokens[0] != NULL && tokens[0][0] != '\0') + real_name = g_strdup (tokens[0]); + else + real_name = g_strdup (""); + g_strfreev (tokens); + + image = g_build_filename (entry->pw_dir, ".face", NULL); + if (!g_file_test (image, G_FILE_TEST_EXISTS)) + { + g_free (image); + image = g_build_filename (entry->pw_dir, ".face.icon", NULL); + if (!g_file_test (image, G_FILE_TEST_EXISTS)) + { + g_free (image); + image = NULL; + } + } + + priv->user_list = user_list; + priv->name = g_strdup (entry->pw_name); + priv->real_name = real_name; + priv->home_directory = g_strdup (entry->pw_dir); + priv->shell = g_strdup (entry->pw_shell); + priv->image = image; + priv->uid = entry->pw_uid; + priv->gid = entry->pw_gid; + + return user; +} + static void load_passwd_file (CommonUserList *user_list, gboolean emit_add_signal) { @@ -283,9 +335,6 @@ load_passwd_file (CommonUserList *user_list, gboolean emit_add_signal) { struct passwd *entry; CommonUser *user; - CommonUserPrivate *user_priv; - char **tokens; - gchar *real_name, *image; int i; errno = 0; @@ -310,36 +359,7 @@ load_passwd_file (CommonUserList *user_list, gboolean emit_add_signal) if (hidden_users[i]) continue; - tokens = g_strsplit (entry->pw_gecos, ",", -1); - if (tokens[0] != NULL && tokens[0][0] != '\0') - real_name = g_strdup (tokens[0]); - else - real_name = g_strdup (""); - g_strfreev (tokens); - - image = g_build_filename (entry->pw_dir, ".face", NULL); - if (!g_file_test (image, G_FILE_TEST_EXISTS)) - { - g_free (image); - image = g_build_filename (entry->pw_dir, ".face.icon", NULL); - if (!g_file_test (image, G_FILE_TEST_EXISTS)) - { - g_free (image); - image = NULL; - } - } - - user = g_object_new (COMMON_TYPE_USER, NULL); - user_priv = GET_USER_PRIVATE (user); - user_priv->user_list = user_list; - g_free (user_priv->name); - user_priv->name = g_strdup (entry->pw_name); - g_free (user_priv->real_name); - user_priv->real_name = real_name; - g_free (user_priv->home_directory); - user_priv->home_directory = g_strdup (entry->pw_dir); - g_free (user_priv->image); - user_priv->image = image; + user = make_passwd_user (user_list, entry); /* Update existing users if have them */ for (link = priv->users; link; link = link->next) @@ -347,7 +367,7 @@ load_passwd_file (CommonUserList *user_list, gboolean emit_add_signal) CommonUser *info = link->data; if (strcmp (common_user_get_name (info), common_user_get_name (user)) == 0) { - if (update_passwd_user (info, common_user_get_real_name (user), common_user_get_home_directory (user), common_user_get_image (user))) + if (update_passwd_user (info, common_user_get_real_name (user), common_user_get_home_directory (user), common_user_get_shell (user), common_user_get_image (user))) changed_users = g_list_insert_sorted (changed_users, info, compare_user); g_object_unref (user); user = info; @@ -500,6 +520,11 @@ load_accounts_user (CommonUser *user) g_free (priv->home_directory); priv->home_directory = g_variant_dup_string (value, NULL); } + else if (strcmp (name, "Shell") == 0 && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING)) + { + g_free (priv->shell); + priv->shell = g_variant_dup_string (value, NULL); + } else if (strcmp (name, "SystemAccount") == 0 && g_variant_is_of_type (value, G_VARIANT_TYPE_BOOLEAN)) system_account = g_variant_get_boolean (value); else if (strcmp (name, "Language") == 0 && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING)) @@ -545,6 +570,8 @@ load_accounts_user (CommonUser *user) } else if (strcmp (name, "XHasMessages") == 0 && g_variant_is_of_type (value, G_VARIANT_TYPE_BOOLEAN)) priv->has_messages = g_variant_get_boolean (value); + else if (strcmp (name, "Uid") == 0 && g_variant_is_of_type (value, G_VARIANT_TYPE_UINT64)) + priv->uid = g_variant_get_uint64 (value); } g_variant_iter_free (iter); @@ -641,11 +668,11 @@ accounts_user_deleted_cb (GDBusConnection *connection, } } -static Session * +static CommonSession * load_session (CommonUserList *user_list, const gchar *path) { CommonUserListPrivate *priv = GET_LIST_PRIVATE (user_list); - Session *session = NULL; + CommonSession *session = NULL; GVariant *result, *username; GError *error = NULL; @@ -674,7 +701,7 @@ load_session (CommonUserList *user_list, const gchar *path) g_variant_get (username, "&s", &name); g_debug ("Loaded session %s (%s)", path, name); - session = g_object_new (session_get_type (), NULL); + session = g_object_new (common_session_get_type (), NULL); session->username = g_strdup (name); session->path = g_strdup (path); priv->sessions = g_list_append (priv->sessions, session); @@ -696,7 +723,7 @@ session_added_cb (GDBusConnection *connection, { CommonUserList *user_list = data; gchar *path; - Session *session; + CommonSession *session; CommonUser *user = NULL; if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(o)"))) @@ -737,7 +764,7 @@ session_removed_cb (GDBusConnection *connection, for (link = priv->sessions; link; link = link->next) { - Session *session = link->data; + CommonSession *session = link->data; if (strcmp (session->path, path) == 0) { CommonUser *user; @@ -754,6 +781,72 @@ session_removed_cb (GDBusConnection *connection, } static void +load_sessions (CommonUserList *user_list) +{ + CommonUserListPrivate *priv = GET_LIST_PRIVATE (user_list); + GVariant *result; + GError *error = NULL; + + priv->session_added_signal = g_dbus_connection_signal_subscribe (priv->bus, + "org.freedesktop.DisplayManager", + "org.freedesktop.DisplayManager", + "SessionAdded", + "/org/freedesktop/DisplayManager", + NULL, + G_DBUS_SIGNAL_FLAGS_NONE, + session_added_cb, + user_list, + NULL); + priv->session_removed_signal = g_dbus_connection_signal_subscribe (priv->bus, + "org.freedesktop.DisplayManager", + "org.freedesktop.DisplayManager", + "SessionRemoved", + "/org/freedesktop/DisplayManager", + NULL, + G_DBUS_SIGNAL_FLAGS_NONE, + session_removed_cb, + user_list, + NULL); + result = g_dbus_connection_call_sync (priv->bus, + "org.freedesktop.DisplayManager", + "/org/freedesktop/DisplayManager", + "org.freedesktop.DBus.Properties", + "Get", + g_variant_new ("(ss)", "org.freedesktop.DisplayManager", "Sessions"), + G_VARIANT_TYPE ("(v)"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + if (error) + g_warning ("Error getting session list from org.freedesktop.DisplayManager: %s", error->message); + g_clear_error (&error); + if (result) + { + if (g_variant_is_of_type (result, G_VARIANT_TYPE ("(v)"))) + { + GVariant *value; + GVariantIter *iter; + const gchar *path; + + g_variant_get (result, "(v)", &value); + + g_debug ("Loading sessions from org.freedesktop.DisplayManager"); + g_variant_get (value, "ao", &iter); + while (g_variant_iter_loop (iter, "&o", &path)) + load_session (user_list, path); + g_variant_iter_free (iter); + + g_variant_unref (value); + } + else + g_warning ("Unexpected type from org.freedesktop.DisplayManager.Sessions: %s", g_variant_get_type_string (result)); + + g_variant_unref (result); + } +} + +static void load_users (CommonUserList *user_list) { CommonUserListPrivate *priv = GET_LIST_PRIVATE (user_list); @@ -833,65 +926,6 @@ load_users (CommonUserList *user_list) g_signal_connect (priv->passwd_monitor, "changed", G_CALLBACK (passwd_changed_cb), user_list); g_clear_error (&error); } - - priv->session_added_signal = g_dbus_connection_signal_subscribe (priv->bus, - "org.freedesktop.DisplayManager", - "org.freedesktop.DisplayManager", - "SessionAdded", - "/org/freedesktop/DisplayManager", - NULL, - G_DBUS_SIGNAL_FLAGS_NONE, - session_added_cb, - user_list, - NULL); - priv->session_removed_signal = g_dbus_connection_signal_subscribe (priv->bus, - "org.freedesktop.DisplayManager", - "org.freedesktop.DisplayManager", - "SessionRemoved", - "/org/freedesktop/DisplayManager", - NULL, - G_DBUS_SIGNAL_FLAGS_NONE, - session_removed_cb, - - user_list, - NULL); - result = g_dbus_connection_call_sync (priv->bus, - "org.freedesktop.DisplayManager", - "/org/freedesktop/DisplayManager", - "org.freedesktop.DBus.Properties", - "Get", - g_variant_new ("(ss)", "org.freedesktop.DisplayManager", "Sessions"), - G_VARIANT_TYPE ("(v)"), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - &error); - if (error) - g_warning ("Error getting session list from org.freedesktop.DisplayManager: %s", error->message); - g_clear_error (&error); - if (result) - { - if (g_variant_is_of_type (result, G_VARIANT_TYPE ("(v)"))) - { - GVariant *value; - GVariantIter *iter; - const gchar *path; - - g_variant_get (result, "(v)", &value); - - g_debug ("Loading sessions from org.freedesktop.DisplayManager"); - g_variant_get (value, "ao", &iter); - while (g_variant_iter_loop (iter, "&o", &path)) - load_session (user_list, path); - g_variant_iter_free (iter); - - g_variant_unref (value); - } - else - g_warning ("Unexpected type from org.freedesktop.DisplayManager.Sessions: %s", g_variant_get_type_string (result)); - - g_variant_unref (result); - } } /** @@ -931,8 +965,10 @@ common_user_list_get_users (CommonUserList *user_list) * @username: Name of user to get. * * Get infomation about a given user or #NULL if this user doesn't exist. + * Includes hidden and system users, unlike the list from + * common_user_list_get_users. * - * Return value: (transfer none): A #CommonUser entry for the given user. + * Return value: (transfer full): A #CommonUser entry for the given user. **/ CommonUser * common_user_list_get_user_by_name (CommonUserList *user_list, const gchar *username) @@ -942,7 +978,19 @@ common_user_list_get_user_by_name (CommonUserList *user_list, const gchar *usern load_users (user_list); - return get_user_by_name (user_list, username); + CommonUser *user = get_user_by_name (user_list, username); + if (user) + return g_object_ref (user); + + /* Sometimes we need to look up users that aren't in AccountsService. + Notably we need to look up the user that the greeter runs as, which + is usually 'lightdm'. For such cases, we manually create a one-off + CommonUser object and pre-seed with passwd info. */ + struct passwd *entry = getpwnam (username); + if (entry != NULL) + return make_passwd_user (user_list, entry); + + return NULL; } static void @@ -1075,42 +1123,80 @@ common_user_list_class_init (CommonUserListClass *klass) G_TYPE_NONE, 1, COMMON_TYPE_USER); } +static gboolean +call_method (CommonUser *user, const gchar *method, GVariant *args, + const gchar *expected, GVariant **result) +{ + GVariant *answer; + GError *error = NULL; + CommonUserPrivate *user_priv = GET_USER_PRIVATE (user); + CommonUserListPrivate *list_priv = GET_LIST_PRIVATE (user_priv->user_list); + + answer = g_dbus_connection_call_sync (list_priv->bus, + "org.freedesktop.Accounts", + user_priv->path, + "org.freedesktop.Accounts.User", + method, + args, + G_VARIANT_TYPE (expected), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + if (error) + g_warning ("Could not call %s: %s", method, error->message); + g_clear_error (&error); + + if (!answer) + return FALSE; + + if (result) + *result = answer; + else + g_variant_unref (answer); + + return TRUE; +} + static void -load_dmrc (CommonUser *user) +save_string_to_dmrc (CommonUser *user, const gchar *group, + const gchar *key, const gchar *value) { - CommonUserPrivate *priv = GET_USER_PRIVATE (user); - gchar *path; - //gboolean have_dmrc; + GKeyFile *dmrc; + + dmrc = dmrc_load (user); + g_key_file_set_string (dmrc, group, key, value); + dmrc_save (dmrc, user); - if (!priv->dmrc_file) - priv->dmrc_file = g_key_file_new (); + g_key_file_free (dmrc); +} - /* Load from the user directory */ - path = g_build_filename (priv->home_directory, ".dmrc", NULL); - /*have_dmrc = */g_key_file_load_from_file (priv->dmrc_file, path, G_KEY_FILE_KEEP_COMMENTS, NULL); - g_free (path); +static void +load_dmrc (CommonUser *user) +{ + CommonUserPrivate *priv = GET_USER_PRIVATE (user); + GKeyFile *dmrc; - /* If no ~/.dmrc, then load from the cache */ - // FIXME + dmrc = dmrc_load (user); // FIXME: Watch for changes /* The Language field contains the locale */ - if (priv->language) - g_free (priv->language); - priv->language = g_key_file_get_string (priv->dmrc_file, "Desktop", "Language", NULL); + g_free (priv->language); + priv->language = g_key_file_get_string (dmrc, "Desktop", "Language", NULL); - if (g_key_file_has_key (priv->dmrc_file, "Desktop", "Layout", NULL)) + if (g_key_file_has_key (dmrc, "Desktop", "Layout", NULL)) { g_strfreev (priv->layouts); priv->layouts = g_malloc (sizeof (gchar *) * 2); - priv->layouts[0] = g_key_file_get_string (priv->dmrc_file, "Desktop", "Layout", NULL); + priv->layouts[0] = g_key_file_get_string (dmrc, "Desktop", "Layout", NULL); priv->layouts[1] = NULL; } - if (priv->session) - g_free (priv->session); - priv->session = g_key_file_get_string (priv->dmrc_file, "Desktop", "Session", NULL); + g_free (priv->session); + priv->session = g_key_file_get_string (dmrc, "Desktop", "Session", NULL); + + g_key_file_free (dmrc); } /* Loads language/layout/session info for user */ @@ -1200,6 +1286,22 @@ common_user_get_home_directory (CommonUser *user) } /** + * common_user_get_shell: + * @user: A #CommonUser + * + * Get the shell for a user. + * + * Return value: The user's shell + */ +const gchar * +common_user_get_shell (CommonUser *user) +{ + g_return_val_if_fail (COMMON_IS_USER (user), NULL); + load_user_values (user); + return GET_USER_PRIVATE (user)->shell; +} + +/** * common_user_get_image: * @user: A #CommonUser * @@ -1244,7 +1346,26 @@ common_user_get_language (CommonUser *user) { g_return_val_if_fail (COMMON_IS_USER (user), NULL); load_user_values (user); - return GET_USER_PRIVATE (user)->language; + const gchar *language = GET_USER_PRIVATE (user)->language; + return (language && language[0] == 0) ? NULL : language; /* Treat "" as NULL */ +} + +/** + * common_user_set_language: + * @user: A #CommonUser + * @language: The user's new language + * + * Set the language for a user. + **/ +void +common_user_set_language (CommonUser *user, const gchar *language) +{ + g_return_if_fail (COMMON_IS_USER (user)); + if (g_strcmp0 (common_user_get_language (user), language) != 0) + { + call_method (user, "SetLanguage", g_variant_new ("(s)", language), "()", NULL); + save_string_to_dmrc (user, "Desktop", "Language", language); + } } /** @@ -1292,7 +1413,26 @@ common_user_get_session (CommonUser *user) { g_return_val_if_fail (COMMON_IS_USER (user), NULL); load_user_values (user); - return GET_USER_PRIVATE (user)->session; + const gchar *session = GET_USER_PRIVATE (user)->session; + return (session && session[0] == 0) ? NULL : session; /* Treat "" as NULL */ +} + +/** + * common_user_set_session: + * @user: A #CommonUser + * @language: The user's new session + * + * Set the session for a user. + **/ +void +common_user_set_session (CommonUser *user, const gchar *session) +{ + g_return_if_fail (COMMON_IS_USER (user)); + if (g_strcmp0 (common_user_get_session (user), session) != 0) + { + call_method (user, "SetXSession", g_variant_new ("(s)", session), "()", NULL); + save_string_to_dmrc (user, "Desktop", "Session", session); + } } /** @@ -1315,9 +1455,13 @@ common_user_get_logged_in (CommonUser *user) priv = GET_USER_PRIVATE (user); list_priv = GET_LIST_PRIVATE (priv->user_list); + // Lazily decide to load/listen to sessions + if (list_priv->session_added_signal == 0) + load_sessions (priv->user_list); + for (link = list_priv->sessions; link; link = link->next) { - Session *session = link->data; + CommonSession *session = link->data; if (strcmp (session->username, priv->name) == 0) return TRUE; } @@ -1341,6 +1485,48 @@ common_user_get_has_messages (CommonUser *user) return GET_USER_PRIVATE (user)->has_messages; } +/** + * common_user_get_uid: + * @user: A #CommonUser + * + * Get the uid of a user + * + * Return value: The user's uid + **/ +uid_t +common_user_get_uid (CommonUser *user) +{ + g_return_val_if_fail (COMMON_IS_USER (user), 0); + load_user_values (user); + return GET_USER_PRIVATE (user)->uid; +} + +/** + * common_user_get_gid: + * @user: A #CommonUser + * + * Get the gid of a user + * + * Return value: The user's gid + **/ +gid_t +common_user_get_gid (CommonUser *user) +{ + g_return_val_if_fail (COMMON_IS_USER (user), 0); + load_user_values (user); + /* gid is not actually stored in AccountsService, so if our user is from + AccountsService, we have to look up manually in passwd. gid won't + change, so just look up the first time we're asked and never again. */ + CommonUserPrivate *priv = GET_USER_PRIVATE (user); + if (priv->uid != 0 && priv->gid == 0) + { + struct passwd *entry = getpwuid (priv->uid); + if (entry != NULL) + priv->gid = entry->pw_gid; + } + return priv->gid; +} + static void common_user_init (CommonUser *user) { @@ -1382,6 +1568,9 @@ common_user_get_property (GObject *object, case USER_PROP_HOME_DIRECTORY: g_value_set_string (value, common_user_get_home_directory (self)); break; + case USER_PROP_SHELL: + g_value_set_string (value, common_user_get_shell (self)); + break; case USER_PROP_IMAGE: g_value_set_string (value, common_user_get_image (self)); break; @@ -1406,6 +1595,12 @@ common_user_get_property (GObject *object, case USER_PROP_HAS_MESSAGES: g_value_set_boolean (value, common_user_get_has_messages (self)); break; + case USER_PROP_UID: + g_value_set_uint64 (value, common_user_get_uid (self)); + break; + case USER_PROP_GID: + g_value_set_uint64 (value, common_user_get_gid (self)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1424,11 +1619,10 @@ common_user_finalize (GObject *object) g_free (priv->name); g_free (priv->real_name); g_free (priv->home_directory); + g_free (priv->shell); g_free (priv->image); g_free (priv->background); g_strfreev (priv->layouts); - if (priv->dmrc_file) - g_key_file_free (priv->dmrc_file); } static void @@ -1471,6 +1665,13 @@ common_user_class_init (CommonUserClass *klass) NULL, G_PARAM_READWRITE)); g_object_class_install_property (object_class, + USER_PROP_SHELL, + g_param_spec_string ("shell", + "shell", + "Shell", + NULL, + G_PARAM_READWRITE)); + g_object_class_install_property (object_class, USER_PROP_IMAGE, g_param_spec_string ("image", "image", @@ -1526,6 +1727,24 @@ common_user_class_init (CommonUserClass *klass) "TRUE if the user is has waiting messages", FALSE, G_PARAM_READWRITE)); + g_object_class_install_property (object_class, + USER_PROP_UID, + g_param_spec_uint64 ("uid", + "uid", + "Uid", + 0, + G_MAXUINT64, + 0, + G_PARAM_READWRITE)); + g_object_class_install_property (object_class, + USER_PROP_GID, + g_param_spec_uint64 ("gd", + "gid", + "Gid", + 0, + G_MAXUINT64, + 0, + G_PARAM_READWRITE)); /** * CommonUser::changed: @@ -1544,22 +1763,22 @@ common_user_class_init (CommonUserClass *klass) } static void -session_init (Session *session) +common_session_init (CommonSession *common_session) { } static void -session_finalize (GObject *object) +common_session_finalize (GObject *object) { - Session *self = SESSION (object); + CommonSession *self = COMMON_SESSION (object); g_free (self->path); g_free (self->username); } static void -session_class_init (SessionClass *klass) +common_session_class_init (CommonSessionClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - object_class->finalize = session_finalize; + object_class->finalize = common_session_finalize; } diff --git a/common/user-list.h b/common/user-list.h index 19926cf2..820e0b25 100644 --- a/common/user-list.h +++ b/common/user-list.h @@ -14,6 +14,7 @@ #define COMMON_USER_LIST_H_ #include <glib-object.h> +#include <sys/types.h> G_BEGIN_DECLS @@ -77,22 +78,32 @@ const gchar *common_user_get_display_name (CommonUser *user); const gchar *common_user_get_home_directory (CommonUser *user); +const gchar *common_user_get_shell (CommonUser *user); + const gchar *common_user_get_image (CommonUser *user); const gchar *common_user_get_background (CommonUser *user); const gchar *common_user_get_language (CommonUser *user); +void common_user_set_language (CommonUser *user, const gchar *language); + const gchar *common_user_get_layout (CommonUser *user); const gchar * const *common_user_get_layouts (CommonUser *user); const gchar *common_user_get_session (CommonUser *user); +void common_user_set_session (CommonUser *user, const gchar *session); + gboolean common_user_get_logged_in (CommonUser *user); gboolean common_user_get_has_messages (CommonUser *user); +uid_t common_user_get_uid (CommonUser *user); + +gid_t common_user_get_gid (CommonUser *user); + G_END_DECLS #endif /* COMMON_USER_LIST_H_ */ diff --git a/configure.ac b/configure.ac index 4c0d0895..225de840 100644 --- a/configure.ac +++ b/configure.ac @@ -209,6 +209,7 @@ dnl ########################################################################### AC_CONFIG_FILES([ Makefile +common/Makefile data/Makefile doc/Makefile help/Makefile diff --git a/liblightdm-gobject/Makefile.am b/liblightdm-gobject/Makefile.am index 770ea13b..ef4cee59 100644 --- a/liblightdm-gobject/Makefile.am +++ b/liblightdm-gobject/Makefile.am @@ -1,9 +1,12 @@ lib_LTLIBRARIES = liblightdm-gobject-1.la liblightdm_gobject_1_la_LDFLAGS = -export-symbols-regex \^lightdm_.* -liblightdm_gobject_1_la_LIBADD = $(LIBLIGHTDM_GOBJECT_LIBS) +liblightdm_gobject_1_la_LIBADD = \ + $(LIBLIGHTDM_GOBJECT_LIBS) \ + $(top_builddir)/common/libcommon.la liblightdm_gobject_1_la_CFLAGS = $(LIBLIGHTDM_GOBJECT_CFLAGS) \ $(WARN_CFLAGS) \ + -I"$(top_srcdir)/common" \ -DCONFIG_DIR=\"$(sysconfdir)/lightdm\" \ -DSESSIONS_DIR=\"$(pkgdatadir)/sessions:$(datadir)/xsessions\" \ -DREMOTE_SESSIONS_DIR=\"$(pkgdatadir)/remote-sessions\" @@ -29,7 +32,6 @@ liblightdm_gobject_1_la_SOURCES= \ power.c \ session.c \ user.c \ - $(top_srcdir)/common/user-list.c \ $(liblightdm_gobject_1include_HEADERS) if HAVE_INTROSPECTION diff --git a/liblightdm-gobject/session.c b/liblightdm-gobject/session.c index 949778f0..0b89eab7 100644 --- a/liblightdm-gobject/session.c +++ b/liblightdm-gobject/session.c @@ -11,6 +11,7 @@ #include <string.h> #include <gio/gdesktopappinfo.h> +#include "configuration.h" #include "lightdm/session.h" enum { @@ -191,7 +192,6 @@ load_sessions (const gchar *sessions_dir) static void update_sessions (void) { - GKeyFile *config_key_file = NULL; gchar *config_path = NULL; gchar *sessions_dir; gchar *remote_sessions_dir; @@ -207,8 +207,8 @@ update_sessions (void) /* Use session directory from configuration */ /* FIXME: This should be sent in the greeter connection */ config_path = g_build_filename (CONFIG_DIR, "lightdm.conf", NULL); - config_key_file = g_key_file_new (); - result = g_key_file_load_from_file (config_key_file, config_path, G_KEY_FILE_NONE, &error); + /* FIXME: This should load from lightdm.conf.d as well */ + result = config_load_from_file (config_get_instance (), config_path, &error); if (error && !g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) g_warning ("Failed to open configuration file: %s", error->message); g_clear_error (&error); @@ -216,21 +216,20 @@ update_sessions (void) { gchar *value; - value = g_key_file_get_string (config_key_file, "LightDM", "sessions-directory", NULL); + value = config_get_string (config_get_instance (), "LightDM", "sessions-directory"); if (value) { g_free (sessions_dir); sessions_dir = value; } - value = g_key_file_get_string (config_key_file, "LightDM", "remote-sessions-directory", NULL); + value = config_get_string (config_get_instance (), "LightDM", "remote-sessions-directory"); if (value) { g_free (remote_sessions_dir); remote_sessions_dir = value; } } - g_key_file_free (config_key_file); g_free (config_path); local_sessions = load_sessions (sessions_dir); diff --git a/liblightdm-gobject/user.c b/liblightdm-gobject/user.c index 664cfa64..4fb5f044 100644 --- a/liblightdm-gobject/user.c +++ b/liblightdm-gobject/user.c @@ -13,7 +13,7 @@ #include <config.h> -#include "common/user-list.h" +#include "user-list.h" #include "lightdm/user.h" enum diff --git a/src/Makefile.am b/src/Makefile.am index fa3a20f4..766ef679 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -4,16 +4,12 @@ bin_PROGRAMS = dm-tool lightdm_SOURCES = \ accounts.c \ accounts.h \ - configuration.c \ - configuration.h \ console-kit.c \ console-kit.h \ display-manager.c \ display-manager.h \ display-server.c \ display-server.h \ - dmrc.c \ - dmrc.h \ greeter.c \ greeter.h \ guest-account.c \ @@ -27,8 +23,6 @@ lightdm_SOURCES = \ mir-server.h \ plymouth.c \ plymouth.h \ - privileges.c \ - privileges.h \ process.c \ process.h \ seat.c \ @@ -80,6 +74,7 @@ lightdm_SOURCES = \ lightdm_CFLAGS = \ $(LIGHTDM_CFLAGS) \ $(WARN_CFLAGS) \ + -I"$(top_srcdir)/common" \ -DSBIN_DIR=\"$(sbindir)\" \ -DCONFIG_DIR=\"$(sysconfdir)/lightdm\" \ -DLOG_DIR=\"$(localstatedir)/log/lightdm\" \ @@ -92,6 +87,7 @@ lightdm_CFLAGS = \ lightdm_LDADD = \ $(LIGHTDM_LIBS) \ + $(top_builddir)/common/libcommon.la \ -lgcrypt \ -lpam diff --git a/src/accounts.c b/src/accounts.c index 63d8a40d..797b6d9d 100644 --- a/src/accounts.c +++ b/src/accounts.c @@ -10,273 +10,34 @@ * license. */ -#include <errno.h> #include <pwd.h> #include <stdlib.h> -#include <string.h> #include "accounts.h" -#include "dmrc.h" +#include "user-list.h" struct UserPrivate { - /* Name of user */ - gchar *name; - - /* Accounts interface proxy */ - GDBusProxy *proxy; - - /* User ID */ - uid_t uid; - - /* Group ID */ - gid_t gid; - - /* GECOS information */ - gchar *gecos; - - /* Home directory */ - gchar *home_directory; - - /* Shell */ - gchar *shell; - - /* Language */ - gchar *language; - - /* X session */ - gchar *xsession; + /* Internal user object */ + CommonUser *common_user; }; G_DEFINE_TYPE (User, user, G_TYPE_OBJECT); -/* Connection to AccountsService */ -static GDBusProxy *accounts_service_proxy = NULL; -static gboolean have_accounts_service_proxy = FALSE; - -static gboolean -call_method (GDBusProxy *proxy, const gchar *method, GVariant *args, - const gchar *expected, GVariant **result) -{ - GVariant *answer; - GError *error = NULL; - - if (!proxy) - return FALSE; - - answer = g_dbus_proxy_call_sync (proxy, - method, - args, - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - &error); - if (error) - g_warning ("Could not call %s: %s", method, error->message); - g_clear_error (&error); - - if (!answer) - return FALSE; - - if (!g_variant_is_of_type (answer, G_VARIANT_TYPE (expected))) - { - g_warning ("Unexpected response from %s: %s", - method, g_variant_get_type_string (answer)); - g_variant_unref (answer); - return FALSE; - } - - if (result) - *result = answer; - else - g_variant_unref (answer); - - return TRUE; -} - -static gboolean -get_property (GDBusProxy *proxy, const gchar *property, - const gchar *expected, GVariant **result) -{ - GVariant *answer; - - answer = g_dbus_proxy_get_cached_property (proxy, property); - - if (!answer) - { - g_warning ("Could not get accounts property %s", property); - return FALSE; - } - - if (!g_variant_is_of_type (answer, G_VARIANT_TYPE (expected))) - { - g_warning ("Unexpected accounts property type for %s: %s", - property, g_variant_get_type_string (answer)); - g_variant_unref (answer); - return FALSE; - } - - if (result) - *result = answer; - else - g_variant_unref (answer); - return TRUE; -} - -static void -save_string_to_dmrc (const gchar *username, const gchar *group, - const gchar *key, const gchar *value) -{ - GKeyFile *dmrc; - - dmrc = dmrc_load (username); - g_key_file_set_string (dmrc, group, key, value); - dmrc_save (dmrc, username); - - g_key_file_free (dmrc); -} - -static gchar * -get_string_from_dmrc (const gchar *username, const gchar *group, - const gchar *key) -{ - GKeyFile *dmrc; - gchar *value; - - dmrc = dmrc_load (username); - value = g_key_file_get_string (dmrc, group, key, NULL); - - g_key_file_free (dmrc); - return value; -} - -static GDBusProxy * -get_accounts_service_proxy (void) -{ - GError *error = NULL; - - if (have_accounts_service_proxy) - return accounts_service_proxy; - - have_accounts_service_proxy = TRUE; - accounts_service_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.freedesktop.Accounts", - "/org/freedesktop/Accounts", - "org.freedesktop.Accounts", - NULL, &error); - if (error) - g_warning ("Could not get accounts proxy: %s", error->message); - g_clear_error (&error); - - if (accounts_service_proxy) - { - gchar *name; - name = g_dbus_proxy_get_name_owner (accounts_service_proxy); - if (!name) - { - g_debug ("org.freedesktop.Accounts does not exist, falling back to passwd file"); - g_object_unref (accounts_service_proxy); - accounts_service_proxy = NULL; - } - g_free (name); - } - - return accounts_service_proxy; -} - -static GDBusProxy * -get_accounts_proxy_for_user (const gchar *user) -{ - GDBusProxy *proxy; - GError *error = NULL; - GVariant *result; - gboolean success; - gchar *user_path = NULL; - - g_return_val_if_fail (user != NULL, NULL); - - proxy = get_accounts_service_proxy (); - if (!proxy) - return NULL; - - success = call_method (proxy, "FindUserByName", g_variant_new ("(s)", user), "(o)", &result); - - if (!success) - return NULL; - - g_variant_get (result, "(o)", &user_path); - g_variant_unref (result); - - if (!user_path) - return NULL; - - proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.freedesktop.Accounts", - user_path, - "org.freedesktop.Accounts.User", - NULL, &error); - if (error) - g_warning ("Could not get accounts user proxy: %s", error->message); - g_clear_error (&error); - g_free (user_path); - - return proxy; -} - -static User * -user_from_passwd (struct passwd *user_info) -{ - User *user; - - user = g_object_new (USER_TYPE, NULL); - user->priv->name = g_strdup (user_info->pw_name); - user->priv->uid = user_info->pw_uid; - user->priv->gid = user_info->pw_gid; - user->priv->gecos = g_strdup (user_info->pw_gecos); - user->priv->home_directory = g_strdup (user_info->pw_dir); - user->priv->shell = g_strdup (user_info->pw_shell); - user->priv->proxy = get_accounts_proxy_for_user (user->priv->name); - - return user; -} - User * accounts_get_user_by_name (const gchar *username) { - struct passwd *user_info; User *user = NULL; + CommonUser *common_user; g_return_val_if_fail (username != NULL, NULL); - errno = 0; - user_info = getpwnam (username); - if (user_info) - user = user_from_passwd (user_info); - - if (!user && errno != 0) - g_warning ("Unable to get information on user %s: %s", username, strerror (errno)); - - return user; -} - -User * -accounts_get_user_by_uid (uid_t uid) -{ - User *user = NULL; - - errno = 0; - struct passwd *user_info; - - user_info = getpwuid (uid); - if (user_info) - user = user_from_passwd (user_info); - - if (!user && errno != 0) - g_warning ("Unable to get information on user %d: %s", uid, strerror (errno)); + common_user = common_user_list_get_user_by_name (common_user_list_get_instance (), username); + if (common_user != NULL) + { + user = g_object_new (USER_TYPE, NULL); + user->priv->common_user = common_user; + } return user; } @@ -284,136 +45,74 @@ accounts_get_user_by_uid (uid_t uid) User * accounts_get_current_user () { - return user_from_passwd (getpwuid (getuid ())); + struct passwd *entry = getpwuid (getuid ()); + if (entry != NULL) + return accounts_get_user_by_name (entry->pw_name); + else + return NULL; } const gchar * user_get_name (User *user) { g_return_val_if_fail (user != NULL, NULL); - return user->priv->name; + return common_user_get_name (user->priv->common_user); } uid_t user_get_uid (User *user) { g_return_val_if_fail (user != NULL, 0); - return user->priv->uid; + return common_user_get_uid (user->priv->common_user); } gid_t user_get_gid (User *user) { g_return_val_if_fail (user != NULL, 0); - return user->priv->gid; -} - -const gchar * -user_get_gecos (User *user) -{ - g_return_val_if_fail (user != NULL, NULL); - return user->priv->gecos; + return common_user_get_gid (user->priv->common_user); } const gchar * user_get_home_directory (User *user) { g_return_val_if_fail (user != NULL, NULL); - return user->priv->home_directory; + return common_user_get_home_directory (user->priv->common_user); } const gchar * user_get_shell (User *user) { g_return_val_if_fail (user != NULL, NULL); - return user->priv->shell; + return common_user_get_shell (user->priv->common_user); } void user_set_language (User *user, const gchar *language) { g_return_if_fail (user != NULL); - - call_method (user->priv->proxy, "SetLanguage", g_variant_new ("(s)", language), "()", NULL); - save_string_to_dmrc (user->priv->name, "Desktop", "Language", language); + common_user_set_language (user->priv->common_user, language); } const gchar * user_get_language (User *user) { - GVariant *variant, *inner; - gboolean success; - g_return_val_if_fail (user != NULL, NULL); - - g_free (user->priv->language); - if (user->priv->proxy) - { - /* the "Language" property cannot be retrieved with get_property () here since it - * uses g_dbus_proxy_get_cached_property () which would return the previous (cached) value - * of the "Language" property - */ - success = call_method (user->priv->proxy, "org.freedesktop.DBus.Properties.Get", g_variant_new ("(ss)", g_dbus_proxy_get_interface_name(user->priv->proxy), "Language"), "(v)", &variant); - if (success) - { - g_variant_get (variant, "(v)", &inner); - user->priv->language = g_variant_dup_string (inner, NULL); - g_variant_unref (inner); - g_variant_unref (variant); - } - else - user->priv->language = NULL; - } - else - user->priv->language = get_string_from_dmrc (user->priv->name, "Desktop", "Language"); - - /* Treat a blank language as unset */ - if (g_strcmp0 (user->priv->language, "") == 0) - { - g_free (user->priv->language); - user->priv->language = NULL; - } - - return user->priv->language; + return common_user_get_language (user->priv->common_user); } void user_set_xsession (User *user, const gchar *xsession) { g_return_if_fail (user != NULL); - - call_method (user->priv->proxy, "SetXSession", g_variant_new ("(s)", xsession), "()", NULL); - save_string_to_dmrc (user->priv->name, "Desktop", "Session", xsession); + common_user_set_session (user->priv->common_user, xsession); } const gchar * user_get_xsession (User *user) { - GVariant *result; - g_return_val_if_fail (user != NULL, NULL); - - g_free (user->priv->xsession); - if (user->priv->proxy) - { - if (get_property (user->priv->proxy, "XSession", "s", &result)) - { - g_variant_get (result, "s", &user->priv->xsession); - g_variant_unref (result); - } - else - user->priv->xsession = NULL; - } - else - user->priv->xsession = get_string_from_dmrc (user->priv->name, "Desktop", "Session"); - - if (g_strcmp0 (user->priv->xsession, "") == 0) - { - g_free (user->priv->xsession); - user->priv->xsession = NULL; - } - - return user->priv->xsession; + return common_user_get_session (user->priv->common_user); } static void @@ -429,38 +128,19 @@ user_dispose (GObject *object) self = USER (object); - if (self->priv->proxy) - { - g_object_unref (self->priv->proxy); - self->priv->proxy = NULL; - } + if (self->priv->common_user) + g_object_unref (self->priv->common_user); + self->priv->common_user = NULL; G_OBJECT_CLASS (user_parent_class)->dispose (object); } static void -user_finalize (GObject *object) -{ - User *self; - - self = USER (object); - - g_free (self->priv->name); - g_free (self->priv->gecos); - g_free (self->priv->home_directory); - g_free (self->priv->shell); - g_free (self->priv->language); - - G_OBJECT_CLASS (user_parent_class)->finalize (object); -} - -static void user_class_init (UserClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->dispose = user_dispose; - object_class->finalize = user_finalize; g_type_class_add_private (klass, sizeof (UserPrivate)); } diff --git a/src/accounts.h b/src/accounts.h index 1f9eb078..a6468570 100644 --- a/src/accounts.h +++ b/src/accounts.h @@ -36,8 +36,6 @@ typedef struct User *accounts_get_user_by_name (const gchar *username); -User *accounts_get_user_by_uid (uid_t uid); - User *accounts_get_current_user (void); GType user_get_type (void); @@ -48,8 +46,6 @@ uid_t user_get_uid (User *user); gid_t user_get_gid (User *user); -const gchar *user_get_gecos (User *user); - const gchar *user_get_home_directory (User *user); const gchar *user_get_shell (User *user); diff --git a/src/session-child.c b/src/session-child.c index 01eb1c37..1feb7ac2 100644 --- a/src/session-child.c +++ b/src/session-child.c @@ -512,7 +512,7 @@ session_child_run (int argc, char **argv) drop_privileges = geteuid () == 0; if (drop_privileges) - privileges_drop (user); + privileges_drop (user_get_uid (user), user_get_gid (user)); result = x_authority_write (x_authority, XAUTH_WRITE_MODE_REPLACE, x_authority_filename, &error); if (drop_privileges) privileges_reclaim (); @@ -660,7 +660,7 @@ session_child_run (int argc, char **argv) drop_privileges = geteuid () == 0; if (drop_privileges) - privileges_drop (user); + privileges_drop (user_get_uid (user), user_get_gid (user)); result = x_authority_write (x_authority, XAUTH_WRITE_MODE_REMOVE, x_authority_filename, &error); if (drop_privileges) privileges_reclaim (); diff --git a/tests/src/test-gobject-greeter.c b/tests/src/test-gobject-greeter.c index 077fd2b9..afb14cc6 100644 --- a/tests/src/test-gobject-greeter.c +++ b/tests/src/test-gobject-greeter.c @@ -218,7 +218,7 @@ request_cb (const gchar *request) if (strcmp (name, "LOG-USER") == 0) { LightDMUser *user; - const gchar *username, *image, *background, *layout, *session; + const gchar *username, *image, *background, *language, *layout, *session; const gchar * const * layouts; gchar **fields = NULL; gchar *layouts_text; @@ -237,6 +237,7 @@ request_cb (const gchar *request) user = lightdm_user_list_get_user_by_name (lightdm_user_list_get_instance (), username); image = lightdm_user_get_image (user); background = lightdm_user_get_background (user); + language = lightdm_user_get_language (user); layout = lightdm_user_get_layout (user); layouts = lightdm_user_get_layouts (user); layouts_text = g_strjoinv (";", (gchar **) layouts); @@ -255,7 +256,7 @@ request_cb (const gchar *request) else if (strcmp (fields[i], "BACKGROUND") == 0) g_string_append_printf (status_text, " BACKGROUND=%s", background ? background : ""); else if (strcmp (fields[i], "LANGUAGE") == 0) - g_string_append_printf (status_text, " LANGUAGE=%s", lightdm_user_get_language (user)); + g_string_append_printf (status_text, " LANGUAGE=%s", language ? language : ""); else if (strcmp (fields[i], "LAYOUT") == 0) g_string_append_printf (status_text, " LAYOUT=%s", layout ? layout : ""); else if (strcmp (fields[i], "LAYOUTS") == 0) diff --git a/tests/src/test-runner.c b/tests/src/test-runner.c index 0cffb524..c00a6290 100644 --- a/tests/src/test-runner.c +++ b/tests/src/test-runner.c @@ -1715,6 +1715,15 @@ handle_user_call (GDBusConnection *connection, user->xsession = g_strdup (xsession); g_dbus_method_invocation_return_value (invocation, g_variant_new ("()")); + + /* And notify others that it took */ + g_dbus_connection_emit_signal (accounts_connection, + NULL, + user->path, + "org.freedesktop.Accounts.User", + "Changed", + g_variant_new ("()"), + NULL); } else g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "No such method: %s", method_name); @@ -1745,6 +1754,10 @@ handle_user_get_property (GDBusConnection *connection, return g_variant_new_string (user->language ? user->language : ""); else if (strcmp (property_name, "IconFile") == 0) return g_variant_new_string (user->image ? user->image : ""); + else if (strcmp (property_name, "Shell") == 0) + return g_variant_new_string ("/bin/sh"); + else if (strcmp (property_name, "Uid") == 0) + return g_variant_new_uint64 (user->uid); else if (strcmp (property_name, "XSession") == 0) return g_variant_new_string (user->xsession ? user->xsession : ""); else if (strcmp (property_name, "XKeyboardLayouts") == 0) @@ -1800,6 +1813,8 @@ accounts_name_acquired_cb (GDBusConnection *connection, " <property name='BackgroundFile' type='s' access='read'/>" " <property name='Language' type='s' access='read'/>" " <property name='IconFile' type='s' access='read'/>" + " <property name='Shell' type='s' access='read'/>" + " <property name='Uid' type='t' access='read'/>" " <property name='XSession' type='s' access='read'/>" " <property name='XKeyboardLayouts' type='as' access='read'/>" " <property name='XHasMessages' type='b' access='read'/>" |