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