1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2 *
3 * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 *
19 */
20
21 #include "config.h"
22
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <stdint.h>
26 #include <fcntl.h>
27 #include <unistd.h>
28 #include <string.h>
29 #include <signal.h>
30 #include <sys/stat.h>
31 #include <sys/types.h>
32
33 #include <glib.h>
34 #include <glib/gi18n.h>
35 #include <glib-object.h>
36
37 #include <xcb/xcb.h>
38 #include <X11/Xlib.h>
39
40 #include "gdm-common.h"
41 #include "gdm-display.h"
42 #include "gdm-display-glue.h"
43 #include "gdm-display-access-file.h"
44 #include "gdm-launch-environment.h"
45
46 #include "gdm-settings-direct.h"
47 #include "gdm-settings-keys.h"
48
49 #include "gdm-launch-environment.h"
50 #include "gdm-dbus-util.h"
51
52 #define INITIAL_SETUP_USERNAME "gnome-initial-setup"
53 #define GNOME_SESSION_SESSIONS_PATH DATADIR "/gnome-session/sessions"
54
55 #define GDM_DISPLAY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_DISPLAY, GdmDisplayPrivate))
56
57 struct GdmDisplayPrivate
58 {
59 char *id;
60 char *seat_id;
61 char *session_id;
62 char *session_class;
63 char *session_type;
64
65 char *remote_hostname;
66 int x11_display_number;
67 char *x11_display_name;
68 int status;
69 time_t creation_time;
70 GTimer *server_timer;
71
72 char *x11_cookie;
73 gsize x11_cookie_size;
74 GdmDisplayAccessFile *access_file;
75
76 guint finish_idle_id;
77
78 xcb_connection_t *xcb_connection;
79 int xcb_screen_number;
80
81 GDBusConnection *connection;
82 GdmDisplayAccessFile *user_access_file;
83
84 GdmDBusDisplay *display_skeleton;
85 GDBusObjectSkeleton *object_skeleton;
86
87 GDBusProxy *accountsservice_proxy;
88
89 /* this spawns and controls the greeter session */
90 GdmLaunchEnvironment *launch_environment;
91
92 guint is_local : 1;
93 guint is_initial : 1;
94 guint allow_timed_login : 1;
95 guint have_existing_user_accounts : 1;
96 guint doing_initial_setup : 1;
97 };
98
99 enum {
100 PROP_0,
101 PROP_ID,
102 PROP_STATUS,
103 PROP_SEAT_ID,
104 PROP_SESSION_ID,
105 PROP_SESSION_CLASS,
106 PROP_SESSION_TYPE,
107 PROP_REMOTE_HOSTNAME,
108 PROP_X11_DISPLAY_NUMBER,
109 PROP_X11_DISPLAY_NAME,
110 PROP_X11_COOKIE,
111 PROP_X11_AUTHORITY_FILE,
112 PROP_IS_CONNECTED,
113 PROP_IS_LOCAL,
114 PROP_LAUNCH_ENVIRONMENT,
115 PROP_IS_INITIAL,
116 PROP_ALLOW_TIMED_LOGIN,
117 PROP_HAVE_EXISTING_USER_ACCOUNTS,
118 PROP_DOING_INITIAL_SETUP,
119 };
120
121 static void gdm_display_class_init (GdmDisplayClass *klass);
122 static void gdm_display_init (GdmDisplay *self);
123 static void gdm_display_finalize (GObject *object);
124 static void queue_finish (GdmDisplay *self);
125 static void _gdm_display_set_status (GdmDisplay *self,
126 int status);
127 static gboolean wants_initial_setup (GdmDisplay *self);
G_DEFINE_ABSTRACT_TYPE(GdmDisplay,gdm_display,G_TYPE_OBJECT)128 G_DEFINE_ABSTRACT_TYPE (GdmDisplay, gdm_display, G_TYPE_OBJECT)
129
130 static gboolean
131 chown_file (GFile *file,
132 uid_t uid,
133 gid_t gid,
134 GError **error)
135 {
136 if (!g_file_set_attribute_uint32 (file, G_FILE_ATTRIBUTE_UNIX_UID, uid,
137 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
138 NULL, error)) {
139 return FALSE;
140 }
141 if (!g_file_set_attribute_uint32 (file, G_FILE_ATTRIBUTE_UNIX_GID, gid,
142 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
143 NULL, error)) {
144 return FALSE;
145 }
146 return TRUE;
147 }
148
149 static gboolean
chown_recursively(GFile * dir,uid_t uid,gid_t gid,GError ** error)150 chown_recursively (GFile *dir,
151 uid_t uid,
152 gid_t gid,
153 GError **error)
154 {
155 GFile *file = NULL;
156 GFileInfo *info = NULL;
157 GFileEnumerator *enumerator = NULL;
158 gboolean retval = FALSE;
159
160 if (chown_file (dir, uid, gid, error) == FALSE) {
161 goto out;
162 }
163
164 enumerator = g_file_enumerate_children (dir,
165 G_FILE_ATTRIBUTE_STANDARD_TYPE","
166 G_FILE_ATTRIBUTE_STANDARD_NAME,
167 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
168 NULL, error);
169 if (!enumerator) {
170 goto out;
171 }
172
173 while ((info = g_file_enumerator_next_file (enumerator, NULL, error)) != NULL) {
174 file = g_file_get_child (dir, g_file_info_get_name (info));
175
176 if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
177 if (chown_recursively (file, uid, gid, error) == FALSE) {
178 goto out;
179 }
180 } else if (chown_file (file, uid, gid, error) == FALSE) {
181 goto out;
182 }
183
184 g_clear_object (&file);
185 g_clear_object (&info);
186 }
187
188 if (*error) {
189 goto out;
190 }
191
192 retval = TRUE;
193 out:
194 g_clear_object (&file);
195 g_clear_object (&info);
196 g_clear_object (&enumerator);
197
198 return retval;
199 }
200
201 GQuark
gdm_display_error_quark(void)202 gdm_display_error_quark (void)
203 {
204 static GQuark ret = 0;
205 if (ret == 0) {
206 ret = g_quark_from_static_string ("gdm_display_error");
207 }
208
209 return ret;
210 }
211
212 time_t
gdm_display_get_creation_time(GdmDisplay * self)213 gdm_display_get_creation_time (GdmDisplay *self)
214 {
215 g_return_val_if_fail (GDM_IS_DISPLAY (self), 0);
216
217 return self->priv->creation_time;
218 }
219
220 int
gdm_display_get_status(GdmDisplay * self)221 gdm_display_get_status (GdmDisplay *self)
222 {
223 g_return_val_if_fail (GDM_IS_DISPLAY (self), 0);
224
225 return self->priv->status;
226 }
227
228 const char *
gdm_display_get_session_id(GdmDisplay * self)229 gdm_display_get_session_id (GdmDisplay *self)
230 {
231 return self->priv->session_id;
232 }
233
234 static GdmDisplayAccessFile *
_create_access_file_for_user(GdmDisplay * self,const char * username,GError ** error)235 _create_access_file_for_user (GdmDisplay *self,
236 const char *username,
237 GError **error)
238 {
239 GdmDisplayAccessFile *access_file;
240 GError *file_error;
241
242 access_file = gdm_display_access_file_new (username);
243
244 file_error = NULL;
245 if (!gdm_display_access_file_open (access_file, &file_error)) {
246 g_propagate_error (error, file_error);
247 return NULL;
248 }
249
250 return access_file;
251 }
252
253 gboolean
gdm_display_create_authority(GdmDisplay * self)254 gdm_display_create_authority (GdmDisplay *self)
255 {
256 GdmDisplayAccessFile *access_file;
257 GError *error;
258 gboolean res;
259
260 g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
261 g_return_val_if_fail (self->priv->access_file == NULL, FALSE);
262
263 error = NULL;
264 access_file = _create_access_file_for_user (self, GDM_USERNAME, &error);
265
266 if (access_file == NULL) {
267 g_critical ("could not create display access file: %s", error->message);
268 g_error_free (error);
269 return FALSE;
270 }
271
272 g_free (self->priv->x11_cookie);
273 self->priv->x11_cookie = NULL;
274 res = gdm_display_access_file_add_display (access_file,
275 self,
276 &self->priv->x11_cookie,
277 &self->priv->x11_cookie_size,
278 &error);
279
280 if (! res) {
281
282 g_critical ("could not add display to access file: %s", error->message);
283 g_error_free (error);
284 gdm_display_access_file_close (access_file);
285 g_object_unref (access_file);
286 return FALSE;
287 }
288
289 self->priv->access_file = access_file;
290
291 return TRUE;
292 }
293
294 static void
setup_xhost_auth(XHostAddress * host_entries)295 setup_xhost_auth (XHostAddress *host_entries)
296 {
297 host_entries[0].family = FamilyServerInterpreted;
298 host_entries[0].address = "localuser\0root";
299 host_entries[0].length = sizeof ("localuser\0root");
300 host_entries[1].family = FamilyServerInterpreted;
301 host_entries[1].address = "localuser\0" GDM_USERNAME;
302 host_entries[1].length = sizeof ("localuser\0" GDM_USERNAME);
303 host_entries[2].family = FamilyServerInterpreted;
304 host_entries[2].address = "localuser\0gnome-initial-setup";
305 host_entries[2].length = sizeof ("localuser\0gnome-initial-setup");
306 }
307
308 gboolean
gdm_display_add_user_authorization(GdmDisplay * self,const char * username,char ** filename,GError ** error)309 gdm_display_add_user_authorization (GdmDisplay *self,
310 const char *username,
311 char **filename,
312 GError **error)
313 {
314 GdmDisplayAccessFile *access_file;
315 GError *access_file_error;
316 gboolean res;
317
318 int i;
319 XHostAddress host_entries[3];
320 xcb_void_cookie_t cookies[3];
321
322 g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
323
324 g_debug ("GdmDisplay: Adding authorization for user:%s on display %s", username, self->priv->x11_display_name);
325
326 g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
327
328 if (self->priv->user_access_file != NULL) {
329 g_set_error (error,
330 G_DBUS_ERROR,
331 G_DBUS_ERROR_ACCESS_DENIED,
332 "user access already assigned");
333 return FALSE;
334 }
335
336 g_debug ("GdmDisplay: Adding user authorization for %s", username);
337
338 access_file_error = NULL;
339 access_file = _create_access_file_for_user (self,
340 username,
341 &access_file_error);
342
343 if (access_file == NULL) {
344 g_propagate_error (error, access_file_error);
345 return FALSE;
346 }
347
348 res = gdm_display_access_file_add_display_with_cookie (access_file,
349 self,
350 self->priv->x11_cookie,
351 self->priv->x11_cookie_size,
352 &access_file_error);
353 if (! res) {
354 g_debug ("GdmDisplay: Unable to add user authorization for %s: %s",
355 username,
356 access_file_error->message);
357 g_propagate_error (error, access_file_error);
358 gdm_display_access_file_close (access_file);
359 g_object_unref (access_file);
360 return FALSE;
361 }
362
363 *filename = gdm_display_access_file_get_path (access_file);
364 self->priv->user_access_file = access_file;
365
366 g_debug ("GdmDisplay: Added user authorization for %s: %s", username, *filename);
367 /* Remove access for the programs run by greeter now that the
368 * user session is starting.
369 */
370 setup_xhost_auth (host_entries);
371
372 for (i = 0; i < G_N_ELEMENTS (host_entries); i++) {
373 cookies[i] = xcb_change_hosts_checked (self->priv->xcb_connection,
374 XCB_HOST_MODE_DELETE,
375 host_entries[i].family,
376 host_entries[i].length,
377 (uint8_t *) host_entries[i].address);
378 }
379
380 for (i = 0; i < G_N_ELEMENTS (cookies); i++) {
381 xcb_generic_error_t *xcb_error;
382
383 xcb_error = xcb_request_check (self->priv->xcb_connection, cookies[i]);
384
385 if (xcb_error != NULL) {
386 g_warning ("Failed to remove greeter program access to the display. Trying to proceed.");
387 free (xcb_error);
388 }
389 }
390
391 return TRUE;
392 }
393
394 gboolean
gdm_display_remove_user_authorization(GdmDisplay * self,const char * username,GError ** error)395 gdm_display_remove_user_authorization (GdmDisplay *self,
396 const char *username,
397 GError **error)
398 {
399 g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
400
401 g_debug ("GdmDisplay: Removing authorization for user:%s on display %s", username, self->priv->x11_display_name);
402
403 gdm_display_access_file_close (self->priv->user_access_file);
404
405 return TRUE;
406 }
407
408 gboolean
gdm_display_get_x11_cookie(GdmDisplay * self,const char ** x11_cookie,gsize * x11_cookie_size,GError ** error)409 gdm_display_get_x11_cookie (GdmDisplay *self,
410 const char **x11_cookie,
411 gsize *x11_cookie_size,
412 GError **error)
413 {
414 g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
415
416 if (x11_cookie != NULL) {
417 *x11_cookie = self->priv->x11_cookie;
418 }
419
420 if (x11_cookie_size != NULL) {
421 *x11_cookie_size = self->priv->x11_cookie_size;
422 }
423
424 return TRUE;
425 }
426
427 gboolean
gdm_display_get_x11_authority_file(GdmDisplay * self,char ** filename,GError ** error)428 gdm_display_get_x11_authority_file (GdmDisplay *self,
429 char **filename,
430 GError **error)
431 {
432 g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
433 g_return_val_if_fail (filename != NULL, FALSE);
434
435 if (self->priv->access_file != NULL) {
436 *filename = gdm_display_access_file_get_path (self->priv->access_file);
437 } else {
438 *filename = NULL;
439 }
440
441 return TRUE;
442 }
443
444 gboolean
gdm_display_get_remote_hostname(GdmDisplay * self,char ** hostname,GError ** error)445 gdm_display_get_remote_hostname (GdmDisplay *self,
446 char **hostname,
447 GError **error)
448 {
449 g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
450
451 if (hostname != NULL) {
452 *hostname = g_strdup (self->priv->remote_hostname);
453 }
454
455 return TRUE;
456 }
457
458 gboolean
gdm_display_get_x11_display_number(GdmDisplay * self,int * number,GError ** error)459 gdm_display_get_x11_display_number (GdmDisplay *self,
460 int *number,
461 GError **error)
462 {
463 g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
464
465 if (number != NULL) {
466 *number = self->priv->x11_display_number;
467 }
468
469 return TRUE;
470 }
471
472 gboolean
gdm_display_get_seat_id(GdmDisplay * self,char ** seat_id,GError ** error)473 gdm_display_get_seat_id (GdmDisplay *self,
474 char **seat_id,
475 GError **error)
476 {
477 g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
478
479 if (seat_id != NULL) {
480 *seat_id = g_strdup (self->priv->seat_id);
481 }
482
483 return TRUE;
484 }
485
486 gboolean
gdm_display_is_initial(GdmDisplay * self,gboolean * is_initial,GError ** error)487 gdm_display_is_initial (GdmDisplay *self,
488 gboolean *is_initial,
489 GError **error)
490 {
491 g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
492
493 if (is_initial != NULL) {
494 *is_initial = self->priv->is_initial;
495 }
496
497 return TRUE;
498 }
499
500 static gboolean
finish_idle(GdmDisplay * self)501 finish_idle (GdmDisplay *self)
502 {
503 self->priv->finish_idle_id = 0;
504 /* finish may end up finalizing object */
505 gdm_display_finish (self);
506 return FALSE;
507 }
508
509 static void
queue_finish(GdmDisplay * self)510 queue_finish (GdmDisplay *self)
511 {
512 if (self->priv->finish_idle_id == 0) {
513 self->priv->finish_idle_id = g_idle_add ((GSourceFunc)finish_idle, self);
514 }
515 }
516
517 static void
_gdm_display_set_status(GdmDisplay * self,int status)518 _gdm_display_set_status (GdmDisplay *self,
519 int status)
520 {
521 if (status != self->priv->status) {
522 self->priv->status = status;
523 g_object_notify (G_OBJECT (self), "status");
524 }
525 }
526
527 static gboolean
gdm_display_real_prepare(GdmDisplay * self)528 gdm_display_real_prepare (GdmDisplay *self)
529 {
530 g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
531
532 g_debug ("GdmDisplay: prepare display");
533
534 _gdm_display_set_status (self, GDM_DISPLAY_PREPARED);
535
536 return TRUE;
537 }
538
539 static void
look_for_existing_users_sync(GdmDisplay * self)540 look_for_existing_users_sync (GdmDisplay *self)
541 {
542 GError *error = NULL;
543 GVariant *call_result;
544 GVariant *user_list;
545
546 self->priv->accountsservice_proxy = g_dbus_proxy_new_sync (self->priv->connection,
547 0, NULL,
548 "org.freedesktop.Accounts",
549 "/org/freedesktop/Accounts",
550 "org.freedesktop.Accounts",
551 NULL,
552 &error);
553
554 if (!self->priv->accountsservice_proxy) {
555 g_warning ("Failed to contact accountsservice: %s", error->message);
556 goto out;
557 }
558
559 call_result = g_dbus_proxy_call_sync (self->priv->accountsservice_proxy,
560 "ListCachedUsers",
561 NULL,
562 0,
563 -1,
564 NULL,
565 &error);
566
567 if (!call_result) {
568 g_warning ("Failed to list cached users: %s", error->message);
569 goto out;
570 }
571
572 g_variant_get (call_result, "(@ao)", &user_list);
573 self->priv->have_existing_user_accounts = g_variant_n_children (user_list) > 0;
574 g_variant_unref (user_list);
575 g_variant_unref (call_result);
576 out:
577 g_clear_error (&error);
578 }
579
580 gboolean
gdm_display_prepare(GdmDisplay * self)581 gdm_display_prepare (GdmDisplay *self)
582 {
583 gboolean ret;
584
585 g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
586
587 g_debug ("GdmDisplay: Preparing display: %s", self->priv->id);
588
589 /* FIXME: we should probably do this in a more global place,
590 * asynchronously
591 */
592 look_for_existing_users_sync (self);
593
594 self->priv->doing_initial_setup = wants_initial_setup (self);
595
596 g_object_ref (self);
597 ret = GDM_DISPLAY_GET_CLASS (self)->prepare (self);
598 g_object_unref (self);
599
600 return ret;
601 }
602
603 gboolean
gdm_display_manage(GdmDisplay * self)604 gdm_display_manage (GdmDisplay *self)
605 {
606 gboolean res;
607
608 g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
609
610 g_debug ("GdmDisplay: Managing display: %s", self->priv->id);
611
612 /* If not explicitly prepared, do it now */
613 if (self->priv->status == GDM_DISPLAY_UNMANAGED) {
614 res = gdm_display_prepare (self);
615 if (! res) {
616 return FALSE;
617 }
618 }
619
620 g_timer_start (self->priv->server_timer);
621
622 if (g_strcmp0 (self->priv->session_class, "greeter") == 0) {
623 if (GDM_DISPLAY_GET_CLASS (self)->manage != NULL) {
624 GDM_DISPLAY_GET_CLASS (self)->manage (self);
625 }
626 }
627
628 return TRUE;
629 }
630
631 gboolean
gdm_display_finish(GdmDisplay * self)632 gdm_display_finish (GdmDisplay *self)
633 {
634 g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
635
636 if (self->priv->finish_idle_id != 0) {
637 g_source_remove (self->priv->finish_idle_id);
638 self->priv->finish_idle_id = 0;
639 }
640
641 _gdm_display_set_status (self, GDM_DISPLAY_FINISHED);
642
643 g_debug ("GdmDisplay: finish display");
644
645 return TRUE;
646 }
647
648 static void
gdm_display_disconnect(GdmDisplay * self)649 gdm_display_disconnect (GdmDisplay *self)
650 {
651 /* These 3 bits are reserved/unused by the X protocol */
652 guint32 unused_bits = 0b11100000000000000000000000000000;
653 XID highest_client, client;
654 guint32 client_increment;
655 const xcb_setup_t *setup;
656
657 if (self->priv->xcb_connection == NULL) {
658 return;
659 }
660
661 setup = xcb_get_setup (self->priv->xcb_connection);
662
663 /* resource_id_mask is the bits given to each client for
664 * addressing resources */
665 highest_client = (XID) ~unused_bits & ~setup->resource_id_mask;
666 client_increment = setup->resource_id_mask + 1;
667
668 /* Kill every client but ourselves, then close our own connection
669 */
670 for (client = 0;
671 client <= highest_client;
672 client += client_increment) {
673
674 if (client != setup->resource_id_base)
675 xcb_kill_client (self->priv->xcb_connection, client);
676 }
677
678 xcb_flush (self->priv->xcb_connection);
679
680 g_clear_pointer (&self->priv->xcb_connection, xcb_disconnect);
681 }
682
683 gboolean
gdm_display_unmanage(GdmDisplay * self)684 gdm_display_unmanage (GdmDisplay *self)
685 {
686 gdouble elapsed;
687
688 g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
689
690 g_debug ("GdmDisplay: unmanage display");
691
692 gdm_display_disconnect (self);
693
694 g_timer_stop (self->priv->server_timer);
695
696 if (self->priv->user_access_file != NULL) {
697 gdm_display_access_file_close (self->priv->user_access_file);
698 g_object_unref (self->priv->user_access_file);
699 self->priv->user_access_file = NULL;
700 }
701
702 if (self->priv->access_file != NULL) {
703 gdm_display_access_file_close (self->priv->access_file);
704 g_object_unref (self->priv->access_file);
705 self->priv->access_file = NULL;
706 }
707
708 elapsed = g_timer_elapsed (self->priv->server_timer, NULL);
709 if (elapsed < 3) {
710 g_warning ("GdmDisplay: display lasted %lf seconds", elapsed);
711 _gdm_display_set_status (self, GDM_DISPLAY_FAILED);
712 } else {
713 _gdm_display_set_status (self, GDM_DISPLAY_UNMANAGED);
714 }
715
716 return TRUE;
717 }
718
719 gboolean
gdm_display_get_id(GdmDisplay * self,char ** id,GError ** error)720 gdm_display_get_id (GdmDisplay *self,
721 char **id,
722 GError **error)
723 {
724 g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
725
726 if (id != NULL) {
727 *id = g_strdup (self->priv->id);
728 }
729
730 return TRUE;
731 }
732
733 gboolean
gdm_display_get_x11_display_name(GdmDisplay * self,char ** x11_display,GError ** error)734 gdm_display_get_x11_display_name (GdmDisplay *self,
735 char **x11_display,
736 GError **error)
737 {
738 g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
739
740 if (x11_display != NULL) {
741 *x11_display = g_strdup (self->priv->x11_display_name);
742 }
743
744 return TRUE;
745 }
746
747 gboolean
gdm_display_is_local(GdmDisplay * self,gboolean * local,GError ** error)748 gdm_display_is_local (GdmDisplay *self,
749 gboolean *local,
750 GError **error)
751 {
752 g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
753
754 if (local != NULL) {
755 *local = self->priv->is_local;
756 }
757
758 return TRUE;
759 }
760
761 static void
_gdm_display_set_id(GdmDisplay * self,const char * id)762 _gdm_display_set_id (GdmDisplay *self,
763 const char *id)
764 {
765 g_debug ("GdmDisplay: id: %s", id);
766 g_free (self->priv->id);
767 self->priv->id = g_strdup (id);
768 }
769
770 static void
_gdm_display_set_seat_id(GdmDisplay * self,const char * seat_id)771 _gdm_display_set_seat_id (GdmDisplay *self,
772 const char *seat_id)
773 {
774 g_debug ("GdmDisplay: seat id: %s", seat_id);
775 g_free (self->priv->seat_id);
776 self->priv->seat_id = g_strdup (seat_id);
777 }
778
779 static void
_gdm_display_set_session_id(GdmDisplay * self,const char * session_id)780 _gdm_display_set_session_id (GdmDisplay *self,
781 const char *session_id)
782 {
783 g_debug ("GdmDisplay: session id: %s", session_id);
784 g_free (self->priv->session_id);
785 self->priv->session_id = g_strdup (session_id);
786 }
787
788 static void
_gdm_display_set_session_class(GdmDisplay * self,const char * session_class)789 _gdm_display_set_session_class (GdmDisplay *self,
790 const char *session_class)
791 {
792 g_debug ("GdmDisplay: session class: %s", session_class);
793 g_free (self->priv->session_class);
794 self->priv->session_class = g_strdup (session_class);
795 }
796
797 static void
_gdm_display_set_session_type(GdmDisplay * self,const char * session_type)798 _gdm_display_set_session_type (GdmDisplay *self,
799 const char *session_type)
800 {
801 g_debug ("GdmDisplay: session type: %s", session_type);
802 g_free (self->priv->session_type);
803 self->priv->session_type = g_strdup (session_type);
804 }
805
806 static void
_gdm_display_set_remote_hostname(GdmDisplay * self,const char * hostname)807 _gdm_display_set_remote_hostname (GdmDisplay *self,
808 const char *hostname)
809 {
810 g_free (self->priv->remote_hostname);
811 self->priv->remote_hostname = g_strdup (hostname);
812 }
813
814 static void
_gdm_display_set_x11_display_number(GdmDisplay * self,int num)815 _gdm_display_set_x11_display_number (GdmDisplay *self,
816 int num)
817 {
818 self->priv->x11_display_number = num;
819 }
820
821 static void
_gdm_display_set_x11_display_name(GdmDisplay * self,const char * x11_display)822 _gdm_display_set_x11_display_name (GdmDisplay *self,
823 const char *x11_display)
824 {
825 g_free (self->priv->x11_display_name);
826 self->priv->x11_display_name = g_strdup (x11_display);
827 }
828
829 static void
_gdm_display_set_x11_cookie(GdmDisplay * self,const char * x11_cookie)830 _gdm_display_set_x11_cookie (GdmDisplay *self,
831 const char *x11_cookie)
832 {
833 g_free (self->priv->x11_cookie);
834 self->priv->x11_cookie = g_strdup (x11_cookie);
835 }
836
837 static void
_gdm_display_set_is_local(GdmDisplay * self,gboolean is_local)838 _gdm_display_set_is_local (GdmDisplay *self,
839 gboolean is_local)
840 {
841 g_debug ("GdmDisplay: local: %s", is_local? "yes" : "no");
842 self->priv->is_local = is_local;
843 }
844
845 static void
_gdm_display_set_launch_environment(GdmDisplay * self,GdmLaunchEnvironment * launch_environment)846 _gdm_display_set_launch_environment (GdmDisplay *self,
847 GdmLaunchEnvironment *launch_environment)
848 {
849 g_clear_object (&self->priv->launch_environment);
850
851 self->priv->launch_environment = g_object_ref (launch_environment);
852 }
853
854 static void
_gdm_display_set_is_initial(GdmDisplay * self,gboolean initial)855 _gdm_display_set_is_initial (GdmDisplay *self,
856 gboolean initial)
857 {
858 g_debug ("GdmDisplay: initial: %s", initial? "yes" : "no");
859 self->priv->is_initial = initial;
860 }
861
862 static void
_gdm_display_set_allow_timed_login(GdmDisplay * self,gboolean allow_timed_login)863 _gdm_display_set_allow_timed_login (GdmDisplay *self,
864 gboolean allow_timed_login)
865 {
866 g_debug ("GdmDisplay: allow timed login: %s", allow_timed_login? "yes" : "no");
867 self->priv->allow_timed_login = allow_timed_login;
868 }
869
870 static void
gdm_display_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)871 gdm_display_set_property (GObject *object,
872 guint prop_id,
873 const GValue *value,
874 GParamSpec *pspec)
875 {
876 GdmDisplay *self;
877
878 self = GDM_DISPLAY (object);
879
880 switch (prop_id) {
881 case PROP_ID:
882 _gdm_display_set_id (self, g_value_get_string (value));
883 break;
884 case PROP_STATUS:
885 _gdm_display_set_status (self, g_value_get_int (value));
886 break;
887 case PROP_SEAT_ID:
888 _gdm_display_set_seat_id (self, g_value_get_string (value));
889 break;
890 case PROP_SESSION_ID:
891 _gdm_display_set_session_id (self, g_value_get_string (value));
892 break;
893 case PROP_SESSION_CLASS:
894 _gdm_display_set_session_class (self, g_value_get_string (value));
895 break;
896 case PROP_SESSION_TYPE:
897 _gdm_display_set_session_type (self, g_value_get_string (value));
898 break;
899 case PROP_REMOTE_HOSTNAME:
900 _gdm_display_set_remote_hostname (self, g_value_get_string (value));
901 break;
902 case PROP_X11_DISPLAY_NUMBER:
903 _gdm_display_set_x11_display_number (self, g_value_get_int (value));
904 break;
905 case PROP_X11_DISPLAY_NAME:
906 _gdm_display_set_x11_display_name (self, g_value_get_string (value));
907 break;
908 case PROP_X11_COOKIE:
909 _gdm_display_set_x11_cookie (self, g_value_get_string (value));
910 break;
911 case PROP_IS_LOCAL:
912 _gdm_display_set_is_local (self, g_value_get_boolean (value));
913 break;
914 case PROP_ALLOW_TIMED_LOGIN:
915 _gdm_display_set_allow_timed_login (self, g_value_get_boolean (value));
916 break;
917 case PROP_LAUNCH_ENVIRONMENT:
918 _gdm_display_set_launch_environment (self, g_value_get_object (value));
919 break;
920 case PROP_IS_INITIAL:
921 _gdm_display_set_is_initial (self, g_value_get_boolean (value));
922 break;
923 default:
924 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
925 break;
926 }
927 }
928
929 static void
gdm_display_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)930 gdm_display_get_property (GObject *object,
931 guint prop_id,
932 GValue *value,
933 GParamSpec *pspec)
934 {
935 GdmDisplay *self;
936
937 self = GDM_DISPLAY (object);
938
939 switch (prop_id) {
940 case PROP_ID:
941 g_value_set_string (value, self->priv->id);
942 break;
943 case PROP_STATUS:
944 g_value_set_int (value, self->priv->status);
945 break;
946 case PROP_SEAT_ID:
947 g_value_set_string (value, self->priv->seat_id);
948 break;
949 case PROP_SESSION_ID:
950 g_value_set_string (value, self->priv->session_id);
951 break;
952 case PROP_SESSION_CLASS:
953 g_value_set_string (value, self->priv->session_class);
954 break;
955 case PROP_SESSION_TYPE:
956 g_value_set_string (value, self->priv->session_type);
957 break;
958 case PROP_REMOTE_HOSTNAME:
959 g_value_set_string (value, self->priv->remote_hostname);
960 break;
961 case PROP_X11_DISPLAY_NUMBER:
962 g_value_set_int (value, self->priv->x11_display_number);
963 break;
964 case PROP_X11_DISPLAY_NAME:
965 g_value_set_string (value, self->priv->x11_display_name);
966 break;
967 case PROP_X11_COOKIE:
968 g_value_set_string (value, self->priv->x11_cookie);
969 break;
970 case PROP_X11_AUTHORITY_FILE:
971 g_value_take_string (value,
972 self->priv->access_file?
973 gdm_display_access_file_get_path (self->priv->access_file) : NULL);
974 break;
975 case PROP_IS_LOCAL:
976 g_value_set_boolean (value, self->priv->is_local);
977 break;
978 case PROP_IS_CONNECTED:
979 g_value_set_boolean (value, self->priv->xcb_connection != NULL);
980 break;
981 case PROP_LAUNCH_ENVIRONMENT:
982 g_value_set_object (value, self->priv->launch_environment);
983 break;
984 case PROP_IS_INITIAL:
985 g_value_set_boolean (value, self->priv->is_initial);
986 break;
987 case PROP_HAVE_EXISTING_USER_ACCOUNTS:
988 g_value_set_boolean (value, self->priv->have_existing_user_accounts);
989 break;
990 case PROP_DOING_INITIAL_SETUP:
991 g_value_set_boolean (value, self->priv->doing_initial_setup);
992 break;
993 case PROP_ALLOW_TIMED_LOGIN:
994 g_value_set_boolean (value, self->priv->allow_timed_login);
995 break;
996 default:
997 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
998 break;
999 }
1000 }
1001
1002 static gboolean
handle_get_id(GdmDBusDisplay * skeleton,GDBusMethodInvocation * invocation,GdmDisplay * self)1003 handle_get_id (GdmDBusDisplay *skeleton,
1004 GDBusMethodInvocation *invocation,
1005 GdmDisplay *self)
1006 {
1007 char *id;
1008
1009 gdm_display_get_id (self, &id, NULL);
1010
1011 gdm_dbus_display_complete_get_id (skeleton, invocation, id);
1012
1013 g_free (id);
1014 return TRUE;
1015 }
1016
1017 static gboolean
handle_get_remote_hostname(GdmDBusDisplay * skeleton,GDBusMethodInvocation * invocation,GdmDisplay * self)1018 handle_get_remote_hostname (GdmDBusDisplay *skeleton,
1019 GDBusMethodInvocation *invocation,
1020 GdmDisplay *self)
1021 {
1022 char *hostname;
1023
1024 gdm_display_get_remote_hostname (self, &hostname, NULL);
1025
1026 gdm_dbus_display_complete_get_remote_hostname (skeleton,
1027 invocation,
1028 hostname ? hostname : "");
1029
1030 g_free (hostname);
1031 return TRUE;
1032 }
1033
1034 static gboolean
handle_get_seat_id(GdmDBusDisplay * skeleton,GDBusMethodInvocation * invocation,GdmDisplay * self)1035 handle_get_seat_id (GdmDBusDisplay *skeleton,
1036 GDBusMethodInvocation *invocation,
1037 GdmDisplay *self)
1038 {
1039 char *seat_id;
1040
1041 seat_id = NULL;
1042 gdm_display_get_seat_id (self, &seat_id, NULL);
1043
1044 if (seat_id == NULL) {
1045 seat_id = g_strdup ("");
1046 }
1047 gdm_dbus_display_complete_get_seat_id (skeleton, invocation, seat_id);
1048
1049 g_free (seat_id);
1050 return TRUE;
1051 }
1052
1053 static gboolean
handle_get_x11_display_name(GdmDBusDisplay * skeleton,GDBusMethodInvocation * invocation,GdmDisplay * self)1054 handle_get_x11_display_name (GdmDBusDisplay *skeleton,
1055 GDBusMethodInvocation *invocation,
1056 GdmDisplay *self)
1057 {
1058 char *name;
1059
1060 gdm_display_get_x11_display_name (self, &name, NULL);
1061
1062 gdm_dbus_display_complete_get_x11_display_name (skeleton, invocation, name);
1063
1064 g_free (name);
1065 return TRUE;
1066 }
1067
1068 static gboolean
handle_is_local(GdmDBusDisplay * skeleton,GDBusMethodInvocation * invocation,GdmDisplay * self)1069 handle_is_local (GdmDBusDisplay *skeleton,
1070 GDBusMethodInvocation *invocation,
1071 GdmDisplay *self)
1072 {
1073 gboolean is_local;
1074
1075 gdm_display_is_local (self, &is_local, NULL);
1076
1077 gdm_dbus_display_complete_is_local (skeleton, invocation, is_local);
1078
1079 return TRUE;
1080 }
1081
1082 static gboolean
handle_is_initial(GdmDBusDisplay * skeleton,GDBusMethodInvocation * invocation,GdmDisplay * self)1083 handle_is_initial (GdmDBusDisplay *skeleton,
1084 GDBusMethodInvocation *invocation,
1085 GdmDisplay *self)
1086 {
1087 gboolean is_initial = FALSE;
1088
1089 gdm_display_is_initial (self, &is_initial, NULL);
1090
1091 gdm_dbus_display_complete_is_initial (skeleton, invocation, is_initial);
1092
1093 return TRUE;
1094 }
1095
1096 static gboolean
register_display(GdmDisplay * self)1097 register_display (GdmDisplay *self)
1098 {
1099 GError *error = NULL;
1100
1101 error = NULL;
1102 self->priv->connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
1103 if (self->priv->connection == NULL) {
1104 g_critical ("error getting system bus: %s", error->message);
1105 g_error_free (error);
1106 exit (EXIT_FAILURE);
1107 }
1108
1109 self->priv->object_skeleton = g_dbus_object_skeleton_new (self->priv->id);
1110 self->priv->display_skeleton = GDM_DBUS_DISPLAY (gdm_dbus_display_skeleton_new ());
1111
1112 g_signal_connect_object (self->priv->display_skeleton, "handle-get-id",
1113 G_CALLBACK (handle_get_id), self, 0);
1114 g_signal_connect_object (self->priv->display_skeleton, "handle-get-remote-hostname",
1115 G_CALLBACK (handle_get_remote_hostname), self, 0);
1116 g_signal_connect_object (self->priv->display_skeleton, "handle-get-seat-id",
1117 G_CALLBACK (handle_get_seat_id), self, 0);
1118 g_signal_connect_object (self->priv->display_skeleton, "handle-get-x11-display-name",
1119 G_CALLBACK (handle_get_x11_display_name), self, 0);
1120 g_signal_connect_object (self->priv->display_skeleton, "handle-is-local",
1121 G_CALLBACK (handle_is_local), self, 0);
1122 g_signal_connect_object (self->priv->display_skeleton, "handle-is-initial",
1123 G_CALLBACK (handle_is_initial), self, 0);
1124
1125 g_dbus_object_skeleton_add_interface (self->priv->object_skeleton,
1126 G_DBUS_INTERFACE_SKELETON (self->priv->display_skeleton));
1127
1128 return TRUE;
1129 }
1130
1131 /*
1132 dbus-send --system --print-reply --dest=org.gnome.DisplayManager /org/gnome/DisplayManager/Displays/1 org.freedesktop.DBus.Introspectable.Introspect
1133 */
1134
1135 static GObject *
gdm_display_constructor(GType type,guint n_construct_properties,GObjectConstructParam * construct_properties)1136 gdm_display_constructor (GType type,
1137 guint n_construct_properties,
1138 GObjectConstructParam *construct_properties)
1139 {
1140 GdmDisplay *self;
1141 gboolean res;
1142
1143 self = GDM_DISPLAY (G_OBJECT_CLASS (gdm_display_parent_class)->constructor (type,
1144 n_construct_properties,
1145 construct_properties));
1146
1147 g_free (self->priv->id);
1148 self->priv->id = g_strdup_printf ("/org/gnome/DisplayManager/Displays/%lu",
1149 (gulong) self);
1150
1151 res = register_display (self);
1152 if (! res) {
1153 g_warning ("Unable to register display with system bus");
1154 }
1155
1156 return G_OBJECT (self);
1157 }
1158
1159 static void
gdm_display_dispose(GObject * object)1160 gdm_display_dispose (GObject *object)
1161 {
1162 GdmDisplay *self;
1163
1164 self = GDM_DISPLAY (object);
1165
1166 g_debug ("GdmDisplay: Disposing display");
1167
1168 if (self->priv->finish_idle_id != 0) {
1169 g_source_remove (self->priv->finish_idle_id);
1170 self->priv->finish_idle_id = 0;
1171 }
1172 g_clear_object (&self->priv->launch_environment);
1173
1174 g_warn_if_fail (self->priv->status != GDM_DISPLAY_MANAGED);
1175 g_warn_if_fail (self->priv->user_access_file == NULL);
1176 g_warn_if_fail (self->priv->access_file == NULL);
1177
1178 G_OBJECT_CLASS (gdm_display_parent_class)->dispose (object);
1179 }
1180
1181 static void
gdm_display_class_init(GdmDisplayClass * klass)1182 gdm_display_class_init (GdmDisplayClass *klass)
1183 {
1184 GObjectClass *object_class = G_OBJECT_CLASS (klass);
1185
1186 object_class->get_property = gdm_display_get_property;
1187 object_class->set_property = gdm_display_set_property;
1188 object_class->constructor = gdm_display_constructor;
1189 object_class->dispose = gdm_display_dispose;
1190 object_class->finalize = gdm_display_finalize;
1191
1192 klass->prepare = gdm_display_real_prepare;
1193
1194 g_object_class_install_property (object_class,
1195 PROP_ID,
1196 g_param_spec_string ("id",
1197 "id",
1198 "id",
1199 NULL,
1200 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
1201 g_object_class_install_property (object_class,
1202 PROP_REMOTE_HOSTNAME,
1203 g_param_spec_string ("remote-hostname",
1204 "remote-hostname",
1205 "remote-hostname",
1206 NULL,
1207 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
1208 g_object_class_install_property (object_class,
1209 PROP_X11_DISPLAY_NUMBER,
1210 g_param_spec_int ("x11-display-number",
1211 "x11 display number",
1212 "x11 display number",
1213 -1,
1214 G_MAXINT,
1215 -1,
1216 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
1217 g_object_class_install_property (object_class,
1218 PROP_X11_DISPLAY_NAME,
1219 g_param_spec_string ("x11-display-name",
1220 "x11-display-name",
1221 "x11-display-name",
1222 NULL,
1223 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
1224 g_object_class_install_property (object_class,
1225 PROP_SEAT_ID,
1226 g_param_spec_string ("seat-id",
1227 "seat id",
1228 "seat id",
1229 NULL,
1230 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
1231 g_object_class_install_property (object_class,
1232 PROP_SESSION_ID,
1233 g_param_spec_string ("session-id",
1234 "session id",
1235 "session id",
1236 NULL,
1237 G_PARAM_READWRITE));
1238 g_object_class_install_property (object_class,
1239 PROP_SESSION_CLASS,
1240 g_param_spec_string ("session-class",
1241 NULL,
1242 NULL,
1243 "greeter",
1244 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
1245 g_object_class_install_property (object_class,
1246 PROP_SESSION_TYPE,
1247 g_param_spec_string ("session-type",
1248 NULL,
1249 NULL,
1250 NULL,
1251 G_PARAM_READWRITE));
1252 g_object_class_install_property (object_class,
1253 PROP_IS_INITIAL,
1254 g_param_spec_boolean ("is-initial",
1255 NULL,
1256 NULL,
1257 FALSE,
1258 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
1259 g_object_class_install_property (object_class,
1260 PROP_ALLOW_TIMED_LOGIN,
1261 g_param_spec_boolean ("allow-timed-login",
1262 NULL,
1263 NULL,
1264 TRUE,
1265 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
1266 g_object_class_install_property (object_class,
1267 PROP_X11_COOKIE,
1268 g_param_spec_string ("x11-cookie",
1269 "cookie",
1270 "cookie",
1271 NULL,
1272 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
1273 g_object_class_install_property (object_class,
1274 PROP_X11_AUTHORITY_FILE,
1275 g_param_spec_string ("x11-authority-file",
1276 "authority file",
1277 "authority file",
1278 NULL,
1279 G_PARAM_READABLE));
1280
1281 g_object_class_install_property (object_class,
1282 PROP_IS_LOCAL,
1283 g_param_spec_boolean ("is-local",
1284 NULL,
1285 NULL,
1286 TRUE,
1287 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
1288 g_object_class_install_property (object_class,
1289 PROP_IS_CONNECTED,
1290 g_param_spec_boolean ("is-connected",
1291 NULL,
1292 NULL,
1293 TRUE,
1294 G_PARAM_READABLE));
1295 g_object_class_install_property (object_class,
1296 PROP_HAVE_EXISTING_USER_ACCOUNTS,
1297 g_param_spec_boolean ("have-existing-user-accounts",
1298 NULL,
1299 NULL,
1300 FALSE,
1301 G_PARAM_READABLE));
1302 g_object_class_install_property (object_class,
1303 PROP_DOING_INITIAL_SETUP,
1304 g_param_spec_boolean ("doing-initial-setup",
1305 NULL,
1306 NULL,
1307 FALSE,
1308 G_PARAM_READABLE));
1309 g_object_class_install_property (object_class,
1310 PROP_LAUNCH_ENVIRONMENT,
1311 g_param_spec_object ("launch-environment",
1312 NULL,
1313 NULL,
1314 GDM_TYPE_LAUNCH_ENVIRONMENT,
1315 G_PARAM_READWRITE));
1316 g_object_class_install_property (object_class,
1317 PROP_STATUS,
1318 g_param_spec_int ("status",
1319 "status",
1320 "status",
1321 -1,
1322 G_MAXINT,
1323 GDM_DISPLAY_UNMANAGED,
1324 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
1325
1326 g_type_class_add_private (klass, sizeof (GdmDisplayPrivate));
1327 }
1328
1329 static void
gdm_display_init(GdmDisplay * self)1330 gdm_display_init (GdmDisplay *self)
1331 {
1332
1333 self->priv = GDM_DISPLAY_GET_PRIVATE (self);
1334
1335 self->priv->creation_time = time (NULL);
1336 self->priv->server_timer = g_timer_new ();
1337 }
1338
1339 static void
gdm_display_finalize(GObject * object)1340 gdm_display_finalize (GObject *object)
1341 {
1342 GdmDisplay *self;
1343
1344 g_return_if_fail (object != NULL);
1345 g_return_if_fail (GDM_IS_DISPLAY (object));
1346
1347 self = GDM_DISPLAY (object);
1348
1349 g_return_if_fail (self->priv != NULL);
1350
1351 g_debug ("GdmDisplay: Finalizing display: %s", self->priv->id);
1352 g_free (self->priv->id);
1353 g_free (self->priv->seat_id);
1354 g_free (self->priv->session_class);
1355 g_free (self->priv->remote_hostname);
1356 g_free (self->priv->x11_display_name);
1357 g_free (self->priv->x11_cookie);
1358
1359 g_clear_object (&self->priv->display_skeleton);
1360 g_clear_object (&self->priv->object_skeleton);
1361 g_clear_object (&self->priv->connection);
1362 g_clear_object (&self->priv->accountsservice_proxy);
1363
1364 if (self->priv->access_file != NULL) {
1365 g_object_unref (self->priv->access_file);
1366 }
1367
1368 if (self->priv->user_access_file != NULL) {
1369 g_object_unref (self->priv->user_access_file);
1370 }
1371
1372 if (self->priv->server_timer != NULL) {
1373 g_timer_destroy (self->priv->server_timer);
1374 }
1375
1376 G_OBJECT_CLASS (gdm_display_parent_class)->finalize (object);
1377 }
1378
1379 GDBusObjectSkeleton *
gdm_display_get_object_skeleton(GdmDisplay * self)1380 gdm_display_get_object_skeleton (GdmDisplay *self)
1381 {
1382 return self->priv->object_skeleton;
1383 }
1384
1385 static void
on_launch_environment_session_opened(GdmLaunchEnvironment * launch_environment,GdmDisplay * self)1386 on_launch_environment_session_opened (GdmLaunchEnvironment *launch_environment,
1387 GdmDisplay *self)
1388 {
1389 char *session_id;
1390
1391 g_debug ("GdmDisplay: Greeter session opened");
1392 session_id = gdm_launch_environment_get_session_id (launch_environment);
1393 _gdm_display_set_session_id (self, session_id);
1394 g_free (session_id);
1395 }
1396
1397 static void
on_launch_environment_session_started(GdmLaunchEnvironment * launch_environment,GdmDisplay * self)1398 on_launch_environment_session_started (GdmLaunchEnvironment *launch_environment,
1399 GdmDisplay *self)
1400 {
1401 g_debug ("GdmDisplay: Greeter started");
1402 }
1403
1404 static void
self_destruct(GdmDisplay * self)1405 self_destruct (GdmDisplay *self)
1406 {
1407 g_object_ref (self);
1408 if (gdm_display_get_status (self) == GDM_DISPLAY_MANAGED) {
1409 gdm_display_unmanage (self);
1410 }
1411
1412 if (gdm_display_get_status (self) != GDM_DISPLAY_FINISHED) {
1413 queue_finish (self);
1414 }
1415 g_object_unref (self);
1416 }
1417
1418 static void
on_launch_environment_session_stopped(GdmLaunchEnvironment * launch_environment,GdmDisplay * self)1419 on_launch_environment_session_stopped (GdmLaunchEnvironment *launch_environment,
1420 GdmDisplay *self)
1421 {
1422 g_debug ("GdmDisplay: Greeter stopped");
1423 self_destruct (self);
1424 }
1425
1426 static void
on_launch_environment_session_exited(GdmLaunchEnvironment * launch_environment,int code,GdmDisplay * self)1427 on_launch_environment_session_exited (GdmLaunchEnvironment *launch_environment,
1428 int code,
1429 GdmDisplay *self)
1430 {
1431 g_debug ("GdmDisplay: Greeter exited: %d", code);
1432 self_destruct (self);
1433 }
1434
1435 static void
on_launch_environment_session_died(GdmLaunchEnvironment * launch_environment,int signal,GdmDisplay * self)1436 on_launch_environment_session_died (GdmLaunchEnvironment *launch_environment,
1437 int signal,
1438 GdmDisplay *self)
1439 {
1440 g_debug ("GdmDisplay: Greeter died: %d", signal);
1441 self_destruct (self);
1442 }
1443
1444 static gboolean
can_create_environment(const char * session_id)1445 can_create_environment (const char *session_id)
1446 {
1447 char *path;
1448 gboolean session_exists;
1449
1450 path = g_strdup_printf (GNOME_SESSION_SESSIONS_PATH "/%s.session", session_id);
1451 session_exists = g_file_test (path, G_FILE_TEST_EXISTS);
1452
1453 g_free (path);
1454
1455 return session_exists;
1456 }
1457
1458 #define ALREADY_RAN_INITIAL_SETUP_ON_THIS_BOOT GDM_RUN_DIR "/gdm.ran-initial-setup"
1459
1460 static gboolean
already_done_initial_setup_on_this_boot(void)1461 already_done_initial_setup_on_this_boot (void)
1462 {
1463 if (g_file_test (ALREADY_RAN_INITIAL_SETUP_ON_THIS_BOOT, G_FILE_TEST_EXISTS))
1464 return TRUE;
1465
1466 return FALSE;
1467 }
1468
1469 static gboolean
kernel_cmdline_initial_setup_argument(const gchar * contents,gchar ** initial_setup_argument,GError ** error)1470 kernel_cmdline_initial_setup_argument (const gchar *contents,
1471 gchar **initial_setup_argument,
1472 GError **error)
1473 {
1474 GRegex *regex = NULL;
1475 GMatchInfo *match_info = NULL;
1476 gchar *match_group = NULL;
1477
1478 g_return_val_if_fail (initial_setup_argument != NULL, FALSE);
1479
1480 regex = g_regex_new ("\\bgnome.initial-setup=([^\\s]*)\\b", 0, 0, error);
1481
1482 if (!regex)
1483 return FALSE;
1484
1485 if (!g_regex_match (regex, contents, 0, &match_info)) {
1486 g_free (match_info);
1487 g_free (regex);
1488
1489 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
1490 "Could not match gnome.initial-setup= in kernel cmdline");
1491
1492 return FALSE;
1493 }
1494
1495 match_group = g_match_info_fetch (match_info, 1);
1496
1497 if (!match_group) {
1498 g_free (match_info);
1499 g_free (regex);
1500
1501 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
1502 "Could not match gnome.initial-setup= in kernel cmdline");
1503
1504 return FALSE;
1505 }
1506
1507 *initial_setup_argument = match_group;
1508
1509 g_free (match_info);
1510 g_free (regex);
1511
1512 return TRUE;
1513 }
1514
1515 /* Function returns true if we had a force state in the kernel
1516 * cmdline */
1517 static gboolean
kernel_cmdline_initial_setup_force_state(gboolean * force_state)1518 kernel_cmdline_initial_setup_force_state (gboolean *force_state)
1519 {
1520 GError *error = NULL;
1521 gchar *contents = NULL;
1522 gchar *setup_argument = NULL;
1523
1524 g_return_val_if_fail (force_state != NULL, FALSE);
1525
1526 if (!g_file_get_contents ("/proc/cmdline", &contents, NULL, &error)) {
1527 g_debug ("GdmDisplay: Could not check kernel parameters, not forcing initial setup: %s",
1528 error->message);
1529 g_clear_error (&error);
1530 return FALSE;
1531 }
1532
1533 g_debug ("GdmDisplay: Checking kernel command buffer %s", contents);
1534
1535 if (!kernel_cmdline_initial_setup_argument (contents, &setup_argument, &error)) {
1536 g_debug ("GdmDisplay: Failed to read kernel commandline: %s", error->message);
1537 g_clear_pointer (&contents, g_free);
1538 return FALSE;
1539 }
1540
1541 g_clear_pointer (&contents, g_free);
1542
1543 /* Poor-man's check for truthy or falsey values */
1544 *force_state = setup_argument[0] == '1';
1545
1546 g_free (setup_argument);
1547 return TRUE;
1548 }
1549
1550 static gboolean
wants_initial_setup(GdmDisplay * self)1551 wants_initial_setup (GdmDisplay *self)
1552 {
1553 gboolean enabled = FALSE;
1554 gboolean forced = FALSE;
1555
1556 if (already_done_initial_setup_on_this_boot ()) {
1557 return FALSE;
1558 }
1559
1560 if (kernel_cmdline_initial_setup_force_state (&forced)) {
1561 if (forced) {
1562 g_debug ("GdmDisplay: Forcing gnome-initial-setup");
1563 return TRUE;
1564 }
1565
1566 g_debug ("GdmDisplay: Forceing no gnome-initial-setup");
1567 return FALSE;
1568 }
1569
1570 /* don't run initial-setup on remote displays
1571 */
1572 if (!self->priv->is_local) {
1573 return FALSE;
1574 }
1575
1576 /* don't run if the system has existing users */
1577 if (self->priv->have_existing_user_accounts) {
1578 return FALSE;
1579 }
1580
1581 /* don't run if initial-setup is unavailable */
1582 if (!can_create_environment ("gnome-initial-setup")) {
1583 return FALSE;
1584 }
1585
1586 if (!gdm_settings_direct_get_boolean (GDM_KEY_INITIAL_SETUP_ENABLE, &enabled)) {
1587 return FALSE;
1588 }
1589
1590 return enabled;
1591 }
1592
1593 void
gdm_display_start_greeter_session(GdmDisplay * self)1594 gdm_display_start_greeter_session (GdmDisplay *self)
1595 {
1596 GdmSession *session;
1597 char *display_name;
1598 char *seat_id;
1599 char *hostname;
1600 char *auth_file = NULL;
1601
1602 g_return_if_fail (g_strcmp0 (self->priv->session_class, "greeter") == 0);
1603
1604 g_debug ("GdmDisplay: Running greeter");
1605
1606 display_name = NULL;
1607 seat_id = NULL;
1608 hostname = NULL;
1609
1610 g_object_get (self,
1611 "x11-display-name", &display_name,
1612 "seat-id", &seat_id,
1613 "remote-hostname", &hostname,
1614 NULL);
1615 if (self->priv->access_file != NULL) {
1616 auth_file = gdm_display_access_file_get_path (self->priv->access_file);
1617 }
1618
1619 g_debug ("GdmDisplay: Creating greeter for %s %s", display_name, hostname);
1620
1621 g_signal_connect_object (self->priv->launch_environment,
1622 "opened",
1623 G_CALLBACK (on_launch_environment_session_opened),
1624 self, 0);
1625 g_signal_connect_object (self->priv->launch_environment,
1626 "started",
1627 G_CALLBACK (on_launch_environment_session_started),
1628 self, 0);
1629 g_signal_connect_object (self->priv->launch_environment,
1630 "stopped",
1631 G_CALLBACK (on_launch_environment_session_stopped),
1632 self, 0);
1633 g_signal_connect_object (self->priv->launch_environment,
1634 "exited",
1635 G_CALLBACK (on_launch_environment_session_exited),
1636 self, 0);
1637 g_signal_connect_object (self->priv->launch_environment,
1638 "died",
1639 G_CALLBACK (on_launch_environment_session_died),
1640 self, 0);
1641
1642 if (auth_file != NULL) {
1643 g_object_set (self->priv->launch_environment,
1644 "x11-authority-file", auth_file,
1645 NULL);
1646 }
1647
1648 gdm_launch_environment_start (self->priv->launch_environment);
1649
1650 session = gdm_launch_environment_get_session (self->priv->launch_environment);
1651 g_object_set (G_OBJECT (session),
1652 "display-is-initial", self->priv->is_initial,
1653 NULL);
1654
1655 g_free (display_name);
1656 g_free (seat_id);
1657 g_free (hostname);
1658 g_free (auth_file);
1659 }
1660
1661 static void
chown_initial_setup_home_dir(void)1662 chown_initial_setup_home_dir (void)
1663 {
1664 GFile *dir;
1665 GError *error;
1666 char *gis_dir_path;
1667 char *gis_uid_path;
1668 char *gis_uid_contents;
1669 struct passwd *pwe;
1670 uid_t uid;
1671
1672 if (!gdm_get_pwent_for_name (INITIAL_SETUP_USERNAME, &pwe)) {
1673 g_warning ("Unknown user %s", INITIAL_SETUP_USERNAME);
1674 return;
1675 }
1676
1677 gis_dir_path = g_strdup (pwe->pw_dir);
1678
1679 gis_uid_path = g_build_filename (gis_dir_path,
1680 "gnome-initial-setup-uid",
1681 NULL);
1682 if (!g_file_get_contents (gis_uid_path, &gis_uid_contents, NULL, NULL)) {
1683 g_warning ("Unable to read %s", gis_uid_path);
1684 goto out;
1685 }
1686
1687 uid = (uid_t) atoi (gis_uid_contents);
1688 pwe = getpwuid (uid);
1689 if (uid == 0 || pwe == NULL) {
1690 g_warning ("UID '%s' in %s is not valid", gis_uid_contents, gis_uid_path);
1691 goto out;
1692 }
1693
1694 error = NULL;
1695 dir = g_file_new_for_path (gis_dir_path);
1696 if (!chown_recursively (dir, pwe->pw_uid, pwe->pw_gid, &error)) {
1697 g_warning ("Failed to change ownership for %s: %s", gis_dir_path, error->message);
1698 g_error_free (error);
1699 }
1700 g_object_unref (dir);
1701 out:
1702 g_free (gis_uid_contents);
1703 g_free (gis_uid_path);
1704 g_free (gis_dir_path);
1705 }
1706
1707 void
gdm_display_stop_greeter_session(GdmDisplay * self)1708 gdm_display_stop_greeter_session (GdmDisplay *self)
1709 {
1710 GError *error = NULL;
1711
1712 if (self->priv->launch_environment != NULL) {
1713
1714 g_signal_handlers_disconnect_by_func (self->priv->launch_environment,
1715 G_CALLBACK (on_launch_environment_session_opened),
1716 self);
1717 g_signal_handlers_disconnect_by_func (self->priv->launch_environment,
1718 G_CALLBACK (on_launch_environment_session_started),
1719 self);
1720 g_signal_handlers_disconnect_by_func (self->priv->launch_environment,
1721 G_CALLBACK (on_launch_environment_session_stopped),
1722 self);
1723 g_signal_handlers_disconnect_by_func (self->priv->launch_environment,
1724 G_CALLBACK (on_launch_environment_session_exited),
1725 self);
1726 g_signal_handlers_disconnect_by_func (self->priv->launch_environment,
1727 G_CALLBACK (on_launch_environment_session_died),
1728 self);
1729 gdm_launch_environment_stop (self->priv->launch_environment);
1730 g_clear_object (&self->priv->launch_environment);
1731 }
1732
1733 if (self->priv->doing_initial_setup) {
1734 chown_initial_setup_home_dir ();
1735
1736 if (!g_file_set_contents (ALREADY_RAN_INITIAL_SETUP_ON_THIS_BOOT,
1737 "1",
1738 1,
1739 &error)) {
1740 g_warning ("GdmDisplay: Could not write initial-setup-done marker to %s: %s",
1741 ALREADY_RAN_INITIAL_SETUP_ON_THIS_BOOT,
1742 error->message);
1743 g_clear_error (&error);
1744 }
1745 }
1746 }
1747
1748 static xcb_window_t
get_root_window(xcb_connection_t * connection,int screen_number)1749 get_root_window (xcb_connection_t *connection,
1750 int screen_number)
1751 {
1752 xcb_screen_t *screen = NULL;
1753 xcb_screen_iterator_t iter;
1754
1755 iter = xcb_setup_roots_iterator (xcb_get_setup (connection));
1756 while (iter.rem) {
1757 if (screen_number == 0)
1758 screen = iter.data;
1759 screen_number--;
1760 xcb_screen_next (&iter);
1761 }
1762
1763 if (screen != NULL) {
1764 return screen->root;
1765 }
1766
1767 return XCB_WINDOW_NONE;
1768 }
1769
1770 static void
gdm_display_set_windowpath(GdmDisplay * self)1771 gdm_display_set_windowpath (GdmDisplay *self)
1772 {
1773 /* setting WINDOWPATH for clients */
1774 xcb_intern_atom_cookie_t atom_cookie;
1775 xcb_intern_atom_reply_t *atom_reply = NULL;
1776 xcb_get_property_cookie_t get_property_cookie;
1777 xcb_get_property_reply_t *get_property_reply = NULL;
1778 xcb_window_t root_window = XCB_WINDOW_NONE;
1779 const char *windowpath;
1780 char *newwindowpath;
1781 uint32_t num;
1782 char nums[10];
1783 int numn;
1784
1785 atom_cookie = xcb_intern_atom (self->priv->xcb_connection, 0, strlen("XFree86_VT"), "XFree86_VT");
1786 atom_reply = xcb_intern_atom_reply (self->priv->xcb_connection, atom_cookie, NULL);
1787
1788 if (atom_reply == NULL) {
1789 g_debug ("no XFree86_VT atom\n");
1790 goto out;
1791 }
1792
1793 root_window = get_root_window (self->priv->xcb_connection,
1794 self->priv->xcb_screen_number);
1795
1796 if (root_window == XCB_WINDOW_NONE) {
1797 g_debug ("couldn't find root window\n");
1798 goto out;
1799 }
1800
1801 get_property_cookie = xcb_get_property (self->priv->xcb_connection,
1802 FALSE,
1803 root_window,
1804 atom_reply->atom,
1805 XCB_ATOM_INTEGER,
1806 0,
1807 1);
1808
1809 get_property_reply = xcb_get_property_reply (self->priv->xcb_connection, get_property_cookie, NULL);
1810
1811 if (get_property_reply == NULL) {
1812 g_debug ("no XFree86_VT property\n");
1813 goto out;
1814 }
1815
1816 num = ((uint32_t *) xcb_get_property_value (get_property_reply))[0];
1817
1818 windowpath = getenv ("WINDOWPATH");
1819 numn = snprintf (nums, sizeof (nums), "%u", num);
1820 if (!windowpath) {
1821 newwindowpath = malloc (numn + 1);
1822 sprintf (newwindowpath, "%s", nums);
1823 } else {
1824 newwindowpath = malloc (strlen (windowpath) + 1 + numn + 1);
1825 sprintf (newwindowpath, "%s:%s", windowpath, nums);
1826 }
1827
1828 g_setenv ("WINDOWPATH", newwindowpath, TRUE);
1829 out:
1830 g_clear_pointer (&atom_reply, free);
1831 g_clear_pointer (&get_property_reply, free);
1832 }
1833
1834 gboolean
gdm_display_connect(GdmDisplay * self)1835 gdm_display_connect (GdmDisplay *self)
1836 {
1837 xcb_auth_info_t *auth_info = NULL;
1838 gboolean ret;
1839
1840 ret = FALSE;
1841
1842 g_debug ("GdmDisplay: Server is ready - opening display %s", self->priv->x11_display_name);
1843
1844 /* Get access to the display independent of current hostname */
1845 if (self->priv->x11_cookie != NULL) {
1846 auth_info = g_alloca (sizeof (xcb_auth_info_t));
1847
1848 auth_info->namelen = strlen ("MIT-MAGIC-COOKIE-1");
1849 auth_info->name = "MIT-MAGIC-COOKIE-1";
1850 auth_info->datalen = self->priv->x11_cookie_size;
1851 auth_info->data = self->priv->x11_cookie;
1852
1853 }
1854
1855 self->priv->xcb_connection = xcb_connect_to_display_with_auth_info (self->priv->x11_display_name,
1856 auth_info,
1857 &self->priv->xcb_screen_number);
1858
1859 if (xcb_connection_has_error (self->priv->xcb_connection)) {
1860 g_clear_pointer (&self->priv->xcb_connection, xcb_disconnect);
1861 g_warning ("Unable to connect to display %s", self->priv->x11_display_name);
1862 ret = FALSE;
1863 } else if (self->priv->is_local) {
1864 XHostAddress host_entries[3];
1865 xcb_void_cookie_t cookies[3];
1866 int i;
1867
1868 g_debug ("GdmDisplay: Connected to display %s", self->priv->x11_display_name);
1869 ret = TRUE;
1870
1871 /* Give programs access to the display independent of current hostname
1872 */
1873 setup_xhost_auth (host_entries);
1874
1875 for (i = 0; i < G_N_ELEMENTS (host_entries); i++) {
1876 cookies[i] = xcb_change_hosts_checked (self->priv->xcb_connection,
1877 XCB_HOST_MODE_INSERT,
1878 host_entries[i].family,
1879 host_entries[i].length,
1880 (uint8_t *) host_entries[i].address);
1881 }
1882
1883 for (i = 0; i < G_N_ELEMENTS (cookies); i++) {
1884 xcb_generic_error_t *xcb_error;
1885
1886 xcb_error = xcb_request_check (self->priv->xcb_connection, cookies[i]);
1887
1888 if (xcb_error != NULL) {
1889 g_debug ("Failed to give system user '%s' access to the display. Trying to proceed.", host_entries[i].address + sizeof ("localuser"));
1890 free (xcb_error);
1891 } else {
1892 g_debug ("Gave system user '%s' access to the display.", host_entries[i].address + sizeof ("localuser"));
1893 }
1894 }
1895
1896 gdm_display_set_windowpath (self);
1897 } else {
1898 g_debug ("GdmDisplay: Connected to display %s", self->priv->x11_display_name);
1899 ret = TRUE;
1900 }
1901
1902 if (ret == TRUE) {
1903 g_object_notify (G_OBJECT (self), "is-connected");
1904 }
1905
1906 return ret;
1907 }
1908
1909