]> rtime.felk.cvut.cz Git - sojka/lightdm.git/blobdiff - src/session.c
explicitly provide shared dir path to sessions
[sojka/lightdm.git] / src / session.c
index f88686e3e238a7457c98a1bede2c58e2f7c4e09f..f888ec7f662c4dfa6cc593cc2adc9ca48e4232ef 100644 (file)
@@ -26,6 +26,7 @@
 #include "console-kit.h"
 #include "login1.h"
 #include "guest-account.h"
+#include "shared-data-manager.h"
 
 enum {
     GOT_MESSAGES,
@@ -37,6 +38,9 @@ static guint signals[LAST_SIGNAL] = { 0 };
 
 struct SessionPrivate
 {
+    /* Session type */
+    gchar *session_type;
+
     /* Display server running on */
     DisplayServer *display_server;
 
@@ -81,16 +85,13 @@ struct SessionPrivate
     /* File to log to */
     gchar *log_filename;
 
-    /* Seat class */
-    gchar *class;
-
     /* tty this session is running on */
     gchar *tty;
 
     /* X display connected to */
     gchar *xdisplay;
-    XAuthority *xauthority;
-    gboolean xauth_use_system_location;
+    XAuthority *x_authority;
+    gboolean x_authority_use_system_location;
 
     /* Remote host this session is being controlled from */
     gchar *remote_host_name;
@@ -117,7 +118,32 @@ struct SessionPrivate
 /* Maximum length of a string to pass between daemon and session */
 #define MAX_STRING_LENGTH 65535
 
-G_DEFINE_TYPE (Session, session, G_TYPE_OBJECT);
+static void session_logger_iface_init (LoggerInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (Session, session, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (
+                             LOGGER_TYPE, session_logger_iface_init));
+
+Session *
+session_new (void)
+{
+    return g_object_new (SESSION_TYPE, NULL);
+}
+
+void
+session_set_session_type (Session *session, const gchar *session_type)
+{
+    g_return_if_fail (session != NULL);
+    g_free (session->priv->session_type);
+    session->priv->session_type = g_strdup (session_type);
+}
+
+const gchar *
+session_get_session_type (Session *session)
+{
+    g_return_val_if_fail (session != NULL, NULL);
+    return session->priv->session_type;
+}
 
 void
 session_set_pam_service (Session *session, const gchar *pam_service)
@@ -171,21 +197,16 @@ session_set_log_file (Session *session, const gchar *filename)
     session->priv->log_filename = g_strdup (filename);
 }
 
-void
-session_set_class (Session *session, const gchar *class)
-{
-    g_return_if_fail (session != NULL);
-    g_free (session->priv->class);
-    session->priv->class = g_strdup (class);
-}
-
 void
 session_set_display_server (Session *session, DisplayServer *display_server)
 {
     g_return_if_fail (session != NULL);
     g_return_if_fail (display_server != NULL);
     if (session->priv->display_server)
+    {
+        display_server_disconnect_session (session->priv->display_server, session);
         g_object_unref (session->priv->display_server);
+    }
     session->priv->display_server = g_object_ref (display_server);
 }
 
@@ -213,17 +234,17 @@ session_set_xdisplay (Session *session, const gchar *xdisplay)
 }
 
 void
-session_set_xauthority (Session *session, XAuthority *authority, gboolean use_system_location)
+session_set_x_authority (Session *session, XAuthority *authority, gboolean use_system_location)
 {
     g_return_if_fail (session != NULL);
-    if (session->priv->xauthority)
+    if (session->priv->x_authority)
     {
-        g_object_unref (session->priv->xauthority);
-        session->priv->xauthority = NULL;
+        g_object_unref (session->priv->x_authority);
+        session->priv->x_authority = NULL;
     }
     if (authority)
-        session->priv->xauthority = g_object_ref (authority);
-    session->priv->xauth_use_system_location = use_system_location;
+        session->priv->x_authority = g_object_ref (authority);
+    session->priv->x_authority_use_system_location = use_system_location;
 }
 
 void
@@ -234,11 +255,71 @@ session_set_remote_host_name (Session *session, const gchar *remote_host_name)
     session->priv->remote_host_name = g_strdup (remote_host_name);
 }
 
+static GList *
+find_env_entry (Session *session, const gchar *name)
+{
+    GList *link;
+
+    for (link = session->priv->env; link; link = link->next)
+    {
+        const gchar *entry = link->data;
+
+        if (g_str_has_prefix (entry, name) && entry[strlen (name)] == '=')
+            return link;
+    }
+
+    return NULL;
+}
+
 void
 session_set_env (Session *session, const gchar *name, const gchar *value)
 {
+    GList *link;
+    gchar *entry;
+
+    g_return_if_fail (session != NULL);
+    g_return_if_fail (value != NULL);
+
+    entry = g_strdup_printf ("%s=%s", name, value);
+
+    link = find_env_entry (session, name);
+    if (link)
+    {
+        g_free (link->data);
+        link->data = entry;
+    }
+    else
+        session->priv->env = g_list_append (session->priv->env, entry);
+}
+
+const gchar *
+session_get_env (Session *session, const gchar *name)
+{
+    GList *link;
+    gchar *entry;
+
+    link = find_env_entry (session, name);
+    if (!link)
+        return NULL;
+  
+    entry = link->data;
+
+    return entry + strlen (name) + 1;
+}
+
+void
+session_unset_env (Session *session, const gchar *name)
+{
+    GList *link;
+
     g_return_if_fail (session != NULL);
-    session->priv->env = g_list_append (session->priv->env, g_strdup_printf ("%s=%s", name, value));
+  
+    link = find_env_entry (session, name);
+    if (!link)
+        return;
+
+    g_free (link->data);
+    session->priv->env = g_list_remove_link (session->priv->env, link);
 }
 
 void
@@ -266,7 +347,7 @@ static void
 write_data (Session *session, const void *buf, size_t count)
 {
     if (write (session->priv->to_child_input, buf, count) != count)
-        g_warning ("Error writing to session: %s", strerror (errno));
+        l_warning (session, "Error writing to session: %s", strerror (errno));
 }
 
 static void
@@ -281,27 +362,27 @@ write_string (Session *session, const char *value)
 }
 
 static void
-write_xauth (Session *session, XAuthority *xauthority)
+write_xauth (Session *session, XAuthority *x_authority)
 {
     guint16 family;
     gsize length;
 
-    if (!xauthority)
+    if (!x_authority)
     {
         write_string (session, NULL);
         return;
     }
 
-    write_string (session, xauth_get_authorization_name (session->priv->xauthority));
-    family = xauth_get_family (session->priv->xauthority);
+    write_string (session, x_authority_get_authorization_name (session->priv->x_authority));
+    family = x_authority_get_family (session->priv->x_authority);
     write_data (session, &family, sizeof (family));
-    length = xauth_get_address_length (session->priv->xauthority);
+    length = x_authority_get_address_length (session->priv->x_authority);
     write_data (session, &length, sizeof (length));
-    write_data (session, xauth_get_address (session->priv->xauthority), length);
-    write_string (session, xauth_get_number (session->priv->xauthority));
-    length = xauth_get_authorization_data_length (session->priv->xauthority);
+    write_data (session, x_authority_get_address (session->priv->x_authority), length);
+    write_string (session, x_authority_get_number (session->priv->x_authority));
+    length = x_authority_get_authorization_data_length (session->priv->x_authority);
     write_data (session, &length, sizeof (length));
-    write_data (session, xauth_get_authorization_data (session->priv->xauthority), length);
+    write_data (session, x_authority_get_authorization_data (session->priv->x_authority), length);
 }
 
 static ssize_t
@@ -310,7 +391,7 @@ read_from_child (Session *session, void *buf, size_t count)
     ssize_t n_read;
     n_read = read (session->priv->from_child_output, buf, count);
     if (n_read < 0)
-        g_warning ("Error reading from session: %s", strerror (errno));
+        l_warning (session, "Error reading from session: %s", strerror (errno));
     return n_read;
 }
 
@@ -326,7 +407,7 @@ read_string_from_child (Session *session)
         return NULL;
     if (length > MAX_STRING_LENGTH)
     {
-        g_warning ("Invalid string length %d from child", length);
+        l_warning (session, "Invalid string length %d from child", length);
         return NULL;
     }
 
@@ -342,17 +423,20 @@ session_watch_cb (GPid pid, gint status, gpointer data)
 {
     Session *session = data;
 
-    session->priv->pid = 0;
+    session->priv->child_watch = 0;
 
     if (WIFEXITED (status))
-        g_debug ("Session %d exited with return value %d", pid, WEXITSTATUS (status));
+        l_debug (session, "Exited with return value %d", WEXITSTATUS (status));
     else if (WIFSIGNALED (status))
-        g_debug ("Session %d terminated with signal %d", pid, WTERMSIG (status));
+        l_debug (session, "Terminated with signal %d", WTERMSIG (status));
+
+    /* do this as late as possible for log messages prefix */
+    session->priv->pid = 0;
 
     /* If failed during authentication then report this as an authentication failure */
     if (session->priv->authentication_started && !session->priv->authentication_complete)
     {
-        g_debug ("Session %d failed during authentication", pid);
+        l_debug (session, "Failed during authentication");
         session->priv->authentication_complete = TRUE;
         session->priv->authentication_result = PAM_CONV_ERR;
         g_free (session->priv->authentication_result_string);
@@ -401,7 +485,7 @@ from_child_cb (GIOChannel *source, GIOCondition condition, gpointer data)
     /* Check if authentication completed */
     n_read = read_from_child (session, &auth_complete, sizeof (auth_complete));
     if (n_read < 0)
-        g_debug ("Error reading from child: %s", strerror (errno));
+        l_debug (session, "Error reading from child: %s", strerror (errno));
     if (n_read <= 0)
     {
         session->priv->from_child_watch = 0;
@@ -415,7 +499,7 @@ from_child_cb (GIOChannel *source, GIOCondition condition, gpointer data)
         g_free (session->priv->authentication_result_string);
         session->priv->authentication_result_string = read_string_from_child (session);
 
-        g_debug ("Session %d authentication complete with return value %d: %s", session->priv->pid, session->priv->authentication_result, session->priv->authentication_result_string);
+        l_debug (session, "Authentication complete with return value %d: %s", session->priv->authentication_result, session->priv->authentication_result_string);
 
         /* No longer expect any more messages */
         session->priv->from_child_watch = 0;
@@ -438,7 +522,7 @@ from_child_cb (GIOChannel *source, GIOCondition condition, gpointer data)
             m->msg = read_string_from_child (session);
         }
 
-        g_debug ("Session %d got %d message(s) from PAM", session->priv->pid, session->priv->messages_length);
+        l_debug (session, "Got %d message(s) from PAM", session->priv->messages_length);
 
         g_signal_emit (G_OBJECT (session), signals[GOT_MESSAGES], 0);
     }
@@ -449,7 +533,7 @@ from_child_cb (GIOChannel *source, GIOCondition condition, gpointer data)
 gboolean
 session_start (Session *session)
 {
-    g_return_val_if_fail (session->priv->display_server != NULL, FALSE);
+    g_return_val_if_fail (session != NULL, FALSE);
     return SESSION_GET_CLASS (session)->start (session);
 }
 
@@ -466,9 +550,11 @@ session_real_start (Session *session)
     int to_child_pipe[2], from_child_pipe[2];
     int to_child_output, from_child_input;
 
-    g_return_val_if_fail (session != NULL, FALSE);
     g_return_val_if_fail (session->priv->pid == 0, FALSE);
 
+    if (session->priv->display_server)
+        display_server_connect_session (session->priv->display_server, session);
+
     /* Create pipes to talk to the child */
     if (pipe (to_child_pipe) < 0 || pipe (from_child_pipe) < 0)
     {
@@ -536,13 +622,13 @@ session_real_start (Session *session)
     write_string (session, session->priv->username);
     write_data (session, &session->priv->do_authenticate, sizeof (session->priv->do_authenticate));
     write_data (session, &session->priv->is_interactive, sizeof (session->priv->is_interactive));
-    write_string (session, session->priv->class);
+    write_string (session, NULL); /* Used to be class, now we just use the environment variable */
     write_string (session, session->priv->tty);
     write_string (session, session->priv->remote_host_name);
     write_string (session, session->priv->xdisplay);
-    write_xauth (session, session->priv->xauthority);
+    write_xauth (session, session->priv->x_authority);
 
-    g_debug ("Started session %d with service '%s', username '%s'", session->priv->pid, session->priv->pam_service, session->priv->username);
+    l_debug (session, "Started with service '%s', username '%s'", session->priv->pam_service, session->priv->username);
 
     return TRUE;
 }
@@ -639,7 +725,7 @@ static void
 session_real_run (Session *session)
 {
     gsize i, argc;
-    gchar *command, *xauth_filename;
+    gchar *command, *x_authority_filename;
     GList *link;
 
     g_return_if_fail (session != NULL);
@@ -648,14 +734,16 @@ session_real_run (Session *session)
     g_return_if_fail (session->priv->argv != NULL);
     g_return_if_fail (session->priv->pid != 0);
 
+    display_server_connect_session (session->priv->display_server, session);
+
     session->priv->command_run = TRUE;
 
     command = g_strjoinv (" ", session->priv->argv);
-    g_debug ("Session %d running command %s", session->priv->pid, command);
+    l_debug (session, "Running command %s", command);
     g_free (command);
 
     /* Create authority location */
-    if (session->priv->xauth_use_system_location)
+    if (session->priv->x_authority_use_system_location)
     {
         gchar *run_dir, *dir;
 
@@ -664,25 +752,39 @@ session_real_run (Session *session)
         g_free (run_dir);
 
         if (g_mkdir_with_parents (dir, S_IRWXU) < 0)
-            g_warning ("Failed to set create system authority dir %s: %s", dir, strerror (errno));          
+            l_warning (session, "Failed to set create system authority dir %s: %s", dir, strerror (errno));
         if (getuid () == 0)
         {
             if (chown (dir, user_get_uid (session_get_user (session)), user_get_gid (session_get_user (session))) < 0)
-                g_warning ("Failed to set ownership of user authority dir: %s", strerror (errno));
+                l_warning (session, "Failed to set ownership of user authority dir: %s", strerror (errno));
         }
 
-        xauth_filename = g_build_filename (dir, "xauthority", NULL);
+        x_authority_filename = g_build_filename (dir, "xauthority", NULL);
         g_free (dir);
     }
     else
-        xauth_filename = g_build_filename (user_get_home_directory (session_get_user (session)), ".Xauthority", NULL);
+        x_authority_filename = g_build_filename (user_get_home_directory (session_get_user (session)), ".Xauthority", NULL);
 
+    /* Make sure shared user directory for this user exists */
+    if (!session->priv->remote_host_name)
+    {
+        gchar *data_dir = shared_data_manager_ensure_user_dir (shared_data_manager_get_instance (), session->priv->username);
+        l_debug(session, "MIKE set XDG_GREETER_DATA_DIR=%s from user %s", data_dir, session->priv->username);
+        if (data_dir)
+        {
+            session_set_env (session, "XDG_GREETER_DATA_DIR", data_dir);
+            g_free (data_dir);
+        }
+    }
+
+    if (session->priv->log_filename)
+        l_debug (session, "Logging to %s", session->priv->log_filename);
     write_string (session, session->priv->log_filename);
     write_string (session, session->priv->tty);
-    write_string (session, xauth_filename);
-    g_free (xauth_filename);
+    write_string (session, x_authority_filename);
+    g_free (x_authority_filename);
     write_string (session, session->priv->xdisplay);
-    write_xauth (session, session->priv->xauthority);
+    write_xauth (session, session->priv->x_authority);
     argc = g_list_length (session->priv->env);
     write_data (session, &argc, sizeof (argc));
     for (link = session->priv->env; link; link = link->next)
@@ -704,9 +806,9 @@ session_lock (Session *session)
     g_return_if_fail (session != NULL);
     if (getuid () == 0)
     {
-        if (login1_is_running ())
+        if (session->priv->login1_session)
             login1_lock_session (session->priv->login1_session);
-        if (!session->priv->login1_session)
+        else if (session->priv->console_kit_cookie)
             ck_lock_session (session->priv->console_kit_cookie);
     }
 }
@@ -717,9 +819,9 @@ session_unlock (Session *session)
     g_return_if_fail (session != NULL);
     if (getuid () == 0)
     {
-        if (login1_is_running ())
+        if (session->priv->login1_session)
             login1_unlock_session (session->priv->login1_session);
-        if (!session->priv->login1_session)
+        else if (session->priv->console_kit_cookie)
             ck_unlock_session (session->priv->console_kit_cookie);
     }
 }
@@ -733,9 +835,17 @@ session_stop (Session *session)
         return;
     session->priv->stopping = TRUE;
 
+    return SESSION_GET_CLASS (session)->stop (session);
+}
+
+static void
+session_real_stop (Session *session)
+{
+    g_return_if_fail (session != NULL);
+
     if (session->priv->pid > 0)
     {
-        g_debug ("Session %d: Sending SIGTERM", session->priv->pid);
+        l_debug (session, "Sending SIGTERM");
         kill (session->priv->pid, SIGTERM);
         // FIXME: Handle timeout
     }
@@ -754,6 +864,7 @@ static void
 session_init (Session *session)
 {
     session->priv = G_TYPE_INSTANCE_GET_PRIVATE (session, SESSION_TYPE, SessionPrivate);
+    session->priv->log_filename = g_strdup (".xsession-errors");
 }
 
 static void
@@ -762,6 +873,7 @@ session_finalize (GObject *object)
     Session *self = SESSION (object);
     int i;
 
+    g_free (self->priv->session_type);
     if (self->priv->display_server)
         g_object_unref (self->priv->display_server);
     if (self->priv->pid)
@@ -781,11 +893,10 @@ session_finalize (GObject *object)
     g_free (self->priv->messages);
     g_free (self->priv->authentication_result_string);
     g_free (self->priv->log_filename);
-    g_free (self->priv->class);
     g_free (self->priv->tty);
     g_free (self->priv->xdisplay);
-    if (self->priv->xauthority)
-        g_object_unref (self->priv->xauthority);
+    if (self->priv->x_authority)
+        g_object_unref (self->priv->x_authority);
     g_free (self->priv->remote_host_name);
     g_free (self->priv->login1_session);
     g_free (self->priv->console_kit_cookie);
@@ -802,6 +913,7 @@ session_class_init (SessionClass *klass)
 
     klass->start = session_real_start;
     klass->run = session_real_run;
+    klass->stop = session_real_stop;
     object_class->finalize = session_finalize;
 
     g_type_class_add_private (klass, sizeof (SessionPrivate));
@@ -812,7 +924,7 @@ session_class_init (SessionClass *klass)
                       G_SIGNAL_RUN_LAST,
                       G_STRUCT_OFFSET (SessionClass, got_messages),
                       NULL, NULL,
-                      g_cclosure_marshal_VOID__VOID,
+                      NULL,
                       G_TYPE_NONE, 0);
 
     signals[AUTHENTICATION_COMPLETE] =
@@ -821,7 +933,7 @@ session_class_init (SessionClass *klass)
                       G_SIGNAL_RUN_LAST,
                       G_STRUCT_OFFSET (SessionClass, authentication_complete),
                       NULL, NULL,
-                      g_cclosure_marshal_VOID__VOID,
+                      NULL,
                       G_TYPE_NONE, 0);
 
     signals[STOPPED] =
@@ -830,6 +942,22 @@ session_class_init (SessionClass *klass)
                       G_SIGNAL_RUN_LAST,
                       G_STRUCT_OFFSET (SessionClass, stopped),
                       NULL, NULL,
-                      g_cclosure_marshal_VOID__VOID,
+                      NULL,
                       G_TYPE_NONE, 0);
 }
+
+static gint
+session_real_logprefix (Logger *self, gchar *buf, gulong buflen)
+{
+    Session *session = SESSION (self);
+    if (session->priv->pid != 0)
+        return g_snprintf (buf, buflen, "Session pid=%d: ", session->priv->pid);
+    else
+        return g_snprintf (buf, buflen, "Session: ");
+}
+
+static void
+session_logger_iface_init (LoggerInterface *iface)
+{
+    iface->logprefix = &session_real_logprefix;
+}