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