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