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

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