You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
344 lines
14 KiB
344 lines
14 KiB
From 58f2bb3560f1066d0cda93a749a6d1648e3c3d0c Mon Sep 17 00:00:00 2001 |
|
From: Ray Strode <rstrode@redhat.com> |
|
Date: Thu, 20 Dec 2018 14:51:38 -0500 |
|
Subject: [PATCH 1/3] manager: allow multiple xdmcp logins for the same user |
|
|
|
--- |
|
common/gdm-settings-keys.h | 1 + |
|
daemon/gdm-manager.c | 71 ++++++++++++++++++++++++++++---------- |
|
data/gdm.schemas.in | 5 +++ |
|
3 files changed, 59 insertions(+), 18 deletions(-) |
|
|
|
diff --git a/common/gdm-settings-keys.h b/common/gdm-settings-keys.h |
|
index 87685d3c..4b3a1ffe 100644 |
|
--- a/common/gdm-settings-keys.h |
|
+++ b/common/gdm-settings-keys.h |
|
@@ -30,37 +30,38 @@ G_BEGIN_DECLS |
|
#define GDM_KEY_AUTO_LOGIN_ENABLE "daemon/AutomaticLoginEnable" |
|
#define GDM_KEY_AUTO_LOGIN_USER "daemon/AutomaticLogin" |
|
#define GDM_KEY_TIMED_LOGIN_ENABLE "daemon/TimedLoginEnable" |
|
#define GDM_KEY_TIMED_LOGIN_USER "daemon/TimedLogin" |
|
#define GDM_KEY_TIMED_LOGIN_DELAY "daemon/TimedLoginDelay" |
|
#define GDM_KEY_INITIAL_SETUP_ENABLE "daemon/InitialSetupEnable" |
|
#define GDM_KEY_PREFERRED_DISPLAY_SERVER "daemon/PreferredDisplayServer" |
|
#define GDM_KEY_WAYLAND_ENABLE "daemon/WaylandEnable" |
|
#define GDM_KEY_XORG_ENABLE "daemon/XorgEnable" |
|
|
|
#define GDM_KEY_DEBUG "debug/Enable" |
|
|
|
#define GDM_KEY_INCLUDE "greeter/Include" |
|
#define GDM_KEY_EXCLUDE "greeter/Exclude" |
|
#define GDM_KEY_INCLUDE_ALL "greeter/IncludeAll" |
|
|
|
#define GDM_KEY_DISALLOW_TCP "security/DisallowTCP" |
|
#define GDM_KEY_ALLOW_REMOTE_AUTOLOGIN "security/AllowRemoteAutoLogin" |
|
|
|
#define GDM_KEY_XDMCP_ENABLE "xdmcp/Enable" |
|
#define GDM_KEY_SHOW_LOCAL_GREETER "xdmcp/ShowLocalGreeter" |
|
#define GDM_KEY_MAX_PENDING "xdmcp/MaxPending" |
|
#define GDM_KEY_MAX_SESSIONS "xdmcp/MaxSessions" |
|
#define GDM_KEY_MAX_WAIT "xdmcp/MaxWait" |
|
#define GDM_KEY_DISPLAYS_PER_HOST "xdmcp/DisplaysPerHost" |
|
#define GDM_KEY_UDP_PORT "xdmcp/Port" |
|
#define GDM_KEY_INDIRECT "xdmcp/HonorIndirect" |
|
#define GDM_KEY_MAX_WAIT_INDIRECT "xdmcp/MaxWaitIndirect" |
|
#define GDM_KEY_PING_INTERVAL "xdmcp/PingIntervalSeconds" |
|
#define GDM_KEY_WILLING "xdmcp/Willing" |
|
+#define GDM_KEY_ALLOW_MULTIPLE_SESSIONS_PER_USER "xdmcp/AllowMultipleSessionsPerUser" |
|
|
|
#define GDM_KEY_MULTICAST "chooser/Multicast" |
|
#define GDM_KEY_MULTICAST_ADDR "chooser/MulticastAddr" |
|
|
|
G_END_DECLS |
|
|
|
#endif /* _GDM_SETTINGS_KEYS_H */ |
|
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c |
|
index e1bc62d7..08c3cc17 100644 |
|
--- a/daemon/gdm-manager.c |
|
+++ b/daemon/gdm-manager.c |
|
@@ -566,93 +566,106 @@ get_display_and_details_for_bus_sender (GdmManager *self, |
|
*out_tty = get_tty_for_session_id (session_id, &error); |
|
|
|
if (error != NULL) { |
|
g_debug ("GdmManager: Error while retrieving tty for session: %s", |
|
error->message); |
|
g_clear_error (&error); |
|
} |
|
} |
|
|
|
display = gdm_display_store_find (self->priv->display_store, |
|
lookup_by_session_id, |
|
(gpointer) session_id); |
|
|
|
out: |
|
if (out_display != NULL) { |
|
*out_display = display; |
|
} |
|
|
|
g_free (session_id); |
|
} |
|
|
|
static gboolean |
|
switch_to_compatible_user_session (GdmManager *manager, |
|
GdmSession *session, |
|
gboolean fail_if_already_switched) |
|
{ |
|
gboolean res; |
|
gboolean ret; |
|
const char *username; |
|
const char *seat_id; |
|
- const char *ssid_to_activate; |
|
+ const char *ssid_to_activate = NULL; |
|
GdmSession *existing_session; |
|
|
|
ret = FALSE; |
|
|
|
username = gdm_session_get_username (session); |
|
seat_id = gdm_session_get_display_seat_id (session); |
|
|
|
- if (!fail_if_already_switched) { |
|
- session = NULL; |
|
- } |
|
+ if (!fail_if_already_switched) |
|
+ ssid_to_activate = gdm_session_get_session_id (session); |
|
|
|
- existing_session = find_session_for_user_on_seat (manager, username, seat_id, session); |
|
+ if (ssid_to_activate == NULL) { |
|
+ if (!seat_id || !sd_seat_can_multi_session (seat_id)) { |
|
+ g_debug ("GdmManager: unable to activate existing sessions from login screen unless on seat0"); |
|
+ goto out; |
|
+ } |
|
|
|
- if (existing_session != NULL) { |
|
- ssid_to_activate = gdm_session_get_session_id (existing_session); |
|
- if (seat_id != NULL) { |
|
- res = gdm_activate_session_by_id (manager->priv->connection, seat_id, ssid_to_activate); |
|
- if (! res) { |
|
- g_debug ("GdmManager: unable to activate session: %s", ssid_to_activate); |
|
- goto out; |
|
- } |
|
+ if (!fail_if_already_switched) { |
|
+ session = NULL; |
|
} |
|
|
|
- res = session_unlock (manager, ssid_to_activate); |
|
- if (!res) { |
|
- /* this isn't fatal */ |
|
- g_debug ("GdmManager: unable to unlock session: %s", ssid_to_activate); |
|
+ existing_session = find_session_for_user_on_seat (manager, username, seat_id, session); |
|
+ |
|
+ if (existing_session != NULL) { |
|
+ ssid_to_activate = gdm_session_get_session_id (existing_session); |
|
} |
|
- } else { |
|
+ } |
|
+ |
|
+ if (ssid_to_activate == NULL) { |
|
goto out; |
|
} |
|
|
|
+ if (seat_id != NULL) { |
|
+ res = gdm_activate_session_by_id (manager->priv->connection, seat_id, ssid_to_activate); |
|
+ if (! res) { |
|
+ g_debug ("GdmManager: unable to activate session: %s", ssid_to_activate); |
|
+ goto out; |
|
+ } |
|
+ } |
|
+ |
|
+ res = session_unlock (manager, ssid_to_activate); |
|
+ if (!res) { |
|
+ /* this isn't fatal */ |
|
+ g_debug ("GdmManager: unable to unlock session: %s", ssid_to_activate); |
|
+ } |
|
+ |
|
ret = TRUE; |
|
|
|
out: |
|
return ret; |
|
} |
|
|
|
static GdmDisplay * |
|
get_display_for_user_session (GdmSession *session) |
|
{ |
|
return g_object_get_data (G_OBJECT (session), "gdm-display"); |
|
} |
|
|
|
static GdmSession * |
|
get_user_session_for_display (GdmDisplay *display) |
|
{ |
|
if (display == NULL) { |
|
return NULL; |
|
} |
|
|
|
return g_object_get_data (G_OBJECT (display), "gdm-user-session"); |
|
} |
|
|
|
static gboolean |
|
add_session_record (GdmManager *manager, |
|
GdmSession *session, |
|
GPid pid, |
|
SessionRecord record) |
|
{ |
|
const char *username; |
|
char *display_name, *hostname, *display_device, *display_seat_id; |
|
@@ -1096,92 +1109,114 @@ open_temporary_reauthentication_channel (GdmManager *self, |
|
g_signal_connect (session, |
|
"client-disconnected", |
|
G_CALLBACK (on_reauthentication_client_disconnected), |
|
self); |
|
g_signal_connect (session, |
|
"client-rejected", |
|
G_CALLBACK (on_reauthentication_client_rejected), |
|
self); |
|
g_signal_connect (session, |
|
"cancelled", |
|
G_CALLBACK (on_reauthentication_cancelled), |
|
self); |
|
g_signal_connect (session, |
|
"conversation-started", |
|
G_CALLBACK (on_reauthentication_conversation_started), |
|
self); |
|
g_signal_connect (session, |
|
"conversation-stopped", |
|
G_CALLBACK (on_reauthentication_conversation_stopped), |
|
self); |
|
g_signal_connect (session, |
|
"verification-complete", |
|
G_CALLBACK (on_reauthentication_verification_complete), |
|
self); |
|
|
|
address = gdm_session_get_server_address (session); |
|
|
|
return g_strdup (address); |
|
} |
|
|
|
+static gboolean |
|
+remote_users_can_log_in_more_than_once (GdmManager *manager) |
|
+{ |
|
+ gboolean enabled; |
|
+ |
|
+ enabled = FALSE; |
|
+ |
|
+ gdm_settings_direct_get_boolean (GDM_KEY_ALLOW_MULTIPLE_SESSIONS_PER_USER, &enabled); |
|
+ |
|
+ g_debug ("GdmDisplay: Remote users allowed to log in more than once: %s", enabled? "yes" : "no"); |
|
+ |
|
+ return enabled; |
|
+} |
|
+ |
|
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, NULL, &pid, &uid, &is_login_screen, &is_remote); |
|
|
|
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; |
|
} |
|
|
|
+ if (is_login_screen && is_remote && remote_users_can_log_in_more_than_once (self)) { |
|
+ g_dbus_method_invocation_return_error_literal (invocation, |
|
+ G_DBUS_ERROR, |
|
+ G_DBUS_ERROR_ACCESS_DENIED, |
|
+ "Login screen creates new sessions for remote connections"); |
|
+ return TRUE; |
|
+ } |
|
+ |
|
if (is_login_screen) { |
|
g_debug ("GdmManager: looking for login screen session for user %s on seat %s", username, seat_id); |
|
session = find_session_for_user_on_seat (self, |
|
username, |
|
seat_id, |
|
NULL); |
|
} else { |
|
g_debug ("GdmManager: looking for user session on display"); |
|
session = get_user_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); |
|
diff --git a/data/gdm.schemas.in b/data/gdm.schemas.in |
|
index a1035f95..929d13d9 100644 |
|
--- a/data/gdm.schemas.in |
|
+++ b/data/gdm.schemas.in |
|
@@ -112,33 +112,38 @@ |
|
<schema> |
|
<key>xdmcp/DisplaysPerHost</key> |
|
<signature>i</signature> |
|
<default>1</default> |
|
</schema> |
|
<schema> |
|
<key>xdmcp/Port</key> |
|
<signature>i</signature> |
|
<default>177</default> |
|
</schema> |
|
<schema> |
|
<key>xdmcp/HonorIndirect</key> |
|
<signature>b</signature> |
|
<default>true</default> |
|
</schema> |
|
<schema> |
|
<key>xdmcp/MaxWaitIndirect</key> |
|
<signature>i</signature> |
|
<default>30</default> |
|
</schema> |
|
<schema> |
|
<key>xdmcp/PingIntervalSeconds</key> |
|
<signature>i</signature> |
|
<default>0</default> |
|
</schema> |
|
<schema> |
|
<key>xdmcp/Willing</key> |
|
<signature>s</signature> |
|
<default>@gdmconfdir@/Xwilling</default> |
|
</schema> |
|
+ <schema> |
|
+ <key>xdmcp/AllowMultipleSessionsPerUser</key> |
|
+ <signature>b</signature> |
|
+ <default>false</default> |
|
+ </schema> |
|
</schemalist> |
|
</gdmschemafile> |
|
|
|
-- |
|
2.37.3 |
|
|
|
|