2 * Copyright (C) 2010-2011 Robert Ancell.
3 * Author: Robert Ancell <robert.ancell@canonical.com>
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
20 #include <glib/gstdio.h>
25 #include "configuration.h"
26 #include "console-kit.h"
28 #include "guest-account.h"
32 AUTHENTICATION_COMPLETE,
36 static guint signals[LAST_SIGNAL] = { 0 };
43 /* Display server running on */
44 DisplayServer *display_server;
46 /* PID of child process */
49 /* Pipes to talk to child */
51 int from_child_output;
52 GIOChannel *from_child_channel;
53 guint from_child_watch;
56 /* User to authenticate as */
59 /* TRUE if is a guest account */
62 /* User object that matches the current username */
65 /* PAM service to use */
68 /* TRUE if should run PAM authentication phase */
69 gboolean do_authenticate;
71 /* TRUE if can handle PAM prompts */
72 gboolean is_interactive;
74 /* Messages being requested by PAM */
76 struct pam_message *messages;
78 /* Authentication result from PAM */
79 gboolean authentication_started;
80 gboolean authentication_complete;
81 int authentication_result;
82 gchar *authentication_result_string;
90 /* tty this session is running on */
93 /* X display connected to */
95 XAuthority *x_authority;
96 gboolean x_authority_use_system_location;
98 /* Remote host this session is being controlled from */
99 gchar *remote_host_name;
101 /* Console kit cookie */
102 gchar *console_kit_cookie;
105 gchar *login1_session;
107 /* Environment to set in child */
110 /* Command to run in child */
113 /* True if have run command */
114 gboolean command_run;
116 /* TRUE if stopping this session */
120 /* Maximum length of a string to pass between daemon and session */
121 #define MAX_STRING_LENGTH 65535
123 G_DEFINE_TYPE (Session, session, G_TYPE_OBJECT);
128 return g_object_new (SESSION_TYPE, NULL);
132 session_set_session_type (Session *session, const gchar *session_type)
134 g_return_if_fail (session != NULL);
135 g_free (session->priv->session_type);
136 session->priv->session_type = g_strdup (session_type);
140 session_get_session_type (Session *session)
142 g_return_val_if_fail (session != NULL, NULL);
143 return session->priv->session_type;
147 session_set_pam_service (Session *session, const gchar *pam_service)
149 g_return_if_fail (session != NULL);
150 g_free (session->priv->pam_service);
151 session->priv->pam_service = g_strdup (pam_service);
155 session_set_username (Session *session, const gchar *username)
157 g_return_if_fail (session != NULL);
158 g_free (session->priv->username);
159 session->priv->username = g_strdup (username);
163 session_set_do_authenticate (Session *session, gboolean do_authenticate)
165 g_return_if_fail (session != NULL);
166 session->priv->do_authenticate = do_authenticate;
170 session_set_is_interactive (Session *session, gboolean is_interactive)
172 g_return_if_fail (session != NULL);
173 session->priv->is_interactive = is_interactive;
177 session_set_is_guest (Session *session, gboolean is_guest)
179 g_return_if_fail (session != NULL);
180 session->priv->is_guest = is_guest;
184 session_get_is_guest (Session *session)
186 g_return_val_if_fail (session != NULL, FALSE);
187 return session->priv->is_guest;
191 session_set_log_file (Session *session, const gchar *filename)
193 g_return_if_fail (session != NULL);
194 g_free (session->priv->log_filename);
195 session->priv->log_filename = g_strdup (filename);
199 session_set_class (Session *session, const gchar *class)
201 g_return_if_fail (session != NULL);
202 g_free (session->priv->class);
203 session->priv->class = g_strdup (class);
207 session_set_display_server (Session *session, DisplayServer *display_server)
209 g_return_if_fail (session != NULL);
210 g_return_if_fail (display_server != NULL);
211 if (session->priv->display_server)
213 display_server_disconnect_session (session->priv->display_server, session);
214 g_object_unref (session->priv->display_server);
216 session->priv->display_server = g_object_ref (display_server);
220 session_get_display_server (Session *session)
222 g_return_val_if_fail (session != NULL, NULL);
223 return session->priv->display_server;
227 session_set_tty (Session *session, const gchar *tty)
229 g_return_if_fail (session != NULL);
230 g_free (session->priv->tty);
231 session->priv->tty = g_strdup (tty);
235 session_set_xdisplay (Session *session, const gchar *xdisplay)
237 g_return_if_fail (session != NULL);
238 g_free (session->priv->xdisplay);
239 session->priv->xdisplay = g_strdup (xdisplay);
243 session_set_x_authority (Session *session, XAuthority *authority, gboolean use_system_location)
245 g_return_if_fail (session != NULL);
246 if (session->priv->x_authority)
248 g_object_unref (session->priv->x_authority);
249 session->priv->x_authority = NULL;
252 session->priv->x_authority = g_object_ref (authority);
253 session->priv->x_authority_use_system_location = use_system_location;
257 session_set_remote_host_name (Session *session, const gchar *remote_host_name)
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);
265 find_env_entry (Session *session, const gchar *name)
269 for (link = session->priv->env; link; link = link->next)
271 const gchar *entry = link->data;
273 if (g_str_has_prefix (entry, name) && entry[strlen (name)] == '=')
281 session_set_env (Session *session, const gchar *name, const gchar *value)
286 g_return_if_fail (session != NULL);
287 g_return_if_fail (value != NULL);
289 entry = g_strdup_printf ("%s=%s", name, value);
291 link = find_env_entry (session, name);
298 session->priv->env = g_list_append (session->priv->env, entry);
302 session_unset_env (Session *session, const gchar *name)
306 g_return_if_fail (session != NULL);
308 link = find_env_entry (session, name);
313 session->priv->env = g_list_remove_link (session->priv->env, link);
317 session_set_argv (Session *session, gchar **argv)
319 g_return_if_fail (session != NULL);
320 session->priv->argv = g_strdupv (argv);
324 session_get_user (Session *session)
326 g_return_val_if_fail (session != NULL, NULL);
328 if (session->priv->username == NULL)
331 if (!session->priv->user)
332 session->priv->user = accounts_get_user_by_name (session->priv->username);
334 return session->priv->user;
338 write_data (Session *session, const void *buf, size_t count)
340 if (write (session->priv->to_child_input, buf, count) != count)
341 g_warning ("Error writing to session: %s", strerror (errno));
345 write_string (Session *session, const char *value)
349 length = value ? strlen (value) : -1;
350 write_data (session, &length, sizeof (length));
352 write_data (session, value, sizeof (char) * length);
356 write_xauth (Session *session, XAuthority *x_authority)
363 write_string (session, NULL);
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);
380 read_from_child (Session *session, void *buf, size_t count)
383 n_read = read (session->priv->from_child_output, buf, count);
385 g_warning ("Error reading from session: %s", strerror (errno));
390 read_string_from_child (Session *session)
395 if (read_from_child (session, &length, sizeof (length)) <= 0)
399 if (length > MAX_STRING_LENGTH)
401 g_warning ("Invalid string length %d from child", length);
405 value = g_malloc (sizeof (char) * (length + 1));
406 read_from_child (session, value, length);
407 value[length] = '\0';
413 session_watch_cb (GPid pid, gint status, gpointer data)
415 Session *session = data;
417 session->priv->pid = 0;
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));
424 /* If failed during authentication then report this as an authentication failure */
425 if (session->priv->authentication_started && !session->priv->authentication_complete)
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);
435 g_signal_emit (G_OBJECT (session), signals[STOPPED], 0);
437 /* Delete account if it is a guest one */
438 if (session->priv->is_guest)
439 guest_account_cleanup (session->priv->username);
441 /* Drop our reference on the child process, it has terminated */
442 g_object_unref (session);
446 from_child_cb (GIOChannel *source, GIOCondition condition, gpointer data)
448 Session *session = data;
451 gboolean auth_complete;
453 /* Remote end gone */
454 if (condition == G_IO_HUP)
456 session->priv->from_child_watch = 0;
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)
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;
473 /* Check if authentication completed */
474 n_read = read_from_child (session, &auth_complete, sizeof (auth_complete));
476 g_debug ("Error reading from child: %s", strerror (errno));
479 session->priv->from_child_watch = 0;
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);
490 g_debug ("Session %d authentication complete with return value %d: %s", session->priv->pid, session->priv->authentication_result, session->priv->authentication_result_string);
492 /* No longer expect any more messages */
493 session->priv->from_child_watch = 0;
495 g_signal_emit (G_OBJECT (session), signals[AUTHENTICATION_COMPLETE], 0);
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++)
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);
513 g_debug ("Session %d got %d message(s) from PAM", session->priv->pid, session->priv->messages_length);
515 g_signal_emit (G_OBJECT (session), signals[GOT_MESSAGES], 0);
522 session_start (Session *session)
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);
530 session_get_is_started (Session *session)
532 return session->priv->pid != 0;
536 session_real_start (Session *session)
539 int to_child_pipe[2], from_child_pipe[2];
540 int to_child_output, from_child_input;
542 g_return_val_if_fail (session->priv->pid == 0, FALSE);
544 display_server_connect_session (session->priv->display_server, session);
546 /* Create pipes to talk to the child */
547 if (pipe (to_child_pipe) < 0 || pipe (from_child_pipe) < 0)
549 g_warning ("Failed to create pipe to communicate with session process: %s", strerror (errno));
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);
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);
563 /* Create the guest account if it is one */
564 if (session->priv->is_guest && session->priv->username == NULL)
566 session->priv->username = guest_account_setup ();
567 if (!session->priv->username)
572 session->priv->pid = fork ();
573 if (session->priv->pid < 0)
575 g_debug ("Failed to fork session child process: %s", strerror (errno));
579 if (session->priv->pid == 0)
581 /* Run us again in session child mode */
585 g_strdup_printf ("%d", to_child_output),
586 g_strdup_printf ("%d", from_child_input),
588 _exit (EXIT_FAILURE);
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);
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);
600 /* Close the ends of the pipes we don't need */
601 close (to_child_output);
602 close (from_child_input);
604 /* Indicate what version of the protocol we are using */
606 write_data (session, &version, sizeof (version));
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);
619 g_debug ("Started session %d with service '%s', username '%s'", session->priv->pid, session->priv->pam_service, session->priv->username);
625 session_get_username (Session *session)
627 g_return_val_if_fail (session != NULL, NULL);
628 return session->priv->username;
632 session_get_console_kit_cookie (Session *session)
634 g_return_val_if_fail (session != NULL, NULL);
635 return session->priv->console_kit_cookie;
639 session_respond (Session *session, struct pam_response *response)
641 int error = PAM_SUCCESS;
644 g_return_if_fail (session != NULL);
646 write_data (session, &error, sizeof (error));
647 for (i = 0; i < session->priv->messages_length; i++)
649 write_string (session, response[i].resp);
650 write_data (session, &response[i].resp_retcode, sizeof (response[i].resp_retcode));
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;
662 session_respond_error (Session *session, int error)
664 g_return_if_fail (session != NULL);
665 g_return_if_fail (error != PAM_SUCCESS);
667 write_data (session, &error, sizeof (error));
671 session_get_messages_length (Session *session)
673 g_return_val_if_fail (session != NULL, 0);
674 return session->priv->messages_length;
677 const struct pam_message *
678 session_get_messages (Session *session)
680 g_return_val_if_fail (session != NULL, NULL);
681 return session->priv->messages;
685 session_get_is_authenticated (Session *session)
687 g_return_val_if_fail (session != NULL, FALSE);
688 return session->priv->authentication_complete && session->priv->authentication_result == PAM_SUCCESS;
692 session_get_authentication_result (Session *session)
694 g_return_val_if_fail (session != NULL, 0);
695 return session->priv->authentication_result;
699 session_get_authentication_result_string (Session *session)
701 g_return_val_if_fail (session != NULL, NULL);
702 return session->priv->authentication_result_string;
706 session_run (Session *session)
708 g_return_if_fail (session->priv->display_server != NULL);
709 return SESSION_GET_CLASS (session)->run (session);
713 session_real_run (Session *session)
716 gchar *command, *x_authority_filename;
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);
725 display_server_connect_session (session->priv->display_server, session);
727 session->priv->command_run = TRUE;
729 command = g_strjoinv (" ", session->priv->argv);
730 g_debug ("Session %d running command %s", session->priv->pid, command);
733 /* Create authority location */
734 if (session->priv->x_authority_use_system_location)
736 gchar *run_dir, *dir;
738 run_dir = config_get_string (config_get_instance (), "LightDM", "run-directory");
739 dir = g_build_filename (run_dir, session->priv->username, NULL);
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));
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));
750 x_authority_filename = g_build_filename (dir, "xauthority", NULL);
754 x_authority_filename = g_build_filename (user_get_home_directory (session_get_user (session)), ".Xauthority", NULL);
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]);
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);
778 session_lock (Session *session)
780 g_return_if_fail (session != NULL);
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);
791 session_unlock (Session *session)
793 g_return_if_fail (session != NULL);
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);
804 session_stop (Session *session)
806 g_return_if_fail (session != NULL);
808 if (session->priv->stopping)
810 session->priv->stopping = TRUE;
812 return SESSION_GET_CLASS (session)->stop (session);
816 session_real_stop (Session *session)
818 g_return_if_fail (session != NULL);
820 if (session->priv->pid > 0)
822 g_debug ("Session %d: Sending SIGTERM", session->priv->pid);
823 kill (session->priv->pid, SIGTERM);
824 // FIXME: Handle timeout
827 g_signal_emit (G_OBJECT (session), signals[STOPPED], 0);
831 session_get_is_stopping (Session *session)
833 g_return_val_if_fail (session != NULL, FALSE);
834 return session->priv->stopping;
838 session_init (Session *session)
840 session->priv = G_TYPE_INSTANCE_GET_PRIVATE (session, SESSION_TYPE, SessionPrivate);
841 session->priv->log_filename = g_strdup (".xsession-errors");
845 session_finalize (GObject *object)
847 Session *self = SESSION (object);
850 g_free (self->priv->session_type);
851 if (self->priv->display_server)
852 g_object_unref (self->priv->display_server);
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);
881 G_OBJECT_CLASS (session_parent_class)->finalize (object);
885 session_class_init (SessionClass *klass)
887 GObjectClass *object_class = G_OBJECT_CLASS (klass);
889 klass->start = session_real_start;
890 klass->run = session_real_run;
891 klass->stop = session_real_stop;
892 object_class->finalize = session_finalize;
894 g_type_class_add_private (klass, sizeof (SessionPrivate));
896 signals[GOT_MESSAGES] =
897 g_signal_new ("got-messages",
898 G_TYPE_FROM_CLASS (klass),
900 G_STRUCT_OFFSET (SessionClass, got_messages),
905 signals[AUTHENTICATION_COMPLETE] =
906 g_signal_new ("authentication-complete",
907 G_TYPE_FROM_CLASS (klass),
909 G_STRUCT_OFFSET (SessionClass, authentication_complete),
915 g_signal_new ("stopped",
916 G_TYPE_FROM_CLASS (klass),
918 G_STRUCT_OFFSET (SessionClass, stopped),