summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrobert.ancell@gmail.com <>2010-07-18 15:53:59 +0200
committerrobert.ancell@gmail.com <>2010-07-18 15:53:59 +0200
commit0d7a5f0568bd1d56687b14eefc414cbc28f482fb (patch)
treebcf51a6222a3c87cfdf75c9d681966996c63cf09
parent9d162557efb42b094ab8da7c058e75ebbdf99afe (diff)
downloadlightdm-0d7a5f0568bd1d56687b14eefc414cbc28f482fb.tar.gz
Store authorization in files
-rw-r--r--NEWS1
-rw-r--r--configure.ac11
-rw-r--r--src/Makefile.am3
-rw-r--r--src/display-manager.c101
-rw-r--r--src/display.c2
-rw-r--r--src/session.c39
-rw-r--r--src/session.h5
-rw-r--r--src/xauth.c159
-rw-r--r--src/xauth.h52
-rw-r--r--src/xdmcp-server.c24
-rw-r--r--src/xdmcp-session-private.h4
-rw-r--r--src/xdmcp-session.c12
-rw-r--r--src/xdmcp-session.h4
-rw-r--r--src/xserver.c70
-rw-r--r--src/xserver.h10
15 files changed, 444 insertions, 53 deletions
diff --git a/NEWS b/NEWS
index 99948478..abc1f1e0 100644
--- a/NEWS
+++ b/NEWS
@@ -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);