summaryrefslogtreecommitdiff
path: root/daemon/gdm-session.c
diff options
context:
space:
mode:
Diffstat (limited to 'daemon/gdm-session.c')
-rw-r--r--daemon/gdm-session.c4183
1 files changed, 809 insertions, 3374 deletions
diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c
index 996c4067..bafc03ab 100644
--- a/daemon/gdm-session.c
+++ b/daemon/gdm-session.c
@@ -3,6 +3,7 @@
* session.c - authenticates and authorizes users with system
*
* Copyright (C) 2006 Ray Strode <rstrode@redhat.com>
+ * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -32,8 +33,7 @@
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
-#include <grp.h>
-#include <pwd.h>
+
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
@@ -44,14 +44,20 @@
#include <unistd.h>
#include <utmp.h>
-#include <security/pam_appl.h>
-
#include <glib.h>
#include <glib/gi18n.h>
#include <glib/gstdio.h>
#include <glib-object.h>
+#define DBUS_API_SUBJECT_TO_CHANGE
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
#include "gdm-session.h"
+#include "gdm-session-worker-job.h"
+
+#define GDM_SESSION_DBUS_PATH "/org/gnome/DisplayManager/Session"
+#define GDM_SESSION_DBUS_INTERFACE "org.gnome.DisplayManager.Session"
+
#ifndef GDM_BAD_SESSION_RECORDS_FILE
#define GDM_BAD_SESSION_RECORDS_FILE "/var/log/btmp"
@@ -89,59 +95,6 @@
#define GDM_MAX_LOG_FILENAME_SIZE 1024
#endif
-#ifndef GDM_PASSWD_AUXILLARY_BUFFER_SIZE
-#define GDM_PASSWD_AUXILLARY_BUFFER_SIZE 1024
-#endif
-
-#ifndef GDM_SESSION_MESSAGE_SENTINAL
-#define GDM_SESSION_MESSAGE_SENTINAL "sEnTInAL"
-#endif
-
-#ifndef GDM_SESSION_WORKER_MESSAGE_SENTINAL
-#define GDM_SESSION_WORKER_MESSAGE_SENTINAL "WoRkeR sEnTInAL"
-#endif
-
-#ifndef GDM_SESSION_DEFAULT_PATH
-#define GDM_SESSION_DEFAULT_PATH "/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin"
-#endif
-
-#ifndef GDM_SESSION_ROOT_UID
-#define GDM_SESSION_ROOT_UID 0
-#endif
-
-typedef struct _GdmSessionMessage GdmSessionMessage;
-typedef struct _GdmSessionVerificationMessage GdmSessionVerificationMessage;
-typedef struct _GdmSessionStartProgramMessage GdmSessionStartProgramMessage;
-typedef struct _GdmSessionSetEnvironmentVariableMessage GdmSessionSetEnvironmentVariableMessage;
-typedef struct _GdmSessionInfoReplyMessage GdmSessionInfoReplyMessage;
-typedef struct _GdmSessionSecretInfoReplyMessage GdmSessionSecretInfoReplyMessage;
-typedef struct _GdmSessionWorker GdmSessionWorker;
-typedef struct _GdmSessionWorkerMessage GdmSessionWorkerMessage;
-typedef struct _GdmSessionWorkerVerifiedMessage GdmSessionWorkerVerifiedMessage;
-typedef struct _GdmSessionWorkerVerificationFailedMessage GdmSessionWorkerVerificationFailedMessage;
-typedef struct _GdmSessionWorkerUsernameChangedMessage GdmSessionWorkerUsernameChangedMessage;
-typedef struct _GdmSessionWorkerInfoRequestMessage GdmSessionWorkerInfoRequestMessage;
-typedef struct _GdmSessionWorkerSecretInfoRequestMessage GdmSessionWorkerSecretInfoRequestMessage;
-typedef struct _GdmSessionWorkerInfoMessage GdmSessionWorkerInfoMessage;
-typedef struct _GdmSessionWorkerProblemMessage GdmSessionWorkerProblemMessage;
-typedef struct _GdmSessionWorkerSessionStartedMessage GdmSessionWorkerSessionStartedMessage;
-typedef struct _GdmSessionWorkerSessionStartupFailedMessage GdmSessionWorkerSessionStartupFailedMessage;
-typedef struct _GdmSessionWorkerSessionExitedMessage GdmSessionWorkerSessionExitedMessage;
-typedef struct _GdmSessionWorkerSessionDiedMessage GdmSessionWorkerSessionDiedMessage;
-
-typedef int (* GdmSessionWorkerPamNewMessagesFunc) (int,
- const struct pam_message **,
- struct pam_response **,
- gpointer);
-typedef enum _GdmSessionMessageType {
- GDM_SESSION_MESSAGE_TYPE_INVALID = 0,
- GDM_SESSION_MESSAGE_TYPE_VERIFICATION = 0xc001deed,
- GDM_SESSION_MESSAGE_TYPE_START_PROGRAM,
- GDM_SESSION_MESSAGE_TYPE_SET_ENVIRONMENT_VARIABLE,
- GDM_SESSION_MESSAGE_TYPE_NEW_LOG_FILENAME,
- GDM_SESSION_MESSAGE_TYPE_INFO_REPLY,
- GDM_SESSION_MESSAGE_TYPE_SECRET_INFO_REPLY
-} GdmSessionMessageType;
typedef enum _GdmSessionRecordType {
GDM_SESSION_RECORD_TYPE_LOGIN,
@@ -149,241 +102,28 @@ typedef enum _GdmSessionRecordType {
GDM_SESSION_RECORD_TYPE_LOGOUT,
} GdmSessionRecordType;
-typedef enum _GdmSessionWorkerMessageType {
- GDM_SESSION_WORKER_MESSAGE_TYPE_INVALID = 0,
- GDM_SESSION_WORKER_MESSAGE_TYPE_VERIFIED = 0xdeadbeef,
- GDM_SESSION_WORKER_MESSAGE_TYPE_VERIFICATION_FAILED,
- GDM_SESSION_WORKER_MESSAGE_TYPE_USERNAME_CHANGED,
- GDM_SESSION_WORKER_MESSAGE_TYPE_INFO_REQUEST,
- GDM_SESSION_WORKER_MESSAGE_TYPE_SECRET_INFO_REQUEST,
- GDM_SESSION_WORKER_MESSAGE_TYPE_INFO,
- GDM_SESSION_WORKER_MESSAGE_TYPE_PROBLEM,
- GDM_SESSION_WORKER_MESSAGE_TYPE_SESSION_STARTED,
- GDM_SESSION_WORKER_MESSAGE_TYPE_SESSION_STARTUP_FAILED,
- GDM_SESSION_WORKER_MESSAGE_TYPE_SESSION_EXITED,
- GDM_SESSION_WORKER_MESSAGE_TYPE_SESSION_DIED,
-} GdmSessionWorkerMessageType;
-
struct _GdmSessionPrivate
{
- GPid pid;
-
- char *service_name;
- char **arguments;
- char *username;
- char *hostname;
- char *console_name;
-
- int standard_output_fd;
- int standard_error_fd;
-
- int worker_message_pipe_fd;
- GSource *worker_message_pipe_source;
-
- GMainContext *context;
-
- GPid worker_pid;
- GSource *child_watch_source;
-
- GdmSessionMessageType next_expected_message;
-
- /* variable is only alive briefly to store user
- * responses set in callbacks to authentication queries
- */
- char *query_answer;
-
- guint32 is_verified : 1;
- guint32 is_running : 1;
-};
-
-struct _GdmSessionMessage
-{
- GdmSessionMessageType type;
- gsize size;
-};
-
-struct _GdmSessionVerificationMessage
-{
- GdmSessionMessage header;
-
- char service_name[GDM_MAX_SERVICE_NAME_SIZE];
- char console_name[GDM_MAX_CONSOLE_NAME_SIZE];
- char hostname[GDM_MAX_HOSTNAME_SIZE];
-
- int standard_output_fd;
- int standard_error_fd;
-
- guint32 hostname_is_provided : 1;
-
- gssize username_size;
- char username[0];
-};
-
-struct _GdmSessionStartProgramMessage
-{
- GdmSessionMessage header;
-
- gsize arguments_size;
- char arguments[0];
-};
-
-struct _GdmSessionSetEnvironmentVariableMessage
-{
- GdmSessionMessage header;
-
- gsize environment_variable_size;
- char environment_variable[0];
-};
-
-struct _GdmSessionInfoReplyMessage
-{
- GdmSessionMessage header;
-
- gssize answer_size;
- char answer[0];
-};
-
-struct _GdmSessionSecretInfoReplyMessage
-{
- GdmSessionMessage header;
-
- gssize answer_size;
- char answer[0];
-};
-
-struct _GdmSessionWorker
-{
- GMainLoop *event_loop;
- int exit_code;
-
- pam_handle_t *pam_handle;
-
- int message_pipe_fd;
- GSource *message_pipe_source;
-
- GSList *inherited_fd_list;
-
- GPid child_pid;
- GSource *child_watch_source;
-
- char *username;
- char **arguments;
-
- GHashTable *environment;
-
- int standard_output_fd;
- int standard_error_fd;
-
- guint32 credentials_are_established : 1;
- guint32 is_running : 1;
-};
-
-struct _GdmSessionWorkerMessage
-{
- GdmSessionWorkerMessageType type;
- gsize size;
-};
-
-struct _GdmSessionWorkerInfoRequestMessage
-{
- GdmSessionWorkerMessage header;
-
- gssize question_size;
- char question[0];
-};
-
-struct _GdmSessionWorkerUsernameChangedMessage
-{
- GdmSessionWorkerMessage header;
-
- gssize username_size;
- char username[0];
-};
-
-struct _GdmSessionWorkerSecretInfoRequestMessage
-{
- GdmSessionWorkerMessage header;
+ GdmSessionWorkerJob *job;
+ GPid session_pid;
- gssize question_size;
- char question[0];
-};
-
-struct _GdmSessionWorkerInfoMessage
-{
- GdmSessionWorkerMessage header;
-
- gssize info_size;
- char info[0];
-};
-
-struct _GdmSessionWorkerProblemMessage
-{
- GdmSessionWorkerMessage header;
-
- gssize problem_size;
- char problem[0];
-};
-
-struct _GdmSessionWorkerSessionStartedMessage
-{
- GdmSessionWorkerMessage header;
- GPid pid;
-};
-
-struct _GdmSessionWorkerSessionStartupFailedMessage
-{
- GdmSessionWorkerMessage header;
- GQuark error_domain;
- int error_code;
-
- gssize error_message_size;
- char error_message[0];
-};
-
-struct _GdmSessionWorkerSessionExitedMessage
-{
- GdmSessionWorkerMessage header;
-
- int exit_code;
-};
+ char *service_name;
+ char *username;
+ char *hostname;
+ char *console_name;
-struct _GdmSessionWorkerSessionDiedMessage
-{
- GdmSessionWorkerMessage header;
+ DBusMessage *message_pending_reply;
- int signal_number;
-};
-
-struct _GdmSessionWorkerVerifiedMessage
-{
- GdmSessionWorkerMessage header;
-};
+ GHashTable *environment;
-struct _GdmSessionWorkerVerificationFailedMessage
-{
- GdmSessionWorkerMessage header;
- GQuark error_domain;
- int error_code;
+ DBusServer *server;
+ char *server_address;
+ DBusConnection *worker_connection;
- gssize error_message_size;
- char error_message[0];
+ guint32 is_verified : 1;
+ guint32 is_running : 1;
};
-static GdmSessionWorkerMessage *gdm_session_worker_verified_message_new (void);
-static GdmSessionWorkerMessage *gdm_session_worker_verification_failed_message_new (GError *error);
-static GdmSessionWorkerMessage *gdm_session_worker_info_request_message_new (const char *question);
-static GdmSessionWorkerMessage *gdm_session_worker_username_changed_message_new (const char *new_username);
-static GdmSessionWorkerMessage *gdm_session_worker_secret_info_request_message_new (const char *question);
-static GdmSessionWorkerMessage *gdm_session_worker_info_message_new (const char *info);
-static GdmSessionWorkerMessage *gdm_session_worker_problem_message_new (const char *problem);
-static GdmSessionWorkerMessage *gdm_session_worker_session_started_message_new (GPid pid);
-static GdmSessionWorkerMessage *gdm_session_worker_session_exited_message_new (int exit_code);
-static GdmSessionWorkerMessage *gdm_session_worker_session_died_message_new (int signal_number);
-static void gdm_session_worker_message_free (GdmSessionWorkerMessage *message);
-
-static gboolean gdm_session_worker_process_asynchronous_message (GdmSessionWorker *worker,
- GdmSessionMessage *message);
-
enum {
USER_VERIFIED = 0,
USER_VERIFICATION_ERROR,
@@ -395,6 +135,8 @@ enum {
SESSION_STARTUP_ERROR,
SESSION_EXITED,
SESSION_DIED,
+ OPENED,
+ CLOSED,
LAST_SIGNAL
};
@@ -413,6 +155,74 @@ gdm_session_error_quark (void)
return error_quark;
}
+static gboolean
+send_dbus_message (DBusConnection *connection,
+ DBusMessage *message)
+{
+ gboolean is_connected;
+ gboolean sent;
+
+ g_return_val_if_fail (message != NULL, FALSE);
+
+ if (connection == NULL) {
+ g_warning ("There is no valid connection");
+ return FALSE;
+ }
+
+ is_connected = dbus_connection_get_is_connected (connection);
+ if (! is_connected) {
+ g_warning ("Not connected!");
+ return FALSE;
+ }
+
+ sent = dbus_connection_send (connection, message, NULL);
+
+ return sent;
+}
+
+static void
+send_dbus_string_signal (GdmSession *session,
+ const char *name,
+ const char *text)
+{
+ DBusMessage *message;
+ DBusMessageIter iter;
+
+ g_return_if_fail (session != NULL);
+
+ message = dbus_message_new_signal (GDM_SESSION_DBUS_PATH,
+ GDM_SESSION_DBUS_INTERFACE,
+ name);
+
+ dbus_message_iter_init_append (message, &iter);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &text);
+
+ if (! send_dbus_message (session->priv->worker_connection, message)) {
+ g_debug ("Could not send %s signal", name);
+ }
+
+ dbus_message_unref (message);
+}
+
+static void
+send_dbus_void_signal (GdmSession *session,
+ const char *name)
+{
+ DBusMessage *message;
+
+ g_return_if_fail (session != NULL);
+
+ message = dbus_message_new_signal (GDM_SESSION_DBUS_PATH,
+ GDM_SESSION_DBUS_INTERFACE,
+ name);
+
+ if (! send_dbus_message (session->priv->worker_connection, message)) {
+ g_debug ("Could not send %s signal", name);
+ }
+
+ dbus_message_unref (message);
+}
+
static void
gdm_session_write_record (GdmSession *session,
GdmSessionRecordType record_type)
@@ -500,10 +310,9 @@ gdm_session_write_record (GdmSession *session,
session_record.ut_type = USER_PROCESS;
g_debug ("using type USER_PROCESS");
- if (session->priv->pid != 0)
- session_record.ut_pid = session->priv->pid;
- else
- session_record.ut_pid = session->priv->worker_pid;
+ if (session->priv->session_pid != 0) {
+ session_record.ut_pid = session->priv->session_pid;
+ }
g_debug ("using pid %d", (int) session_record.ut_pid);
@@ -565,6 +374,27 @@ gdm_session_class_install_signals (GdmSessionClass *session_class)
object_class = G_OBJECT_CLASS (session_class);
+ gdm_session_signals[OPENED] =
+ g_signal_new ("opened",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GdmSessionClass, opened),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+ gdm_session_signals[CLOSED] =
+ g_signal_new ("closed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GdmSessionClass, closed),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+ session_class->user_verified = NULL;
gdm_session_signals[USER_VERIFIED] =
g_signal_new ("user-verified",
G_OBJECT_CLASS_TYPE (object_class),
@@ -685,7 +515,7 @@ gdm_session_class_install_signals (GdmSessionClass *session_class)
g_signal_new ("session-died",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (GdmSessionClass, session_exited),
+ G_STRUCT_OFFSET (GdmSessionClass, session_died),
NULL,
NULL,
g_cclosure_marshal_VOID__INT,
@@ -703,11 +533,15 @@ gdm_session_finalize (GObject *object)
session = GDM_SESSION (object);
- g_strfreev (session->priv->arguments);
g_free (session->priv->username);
parent_class = G_OBJECT_CLASS (gdm_session_parent_class);
+ if (session->priv->environment != NULL) {
+ g_hash_table_destroy (session->priv->environment);
+ session->priv->environment = NULL;
+ }
+
if (parent_class->finalize != NULL)
parent_class->finalize (object);
}
@@ -727,3292 +561,937 @@ gdm_session_class_init (GdmSessionClass *session_class)
sizeof (GdmSessionPrivate));
}
-static void
-gdm_session_init (GdmSession *session)
-{
- session->priv = G_TYPE_INSTANCE_GET_PRIVATE (session,
- GDM_TYPE_SESSION,
- GdmSessionPrivate);
-}
-
-static gboolean
-gdm_read_message (int socket_fd,
- gpointer *message_data,
- gsize *message_data_size,
- char **error_message)
-{
- struct msghdr message = { 0 };
- struct iovec data_block = { 0 };
- const int flags = MSG_NOSIGNAL;
-
- gssize num_bytes_received;
-
- message.msg_iov = &data_block;
- message.msg_iovlen = 1;
-
- data_block.iov_base = g_malloc0 (GDM_MAX_MESSAGE_SIZE);
- data_block.iov_len = (size_t) GDM_MAX_MESSAGE_SIZE;
-
- num_bytes_received = 0;
- do {
- num_bytes_received = recvmsg (socket_fd, &message, flags);
-
- if (num_bytes_received > 0) {
- g_debug ("read '%lu' bytes over socket '%d'",
- (gulong) num_bytes_received,
- socket_fd);
- }
- }
- while (!(num_bytes_received > 0) && (errno == EINTR));
-
- if ((num_bytes_received < 0) && (error_message != NULL)) {
- const char *error;
- error = g_strerror (errno);
- g_debug ("message was not received: %s", error);
- *error_message = g_strdup (error);
- return FALSE;
- } else if (num_bytes_received == 0) {
- g_debug ("message was not received: premature eof");
- *error_message = g_strdup ("premature eof");
- return FALSE;
- }
-
- g_debug ("message was received!");
- if (message_data != NULL) {
- *message_data = g_realloc (data_block.iov_base, num_bytes_received);
- *message_data_size = (gsize) num_bytes_received;
- } else {
- g_free (message.msg_iov);
- }
-
- return TRUE;
-}
-
-static GdmSessionMessage *
-gdm_session_verification_message_new (const char *service_name,
- const char *username,
- const char *hostname,
- const char *console_name,
- int standard_output_fd,
- int standard_error_fd)
+static DBusHandlerResult
+gdm_session_handle_verified (GdmSession *session,
+ DBusConnection *connection,
+ DBusMessage *message)
{
- GdmSessionVerificationMessage *message;
- gsize size, username_size;
-
- username_size = (username != NULL? strlen (username) + 1 : 0);
- size = sizeof (GdmSessionVerificationMessage) +
- username_size +
- sizeof (GDM_SESSION_MESSAGE_SENTINAL);
+ DBusMessage *reply;
+ DBusError error;
- message = g_slice_alloc0 (size);
-
- message->header.type = GDM_SESSION_MESSAGE_TYPE_VERIFICATION;
- message->header.size = size;
-
- g_strlcpy (message->service_name, service_name,
- sizeof (message->service_name));
-
- if (username != NULL) {
- g_strlcpy (message->username, username, username_size);
- message->username_size = username_size;
- } else {
- message->username_size = -1;
- }
-
- if (hostname != NULL) {
- g_strlcpy (message->hostname, hostname, sizeof (message->hostname));
- message->hostname_is_provided = TRUE;
- } else {
- message->hostname_is_provided = FALSE;
- }
-
- g_strlcpy (message->console_name, console_name, sizeof (message->console_name));
-
- message->standard_output_fd = standard_output_fd;
- message->standard_error_fd = standard_error_fd;
-
- g_strlcpy ((char *) (char *) ((guint *) message) + size -
- sizeof (GDM_SESSION_MESSAGE_SENTINAL),
- GDM_SESSION_MESSAGE_SENTINAL,
- sizeof (GDM_SESSION_MESSAGE_SENTINAL));
-
- return (GdmSessionMessage *) message;
-}
-
-static char *
-gdm_session_flatten_arguments (const char * const *argv,
- gsize *arguments_size)
-{
- char *arguments;
- gsize i, total_size, argument_size;
-
- total_size = 0;
- for (i = 0; argv[i] != NULL; i++) {
- argument_size = strlen (argv[i]) + 1;
- total_size += argument_size;
- }
- total_size++;
-
- arguments = g_slice_alloc0 (total_size);
-
- total_size = 0;
- for (i = 0; argv[i] != NULL; i++) {
- argument_size = strlen (argv[i]) + 1;
- g_strlcpy (arguments + total_size,
- argv[i], argument_size);
+ g_debug ("Emitting 'user-verified' signal");
- total_size += argument_size;
- }
- total_size++;
+ reply = dbus_message_new_method_return (message);
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (reply);
- if (arguments_size)
- *arguments_size = total_size;
+ session->priv->is_verified = TRUE;
+ g_signal_emit (session,
+ gdm_session_signals[USER_VERIFIED],
+ 0);
- return arguments;
+ return DBUS_HANDLER_RESULT_HANDLED;
}
-static char **
-gdm_session_unflatten_arguments (const char *arguments)
+static DBusHandlerResult
+gdm_session_handle_verification_failed (GdmSession *session,
+ DBusConnection *connection,
+ DBusMessage *message)
{
- GPtrArray *array;
- char *argument;
+ DBusMessage *reply;
+ DBusError error;
+ const char *text;
- array = g_ptr_array_new ();
-
- argument = (char *) arguments;
- while (*argument != '\0') {
- g_ptr_array_add (array, g_strdup (argument));
- argument += strlen (argument) + 1;
+ dbus_error_init (&error);
+ if (! dbus_message_get_args (message, &error,
+ DBUS_TYPE_STRING, &text,
+ DBUS_TYPE_INVALID)) {
+ g_warning ("ERROR: %s", error.message);
}
- g_ptr_array_add (array, NULL);
-
- return (char **) g_ptr_array_free (array, FALSE);
-}
-
-static GdmSessionMessage *
-gdm_session_start_program_message_new (const char * const * args)
-{
- GdmSessionStartProgramMessage *message;
- char *arguments;
- gsize size;
- gsize arguments_size;
-
- g_assert (args != NULL);
- arguments_size = 0;
- arguments = gdm_session_flatten_arguments (args, &arguments_size);
-
- size = sizeof (GdmSessionStartProgramMessage) +
- arguments_size +
- sizeof (GDM_SESSION_MESSAGE_SENTINAL);
-
- message = g_slice_alloc0 (size);
-
- message->header.type = GDM_SESSION_MESSAGE_TYPE_START_PROGRAM;
- message->header.size = size;
-
- memcpy (message->arguments, arguments, arguments_size);
- g_slice_free1 (arguments_size, arguments);
- message->arguments_size = arguments_size;
-
- g_strlcpy ((char *) ((guint *) message) + size -
- sizeof (GDM_SESSION_MESSAGE_SENTINAL),
- GDM_SESSION_MESSAGE_SENTINAL,
- sizeof (GDM_SESSION_MESSAGE_SENTINAL));
-
- return (GdmSessionMessage *) message;
-}
-
-static GdmSessionMessage *
-gdm_session_set_environment_variable_message_new (const char *name,
- const char *value)
-{
- GdmSessionSetEnvironmentVariableMessage *message;
- char *environment_variable;
- gsize size;
- gsize environment_variable_size;
- int length;
+ reply = dbus_message_new_method_return (message);
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (reply);
- g_assert (name != NULL);
- g_assert (strchr (name, '=') == NULL);
- g_assert (value != NULL);
-
- environment_variable = g_strdup_printf ("%s=%s%n", name, value, &length);
- environment_variable_size = length + 1;
-
- size = sizeof (GdmSessionSetEnvironmentVariableMessage) +
- environment_variable_size +
- sizeof (GDM_SESSION_MESSAGE_SENTINAL);
-
- message = g_slice_alloc0 (size);
-
- message->header.type = GDM_SESSION_MESSAGE_TYPE_SET_ENVIRONMENT_VARIABLE;
- message->header.size = size;
-
- g_strlcpy (message->environment_variable,
- environment_variable, environment_variable_size);
- g_free (environment_variable);
- message->environment_variable_size = environment_variable_size;
+ g_debug ("Emitting 'verification-failed' signal");
- g_strlcpy ((char *) ((guint *) message) + size -
- sizeof (GDM_SESSION_MESSAGE_SENTINAL),
- GDM_SESSION_MESSAGE_SENTINAL,
- sizeof (GDM_SESSION_MESSAGE_SENTINAL));
+ g_signal_emit (session,
+ gdm_session_signals[USER_VERIFICATION_ERROR],
+ 0, text);
- return (GdmSessionMessage *) message;
+ return DBUS_HANDLER_RESULT_HANDLED;
}
-static GdmSessionMessage *
-gdm_session_info_reply_message_new (const char *answer)
+static DBusHandlerResult
+gdm_session_handle_username_changed (GdmSession *session,
+ DBusConnection *connection,
+ DBusMessage *message)
{
- GdmSessionInfoReplyMessage *message;
- gsize size;
- gsize answer_size;
-
- answer_size = (answer != NULL? strlen (answer) + 1 : 0);
- size = sizeof (GdmSessionInfoReplyMessage) +
- answer_size +
- sizeof (GDM_SESSION_MESSAGE_SENTINAL);
-
- message = g_slice_alloc0 (size);
+ DBusMessage *reply;
+ DBusError error;
+ const char *text;
- message->header.type = GDM_SESSION_MESSAGE_TYPE_INFO_REPLY;
- message->header.size = size;
-
- if (answer != NULL) {
- g_strlcpy (message->answer, answer, answer_size);
- message->answer_size = answer_size;
- } else {
- message->answer_size = -1;
+ dbus_error_init (&error);
+ if (! dbus_message_get_args (message, &error,
+ DBUS_TYPE_STRING, &text,
+ DBUS_TYPE_INVALID)) {
+ g_warning ("ERROR: %s", error.message);
}
- g_strlcpy ((char *) ((guint *) message) + size -
- sizeof (GDM_SESSION_MESSAGE_SENTINAL),
- GDM_SESSION_MESSAGE_SENTINAL,
- sizeof (GDM_SESSION_MESSAGE_SENTINAL));
-
- return (GdmSessionMessage *) message;
-}
-
-static GdmSessionMessage *
-gdm_session_secret_info_reply_message_new (const char *answer)
-{
- GdmSessionSecretInfoReplyMessage *message;
- gsize size;
- gsize answer_size;
-
- answer_size = (answer != NULL? strlen (answer) + 1 : 0);
- size = sizeof (GdmSessionSecretInfoReplyMessage) +
- answer_size +
- sizeof (GDM_SESSION_MESSAGE_SENTINAL);
-
- message = g_slice_alloc0 (size);
-
- message->header.type = GDM_SESSION_MESSAGE_TYPE_SECRET_INFO_REPLY;
- message->header.size = size;
+ reply = dbus_message_new_method_return (message);
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (reply);
- if (answer != NULL) {
- g_strlcpy (message->answer, answer, answer_size);
- message->answer_size = answer_size;
- } else {
- message->answer_size = -1;
- }
+ g_debug ("changing username from '%s' to '%s'",
+ session->priv->username != NULL ? session->priv->username : "<unset>",
+ (strlen (text)) ? text : "<unset>");
- g_strlcpy ((char *) ((guint *) message) + size -
- sizeof (GDM_SESSION_MESSAGE_SENTINAL),
- GDM_SESSION_MESSAGE_SENTINAL,
- sizeof (GDM_SESSION_MESSAGE_SENTINAL));
+ g_free (session->priv->username);
+ session->priv->username = (strlen (text) > 0) ? g_strdup (text) : NULL;
- return (GdmSessionMessage *) message;
+ return DBUS_HANDLER_RESULT_HANDLED;
}
static void
-gdm_session_message_free (GdmSessionMessage *message)
-{
- g_slice_free1 (message->size, message);
-}
-
-
-GdmSession *
-gdm_session_new (void)
+answer_pending_query (GdmSession *session,
+ const char *answer)
{
- GdmSession *session;
+ DBusMessage *reply;
+ DBusMessageIter iter;
- session = g_object_new (GDM_TYPE_SESSION, NULL);
+ reply = dbus_message_new_method_return (session->priv->message_pending_reply);
+ dbus_message_iter_init_append (reply, &iter);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &answer);
- return session;
-}
-
-static void
-gdm_session_clear_child_watch_source (GdmSession *session)
-{
- session->priv->child_watch_source = NULL;
-}
+ dbus_connection_send (session->priv->worker_connection, reply, NULL);
+ dbus_message_unref (reply);
-static void
-gdm_session_clear_message_pipe_source (GdmSession *session)
-{
- session->priv->worker_message_pipe_source = NULL;
+ dbus_message_unref (session->priv->message_pending_reply);
+ session->priv->message_pending_reply = NULL;
}
static void
-gdm_session_on_child_exited (GPid pid,
- int status,
- GdmSession *session)
+set_pending_query (GdmSession *session,
+ DBusMessage *message)
{
- GError *error;
-
- if (WIFEXITED (status)) {
- if (!session->priv->is_verified) {
- error = g_error_new (GDM_SESSION_ERROR,
- GDM_SESSION_ERROR_WORKER_DIED,
- _("worker exited with status %d"),
- WEXITSTATUS (status));
-
- g_signal_emit (session,
- gdm_session_signals[USER_VERIFICATION_ERROR],
- 0, error);
- g_error_free (error);
- } else if (session->priv->is_running) {
- g_signal_emit (session,
- gdm_session_signals[SESSION_EXITED],
- 0, WEXITSTATUS (status));
- }
- } else if (WIFSIGNALED (status)) {
- if (!session->priv->is_verified) {
- error = g_error_new (GDM_SESSION_ERROR,
- GDM_SESSION_ERROR_WORKER_DIED,
- _("worker got signal '%s' and was subsequently killed"),
- g_strsignal (WTERMSIG (status)));
- g_signal_emit (session,
- gdm_session_signals[USER_VERIFICATION_ERROR],
- 0, error);
- g_error_free (error);
- } else if (session->priv->is_running) {
- g_signal_emit (session,
- gdm_session_signals[SESSION_EXITED],
- 0, WTERMSIG (status));
- }
- } else {
- /* WIFSTOPPED (status) || WIFCONTINUED (status) */
- }
+ g_assert (session->priv->message_pending_reply == NULL);
- g_spawn_close_pid (pid);
- session->priv->worker_pid = 0;
+ session->priv->message_pending_reply = dbus_message_ref (message);
}
-static gboolean
-gdm_session_validate_message_size (GdmSession *session,
- GdmSessionWorkerMessage *message,
- GError **error)
+static DBusHandlerResult
+gdm_session_handle_info_query (GdmSession *session,
+ DBusConnection *connection,
+ DBusMessage *message)
{
- gsize expected_size;
-
- return TRUE;
-
- switch (message->type) {
- case GDM_SESSION_WORKER_MESSAGE_TYPE_VERIFIED:
- expected_size = (gsize) sizeof (GdmSessionWorkerVerifiedMessage);
- break;
-
- case GDM_SESSION_WORKER_MESSAGE_TYPE_VERIFICATION_FAILED:
- expected_size = (gsize) sizeof (GdmSessionWorkerVerificationFailedMessage);
- break;
-
- case GDM_SESSION_WORKER_MESSAGE_TYPE_USERNAME_CHANGED:
- expected_size = (gsize) sizeof (GdmSessionWorkerUsernameChangedMessage);
- break;
-
- case GDM_SESSION_WORKER_MESSAGE_TYPE_INFO_REQUEST:
- expected_size = (gsize) sizeof (GdmSessionWorkerInfoRequestMessage);
- break;
-
- case GDM_SESSION_WORKER_MESSAGE_TYPE_SECRET_INFO_REQUEST:
- expected_size = (gsize) sizeof (GdmSessionWorkerSecretInfoRequestMessage);
- break;
+ DBusError error;
+ const char *text;
- case GDM_SESSION_WORKER_MESSAGE_TYPE_INFO:
- expected_size = (gsize) sizeof (GdmSessionWorkerInfoMessage);
- break;
-
- case GDM_SESSION_WORKER_MESSAGE_TYPE_PROBLEM:
- expected_size = (gsize) sizeof (GdmSessionWorkerProblemMessage);
- break;
-
- case GDM_SESSION_WORKER_MESSAGE_TYPE_SESSION_STARTED:
- expected_size = (gsize) sizeof (GdmSessionWorkerSessionStartedMessage);
- break;
-
- case GDM_SESSION_WORKER_MESSAGE_TYPE_SESSION_STARTUP_FAILED:
- expected_size = (gsize) sizeof (GdmSessionWorkerSessionStartupFailedMessage);
- break;
-
- case GDM_SESSION_WORKER_MESSAGE_TYPE_SESSION_EXITED:
- expected_size = (gsize) sizeof (GdmSessionWorkerSessionExitedMessage);
- break;
-
- case GDM_SESSION_WORKER_MESSAGE_TYPE_SESSION_DIED:
- expected_size = (gsize) sizeof (GdmSessionWorkerSessionDiedMessage);
- break;
-
- default:
- g_debug ("do not know about message type '0x%x'", (guint) message->type);
- g_set_error (error,
- GDM_SESSION_ERROR,
- GDM_SESSION_ERROR_COMMUNICATING,
- _("do not know about message type '0x%x'"),
- (guint) message->type);
- return FALSE;
+ dbus_error_init (&error);
+ if (! dbus_message_get_args (message, &error,
+ DBUS_TYPE_STRING, &text,
+ DBUS_TYPE_INVALID)) {
+ g_warning ("ERROR: %s", error.message);
}
- if (message->size != expected_size) {
- g_debug ("message size was '%lu', but message was supposed "
- "to be '%lu'", (gulong) message->size, (gulong) expected_size);
- g_set_error (error,
- GDM_SESSION_ERROR,
- GDM_SESSION_ERROR_COMMUNICATING,
- "message size was '%lu', but message was supposed "
- "to be '%lu'", (gulong) message->size,
- (gulong) expected_size);
- return FALSE;
- }
-
- return TRUE;
-}
-
-static GdmSessionWorkerMessage *
-gdm_session_get_incoming_message (GdmSession *session,
- GError **error)
-{
- GError *size_error;
- char *error_message;
- GdmSessionWorkerMessage *message;
- gsize message_size;
- gboolean res;
-
- g_debug ("attemping to read message from worker...");
- error_message = NULL;
- res = gdm_read_message (session->priv->worker_message_pipe_fd,
- (gpointer) &message,
- &message_size,
- &error_message);
- if (! res) {
- g_debug ("could not read message from worker: %s", error_message);
- g_set_error (error,
- GDM_SESSION_ERROR,
- GDM_SESSION_ERROR_COMMUNICATING,
- "%s", error_message);
- g_free (error_message);
- return NULL;
- }
- g_debug ("message type is '0x%x'", message->type);
-
- if (message_size != message->size) {
- g_debug ("message reports to be '%ld' bytes but is actually '%ld'",
- (glong) message->size, (glong) message_size);
- g_set_error (error,
- GDM_SESSION_ERROR,
- GDM_SESSION_ERROR_COMMUNICATING,
- _("specified message size does not match size of message "
- "received"));
- return NULL;
- }
- g_debug ("message size is '%lu'", (gulong) message_size);
-
- g_debug ("validating that message size is right for message "
- "type...");
- size_error = NULL;
- res = gdm_session_validate_message_size (session, message, &size_error);
- if (! res) {
- g_propagate_error (error, size_error);
- return NULL;
- }
- g_debug ("message size is valid");
-
- switch (message->type) {
- case GDM_SESSION_WORKER_MESSAGE_TYPE_VERIFIED:
- g_debug ("received valid 'verified' message from worker");
- break;
-
- case GDM_SESSION_WORKER_MESSAGE_TYPE_VERIFICATION_FAILED:
- g_debug ("received valid 'verification failed' message from worker");
- break;
-
- case GDM_SESSION_WORKER_MESSAGE_TYPE_USERNAME_CHANGED:
- g_debug ("received valid 'username changed' message from worker");
- break;
-
- case GDM_SESSION_WORKER_MESSAGE_TYPE_INFO_REQUEST:
- g_debug ("received valid 'info request' message from worker");
- g_debug ("***********MESSAGE QUESTION IS '%s'********",
- ((GdmSessionWorkerInfoRequestMessage *) message)->question);
- break;
-
- case GDM_SESSION_WORKER_MESSAGE_TYPE_SECRET_INFO_REQUEST:
- g_debug ("received valid 'secret info request' message from worker");
- break;
-
- case GDM_SESSION_WORKER_MESSAGE_TYPE_INFO:
- g_debug ("received valid 'info' message from worker");
- break;
-
- case GDM_SESSION_WORKER_MESSAGE_TYPE_PROBLEM:
- g_debug ("received valid 'problem' message from worker");
- break;
-
- case GDM_SESSION_WORKER_MESSAGE_TYPE_SESSION_STARTED:
- g_debug ("received valid 'session started' message from worker");
- break;
-
- case GDM_SESSION_WORKER_MESSAGE_TYPE_SESSION_STARTUP_FAILED:
- g_debug ("received valid 'session startup failed' message from worker");
- break;
-
- case GDM_SESSION_WORKER_MESSAGE_TYPE_SESSION_EXITED:
- g_debug ("received valid 'session exited' message from worker");
- break;
-
- case GDM_SESSION_WORKER_MESSAGE_TYPE_SESSION_DIED:
- g_debug ("received valid 'session died' message from worker");
- break;
-
- default:
- g_debug ("received unknown message of type '0x%x'",
- (guint) message->type);
- g_set_error (error,
- GDM_SESSION_ERROR,
- GDM_SESSION_ERROR_COMMUNICATING,
- _("received unknown message"));
- gdm_session_worker_message_free (message);
- message = NULL;
- break;
- }
-
- return message;
-}
-
-static void
-gdm_session_handle_verified_message (GdmSession *session,
- GdmSessionWorkerVerifiedMessage *message)
-{
- g_debug ("Emitting 'user-verified' signal");
-
- session->priv->is_verified = TRUE;
- g_signal_emit (session,
- gdm_session_signals[USER_VERIFIED],
- 0);
-}
-
-static void
-gdm_session_handle_verification_failed_message (GdmSession *session,
- GdmSessionWorkerVerificationFailedMessage *message)
-{
- GError *error;
-
- g_debug ("Emitting 'verification-failed' signal");
-
- error = g_error_new (message->error_domain,
- message->error_code,
- "%s", message->error_message);
-
- g_signal_emit (session,
- gdm_session_signals[USER_VERIFICATION_ERROR],
- 0, error);
- g_error_free (error);
-}
-
-static void
-gdm_session_handle_username_changed_message (GdmSession *session,
- GdmSessionWorkerUsernameChangedMessage *message)
-{
- g_debug ("changing username from '%s' to '%s'",
- session->priv->username != NULL? session->priv->username : "<unset>",
- (message->username_size >= 0)? message->username : "<unset>");
- g_free (session->priv->username);
- session->priv->username = (message->username_size >= 0)? g_strdup (message->username) : NULL;
-}
-
-static void
-gdm_session_handle_info_request_message (GdmSession*session,
- GdmSessionWorkerInfoRequestMessage *message)
-{
- g_assert (session->priv->query_answer == NULL);
-
- session->priv->next_expected_message = GDM_SESSION_MESSAGE_TYPE_INFO_REPLY;
+ set_pending_query (session, message);
g_debug ("Emitting 'info-query' signal");
g_signal_emit (session,
gdm_session_signals[INFO_QUERY],
- 0, message->question);
-}
-
-static void
-gdm_session_handle_secret_info_request_message (GdmSession *session,
- GdmSessionWorkerSecretInfoRequestMessage *message)
-{
- g_assert (session->priv->query_answer == NULL);
+ 0, text);
- session->priv->next_expected_message = GDM_SESSION_MESSAGE_TYPE_SECRET_INFO_REPLY;
-
- g_debug ("Emitting 'secret-info-query' signal");
-
- g_signal_emit (session,
- gdm_session_signals[SECRET_INFO_QUERY],
- 0, message->question);
+ return DBUS_HANDLER_RESULT_HANDLED;
}
-static void
-gdm_session_handle_info_message (GdmSession *session,
- GdmSessionWorkerInfoMessage *message)
+static DBusHandlerResult
+gdm_session_handle_secret_info_query (GdmSession *session,
+ DBusConnection *connection,
+ DBusMessage *message)
{
- g_debug ("Emitting 'info' signal");
- g_signal_emit (session,
- gdm_session_signals[INFO],
- 0, message->info);
+ DBusMessage *reply;
+ const char *text;
-}
-
-static void
-gdm_session_handle_problem_message (GdmSession *session,
- GdmSessionWorkerProblemMessage *message)
-{
- g_debug ("Emitting 'problem' signal");
- g_signal_emit (session,
- gdm_session_signals[PROBLEM],
- 0, message->problem);
-}
-
-static void
-gdm_session_handle_session_started_message (GdmSession *session,
- GdmSessionWorkerSessionStartedMessage *message)
-{
- g_debug ("Emitting 'session-started' signal with pid '%d'",
- (int) message->pid);
-
- session->priv->pid = message->pid;
- session->priv->is_running = TRUE;
-
- g_signal_emit (session,
- gdm_session_signals[SESSION_STARTED],
- 0, (int) message->pid);
-}
-
-static void
-gdm_session_handle_session_startup_failed_message (GdmSession *session,
- GdmSessionWorkerSessionStartupFailedMessage *message)
-{
- GError *error;
+ dbus_error_init (&error);
+ if (! dbus_message_get_args (message, &error,
+ DBUS_TYPE_STRING, &text,
+ DBUS_TYPE_INVALID)) {
+ g_warning ("ERROR: %s", error.message);
+ }
- g_debug ("Emitting 'session-startup-error' signal");
+ set_pending_query (session, message);
- error = g_error_new (message->error_domain,
- message->error_code,
- "%s", message->error_message);
- g_signal_emit (session,
- gdm_session_signals[SESSION_STARTUP_ERROR],
- 0, error);
- g_error_free (error);
-}
-
-static void
-gdm_session_handle_session_exited_message (GdmSession *session,
- GdmSessionWorkerSessionExitedMessage *message)
-{
- g_debug ("Emitting 'session-exited' signal with exit code '%d'",
- message->exit_code);
+ g_debug ("Emitting 'secret-info-query' signal");
- session->priv->is_running = FALSE;
g_signal_emit (session,
- gdm_session_signals[SESSION_EXITED],
- 0, message->exit_code);
-}
-
-static void
-gdm_session_handle_session_died_message (GdmSession *session,
- GdmSessionWorkerSessionDiedMessage *message)
-{
- g_debug ("Emitting 'session-died' signal with signal number '%d'",
- message->signal_number);
+ gdm_session_signals[SECRET_INFO_QUERY],
+ 0, text);
- session->priv->is_running = FALSE;
- g_signal_emit (session,
- gdm_session_signals[SESSION_DIED],
- 0, message->signal_number);
+ return DBUS_HANDLER_RESULT_HANDLED;
}
-static void
-gdm_session_incoming_message_handler (GdmSession *session)
+static DBusHandlerResult
+gdm_session_handle_info (GdmSession *session,
+ DBusConnection *connection,
+ DBusMessage *message)
{
- GdmSessionWorkerMessage *message;
- GError *error;
-
- error = NULL;
- message = gdm_session_get_incoming_message (session, &error);
+ DBusMessage *reply;
+ DBusError error;
+ const char *text;
- if (message == NULL) {
- g_assert (error != NULL);
- g_warning ("could not receive message from parent: %s\n", error->message);
- g_error_free (error);
-
- /* FIXME: figure out what to do here
- */
- return;
+ dbus_error_init (&error);
+ if (! dbus_message_get_args (message, &error,
+ DBUS_TYPE_STRING, &text,
+ DBUS_TYPE_INVALID)) {
+ g_warning ("ERROR: %s", error.message);
}
- switch (message->type) {
- case GDM_SESSION_WORKER_MESSAGE_TYPE_VERIFIED:
- g_debug ("worker successfully verified user");
- gdm_session_handle_verified_message (session,
- (GdmSessionWorkerVerifiedMessage *)
- message);
-
- break;
-
- case GDM_SESSION_WORKER_MESSAGE_TYPE_VERIFICATION_FAILED:
- g_debug ("worker could not verify user");
- gdm_session_handle_verification_failed_message (session,
- (GdmSessionWorkerVerificationFailedMessage *)
- message);
-
- break;
-
- case GDM_SESSION_WORKER_MESSAGE_TYPE_USERNAME_CHANGED:
- g_debug ("received changed username from worker");
- gdm_session_handle_username_changed_message (session,
- (GdmSessionWorkerUsernameChangedMessage *) message);
- break;
-
- case GDM_SESSION_WORKER_MESSAGE_TYPE_INFO_REQUEST:
- g_debug ("received info request from worker");
- gdm_session_handle_info_request_message (session,
- (GdmSessionWorkerInfoRequestMessage *) message);
- break;
+ reply = dbus_message_new_method_return (message);
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (reply);
- case GDM_SESSION_WORKER_MESSAGE_TYPE_SECRET_INFO_REQUEST:
- g_debug ("received secret info request from worker");
- gdm_session_handle_secret_info_request_message (session,
- (GdmSessionWorkerSecretInfoRequestMessage *) message);
- break;
-
- case GDM_SESSION_WORKER_MESSAGE_TYPE_INFO:
- g_debug ("received new info from worker");
- gdm_session_handle_info_message (session,
- (GdmSessionWorkerInfoMessage *) message);
- break;
-
- case GDM_SESSION_WORKER_MESSAGE_TYPE_PROBLEM:
- g_debug ("received problem from worker");
- gdm_session_handle_problem_message (session,
- (GdmSessionWorkerProblemMessage *) message);
- break;
-
- case GDM_SESSION_WORKER_MESSAGE_TYPE_SESSION_STARTED:
- g_debug ("received session started message from worker");
- gdm_session_handle_session_started_message (session,
- (GdmSessionWorkerSessionStartedMessage *) message);
- break;
-
- case GDM_SESSION_WORKER_MESSAGE_TYPE_SESSION_STARTUP_FAILED:
- g_debug ("received session startup failed message from worker");
- gdm_session_handle_session_startup_failed_message (session,
- (GdmSessionWorkerSessionStartupFailedMessage *) message);
- break;
-
- case GDM_SESSION_WORKER_MESSAGE_TYPE_SESSION_EXITED:
- g_debug ("received session exited message from worker");
- gdm_session_handle_session_exited_message (session,
- (GdmSessionWorkerSessionExitedMessage *) message);
- break;
-
- case GDM_SESSION_WORKER_MESSAGE_TYPE_SESSION_DIED:
- g_debug ("received session died message from worker");
- gdm_session_handle_session_died_message (session,
- (GdmSessionWorkerSessionDiedMessage *) message);
- break;
-
- default:
- g_debug ("received unknown message of type '0x%x' from worker",
- message->type);
- break;
- }
+ g_debug ("Emitting 'info' signal");
+ g_signal_emit (session,
+ gdm_session_signals[INFO],
+ 0, text);
- gdm_session_worker_message_free (message);
+ return DBUS_HANDLER_RESULT_HANDLED;
}
-static gboolean
-gdm_session_data_on_message_pipe_handler (GIOChannel *channel,
- GIOCondition condition,
- GdmSession *session)
+static DBusHandlerResult
+gdm_session_handle_problem (GdmSession *session,
+ DBusConnection *connection,
+ DBusMessage *message)
{
- if ((condition & G_IO_IN) || (condition & G_IO_PRI)) {
- g_debug ("got message from message pipe");
- gdm_session_incoming_message_handler (session);
- }
+ DBusMessage *reply;
+ DBusError error;
+ const char *text;
- if ((condition & G_IO_ERR) || (condition & G_IO_HUP)) {
- g_debug ("got disconnected message from message pipe");
- g_error("not implemented");
- /*gdm_session_disconnected_handler (session);*/
- return FALSE;
+ dbus_error_init (&error);
+ if (! dbus_message_get_args (message, &error,
+ DBUS_TYPE_STRING, &text,
+ DBUS_TYPE_INVALID)) {
+ g_warning ("ERROR: %s", error.message);
}
- return TRUE;
-}
+ reply = dbus_message_new_method_return (message);
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (reply);
-static void
-gdm_session_worker_clear_child_watch_source (GdmSessionWorker *worker)
-{
- worker->child_watch_source = NULL;
+ g_debug ("Emitting 'problem' signal");
+ g_signal_emit (session,
+ gdm_session_signals[PROBLEM],
+ 0, text);
+ return DBUS_HANDLER_RESULT_HANDLED;
}
-static void
-gdm_session_watch_child (GdmSession *session)
+static DBusHandlerResult
+gdm_session_handle_session_started (GdmSession *session,
+ DBusConnection *connection,
+ DBusMessage *message)
{
- GIOChannel *io_channel;
- GIOFlags channel_flags;
-
- g_assert (session->priv->child_watch_source == NULL);
-
- session->priv->child_watch_source = g_child_watch_source_new (session->priv->worker_pid);
- g_source_set_callback (session->priv->child_watch_source,
- (GChildWatchFunc) gdm_session_on_child_exited,
- session,
- (GDestroyNotify) gdm_session_clear_child_watch_source);
- g_source_attach (session->priv->child_watch_source, session->priv->context);
- g_source_unref (session->priv->child_watch_source);
-
- io_channel = g_io_channel_unix_new (session->priv->worker_message_pipe_fd);
-
- channel_flags = g_io_channel_get_flags (io_channel);
- g_io_channel_set_flags (io_channel,
- channel_flags | G_IO_FLAG_NONBLOCK,
- NULL);
-
- g_assert (session->priv->worker_message_pipe_source == NULL);
-
- session->priv->worker_message_pipe_source = g_io_create_watch (io_channel,
- G_IO_IN | G_IO_HUP);
- g_io_channel_unref (io_channel);
-
- g_source_set_callback (session->priv->worker_message_pipe_source,
- (GIOFunc) gdm_session_data_on_message_pipe_handler,
- session,
- (GDestroyNotify) gdm_session_clear_message_pipe_source);
- g_source_attach (session->priv->worker_message_pipe_source, session->priv->context);
- g_source_unref (session->priv->worker_message_pipe_source);
-}
+ DBusMessage *reply;
+ DBusError error;
+ int pid;
-static void
-gdm_session_unwatch_child (GdmSession *session)
-{
- if (session->priv->child_watch_source == NULL) {
- return;
+ dbus_error_init (&error);
+ if (! dbus_message_get_args (message, &error,
+ DBUS_TYPE_INT32, &pid,
+ DBUS_TYPE_INVALID)) {
+ g_warning ("ERROR: %s", error.message);
}
- g_source_destroy (session->priv->child_watch_source);
- session->priv->child_watch_source = NULL;
-
- g_assert (session->priv->worker_message_pipe_source != NULL);
-
- g_source_destroy (session->priv->worker_message_pipe_source);
- session->priv->worker_message_pipe_source = NULL;
-}
-
-static void
-gdm_session_worker_clear_message_pipe_source (GdmSessionWorker *worker)
-{
- worker->message_pipe_source = NULL;
-}
-
-static void
-gdm_session_worker_disconnected_handler (GdmSessionWorker *worker)
-{
- g_debug ("exiting...");
- worker->exit_code = 127;
- g_main_loop_quit (worker->event_loop);
-}
-
-static gboolean
-gdm_session_worker_validate_message_size (GdmSessionWorker *worker,
- GdmSessionMessage *message,
- GError **error)
-{
- gsize expected_size;
+ reply = dbus_message_new_method_return (message);
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (reply);
- return TRUE;
-
- switch (message->type) {
- case GDM_SESSION_MESSAGE_TYPE_VERIFICATION:
- expected_size = (gsize) sizeof (GdmSessionVerificationMessage);
- break;
- case GDM_SESSION_MESSAGE_TYPE_START_PROGRAM:
- expected_size = (gsize) sizeof (GdmSessionStartProgramMessage);
- break;
- case GDM_SESSION_MESSAGE_TYPE_SET_ENVIRONMENT_VARIABLE:
- expected_size = (gsize) sizeof (GdmSessionSetEnvironmentVariableMessage);
- break;
- case GDM_SESSION_MESSAGE_TYPE_INFO_REPLY:
- expected_size = (gsize) sizeof (GdmSessionInfoReplyMessage);
- break;
- case GDM_SESSION_MESSAGE_TYPE_SECRET_INFO_REPLY:
- expected_size = (gsize) sizeof (GdmSessionSecretInfoReplyMessage);
- break;
-
- default:
- g_debug ("do not know about message type '0x%x'",
- (guint) message->type);
+ g_debug ("Emitting 'session-started' signal with pid '%d'",
+ pid);
- g_set_error (error,
- GDM_SESSION_ERROR,
- GDM_SESSION_ERROR_COMMUNICATING,
- _("do not know about message type '0x%x'"),
- (guint) message->type);
- return FALSE;
- }
+ session->priv->session_pid = pid;
+ session->priv->is_running = TRUE;
- if (message->size != expected_size) {
- g_debug ("message size was '%lu', but message was supposed "
- "to be '%lu'",
- (gulong) message->size,
- (gulong) expected_size);
- g_set_error (error,
- GDM_SESSION_ERROR,
- GDM_SESSION_ERROR_COMMUNICATING,
- "message size was '%lu', but message was supposed "
- "to be '%lu'", (gulong) message->size,
- (gulong) expected_size);
- return FALSE;
- }
+ g_signal_emit (session,
+ gdm_session_signals[SESSION_STARTED],
+ 0, pid);
- return TRUE;
+ return DBUS_HANDLER_RESULT_HANDLED;
}
-static GdmSessionMessage *
-gdm_session_worker_get_incoming_message (GdmSessionWorker *worker,
- GError **error)
+static DBusHandlerResult
+gdm_session_handle_startup_failed (GdmSession *session,
+ DBusConnection *connection,
+ DBusMessage *message)
{
- GError *size_error;
- char *error_message;
- GdmSessionMessage *message;
- gsize message_size;
- gboolean res;
-
- g_debug ("attemping to read message from parent...");
- error_message = NULL;
- res = gdm_read_message (worker->message_pipe_fd,
- (gpointer) &message,
- &message_size,
- &error_message);
- if (! res) {
- g_debug ("could not read message from parent: %s", error_message);
- g_set_error (error,
- GDM_SESSION_ERROR,
- GDM_SESSION_ERROR_COMMUNICATING,
- "%s", error_message);
- g_free (error_message);
- return NULL;
- }
- g_debug ("message type is '0x%x'", message->type);
-
- if (message_size != message->size) {
- g_debug ("message reports to be '%ld' bytes but is actually '%ld'",
- (glong) message->size,
- (glong) message_size);
- g_set_error (error,
- GDM_SESSION_ERROR,
- GDM_SESSION_ERROR_COMMUNICATING,
- _("specified message size does not match size of message "
- "received"));
- return NULL;
- }
- g_debug ("message size is '%lu'", (gulong) message_size);
+ DBusMessage *reply;
+ DBusError error;
+ const char *text;
- g_debug ("validating that message size is right for message "
- "type...");
-
- size_error = NULL;
- res = gdm_session_worker_validate_message_size (worker, message, &size_error);
- if (! res) {
- g_propagate_error (error, size_error);
- return NULL;
+ dbus_error_init (&error);
+ if (! dbus_message_get_args (message, &error,
+ DBUS_TYPE_STRING, &text,
+ DBUS_TYPE_INVALID)) {
+ g_warning ("ERROR: %s", error.message);
}
- g_debug ("message size is valid");
- switch (message->type) {
- case GDM_SESSION_MESSAGE_TYPE_VERIFICATION:
- g_debug ("user session verification request received");
- break;
+ reply = dbus_message_new_method_return (message);
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (reply);
- case GDM_SESSION_MESSAGE_TYPE_START_PROGRAM:
- g_debug ("session arguments received");
- break;
-
- case GDM_SESSION_MESSAGE_TYPE_SET_ENVIRONMENT_VARIABLE:
- g_debug ("environment variable received");
- break;
-
- case GDM_SESSION_MESSAGE_TYPE_INFO_REPLY:
- g_debug ("user session info reply received");
- break;
-
- case GDM_SESSION_MESSAGE_TYPE_SECRET_INFO_REPLY:
- g_debug ("user session secret info reply received");
- break;
+ g_debug ("Emitting 'session-startup-error' signal");
- default:
- g_debug ("do not know about message type '0x%x'",
- (guint) message->type);
- g_set_error (error,
- GDM_SESSION_ERROR,
- GDM_SESSION_ERROR_COMMUNICATING,
- _("received unknown message type"));
- gdm_session_message_free (message);
- message = NULL;
- break;
- }
+ g_signal_emit (session,
+ gdm_session_signals[SESSION_STARTUP_ERROR],
+ 0, text);
- return message;
+ return DBUS_HANDLER_RESULT_HANDLED;
}
-static gboolean
-gdm_write_message (int socket_fd,
- gpointer message_data,
- gsize message_data_size,
- char **error_message)
+static DBusHandlerResult
+gdm_session_handle_session_exited (GdmSession *session,
+ DBusConnection *connection,
+ DBusMessage *message)
{
- struct msghdr message = { 0 };
- struct iovec data_block = { 0 };
- const int flags = MSG_NOSIGNAL;
- gboolean message_was_sent;
-
- message.msg_iov = &data_block;
- message.msg_iovlen = 1;
-
- g_assert (message_data_size <= GDM_MAX_MESSAGE_SIZE);
-
- data_block.iov_base = message_data;
- data_block.iov_len = (size_t) message_data_size;
+ DBusMessage *reply;
+ DBusError error;
+ int code;
- message_was_sent = FALSE;
- do {
- gssize num_bytes_sent;
- num_bytes_sent = sendmsg (socket_fd, &message, flags);
-
- if (num_bytes_sent > 0) {
- g_debug ("sent '%lu' bytes over socket '%d'",
- (gulong) num_bytes_sent,
- socket_fd);
- message_was_sent = TRUE;
- }
+ dbus_error_init (&error);
+ if (! dbus_message_get_args (message, &error,
+ DBUS_TYPE_INT32, &code,
+ DBUS_TYPE_INVALID)) {
+ g_warning ("ERROR: %s", error.message);
}
- while (! message_was_sent && (errno == EINTR));
+ reply = dbus_message_new_method_return (message);
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (reply);
- if (! message_was_sent && (error_message != NULL)) {
- const char *error;
- error = g_strerror (errno);
- g_debug ("message was not sent: %s", error);
- *error_message = g_strdup (error);
- } else if (message_was_sent) {
- g_debug ("message was sent!");
- }
+ g_debug ("Emitting 'session-exited' signal with exit code '%d'",
+ code);
- g_free (message.msg_control);
+ session->priv->is_running = FALSE;
+ g_signal_emit (session,
+ gdm_session_signals[SESSION_EXITED],
+ 0, code);
- return message_was_sent;
+ return DBUS_HANDLER_RESULT_HANDLED;
}
-static char *
-gdm_session_worker_ask_question (GdmSessionWorker *worker,
- const char *question)
+static DBusHandlerResult
+gdm_session_handle_session_died (GdmSession *session,
+ DBusConnection *connection,
+ DBusMessage *message)
{
- GdmSessionWorkerMessage *message;
- GdmSessionMessage *reply;
- GdmSessionInfoReplyMessage *info_reply;
- char *answer;
- GError *error;
-
- message = gdm_session_worker_info_request_message_new (question);
- gdm_write_message (worker->message_pipe_fd, message, message->size, NULL);
- gdm_session_worker_message_free (message);
+ DBusMessage *reply;
+ DBusError error;
+ int code;
- error = NULL;
- do {
- gboolean res;
-
- reply = gdm_session_worker_get_incoming_message (worker, &error);
-
- if (reply == NULL) {
- g_warning ("could not receive message from parent: %s", error->message);
- g_error_free (error);
-
- /* FIXME: figure out what to do here
- */
- return NULL;
- }
-
- res = gdm_session_worker_process_asynchronous_message (worker, reply);
- if (res) {
- gdm_session_message_free (reply);
- reply = NULL;
- }
+ dbus_error_init (&error);
+ if (! dbus_message_get_args (message, &error,
+ DBUS_TYPE_INT32, &code,
+ DBUS_TYPE_INVALID)) {
+ g_warning ("ERROR: %s", error.message);
}
- while (reply == NULL);
- /* FIXME: we have to do something better here. Messages aren't gauranteed to
- * be delivered synchronously. We need to either fix that, or fix this to not
- * expect them to be.
- */
- if (reply->type != GDM_SESSION_MESSAGE_TYPE_INFO_REPLY) {
- g_debug ("discarding unexpected message of type 0x%x", reply->type);
- gdm_session_message_free (reply);
- reply = NULL;
- return NULL;
- }
+ reply = dbus_message_new_method_return (message);
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (reply);
- info_reply = (GdmSessionInfoReplyMessage *) reply;
- if (info_reply->answer_size >= 0)
- answer = g_strdup (info_reply->answer);
- else
- answer = NULL;
- gdm_session_message_free (reply);
- reply = NULL;
+ g_debug ("Emitting 'session-died' signal with signal number '%d'",
+ code);
- return answer;
-}
+ session->priv->is_running = FALSE;
+ g_signal_emit (session,
+ gdm_session_signals[SESSION_DIED],
+ 0, code);
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+session_worker_message (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ GdmSession *session = GDM_SESSION (user_data);
+
+ if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "Verified")) {
+ return gdm_session_handle_verified (session, connection, message);
+ } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "VerificationFailed")) {
+ return gdm_session_handle_verification_failed (session, connection, message);
+ } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "UsernameChanged")) {
+ return gdm_session_handle_username_changed (session, connection, message);
+ } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "InfoQuery")) {
+ return gdm_session_handle_info_query (session, connection, message);
+ } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SecretInfoQuery")) {
+ return gdm_session_handle_secret_info_query (session, connection, message);
+ } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "Info")) {
+ return gdm_session_handle_info (session, connection, message);
+ } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "Problem")) {
+ return gdm_session_handle_problem (session, connection, message);
+ } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SessionStarted")) {
+ return gdm_session_handle_session_started (session, connection, message);
+ } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "StartupFailed")) {
+ return gdm_session_handle_startup_failed (session, connection, message);
+ } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SessionExited")) {
+ return gdm_session_handle_session_exited (session, connection, message);
+ } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SessionDied")) {
+ return gdm_session_handle_session_died (session, connection, message);
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static DBusHandlerResult
+do_introspect (DBusConnection *connection,
+ DBusMessage *message)
+{
+ DBusMessage *reply;
+ GString *xml;
+ char *xml_string;
+
+ g_debug ("Do introspect");
+
+ /* standard header */
+ xml = g_string_new ("<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n"
+ "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
+ "<node>\n"
+ " <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
+ " <method name=\"Introspect\">\n"
+ " <arg name=\"data\" direction=\"out\" type=\"s\"/>\n"
+ " </method>\n"
+ " </interface>\n");
+
+ /* interface */
+ xml = g_string_append (xml,
+ " <interface name=\"org.gnome.DisplayManager.Session\">\n"
+ " <method name=\"Verified\">\n"
+ " </method>\n"
+ " <method name=\"VerificationFailed\">\n"
+ " <arg name=\"message\" direction=\"in\" type=\"s\"/>\n"
+ " </method>\n"
+ " <method name=\"InfoQuery\">\n"
+ " <arg name=\"query\" direction=\"in\" type=\"s\"/>\n"
+ " <arg name=\"answer\" direction=\"out\" type=\"s\"/>\n"
+ " </method>\n"
+ " <method name=\"SecretInfoQuery\">\n"
+ " <arg name=\"query\" direction=\"in\" type=\"s\"/>\n"
+ " <arg name=\"answer\" direction=\"out\" type=\"s\"/>\n"
+ " </method>\n"
+ " <method name=\"Info\">\n"
+ " <arg name=\"text\" direction=\"in\" type=\"s\"/>\n"
+ " </method>\n"
+ " <method name=\"Problem\">\n"
+ " <arg name=\"text\" direction=\"in\" type=\"s\"/>\n"
+ " </method>\n"
+ " <method name=\"UsernameChanged\">\n"
+ " <arg name=\"text\" direction=\"in\" type=\"s\"/>\n"
+ " </method>\n"
+ " <method name=\"StartupFailed\">\n"
+ " <arg name=\"message\" direction=\"in\" type=\"s\"/>\n"
+ " </method>\n"
+ " <method name=\"SessionStarted\">\n"
+ " <arg name=\"pid\" direction=\"in\" type=\"i\"/>\n"
+ " </method>\n"
+ " <method name=\"SessionExited\">\n"
+ " <arg name=\"code\" direction=\"in\" type=\"i\"/>\n"
+ " </method>\n"
+ " <method name=\"SessionDied\">\n"
+ " <arg name=\"signal\" direction=\"in\" type=\"i\"/>\n"
+ " </method>\n"
+ " <signal name=\"BeginVerification\">\n"
+ " <arg name=\"service_name\" type=\"s\"/>\n"
+ " <arg name=\"hostname\" type=\"s\"/>\n"
+ " <arg name=\"console\" type=\"s\"/>\n"
+ " </signal>\n"
+ " <signal name=\"BeginVerificationForUser\">\n"
+ " <arg name=\"service_name\" type=\"s\"/>\n"
+ " <arg name=\"hostname\" type=\"s\"/>\n"
+ " <arg name=\"console\" type=\"s\"/>\n"
+ " <arg name=\"username\" type=\"s\"/>\n"
+ " </signal>\n"
+ " <signal name=\"StartProgram\">\n"
+ " <arg name=\"command\" type=\"s\"/>\n"
+ " </signal>\n"
+ " <signal name=\"SetEnvironmentVariable\">\n"
+ " <arg name=\"name\" type=\"s\"/>\n"
+ " <arg name=\"value\" type=\"s\"/>\n"
+ " </signal>\n"
+ " <signal name=\"Reset\">\n"
+ " </signal>\n"
+ " </interface>\n");
+
+ reply = dbus_message_new_method_return (message);
+
+ xml = g_string_append (xml, "</node>\n");
+ xml_string = g_string_free (xml, FALSE);
+
+ dbus_message_append_args (reply,
+ DBUS_TYPE_STRING, &xml_string,
+ DBUS_TYPE_INVALID);
+
+ g_free (xml_string);
+
+ if (reply == NULL) {
+ g_error ("No memory");
+ }
+
+ if (! dbus_connection_send (connection, reply, NULL)) {
+ g_error ("No memory");
+ }
+
+ dbus_message_unref (reply);
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+session_message_handler (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ g_debug ("session_message_handler: destination=%s obj_path=%s interface=%s method=%s",
+ dbus_message_get_destination (message),
+ dbus_message_get_path (message),
+ dbus_message_get_interface (message),
+ dbus_message_get_member (message));
+
+
+ if (dbus_message_is_method_call (message, "org.freedesktop.DBus", "AddMatch")) {
+ DBusMessage *reply;
+
+ reply = dbus_message_new_method_return (message);
+
+ if (reply == NULL) {
+ g_error ("No memory");
+ }
+
+ if (! dbus_connection_send (connection, reply, NULL)) {
+ g_error ("No memory");
+ }
+
+ dbus_message_unref (reply);
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+ } else if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected") &&
+ strcmp (dbus_message_get_path (message), DBUS_PATH_LOCAL) == 0) {
+
+ /*dbus_connection_unref (connection);*/
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+ } else if (dbus_message_is_method_call (message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
+ return do_introspect (connection, message);
+ } else {
+ return session_worker_message (connection, message, user_data);
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+/* Note: Use abstract sockets like dbus does by default on Linux. Abstract
+ * sockets are only available on Linux.
+ */
static char *
-gdm_session_worker_ask_for_secret (GdmSessionWorker *worker,
- const char *secret)
+generate_address (void)
{
- GdmSessionWorkerMessage *message;
- GdmSessionMessage *reply;
- GdmSessionSecretInfoReplyMessage *secret_info_reply;
- char *answer;
- GError *error;
-
- message = gdm_session_worker_secret_info_request_message_new (secret);
- gdm_write_message (worker->message_pipe_fd, message, message->size, NULL);
- gdm_session_worker_message_free (message);
+ char *path;
+#if defined (__linux__)
+ int i;
+ char tmp[9];
- error = NULL;
- do {
- gboolean res;
-
- reply = gdm_session_worker_get_incoming_message (worker, &error);
-
- if (reply == NULL) {
- g_warning ("could not receive message from parent: %s", error->message);
- g_error_free (error);
-
- /* FIXME: figure out what to do here
- */
- return NULL;
- }
-
- res = gdm_session_worker_process_asynchronous_message (worker, reply);
- if (res) {
- gdm_session_message_free (reply);
- reply = NULL;
+ for (i = 0; i < 8; i++) {
+ if (g_random_int_range (0, 2) == 0) {
+ tmp[i] = g_random_int_range ('a', 'z' + 1);
+ } else {
+ tmp[i] = g_random_int_range ('A', 'Z' + 1);
}
}
- while (reply == NULL);
-
- /* FIXME: we have to do something better here. Messages
- * aren't gauranteed to be delivered synchronously. We need
- * to either fix that, or fix this to not expect them to be.
- */
- if (reply->type != GDM_SESSION_MESSAGE_TYPE_SECRET_INFO_REPLY) {
- g_debug ("discarding unexpected message of type 0x%x", reply->type);
- gdm_session_message_free (reply);
- return NULL;
- }
- secret_info_reply = (GdmSessionSecretInfoReplyMessage *) reply;
+ tmp[8] = '\0';
- answer = g_strdup (secret_info_reply->answer);
- gdm_session_message_free (reply);
-
- g_debug ("answer to secret question '%s' is '%s'", secret, answer);
- return answer;
-}
+ path = g_strdup_printf ("unix:abstract=/tmp/gdm-session-%s", tmp);
+#else
+ path = g_strdup ("unix:tmpdir=/tmp/gdm-session");
+#endif
-static void
-gdm_session_worker_report_info (GdmSessionWorker *worker,
- const char *info)
-{
- GdmSessionWorkerMessage *message;
- message = gdm_session_worker_info_message_new (info);
- gdm_write_message (worker->message_pipe_fd, message, message->size, NULL);
- gdm_session_worker_message_free (message);
+ return path;
}
static void
-gdm_session_worker_report_problem (GdmSessionWorker *worker,
- const char *problem)
-{
- GdmSessionWorkerMessage *message;
- message = gdm_session_worker_problem_message_new (problem);
- gdm_write_message (worker->message_pipe_fd, message, message->size, NULL);
- gdm_session_worker_message_free (message);
-}
-
-static gboolean
-gdm_session_worker_get_username (GdmSessionWorker *worker,
- char **username)
+session_unregister_handler (DBusConnection *connection,
+ void *user_data)
{
- gconstpointer item;
-
- g_assert (worker->pam_handle != NULL);
-
- if (pam_get_item (worker->pam_handle, PAM_USER, &item) == PAM_SUCCESS) {
- if (username) {
- *username = g_strdup ((char *) item);
- g_debug ("username is '%s'",
- *username != NULL ? *username :
- "<unset>");
- }
- return TRUE;
- }
-
- return FALSE;
+ g_debug ("session_unregister_handler");
}
-static void
-gdm_session_worker_update_username (GdmSessionWorker *worker)
+static DBusHandlerResult
+connection_filter_function (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
{
- char *username;
- gboolean res;
+ GdmSession *session = GDM_SESSION (user_data);
+ const char *path;
- username = NULL;
- res = gdm_session_worker_get_username (worker, &username);
- if (res) {
- GdmSessionWorkerMessage *message;
+ path = dbus_message_get_path (message);
- if ((worker->username == username) ||
- ((worker->username != NULL) && (username != NULL) &&
- (strcmp (worker->username, username) == 0)))
- goto out;
+ g_debug ("obj_path=%s interface=%s method=%s",
+ dbus_message_get_path (message),
+ dbus_message_get_interface (message),
+ dbus_message_get_member (message));
- g_debug ("setting username to '%s'", username);
+ if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected")
+ && strcmp (path, DBUS_PATH_LOCAL) == 0) {
- g_free (worker->username);
- worker->username = username;
- username = NULL;
+ g_debug ("Disconnected");
- message = gdm_session_worker_username_changed_message_new (worker->username);
- gdm_write_message (worker->message_pipe_fd, message, message->size, NULL);
- gdm_session_worker_message_free (message);
- }
+ dbus_connection_unref (connection);
+ session->priv->worker_connection = NULL;
- out:
- g_free (username);
-}
+ g_signal_emit (session, gdm_session_signals [CLOSED], 0);
+ } else if (dbus_message_is_signal (message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
-static gboolean
-gdm_session_worker_process_pam_message (GdmSessionWorker *worker,
- const struct pam_message *query,
- char **response_text)
-{
- char *user_answer;
- gboolean was_processed;
- g_debug ("received pam message of type %u with payload '%s'",
- query->msg_style, query->msg);
-
- user_answer = NULL;
- was_processed = FALSE;
- switch (query->msg_style) {
- case PAM_PROMPT_ECHO_ON:
- user_answer = gdm_session_worker_ask_question (worker, query->msg);
- break;
- case PAM_PROMPT_ECHO_OFF:
- user_answer = gdm_session_worker_ask_for_secret (worker, query->msg);
- break;
- case PAM_TEXT_INFO:
- gdm_session_worker_report_info (worker, query->msg);
- was_processed = TRUE;
- break;
- case PAM_ERROR_MSG:
- gdm_session_worker_report_problem (worker, query->msg);
- was_processed = TRUE;
- break;
- default:
- g_debug ("unknown query of type %u\n", query->msg_style);
- break;
- }
-
- if (user_answer != NULL) {
- /* we strdup and g_free to make sure we return malloc'd
- * instead of g_malloc'd memory
- */
- if (response_text != NULL) {
- *response_text = strdup (user_answer);
- }
-
- g_free (user_answer);
-
- g_debug ("trying to get updated username");
- gdm_session_worker_update_username (worker);
- was_processed = TRUE;
+ } else {
+ return session_message_handler (connection, message, user_data);
}
- return was_processed;
+ return DBUS_HANDLER_RESULT_HANDLED;
}
-static int
-gdm_session_worker_pam_new_messages_handler (int number_of_messages,
- const struct pam_message **messages,
- struct pam_response **responses,
- GdmSessionWorker *worker)
+static dbus_bool_t
+allow_user_function (DBusConnection *connection,
+ unsigned long uid,
+ void *data)
{
- struct pam_response *replies;
- int return_value;
- int i;
-
- g_debug ("%d new messages received from pam\n", number_of_messages);
-
- return_value = PAM_CONV_ERR;
-
- if (number_of_messages < 0) {
- return PAM_CONV_ERR;
- }
-
- if (number_of_messages == 0) {
- if (responses) {
- *responses = NULL;
- }
-
- return PAM_SUCCESS;
- }
-
- /* we want to generate one reply for every question
- */
- replies = (struct pam_response *) calloc (number_of_messages,
- sizeof (struct pam_response));
- for (i = 0; i < number_of_messages; i++) {
- gboolean got_response;
- char *response_text;
-
- response_text = NULL;
- got_response = gdm_session_worker_process_pam_message (worker,
- messages[i],
- &response_text);
- if (!got_response)
- goto out;
-
- g_debug ("answered pam message %d with response '%s'",
- i, response_text);
- replies[i].resp = response_text;
- replies[i].resp_retcode = PAM_SUCCESS;
- }
-
- return_value = PAM_SUCCESS;
-
- out:
- if (return_value != PAM_SUCCESS) {
- for (i = 0; i < number_of_messages; i++) {
- if (replies[i].resp != NULL) {
- memset (replies[i].resp, 0, strlen (replies[i].resp));
- free (replies[i].resp);
- }
- memset (&replies[i], 0, sizeof (replies[i]));
- }
- free (replies);
- replies = NULL;
+ if (0 == uid) {
+ return TRUE;
}
- if (responses) {
- *responses = replies;
- }
+ g_debug ("User not allowed");
- return return_value;
+ return FALSE;
}
static void
-gdm_session_worker_uninitialize_pam (GdmSessionWorker *worker,
- int error_code)
+handle_connection (DBusServer *server,
+ DBusConnection *new_connection,
+ void *user_data)
{
- g_debug ("uninitializing PAM");
-
- if (worker->pam_handle == NULL)
- return;
+ GdmSession *session = GDM_SESSION (user_data);
- if (worker->credentials_are_established) {
- pam_setcred (worker->pam_handle, PAM_DELETE_CRED);
- worker->credentials_are_established = FALSE;
- }
-
- if (worker->is_running) {
- pam_close_session (worker->pam_handle, 0);
- worker->is_running = FALSE;
- }
-
- pam_end (worker->pam_handle, error_code);
- worker->pam_handle = NULL;
-}
-
-static gboolean
-gdm_session_worker_initialize_pam (GdmSessionWorker *worker,
- const char *service,
- const char *username,
- const char *hostname,
- const char *console_name,
- GError **error)
-{
- struct pam_conv pam_conversation;
- int error_code;
-
- g_assert (worker->pam_handle == NULL);
-
- g_debug ("initializing PAM");
-
- pam_conversation.conv = (GdmSessionWorkerPamNewMessagesFunc) gdm_session_worker_pam_new_messages_handler;
- pam_conversation.appdata_ptr = worker;
-
- error_code = pam_start (service,
- username,
- &pam_conversation,
- &worker->pam_handle);
-
- if (error_code != PAM_SUCCESS) {
- g_debug ("could not initialize pam");
- /* we don't use pam_strerror here because it requires a valid
- * pam handle, and if pam_start fails pam_handle is undefined
- */
- g_set_error (error,
- GDM_SESSION_ERROR,
- GDM_SESSION_ERROR_AUTHENTICATING,
- _("error initiating conversation with authentication system - %s"),
- error_code == PAM_ABORT? _("general failure") :
- error_code == PAM_BUF_ERR? _("out of memory") :
- error_code == PAM_SYSTEM_ERR? _("application programmer error") :
- _("unscoped error"));
+ g_debug ("Handing new connection");
- goto out;
- }
+ if (session->priv->worker_connection == NULL) {
+ DBusObjectPathVTable vtable = { &session_unregister_handler,
+ &session_message_handler,
+ NULL, NULL, NULL, NULL
+ };
- if (username == NULL) {
- error_code = pam_set_item (worker->pam_handle, PAM_USER_PROMPT, _("Username:"));
-
- if (error_code != PAM_SUCCESS) {
- g_set_error (error,
- GDM_SESSION_ERROR,
- GDM_SESSION_ERROR_AUTHENTICATING,
- _("error informing authentication system of preferred username prompt - %s"),
- pam_strerror (worker->pam_handle, error_code));
- goto out;
- }
- }
+ session->priv->worker_connection = new_connection;
+ dbus_connection_ref (new_connection);
+ dbus_connection_setup_with_g_main (new_connection, NULL);
- if (hostname != NULL) {
- error_code = pam_set_item (worker->pam_handle, PAM_RHOST, hostname);
+ g_debug ("worker connection is %p", new_connection);
- if (error_code != PAM_SUCCESS) {
- g_set_error (error,
- GDM_SESSION_ERROR,
- GDM_SESSION_ERROR_AUTHENTICATING,
- _("error informing authentication system of user's hostname - %s"),
- pam_strerror (worker->pam_handle, error_code));
- goto out;
- }
- }
+ dbus_connection_add_filter (new_connection,
+ connection_filter_function,
+ session,
+ NULL);
- error_code = pam_set_item (worker->pam_handle, PAM_TTY, console_name);
+ dbus_connection_set_unix_user_function (new_connection,
+ allow_user_function,
+ session,
+ NULL);
- if (error_code != PAM_SUCCESS) {
- g_set_error (error,
- GDM_SESSION_ERROR,
- GDM_SESSION_ERROR_AUTHENTICATING,
- _("error informing authentication system of user's console - %s"),
- pam_strerror (worker->pam_handle, error_code));
- goto out;
- }
+ dbus_connection_register_object_path (new_connection,
+ "/",
+ &vtable,
+ session);
- out:
- if (error_code != PAM_SUCCESS) {
- gdm_session_worker_uninitialize_pam (worker, error_code);
- return FALSE;
+ g_debug ("Emitting opened signal");
+ g_signal_emit (session, gdm_session_signals [OPENED], 0);
}
-
- return TRUE;
}
static gboolean
-gdm_session_worker_authenticate_user (GdmSessionWorker *worker,
- gboolean password_is_required,
- GError **error)
+setup_server (GdmSession *session)
{
- int error_code;
- int authentication_flags;
+ DBusError error;
+ gboolean ret;
+ char *address;
+ const char *auth_mechanisms[] = {"EXTERNAL", NULL};
- g_debug ("authenticating user");
+ ret = FALSE;
- authentication_flags = 0;
+ g_debug ("Creating D-Bus server for session");
- if (password_is_required) {
- authentication_flags |= PAM_DISALLOW_NULL_AUTHTOK;
- }
+ address = generate_address ();
- /* blocking call, does the actual conversation
- */
- error_code = pam_authenticate (worker->pam_handle, authentication_flags);
+ dbus_error_init (&error);
+ session->priv->server = dbus_server_listen (address, &error);
+ g_free (address);
- if (error_code != PAM_SUCCESS) {
- g_set_error (error,
- GDM_SESSION_ERROR,
- GDM_SESSION_ERROR_AUTHENTICATING,
- "%s", pam_strerror (worker->pam_handle, error_code));
+ if (session->priv->server == NULL) {
+ g_warning ("Cannot create D-BUS server for the session: %s", error.message);
goto out;
}
- out:
- if (error_code != PAM_SUCCESS) {
- gdm_session_worker_uninitialize_pam (worker, error_code);
- return FALSE;
- }
+ dbus_server_setup_with_g_main (session->priv->server, NULL);
+ dbus_server_set_auth_mechanisms (session->priv->server, auth_mechanisms);
+ dbus_server_set_new_connection_function (session->priv->server,
+ handle_connection,
+ session,
+ NULL);
+ ret = TRUE;
- return TRUE;
-}
-
-static gboolean
-gdm_session_worker_authorize_user (GdmSessionWorker *worker,
- gboolean password_is_required,
- GError **error)
-{
- int error_code;
- int authentication_flags;
-
- g_debug ("determining if authenticated user is authorized to session");
+ g_free (session->priv->server_address);
+ session->priv->server_address = dbus_server_get_address (session->priv->server);
- authentication_flags = 0;
-
- if (password_is_required) {
- authentication_flags |= PAM_DISALLOW_NULL_AUTHTOK;
- }
-
- /* check that the account isn't disabled or expired
- */
- error_code = pam_acct_mgmt (worker->pam_handle, authentication_flags);
-
- /* it's possible that the user needs to change their password or pin code
- */
- if (error_code == PAM_NEW_AUTHTOK_REQD)
- error_code = pam_chauthtok (worker->pam_handle, PAM_CHANGE_EXPIRED_AUTHTOK);
-
- if (error_code != PAM_SUCCESS) {
- g_debug ("user is not authorized to log in: %s",
- pam_strerror (worker->pam_handle, error_code));
- g_set_error (error,
- GDM_SESSION_ERROR,
- GDM_SESSION_ERROR_AUTHORIZING,
- "%s", pam_strerror (worker->pam_handle, error_code));
- goto out;
- }
+ g_debug ("D-Bus server listening on %s", session->priv->server_address);
out:
- if (error_code != PAM_SUCCESS) {
- gdm_session_worker_uninitialize_pam (worker, error_code);
- return FALSE;
- }
- return TRUE;
+ return ret;
}
static void
-gdm_session_worker_set_environment_variable (GdmSessionWorker *worker,
- const char *environment_variable)
-{
- char **key_and_value;
-
- key_and_value = g_strsplit (environment_variable, "=", 2);
-
- /* FIXME: maybe we should use use pam_putenv instead of our
- * own hash table, so pam can override our choices if it knows
- * better?
- */
- g_hash_table_replace (worker->environment,
- key_and_value[0],
- key_and_value[1]);
-
- /* We are calling g_free instead of g_strfreev because the
- * hash table is taking over ownership of the individual
- * elements above
- */
- g_free (key_and_value);
-}
-
-static void
-gdm_session_worker_update_environment_from_passwd_entry (GdmSessionWorker *worker,
- struct passwd *passwd_entry)
-{
- char *environment_variable;
-
- environment_variable = g_strdup_printf ("LOGNAME=%s", worker->username);
- gdm_session_worker_set_environment_variable (worker, environment_variable);
- g_free (environment_variable);
-
- environment_variable = g_strdup_printf ("USER=%s", worker->username);
- gdm_session_worker_set_environment_variable (worker, environment_variable);
- g_free (environment_variable);
-
- environment_variable = g_strdup_printf ("USERNAME=%s", worker->username);
- gdm_session_worker_set_environment_variable (worker, environment_variable);
- g_free (environment_variable);
-
- environment_variable = g_strdup_printf ("HOME=%s", passwd_entry->pw_dir);
- gdm_session_worker_set_environment_variable (worker, environment_variable);
- g_free (environment_variable);
-
- environment_variable = g_strdup_printf ("SHELL=%s", passwd_entry->pw_shell);
- gdm_session_worker_set_environment_variable (worker, environment_variable);
- g_free (environment_variable);
-}
-
-static gboolean
-gdm_session_worker_environment_variable_is_set (GdmSessionWorker *worker,
- const char *name)
-{
- return g_hash_table_lookup (worker->environment, name) != NULL;
-}
-
-static gboolean
-gdm_session_worker_give_user_credentials (GdmSessionWorker *worker,
- GError **error)
+gdm_session_init (GdmSession *session)
{
- int error_code;
- struct passwd *passwd_entry, passwd_buffer;
- char *aux_buffer;
- long required_aux_buffer_size;
- gsize aux_buffer_size;
-
- aux_buffer = NULL;
- aux_buffer_size = 0;
-
- if (worker->username == NULL) {
- error_code = PAM_USER_UNKNOWN;
- g_set_error (error,
- GDM_SESSION_ERROR,
- GDM_SESSION_ERROR_GIVING_CREDENTIALS,
- _("no user account available"));
- goto out;
- }
-
- required_aux_buffer_size = sysconf (_SC_GETPW_R_SIZE_MAX);
-
- if (required_aux_buffer_size < 0)
- aux_buffer_size = GDM_PASSWD_AUXILLARY_BUFFER_SIZE;
- else
- aux_buffer_size = (gsize) required_aux_buffer_size;
-
- aux_buffer = g_slice_alloc0 (aux_buffer_size);
-
- /* we use the _r variant of getpwnam()
- * (with its weird semantics) so that the
- * passwd_entry doesn't potentially get stomped on
- * by a PAM module
- */
- passwd_entry = NULL;
- errno = getpwnam_r (worker->username, &passwd_buffer,
- aux_buffer, (size_t) aux_buffer_size,
- &passwd_entry);
-
- if (errno != 0) {
- error_code = PAM_SYSTEM_ERR;
- g_set_error (error, GDM_SESSION_ERROR,
- GDM_SESSION_ERROR_GIVING_CREDENTIALS,
- "%s", g_strerror (errno));
- goto out;
- }
-
- if (passwd_entry == NULL) {
- error_code = PAM_USER_UNKNOWN;
- g_set_error (error,
- GDM_SESSION_ERROR,
- GDM_SESSION_ERROR_GIVING_CREDENTIALS,
- _("user account not available on system"));
- goto out;
- }
-
- gdm_session_worker_update_environment_from_passwd_entry (worker, passwd_entry);
-
- /* Let's give the user a default PATH if he doesn't already have one
- */
- if (!gdm_session_worker_environment_variable_is_set (worker, "PATH"))
- gdm_session_worker_set_environment_variable (worker,
- "PATH=" GDM_SESSION_DEFAULT_PATH);
-
- /* pam_setcred wants to be called as the authenticated user
- * but pam_open_session needs to be called as super-user.
- *
- * Set the real uid and gid to the user and give the user a
- * temporary super-user effective id.
- */
- if (setreuid (passwd_entry->pw_uid, GDM_SESSION_ROOT_UID) < 0) {
- error_code = PAM_SYSTEM_ERR;
- g_set_error (error, GDM_SESSION_ERROR,
- GDM_SESSION_ERROR_GIVING_CREDENTIALS,
- "%s", g_strerror (errno));
- goto out;
- }
-
- if (setgid (passwd_entry->pw_gid) < 0) {
- error_code = PAM_SYSTEM_ERR;
- g_set_error (error, GDM_SESSION_ERROR,
- GDM_SESSION_ERROR_GIVING_CREDENTIALS,
- "%s", g_strerror (errno));
- goto out;
- }
-
- if (initgroups (passwd_entry->pw_name, passwd_entry->pw_gid) < 0) {
- error_code = PAM_SYSTEM_ERR;
- g_set_error (error, GDM_SESSION_ERROR,
- GDM_SESSION_ERROR_GIVING_CREDENTIALS,
- "%s", g_strerror (errno));
- goto out;
- }
-
- error_code = pam_setcred (worker->pam_handle, PAM_ESTABLISH_CRED);
-
- if (error_code != PAM_SUCCESS) {
- g_set_error (error,
- GDM_SESSION_ERROR,
- GDM_SESSION_ERROR_GIVING_CREDENTIALS,
- "%s", pam_strerror (worker->pam_handle, error_code));
- goto out;
- }
+ session->priv = G_TYPE_INSTANCE_GET_PRIVATE (session,
+ GDM_TYPE_SESSION,
+ GdmSessionPrivate);
- worker->credentials_are_established = TRUE;
+ session->priv->environment = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) g_free);
- out:
- if (aux_buffer != NULL) {
- g_assert (aux_buffer_size > 0);
- g_slice_free1 (aux_buffer_size, aux_buffer);
- }
-
- if (error_code != PAM_SUCCESS) {
- gdm_session_worker_uninitialize_pam (worker, error_code);
- return FALSE;
- }
-
- return TRUE;
+ setup_server (session);
}
-static gboolean
-gdm_session_worker_verify_user (GdmSessionWorker *worker,
- const char *service_name,
- const char *username,
- const char *hostname,
- const char *console_name,
- gboolean password_is_required,
- GError **error)
+GdmSession *
+gdm_session_new (void)
{
- GError *pam_error;
- GdmSessionWorkerMessage *reply;
- char *error_message;
- gboolean res;
-
- g_debug ("Verifying user: %s host: %s service: %s tty: %s", username, hostname, service_name, console_name);
-
- pam_error = NULL;
- res = gdm_session_worker_initialize_pam (worker,
- service_name,
- username,
- hostname,
- console_name,
- &pam_error);
- if (! res) {
- g_propagate_error (error, pam_error);
- return FALSE;
- }
-
- /* find out who the user is and ensure they are who they say they are
- */
- res = gdm_session_worker_authenticate_user (worker,
- password_is_required,
- &pam_error);
- if (! res) {
- g_propagate_error (error, pam_error);
- return FALSE;
- }
-
- /* we're authenticated. Let's make sure we've been given
- * a valid username for the system
- */
- g_debug ("trying to get updated username");
- gdm_session_worker_update_username (worker);
-
- /* make sure the user is allowed to log in to this system
- */
- res = gdm_session_worker_authorize_user (worker,
- password_is_required,
- &pam_error);
- if (! res) {
- g_propagate_error (error, pam_error);
- return FALSE;
- }
-
- /* get kerberos tickets, setup group lists, etc
- */
- res = gdm_session_worker_give_user_credentials (worker, &pam_error);
- if (! res) {
- g_propagate_error (error, pam_error);
- return FALSE;
- }
-
- g_debug ("verification process completed, creating reply...");
- reply = gdm_session_worker_verified_message_new ();
-
- error_message = NULL;
- res = gdm_write_message (worker->message_pipe_fd,
- reply,
- reply->size,
- &error_message);
- if (! res) {
- g_warning ("could not send 'verified' reply to parent: %s\n",
- error_message);
- g_free (error_message);
- }
+ GdmSession *session;
- gdm_session_worker_message_free (reply);
+ session = g_object_new (GDM_TYPE_SESSION, NULL);
- return TRUE;
+ return session;
}
static void
-gdm_session_worker_update_environment_from_pam (GdmSessionWorker *worker)
+worker_stopped (GdmSessionWorkerJob *job,
+ GdmSession *session)
{
- char **environment;
- gsize i;
-
- environment = pam_getenvlist (worker->pam_handle);
-
- for (i = 0; environment[i] != NULL; i++)
- gdm_session_worker_set_environment_variable (worker, environment[i]);
-
- for (i = 0; environment[i]; i++)
- free (environment[i]);
- free (environment);
+ g_debug ("Worker job stopped");
}
static void
-gdm_session_worker_fill_environment_array (const char *key,
- const char *value,
- GPtrArray *environment)
+worker_started (GdmSessionWorkerJob *job,
+ GdmSession *session)
{
- char *variable;
-
- if (value == NULL)
- return;
-
- variable = g_strdup_printf ("%s=%s", key, value);
-
- g_ptr_array_add (environment, variable);
-}
-
-static char **
-gdm_session_worker_get_environment (GdmSessionWorker *worker)
-{
- GPtrArray *environment;
-
- environment = g_ptr_array_new ();
- g_hash_table_foreach (worker->environment,
- (GHFunc) gdm_session_worker_fill_environment_array,
- environment);
- g_ptr_array_add (environment, NULL);
-
- return (char **) g_ptr_array_free (environment, FALSE);
+ g_debug ("Worker job started");
}
static void
-gdm_session_worker_on_child_exited (GPid pid,
- int status,
- GdmSessionWorker *worker)
+worker_exited (GdmSessionWorkerJob *job,
+ int code,
+ GdmSession *session)
{
- GdmSessionWorkerMessage *message;
+ g_debug ("Worker job exited: %d", code);
- message = NULL;
+ if (!session->priv->is_verified) {
+ GError *error;
- if (WIFEXITED (status))
- message = gdm_session_worker_session_exited_message_new (WEXITSTATUS (status));
- else if (WIFSIGNALED (status))
- message = gdm_session_worker_session_died_message_new (WTERMSIG (status));
+ error = g_error_new (GDM_SESSION_ERROR,
+ GDM_SESSION_ERROR_WORKER_DIED,
+ _("worker exited with status %d"),
+ code);
- if (message != NULL) {
- gdm_write_message (worker->message_pipe_fd, message, message->size, NULL);
- gdm_session_worker_message_free (message);
+ g_signal_emit (session,
+ gdm_session_signals [USER_VERIFICATION_ERROR],
+ 0, error);
+ g_error_free (error);
+ } else if (session->priv->is_running) {
+ g_signal_emit (session,
+ gdm_session_signals [SESSION_EXITED],
+ 0, code);
}
-
- g_spawn_close_pid (pid);
- worker->child_pid = 0;
-
- worker->exit_code = 0;
- g_main_loop_quit (worker->event_loop);
-}
-
-static void
-gdm_session_worker_watch_child (GdmSessionWorker *worker)
-{
- worker->child_watch_source = g_child_watch_source_new (worker->child_pid);
- g_source_set_callback (worker->child_watch_source,
- (GSourceFunc) (GChildWatchFunc)
- gdm_session_worker_on_child_exited,
- worker,
- (GDestroyNotify)
- gdm_session_worker_clear_child_watch_source);
- g_source_attach (worker->child_watch_source,
- g_main_loop_get_context (worker->event_loop));
- g_source_unref (worker->child_watch_source);
}
-/* adapted from glib script_execute */
static void
-script_execute (const gchar *file,
- char **argv,
- char **envp,
- gboolean search_path)
-{
- /* Count the arguments. */
- int argc = 0;
-
- while (argv[argc])
- ++argc;
-
- /* Construct an argument list for the shell. */
- {
- char **new_argv;
-
- new_argv = g_new0 (gchar*, argc + 2); /* /bin/sh and NULL */
-
- new_argv[0] = (char *) "/bin/sh";
- new_argv[1] = (char *) file;
- while (argc > 0) {
- new_argv[argc + 1] = argv[argc];
- --argc;
- }
-
- /* Execute the shell. */
- if (envp)
- execve (new_argv[0], new_argv, envp);
- else
- execv (new_argv[0], new_argv);
-
- g_free (new_argv);
- }
-}
-
-static char *
-my_strchrnul (const char *str, char c)
-{
- char *p = (char*) str;
- while (*p && (*p != c))
- ++p;
-
- return p;
-}
-
-/* adapted from glib g_execute */
-static gint
-gdm_session_execute (const char *file,
- char **argv,
- char **envp,
- gboolean search_path)
-{
- if (*file == '\0') {
- /* We check the simple case first. */
- errno = ENOENT;
- return -1;
- }
-
- if (!search_path || strchr (file, '/') != NULL) {
- /* Don't search when it contains a slash. */
- if (envp)
- execve (file, argv, envp);
- else
- execv (file, argv);
-
- if (errno == ENOEXEC)
- script_execute (file, argv, envp, FALSE);
- } else {
- gboolean got_eacces = 0;
- const char *path, *p;
- char *name, *freeme;
- gsize len;
- gsize pathlen;
-
- path = g_getenv ("PATH");
- if (path == NULL) {
- /* There is no `PATH' in the environment. The default
- * search path in libc is the current directory followed by
- * the path `confstr' returns for `_CS_PATH'.
- */
-
- /* In GLib we put . last, for security, and don't use the
- * unportable confstr(); UNIX98 does not actually specify
- * what to search if PATH is unset. POSIX may, dunno.
- */
-
- path = "/bin:/usr/bin:.";
- }
-
- len = strlen (file) + 1;
- pathlen = strlen (path);
- freeme = name = g_malloc (pathlen + len + 1);
-
- /* Copy the file name at the top, including '\0' */
- memcpy (name + pathlen + 1, file, len);
- name = name + pathlen;
- /* And add the slash before the filename */
- *name = '/';
-
- p = path;
- do {
- char *startp;
-
- path = p;
- p = my_strchrnul (path, ':');
-
- if (p == path)
- /* Two adjacent colons, or a colon at the beginning or the end
- * of `PATH' means to search the current directory.
- */
- startp = name + 1;
- else
- startp = memcpy (name - (p - path), path, p - path);
-
- /* Try to execute this name. If it works, execv will not return. */
- if (envp)
- execve (startp, argv, envp);
- else
- execv (startp, argv);
-
- if (errno == ENOEXEC)
- script_execute (startp, argv, envp, search_path);
-
- switch (errno) {
- case EACCES:
- /* Record the we got a `Permission denied' error. If we end
- * up finding no executable we can use, we want to diagnose
- * that we did find one but were denied access.
- */
- got_eacces = TRUE;
-
- /* FALL THRU */
-
- case ENOENT:
-#ifdef ESTALE
- case ESTALE:
-#endif
-#ifdef ENOTDIR
- case ENOTDIR:
-#endif
- /* Those errors indicate the file is missing or not executable
- * by us, in which case we want to just try the next path
- * directory.
- */
- break;
-
- default:
- /* Some other error means we found an executable file, but
- * something went wrong executing it; return the error to our
- * caller.
- */
- g_free (freeme);
- return -1;
- }
- } while (*p++ != '\0');
-
- /* We tried every element and none of them worked. */
- if (got_eacces)
- /* At least one failure was due to permissions, so report that
- * error.
- */
- errno = EACCES;
-
- g_free (freeme);
+worker_died (GdmSessionWorkerJob *job,
+ int signum,
+ GdmSession *session)
+{
+ g_debug ("Worker job died: %d", signum);
+
+ if (!session->priv->is_verified) {
+ GError *error;
+ error = g_error_new (GDM_SESSION_ERROR,
+ GDM_SESSION_ERROR_WORKER_DIED,
+ _("worker got signal '%s' and was subsequently killed"),
+ g_strsignal (signum));
+ g_signal_emit (session,
+ gdm_session_signals[USER_VERIFICATION_ERROR],
+ 0, error);
+ g_error_free (error);
+ } else if (session->priv->is_running) {
+ g_signal_emit (session,
+ gdm_session_signals[SESSION_EXITED],
+ 0, signum);
}
-
- /* Return the error from the last attempt (probably ENOENT). */
- return -1;
}
static gboolean
-gdm_session_worker_open_user_session (GdmSessionWorker *worker,
- GError **error)
+start_worker (GdmSession *session)
{
- int error_code;
- pid_t session_pid;
- GdmSessionWorkerMessage *message;
- char *error_message;
-
- g_assert (!worker->is_running);
- g_assert (geteuid () == 0);
- error_code = pam_open_session (worker->pam_handle, 0);
-
- if (error_code != PAM_SUCCESS) {
- g_set_error (error,
- GDM_SESSION_ERROR,
- GDM_SESSION_ERROR_OPENING_SESSION,
- "%s", pam_strerror (worker->pam_handle, error_code));
- goto out;
- }
- worker->is_running = TRUE;
-
- g_debug ("querying pam for user environment");
- gdm_session_worker_update_environment_from_pam (worker);
-
- g_debug ("opening user session with program '%s'",
- worker->arguments[0]);
-
- session_pid = fork ();
-
- if (session_pid < 0) {
- g_set_error (error,
- GDM_SESSION_ERROR,
- GDM_SESSION_ERROR_OPENING_SESSION,
- "%s", g_strerror (errno));
- error_code = PAM_ABORT;
- goto out;
- }
-
- if (session_pid == 0) {
- char **environment;
- char *home_dir;
- int fd;
-
- worker->inherited_fd_list = g_slist_append (NULL,
- GINT_TO_POINTER (worker->standard_output_fd));
- worker->inherited_fd_list = g_slist_append (worker->inherited_fd_list,
- GINT_TO_POINTER (worker->standard_error_fd));
-
-#if 0
- gdm_session_worker_close_open_fds (worker);
-#endif
-
- if (setuid (getuid ()) < 0) {
- g_debug ("could not reset uid - %s", g_strerror (errno));
- _exit (1);
- }
-
- if (setsid () < 0) {
- g_debug ("could not set pid '%u' as leader of new session and process group - %s",
- (guint) getpid (), g_strerror (errno));
- _exit (2);
- }
-
-#if 0
- fd = gdm_open_dev_null (O_RDWR);
-
- if (worker->standard_output_fd >= 0) {
- dup2 (worker->standard_output_fd, STDOUT_FILENO);
- close (worker->standard_output_fd);
- worker->standard_output_fd = -1;
- } else {
- dup2 (fd, STDOUT_FILENO);
- }
-
- if (worker->standard_error_fd >= 0) {
- dup2 (worker->standard_error_fd, STDERR_FILENO);
- close (worker->standard_error_fd);
- worker->standard_error_fd = -1;
- } else {
- dup2 (fd, STDERR_FILENO);
- }
-
- dup2 (fd, STDIN_FILENO);
- close (fd);
-#endif
-
- environment = gdm_session_worker_get_environment (worker);
-
- g_assert (geteuid () == getuid ());
-
- home_dir = g_hash_table_lookup (worker->environment,
- "HOME");
-
- if ((home_dir == NULL) || g_chdir (home_dir) < 0) {
- g_chdir ("/");
- }
-
- gdm_session_execute (worker->arguments[0],
- worker->arguments,
- environment,
- TRUE);
-
- g_debug ("child '%s' could not be started - %s",
- worker->arguments[0],
- g_strerror (errno));
- g_strfreev (environment);
-
- _exit (127);
- }
-
- worker->child_pid = session_pid;
-
- g_debug ("session opened creating reply...");
- g_assert (sizeof (GPid) <= sizeof (int));
-
- message = gdm_session_worker_session_started_message_new ((GPid) session_pid);
-
- error_message = NULL;
- if (!gdm_write_message (worker->message_pipe_fd,
- message, message->size,
- &error_message)) {
- g_warning ("could not send 'session started' reply to parent: %s\n",
- error_message);
- g_free (error_message);
- }
- gdm_session_worker_message_free (message);
-
- gdm_session_worker_watch_child (worker);
-
- out:
- if (error_code != PAM_SUCCESS) {
- gdm_session_worker_uninitialize_pam (worker, error_code);
- return FALSE;
- }
-
- return TRUE;
-}
-
-static GdmSessionWorkerMessage *
-gdm_session_worker_session_startup_failed_message_new (GError *error)
-{
- GdmSessionWorkerSessionStartupFailedMessage *message;
- gsize error_message_size, size;
-
- error_message_size = (error != NULL? strlen (error->message) + 1 : 0);
- size = sizeof (GdmSessionWorkerSessionStartupFailedMessage) +
- error_message_size +
- sizeof (GDM_SESSION_WORKER_MESSAGE_SENTINAL);
-
- message = g_slice_alloc0 (size);
-
- message->header.type = GDM_SESSION_WORKER_MESSAGE_TYPE_SESSION_STARTUP_FAILED;
- message->header.size = size;
-
- if (error != NULL) {
- message->error_domain = error->domain;
- message->error_code = error->code;
- g_strlcpy (message->error_message, error->message,
- error_message_size);
- message->error_message_size = error_message_size;
- } else {
- message->error_message_size = -1;
- }
-
- g_strlcpy ((char *) ((guint *) message) + size -
- sizeof (GDM_SESSION_WORKER_MESSAGE_SENTINAL),
- GDM_SESSION_WORKER_MESSAGE_SENTINAL,
- sizeof (GDM_SESSION_WORKER_MESSAGE_SENTINAL));
-
- return (GdmSessionWorkerMessage *) message;
-}
-
-static void
-gdm_session_worker_handle_verification_message (GdmSessionWorker *worker,
- GdmSessionVerificationMessage *message)
-{
- GError *verification_error;
- GdmSessionWorkerMessage *reply;
- gboolean res;
-
- worker->standard_output_fd = message->standard_output_fd;
- worker->standard_error_fd = message->standard_error_fd;
-
- verification_error = NULL;
- res = gdm_session_worker_verify_user (worker,
- message->service_name,
- (message->username_size >= 0) ? message->username : NULL,
- message->hostname_is_provided ? message->hostname : NULL,
- message->console_name,
- TRUE /* password is required */,
- &verification_error);
- if (! res) {
- g_assert (verification_error != NULL);
-
- g_message ("%s", verification_error->message);
-
- reply = gdm_session_worker_verification_failed_message_new (verification_error);
-
- g_error_free (verification_error);
-
- gdm_write_message (worker->message_pipe_fd, reply, reply->size, NULL);
- gdm_session_worker_message_free (reply);
- goto out;
- }
-
- /* Did start_program get called early? if so, process it now,
- * otherwise we'll do it asynchronously later.
- */
- if ((worker->arguments != NULL) &&
- !gdm_session_worker_open_user_session (worker, &verification_error)) {
- g_assert (verification_error != NULL);
-
- g_message ("%s", verification_error->message);
-
- reply = gdm_session_worker_session_startup_failed_message_new (verification_error);
-
- g_error_free (verification_error);
-
- gdm_write_message (worker->message_pipe_fd, reply, reply->size, NULL);
- gdm_session_worker_message_free (reply);
- goto out;
- }
-
- out:
- ;
-}
-
-static void
-gdm_session_worker_handle_start_program_message (GdmSessionWorker *worker,
- GdmSessionStartProgramMessage *message)
-{
- GError *start_error;
gboolean res;
- if (worker->arguments != NULL)
- g_strfreev (worker->arguments);
-
- worker->arguments = gdm_session_unflatten_arguments (message->arguments);
-
- /* Did start_program get called early? if so, we will process the request
- * later, synchronously after getting credentials
- */
- if (!worker->credentials_are_established)
- return;
-
- start_error = NULL;
- res = gdm_session_worker_open_user_session (worker, &start_error);
- if (! res) {
- GdmSessionWorkerMessage *message;
-
- g_assert (start_error != NULL);
-
- g_warning ("%s", start_error->message);
-
- message = gdm_session_worker_session_startup_failed_message_new (start_error);
-
- g_error_free (start_error);
-
- gdm_write_message (worker->message_pipe_fd, message, message->size, NULL);
- gdm_session_worker_message_free (message);
- }
+ session->priv->job = gdm_session_worker_job_new ();
+ gdm_session_worker_job_set_server_address (session->priv->job, session->priv->server_address);
+ g_signal_connect (session->priv->job,
+ "stopped",
+ G_CALLBACK (worker_stopped),
+ session);
+ g_signal_connect (session->priv->job,
+ "started",
+ G_CALLBACK (worker_started),
+ session);
+ g_signal_connect (session->priv->job,
+ "exited",
+ G_CALLBACK (worker_exited),
+ session);
+ g_signal_connect (session->priv->job,
+ "died",
+ G_CALLBACK (worker_died),
+ session);
+
+ res = gdm_session_worker_job_start (session->priv->job);
+
+ return res;
}
-static void
-gdm_session_worker_handle_set_environment_variable_message (GdmSessionWorker *worker,
- GdmSessionSetEnvironmentVariableMessage *message)
-{
- gdm_session_worker_set_environment_variable (worker,
- message->environment_variable);
-}
-
-static gboolean
-gdm_session_worker_process_asynchronous_message (GdmSessionWorker *worker,
- GdmSessionMessage *message)
+gboolean
+gdm_session_open (GdmSession *session,
+ const char *service_name,
+ const char *hostname,
+ const char *console_name,
+ GError **error)
{
- switch (message->type) {
- case GDM_SESSION_MESSAGE_TYPE_VERIFICATION:
- g_debug ("received verification request from parent");
- gdm_session_worker_handle_verification_message (worker,
- (GdmSessionVerificationMessage *) message);
- return TRUE;
+ gboolean res;
- case GDM_SESSION_MESSAGE_TYPE_START_PROGRAM:
- g_debug ("received new session arguments from parent");
- gdm_session_worker_handle_start_program_message (worker,
- (GdmSessionStartProgramMessage *)
- message);
- return TRUE;
+ g_return_val_if_fail (session != NULL, FALSE);
+ g_return_val_if_fail (service_name != NULL, FALSE);
+ g_return_val_if_fail (console_name != NULL, FALSE);
+ g_return_val_if_fail (hostname != NULL, FALSE);
- case GDM_SESSION_MESSAGE_TYPE_SET_ENVIRONMENT_VARIABLE:
- g_debug ("received new environment variable from parent");
- gdm_session_worker_handle_set_environment_variable_message (worker,
- (GdmSessionSetEnvironmentVariableMessage *)
- message);
- return TRUE;
+ res = start_worker (session);
- default:
- g_debug ("received unknown message with type '0x%x' from parent",
- message->type);
- return FALSE;
- }
+ session->priv->service_name = g_strdup (service_name);
+ session->priv->hostname = g_strdup (hostname);
+ session->priv->console_name = g_strdup (console_name);
- return FALSE;
+ return res;
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
static void
-gdm_session_worker_unwatch_child (GdmSessionWorker *worker)
+send_begin_verification (GdmSession *session)
{
- if (worker->child_watch_source == NULL)
- return;
+ DBusMessage *message;
+ DBusMessageIter iter;
- g_source_destroy (worker->child_watch_source);
- worker->child_watch_source = NULL;
-}
+ message = dbus_message_new_signal (GDM_SESSION_DBUS_PATH,
+ GDM_SESSION_DBUS_INTERFACE,
+ "BeginVerification");
-static int
-gdm_get_max_open_fds (void)
-{
- struct rlimit open_fd_limit;
- const int fallback_limit = GDM_MAX_OPEN_FILE_DESCRIPTORS;
-
- if (getrlimit (RLIMIT_NOFILE, &open_fd_limit) < 0) {
- g_debug ("could not get file descriptor limit: %s",
- g_strerror (errno));
- g_debug ("returning fallback file descriptor limit of %d",
- fallback_limit);
- return fallback_limit;
- }
+ dbus_message_iter_init_append (message, &iter);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &session->priv->service_name);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &session->priv->hostname);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &session->priv->console_name);
- if (open_fd_limit.rlim_cur == RLIM_INFINITY) {
- g_debug ("currently no file descriptor limit, returning fallback limit of %d",
- fallback_limit);
- return fallback_limit;
+ if (! send_dbus_message (session->priv->worker_connection, message)) {
+ g_debug ("Could not send %s signal", "BeginVerification");
}
- return (int) open_fd_limit.rlim_cur;
+ dbus_message_unref (message);
}
static void
-gdm_session_worker_close_all_fds (GdmSessionWorker *worker)
+send_begin_verification_for_user (GdmSession *session)
{
- int max_open_fds, fd;
-
- max_open_fds = gdm_get_max_open_fds ();
- g_debug ("closing all file descriptors except those that are specifically "
- "excluded");
-
- for (fd = 0; fd < max_open_fds; fd++) {
- GSList *node;
- for (node = worker->inherited_fd_list;
- node != NULL;
- node = node->next) {
- if (fd == GPOINTER_TO_INT (node->data))
- break;
- }
+ DBusMessage *message;
+ DBusMessageIter iter;
- if (node == NULL) {
- g_debug ("closing file descriptor '%d'", fd);
- close (fd);
- }
- }
+ message = dbus_message_new_signal (GDM_SESSION_DBUS_PATH,
+ GDM_SESSION_DBUS_INTERFACE,
+ "BeginVerificationForUser");
- g_debug ("closed first '%d' file descriptors", max_open_fds);
-}
+ dbus_message_iter_init_append (message, &iter);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &session->priv->service_name);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &session->priv->hostname);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &session->priv->console_name);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &session->priv->username);
-static void
-gdm_session_worker_close_open_fds (GdmSessionWorker *worker)
-{
- /* using DIR instead of GDir because we need access to dirfd so
- * that we can iterate through the fds and close them in one sweep.
- * (if we just closed all of them then we would close the one we're using
- * for reading the directory!)
- */
- DIR *dir;
- struct dirent *entry;
- int fd, opendir_fd;
- gboolean should_use_fallback;
-
- should_use_fallback = FALSE;
- opendir_fd = -1;
- return;
-
- dir = opendir (GDM_OPEN_FILE_DESCRIPTORS_DIR);
-
- if (dir != NULL) {
- opendir_fd = dirfd (dir);
- g_debug ("opened '"GDM_OPEN_FILE_DESCRIPTORS_DIR"' on file descriptor '%d'", opendir_fd);
+ if (! send_dbus_message (session->priv->worker_connection, message)) {
+ g_debug ("Could not send %s signal", "BeginVerificationForUser");
}
- if ((dir == NULL) || (opendir_fd < 0)) {
- g_debug ("could not open "GDM_OPEN_FILE_DESCRIPTORS_DIR": %s", g_strerror (errno));
- should_use_fallback = TRUE;
- } else {
- g_debug ("reading files in '"GDM_OPEN_FILE_DESCRIPTORS_DIR"'");
- while ((entry = readdir (dir)) != NULL) {
- GSList *node;
- glong filename_as_number;
- char *byte_after_number;
-
- if (entry->d_name[0] == '.')
- continue;
-
- g_debug ("scanning filename '%s' for file descriptor number",
- entry->d_name);
- fd = -1;
- filename_as_number = strtol (entry->d_name, &byte_after_number, 10);
-
- g_assert (byte_after_number != NULL);
-
- if ((*byte_after_number != '\0') ||
- (filename_as_number < 0) ||
- (filename_as_number >= G_MAXINT)) {
- g_debug ("filename '%s' does not appear to represent a "
- "file descriptor: %s",
- entry->d_name, strerror (errno));
- should_use_fallback = TRUE;
- } else {
- fd = (int) filename_as_number;
- g_debug ("filename '%s' represents file descriptor '%d'",
- entry->d_name, fd);
- should_use_fallback = FALSE;
- }
-
- for (node = worker->inherited_fd_list;
- node != NULL;
- node = node->next) {
- if (fd == GPOINTER_TO_INT (node->data))
- break;
- }
-
- if ((node == NULL) &&
- (fd != opendir_fd)) {
- g_debug ("closing file descriptor '%d'", fd);
- close (fd);
- } else {
- g_debug ("will not close file descriptor '%d' because it "
- "is still neded", fd);
- }
- }
- g_debug ("closing directory '"GDM_OPEN_FILE_DESCRIPTORS_DIR"'");
- closedir (dir);
- }
-
- /* if /proc isn't mounted or something else is screwy,
- * fall back to closing everything
- */
- if (should_use_fallback) {
- gdm_session_worker_close_all_fds (worker);
- }
+ dbus_message_unref (message);
}
-
-
-static GdmSessionWorkerMessage *
-gdm_session_worker_verified_message_new (void)
-{
- GdmSessionWorkerVerifiedMessage *message;
- gsize size;
-
- size = sizeof (GdmSessionWorkerVerifiedMessage) +
- sizeof (GDM_SESSION_WORKER_MESSAGE_SENTINAL);
-
- message = g_slice_alloc0 (size);
-
- message->header.type = GDM_SESSION_WORKER_MESSAGE_TYPE_VERIFIED;
- message->header.size = size;
-
- g_strlcpy ((char *) ((guint *) message) + size -
- sizeof (GDM_SESSION_WORKER_MESSAGE_SENTINAL),
- GDM_SESSION_WORKER_MESSAGE_SENTINAL,
- sizeof (GDM_SESSION_WORKER_MESSAGE_SENTINAL));
-
- return (GdmSessionWorkerMessage *) message;
-}
-
-static GdmSessionWorkerMessage *
-gdm_session_worker_verification_failed_message_new (GError *error)
-{
- GdmSessionWorkerVerificationFailedMessage *message;
- gsize error_message_size, size;
-
- error_message_size = (error != NULL? strlen (error->message) + 1 : 0);
- size = sizeof (GdmSessionWorkerVerificationFailedMessage) +
- error_message_size +
- sizeof (GDM_SESSION_WORKER_MESSAGE_SENTINAL);
-
- message = g_slice_alloc0 (size);
-
- message->header.type = GDM_SESSION_WORKER_MESSAGE_TYPE_VERIFICATION_FAILED;
- message->header.size = size;
-
- if (error != NULL) {
- message->error_domain = error->domain;
- message->error_code = error->code;
- g_strlcpy (message->error_message, error->message,
- error_message_size);
- message->error_message_size = error_message_size;
- } else {
- message->error_message_size = -1;
- }
-
- g_strlcpy ((char *) ((guint *) message) + size -
- sizeof (GDM_SESSION_WORKER_MESSAGE_SENTINAL),
- GDM_SESSION_WORKER_MESSAGE_SENTINAL,
- sizeof (GDM_SESSION_WORKER_MESSAGE_SENTINAL));
-
- return (GdmSessionWorkerMessage *) message;
-}
-
-static GdmSessionWorkerMessage *
-gdm_session_worker_info_request_message_new (const char *question)
-{
- GdmSessionWorkerInfoRequestMessage *message;
- gsize question_size, size;
-
- g_assert (question != NULL);
-
- question_size = strlen (question) + 1;
- size = sizeof (GdmSessionWorkerInfoRequestMessage) +
- question_size +
- sizeof (GDM_SESSION_MESSAGE_SENTINAL);
-
- message = g_slice_alloc0 (size);
-
- message->header.type = GDM_SESSION_WORKER_MESSAGE_TYPE_INFO_REQUEST;
- message->header.size = size;
-
- g_strlcpy (message->question, question, question_size);
-
- return (GdmSessionWorkerMessage *) message;
-}
-
-static GdmSessionWorkerMessage *
-gdm_session_worker_username_changed_message_new (const char *new_username)
+gboolean
+gdm_session_begin_verification (GdmSession *session,
+ const char *username,
+ GError **error)
{
- GdmSessionWorkerUsernameChangedMessage *message;
- gsize username_size, size;
-
- username_size = (new_username != NULL? strlen (new_username) + 1 : 0);
-
- size = sizeof (GdmSessionWorkerUsernameChangedMessage) +
- username_size +
- sizeof (GDM_SESSION_WORKER_MESSAGE_SENTINAL);
-
- message = g_slice_alloc0 (size);
+ g_return_val_if_fail (session != NULL, FALSE);
+ g_return_val_if_fail (dbus_connection_get_is_connected (session->priv->worker_connection), FALSE);
- message->header.type = GDM_SESSION_WORKER_MESSAGE_TYPE_USERNAME_CHANGED;
- message->header.size = size;
+ session->priv->username = g_strdup (username);
- if (new_username != NULL) {
- g_strlcpy (message->username, new_username, username_size);
- message->username_size = username_size;
+ if (username == NULL) {
+ send_begin_verification (session);
} else {
- message->username_size = -1;
- }
-
- g_strlcpy ((char *) ((guint *) message) + size -
- sizeof (GDM_SESSION_WORKER_MESSAGE_SENTINAL),
- GDM_SESSION_WORKER_MESSAGE_SENTINAL,
- sizeof (GDM_SESSION_WORKER_MESSAGE_SENTINAL));
-
- return (GdmSessionWorkerMessage *) message;
-}
-
-static GdmSessionWorkerMessage *
-gdm_session_worker_secret_info_request_message_new (const char *question)
-{
- GdmSessionWorkerSecretInfoRequestMessage *message;
- gsize question_size, size;
-
- g_assert (question != NULL);
-
- question_size = strlen (question) + 1;
-
- size = sizeof (GdmSessionWorkerSecretInfoRequestMessage) +
- question_size +
- sizeof (GDM_SESSION_WORKER_MESSAGE_SENTINAL);
-
- message = g_slice_alloc0 (size);
-
- message->header.type = GDM_SESSION_WORKER_MESSAGE_TYPE_SECRET_INFO_REQUEST;
- message->header.size = size;
-
- g_strlcpy (message->question, question, question_size);
- message->question_size = question_size;
-
- g_strlcpy ((char *) ((guint *) message) + size -
- sizeof (GDM_SESSION_WORKER_MESSAGE_SENTINAL),
- GDM_SESSION_WORKER_MESSAGE_SENTINAL,
- sizeof (GDM_SESSION_WORKER_MESSAGE_SENTINAL));
-
- return (GdmSessionWorkerMessage *) message;
-}
-
-static GdmSessionWorkerMessage *
-gdm_session_worker_info_message_new (const char *info)
-{
- GdmSessionWorkerInfoMessage *message;
- gsize info_size, size;
-
- g_assert (info != NULL);
-
- info_size = strlen (info) + 1;
-
- size = sizeof (GdmSessionWorkerInfoRequestMessage) +
- info_size +
- sizeof (GDM_SESSION_WORKER_MESSAGE_SENTINAL);
-
- message = g_slice_alloc0 (size);
-
- message->header.type = GDM_SESSION_WORKER_MESSAGE_TYPE_INFO;
- message->header.size = size;
-
- g_strlcpy (message->info, info, info_size);
- message->info_size = info_size;
-
- g_strlcpy ((char *) ((guint *) message) + size -
- sizeof (GDM_SESSION_WORKER_MESSAGE_SENTINAL),
- GDM_SESSION_WORKER_MESSAGE_SENTINAL,
- sizeof (GDM_SESSION_WORKER_MESSAGE_SENTINAL));
-
- return (GdmSessionWorkerMessage *) message;
-}
-
-static GdmSessionWorkerMessage *
-gdm_session_worker_problem_message_new (const char *problem)
-{
- GdmSessionWorkerProblemMessage *message;
- gsize problem_size, size;
-
- g_assert (problem != NULL);
-
- problem_size = strlen (problem) + 1;
-
- size = sizeof (GdmSessionWorkerProblemMessage) +
- problem_size +
- sizeof (GDM_SESSION_WORKER_MESSAGE_SENTINAL);
-
- message = g_slice_alloc0 (size);
-
- message->header.type = GDM_SESSION_WORKER_MESSAGE_TYPE_PROBLEM;
- message->header.size = size;
-
- g_strlcpy (message->problem, problem, problem_size);
- message->problem_size = problem_size;
-
- g_strlcpy ((char *) ((guint *) message) + size -
- sizeof (GDM_SESSION_WORKER_MESSAGE_SENTINAL),
- GDM_SESSION_WORKER_MESSAGE_SENTINAL,
- sizeof (GDM_SESSION_WORKER_MESSAGE_SENTINAL));
-
- return (GdmSessionWorkerMessage *) message;
-}
-
-static GdmSessionWorkerMessage *
-gdm_session_worker_session_started_message_new (GPid pid)
-{
- GdmSessionWorkerSessionStartedMessage *message;
- gsize size;
-
- size = sizeof (GdmSessionWorkerSessionStartedMessage) +
- sizeof (GDM_SESSION_WORKER_MESSAGE_SENTINAL);
-
- message = g_slice_alloc0 (size);
-
- message->header.type = GDM_SESSION_WORKER_MESSAGE_TYPE_SESSION_STARTED;
- message->header.size = size;
-
- message->pid = pid;
-
- g_strlcpy ((char *) ((guint *) message) + size -
- sizeof (GDM_SESSION_WORKER_MESSAGE_SENTINAL),
- GDM_SESSION_WORKER_MESSAGE_SENTINAL,
- sizeof (GDM_SESSION_WORKER_MESSAGE_SENTINAL));
-
- return (GdmSessionWorkerMessage *) message;
-}
-
-
-static GdmSessionWorkerMessage *
-gdm_session_worker_session_exited_message_new (int exit_code)
-{
- GdmSessionWorkerSessionExitedMessage *message;
- gsize size;
-
- size = sizeof (GdmSessionWorkerSessionExitedMessage) +
- sizeof (GDM_SESSION_WORKER_MESSAGE_SENTINAL);
-
- message = g_slice_alloc0 (size);
-
- message->header.type = GDM_SESSION_WORKER_MESSAGE_TYPE_SESSION_EXITED;
- message->header.size = size;
-
- message->exit_code = exit_code;
-
- g_strlcpy ((char *) ((guint *) message) + size -
- sizeof (GDM_SESSION_WORKER_MESSAGE_SENTINAL),
- GDM_SESSION_WORKER_MESSAGE_SENTINAL,
- sizeof (GDM_SESSION_WORKER_MESSAGE_SENTINAL));
-
- return (GdmSessionWorkerMessage *) message;
-}
-
-static GdmSessionWorkerMessage *
-gdm_session_worker_session_died_message_new (int signal_number)
-{
- GdmSessionWorkerSessionDiedMessage *message;
- gsize size;
-
- size = sizeof (GdmSessionWorkerSessionDiedMessage) +
- sizeof (GDM_SESSION_WORKER_MESSAGE_SENTINAL);
-
- message = g_slice_alloc0 (size);
-
- message->header.type = GDM_SESSION_WORKER_MESSAGE_TYPE_SESSION_EXITED;
- message->header.size = size;
-
- message->signal_number = signal_number;
-
- g_strlcpy ((char *) ((guint *) message) + size -
- sizeof (GDM_SESSION_WORKER_MESSAGE_SENTINAL),
- GDM_SESSION_WORKER_MESSAGE_SENTINAL,
- sizeof (GDM_SESSION_WORKER_MESSAGE_SENTINAL));
-
- return (GdmSessionWorkerMessage *) message;
-}
-
-static void
-gdm_session_worker_message_free (GdmSessionWorkerMessage *message)
-{
- g_slice_free1 (message->size, message);
-}
-
-static void
-gdm_session_worker_incoming_message_handler (GdmSessionWorker *worker)
-{
- GdmSessionMessage *message;
- GError *error;
-
- error = NULL;
- message = gdm_session_worker_get_incoming_message (worker, &error);
-
- if (message == NULL) {
- g_assert (error != NULL);
- g_warning ("could not receive message from parent: %s\n",
- error->message);
- g_error_free (error);
-
- /* FIXME: figure out what to do here
- */
- return;
- }
-
- gdm_session_worker_process_asynchronous_message (worker, message);
-
- gdm_session_message_free (message);
-}
-
-static gboolean
-gdm_session_worker_data_on_message_pipe_handler (GIOChannel *channel,
- GIOCondition condition,
- GdmSessionWorker *worker)
-{
- if ((condition & G_IO_IN) || (condition & G_IO_PRI)) {
- g_debug ("got message from message pipe");
- gdm_session_worker_incoming_message_handler (worker);
- }
-
- if ((condition & G_IO_ERR) || (condition & G_IO_HUP)) {
- g_debug ("got disconnected message from message pipe");
- gdm_session_worker_disconnected_handler (worker);
- return FALSE;
+ send_begin_verification_for_user (session);
}
return TRUE;
}
static void
-gdm_session_worker_watch_message_pipe (GdmSessionWorker *worker)
-{
- GIOChannel *io_channel;
-
- io_channel = g_io_channel_unix_new (worker->message_pipe_fd);
- g_io_channel_set_close_on_unref (io_channel, TRUE);
-
- worker->message_pipe_source = g_io_create_watch (io_channel,
- G_IO_IN | G_IO_HUP);
- g_io_channel_unref (io_channel);
-
- g_source_set_callback (worker->message_pipe_source,
- (GSourceFunc) (GIOFunc)
- gdm_session_worker_data_on_message_pipe_handler,
- worker,
- (GDestroyNotify)
- gdm_session_worker_clear_message_pipe_source);
- g_source_attach (worker->message_pipe_source,
- g_main_loop_get_context (worker->event_loop));
- g_source_unref (worker->message_pipe_source);
-}
-
-static void
-gdm_session_worker_wait_for_messages (GdmSessionWorker *worker)
-{
- gdm_session_worker_watch_message_pipe (worker);
-
- g_main_loop_run (worker->event_loop);
-}
-
-static gboolean
-gdm_open_bidirectional_pipe (int *fd1,
- int *fd2,
- char **error_message)
+send_environment_variable (const char *key,
+ const char *value,
+ GdmSession *session)
{
- int pipe_fds[2];
-
- g_assert (fd1 != NULL);
- g_assert (fd2 != NULL);
+ DBusMessage *message;
+ DBusMessageIter iter;
- if (socketpair (AF_UNIX, SOCK_DGRAM, 0, pipe_fds) < 0) {
- if (error_message != NULL)
- *error_message = g_strdup_printf ("%s",
- g_strerror (errno));
- return FALSE;
- }
+ message = dbus_message_new_signal (GDM_SESSION_DBUS_PATH,
+ GDM_SESSION_DBUS_INTERFACE,
+ "SetEnvironmentVariable");
- if (fcntl (pipe_fds[0], F_SETFD, FD_CLOEXEC) < 0) {
- if (error_message != NULL)
- *error_message = g_strdup_printf ("%s",
- g_strerror (errno));
- close (pipe_fds[0]);
- close (pipe_fds[1]);
- return FALSE;
- }
+ dbus_message_iter_init_append (message, &iter);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value);
- if (fcntl (pipe_fds[1], F_SETFD, FD_CLOEXEC) < 0) {
- if (error_message != NULL)
- *error_message = g_strdup_printf ("%s",
- g_strerror (errno));
- close (pipe_fds[0]);
- close (pipe_fds[1]);
- return FALSE;
+ if (! send_dbus_message (session->priv->worker_connection, message)) {
+ g_debug ("Could not send %s signal", "SetEnvironmentVariable");
}
- *fd1 = pipe_fds[0];
- *fd2 = pipe_fds[1];
-
- return TRUE;
-}
-
-static GdmSessionWorker *
-gdm_session_worker_new (void)
-{
- GdmSessionWorker *worker;
- GMainContext *context;
-
- worker = g_slice_new0 (GdmSessionWorker);
-
- context = g_main_context_new ();
- worker->event_loop = g_main_loop_new (context, FALSE);
- g_main_context_unref (context);
-
- worker->pam_handle = NULL;
-
- worker->message_pipe_fd = -1;
- worker->message_pipe_source = NULL;
-
- worker->inherited_fd_list = NULL;
-
- worker->username = NULL;
- worker->arguments = NULL;
-
- worker->environment = g_hash_table_new_full (g_str_hash,
- g_str_equal,
- (GDestroyNotify) g_free,
- (GDestroyNotify) g_free);
- worker->standard_output_fd = -1;
- worker->standard_error_fd = -1;
-
- worker->exit_code = 127;
-
- worker->credentials_are_established = FALSE;
- worker->is_running = FALSE;
-
- return worker;
+ dbus_message_unref (message);
}
static void
-gdm_session_worker_free (GdmSessionWorker *worker)
+send_environment (GdmSession *session)
{
- if (worker == NULL)
- return;
-
- gdm_session_worker_unwatch_child (worker);
-
- if (worker->message_pipe_fd != -1) {
- close (worker->message_pipe_fd);
- worker->message_pipe_fd = -1;
- }
-
- if (worker->username != NULL) {
- g_free (worker->username);
- worker->username = NULL;
- }
-
- if (worker->arguments != NULL) {
- g_strfreev (worker->arguments);
- worker->arguments = NULL;
- }
-
- if (worker->environment != NULL) {
- g_hash_table_destroy (worker->environment);
- worker->environment = NULL;
- }
-
- if (worker->standard_output_fd >= 0) {
- close (worker->standard_output_fd);
- worker->standard_output_fd = -1;
- }
-
- if (worker->standard_error_fd >= 0) {
- close (worker->standard_error_fd);
- worker->standard_error_fd = -1;
- }
- if (worker->event_loop != NULL) {
- g_main_loop_unref (worker->event_loop);
- worker->event_loop = NULL;
- }
-
- g_slice_free (GdmSessionWorker, worker);
-}
-
-static gboolean
-gdm_session_create_worker (GdmSession *session,
- int standard_output_fd,
- int standard_error_fd,
- int *worker_fd,
- GPid *worker_pid,
- GError **error)
-{
- GdmSessionWorker *worker;
- int session_message_pipe_fd, worker_message_pipe_fd;
- char *error_message;
- pid_t child_pid;
-
- session_message_pipe_fd = -1;
- worker_message_pipe_fd = -1;
- error_message = NULL;
- if (!gdm_open_bidirectional_pipe (&session_message_pipe_fd,
- &worker_message_pipe_fd,
- &error_message)) {
- g_debug ("unable open message pipe: %s", error_message);
- g_set_error (error,
- GDM_SESSION_ERROR,
- GDM_SESSION_ERROR_OPENING_MESSAGE_PIPE,
- "%s", error_message);
- g_free (error_message);
- return FALSE;
- }
-
- g_assert (session_message_pipe_fd >= 0);
- g_assert (worker_message_pipe_fd >= 0);
-
- child_pid = fork ();
-
- if (child_pid < 0) {
- g_set_error (error, GDM_SESSION_ERROR,
- GDM_SESSION_ERROR_FORKING,
- "%s", g_strerror (errno));
- return FALSE;
- }
-
- if (child_pid == 0) {
- GError *child_error;
- int fd;
-
- setsid ();
-
- worker = gdm_session_worker_new ();
- worker->message_pipe_fd = worker_message_pipe_fd;
- worker->inherited_fd_list =
- g_slist_append (worker->inherited_fd_list,
- GINT_TO_POINTER (worker->message_pipe_fd));
-
- if (standard_output_fd >= 0)
- worker->inherited_fd_list =
- g_slist_append (worker->inherited_fd_list,
- GINT_TO_POINTER (standard_output_fd));
- if (standard_error_fd >= 0)
- worker->inherited_fd_list =
- g_slist_append (worker->inherited_fd_list,
- GINT_TO_POINTER (standard_error_fd));
-
-#if 0
- gdm_session_worker_close_open_fds (worker);
-
- fd = gdm_open_dev_null (O_RDWR);
- dup2 (fd, STDIN_FILENO);
-
- if (standard_output_fd >= 0 &&
- standard_output_fd != STDOUT_FILENO)
- dup2 (standard_output_fd, STDOUT_FILENO);
- else
- dup2 (fd, STDOUT_FILENO);
-
- if (standard_error_fd >= 0 &&
- standard_error_fd != STDERR_FILENO)
- dup2 (standard_error_fd, STDERR_FILENO);
- else
- dup2 (fd, STDERR_FILENO);
- close (fd);
-#endif
-
- g_debug ("waiting for messages from parent");
- child_error = NULL;
-
- gdm_session_worker_wait_for_messages (worker);
-
- g_debug ("exiting with code '%d'", worker->exit_code);
- gdm_session_worker_free (worker);
- _exit (worker->exit_code);
- }
- close (worker_message_pipe_fd);
-
- g_assert (child_pid != 0);
- if (worker_pid != NULL)
- *worker_pid = (GPid) child_pid;
-
- if (worker_fd != NULL)
- *worker_fd = session_message_pipe_fd;
-
- return TRUE;
-}
-
-static gboolean
-gdm_session_open_with_worker (GdmSession *session,
- const char *service_name,
- const char *username,
- const char *hostname,
- const char *console_name,
- int standard_output_fd,
- int standard_error_fd,
- GError **error)
-{
- GdmSessionMessage *message;
- GError *worker_error;
- int worker_message_pipe_fd;
- GPid worker_pid;
- gboolean worker_is_created;
-
- worker_error = NULL;
- worker_is_created = gdm_session_create_worker (session,
- standard_output_fd,
- standard_error_fd,
- &worker_message_pipe_fd,
- &worker_pid,
- &worker_error);
- if (!worker_is_created) {
- g_debug ("worker could not be created");
- g_propagate_error (error, worker_error);
- return FALSE;
- }
-
- session->priv->service_name = g_strdup (service_name);
-
- session->priv->arguments = NULL;
- session->priv->username = g_strdup (username);
-
- session->priv->hostname = g_strdup (hostname);
- session->priv->console_name = g_strdup (console_name);
- session->priv->standard_output_fd = standard_output_fd;
- session->priv->standard_error_fd = standard_error_fd;
-
- session->priv->worker_message_pipe_fd = worker_message_pipe_fd;
- session->priv->worker_pid = worker_pid;
- session->priv->next_expected_message = GDM_SESSION_MESSAGE_TYPE_VERIFICATION;
- session->priv->query_answer = NULL;
-
- gdm_session_watch_child (session);
-
- message = gdm_session_verification_message_new (service_name,
- username,
- hostname,
- console_name,
- standard_output_fd,
- standard_error_fd);
- gdm_write_message (session->priv->worker_message_pipe_fd, message, message->size,
- NULL);
- gdm_session_message_free (message);
-
- return TRUE;
-}
-
-gboolean
-gdm_session_open (GdmSession *session,
- const char *service_name,
- const char *hostname,
- const char *console_name,
- int standard_output_fd,
- int standard_error_fd,
- GError **error)
-{
- g_return_val_if_fail (session != NULL, FALSE);
- g_return_val_if_fail (service_name != NULL, FALSE);
- g_return_val_if_fail (console_name != NULL, FALSE);
-
- return gdm_session_open_with_worker (session, service_name,
- NULL, hostname, console_name,
- standard_output_fd,
- standard_error_fd, error);
-}
-
-gboolean
-gdm_session_open_for_user (GdmSession *session,
- const char *service_name,
- const char *username,
- const char *hostname,
- const char *console_name,
- int standard_output_fd,
- int standard_error_fd,
- GError **error)
-{
- g_return_val_if_fail (session != NULL, FALSE);
- g_return_val_if_fail (service_name != NULL, FALSE);
- g_return_val_if_fail (username != NULL, FALSE);
- g_return_val_if_fail (console_name != NULL, FALSE);
-
- return gdm_session_open_with_worker (session,
- service_name,
- username, hostname, console_name,
- standard_output_fd,
- standard_error_fd, error);
+ g_hash_table_foreach (session->priv->environment,
+ (GHFunc) send_environment_variable,
+ session);
}
void
-gdm_session_start_program (GdmSession *session,
- int argc,
- const char **argv)
+gdm_session_start_program (GdmSession *session,
+ const char *command)
{
- GdmSessionMessage *message;
- int i;
-
g_return_if_fail (session != NULL);
g_return_if_fail (session != NULL);
g_return_if_fail (gdm_session_is_running (session) == FALSE);
- g_return_if_fail (argv != NULL);
- g_return_if_fail (argv[0] != NULL);
+ g_return_if_fail (command != NULL);
- session->priv->arguments = g_new0 (char *, (argc + 1));
+ send_environment (session);
- for (i = 0; argv[i] != NULL; i++) {
- session->priv->arguments[i] = g_strdup (argv[i]);
- }
-
- message = gdm_session_start_program_message_new (argv);
- gdm_write_message (session->priv->worker_message_pipe_fd,
- message,
- message->size,
- NULL);
- gdm_session_message_free (message);
+ send_dbus_string_signal (session, "StartProgram", command);
}
void
@@ -4020,21 +1499,13 @@ gdm_session_close (GdmSession *session)
{
g_return_if_fail (session != NULL);
- gdm_session_unwatch_child (session);
- session->priv->next_expected_message = GDM_SESSION_MESSAGE_TYPE_VERIFICATION;
-
- if (session->priv->worker_message_pipe_fd > 0) {
- close (session->priv->worker_message_pipe_fd);
- session->priv->worker_message_pipe_fd = -1;
- }
-
- if (session->priv->worker_pid > 0) {
- if (session->priv->is_running)
+ if (session->priv->job != NULL) {
+ if (session->priv->is_running) {
gdm_session_write_record (session,
GDM_SESSION_RECORD_TYPE_LOGOUT);
- kill (-session->priv->worker_pid, SIGTERM);
- waitpid (session->priv->worker_pid, NULL, 0);
- session->priv->worker_pid = -1;
+ }
+
+ gdm_session_worker_job_stop (session->priv->job);
}
session->priv->is_running = FALSE;
@@ -4045,11 +1516,6 @@ gdm_session_close (GdmSession *session)
session->priv->service_name = NULL;
}
- if (session->priv->arguments) {
- g_strfreev (session->priv->arguments);
- session->priv->arguments = NULL;
- }
-
if (session->priv->hostname) {
g_free (session->priv->hostname);
session->priv->hostname = NULL;
@@ -4059,69 +1525,38 @@ gdm_session_close (GdmSession *session)
g_free (session->priv->username);
session->priv->username = NULL;
}
-
}
gboolean
gdm_session_is_running (GdmSession *session)
{
+ g_return_val_if_fail (session != NULL, FALSE);
+
return session->priv->is_running;
}
void
-gdm_session_set_environment_variable (GdmSession *session,
- const char *key,
- const char *value)
+gdm_session_set_environment_variable (GdmSession *session,
+ const char *key,
+ const char *value)
{
- GdmSessionMessage *message;
-
g_return_if_fail (session != NULL);
g_return_if_fail (session != NULL);
g_return_if_fail (key != NULL);
g_return_if_fail (value != NULL);
- message = gdm_session_set_environment_variable_message_new (key, value);
- gdm_write_message (session->priv->worker_message_pipe_fd, message, message->size,
- NULL);
- gdm_session_message_free (message);
+ g_hash_table_replace (session->priv->environment,
+ g_strdup (key),
+ g_strdup (value));
}
void
-gdm_session_answer_query (GdmSession *session,
- const char *answer)
+gdm_session_answer_query (GdmSession *session,
+ const char *answer)
{
- GdmSessionMessage *reply;
-
g_return_if_fail (session != NULL);
- if (session->priv->query_answer != NULL)
- g_free (session->priv->query_answer);
-
- session->priv->query_answer = g_strdup (answer);
-
- reply = NULL;
- switch (session->priv->next_expected_message) {
- case GDM_SESSION_MESSAGE_TYPE_INFO_REPLY:
- reply = gdm_session_info_reply_message_new (session->priv->query_answer);
- break;
-
- case GDM_SESSION_MESSAGE_TYPE_SECRET_INFO_REPLY:
- reply = gdm_session_secret_info_reply_message_new (session->priv->query_answer);
- break;
-
- default:
- break;
- }
- g_free (session->priv->query_answer);
- session->priv->query_answer = NULL;
-
- if (reply != NULL) {
- gdm_write_message (session->priv->worker_message_pipe_fd, reply, reply->size,
- NULL);
- gdm_session_message_free (reply);
- }
-
- session->priv->next_expected_message = GDM_SESSION_MESSAGE_TYPE_INVALID;
+ answer_pending_query (session, answer);
}
char *