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