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