#include "console-kit.h"
#include "login1.h"
#include "guest-account.h"
+#include "shared-data-manager.h"
enum {
GOT_MESSAGES,
struct SessionPrivate
{
+ /* Session type */
+ gchar *session_type;
+
/* Display server running on */
DisplayServer *display_server;
/* User object that matches the current username */
User *user;
+ /* PAM service to use */
+ gchar *pam_service;
+
+ /* TRUE if should run PAM authentication phase */
+ gboolean do_authenticate;
+
+ /* TRUE if can handle PAM prompts */
+ gboolean is_interactive;
+
/* Messages being requested by PAM */
int messages_length;
struct pam_message *messages;
/* 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;
/* Environment to set in child */
GList *env;
+
+ /* Command to run in child */
+ gchar **argv;
+
+ /* True if have run command */
+ gboolean command_run;
+
+ /* TRUE if stopping this session */
+ gboolean stopping;
};
/* 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_log_file (Session *session, const gchar *filename)
+session_set_session_type (Session *session, const gchar *session_type)
{
g_return_if_fail (session != NULL);
- g_free (session->priv->log_filename);
- session->priv->log_filename = g_strdup (filename);
+ 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_class (Session *session, const gchar *class)
+session_set_pam_service (Session *session, const gchar *pam_service)
{
g_return_if_fail (session != NULL);
- g_free (session->priv->class);
- session->priv->class = g_strdup (class);
+ g_free (session->priv->pam_service);
+ session->priv->pam_service = g_strdup (pam_service);
}
-static void
-session_real_set_display_server (Session *session, DisplayServer *display_server)
+void
+session_set_username (Session *session, const gchar *username)
{
- if (session->priv->display_server)
- g_object_unref (session->priv->display_server);
- session->priv->display_server = g_object_ref (display_server);
+ g_return_if_fail (session != NULL);
+ g_free (session->priv->username);
+ session->priv->username = g_strdup (username);
+}
+
+void
+session_set_do_authenticate (Session *session, gboolean do_authenticate)
+{
+ g_return_if_fail (session != NULL);
+ session->priv->do_authenticate = do_authenticate;
+}
+
+void
+session_set_is_interactive (Session *session, gboolean is_interactive)
+{
+ g_return_if_fail (session != NULL);
+ session->priv->is_interactive = is_interactive;
+}
+
+void
+session_set_is_guest (Session *session, gboolean is_guest)
+{
+ g_return_if_fail (session != NULL);
+ session->priv->is_guest = is_guest;
+}
+
+gboolean
+session_get_is_guest (Session *session)
+{
+ g_return_val_if_fail (session != NULL, FALSE);
+ return session->priv->is_guest;
+}
+
+void
+session_set_log_file (Session *session, const gchar *filename)
+{
+ g_return_if_fail (session != NULL);
+ g_free (session->priv->log_filename);
+ session->priv->log_filename = g_strdup (filename);
}
void
{
g_return_if_fail (session != NULL);
g_return_if_fail (display_server != NULL);
- SESSION_GET_CLASS (session)->set_display_server (session, display_server);
+ 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);
+}
+
+DisplayServer *
+session_get_display_server (Session *session)
+{
+ g_return_val_if_fail (session != NULL, NULL);
+ return session->priv->display_server;
}
void
}
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)
- g_object_unref (session->priv->xauthority);
- session->priv->xauthority = g_object_ref (authority);
- session->priv->xauth_use_system_location = use_system_location;
+ if (session->priv->x_authority)
+ {
+ g_object_unref (session->priv->x_authority);
+ session->priv->x_authority = NULL;
+ }
+ if (authority)
+ session->priv->x_authority = g_object_ref (authority);
+ session->priv->x_authority_use_system_location = use_system_location;
}
void
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);
- session->priv->env = g_list_append (session->priv->env, g_strdup_printf ("%s=%s", name, value));
+ 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);
+
+ 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
+session_set_argv (Session *session, gchar **argv)
+{
+ g_return_if_fail (session != NULL);
+ session->priv->argv = g_strdupv (argv);
}
User *
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
}
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
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;
}
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;
}
{
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);
/* 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;
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;
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);
}
}
gboolean
-session_start (Session *session, const gchar *service, const gchar *username, gboolean do_authenticate, gboolean is_interactive, gboolean is_guest)
+session_start (Session *session)
+{
+ g_return_val_if_fail (session != NULL, FALSE);
+ return SESSION_GET_CLASS (session)->start (session);
+}
+
+gboolean
+session_get_is_started (Session *session)
+{
+ return session->priv->pid != 0;
+}
+
+static gboolean
+session_real_start (Session *session)
{
int version;
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 (service != 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)
{
fcntl (session->priv->from_child_output, F_SETFD, FD_CLOEXEC);
/* Create the guest account if it is one */
- session->priv->is_guest = is_guest;
- if (is_guest && username == NULL)
- username = guest_account_setup ();
-
- /* Remember what username we started with - it will be updated by PAM during authentication */
- session->priv->username = g_strdup (username);
+ if (session->priv->is_guest && session->priv->username == NULL)
+ {
+ session->priv->username = guest_account_setup ();
+ if (!session->priv->username)
+ return FALSE;
+ }
/* Run the child */
session->priv->pid = fork ();
write_data (session, &version, sizeof (version));
/* Send configuration */
- write_string (session, service);
- write_string (session, username);
- write_data (session, &do_authenticate, sizeof (do_authenticate));
- write_data (session, &is_interactive, sizeof (is_interactive));
- write_string (session, session->priv->class);
+ write_string (session, session->priv->pam_service);
+ 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, 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, service, username);
+ l_debug (session, "Started with service '%s', username '%s'", session->priv->pam_service, session->priv->username);
return TRUE;
}
}
void
-session_run (Session *session, gchar **argv)
+session_run (Session *session)
+{
+ g_return_if_fail (session->priv->display_server != NULL);
+ return SESSION_GET_CLASS (session)->run (session);
+}
+
+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);
+ g_return_if_fail (!session->priv->command_run);
g_return_if_fail (session_get_is_authenticated (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 (" ", argv);
- g_debug ("Session %d running command %s", session->priv->pid, command);
+ command = g_strjoinv (" ", session->priv->argv);
+ 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;
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)
write_string (session, (gchar *) link->data);
- argc = g_strv_length (argv);
+ argc = g_strv_length (session->priv->argv);
write_data (session, &argc, sizeof (argc));
for (i = 0; i < argc; i++)
- write_string (session, argv[i]);
+ write_string (session, session->priv->argv[i]);
if (login1_is_running ())
- session->priv->login1_session = read_string_from_child (session);
+ session->priv->login1_session = read_string_from_child (session);
if (!session->priv->login1_session)
- session->priv->console_kit_cookie = read_string_from_child (session);
+ session->priv->console_kit_cookie = read_string_from_child (session);
}
void
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);
}
}
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);
}
}
{
g_return_if_fail (session != NULL);
+ if (session->priv->stopping)
+ 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
}
+ else
+ g_signal_emit (G_OBJECT (session), signals[STOPPED], 0);
}
gboolean
-session_get_is_stopped (Session *session)
+session_get_is_stopping (Session *session)
{
- g_return_val_if_fail (session != NULL, TRUE);
- return session->priv->pid == 0;
+ g_return_val_if_fail (session != NULL, FALSE);
+ return session->priv->stopping;
}
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
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)
g_free (self->priv->username);
if (self->priv->user)
g_object_unref (self->priv->user);
+ g_free (self->priv->pam_service);
for (i = 0; i < self->priv->messages_length; i++)
g_free ((char *) self->priv->messages[i].msg);
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);
g_list_free_full (self->priv->env, g_free);
+ g_strfreev (self->priv->argv);
G_OBJECT_CLASS (session_parent_class)->finalize (object);
}
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
- klass->set_display_server = session_real_set_display_server;
+ 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));
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;
+}