Blob Blame Raw
From 0ecacfd6123e4026c78d5d61670da0abdcbf7559 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Thu, 22 Jan 2015 11:51:18 -0500
Subject: [PATCH] manager: allow the login screen to do reauthentication

At the moment, we only allow the user session to do reauthentication
from its lock screen.  If a user does user switching we instead open
a new session for checking the user's password.

This commit enables reauthentication from the login screen as well.
---
 daemon/gdm-manager.c | 23 ++++++++++++++---------
 1 file changed, 14 insertions(+), 9 deletions(-)

diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
index 8c41045..0278512 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -1161,84 +1161,89 @@ open_temporary_reauthentication_channel (GdmManager            *self,
                           self);
 
         address = gdm_session_get_server_address (session);
 
         return g_strdup (address);
 }
 
 static gboolean
 gdm_manager_handle_open_reauthentication_channel (GdmDBusManager        *manager,
                                                   GDBusMethodInvocation *invocation,
                                                   const char            *username)
 {
         GdmManager       *self = GDM_MANAGER (manager);
         const char       *sender;
         GdmDisplay       *display = NULL;
         GdmSession       *session;
         GDBusConnection  *connection;
         char             *seat_id = NULL;
         char             *session_id = NULL;
         GPid              pid = 0;
         uid_t             uid = (uid_t) -1;
         gboolean          is_login_screen = FALSE;
         gboolean          is_remote = FALSE;
 
         g_debug ("GdmManager: trying to open reauthentication channel for user %s", username);
 
         sender = g_dbus_method_invocation_get_sender (invocation);
         connection = g_dbus_method_invocation_get_connection (invocation);
         get_display_and_details_for_bus_sender (self, connection, sender, &display, &seat_id, &session_id, &pid, &uid, &is_login_screen, &is_remote);
 
-        if (is_login_screen) {
-                g_dbus_method_invocation_return_error_literal (invocation,
-                                                               G_DBUS_ERROR,
-                                                               G_DBUS_ERROR_ACCESS_DENIED,
-                                                               "Login screen not allow to open reauthentication channel");
-                return TRUE;
-        }
-
         if (session_id == NULL || pid == 0 || uid == (uid_t) -1) {
                 g_dbus_method_invocation_return_error_literal (invocation,
                                                                G_DBUS_ERROR,
                                                                G_DBUS_ERROR_ACCESS_DENIED,
                                                                _("No session available"));
 
                 return TRUE;
         }
 
-        session = get_seed_session_for_display (display);
+        if (is_login_screen) {
+                session = find_session_for_user_on_seat (self,
+                                                         username,
+                                                         seat_id,
+                                                         NULL);
+        } else {
+                session = get_seed_session_for_display (display);
+        }
 
         if (session != NULL && gdm_session_is_running (session)) {
                 gdm_session_start_reauthentication (session, pid, uid);
                 g_hash_table_insert (self->priv->open_reauthentication_requests,
                                      GINT_TO_POINTER (pid),
                                      invocation);
+        } else if (is_login_screen) {
+                g_dbus_method_invocation_return_error_literal (invocation,
+                                                               G_DBUS_ERROR,
+                                                               G_DBUS_ERROR_ACCESS_DENIED,
+                                                               "Login screen only allowed to open reauthentication channels for running sessions");
+                return TRUE;
         } else {
                 char *address;
                 address = open_temporary_reauthentication_channel (self,
                                                                    seat_id,
                                                                    session_id,
                                                                    pid,
                                                                    uid,
                                                                    is_remote);
                 gdm_dbus_manager_complete_open_reauthentication_channel (GDM_DBUS_MANAGER (manager),
                                                                          invocation,
                                                                          address);
                 g_free (address);
         }
 
         return TRUE;
 }
 
 static void
 manager_interface_init (GdmDBusManagerIface *interface)
 {
         interface->handle_open_session = gdm_manager_handle_open_session;
         interface->handle_open_reauthentication_channel = gdm_manager_handle_open_reauthentication_channel;
 }
 
 static void
 set_up_greeter_session (GdmManager *manager,
                         GdmDisplay *display)
 {
         char *allowed_user;
         struct passwd *passwd_entry;
-- 
2.2.1

From 259ef2d7d7acc4e7bb0602eea835b9585997413b Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Fri, 23 Jan 2015 14:25:05 -0500
Subject: [PATCH] manager: clean seed session when its display goes away

If the display goes away right before the session exits, then we
can crash because we'll try to finish the already finished display.

This commit corrects the problem by making sure to dissociate the
display from the seed session when the display is finished.

https://bugzilla.gnome.org/show_bug.cgi?id=719418
---
 daemon/gdm-manager.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
index 0278512..684e462 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -1820,60 +1820,67 @@ start_autologin_conversation_if_necessary (GdmManager *manager,
         if (delay == 0 && g_file_test (GDM_RAN_ONCE_MARKER_FILE, G_FILE_TEST_EXISTS)) {
                 return;
         }
 
         if (!enabled) {
                 return;
         }
 
         g_debug ("GdmManager: Starting automatic login conversation");
         gdm_session_start_conversation (session, "gdm-autologin");
 }
 
 static void
 touch_ran_once_marker_file (GdmManager *manager)
 {
         int fd;
 
         fd = g_creat (GDM_RAN_ONCE_MARKER_FILE, 0644);
 
         if (fd < 0 && errno != EEXIST) {
                 g_warning ("could not create %s to mark run, this may cause auto login "
                            "to repeat: %m", GDM_RAN_ONCE_MARKER_FILE);
                 return;
         }
 
         fsync (fd);
         close (fd);
 }
 
 static void
+clean_seed_session (GdmSession *session)
+{
+        g_object_set_data (G_OBJECT (session), "gdm-display", NULL);
+        g_object_unref (session);
+}
+
+static void
 create_seed_session_for_display (GdmManager *manager,
                                  GdmDisplay *display,
                                  uid_t       allowed_user)
 {
         GdmSession *session;
         gboolean    display_is_local = FALSE;
         char       *display_name = NULL;
         char       *display_device = NULL;
         char       *remote_hostname = NULL;
         char       *display_auth_file = NULL;
         char       *display_seat_id = NULL;
         char       *display_id = NULL;
 
         g_object_get (G_OBJECT (display),
                       "id", &display_id,
                       "x11-display-name", &display_name,
                       "is-local", &display_is_local,
                       "remote-hostname", &remote_hostname,
                       "x11-authority-file", &display_auth_file,
                       "seat-id", &display_seat_id,
                       NULL);
         display_device = get_display_device (manager, display);
 
         session = gdm_session_new (GDM_SESSION_VERIFICATION_MODE_LOGIN,
                                    allowed_user,
                                    display_name,
                                    remote_hostname,
                                    display_device,
                                    display_seat_id,
                                    display_auth_file,
@@ -1906,61 +1913,61 @@ create_seed_session_for_display (GdmManager *manager,
                           manager);
         g_signal_connect (session,
                           "cancelled",
                           G_CALLBACK (on_session_cancelled),
                           manager);
         g_signal_connect (session,
                           "conversation-started",
                           G_CALLBACK (on_session_conversation_started),
                           manager);
         g_signal_connect (session,
                           "conversation-stopped",
                           G_CALLBACK (on_session_conversation_stopped),
                           manager);
         g_signal_connect (session,
                           "session-opened",
                           G_CALLBACK (on_session_opened),
                           manager);
         g_signal_connect (session,
                           "session-started",
                           G_CALLBACK (on_session_started),
                           manager);
         g_signal_connect (session,
                           "session-exited",
                           G_CALLBACK (on_user_session_exited),
                           manager);
         g_signal_connect (session,
                           "session-died",
                           G_CALLBACK (on_user_session_died),
                           manager);
         g_object_set_data (G_OBJECT (session), "gdm-display", display);
-        g_object_set_data_full (G_OBJECT (display), "gdm-seed-session", g_object_ref (session), (GDestroyNotify) g_object_unref);
+        g_object_set_data_full (G_OBJECT (display), "gdm-seed-session", g_object_ref (session), (GDestroyNotify) clean_seed_session);
 
         start_autologin_conversation_if_necessary (manager, display, session);
 }
 
 static void
 on_display_added (GdmDisplayStore *display_store,
                   const char      *id,
                   GdmManager      *manager)
 {
         GdmDisplay *display;
 
         display = gdm_display_store_lookup (display_store, id);
 
         if (display != NULL) {
                 g_dbus_object_manager_server_export (manager->priv->object_manager,
                                                      gdm_display_get_object_skeleton (display));
 
                 g_signal_connect (display, "notify::status",
                                   G_CALLBACK (on_display_status_changed),
                                   manager);
                 g_signal_emit (manager, signals[DISPLAY_ADDED], 0, id);
         }
 }
 
 GQuark
 gdm_manager_error_quark (void)
 {
         static GQuark ret = 0;
         if (ret == 0) {
                 ret = g_quark_from_static_string ("gdm_manager_error");
-- 
2.2.1