summaryrefslogtreecommitdiff
path: root/0001-manager-allow-multiple-xdmcp-logins-for-the-same-use.patch
blob: f514073a0c416f1e9c439f3d88ae456f6d069038 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
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