Blame SOURCES/0001-manager-allow-multiple-xdmcp-logins-for-the-same-use.patch

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