Blob Blame History Raw
From 60a03333bec4f7904a2cfddb291d22ce493e1ced Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Fri, 31 Mar 2017 14:54:44 -0400
Subject: [PATCH 06/13] manager: fix up support for chooser

We were missing some chunks of code to handle dealing with
the chooser.

This commit adds in the necessary bits to start the chooser,
and deal with the choice.
---
 daemon/gdm-manager.c | 62 ++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 53 insertions(+), 9 deletions(-)

diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
index 3014dad3..373778d9 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -18,67 +18,69 @@
  *
  */
 
 #include "config.h"
 
 #include <stdlib.h>
 #include <stdio.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <string.h>
 #include <signal.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 
 #include <glib.h>
 #include <glib/gi18n.h>
 #include <glib/gstdio.h>
 #include <glib-object.h>
 
 #include <act/act-user-manager.h>
 
 #include <systemd/sd-login.h>
 
 #include "gdm-common.h"
 
 #include "gdm-dbus-util.h"
 #include "gdm-manager.h"
 #include "gdm-manager-glue.h"
 #include "gdm-display-store.h"
 #include "gdm-display-factory.h"
+#include "gdm-launch-environment.h"
 #include "gdm-local-display.h"
 #include "gdm-local-display-factory.h"
 #include "gdm-session.h"
 #include "gdm-session-record.h"
 #include "gdm-settings-direct.h"
 #include "gdm-settings-keys.h"
 #include "gdm-xdmcp-display-factory.h"
+#include "gdm-xdmcp-chooser-display.h"
 
 #define GDM_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_MANAGER, GdmManagerPrivate))
 
 #define GDM_DBUS_PATH             "/org/gnome/DisplayManager"
 #define GDM_MANAGER_PATH          GDM_DBUS_PATH "/Manager"
 #define GDM_MANAGER_DISPLAYS_PATH GDM_DBUS_PATH "/Displays"
 
 #define INITIAL_SETUP_USERNAME "gnome-initial-setup"
 
 typedef struct
 {
         GdmManager *manager;
         GdmSession *session;
         char *service_name;
         guint idle_id;
 } StartUserSessionOperation;
 
 struct GdmManagerPrivate
 {
         GdmDisplayStore        *display_store;
         GdmLocalDisplayFactory *local_factory;
 #ifdef HAVE_LIBXDMCP
         GdmXdmcpDisplayFactory *xdmcp_factory;
 #endif
         GList                  *user_sessions;
         GHashTable             *transient_sessions;
         GHashTable             *open_reauthentication_requests;
         gboolean                xdmcp_enabled;
         GCancellable           *cancellable;
 
@@ -793,89 +795,107 @@ gdm_manager_handle_register_display (GdmDBusManager        *manager,
                 /* FIXME: this should happen in gdm-session.c when the session is opened
                  */
                 if (tty != NULL)
                         g_object_set (G_OBJECT (session), "display-device", tty, NULL);
 
                 pid = gdm_session_get_pid (session);
 
                 if (pid > 0) {
                         add_session_record (self, session, pid, SESSION_RECORD_LOGIN);
                 }
         }
 
         g_object_set (G_OBJECT (display), "status", GDM_DISPLAY_MANAGED, NULL);
 
         gdm_dbus_manager_complete_register_display (GDM_DBUS_MANAGER (manager),
                                                     invocation);
 
         g_clear_pointer (&x11_display_name, g_free);
         g_clear_pointer (&tty, g_free);
         return TRUE;
 }
 
 static gboolean
 gdm_manager_handle_open_session (GdmDBusManager        *manager,
                                  GDBusMethodInvocation *invocation)
 {
         GdmManager       *self = GDM_MANAGER (manager);
         const char       *sender;
         GDBusConnection  *connection;
         GdmDisplay       *display = NULL;
-        GdmSession       *session;
+        GdmSession       *session = NULL;
         const char       *address;
         GPid              pid = 0;
         uid_t             uid = (uid_t) -1;
         uid_t             allowed_user;
 
         g_debug ("GdmManager: trying to open new session");
 
         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, NULL, NULL, NULL, &pid, &uid, NULL, NULL);
 
         if (display == NULL) {
                 g_dbus_method_invocation_return_error_literal (invocation,
                                                                G_DBUS_ERROR,
                                                                G_DBUS_ERROR_ACCESS_DENIED,
                                                                _("No session available"));
 
                 return TRUE;
         }
 
-        session = get_embryonic_user_session_for_display (display);
+        if (GDM_IS_XDMCP_CHOOSER_DISPLAY (display)) {
+                GdmLaunchEnvironment *launch_environment;
 
-        if (gdm_session_is_running (session)) {
-                g_dbus_method_invocation_return_error_literal (invocation,
-                                                               G_DBUS_ERROR,
-                                                               G_DBUS_ERROR_ACCESS_DENIED,
-                                                               _("Can only be called before user is logged in"));
-                return TRUE;
+                g_object_get (display, "launch-environment", &launch_environment, NULL);
+
+                if (launch_environment != NULL) {
+                        session = gdm_launch_environment_get_session (launch_environment);
+                }
+
+                if (session == NULL) {
+                        g_dbus_method_invocation_return_error_literal (invocation,
+                                                                       G_DBUS_ERROR,
+                                                                       G_DBUS_ERROR_ACCESS_DENIED,
+                                                                       _("Chooser session unavailable"));
+                        return TRUE;
+                }
+        } else {
+                session = get_embryonic_user_session_for_display (display);
+
+                if (gdm_session_is_running (session)) {
+                        g_dbus_method_invocation_return_error_literal (invocation,
+                                                                       G_DBUS_ERROR,
+                                                                       G_DBUS_ERROR_ACCESS_DENIED,
+                                                                       _("Can only be called before user is logged in"));
+                        return TRUE;
+                }
         }
 
         allowed_user = gdm_session_get_allowed_user (session);
 
         if (uid != allowed_user) {
                 g_dbus_method_invocation_return_error_literal (invocation,
                                                                G_DBUS_ERROR,
                                                                G_DBUS_ERROR_ACCESS_DENIED,
                                                                _("Caller not GDM"));
                 return TRUE;
         }
 
         address = gdm_session_get_server_address (session);
 
         if (address == NULL) {
                 g_dbus_method_invocation_return_error_literal (invocation,
                                                                G_DBUS_ERROR,
                                                                G_DBUS_ERROR_ACCESS_DENIED,
                                                                _("Unable to open private communication channel"));
                 return TRUE;
         }
 
         gdm_dbus_manager_complete_open_session (GDM_DBUS_MANAGER (manager),
                                                 invocation,
                                                 address);
         return TRUE;
 }
 
 static void
 close_transient_session (GdmManager *self,
@@ -1309,60 +1329,80 @@ get_username_for_greeter_display (GdmManager *manager,
         }
 }
 
 static void
 set_up_automatic_login_session (GdmManager *manager,
                                 GdmDisplay *display)
 {
         GdmSession *session;
         char       *display_session_type = NULL;
         gboolean is_initial;
 
         /* 0 is root user; since the daemon talks to the session object
          * directly, itself, for automatic login
          */
         session = create_embryonic_user_session_for_display (manager, display, 0);
 
         g_object_get (G_OBJECT (display),
                       "is-initial", &is_initial,
                       "session-type", &display_session_type,
                       NULL);
 
         g_object_set (G_OBJECT (session),
                       "display-is-initial", is_initial,
                       NULL);
 
         g_debug ("GdmManager: Starting automatic login conversation");
         gdm_session_start_conversation (session, "gdm-autologin");
 }
 
 static void
+set_up_chooser_session (GdmManager *manager,
+                        GdmDisplay *display)
+{
+        const char *allowed_user;
+        struct passwd *passwd_entry;
+
+        allowed_user = get_username_for_greeter_display (manager, display);
+
+        if (!gdm_get_pwent_for_name (allowed_user, &passwd_entry)) {
+                g_warning ("GdmManager: couldn't look up username %s",
+                           allowed_user);
+                gdm_display_unmanage (display);
+                gdm_display_finish (display);
+                return;
+        }
+
+        gdm_display_start_greeter_session (display);
+}
+
+static void
 set_up_greeter_session (GdmManager *manager,
                         GdmDisplay *display)
 {
         const char *allowed_user;
         struct passwd *passwd_entry;
 
         allowed_user = get_username_for_greeter_display (manager, display);
 
         if (!gdm_get_pwent_for_name (allowed_user, &passwd_entry)) {
                 g_warning ("GdmManager: couldn't look up username %s",
                            allowed_user);
                 gdm_display_unmanage (display);
                 gdm_display_finish (display);
                 return;
         }
 
         create_embryonic_user_session_for_display (manager, display, passwd_entry->pw_uid);
         gdm_display_start_greeter_session (display);
 }
 
 static void
 set_up_automatic_login_session_if_user_exists (GdmManager *manager,
                                                GdmDisplay *display,
                                                ActUser    *user)
 {
         if (act_user_is_nonexistent (user))
                 set_up_greeter_session (manager, display);
         else
                 set_up_automatic_login_session (manager, display);
 }
@@ -1383,61 +1423,65 @@ destroy_username_lookup_operation (UsernameLookupOperation *operation)
 }
 
 static void
 on_user_is_loaded_changed (ActUser                 *user,
                            GParamSpec              *pspec,
                            UsernameLookupOperation *operation)
 {
         if (act_user_is_loaded (user)) {
                 set_up_automatic_login_session_if_user_exists (operation->manager, operation->display, user);
                 g_signal_handlers_disconnect_by_func (G_OBJECT (user),
                                                       G_CALLBACK (on_user_is_loaded_changed),
                                                       operation);
                 destroy_username_lookup_operation (operation);
         }
 }
 
 static void
 set_up_session (GdmManager *manager,
                 GdmDisplay *display)
 {
         ActUserManager *user_manager;
         ActUser *user;
         gboolean loaded;
         gboolean autologin_enabled = FALSE;
         char *username = NULL;
 
         if (!manager->priv->ran_once && display_is_on_seat0 (display))
                 autologin_enabled = get_automatic_login_details (manager, &username);
 
         if (!autologin_enabled) {
-                set_up_greeter_session (manager, display);
+                if (GDM_IS_XDMCP_CHOOSER_DISPLAY (display)) {
+                        set_up_chooser_session (manager, display);
+                } else {
+                        set_up_greeter_session (manager, display);
+                }
                 g_free (username);
                 return;
         }
 
         /* Check whether the user really exists before committing to autologin. */
         user_manager = act_user_manager_get_default ();
         user = act_user_manager_get_user (user_manager, username);
         g_object_get (user_manager, "is-loaded", &loaded, NULL);
 
         if (loaded) {
                 set_up_automatic_login_session_if_user_exists (manager, display, user);
         } else {
                 UsernameLookupOperation *operation;
 
                 operation = g_new (UsernameLookupOperation, 1);
                 operation->manager = g_object_ref (manager);
                 operation->display = g_object_ref (display);
                 operation->username = username;
 
                 g_signal_connect (user,
                                   "notify::is-loaded",
                                   G_CALLBACK (on_user_is_loaded_changed),
                                   operation);
         }
 }
 
 static void
 greeter_display_started (GdmManager *manager,
                          GdmDisplay *display)
 {
-- 
2.12.0