Blame SOURCES/0032-manager-rework-how-autologin-is-figured-out.patch

c90517
From a539080c470125871aa1774318a0b5aca14ce91d Mon Sep 17 00:00:00 2001
c90517
From: Ray Strode <rstrode@redhat.com>
c90517
Date: Tue, 25 Sep 2018 10:59:37 -0400
c90517
Subject: [PATCH 32/48] manager: rework how autologin is figured out
c90517
c90517
At the moment we decide whether or not to perform autologin, by
c90517
looking at if the display is the initial VT display and if autologin
c90517
hasn't been started before.
c90517
c90517
That isn't going to work in the future when autologin is started
c90517
on a non-initial vt.
c90517
c90517
This commit changes GDM to instead check if the seat is seat0, and
c90517
if autologin hasn't run before, before deciding to do autologin.
c90517
---
c90517
 daemon/gdm-manager.c | 46 ++++++++++++++++++++++++++++++++------------
c90517
 1 file changed, 34 insertions(+), 12 deletions(-)
c90517
c90517
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
c90517
index fb7b1ec4b..228cec6ff 100644
c90517
--- a/daemon/gdm-manager.c
c90517
+++ b/daemon/gdm-manager.c
c90517
@@ -51,75 +51,76 @@
c90517
 #include "gdm-session.h"
c90517
 #include "gdm-session-record.h"
c90517
 #include "gdm-settings-direct.h"
c90517
 #include "gdm-settings-keys.h"
c90517
 #include "gdm-xdmcp-display-factory.h"
c90517
 #include "gdm-xdmcp-chooser-display.h"
c90517
 
c90517
 #define GDM_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_MANAGER, GdmManagerPrivate))
c90517
 
c90517
 #define GDM_DBUS_PATH             "/org/gnome/DisplayManager"
c90517
 #define GDM_MANAGER_PATH          GDM_DBUS_PATH "/Manager"
c90517
 #define GDM_MANAGER_DISPLAYS_PATH GDM_DBUS_PATH "/Displays"
c90517
 
c90517
 #define INITIAL_SETUP_USERNAME "gnome-initial-setup"
c90517
 
c90517
 typedef struct
c90517
 {
c90517
         GdmManager *manager;
c90517
         GdmSession *session;
c90517
         char *service_name;
c90517
         guint idle_id;
c90517
 } StartUserSessionOperation;
c90517
 
c90517
 struct GdmManagerPrivate
c90517
 {
c90517
         GdmDisplayStore        *display_store;
c90517
         GdmLocalDisplayFactory *local_factory;
c90517
 #ifdef HAVE_LIBXDMCP
c90517
         GdmXdmcpDisplayFactory *xdmcp_factory;
c90517
 #endif
c90517
+        GdmDisplay             *automatic_login_display;
c90517
         GList                  *user_sessions;
c90517
         GHashTable             *transient_sessions;
c90517
         GHashTable             *open_reauthentication_requests;
c90517
         gboolean                xdmcp_enabled;
c90517
 
c90517
         gboolean                started;
c90517
         gboolean                show_local_greeter;
c90517
 
c90517
         GDBusConnection          *connection;
c90517
         GDBusObjectManagerServer *object_manager;
c90517
 
c90517
 #ifdef  WITH_PLYMOUTH
c90517
         guint                     plymouth_is_running : 1;
c90517
 #endif
c90517
-        guint                     ran_once : 1;
c90517
+        guint                     did_automatic_login : 1;
c90517
 };
c90517
 
c90517
 enum {
c90517
         PROP_0,
c90517
         PROP_XDMCP_ENABLED,
c90517
         PROP_SHOW_LOCAL_GREETER
c90517
 };
c90517
 
c90517
 enum {
c90517
         DISPLAY_ADDED,
c90517
         DISPLAY_REMOVED,
c90517
         LAST_SIGNAL
c90517
 };
c90517
 
c90517
 typedef enum {
c90517
         SESSION_RECORD_LOGIN,
c90517
         SESSION_RECORD_LOGOUT,
c90517
         SESSION_RECORD_FAILED,
c90517
 } SessionRecord;
c90517
 
c90517
 static guint signals [LAST_SIGNAL] = { 0, };
c90517
 
c90517
 static void     gdm_manager_class_init  (GdmManagerClass *klass);
c90517
 static void     gdm_manager_init        (GdmManager      *manager);
c90517
 static void     gdm_manager_dispose     (GObject         *object);
c90517
 
c90517
 static GdmSession *create_user_session_for_display (GdmManager *manager,
c90517
                                                     GdmDisplay *display,
c90517
                                                     uid_t       allowed_user);
c90517
 static void     start_user_session (GdmManager                *manager,
c90517
@@ -1415,67 +1416,74 @@ typedef struct {
c90517
 static void
c90517
 destroy_username_lookup_operation (UsernameLookupOperation *operation)
c90517
 {
c90517
         g_object_unref (operation->manager);
c90517
         g_object_unref (operation->display);
c90517
         g_free (operation->username);
c90517
         g_free (operation);
c90517
 }
c90517
 
c90517
 static void
c90517
 on_user_is_loaded_changed (ActUser                 *user,
c90517
                            GParamSpec              *pspec,
c90517
                            UsernameLookupOperation *operation)
c90517
 {
c90517
         if (act_user_is_loaded (user)) {
c90517
                 set_up_automatic_login_session_if_user_exists (operation->manager, operation->display, user);
c90517
                 g_signal_handlers_disconnect_by_func (G_OBJECT (user),
c90517
                                                       G_CALLBACK (on_user_is_loaded_changed),
c90517
                                                       operation);
c90517
                 destroy_username_lookup_operation (operation);
c90517
         }
c90517
 }
c90517
 
c90517
 static void
c90517
 set_up_session (GdmManager *manager,
c90517
                 GdmDisplay *display)
c90517
 {
c90517
         ActUserManager *user_manager;
c90517
         ActUser *user;
c90517
         gboolean loaded;
c90517
-        gboolean is_initial_display = FALSE;
c90517
+        gboolean seat_can_autologin = FALSE, seat_did_autologin = FALSE;
c90517
         gboolean autologin_enabled = FALSE;
c90517
+        g_autofree char *seat_id = NULL;
c90517
         char *username = NULL;
c90517
 
c90517
-        g_object_get (G_OBJECT (display), "is-initial", &is_initial_display, NULL);
c90517
+        g_object_get (G_OBJECT (display), "seat-id", &seat_id, NULL);
c90517
+
c90517
+        if (g_strcmp0 (seat_id, "seat0") == 0)
c90517
+                seat_can_autologin = TRUE;
c90517
+
c90517
+        if (manager->priv->did_automatic_login || manager->priv->automatic_login_display != NULL)
c90517
+                seat_did_autologin = TRUE;
c90517
 
c90517
-        if (!manager->priv->ran_once && is_initial_display)
c90517
+        if (seat_can_autologin && !seat_did_autologin)
c90517
                 autologin_enabled = get_automatic_login_details (manager, &username);
c90517
 
c90517
         if (!autologin_enabled) {
c90517
                 g_free (username);
c90517
 
c90517
 #ifdef HAVE_LIBXDMCP
c90517
                 if (GDM_IS_XDMCP_CHOOSER_DISPLAY (display)) {
c90517
                         set_up_chooser_session (manager, display);
c90517
                         return;
c90517
                 }
c90517
 #endif
c90517
 
c90517
                 set_up_greeter_session (manager, display);
c90517
                 return;
c90517
         }
c90517
 
c90517
         /* Check whether the user really exists before committing to autologin. */
c90517
         user_manager = act_user_manager_get_default ();
c90517
         user = act_user_manager_get_user (user_manager, username);
c90517
         g_object_get (user_manager, "is-loaded", &loaded, NULL);
c90517
 
c90517
         if (loaded) {
c90517
                 set_up_automatic_login_session_if_user_exists (manager, display, user);
c90517
         } else {
c90517
                 UsernameLookupOperation *operation;
c90517
 
c90517
                 operation = g_new (UsernameLookupOperation, 1);
c90517
                 operation->manager = g_object_ref (manager);
c90517
                 operation->display = g_object_ref (display);
c90517
                 operation->username = username;
c90517
@@ -1512,62 +1520,72 @@ on_display_status_changed (GdmDisplay *display,
c90517
                       "session-type", &session_type,
c90517
                       NULL);
c90517
 
c90517
         status = gdm_display_get_status (display);
c90517
 
c90517
         switch (status) {
c90517
                 case GDM_DISPLAY_PREPARED:
c90517
                 case GDM_DISPLAY_MANAGED:
c90517
                         if ((display_number == -1 && status == GDM_DISPLAY_PREPARED) ||
c90517
                             (display_number != -1 && status == GDM_DISPLAY_MANAGED)) {
c90517
                                 char *session_class;
c90517
 
c90517
                                 g_object_get (display,
c90517
                                               "session-class", &session_class,
c90517
                                               NULL);
c90517
                                 if (g_strcmp0 (session_class, "greeter") == 0)
c90517
                                         set_up_session (manager, display);
c90517
                                 g_free (session_class);
c90517
                         }
c90517
                         break;
c90517
                 case GDM_DISPLAY_FAILED:
c90517
                 case GDM_DISPLAY_UNMANAGED:
c90517
                 case GDM_DISPLAY_FINISHED:
c90517
 #ifdef WITH_PLYMOUTH
c90517
                         if (quit_plymouth) {
c90517
                                 plymouth_quit_without_transition ();
c90517
                                 manager->priv->plymouth_is_running = FALSE;
c90517
                         }
c90517
 #endif
c90517
 
c90517
-                        if (!doing_initial_setup && (status == GDM_DISPLAY_FINISHED || g_strcmp0 (session_type, "x11") == 0)) {
c90517
-                                manager->priv->ran_once = TRUE;
c90517
+                        if (display == manager->priv->automatic_login_display) {
c90517
+                                g_clear_weak_pointer (&manager->priv->automatic_login_display);
c90517
+
c90517
+                                manager->priv->did_automatic_login = TRUE;
c90517
+
c90517
+#ifdef ENABLE_WAYLAND_SUPPORT
c90517
+                                if (g_strcmp0 (session_type, "wayland") != 0 && status == GDM_DISPLAY_FAILED) {
c90517
+                                        /* we're going to fall back to X11, so try to autologin again
c90517
+                                         */
c90517
+                                        manager->priv->did_automatic_login = FALSE;
c90517
+                                }
c90517
+#endif
c90517
                         }
c90517
                         break;
c90517
                 default:
c90517
                         break;
c90517
         }
c90517
 
c90517
 }
c90517
 
c90517
 static void
c90517
 on_display_removed (GdmDisplayStore *display_store,
c90517
                     GdmDisplay      *display,
c90517
                     GdmManager      *manager)
c90517
 {
c90517
         char    *id;
c90517
 
c90517
         gdm_display_get_id (display, &id, NULL);
c90517
         g_dbus_object_manager_server_unexport (manager->priv->object_manager, id);
c90517
         g_free (id);
c90517
 
c90517
         g_signal_handlers_disconnect_by_func (display, G_CALLBACK (on_display_status_changed), manager);
c90517
 
c90517
         g_signal_emit (manager, signals[DISPLAY_REMOVED], 0, display);
c90517
 }
c90517
 
c90517
 static void
c90517
 destroy_start_user_session_operation (StartUserSessionOperation *operation)
c90517
 {
c90517
         g_object_set_data (G_OBJECT (operation->session),
c90517
                            "start-user-session-operation",
c90517
                            NULL);
c90517
@@ -1621,132 +1639,134 @@ create_display_for_user_session (GdmManager *self,
c90517
                                  const char *session_id)
c90517
 {
c90517
         GdmDisplay *display;
c90517
         /* at the moment we only create GdmLocalDisplay objects on seat0 */
c90517
         const char *seat_id = "seat0";
c90517
 
c90517
         display = gdm_local_display_new ();
c90517
 
c90517
         g_object_set (G_OBJECT (display),
c90517
                       "session-class", "user",
c90517
                       "seat-id", seat_id,
c90517
                       "session-id", session_id,
c90517
                       NULL);
c90517
         gdm_display_store_add (self->priv->display_store,
c90517
                                display);
c90517
         g_object_set_data (G_OBJECT (session), "gdm-display", display);
c90517
         g_object_set_data_full (G_OBJECT (display),
c90517
                                 "gdm-user-session",
c90517
                                 g_object_ref (session),
c90517
                                 (GDestroyNotify)
c90517
                                 clean_user_session);
c90517
 }
c90517
 
c90517
 static gboolean
c90517
 on_start_user_session (StartUserSessionOperation *operation)
c90517
 {
c90517
         GdmManager *self = operation->manager;
c90517
         gboolean migrated;
c90517
         gboolean fail_if_already_switched = TRUE;
c90517
         gboolean doing_initial_setup = FALSE;
c90517
-        gboolean starting_user_session_right_away = TRUE;
c90517
         GdmDisplay *display;
c90517
         const char *session_id;
c90517
 
c90517
         g_debug ("GdmManager: start or jump to session");
c90517
 
c90517
         /* If there's already a session running, jump to it.
c90517
          * If the only session running is the one we just opened,
c90517
          * start a session on it.
c90517
          */
c90517
         migrated = switch_to_compatible_user_session (operation->manager, operation->session, fail_if_already_switched);
c90517
 
c90517
         g_debug ("GdmManager: migrated: %d", migrated);
c90517
         if (migrated) {
c90517
                 /* We don't stop the manager here because
c90517
                    when Xorg exits it switches to the VT it was
c90517
                    started from.  That interferes with fast
c90517
                    user switching. */
c90517
                 gdm_session_reset (operation->session);
c90517
                 destroy_start_user_session_operation (operation);
c90517
                 goto out;
c90517
         }
c90517
 
c90517
         display = get_display_for_user_session (operation->session);
c90517
 
c90517
         g_object_get (G_OBJECT (display), "doing-initial-setup", &doing_initial_setup, NULL);
c90517
 
c90517
         session_id = gdm_session_get_conversation_session_id (operation->session,
c90517
                                                               operation->service_name);
c90517
 
c90517
         if (gdm_session_get_display_mode (operation->session) == GDM_SESSION_DISPLAY_MODE_REUSE_VT) {
c90517
                 /* In this case, the greeter's display is morphing into
c90517
                  * the user session display. Kill the greeter on this session
c90517
                  * and let the user session follow the same display. */
c90517
                 gdm_display_stop_greeter_session (display);
c90517
                 g_object_set (G_OBJECT (display),
c90517
                                 "session-class", "user",
c90517
                                 "session-id", session_id,
c90517
                                 NULL);
c90517
         } else {
c90517
                 uid_t allowed_uid;
c90517
 
c90517
                 g_object_ref (display);
c90517
                 if (doing_initial_setup) {
c90517
                         g_debug ("GdmManager: closing down initial setup display");
c90517
                         gdm_display_stop_greeter_session (display);
c90517
                         gdm_display_unmanage (display);
c90517
                         gdm_display_finish (display);
c90517
                 } else {
c90517
                         g_debug ("GdmManager: session has its display server, reusing our server for another login screen");
c90517
                 }
c90517
 
c90517
                 /* The user session is going to follow the session worker
c90517
                  * into the new display. Untie it from this display and
c90517
                  * create a new session for a future user login. */
c90517
                 allowed_uid = gdm_session_get_allowed_user (operation->session);
c90517
                 g_object_set_data (G_OBJECT (display), "gdm-user-session", NULL);
c90517
                 g_object_set_data (G_OBJECT (operation->session), "gdm-display", NULL);
c90517
                 create_user_session_for_display (operation->manager, display, allowed_uid);
c90517
 
c90517
+                /* Give the user session a new display object for bookkeeping purposes */
c90517
+                create_display_for_user_session (operation->manager,
c90517
+                                                 operation->session,
c90517
+                                                 session_id);
c90517
+
c90517
                 if ((g_strcmp0 (operation->service_name, "gdm-autologin") == 0) &&
c90517
                     !gdm_session_client_is_connected (operation->session)) {
c90517
                         /* remove the unused prepared greeter display since we're not going
c90517
                          * to have a greeter */
c90517
                         gdm_display_store_remove (self->priv->display_store, display);
c90517
                         g_object_unref (display);
c90517
-                }
c90517
 
c90517
-                /* Give the user session a new display object for bookkeeping purposes */
c90517
-                create_display_for_user_session (operation->manager,
c90517
-                                                 operation->session,
c90517
-                                                 session_id);
c90517
+                        self->priv->automatic_login_display = g_object_get_data (G_OBJECT (operation->session), "gdm-display");
c90517
+                        g_object_add_weak_pointer (G_OBJECT (display), (gpointer *) &self->priv->automatic_login_display);
c90517
+                }
c90517
         }
c90517
 
c90517
         start_user_session (operation->manager, operation);
c90517
 
c90517
  out:
c90517
         return G_SOURCE_REMOVE;
c90517
 }
c90517
 
c90517
 static void
c90517
 queue_start_user_session (GdmManager *manager,
c90517
                           GdmSession *session,
c90517
                           const char *service_name)
c90517
 {
c90517
         StartUserSessionOperation *operation;
c90517
 
c90517
         operation = g_slice_new0 (StartUserSessionOperation);
c90517
         operation->manager = manager;
c90517
         operation->session = g_object_ref (session);
c90517
         operation->service_name = g_strdup (service_name);
c90517
 
c90517
         operation->idle_id = g_idle_add ((GSourceFunc) on_start_user_session, operation);
c90517
         g_object_set_data (G_OBJECT (session), "start-user-session-operation", operation);
c90517
 }
c90517
 
c90517
 static void
c90517
 start_user_session_if_ready (GdmManager *manager,
c90517
                              GdmSession *session,
c90517
                              const char *service_name)
c90517
 {
c90517
         gboolean start_when_ready;
c90517
@@ -2601,60 +2621,62 @@ unexport_display (const char *id,
c90517
                   GdmDisplay *display,
c90517
                   GdmManager *manager)
c90517
 {
c90517
         if (!g_dbus_connection_is_closed (manager->priv->connection))
c90517
                 g_dbus_object_manager_server_unexport (manager->priv->object_manager, id);
c90517
 }
c90517
 
c90517
 static void
c90517
 finish_display (const char *id,
c90517
                 GdmDisplay *display,
c90517
                 GdmManager *manager)
c90517
 {
c90517
         gdm_display_stop_greeter_session (display);
c90517
         if (gdm_display_get_status (display) == GDM_DISPLAY_MANAGED)
c90517
                 gdm_display_unmanage (display);
c90517
         gdm_display_finish (display);
c90517
 }
c90517
 
c90517
 static void
c90517
 gdm_manager_dispose (GObject *object)
c90517
 {
c90517
         GdmManager *manager;
c90517
 
c90517
         g_return_if_fail (object != NULL);
c90517
         g_return_if_fail (GDM_IS_MANAGER (object));
c90517
 
c90517
         manager = GDM_MANAGER (object);
c90517
 
c90517
         g_return_if_fail (manager->priv != NULL);
c90517
 
c90517
+        g_clear_weak_pointer (&manager->priv->automatic_login_display);
c90517
+
c90517
 #ifdef HAVE_LIBXDMCP
c90517
         g_clear_object (&manager->priv->xdmcp_factory);
c90517
 #endif
c90517
         g_clear_object (&manager->priv->local_factory);
c90517
         g_clear_pointer (&manager->priv->open_reauthentication_requests,
c90517
                          (GDestroyNotify)
c90517
                          g_hash_table_unref);
c90517
         g_clear_pointer (&manager->priv->transient_sessions,
c90517
                          (GDestroyNotify)
c90517
                          g_hash_table_unref);
c90517
 
c90517
         g_list_foreach (manager->priv->user_sessions,
c90517
                         (GFunc) gdm_session_close,
c90517
                         NULL);
c90517
         g_list_free_full (manager->priv->user_sessions, (GDestroyNotify) g_object_unref);
c90517
         manager->priv->user_sessions = NULL;
c90517
 
c90517
         g_signal_handlers_disconnect_by_func (G_OBJECT (manager->priv->display_store),
c90517
                                               G_CALLBACK (on_display_added),
c90517
                                               manager);
c90517
         g_signal_handlers_disconnect_by_func (G_OBJECT (manager->priv->display_store),
c90517
                                               G_CALLBACK (on_display_removed),
c90517
                                               manager);
c90517
 
c90517
         if (!g_dbus_connection_is_closed (manager->priv->connection)) {
c90517
                 gdm_display_store_foreach (manager->priv->display_store,
c90517
                                            (GdmDisplayStoreFunc)unexport_display,
c90517
                                            manager);
c90517
                 g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (manager));
c90517
         }
c90517
-- 
c90517
2.26.0
c90517