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