diff options
author | robert.ancell@gmail.com <> | 2010-07-18 15:53:59 +0200 |
---|---|---|
committer | robert.ancell@gmail.com <> | 2010-07-18 15:53:59 +0200 |
commit | 0d7a5f0568bd1d56687b14eefc414cbc28f482fb (patch) | |
tree | bcf51a6222a3c87cfdf75c9d681966996c63cf09 | |
parent | 9d162557efb42b094ab8da7c058e75ebbdf99afe (diff) | |
download | lightdm-0d7a5f0568bd1d56687b14eefc414cbc28f482fb.tar.gz |
Store authorization in files
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | configure.ac | 11 | ||||
-rw-r--r-- | src/Makefile.am | 3 | ||||
-rw-r--r-- | src/display-manager.c | 101 | ||||
-rw-r--r-- | src/display.c | 2 | ||||
-rw-r--r-- | src/session.c | 39 | ||||
-rw-r--r-- | src/session.h | 5 | ||||
-rw-r--r-- | src/xauth.c | 159 | ||||
-rw-r--r-- | src/xauth.h | 52 | ||||
-rw-r--r-- | src/xdmcp-server.c | 24 | ||||
-rw-r--r-- | src/xdmcp-session-private.h | 4 | ||||
-rw-r--r-- | src/xdmcp-session.c | 12 | ||||
-rw-r--r-- | src/xdmcp-session.h | 4 | ||||
-rw-r--r-- | src/xserver.c | 70 | ||||
-rw-r--r-- | src/xserver.h | 10 |
15 files changed, 444 insertions, 53 deletions
@@ -2,6 +2,7 @@ Overview of changes in lightdm 0.0.5 * Make --test-mode which runs as the current user * Support displays acting as XDMCP terminals + * Support MIT-MAGIC-COOKIE-1 and XDM-AUTHORIZATION-1 authorization Overview of changes in lightdm 0.0.4 diff --git a/configure.ac b/configure.ac index 8ddbe1bf..b78e2904 100644 --- a/configure.ac +++ b/configure.ac @@ -88,6 +88,16 @@ AC_ARG_WITH(xserver-binary, ) AC_SUBST(XSERVER_BINARY) +XAUTH_DIR=$localstatedir/run/lightdm/authority +AC_ARG_WITH(xauth-dir, + AS_HELP_STRING([--with-xauth-dir=<dir>], + [X server authorization directory]), + if test x$withval != x; then + XAUTH_DIR="$withval" + fi +) +AC_SUBST(XAUTH_DIR) + XSESSION_DIR=/usr/share/xsessions AC_ARG_WITH(xsession-dir, AS_HELP_STRING([--with-xsession-dir=<dir>], @@ -183,6 +193,7 @@ echo " Config file: ${CONFIG_FILE} D-Bus system directory: ${DBUS_SYS_DIR} X server binary: ${XSERVER_BINARY} + X authorization dir: ${XAUTH_DIR} XSessions dir: ${XSESSION_DIR} Default session: ${DEFAULT_SESSION} Greeter user: ${GREETER_USER} diff --git a/src/Makefile.am b/src/Makefile.am index 7c9e6faf..3388458a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -21,6 +21,8 @@ lightdm_SOURCES = \ theme.h \ user-manager.c \ user-manager.h \ + xauth.c \ + xauth.h \ xdmcp-protocol.c \ xdmcp-protocol.h \ xdmcp-server.c \ @@ -43,6 +45,7 @@ lightdm_CFLAGS = \ -DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\" \ -DLOCALE_DIR=\"$(localedir)\" \ -DXSERVER_BINARY=\"$(XSERVER_BINARY)\" \ + -DXAUTH_DIR=\"$(XAUTH_DIR)\" \ -DXSESSIONS_DIR=\"$(XSESSION_DIR)\" \ -DDEFAULT_SESSION=\"$(DEFAULT_SESSION)\" \ -DGREETER_USER=\"$(GREETER_USER)\" \ diff --git a/src/display-manager.c b/src/display-manager.c index f163fa04..a2547407 100644 --- a/src/display-manager.c +++ b/src/display-manager.c @@ -11,6 +11,7 @@ #include <stdlib.h> #include <string.h> +#include <sys/stat.h> #include <dbus/dbus-glib.h> #include "display-manager.h" @@ -33,12 +34,16 @@ static guint signals[LAST_SIGNAL] = { 0 }; struct DisplayManagerPrivate { GKeyFile *config; + + gchar *auth_dir; gboolean test_mode; GList *displays; XDMCPServer *xdmcp_server; + + guint auth_counter; }; G_DEFINE_TYPE (DisplayManager, display_manager, G_TYPE_OBJECT); @@ -93,10 +98,22 @@ get_free_display_number (DisplayManager *manager) return display_number; } +static gchar * +get_authorization_path (DisplayManager *manager) +{ + gchar *path; + + path = g_strdup_printf ("%s/%d", manager->priv->auth_dir, manager->priv->auth_counter); + manager->priv->auth_counter++; + + return path; +} + static void start_session_cb (Display *display, Session *session, DisplayManager *manager) { gchar *string; + XAuthorization *authorization; /* Connect using the session bus */ if (manager->priv->test_mode) @@ -109,6 +126,16 @@ start_session_cb (Display *display, Session *session, DisplayManager *manager) string = g_strdup_printf ("/org/gnome/LightDisplayManager/Display%d", display_get_index (display)); session_set_env (session, "LDM_DISPLAY", string); + 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); + } + g_free (string); } @@ -150,15 +177,22 @@ static void xdmcp_session_cb (XDMCPServer *server, XDMCPSession *session, DisplayManager *manager) { Display *display; - gchar *address; + gchar *address, *path; XServer *xserver; + XAuthorization *authorization; display = add_display (manager); address = g_inet_address_to_string (G_INET_ADDRESS (xdmcp_session_get_address (session))); xserver = xserver_new (XSERVER_TYPE_REMOTE, address, xdmcp_session_get_display_number (session)); + authorization = xauth_new (xdmcp_session_get_authorization_name (session), + xdmcp_session_get_authorization_data (session), + xdmcp_session_get_authorization_data_length (session)); + path = get_authorization_path (manager); + xserver_set_authorization (xserver, authorization, path); display_start (display, xserver, NULL, 0); g_object_unref (xserver); g_free (address); + g_free (path); } static guchar @@ -198,11 +232,51 @@ string_to_xdm_auth_key (const gchar *key, guchar *data) } } +static void +setup_auth_dir (DisplayManager *manager) +{ + GDir *dir; + GError *error = NULL; + + g_mkdir_with_parents (manager->priv->auth_dir, S_IRWXU); + dir = g_dir_open (manager->priv->auth_dir, 0, &error); + if (!dir) + { + g_warning ("Authorization dir not created: %s", error->message); + g_clear_error (&error); + return; + } + + /* Clear out the directory */ + while (TRUE) + { + const gchar *filename; + gchar *path; + GFile *file; + + filename = g_dir_read_name (dir); + if (!filename) + break; + + path = g_build_filename (manager->priv->auth_dir, filename, NULL); + file = g_file_new_for_path (filename); + g_file_delete (file, NULL, NULL); + + g_free (path); + g_object_unref (file); + } + + g_dir_close (dir); +} + void display_manager_start (DisplayManager *manager) { gchar *displays; gchar **tokens, **i; + + /* Make an empty authorization directory */ + setup_auth_dir (manager); /* Start the first display */ displays = g_key_file_get_string (manager->priv->config, "LightDM", "displays", NULL); @@ -258,14 +332,31 @@ display_manager_start (DisplayManager *manager) if (key) { guchar data[8]; + gchar *path; + XAuthorization *authorization; string_to_xdm_auth_key (key, data); xserver_set_authentication (xserver, "XDM-AUTHENTICATION-1", data, 8); - xserver_set_authorization (xserver, "XDM-AUTHORIZATION-1", data, 8); + + authorization = xauth_new ("XDM-AUTHORIZATION-1", data, 8); + path = get_authorization_path (manager); + xserver_set_authorization (xserver, authorization, path); + + g_free (path); } } else + { + gchar *path; + XAuthorization *authorization; + xserver = xserver_new (XSERVER_TYPE_LOCAL, NULL, display_number); + + authorization = xauth_new_cookie (); + path = get_authorization_path (manager); + xserver_set_authorization (xserver, authorization, path); + g_free (path); + } g_free (xdmcp_manager); if (manager->priv->test_mode) @@ -326,6 +417,10 @@ display_manager_set_property (GObject *object, case PROP_CONFIG: self->priv->config = g_value_get_pointer (value); self->priv->test_mode = g_key_file_get_boolean (self->priv->config, "LightDM", "test-mode", NULL); + if (self->priv->test_mode) + self->priv->auth_dir = g_build_filename (g_get_user_cache_dir (), "lightdm", "authority", NULL); + else + self->priv->auth_dir = g_strdup (XAUTH_DIR); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -333,7 +428,6 @@ display_manager_set_property (GObject *object, } } - static void display_manager_get_property (GObject *object, guint prop_id, @@ -366,6 +460,7 @@ display_manager_finalize (GObject *object) g_object_unref (self->priv->xdmcp_server); for (link = self->priv->displays; link; link = link->next) g_object_unref (link->data); + g_list_free (self->priv->displays); } static void diff --git a/src/display.c b/src/display.c index 9875ba50..d14bf09b 100644 --- a/src/display.c +++ b/src/display.c @@ -188,7 +188,7 @@ session_exit_cb (Session *session, Display *display) case SESSION_NONE: break; case SESSION_GREETER_PRE_CONNECT: - g_error ("Failed to start greeter"); + g_warning ("Failed to start greeter"); break; case SESSION_GREETER: if (display->priv->default_user && display->priv->timeout > 0) diff --git a/src/session.c b/src/session.c index 2f162d26..7444cce9 100644 --- a/src/session.c +++ b/src/session.c @@ -43,6 +43,11 @@ struct SessionPrivate /* Session process */ GPid pid; + + /* X authorization */ + XAuthorization *authorization; + gchar *authorization_path; + GFile *authorization_file; }; G_DEFINE_TYPE (Session, session, G_TYPE_OBJECT); @@ -71,6 +76,18 @@ session_set_env (Session *session, const gchar *name, const gchar *value) g_hash_table_insert (session->priv->env, g_strdup (name), g_strdup (value)); } +void +session_set_authorization (Session *session, XAuthorization *authorization, const gchar *path) +{ + session->priv->authorization = authorization; + session->priv->authorization_path = g_strdup (path); +} + +XAuthorization *session_get_authorization (Session *session) +{ + return session->priv->authorization; +} + static void session_watch_cb (GPid pid, gint status, gpointer data) { @@ -155,7 +172,7 @@ session_start (Session *session) g_warning ("Unable to get information on user %s: %s", session->priv->username, strerror (errno)); return FALSE; } - + working_dir = user_info->pw_dir; session_set_env (session, "USER", user_info->pw_name); session_set_env (session, "HOME", user_info->pw_dir); @@ -168,11 +185,21 @@ session_start (Session *session) session_set_env (session, "SHELL", getenv ("SHELL")); } + if (session->priv->authorization) + { + session->priv->authorization_file = xauth_write (session->priv->authorization, session->priv->authorization_path, &error); + if (session->priv->authorization_file) + session_set_env (session, "XAUTHORITY", session->priv->authorization_path); + else + g_warning ("Failed to write authorization: %s", error->message); + g_clear_error (&error); + } + env = session_get_env (session); result = g_shell_parse_argv (session->priv->command, &argc, &argv, &error); if (!result) - g_error ("Failed to parse session command line: %s", error->message); + g_warning ("Failed to parse session command line: %s", error->message); g_clear_error (&error); if (!result) return FALSE; @@ -263,6 +290,14 @@ session_finalize (GObject *object) g_free (self->priv->username); 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); + } } static void diff --git a/src/session.h b/src/session.h index 0aef17c1..1ddb9434 100644 --- a/src/session.h +++ b/src/session.h @@ -13,6 +13,7 @@ #define _SESSION_H_ #include <glib-object.h> +#include "xauth.h" G_BEGIN_DECLS @@ -44,6 +45,10 @@ const gchar *session_get_command (Session *session); void session_set_env (Session *session, const gchar *name, const gchar *value); +void session_set_authorization (Session *session, XAuthorization *authorization, const gchar *path); + +XAuthorization *session_get_authorization (Session *session); + gboolean session_start (Session *session); G_END_DECLS diff --git a/src/xauth.c b/src/xauth.c new file mode 100644 index 00000000..e59760fd --- /dev/null +++ b/src/xauth.c @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2010 Robert Ancell. + * Author: Robert Ancell <robert.ancell@canonical.com> + * + * 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 the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. See http://www.gnu.org/copyleft/gpl.html the full text of the + * license. + */ + +#include <string.h> + +#include "xauth.h" + +struct XAuthorizationPrivate +{ + /* User who is using this authorization */ + gchar *username; + + /* Authorization scheme */ + gchar *authorization_name; + + /* Authorization data */ + guchar *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) +{ + 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); + + return auth; +} + +XAuthorization *xauth_new_cookie (void) +{ + guchar 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); +} + +const gchar * +xauth_get_authorization_name (XAuthorization *auth) +{ + return auth->priv->authorization_name; +} + +const guchar * +xauth_get_authorization_data (XAuthorization *auth) +{ + return auth->priv->authorization_data; +} + +gsize +xauth_get_authorization_data_length (XAuthorization *auth) +{ + return auth->priv->authorization_data_length; +} + +static void +write_uint16 (GString *string, guint16 value) +{ + g_string_append_c (string, (gchar) value >> 8); + g_string_append_c (string, (gchar) value); +} + +static void +write_data (GString *string, guchar *value, gsize value_len) +{ + g_string_append_len (string, (gchar *) value, value_len); +} + +static void +write_string (GString *string, const gchar *value) +{ + write_uint16 (string, strlen (value)); + g_string_append (string, value); +} + +GFile * +xauth_write (XAuthorization *auth, const gchar *path, GError **error) +{ + GFile *file; + GFileOutputStream *stream; + GString *data; + gboolean result; + gsize n_written; + + file = g_file_new_for_path (path); + + stream = g_file_replace (file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, error); + if (!stream) + { + g_object_unref (file); + return FALSE; + } + + 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); + + g_object_unref (stream); + if (!result) + { + g_object_unref (file); + file = NULL; + } + + return file; +} + +static void +xauth_init (XAuthorization *auth) +{ + auth->priv = G_TYPE_INSTANCE_GET_PRIVATE (auth, XAUTH_TYPE, XAuthorizationPrivate); + auth->priv->authorization_name = g_strdup (""); +} + +static void +xauth_finalize (GObject *object) +{ + XAuthorization *self; + + self = XAUTH (object); + + g_free (self->priv->username); + g_free (self->priv->authorization_name); + g_free (self->priv->authorization_data); +} + +static void +xauth_class_init (XAuthorizationClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = xauth_finalize; + + g_type_class_add_private (klass, sizeof (XAuthorizationPrivate)); +} diff --git a/src/xauth.h b/src/xauth.h new file mode 100644 index 00000000..fa2600fa --- /dev/null +++ b/src/xauth.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2010 Robert Ancell. + * Author: Robert Ancell <robert.ancell@canonical.com> + * + * 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 the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. See http://www.gnu.org/copyleft/gpl.html the full text of the + * license. + */ + +#ifndef _XAUTH_H_ +#define _XAUTH_H_ + +#include <glib-object.h> +#include <gio/gio.h> + +G_BEGIN_DECLS + +#define XAUTH_TYPE (xauth_get_type()) +#define XAUTH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), XAUTH_TYPE, XAuthorization)); + +typedef struct XAuthorizationPrivate XAuthorizationPrivate; + +typedef struct +{ + GObject parent_instance; + XAuthorizationPrivate *priv; +} XAuthorization; + +typedef struct +{ + GObjectClass parent_class; +} XAuthorizationClass; + +GType xauth_get_type (void); + +XAuthorization *xauth_new (const gchar *name, const guchar *data, gsize data_length); + +XAuthorization *xauth_new_cookie (void); + +const gchar *xauth_get_authorization_name (XAuthorization *auth); + +const guchar *xauth_get_authorization_data (XAuthorization *auth); + +gsize xauth_get_authorization_data_length (XAuthorization *auth); + +GFile *xauth_write (XAuthorization *auth, const gchar *path, GError **error); + +G_END_DECLS + +#endif /* _XAUTH_H_ */ diff --git a/src/xdmcp-server.c b/src/xdmcp-server.c index cce3ff2e..b69b960e 100644 --- a/src/xdmcp-server.c +++ b/src/xdmcp-server.c @@ -267,8 +267,9 @@ handle_request (XDMCPServer *server, GSocket *socket, GSocketAddress *address, X gboolean match_authorization = FALSE; guchar *authorization_data = NULL; gsize authorization_data_length = 0; + guchar *session_authorization_data = NULL; + gsize session_authorization_data_length = 0; gchar **j; - guchar session_key[8]; GInetAddress *address4 = NULL; /*, *address6 = NULL;*/ /* Must be using our authentication scheme */ @@ -333,7 +334,6 @@ handle_request (XDMCPServer *server, GSocket *socket, GSocketAddress *address, X } /* Perform requested authorization */ - memset (session_key, 0, sizeof (session_key)); if (strcmp (server->priv->authorization_name, "MIT-MAGIC-COOKIE-1") == 0) { /* Data is the cookie */ @@ -344,18 +344,28 @@ handle_request (XDMCPServer *server, GSocket *socket, GSocketAddress *address, X else if (strcmp (server->priv->authorization_name, "XDM-AUTHORIZATION-1") == 0) { gint i; - guchar key[8]; + guchar key[8], session_key[8]; /* Setup key */ memset (key, 0, 8); memcpy (key, server->priv->authentication_data, server->priv->authentication_data_length > 8 ? 8 : server->priv->authentication_data_length); - /* Generate a private session key and encode it */ + /* Generate a private session key */ + // FIXME: Pick a good DES key? for (i = 0; i < 8; i++) session_key[i] = g_random_int () & 0xFF; + + /* Encrypt the session key and send it to the server */ authorization_data = g_malloc (sizeof (guchar) * 8); authorization_data_length = 8; XdmcpWrap (session_key, key, authorization_data, authorization_data_length); + + /* Authorization data is the session key (64 bit) followed by the private key (56 bit) followed by an empty byte */ + session_authorization_data = g_malloc (sizeof (guchar) * 16); + session_authorization_data_length = 8; + memcpy (session_authorization_data, session_key, 8); + memcpy (session_authorization_data + 8, key + 1, 7); + session_authorization_data[15] = 0; } for (i = 0; i < packet->Request.n_connections; i++) @@ -390,7 +400,9 @@ handle_request (XDMCPServer *server, GSocket *socket, GSocketAddress *address, X session = add_session (server); session->priv->address = address4; /*address6 ? address6 : address4;*/ - memcpy (session->priv->key, session_key, 8); + session->priv->authorization_name = g_strdup (server->priv->authorization_name); + session->priv->authorization_data = session_authorization_data; + session->priv->authorization_data_length = session_authorization_data_length; response = xdmcp_packet_alloc (XDMCP_Accept); response->Accept.session_id = xdmcp_session_get_id (session); @@ -574,7 +586,7 @@ xdmcp_server_init (XDMCPServer *server) server->priv->port = XDM_UDP_PORT; server->priv->hostname = g_strdup (""); server->priv->status = g_strdup (""); - server->priv->sessions = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free); + server->priv->sessions = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref); server->priv->authentication_name = g_strdup (""); server->priv->authorization_name = g_strdup (""); } diff --git a/src/xdmcp-session-private.h b/src/xdmcp-session-private.h index c65597c9..d5168331 100644 --- a/src/xdmcp-session-private.h +++ b/src/xdmcp-session-private.h @@ -29,8 +29,8 @@ struct XDMCPSessionPrivate gchar *authorization_name; - /* Session key for XDM-AUTHORIZATION-1 */ - guchar key[8]; + guchar *authorization_data; + gsize authorization_data_length; gboolean started; diff --git a/src/xdmcp-session.c b/src/xdmcp-session.c index 6c0ff36e..c4a09683 100644 --- a/src/xdmcp-session.c +++ b/src/xdmcp-session.c @@ -50,6 +50,18 @@ xdmcp_session_get_authorization_name (XDMCPSession *session) return session->priv->authorization_name; } +const guchar * +xdmcp_session_get_authorization_data (XDMCPSession *session) +{ + return session->priv->authorization_data; +} + +const gsize +xdmcp_session_get_authorization_data_length (XDMCPSession *session) +{ + return session->priv->authorization_data_length; +} + guint16 xdmcp_session_get_display_number (XDMCPSession *session) { diff --git a/src/xdmcp-session.h b/src/xdmcp-session.h index c2138507..7d921060 100644 --- a/src/xdmcp-session.h +++ b/src/xdmcp-session.h @@ -45,6 +45,10 @@ const GInetAddress *xdmcp_session_get_address (XDMCPSession *session); const gchar *xdmcp_session_get_authorization_name (XDMCPSession *session); +const guchar *xdmcp_session_get_authorization_data (XDMCPSession *session); + +const gsize xdmcp_session_get_authorization_data_length (XDMCPSession *session); + guint16 xdmcp_session_get_display_number (XDMCPSession *session); const gchar *xdmcp_session_get_display_class (XDMCPSession *session); diff --git a/src/xserver.c b/src/xserver.c index ed8286c6..bbf3607c 100644 --- a/src/xserver.c +++ b/src/xserver.c @@ -58,12 +58,10 @@ struct XServerPrivate guchar *authentication_data; gsize authentication_data_length; - /* Authorization scheme to use */ - gchar *authorization_name; - - /* Authorization data */ - guchar *authorization_data; - gsize authorization_data_length; + /* Authorization */ + XAuthorization *authorization; + gchar *authorization_path; + GFile *authorization_file; /* Display number */ gint display_number; @@ -188,32 +186,16 @@ xserver_get_authentication_data_length (XServer *server) } void -xserver_set_authorization (XServer *server, const gchar *name, const guchar *data, gsize data_length) -{ - g_free (server->priv->authorization_name); - server->priv->authorization_name = g_strdup (name); - g_free (server->priv->authorization_data); - server->priv->authorization_data = g_malloc (data_length); - server->priv->authorization_data_length = data_length; - memcpy (server->priv->authorization_data, data, data_length); -} - -const gchar * -xserver_get_authorization_name (XServer *server) +xserver_set_authorization (XServer *server, XAuthorization *authorization, const gchar *path) { - return server->priv->authorization_name; + server->priv->authorization = authorization; + server->priv->authorization_path = g_strdup (path); } -const guchar * -xserver_get_authorization_data (XServer *server) -{ - return server->priv->authorization_data; -} - -gsize -xserver_get_authorization_data_length (XServer *server) +XAuthorization * +xserver_get_authorization (XServer *server) { - return server->priv->authorization_data_length; + return server->priv->authorization; } static void @@ -252,6 +234,8 @@ xserver_start (XServer *server) gint n_env = 0; gchar *env_string; //gint xserver_stdin, xserver_stdout, xserver_stderr; + + g_return_val_if_fail (server->priv->pid == 0, FALSE); /* Don't need to do anything if a remote server */ if (server->priv->type == XSERVER_TYPE_REMOTE) @@ -269,10 +253,25 @@ xserver_start (XServer *server) env[n_env++] = g_strdup_printf ("XAUTHORITY=%s", getenv ("XAUTHORITY")); env[n_env] = NULL; + /* Write the authorization file */ + if (server->priv->authorization) + { + GError *error = NULL; + + server->priv->authorization_file = xauth_write (server->priv->authorization, server->priv->authorization_path, &error); + if (!server->priv->authorization_file) + g_warning ("Failed to write authorization: %s", error->message); + g_clear_error (&error); + } + command = g_string_new (server->priv->command); g_string_append_printf (command, " :%d", server->priv->display_number); g_string_append (command, " -nr"); /* No root background */ //g_string_append_printf (command, " vt%d"); + + if (server->priv->authorization) + g_string_append_printf (command, " -auth %s", server->priv->authorization_path); + if (server->priv->type == XSERVER_TYPE_LOCAL_TERMINAL) { if (server->priv->port != 0) @@ -300,7 +299,7 @@ xserver_start (XServer *server) result = g_shell_parse_argv (command->str, &argc, &argv, &error); g_string_free (command, TRUE); if (!result) - g_error ("Failed to parse X server command line: %s", error->message); + g_warning ("Failed to parse X server command line: %s", error->message); g_clear_error (&error); if (!result) return FALSE; @@ -310,7 +309,7 @@ xserver_start (XServer *server) env, G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD, xserver_fork_cb, - NULL, + server, &server->priv->pid, //&xserver_stdin, &xserver_stdout, &xserver_stderr, &error); @@ -334,7 +333,6 @@ xserver_init (XServer *server) server->priv = G_TYPE_INSTANCE_GET_PRIVATE (server, XSERVER_TYPE, XServerPrivate); server->priv->command = g_strdup (XSERVER_BINARY); server->priv->authentication_name = g_strdup (""); - server->priv->authorization_name = g_strdup (""); } static void @@ -419,9 +417,15 @@ xserver_finalize (GObject *object) g_free (self->priv->hostname); g_free (self->priv->authentication_name); g_free (self->priv->authentication_data); - g_free (self->priv->authorization_name); - g_free (self->priv->authorization_data); g_free (self->priv->address); + 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); + } } static void diff --git a/src/xserver.h b/src/xserver.h index c0710a61..b916205f 100644 --- a/src/xserver.h +++ b/src/xserver.h @@ -15,6 +15,8 @@ #include <glib-object.h> #include <dbus/dbus-glib.h> +#include "xauth.h" + G_BEGIN_DECLS #define XSERVER_TYPE (xserver_get_type()) @@ -78,13 +80,9 @@ const guchar *xserver_get_authentication_data (XServer *server); gsize xserver_get_authentication_data_length (XServer *server); -void xserver_set_authorization (XServer *server, const gchar *name, const guchar *data, gsize data_length); - -const gchar *xserver_get_authorization_name (XServer *server); - -const guchar *xserver_get_authorization_data (XServer *server); +void xserver_set_authorization (XServer *server, XAuthorization *authorization, const gchar *path); -gsize xserver_get_authorization_data_length (XServer *server); +XAuthorization *xserver_get_authorization (XServer *server); gboolean xserver_start (XServer *server); |