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