]> rtime.felk.cvut.cz Git - sojka/lightdm.git/blob - src/session.c
92a59bbd28c09c641909cd88a240db7f9cbe9f74
[sojka/lightdm.git] / src / session.c
1 /*
2  * Copyright (C) 2010-2011 Robert Ancell.
3  * Author: Robert Ancell <robert.ancell@canonical.com>
4  *
5  * This program is free software: you can redistribute it and/or modify it under
6  * the terms of the GNU General Public License as published by the Free Software
7  * Foundation, either version 3 of the License, or (at your option) any later
8  * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
9  * license.
10  */
11
12 #include <config.h>
13
14 #include <stdlib.h>
15 #include <string.h>
16 #include <errno.h>
17 #include <unistd.h>
18 #include <sys/wait.h>
19 #include <fcntl.h>
20 #include <glib/gstdio.h>
21 #include <grp.h>
22 #include <pwd.h>
23
24 #include "session.h"
25 #include "configuration.h"
26 #include "console-kit.h"
27 #include "login1.h"
28 #include "guest-account.h"
29 #include "shared-data-manager.h"
30 #include "greeter-socket.h"
31
32 enum {
33     CREATE_GREETER,
34     GOT_MESSAGES,
35     AUTHENTICATION_COMPLETE,
36     STOPPED,
37     LAST_SIGNAL
38 };
39 static guint signals[LAST_SIGNAL] = { 0 };
40
41 struct SessionPrivate
42 {
43     /* Configuration for this session */
44     SessionConfig *config;
45
46     /* Display server running on */
47     DisplayServer *display_server;
48
49     /* PID of child process */
50     GPid pid;
51
52     /* Pipes to talk to child */
53     int to_child_input;
54     int from_child_output;
55     GIOChannel *from_child_channel;
56     guint from_child_watch;
57     guint child_watch;
58
59     /* User to authenticate as */
60     gchar *username;
61
62     /* TRUE if is a guest account */
63     gboolean is_guest;
64
65     /* User object that matches the current username */
66     User *user;
67
68     /* PAM service to use */
69     gchar *pam_service;
70
71     /* TRUE if should run PAM authentication phase */
72     gboolean do_authenticate;
73
74     /* TRUE if can handle PAM prompts */
75     gboolean is_interactive;
76
77     /* Messages being requested by PAM */
78     int messages_length;
79     struct pam_message *messages;
80
81     /* Authentication result from PAM */
82     gboolean authentication_started;
83     gboolean authentication_complete;
84     int authentication_result;
85     gchar *authentication_result_string;
86
87     /* File to log to */
88     gchar *log_filename;
89     LogMode log_mode;
90
91     /* tty this session is running on */
92     gchar *tty;
93
94     /* X display connected to */
95     gchar *xdisplay;
96     XAuthority *x_authority;
97     gboolean x_authority_use_system_location;
98
99     /* Socket to allow greeters to connect to (if allowed) */
100     GreeterSocket *greeter_socket;
101
102     /* Remote host this session is being controlled from */
103     gchar *remote_host_name;
104
105     /* Console kit cookie */
106     gchar *console_kit_cookie;
107
108     /* login1 session ID */
109     gchar *login1_session_id;
110
111     /* Environment to set in child */
112     GList *env;
113
114     /* Command to run in child */
115     gchar **argv;
116
117     /* True if have run command */
118     gboolean command_run;
119
120     /* TRUE if stopping this session */
121     gboolean stopping;
122 };
123
124 /* Maximum length of a string to pass between daemon and session */
125 #define MAX_STRING_LENGTH 65535
126
127 static void session_logger_iface_init (LoggerInterface *iface);
128
129 G_DEFINE_TYPE_WITH_CODE (Session, session, G_TYPE_OBJECT,
130                          G_IMPLEMENT_INTERFACE (
131                              LOGGER_TYPE, session_logger_iface_init));
132
133 Session *
134 session_new (void)
135 {
136     return g_object_new (SESSION_TYPE, NULL);
137 }
138
139 void
140 session_set_config (Session *session, SessionConfig *config)
141 {
142     g_return_if_fail (session != NULL);
143
144     g_clear_object (&session->priv->config);
145     session->priv->config = g_object_ref (config);
146 }
147
148 SessionConfig *
149 session_get_config (Session *session)
150 {
151     g_return_val_if_fail (session != NULL, NULL);
152     return session->priv->config;
153 }
154
155 const gchar *
156 session_get_session_type (Session *session)
157 {
158     g_return_val_if_fail (session != NULL, NULL);
159     return session_config_get_session_type (session->priv->config);
160 }
161
162 void
163 session_set_pam_service (Session *session, const gchar *pam_service)
164 {
165     g_return_if_fail (session != NULL);
166     g_free (session->priv->pam_service);
167     session->priv->pam_service = g_strdup (pam_service);
168 }
169
170 void
171 session_set_username (Session *session, const gchar *username)
172 {
173     g_return_if_fail (session != NULL);
174     g_free (session->priv->username);
175     session->priv->username = g_strdup (username);
176 }
177
178 void
179 session_set_do_authenticate (Session *session, gboolean do_authenticate)
180 {
181     g_return_if_fail (session != NULL);
182     session->priv->do_authenticate = do_authenticate;
183 }
184
185 void
186 session_set_is_interactive (Session *session, gboolean is_interactive)
187 {
188     g_return_if_fail (session != NULL);
189     session->priv->is_interactive = is_interactive;
190 }
191
192 void
193 session_set_is_guest (Session *session, gboolean is_guest)
194 {
195     g_return_if_fail (session != NULL);
196     session->priv->is_guest = is_guest;
197 }
198
199 gboolean
200 session_get_is_guest (Session *session)
201 {
202     g_return_val_if_fail (session != NULL, FALSE);
203     return session->priv->is_guest;
204 }
205
206 void
207 session_set_log_file (Session *session, const gchar *filename, LogMode log_mode)
208 {
209     g_return_if_fail (session != NULL);
210     g_free (session->priv->log_filename);
211     session->priv->log_filename = g_strdup (filename);
212     session->priv->log_mode = log_mode;
213 }
214
215 void
216 session_set_display_server (Session *session, DisplayServer *display_server)
217 {
218     g_return_if_fail (session != NULL);
219     g_return_if_fail (display_server != NULL);
220
221     if (session->priv->display_server == display_server)
222         return;
223
224     if (session->priv->display_server)
225     {
226         display_server_disconnect_session (session->priv->display_server, session);
227         g_object_unref (session->priv->display_server);
228     }
229     session->priv->display_server = g_object_ref (display_server);
230 }
231
232 DisplayServer *
233 session_get_display_server (Session *session)
234 {
235     g_return_val_if_fail (session != NULL, NULL);
236     return session->priv->display_server;
237 }
238
239 void
240 session_set_tty (Session *session, const gchar *tty)
241 {
242     g_return_if_fail (session != NULL);
243     g_free (session->priv->tty);
244     session->priv->tty = g_strdup (tty);
245 }
246
247 void
248 session_set_xdisplay (Session *session, const gchar *xdisplay)
249 {
250     g_return_if_fail (session != NULL);
251     g_free (session->priv->xdisplay);
252     session->priv->xdisplay = g_strdup (xdisplay);
253 }
254
255 void
256 session_set_x_authority (Session *session, XAuthority *authority, gboolean use_system_location)
257 {
258     g_return_if_fail (session != NULL);
259     g_clear_object (&session->priv->x_authority);
260     if (authority)
261         session->priv->x_authority = g_object_ref (authority);
262     session->priv->x_authority_use_system_location = use_system_location;
263 }
264
265 void
266 session_set_remote_host_name (Session *session, const gchar *remote_host_name)
267 {
268     g_return_if_fail (session != NULL);
269     g_free (session->priv->remote_host_name);
270     session->priv->remote_host_name = g_strdup (remote_host_name);
271 }
272
273 static GList *
274 find_env_entry (Session *session, const gchar *name)
275 {
276     GList *link;
277
278     for (link = session->priv->env; link; link = link->next)
279     {
280         const gchar *entry = link->data;
281
282         if (g_str_has_prefix (entry, name) && entry[strlen (name)] == '=')
283             return link;
284     }
285
286     return NULL;
287 }
288
289 void
290 session_set_env (Session *session, const gchar *name, const gchar *value)
291 {
292     GList *link;
293     gchar *entry;
294
295     g_return_if_fail (session != NULL);
296     g_return_if_fail (value != NULL);
297
298     entry = g_strdup_printf ("%s=%s", name, value);
299
300     link = find_env_entry (session, name);
301     if (link)
302     {
303         g_free (link->data);
304         link->data = entry;
305     }
306     else
307         session->priv->env = g_list_append (session->priv->env, entry);
308 }
309
310 const gchar *
311 session_get_env (Session *session, const gchar *name)
312 {
313     GList *link;
314     gchar *entry;
315
316     link = find_env_entry (session, name);
317     if (!link)
318         return NULL;
319
320     entry = link->data;
321
322     return entry + strlen (name) + 1;
323 }
324
325 void
326 session_unset_env (Session *session, const gchar *name)
327 {
328     GList *link;
329
330     g_return_if_fail (session != NULL);
331
332     link = find_env_entry (session, name);
333     if (!link)
334         return;
335
336     g_free (link->data);
337     session->priv->env = g_list_delete_link (session->priv->env, link);
338 }
339
340 void
341 session_set_argv (Session *session, gchar **argv)
342 {
343     g_return_if_fail (session != NULL);
344     session->priv->argv = g_strdupv (argv);
345 }
346
347 User *
348 session_get_user (Session *session)
349 {
350     g_return_val_if_fail (session != NULL, NULL);
351
352     if (session->priv->username == NULL)
353         return NULL;
354
355     if (!session->priv->user)
356         session->priv->user = accounts_get_user_by_name (session->priv->username);
357
358     return session->priv->user;
359 }
360
361 static void
362 write_data (Session *session, const void *buf, size_t count)
363 {
364     if (write (session->priv->to_child_input, buf, count) != count)
365         l_warning (session, "Error writing to session: %s", strerror (errno));
366 }
367
368 static void
369 write_string (Session *session, const char *value)
370 {
371     int length;
372
373     length = value ? strlen (value) : -1;
374     write_data (session, &length, sizeof (length));
375     if (value)
376         write_data (session, value, sizeof (char) * length);
377 }
378
379 static void
380 write_xauth (Session *session, XAuthority *x_authority)
381 {
382     guint16 family;
383     gsize length;
384
385     if (!x_authority)
386     {
387         write_string (session, NULL);
388         return;
389     }
390
391     write_string (session, x_authority_get_authorization_name (session->priv->x_authority));
392     family = x_authority_get_family (session->priv->x_authority);
393     write_data (session, &family, sizeof (family));
394     length = x_authority_get_address_length (session->priv->x_authority);
395     write_data (session, &length, sizeof (length));
396     write_data (session, x_authority_get_address (session->priv->x_authority), length);
397     write_string (session, x_authority_get_number (session->priv->x_authority));
398     length = x_authority_get_authorization_data_length (session->priv->x_authority);
399     write_data (session, &length, sizeof (length));
400     write_data (session, x_authority_get_authorization_data (session->priv->x_authority), length);
401 }
402
403 static ssize_t
404 read_from_child (Session *session, void *buf, size_t count)
405 {
406     ssize_t n_read;
407     n_read = read (session->priv->from_child_output, buf, count);
408     if (n_read < 0)
409         l_warning (session, "Error reading from session: %s", strerror (errno));
410     return n_read;
411 }
412
413 static gchar *
414 read_string_from_child (Session *session)
415 {
416     int length;
417     char *value;
418
419     if (read_from_child (session, &length, sizeof (length)) <= 0)
420         return NULL;
421     if (length < 0)
422         return NULL;
423     if (length > MAX_STRING_LENGTH)
424     {
425         l_warning (session, "Invalid string length %d from child", length);
426         return NULL;
427     }
428
429     value = g_malloc (sizeof (char) * (length + 1));
430     read_from_child (session, value, length);
431     value[length] = '\0';
432
433     return value;
434 }
435
436 static void
437 session_watch_cb (GPid pid, gint status, gpointer data)
438 {
439     Session *session = data;
440
441     session->priv->child_watch = 0;
442
443     if (WIFEXITED (status))
444         l_debug (session, "Exited with return value %d", WEXITSTATUS (status));
445     else if (WIFSIGNALED (status))
446         l_debug (session, "Terminated with signal %d", WTERMSIG (status));
447
448     /* do this as late as possible for log messages prefix */
449     session->priv->pid = 0;
450
451     /* If failed during authentication then report this as an authentication failure */
452     if (session->priv->authentication_started && !session->priv->authentication_complete)
453     {
454         l_debug (session, "Failed during authentication");
455         session->priv->authentication_complete = TRUE;
456         session->priv->authentication_result = PAM_CONV_ERR;
457         g_free (session->priv->authentication_result_string);
458         session->priv->authentication_result_string = g_strdup ("Authentication stopped before completion");
459         g_signal_emit (G_OBJECT (session), signals[AUTHENTICATION_COMPLETE], 0);
460     }
461
462     g_signal_emit (G_OBJECT (session), signals[STOPPED], 0);
463
464     /* Delete account if it is a guest one */
465     if (session->priv->is_guest)
466         guest_account_cleanup (session->priv->username);
467
468     /* Drop our reference on the child process, it has terminated */
469     g_object_unref (session);
470 }
471
472 static gboolean
473 from_child_cb (GIOChannel *source, GIOCondition condition, gpointer data)
474 {
475     Session *session = data;
476     gchar *username;
477     ssize_t n_read;
478     gboolean auth_complete;
479
480     /* Remote end gone */
481     if (condition == G_IO_HUP)
482     {
483         session->priv->from_child_watch = 0;
484         return FALSE;
485     }
486
487     /* Get the username currently being authenticated (may change during authentication) */
488     username = read_string_from_child (session);
489     if (g_strcmp0 (username, session->priv->username) != 0)
490     {
491         g_free (session->priv->username);
492         session->priv->username = username;
493         g_clear_object (&session->priv->user);
494     }
495     else
496         g_free (username);
497
498     /* Check if authentication completed */
499     n_read = read_from_child (session, &auth_complete, sizeof (auth_complete));
500     if (n_read < 0)
501         l_debug (session, "Error reading from child: %s", strerror (errno));
502     if (n_read <= 0)
503     {
504         session->priv->from_child_watch = 0;
505         return FALSE;
506     }
507
508     if (auth_complete)
509     {
510         session->priv->authentication_complete = TRUE;
511         read_from_child (session, &session->priv->authentication_result, sizeof (session->priv->authentication_result));
512         g_free (session->priv->authentication_result_string);
513         session->priv->authentication_result_string = read_string_from_child (session);
514
515         l_debug (session, "Authentication complete with return value %d: %s", session->priv->authentication_result, session->priv->authentication_result_string);
516
517         /* No longer expect any more messages */
518         session->priv->from_child_watch = 0;
519
520         g_signal_emit (G_OBJECT (session), signals[AUTHENTICATION_COMPLETE], 0);
521
522         return FALSE;
523     }
524     else
525     {
526         int i;
527
528         session->priv->messages_length = 0;
529         read_from_child (session, &session->priv->messages_length, sizeof (session->priv->messages_length));
530         session->priv->messages = calloc (session->priv->messages_length, sizeof (struct pam_message));
531         for (i = 0; i < session->priv->messages_length; i++)
532         {
533             struct pam_message *m = &session->priv->messages[i];
534             read_from_child (session, &m->msg_style, sizeof (m->msg_style));
535             m->msg = read_string_from_child (session);
536         }
537
538         l_debug (session, "Got %d message(s) from PAM", session->priv->messages_length);
539
540         g_signal_emit (G_OBJECT (session), signals[GOT_MESSAGES], 0);
541     }
542
543     return TRUE;
544 }
545
546 gboolean
547 session_start (Session *session)
548 {
549     g_return_val_if_fail (session != NULL, FALSE);
550     return SESSION_GET_CLASS (session)->start (session);
551 }
552
553 gboolean
554 session_get_is_started (Session *session)
555 {
556     return session->priv->pid != 0;
557 }
558
559 static Greeter *
560 create_greeter_cb (GreeterSocket *socket, Session *session)
561 {
562     Greeter *greeter;
563     g_signal_emit (session, signals[CREATE_GREETER], 0, &greeter);
564     return greeter;
565 }
566
567 static gboolean
568 session_real_start (Session *session)
569 {
570     int version;
571     int to_child_pipe[2], from_child_pipe[2];
572     int to_child_output, from_child_input;
573     gchar *arg0, *arg1;
574
575     g_return_val_if_fail (session->priv->pid == 0, FALSE);
576
577     if (session->priv->display_server)
578         display_server_connect_session (session->priv->display_server, session);
579
580     /* Create pipes to talk to the child */
581     if (pipe (to_child_pipe) < 0 || pipe (from_child_pipe) < 0)
582     {
583         g_warning ("Failed to create pipe to communicate with session process: %s", strerror (errno));
584         return FALSE;
585     }
586     to_child_output = to_child_pipe[0];
587     session->priv->to_child_input = to_child_pipe[1];
588     session->priv->from_child_output = from_child_pipe[0];
589     from_child_input = from_child_pipe[1];
590     session->priv->from_child_channel = g_io_channel_unix_new (session->priv->from_child_output);
591     session->priv->from_child_watch = g_io_add_watch (session->priv->from_child_channel, G_IO_IN | G_IO_HUP, from_child_cb, session);
592
593     /* Don't allow the daemon end of the pipes to be accessed in child processes */
594     fcntl (session->priv->to_child_input, F_SETFD, FD_CLOEXEC);
595     fcntl (session->priv->from_child_output, F_SETFD, FD_CLOEXEC);
596
597     /* Create the guest account if it is one */
598     if (session->priv->is_guest && session->priv->username == NULL)
599     {
600         session->priv->username = guest_account_setup ();
601         if (!session->priv->username)
602             return FALSE;
603     }
604
605     /* Open socket to allow in-session greeter */
606     if (session->priv->config && session_config_get_allow_greeter (session->priv->config))
607     {
608         gchar *run_dir, *dir, *path;
609         GError *error = NULL;
610
611         run_dir = config_get_string (config_get_instance (), "LightDM", "run-directory");
612         dir = g_build_filename (run_dir, session->priv->username, NULL);
613         g_free (run_dir);
614
615         if (g_mkdir_with_parents (dir, S_IRWXU) < 0)
616             l_warning (session, "Failed to create greeter socket dir %s: %s", dir, strerror (errno));
617         if (getuid () == 0)
618         {
619             if (chown (dir, user_get_uid (session_get_user (session)), user_get_gid (session_get_user (session))) < 0)
620                 l_warning (session, "Failed to set ownership of greeter socket dir: %s", strerror (errno));
621         }
622
623         path = g_build_filename (dir, "greeter-socket", NULL);
624         session->priv->greeter_socket = greeter_socket_new (path);
625         g_signal_connect (session->priv->greeter_socket, GREETER_SOCKET_SIGNAL_CREATE_GREETER, G_CALLBACK (create_greeter_cb), session);
626         session_set_env (session, "LIGHTDM_GREETER_PIPE", path);
627         g_free (path);
628         g_free (dir);
629
630         if (!greeter_socket_start (session->priv->greeter_socket, &error))
631         {
632             l_warning (session, "Failed to start greeter socket: %s\n", error->message);
633             g_clear_error (&error);
634         }
635     }
636
637     /* Run the child */
638     arg0 = g_strdup_printf ("%d", to_child_output);
639     arg1 = g_strdup_printf ("%d", from_child_input);
640     session->priv->pid = fork ();
641     if (session->priv->pid == 0)
642     {
643         /* Run us again in session child mode */
644         execlp ("lightdm",
645                 "lightdm",
646                 "--session-child",
647                 arg0, arg1, NULL);
648         _exit (EXIT_FAILURE);
649     }
650     g_free (arg0);
651     g_free (arg1);
652
653     if (session->priv->pid < 0)
654     {
655         g_debug ("Failed to fork session child process: %s", strerror (errno));
656         return FALSE;
657     }
658
659     /* Hold a reference on this object until the child process terminates so we
660      * can handle the watch callback even if it is no longer used. Otherwise a
661      * zombie process will remain */
662     g_object_ref (session);
663
664     /* Listen for session termination */
665     session->priv->authentication_started = TRUE;
666     session->priv->child_watch = g_child_watch_add (session->priv->pid, session_watch_cb, session);
667
668     /* Close the ends of the pipes we don't need */
669     close (to_child_output);
670     close (from_child_input);
671
672     /* Indicate what version of the protocol we are using */
673     version = 3;
674     write_data (session, &version, sizeof (version));
675
676     /* Send configuration */
677     write_string (session, session->priv->pam_service);
678     write_string (session, session->priv->username);
679     write_data (session, &session->priv->do_authenticate, sizeof (session->priv->do_authenticate));
680     write_data (session, &session->priv->is_interactive, sizeof (session->priv->is_interactive));
681     write_string (session, NULL); /* Used to be class, now we just use the environment variable */
682     write_string (session, session->priv->tty);
683     write_string (session, session->priv->remote_host_name);
684     write_string (session, session->priv->xdisplay);
685     write_xauth (session, session->priv->x_authority);
686
687     l_debug (session, "Started with service '%s', username '%s'", session->priv->pam_service, session->priv->username);
688
689     return TRUE;
690 }
691
692 const gchar *
693 session_get_username (Session *session)
694 {
695     g_return_val_if_fail (session != NULL, NULL);
696     return session->priv->username;
697 }
698
699 const gchar *
700 session_get_login1_session_id (Session *session)
701 {
702     g_return_val_if_fail (session != NULL, NULL);
703     return session->priv->login1_session_id;
704 }
705
706 const gchar *
707 session_get_console_kit_cookie (Session *session)
708 {
709     g_return_val_if_fail (session != NULL, NULL);
710     return session->priv->console_kit_cookie;
711 }
712
713 void
714 session_respond (Session *session, struct pam_response *response)
715 {
716     int error = PAM_SUCCESS;
717     int i;
718
719     g_return_if_fail (session != NULL);
720
721     write_data (session, &error, sizeof (error));
722     for (i = 0; i < session->priv->messages_length; i++)
723     {
724         write_string (session, response[i].resp);
725         write_data (session, &response[i].resp_retcode, sizeof (response[i].resp_retcode));
726     }
727
728     /* Delete the old messages */
729     for (i = 0; i < session->priv->messages_length; i++)
730         g_free ((char *) session->priv->messages[i].msg);
731     g_free (session->priv->messages);
732     session->priv->messages = NULL;
733     session->priv->messages_length = 0;
734 }
735
736 void
737 session_respond_error (Session *session, int error)
738 {
739     g_return_if_fail (session != NULL);
740     g_return_if_fail (error != PAM_SUCCESS);
741
742     write_data (session, &error, sizeof (error));
743 }
744
745 int
746 session_get_messages_length (Session *session)
747 {
748     g_return_val_if_fail (session != NULL, 0);
749     return session->priv->messages_length;
750 }
751
752 const struct pam_message *
753 session_get_messages (Session *session)
754 {
755     g_return_val_if_fail (session != NULL, NULL);
756     return session->priv->messages;
757 }
758
759 gboolean
760 session_get_is_authenticated (Session *session)
761 {
762     g_return_val_if_fail (session != NULL, FALSE);
763     return session->priv->authentication_complete && session->priv->authentication_result == PAM_SUCCESS;
764 }
765
766 int
767 session_get_authentication_result (Session *session)
768 {
769     g_return_val_if_fail (session != NULL, 0);
770     return session->priv->authentication_result;
771 }
772
773 const gchar *
774 session_get_authentication_result_string (Session *session)
775 {
776     g_return_val_if_fail (session != NULL, NULL);
777     return session->priv->authentication_result_string;
778 }
779
780 void
781 session_run (Session *session)
782 {
783     g_return_if_fail (session != NULL);
784     g_return_if_fail (session->priv->display_server != NULL);
785     return SESSION_GET_CLASS (session)->run (session);
786 }
787
788 gboolean
789 session_get_is_run (Session *session)
790 {
791     g_return_val_if_fail (session != NULL, FALSE);
792     return session->priv->command_run;
793 }
794
795 static void
796 session_real_run (Session *session)
797 {
798     gsize i, argc;
799     gchar *command, *x_authority_filename;
800     GList *link;
801
802     g_return_if_fail (session != NULL);
803     g_return_if_fail (!session->priv->command_run);
804     g_return_if_fail (session_get_is_authenticated (session));
805     g_return_if_fail (session->priv->argv != NULL);
806     g_return_if_fail (session->priv->pid != 0);
807
808     display_server_connect_session (session->priv->display_server, session);
809
810     session->priv->command_run = TRUE;
811
812     command = g_strjoinv (" ", session->priv->argv);
813     l_debug (session, "Running command %s", command);
814     g_free (command);
815
816     /* Create authority location */
817     if (session->priv->x_authority_use_system_location)
818     {
819         gchar *run_dir, *dir;
820
821         run_dir = config_get_string (config_get_instance (), "LightDM", "run-directory");
822         dir = g_build_filename (run_dir, session->priv->username, NULL);
823         g_free (run_dir);
824
825         if (g_mkdir_with_parents (dir, S_IRWXU) < 0)
826             l_warning (session, "Failed to set create system authority dir %s: %s", dir, strerror (errno));
827         if (getuid () == 0)
828         {
829             if (chown (dir, user_get_uid (session_get_user (session)), user_get_gid (session_get_user (session))) < 0)
830                 l_warning (session, "Failed to set ownership of user authority dir: %s", strerror (errno));
831         }
832
833         x_authority_filename = g_build_filename (dir, "xauthority", NULL);
834         g_free (dir);
835     }
836     else
837         x_authority_filename = g_build_filename (user_get_home_directory (session_get_user (session)), ".Xauthority", NULL);
838
839     /* Make sure shared user directory for this user exists */
840     if (!session->priv->remote_host_name)
841     {
842         gchar *data_dir = shared_data_manager_ensure_user_dir (shared_data_manager_get_instance (), session->priv->username);
843         if (data_dir)
844         {
845             session_set_env (session, "XDG_GREETER_DATA_DIR", data_dir);
846             g_free (data_dir);
847         }
848     }
849
850     if (session->priv->log_filename)
851         l_debug (session, "Logging to %s", session->priv->log_filename);
852     write_string (session, session->priv->log_filename);
853     write_data (session, &session->priv->log_mode, sizeof (session->priv->log_mode));
854     write_string (session, session->priv->tty);
855     write_string (session, x_authority_filename);
856     g_free (x_authority_filename);
857     write_string (session, session->priv->xdisplay);
858     write_xauth (session, session->priv->x_authority);
859     argc = g_list_length (session->priv->env);
860     write_data (session, &argc, sizeof (argc));
861     for (link = session->priv->env; link; link = link->next)
862         write_string (session, (gchar *) link->data);
863     argc = g_strv_length (session->priv->argv);
864     write_data (session, &argc, sizeof (argc));
865     for (i = 0; i < argc; i++)
866         write_string (session, session->priv->argv[i]);
867
868     session->priv->login1_session_id = read_string_from_child (session);
869     session->priv->console_kit_cookie = read_string_from_child (session);
870 }
871
872 void
873 session_lock (Session *session)
874 {
875     g_return_if_fail (session != NULL);
876     if (getuid () == 0)
877     {
878         if (session->priv->login1_session_id)
879             login1_service_lock_session (login1_service_get_instance (), session->priv->login1_session_id);
880         else if (session->priv->console_kit_cookie)
881             ck_lock_session (session->priv->console_kit_cookie);
882     }
883 }
884
885 void
886 session_unlock (Session *session)
887 {
888     g_return_if_fail (session != NULL);
889     if (getuid () == 0)
890     {
891         if (session->priv->login1_session_id)
892             login1_service_unlock_session (login1_service_get_instance (), session->priv->login1_session_id);
893         else if (session->priv->console_kit_cookie)
894             ck_unlock_session (session->priv->console_kit_cookie);
895     }
896 }
897
898 void
899 session_activate (Session *session)
900 {
901     g_return_if_fail (session != NULL);
902     if (getuid () == 0)
903     {
904         if (session->priv->login1_session_id)
905             login1_service_activate_session (login1_service_get_instance (), session->priv->login1_session_id);
906         else if (session->priv->console_kit_cookie)
907             ck_activate_session (session->priv->console_kit_cookie);
908     }
909 }
910
911 void
912 session_stop (Session *session)
913 {
914     g_return_if_fail (session != NULL);
915
916     /* If can cleanly stop then do that */
917     if (session_get_is_authenticated (session) && !session->priv->command_run)
918     {
919         gsize n = 0;
920         LogMode log_mode = LOG_MODE_INVALID;
921
922         session->priv->command_run = TRUE;
923         write_string (session, NULL); // log filename
924         write_data (session, &log_mode, sizeof (log_mode)); // log mode
925         write_string (session, NULL); // tty
926         write_string (session, NULL); // xauth filename
927         write_string (session, NULL); // xdisplay
928         write_xauth (session, NULL); // xauth
929         write_data (session, &n, sizeof (n)); // environment
930         write_data (session, &n, sizeof (n)); // command
931         return;
932     }
933
934     if (session->priv->stopping)
935         return;
936     session->priv->stopping = TRUE;
937
938     return SESSION_GET_CLASS (session)->stop (session);
939 }
940
941 static void
942 session_real_stop (Session *session)
943 {
944     g_return_if_fail (session != NULL);
945
946     if (session->priv->pid > 0)
947     {
948         l_debug (session, "Sending SIGTERM");
949         kill (session->priv->pid, SIGTERM);
950         // FIXME: Handle timeout
951     }
952     else
953         g_signal_emit (G_OBJECT (session), signals[STOPPED], 0);
954 }
955
956 gboolean
957 session_get_is_stopping (Session *session)
958 {
959     g_return_val_if_fail (session != NULL, FALSE);
960     return session->priv->stopping;
961 }
962
963 static void
964 session_init (Session *session)
965 {
966     session->priv = G_TYPE_INSTANCE_GET_PRIVATE (session, SESSION_TYPE, SessionPrivate);
967     session->priv->log_filename = g_strdup (".xsession-errors");
968     session->priv->log_mode = LOG_MODE_BACKUP_AND_TRUNCATE;
969     session->priv->to_child_input = -1;
970     session->priv->from_child_output = -1;
971 }
972
973 static void
974 session_finalize (GObject *object)
975 {
976     Session *self = SESSION (object);
977     int i;
978
979     g_clear_object (&self->priv->config);
980     g_clear_object (&self->priv->display_server);
981     if (self->priv->pid)
982         kill (self->priv->pid, SIGKILL);
983     close (self->priv->to_child_input);
984     close (self->priv->from_child_output);
985     if (self->priv->from_child_channel)
986         g_io_channel_unref (self->priv->from_child_channel);
987     if (self->priv->from_child_watch)
988         g_source_remove (self->priv->from_child_watch);
989     if (self->priv->child_watch)
990         g_source_remove (self->priv->child_watch);
991     g_free (self->priv->username);
992     g_clear_object (&self->priv->user);
993     g_free (self->priv->pam_service);
994     for (i = 0; i < self->priv->messages_length; i++)
995         g_free ((char *) self->priv->messages[i].msg);
996     g_free (self->priv->messages);
997     g_free (self->priv->authentication_result_string);
998     g_free (self->priv->log_filename);
999     g_free (self->priv->tty);
1000     g_free (self->priv->xdisplay);
1001     g_clear_object (&self->priv->x_authority);
1002     g_free (self->priv->remote_host_name);
1003     g_free (self->priv->login1_session_id);
1004     g_free (self->priv->console_kit_cookie);
1005     g_list_free_full (self->priv->env, g_free);
1006     g_strfreev (self->priv->argv);
1007
1008     G_OBJECT_CLASS (session_parent_class)->finalize (object);
1009 }
1010
1011 static void
1012 session_class_init (SessionClass *klass)
1013 {
1014     GObjectClass *object_class = G_OBJECT_CLASS (klass);
1015
1016     klass->start = session_real_start;
1017     klass->run = session_real_run;
1018     klass->stop = session_real_stop;
1019     object_class->finalize = session_finalize;
1020
1021     g_type_class_add_private (klass, sizeof (SessionPrivate));
1022
1023     signals[CREATE_GREETER] =
1024         g_signal_new (SESSION_SIGNAL_CREATE_GREETER,
1025                       G_TYPE_FROM_CLASS (klass),
1026                       G_SIGNAL_RUN_LAST,
1027                       G_STRUCT_OFFSET (SessionClass, create_greeter),
1028                       g_signal_accumulator_first_wins,
1029                       NULL,
1030                       NULL,
1031                       GREETER_TYPE, 0);
1032
1033     signals[GOT_MESSAGES] =
1034         g_signal_new (SESSION_SIGNAL_GOT_MESSAGES,
1035                       G_TYPE_FROM_CLASS (klass),
1036                       G_SIGNAL_RUN_LAST,
1037                       G_STRUCT_OFFSET (SessionClass, got_messages),
1038                       NULL, NULL,
1039                       NULL,
1040                       G_TYPE_NONE, 0);
1041
1042     signals[AUTHENTICATION_COMPLETE] =
1043         g_signal_new (SESSION_SIGNAL_AUTHENTICATION_COMPLETE,
1044                       G_TYPE_FROM_CLASS (klass),
1045                       G_SIGNAL_RUN_LAST,
1046                       G_STRUCT_OFFSET (SessionClass, authentication_complete),
1047                       NULL, NULL,
1048                       NULL,
1049                       G_TYPE_NONE, 0);
1050
1051     signals[STOPPED] =
1052         g_signal_new (SESSION_SIGNAL_STOPPED,
1053                       G_TYPE_FROM_CLASS (klass),
1054                       G_SIGNAL_RUN_LAST,
1055                       G_STRUCT_OFFSET (SessionClass, stopped),
1056                       NULL, NULL,
1057                       NULL,
1058                       G_TYPE_NONE, 0);
1059 }
1060
1061 static gint
1062 session_real_logprefix (Logger *self, gchar *buf, gulong buflen)
1063 {
1064     Session *session = SESSION (self);
1065     if (session->priv->pid != 0)
1066         return g_snprintf (buf, buflen, "Session pid=%d: ", session->priv->pid);
1067     else
1068         return g_snprintf (buf, buflen, "Session: ");
1069 }
1070
1071 static void
1072 session_logger_iface_init (LoggerInterface *iface)
1073 {
1074     iface->logprefix = &session_real_logprefix;
1075 }