summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRobert Ancell <robert.ancell@canonical.com>2011-07-15 10:16:13 +1000
committerRobert Ancell <robert.ancell@canonical.com>2011-07-15 10:16:13 +1000
commitbb774efe7f674c8740781724280cb802c53d40a5 (patch)
treedc90493f19b3e6511952a8fe1e2836759be1d431 /src
parent747b5449507fa3e246367801814ebce11b1b3116 (diff)
downloadlightdm-bb774efe7f674c8740781724280cb802c53d40a5.tar.gz
Reworked X authority code
Diffstat (limited to 'src')
-rw-r--r--src/child-process.c8
-rw-r--r--src/display-manager.c35
-rw-r--r--src/display.c26
-rw-r--r--src/session.c54
-rw-r--r--src/session.h2
-rw-r--r--src/xauth.c312
-rw-r--r--src/xauth.h39
-rw-r--r--src/xdmcp-server.c4
-rw-r--r--src/xserver.c34
9 files changed, 404 insertions, 110 deletions
diff --git a/src/child-process.c b/src/child-process.c
index 8a81a81a..72689cf3 100644
--- a/src/child-process.c
+++ b/src/child-process.c
@@ -98,10 +98,7 @@ void
child_process_set_env (ChildProcess *process, const gchar *name, const gchar *value)
{
g_return_if_fail (process != NULL);
- if (value)
- g_hash_table_insert (process->priv->env, g_strdup (name), g_strdup (value));
- else
- g_hash_table_remove (process->priv->env, name);
+ g_hash_table_insert (process->priv->env, g_strdup (name), g_strdup (value));
}
static void
@@ -144,6 +141,7 @@ run_child_process (ChildProcess *process, char *const argv[])
close (fd);
/* Set environment */
+ clearenv ();
g_hash_table_iter_init (&iter, process->priv->env);
while (g_hash_table_iter_next (&iter, &key, &value))
g_setenv ((gchar *)key, (gchar *)value, TRUE);
@@ -205,7 +203,7 @@ run_child_process (ChildProcess *process, char *const argv[])
}
}
- execvp (argv[0], argv);
+ execv (argv[0], argv);
g_warning ("Error executing child process %s: %s", argv[0], g_strerror (errno));
_exit (EXIT_FAILURE);
diff --git a/src/display-manager.c b/src/display-manager.c
index e4531c0b..042ed013 100644
--- a/src/display-manager.c
+++ b/src/display-manager.c
@@ -126,13 +126,7 @@ start_session (Display *display, Session *session, gboolean is_greeter, DisplayM
authorization = xserver_get_authorization (display_get_xserver (display));
if (authorization)
- {
- gchar *path;
-
- path = get_authorization_path (manager);
- session_set_authorization (session, authorization, path);
- g_free (path);
- }
+ session_set_authorization (session, authorization);
if (is_greeter)
{
@@ -201,10 +195,13 @@ end_session_cb (Display *display, Session *session, DisplayManager *manager)
xserver = display_get_xserver (display);
if (xserver && xserver_get_server_type (xserver) == XSERVER_TYPE_LOCAL)
{
- XAuthorization *authorization;
+ XAuthorization *old_authorization, *authorization;
g_debug ("Generating new authorization cookie for %s", xserver_get_address (xserver));
- authorization = xauth_new_cookie ();
+ old_authorization = xserver_get_authorization (xserver);
+ authorization = xauth_new_cookie (xauth_get_family (old_authorization),
+ xauth_get_address (old_authorization),
+ xauth_get_number (old_authorization));
xserver_set_authorization (xserver, authorization, xserver_get_authorization_path (xserver));
g_object_unref (authorization);
}
@@ -298,13 +295,19 @@ make_xserver (DisplayManager *manager, gchar *config_section)
string_to_xdm_auth_key (key, data);
xserver_set_authentication (xserver, "XDM-AUTHENTICATION-1", data, 8);
- authorization = xauth_new ("XDM-AUTHORIZATION-1", data, 8);
+ authorization = xauth_new (XAUTH_FAMILY_WILD, "", "", "XDM-AUTHORIZATION-1", data, 8);
}
}
else
{
+ gchar *number;
+ gchar hostname[1024];
+
xserver = xserver_new (XSERVER_TYPE_LOCAL, NULL, display_number);
- authorization = xauth_new_cookie ();
+ number = g_strdup_printf ("%d", display_number);
+ gethostname (hostname, 1024);
+ authorization = xauth_new_cookie (XAUTH_FAMILY_LOCAL, hostname, number);
+ g_free (number);
}
g_free (xdmcp_manager);
@@ -476,7 +479,7 @@ xdmcp_session_cb (XDMCPServer *server, XDMCPSession *session, DisplayManager *ma
gchar *address;
XServer *xserver;
gboolean result;
-
+
// FIXME: Try IPv6 then fallback to IPv4
address = g_inet_address_to_string (G_INET_ADDRESS (xdmcp_session_get_address (session)));
@@ -487,10 +490,16 @@ xdmcp_session_cb (XDMCPServer *server, XDMCPSession *session, DisplayManager *ma
{
XAuthorization *authorization = NULL;
gchar *path;
+ gchar *number;
- authorization = xauth_new (xdmcp_session_get_authorization_name (session),
+ number = g_strdup_printf ("%d", xdmcp_session_get_display_number (session));
+ authorization = xauth_new (XAUTH_FAMILY_INTERNET, // FIXME: Handle IPv6
+ address,
+ number,
+ xdmcp_session_get_authorization_name (session),
xdmcp_session_get_authorization_data (session),
xdmcp_session_get_authorization_data_length (session));
+ g_free (number);
path = get_authorization_path (manager);
xserver_set_authorization (xserver, authorization, path);
diff --git a/src/display.c b/src/display.c
index b7147b85..8ffb8485 100644
--- a/src/display.c
+++ b/src/display.c
@@ -585,10 +585,23 @@ start_user_session (Display *display, const gchar *session)
session_set_user (display->priv->user_session, user);
session_set_command (display->priv->user_session, session_command);
+ child_process_set_env (CHILD_PROCESS (display->priv->user_session), "PATH", "/usr/local/bin:/usr/bin:/bin");
+ child_process_set_env (CHILD_PROCESS (display->priv->user_session), "USER", user_get_name (user));
+ child_process_set_env (CHILD_PROCESS (display->priv->user_session), "USERNAME", user_get_name (user)); // FIXME: Is this required?
+ child_process_set_env (CHILD_PROCESS (display->priv->user_session), "HOME", user_get_home_directory (user));
+ child_process_set_env (CHILD_PROCESS (display->priv->user_session), "SHELL", user_get_shell (user));
child_process_set_env (CHILD_PROCESS (display->priv->user_session), "DESKTOP_SESSION", session); // FIXME: Apparently deprecated?
child_process_set_env (CHILD_PROCESS (display->priv->user_session), "GDMSESSION", session); // FIXME: Not cross-desktop
child_process_set_env (CHILD_PROCESS (display->priv->user_session), "DISPLAY", xserver_get_address (display->priv->xserver));
set_env_from_pam_session (display->priv->user_session, display->priv->user_pam_session);
+
+ /* Variable required for regression tests */
+ if (getenv ("LIGHTDM_TEST_STATUS_SOCKET"))
+ {
+ child_process_set_env (CHILD_PROCESS (display->priv->user_session), "LIGHTDM_TEST_STATUS_SOCKET", getenv ("LIGHTDM_TEST_STATUS_SOCKET"));
+ child_process_set_env (CHILD_PROCESS (display->priv->user_session), "LIGHTDM_TEST_CONFIG", getenv ("LIGHTDM_TEST_CONFIG"));
+ child_process_set_env (CHILD_PROCESS (display->priv->user_session), "LIGHTDM_TEST_HOME_DIR", getenv ("LIGHTDM_TEST_HOME_DIR"));
+ }
g_object_unref (user);
g_free (session_command);
@@ -780,11 +793,24 @@ start_greeter (Display *display)
command = theme_get_command (theme);
session_set_command (SESSION (display->priv->greeter_session), command);
g_free (command);
+
+ child_process_set_env (CHILD_PROCESS (display->priv->greeter_session), "PATH", "/usr/local/bin:/usr/bin:/bin");
+ child_process_set_env (CHILD_PROCESS (display->priv->greeter_session), "USER", user_get_name (user));
+ child_process_set_env (CHILD_PROCESS (display->priv->greeter_session), "HOME", user_get_home_directory (user));
+ child_process_set_env (CHILD_PROCESS (display->priv->greeter_session), "SHELL", user_get_shell (user));
child_process_set_env (CHILD_PROCESS (display->priv->greeter_session), "DISPLAY", xserver_get_address (display->priv->xserver));
if (display->priv->greeter_ck_cookie)
child_process_set_env (CHILD_PROCESS (display->priv->greeter_session), "XDG_SESSION_COOKIE", display->priv->greeter_ck_cookie);
set_env_from_pam_session (SESSION (display->priv->greeter_session), display->priv->greeter_pam_session);
+ /* Variable required for regression tests */
+ if (getenv ("LIGHTDM_TEST_STATUS_SOCKET"))
+ {
+ child_process_set_env (CHILD_PROCESS (display->priv->greeter_session), "LIGHTDM_TEST_STATUS_SOCKET", getenv ("LIGHTDM_TEST_STATUS_SOCKET"));
+ child_process_set_env (CHILD_PROCESS (display->priv->greeter_session), "LIGHTDM_TEST_CONFIG", getenv ("LIGHTDM_TEST_CONFIG"));
+ child_process_set_env (CHILD_PROCESS (display->priv->greeter_session), "LIGHTDM_TEST_HOME_DIR", getenv ("LIGHTDM_TEST_HOME_DIR"));
+ }
+
g_signal_emit (display, signals[START_GREETER], 0, display->priv->greeter_session);
result = session_start (SESSION (display->priv->greeter_session), TRUE);
diff --git a/src/session.c b/src/session.c
index 61267f01..937e4d93 100644
--- a/src/session.c
+++ b/src/session.c
@@ -23,18 +23,11 @@ struct SessionPrivate
/* User running this session */
User *user;
- /* Path of file to log to */
- gchar *log_file;
-
- /* Environment variables */
- GHashTable *env;
-
/* Command to run for this session */
gchar *command;
/* X authorization */
XAuthorization *authorization;
- gchar *authorization_path;
GFile *authorization_file;
};
@@ -80,15 +73,13 @@ session_get_command (Session *session)
}
void
-session_set_authorization (Session *session, XAuthorization *authorization, const gchar *path)
+session_set_authorization (Session *session, XAuthorization *authorization)
{
g_return_if_fail (session != NULL);
if (session->priv->authorization)
g_object_unref (session->priv->authorization);
session->priv->authorization = g_object_ref (authorization);
- g_free (session->priv->authorization_path);
- session->priv->authorization_path = g_strdup (path);
}
XAuthorization *
@@ -104,23 +95,29 @@ session_start (Session *session, gboolean create_pipe)
//gint session_stdin, session_stdout, session_stderr;
gboolean result;
GError *error = NULL;
+ gchar *full_path;
g_return_val_if_fail (session != NULL, FALSE);
g_return_val_if_fail (session->priv->user != NULL, FALSE);
g_return_val_if_fail (session->priv->command != NULL, FALSE);
- child_process_set_env (CHILD_PROCESS (session), "USER", user_get_name (session->priv->user));
- child_process_set_env (CHILD_PROCESS (session), "USERNAME", user_get_name (session->priv->user)); // FIXME: Is this required?
- child_process_set_env (CHILD_PROCESS (session), "HOME", user_get_home_directory (session->priv->user));
- child_process_set_env (CHILD_PROCESS (session), "SHELL", user_get_shell (session->priv->user));
+ full_path = g_find_program_in_path (session->priv->command);
+ if (!full_path)
+ {
+ g_debug ("Can't launch session %s, not found in path", session->priv->command);
+ return FALSE;
+ }
if (session->priv->authorization)
{
- g_debug ("Writing session authority to %s", session->priv->authorization_path);
- session->priv->authorization_file = xauth_write (session->priv->authorization, session->priv->user, session->priv->authorization_path, &error);
- if (session->priv->authorization_file)
- child_process_set_env (CHILD_PROCESS (session), "XAUTHORITY", session->priv->authorization_path);
- else
+ gchar *path;
+
+ path = g_build_filename (user_get_home_directory (session->priv->user), ".Xauthority", NULL);
+ session->priv->authorization_file = g_file_new_for_path (path);
+ g_free (path);
+
+ g_debug ("Adding session authority to %s", g_file_get_path (session->priv->authorization_file));
+ if (!xauth_update (session->priv->authorization, session->priv->user, session->priv->authorization_file, &error))
g_warning ("Failed to write authorization: %s", error->message);
g_clear_error (&error);
}
@@ -130,9 +127,10 @@ session_start (Session *session, gboolean create_pipe)
result = child_process_start (CHILD_PROCESS (session),
session->priv->user,
user_get_home_directory (session->priv->user),
- session->priv->command,
+ full_path,
create_pipe,
&error);
+ g_free (full_path);
if (!result)
g_warning ("Failed to spawn session: %s", error->message);
@@ -152,7 +150,6 @@ static void
session_init (Session *session)
{
session->priv = G_TYPE_INSTANCE_GET_PRIVATE (session, SESSION_TYPE, SessionPrivate);
- session->priv->env = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
}
static void
@@ -161,18 +158,19 @@ session_finalize (GObject *object)
Session *self;
self = SESSION (object);
+
+ if (self->priv->authorization_file)
+ {
+ g_debug ("Removing session authority from %s", g_file_get_path (self->priv->authorization_file));
+ xauth_remove (self->priv->authorization, self->priv->user, self->priv->authorization_file, NULL);
+ g_object_unref (self->priv->authorization_file);
+ }
+
if (self->priv->user)
g_object_unref (self->priv->user);
- g_hash_table_unref (self->priv->env);
g_free (self->priv->command);
if (self->priv->authorization)
g_object_unref (self->priv->authorization);
- g_free (self->priv->authorization_path);
- if (self->priv->authorization_file)
- {
- g_file_delete (self->priv->authorization_file, NULL, NULL);
- g_object_unref (self->priv->authorization_file);
- }
G_OBJECT_CLASS (session_parent_class)->finalize (object);
}
diff --git a/src/session.h b/src/session.h
index 7383e742..7e79b3a9 100644
--- a/src/session.h
+++ b/src/session.h
@@ -46,7 +46,7 @@ void session_set_command (Session *session, const gchar *command);
const gchar *session_get_command (Session *session);
-void session_set_authorization (Session *session, XAuthorization *authorization, const gchar *path);
+void session_set_authorization (Session *session, XAuthorization *authorization);
XAuthorization *session_get_authorization (Session *session);
diff --git a/src/xauth.c b/src/xauth.c
index e4593648..72df2ca3 100644
--- a/src/xauth.c
+++ b/src/xauth.c
@@ -18,57 +18,135 @@
struct XAuthorizationPrivate
{
+ /* Protocol family */
+ guint16 family;
+
+ /* Host address of X server */
+ gchar *address;
+
+ /* Display number of X server */
+ gchar *number;
+
/* Authorization scheme */
gchar *authorization_name;
/* Authorization data */
- guchar *authorization_data;
+ guint8 *authorization_data;
gsize authorization_data_length;
};
G_DEFINE_TYPE (XAuthorization, xauth, G_TYPE_OBJECT);
XAuthorization *
-xauth_new (const gchar *name, const guchar *data, gsize data_length)
+xauth_new (guint16 family, const gchar *address, const gchar *number, const gchar *name, const guint8 *data, gsize data_length)
{
XAuthorization *auth = g_object_new (XAUTH_TYPE, NULL);
- auth->priv->authorization_name = g_strdup (name);
- auth->priv->authorization_data = g_malloc (data_length);
- auth->priv->authorization_data_length = data_length;
- memcpy (auth->priv->authorization_data, data, data_length);
+ xauth_set_family (auth, family);
+ xauth_set_address (auth, address);
+ xauth_set_number (auth, number);
+ xauth_set_authorization_name (auth, name);
+ xauth_set_authorization_data (auth, data, data_length);
return auth;
}
XAuthorization *
-xauth_new_cookie (void)
+xauth_new_cookie (guint16 family, const gchar *address, const gchar *number)
{
- guchar cookie[16];
+ guint8 cookie[16];
gint i;
for (i = 0; i < 16; i++)
cookie[i] = g_random_int () & 0xFF;
- return xauth_new ("MIT-MAGIC-COOKIE-1", cookie, 16);
+ return xauth_new (family, address, number, "MIT-MAGIC-COOKIE-1", cookie, 16);
+}
+
+void
+xauth_set_family (XAuthorization *auth, guint16 family)
+{
+ g_return_if_fail (auth != NULL);
+ auth->priv->family = family;
+}
+
+guint16
+xauth_get_family (XAuthorization *auth)
+{
+ g_return_val_if_fail (auth != NULL, 0);
+ return auth->priv->family;
+}
+
+void
+xauth_set_address (XAuthorization *auth, const gchar *address)
+{
+ g_return_if_fail (auth != NULL);
+ g_free (auth->priv->address);
+ auth->priv->address = g_strdup (address);
+}
+
+const gchar *
+xauth_get_address (XAuthorization *auth)
+{
+ g_return_val_if_fail (auth != NULL, NULL);
+ return auth->priv->address;
+}
+
+void
+xauth_set_number (XAuthorization *auth, const gchar *number)
+{
+ g_return_if_fail (auth != NULL);
+ g_free (auth->priv->number);
+ auth->priv->number = g_strdup (number);
+}
+
+const gchar *
+xauth_get_number (XAuthorization *auth)
+{
+ g_return_val_if_fail (auth != NULL, NULL);
+ return auth->priv->number;
+}
+
+void
+xauth_set_authorization_name (XAuthorization *auth, const gchar *name)
+{
+ g_return_if_fail (auth != NULL);
+ g_free (auth->priv->authorization_name);
+ auth->priv->authorization_name = g_strdup (name);
}
const gchar *
xauth_get_authorization_name (XAuthorization *auth)
{
+ g_return_val_if_fail (auth != NULL, NULL);
return auth->priv->authorization_name;
}
-const guchar *
+void
+xauth_set_authorization_data (XAuthorization *auth, const guint8 *data, gsize data_length)
+{
+ g_return_if_fail (auth != NULL);
+ g_free (auth->priv->authorization_data);
+ auth->priv->authorization_data = g_malloc (data_length);
+ memcpy (auth->priv->authorization_data, data, data_length);
+ auth->priv->authorization_data_length = data_length;
+}
+
+const guint8 *
xauth_get_authorization_data (XAuthorization *auth)
{
+ g_return_val_if_fail (auth != NULL, NULL);
return auth->priv->authorization_data;
}
-guchar *
+guint8 *
xauth_copy_authorization_data (XAuthorization *auth)
{
- guchar *data = g_malloc (auth->priv->authorization_data_length);
+ guint8 *data;
+
+ g_return_val_if_fail (auth != NULL, NULL);
+
+ data = g_malloc (auth->priv->authorization_data_length);
memcpy (data, auth->priv->authorization_data, auth->priv->authorization_data_length);
return data;
}
@@ -76,81 +154,211 @@ xauth_copy_authorization_data (XAuthorization *auth)
gsize
xauth_get_authorization_data_length (XAuthorization *auth)
{
+ g_return_val_if_fail (auth != NULL, 0);
return auth->priv->authorization_data_length;
}
-static void
-write_uint16 (GString *string, guint16 value)
+static guint16
+read_uint16 (GInputStream *stream, gboolean *eof, GError **error)
+{
+ guint8 data[2] = {0, 0};
+ gsize n_read;
+
+ if (error && *error)
+ return 0;
+
+ if (g_input_stream_read_all (stream, data, 2, &n_read, NULL, error) < 0)
+ return 0;
+
+ if (n_read == 0 && eof)
+ *eof = TRUE;
+
+ return data[0] << 8 | data[1];
+}
+
+static guint8 *
+read_data (GInputStream *stream, guint16 length, GError **error)
{
- g_string_append_c (string, (gchar) (value >> 8));
- g_string_append_c (string, (gchar) value);
+ guint8 *data;
+
+ if (error && *error)
+ return NULL;
+
+ data = g_malloc0 (length + 1);
+ if (g_input_stream_read_all (stream, data, length, NULL, NULL, error) < 0)
+ {
+ g_free (data);
+ return NULL;
+ }
+ data[length] = 0;
+
+ return data;
+}
+
+static gchar *
+read_string (GInputStream *stream, GError **error)
+{
+ guint16 length;
+ length = read_uint16 (stream, NULL, error);
+ return (gchar *) read_data (stream, length, error);
}
static void
-write_data (GString *string, guchar *value, gsize value_len)
+write_uint16 (GOutputStream *stream, guint16 value, GError **error)
{
- g_string_append_len (string, (gchar *) value, value_len);
+ guint8 data[2];
+
+ if (error && *error)
+ return;
+
+ data[0] = value >> 8;
+ data[1] = value & 0xFF;
+ g_output_stream_write (stream, data, 2, NULL, error);
}
static void
-write_string (GString *string, const gchar *value)
+write_data (GOutputStream *stream, const guint8 *data, gsize data_length, GError **error)
{
- write_uint16 (string, strlen (value));
- g_string_append (string, value);
+ if (error && *error)
+ return;
+ g_output_stream_write (stream, data, data_length, NULL, error);
}
-GFile *
-xauth_write (XAuthorization *auth, User *user, const gchar *path, GError **error)
+static void
+write_string (GOutputStream *stream, const gchar *value, GError **error)
{
- GFile *file;
- GFileOutputStream *stream;
- GString *data;
- gboolean result;
- gsize n_written;
+ write_uint16 (stream, strlen (value), error);
+ write_data (stream, (guint8 *) value, strlen (value), error);
+}
- file = g_file_new_for_path (path);
+static gboolean
+xauth_merge (XAuthorization *auth, gboolean delete, User *user, GFile *file, GError **error)
+{
+ GList *link, *records = NULL;
+ GFileInputStream *input_stream;
+ GFileOutputStream *output_stream;
+ XAuthorization *a;
+ gboolean matched = FALSE;
+
+ /* Read out existing records */
+ input_stream = g_file_read (file, NULL, error);
+ if (!input_stream && error && !g_error_matches (*error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
+ return FALSE;
- stream = g_file_replace (file, NULL, FALSE, G_FILE_CREATE_PRIVATE, NULL, error);
- if (!stream)
+ while (input_stream)
{
- g_object_unref (file);
+ guint16 family;
+ gboolean eof = FALSE;
+
+ family = read_uint16 (G_INPUT_STREAM (input_stream), &eof, error);
+ if (eof)
+ break;
+
+ a = g_object_new (XAUTH_TYPE, NULL);
+ a->priv->family = family;
+ a->priv->address = read_string (G_INPUT_STREAM (input_stream), error);
+ a->priv->number = read_string (G_INPUT_STREAM (input_stream), error);
+ a->priv->authorization_name = read_string (G_INPUT_STREAM (input_stream), error);
+ a->priv->authorization_data_length = read_uint16 (G_INPUT_STREAM (input_stream), NULL, error);
+ a->priv->authorization_data = read_data (G_INPUT_STREAM (input_stream), a->priv->authorization_data_length, error);
+
+ if (error && *error)
+ {
+ g_warning ("Error reading X authority %s: %s", g_file_get_path (file), (*error)->message);
+ g_clear_error (error);
+ break;
+ }
+
+ /* If this record matches, then update or delete it */
+ if (!matched &&
+ auth->priv->family == family &&
+ strcmp (auth->priv->address, a->priv->address) == 0 &&
+ strcmp (auth->priv->number, a->priv->number) == 0)
+ {
+ matched = TRUE;
+ if (delete)
+ {
+ g_object_unref (a);
+ continue;
+ }
+ else
+ xauth_set_authorization_data (a, auth->priv->authorization_data, auth->priv->authorization_data_length);
+ }
+
+ records = g_list_append (records, a);
+ }
+ if (input_stream)
+ {
+ g_input_stream_close (G_INPUT_STREAM (input_stream), NULL, error);
+ g_object_unref (input_stream);
+ }
+
+ /* If didn't exist, then add a new one */
+ if (!matched)
+ records = g_list_append (records, g_object_ref (auth));
+
+ output_stream = g_file_replace (file, NULL, FALSE, G_FILE_CREATE_PRIVATE, NULL, error);
+ if (!output_stream)
return FALSE;
+
+ /* Workaround because g_file_replace () generates a file does not exist error even though it can replace it */
+ g_clear_error (error);
+
+ /* Write records back */
+ for (link = records; link; link = link->next)
+ {
+ XAuthorization *a = link->data;
+
+ write_uint16 (G_OUTPUT_STREAM (output_stream), a->priv->family, error);
+ write_string (G_OUTPUT_STREAM (output_stream), a->priv->address, error);
+ write_string (G_OUTPUT_STREAM (output_stream), a->priv->number, error);
+ write_string (G_OUTPUT_STREAM (output_stream), a->priv->authorization_name, error);
+ write_uint16 (G_OUTPUT_STREAM (output_stream), a->priv->authorization_data_length, error);
+ write_data (G_OUTPUT_STREAM (output_stream), a->priv->authorization_data, a->priv->authorization_data_length, error);
+
+ g_object_unref (a);
}
+ g_list_free (records);
+ g_output_stream_close (G_OUTPUT_STREAM (output_stream), NULL, error);
+ g_object_unref (output_stream);
+
+ if (error && *error)
+ return FALSE;
/* NOTE: Would like to do:
* g_file_set_attribute_string (file, G_FILE_ATTRIBUTE_OWNER_USER, username, G_FILE_QUERY_INFO_NONE, NULL, error))
* but not supported. */
if (user && getuid () == 0)
{
- if (chown (path, user_get_uid (user), user_get_gid (user)) < 0)
+ if (chown (g_file_get_path (file), user_get_uid (user), user_get_gid (user)) < 0)
g_warning ("Failed to set authorization owner: %s", strerror (errno));
}
+
+ return TRUE;
+}
- data = g_string_sized_new (1024);
- write_uint16 (data, 0xFFFF); /* FamilyWild - this entry is used for all connections */
- write_string (data, ""); /* Not requires as using FamilyWild */
- write_string (data, ""); /* Not requires as using FamilyWild */
- write_string (data, auth->priv->authorization_name);
- write_uint16 (data, auth->priv->authorization_data_length);
- write_data (data, auth->priv->authorization_data, auth->priv->authorization_data_length);
-
- result = g_output_stream_write_all (G_OUTPUT_STREAM (stream), data->str, data->len, &n_written, NULL, error);
- g_string_free (data, TRUE);
+gboolean
+xauth_update (XAuthorization *auth, User *user, GFile *file, GError **error)
+{
+ g_return_val_if_fail (auth != NULL, FALSE);
+ g_return_val_if_fail (file != NULL, FALSE);
+ return xauth_merge (auth, FALSE, user, file, error);
+}
- g_object_unref (stream);
- if (!result)
- {
- g_object_unref (file);
- file = NULL;
- }
-
- return file;
+gboolean
+xauth_remove (XAuthorization *auth, User *user, GFile *file, GError **error)
+{
+ g_return_val_if_fail (auth != NULL, FALSE);
+ g_return_val_if_fail (file != NULL, FALSE);
+ return xauth_merge (auth, TRUE, user, file, error);
}
static void
xauth_init (XAuthorization *auth)
{
auth->priv = G_TYPE_INSTANCE_GET_PRIVATE (auth, XAUTH_TYPE, XAuthorizationPrivate);
+ auth->priv->address = g_strdup ("");
+ auth->priv->number = g_strdup ("");
}
static void
@@ -160,6 +368,8 @@ xauth_finalize (GObject *object)
self = XAUTH (object);
+ g_free (self->priv->address);
+ g_free (self->priv->number);
g_free (self->priv->authorization_name);
g_free (self->priv->authorization_data);
diff --git a/src/xauth.h b/src/xauth.h
index 538e1704..6f4b3ae6 100644
--- a/src/xauth.h
+++ b/src/xauth.h
@@ -35,21 +35,50 @@ typedef struct
GObjectClass parent_class;
} XAuthorizationClass;
+#define XAUTH_FAMILY_INTERNET 0
+#define XAUTH_FAMILY_DECNET 1
+#define XAUTH_FAMILY_CHAOS 2
+#define XAUTH_FAMILY_SERVER_INTERPRETED 5
+#define XAUTH_FAMILY_INTERNET6 6
+#define XAUTH_FAMILY_LOCALHOST 252
+#define XAUTH_FAMILY_KRB5_PRINCIPAL 253
+#define XAUTH_FAMILY_NETNAME 254
+#define XAUTH_FAMILY_LOCAL 256
+#define XAUTH_FAMILY_WILD 65535
+
GType xauth_get_type (void);
-XAuthorization *xauth_new (const gchar *name, const guchar *data, gsize data_length);
+XAuthorization *xauth_new (guint16 family, const gchar *address, const gchar *number, const gchar *name, const guint8 *data, gsize data_length);
+
+XAuthorization *xauth_new_cookie (guint16 family, const gchar *address, const gchar *number);
+
+void xauth_set_family (XAuthorization *auth, guint16 family);
+
+guint16 xauth_get_family (XAuthorization *auth);
+
+void xauth_set_address (XAuthorization *auth, const gchar *address);
-XAuthorization *xauth_new_cookie (void);
+const gchar *xauth_get_address (XAuthorization *auth);
+
+void xauth_set_number (XAuthorization *auth, const gchar *number);
+
+const gchar *xauth_get_number (XAuthorization *auth);
+
+void xauth_set_authorization_name (XAuthorization *auth, const gchar *name);
const gchar *xauth_get_authorization_name (XAuthorization *auth);
-const guchar *xauth_get_authorization_data (XAuthorization *auth);
+void xauth_set_authorization_data (XAuthorization *auth, const guint8 *data, gsize data_length);
-guchar *xauth_copy_authorization_data (XAuthorization *auth);
+const guint8 *xauth_get_authorization_data (XAuthorization *auth);
+
+guint8 *xauth_copy_authorization_data (XAuthorization *auth);
gsize xauth_get_authorization_data_length (XAuthorization *auth);
-GFile *xauth_write (XAuthorization *auth, User *user, const gchar *path, GError **error);
+gboolean xauth_update (XAuthorization *auth, User *user, GFile *file, GError **error);
+
+gboolean xauth_remove (XAuthorization *auth, User *user, GFile *file, GError **error);
G_END_DECLS
diff --git a/src/xdmcp-server.c b/src/xdmcp-server.c
index 67b90c6c..bc914610 100644
--- a/src/xdmcp-server.c
+++ b/src/xdmcp-server.c
@@ -362,11 +362,13 @@ handle_request (XDMCPServer *server, GSocket *socket, GSocketAddress *address, X
XAuthorization *auth;
/* Data is the cookie */
- auth = xauth_new_cookie ();
+ auth = xauth_new_cookie (XAUTH_FAMILY_WILD, "", "");
authorization_data = xauth_copy_authorization_data (auth);
authorization_data_length = xauth_get_authorization_data_length (auth);
session_authorization_data = xauth_copy_authorization_data (auth);
session_authorization_data_length = xauth_get_authorization_data_length (auth);
+
+ g_object_unref (auth);
}
else if (strcmp (server->priv->authorization_name, "XDM-AUTHORIZATION-1") == 0)
{
diff --git a/src/xserver.c b/src/xserver.c
index f17ada24..b10f4337 100644
--- a/src/xserver.c
+++ b/src/xserver.c
@@ -260,8 +260,8 @@ write_authorization_file (XServer *server)
g_debug ("Writing X server authorization to %s", server->priv->authorization_path);
- server->priv->authorization_file = xauth_write (server->priv->authorization, NULL, server->priv->authorization_path, &error);
- if (!server->priv->authorization_file)
+ server->priv->authorization_file = g_file_new_for_path (server->priv->authorization_path);
+ if (!xauth_update (server->priv->authorization, NULL, server->priv->authorization_file, &error))
g_warning ("Failed to write authorization: %s", error->message);
g_clear_error (&error);
}
@@ -372,6 +372,7 @@ xserver_start (XServer *server)
{
GError *error = NULL;
gboolean result;
+ gchar *full_path;
GString *command;
g_return_val_if_fail (server != NULL, FALSE);
@@ -392,12 +393,16 @@ xserver_start (XServer *server)
g_return_val_if_fail (server->priv->command != NULL, FALSE);
- /* Write the authorization file */
- write_authorization_file (server);
+ full_path = g_find_program_in_path (server->priv->command);
+ if (!full_path)
+ {
+ g_debug ("Can't launch X server %s, not found in path", server->priv->command);
+ return FALSE;
+ }
+ command = g_string_new (full_path);
+ g_free (full_path);
- command = g_string_new (server->priv->command);
g_string_append_printf (command, " :%d", server->priv->display_number);
- //g_string_append_printf (command, " vt%d");
if (server->priv->config_file)
g_string_append_printf (command, " -config %s", server->priv->config_file);
@@ -434,8 +439,25 @@ xserver_start (XServer *server)
if (server->priv->no_root)
g_string_append (command, " -background none");
+ /* Write the authorization file */
+ write_authorization_file (server);
+
g_debug ("Launching X Server");
+ /* If running inside another display then pass through those variables */
+ if (getenv ("DISPLAY"))
+ child_process_set_env (CHILD_PROCESS (server), "DISPLAY", getenv ("DISPLAY"));
+ if (getenv ("XAUTHORITY"))
+ child_process_set_env (CHILD_PROCESS (server), "XAUTHORITY", getenv ("XAUTHORITY"));
+
+ /* Variable required for regression tests */
+ if (getenv ("LIGHTDM_TEST_STATUS_SOCKET"))
+ {
+ child_process_set_env (CHILD_PROCESS (server), "LIGHTDM_TEST_STATUS_SOCKET", getenv ("LIGHTDM_TEST_STATUS_SOCKET"));
+ child_process_set_env (CHILD_PROCESS (server), "LIGHTDM_TEST_CONFIG", getenv ("LIGHTDM_TEST_CONFIG"));
+ child_process_set_env (CHILD_PROCESS (server), "LIGHTDM_TEST_HOME_DIR", getenv ("LIGHTDM_TEST_HOME_DIR"));
+ }
+
result = child_process_start (CHILD_PROCESS (server),
user_get_current (),
NULL,