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