]> rtime.felk.cvut.cz Git - sojka/lightdm.git/commitdiff
Suport authentication and authorization better
authorunknown <robert.ancell@gmail.com>
Sat, 17 Jul 2010 05:19:57 +0000 (15:19 +1000)
committerunknown <robert.ancell@gmail.com>
Sat, 17 Jul 2010 05:19:57 +0000 (15:19 +1000)
src/display-manager.c
src/xdmcp-server.c
src/xdmcp-server.h
src/xdmcp-session-private.h
src/xserver.c
src/xserver.h

index ad0225d63989c4b23b10c475acb32ab2596e5c71..6d0530651726f8e7bbb6807821f572735e1af37d 100644 (file)
@@ -10,6 +10,7 @@
  */
 
 #include <stdlib.h>
+#include <string.h>
 #include <dbus/dbus-glib.h>
 
 #include "display-manager.h"
@@ -160,6 +161,43 @@ xdmcp_session_cb (XDMCPServer *server, XDMCPSession *session, DisplayManager *ma
     g_free (address);
 }
 
+static guchar
+atox (char c)
+{
+    if (c >= '0' && c <= '9')
+        return c - '0';
+    if (c >= 'a' && c <= 'f')
+        return c - 'a' + 10;
+    if (c >= 'A' && c <= 'F')
+        return c - 'A' + 10;
+    return 0;
+}
+
+static void
+string_to_xdm_auth_key (const gchar *key, guchar *data)
+{
+    gint i;
+
+    memset (data, 0, sizeof (data));
+    if (strncmp (key, "0x", 2) == 0 || strncmp (key, "0X", 2) == 0)
+    {
+        for (i = 0; i < 8; i++)
+        {
+            if (key[i*2] == '\0')
+                break;
+            data[i] |= atox (key[i*2]) << 8;
+            if (key[i*2+1] == '\0')
+                break;
+            data[i] |= atox (key[i*2+1]);
+        }
+    }
+    else
+    {
+        for (i = 1; i < 8 && key[i-1]; i++)
+           data[i] = key[i-1];
+    }
+}
+
 void
 display_manager_start (DisplayManager *manager)
 {
@@ -218,7 +256,13 @@ display_manager_start (DisplayManager *manager)
                 xserver_set_port (xserver, port);
             key = g_key_file_get_string (manager->priv->config, display_name, "key", NULL);
             if (key)
-                xserver_set_cookie (xserver, key);
+            {
+                guchar data[8];
+
+                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);
+            }
         }
         else
             xserver = xserver_new (XSERVER_TYPE_LOCAL, NULL, display_number);
@@ -249,7 +293,12 @@ display_manager_start (DisplayManager *manager)
 
         key = g_key_file_get_string (manager->priv->config, "xdmcp", "key", NULL);
         if (key)
-            xdmcp_server_set_authentication_key (manager->priv->xdmcp_server, key);
+        {
+            guchar data[8];
+            string_to_xdm_auth_key (key, data);
+            xdmcp_server_set_authentication (manager->priv->xdmcp_server, "XDM-AUTHENTICATION-1", data, 8);
+            //xdmcp_server_set_authorization (manager->priv->xdmcp_server, "XDM-AUTHORIZATION-1", data, 8);
+        }
         g_free (key);
 
         g_debug ("Starting XDMCP server on UDP/IP port %d", xdmcp_server_get_port (manager->priv->xdmcp_server));
index 35c0e0935380374f2857f381c57bde258431964b..60c9cdd3a39f27c011dcf10535b76ceea8e5e71b 100644 (file)
 #include "xdmcp-protocol.h"
 #include "xdmcp-session-private.h"
 
-enum {
-    PROP_0,
-    PROP_PORT,  
-    PROP_HOSTNAME,
-    PROP_STATUS,
-    PROP_AUTHENTICATION_KEY
-};
-
 enum {
     SESSION_ADDED,
     LAST_SIGNAL
@@ -36,18 +28,33 @@ static guint signals[LAST_SIGNAL] = { 0 };
 
 struct XDMCPServerPrivate
 {
-    GKeyFile *config;
-  
+    /* Port to listen on */
     guint port;
 
+    /* Listening socket */
     GSocket *socket;
 
+    /* Hostname to report to client */
     gchar *hostname;
 
+    /* Status to report to clients */
     gchar *status;
 
-    gchar *authentication_key_string;
+    /* Auhentication scheme to use */
+    gchar *authentication_name;
+
+    /* Auhentication data */  
+    guchar *authentication_data;
+    gsize authentication_data_length;
+
+    /* Authorization scheme to use */
+    gchar *authorization_name;
+
+    /* Authorization data */
+    guchar *authorization_data;
+    gsize authorization_data_length;
 
+    /* Active XDMCP sessions */
     GHashTable *sessions;
 };
 
@@ -98,16 +105,69 @@ xdmcp_server_get_status (XDMCPServer *server)
 }
 
 void
-xdmcp_server_set_authentication_key (XDMCPServer *server, const gchar *key_string)
+xdmcp_server_set_authentication (XDMCPServer *server, const gchar *name, const guchar *data, gsize data_length)
 {
-    g_free (server->priv->authentication_key_string);
-    server->priv->authentication_key_string = g_strdup (key_string);
+    g_free (server->priv->authentication_name);
+    server->priv->authentication_name = g_strdup (name);
+    g_free (server->priv->authentication_data);
+    server->priv->authentication_data = g_malloc (data_length);
+    server->priv->authentication_data_length = data_length;
+    memcpy (server->priv->authentication_data, data, data_length);
 }
 
 const gchar *
-xdmcp_server_get_authentication_key (XDMCPServer *server)
+xdmcp_server_get_authentication_name (XDMCPServer *server)
+{
+    return server->priv->authentication_name;
+}
+
+const guchar *
+xdmcp_server_get_authentication_data (XDMCPServer *server)
+{
+    return server->priv->authentication_data;
+}
+
+gsize
+xdmcp_server_get_authentication_data_length (XDMCPServer *server)
+{
+    return server->priv->authentication_data_length;
+}
+
+void
+xdmcp_server_set_authorization (XDMCPServer *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 *
+xdmcp_server_get_authorization_name (XDMCPServer *server)
+{
+    return server->priv->authorization_name;
+}
+
+const guchar *
+xdmcp_server_get_authorization_data (XDMCPServer *server)
+{
+    return server->priv->authorization_data;
+}
+
+gsize
+xdmcp_server_get_authorization_data_length (XDMCPServer *server)
 {
-    return server->priv->authentication_key_string;
+    return server->priv->authorization_data_length;
+}
+
+static gboolean
+session_timeout_cb (XDMCPSession *session)
+{
+    g_debug ("Timing out unmanaged session %d", session->priv->id);
+    g_hash_table_remove (session->priv->server->priv->sessions, GINT_TO_POINTER ((gint) session->priv->id));
+    return TRUE;
 }
 
 static XDMCPSession *
@@ -122,7 +182,9 @@ add_session (XDMCPServer *server)
     } while (g_hash_table_lookup (server->priv->sessions, GINT_TO_POINTER ((gint) id)));
 
     session = xdmcp_session_new (id);
+    session->priv->server = server;
     g_hash_table_insert (server->priv->sessions, GINT_TO_POINTER ((gint) id), g_object_ref (session));
+    session->priv->inactive_timeout = g_timeout_add (10, (GSourceFunc) session_timeout_cb, session);
 
     return session;
 }
@@ -159,74 +221,39 @@ static void
 handle_query (XDMCPServer *server, GSocket *socket, GSocketAddress *address, XDMCPPacket *packet)
 {
     XDMCPPacket *response;
-    const gchar *authentication_name = "";
     gchar **i;
+    gboolean match_authentication = FALSE;
+
+    /* If no authentication requested and we are configured for none then allow */
+    if (packet->Query.authentication_names[0] == NULL && strcmp (server->priv->authentication_name, "") == 0)
+        match_authentication = TRUE;
 
-    /* Use authentication if we are configured for it */
     for (i = packet->Query.authentication_names; *i; i++)
     {
-        if (strcmp (*i, "XDM-AUTHENTICATION-1") == 0)
+        if (strcmp (*i, server->priv->authentication_name) == 0)
         {
-            if (server->priv->authentication_key_string)
-                authentication_name = "XDM-AUTHENTICATION-1";
+            match_authentication = TRUE;
+            break;
         }
     }
 
-    response = xdmcp_packet_alloc (XDMCP_Willing);
-    response->Willing.authentication_name = g_strdup (authentication_name);
-    response->Willing.hostname = g_strdup (server->priv->hostname);
-    response->Willing.status = g_strdup (server->priv->status);
-
-    send_packet (socket, address, response);
-
-    xdmcp_packet_free (response);
-}
-
-static guchar
-atox (gchar c)
-{
-    if (c >= '0' && c <= '9')
-        return c - '0';
-    if (c >= 'a' && c <= 'f')
-        return c - 'a' + 10;
-    if (c >= 'A' && c <= 'F')
-        return c - 'A' + 10;
-    return 0;
-}
-
-static void
-string_to_key (XdmAuthKeyRec *key, const gchar *string)
-{
-    gint i;
-  
-    if (strncmp (string, "0x", 2) == 0 || strncmp (string, "0X", 2) == 0)
+    if (match_authentication)
     {
-        gint j = 0;
-
-        for (i = 0; i < 8 && string[j]; i++)
-        {
-            key->data[i] = 0;
-
-            if (string[j])
-            {
-                key->data[i] |= atox (string[j]) >> 8;
-                j++;
-                if (string[j])
-                {
-                    key->data[i] |= atox (string[j+1]);
-                    j++;
-                }
-            }
-        }
+        response = xdmcp_packet_alloc (XDMCP_Willing);
+        response->Willing.authentication_name = g_strdup (server->priv->authentication_name);
+        response->Willing.hostname = g_strdup (server->priv->hostname);
+        response->Willing.status = g_strdup (server->priv->status);
     }
     else
     {
-        key->data[0] = 0;
-        for (i = 1; i < 8 && string[i-1]; i++)
-            key->data[i] = string[i-1];
-        for (; i < 8; i++)
-            key->data[i] = 0;
+        response = xdmcp_packet_alloc (XDMCP_Unwilling);
+        response->Willing.hostname = g_strdup (server->priv->hostname);
+        response->Willing.status = g_strdup (server->priv->status);
     }
+  
+    send_packet (socket, address, response);
+
+    xdmcp_packet_free (response);
 }
 
 static void
@@ -235,66 +262,74 @@ handle_request (XDMCPServer *server, GSocket *socket, GSocketAddress *address, X
     int i;
     XDMCPPacket *response;
     XDMCPSession *session;
-    const gchar *authorization_name = "";
     guchar *authentication_data = NULL;
     gsize authentication_data_length = 0;
+    gboolean match_authorization = FALSE;
+    guchar *authorization_data = NULL;
+    gsize authorization_data_length = 0;
     gchar **j;
     GInetAddress *address4 = NULL; /*, *address6 = NULL;*/
   
-    /* FIXME: If session not started (i.e. not received the Manage then response with Accept again) */
+    /* Must be using our authentication scheme */
+    if (strcmp (packet->Request.authentication_name, server->priv->authentication_name) != 0)
+    {
+        response = xdmcp_packet_alloc (XDMCP_Decline);
+        if (strcmp (server->priv->authentication_name, "") == 0)
+            response->Decline.status = g_strdup ("Server does not support authentication");
+        else
+            response->Decline.status = g_strdup_printf ("Server only supports %s authentication", server->priv->authentication_name);
+        response->Decline.authentication_name = g_strdup ("");
+        send_packet (socket, address, response);
+        xdmcp_packet_free (response);
+        return;
+    }
 
-    /* FIXME: Perform requested authentication */
-    if (strcmp (packet->Request.authentication_name, "") == 0)
-        ; /* No authentication */
-    else if (strcmp (packet->Request.authentication_name, "XDM-AUTHENTICATION-1") == 0)
+    /* Perform requested authentication */
+    if (strcmp (server->priv->authentication_name, "XDM-AUTHENTICATION-1") == 0)
     {
-        XdmAuthKeyRec key, message;
+        guchar input[8], key[8];
+        XdmAuthKeyRec message;
 
-        if (!server->priv->authentication_key_string)
-        {
-            // FIXME: Send Decline
-            return;
-        }
-
-        // FIXME: I don't think it technically has to be 8 but the Xdmcp library requires it
-        if (packet->Request.authentication_data.length != 8)
-        {
-            // FIXME: Send Decline
-            return;
-        }
+        memset (input, 0, 8);
+        memcpy (input, packet->Request.authentication_data.data, packet->Request.authentication_data.length > 8 ? 8 : packet->Request.authentication_data.length);
 
         /* Setup key */
-        string_to_key (&key, server->priv->authentication_key_string);
+        memset (key, 0, 8);
+        memcpy (key, server->priv->authentication_data, server->priv->authentication_data_length > 8 ? 8 : server->priv->authentication_data_length);
 
         /* Decode message from server */
-        authentication_data = g_malloc (sizeof (guchar) * packet->Request.authentication_data.length);
-        authentication_data_length = packet->Request.authentication_data.length;
+        authentication_data = g_malloc (sizeof (guchar) * 8);
+        authentication_data_length = 8;
 
-        XdmcpUnwrap (packet->Request.authentication_data.data, key.data, message.data, authentication_data_length);
+        XdmcpUnwrap (input, key, message.data, authentication_data_length);
         XdmcpIncrementKey (&message);
-        XdmcpWrap (message.data, key.data, authentication_data, authentication_data_length);
-
-        //authorization_name = "XDM_AUTHORIZATION-1";
-    }
-    else
-    {
-        // FIXME: Send Decline
-        return;
+        XdmcpWrap (message.data, key, authentication_data, authentication_data_length);
     }
 
-    /* Choose an authorization from the list */
+    /* Check if they support our authorization */
     for (j = packet->Request.authorization_names; *j; j++)
     {
-        if (strcmp (*j, "MIT-MAGIC-COOKIE-1") == 0)
-        {
-            // FIXME: Generate cookie
-        }
-        else if (strcmp (*j, "XDM-AUTHORIZATION-1") == 0)
+        if (strcmp (*j, server->priv->authorization_name) == 0)
         {
+             match_authorization = TRUE;
+             break;
         }
     }
 
-    // FIXME: Check have supported authorization
+    if (!match_authorization)
+    {
+        response = xdmcp_packet_alloc (XDMCP_Decline);
+        if (strcmp (server->priv->authorization_name, "") == 0)
+            response->Decline.status = g_strdup ("Server does not support authorization");
+        else
+            response->Decline.status = g_strdup_printf ("Server only supports %s authorization", server->priv->authorization_name);
+        response->Decline.authentication_name = g_strdup (packet->Request.authentication_name);
+        response->Decline.authentication_data.data = authentication_data;
+        response->Decline.authentication_data.length = authentication_data_length;
+        send_packet (socket, address, response);
+        xdmcp_packet_free (response);
+        return;
+    }
 
     for (i = 0; i < packet->Request.n_connections; i++)
     {
@@ -319,25 +354,24 @@ handle_request (XDMCPServer *server, GSocket *socket, GSocketAddress *address, X
         response = xdmcp_packet_alloc (XDMCP_Decline);
         response->Decline.status = g_strdup ("No valid address found");
         response->Decline.authentication_name = g_strdup (packet->Request.authentication_name);
-        response->Accept.authentication_data.data = authentication_data;
-        response->Accept.authentication_data.length = authentication_data_length;
+        response->Decline.authentication_data.data = authentication_data;
+        response->Decline.authentication_data.length = authentication_data_length;
         send_packet (socket, address, response);
         xdmcp_packet_free (response);
         return;
     }
 
-    /* FIXME: Allow a higher layer to decline */
-
     session = add_session (server);
     session->priv->address = address4; /*address6 ? address6 : address4;*/
-    // FIXME: Timeout inactive sessions?
 
     response = xdmcp_packet_alloc (XDMCP_Accept);
     response->Accept.session_id = xdmcp_session_get_id (session);
     response->Accept.authentication_name = g_strdup (packet->Request.authentication_name);
     response->Accept.authentication_data.data = authentication_data;
     response->Accept.authentication_data.length = authentication_data_length;
-    response->Accept.authorization_name = g_strdup (authorization_name);
+    response->Accept.authorization_name = g_strdup (server->priv->authorization_name);
+    response->Accept.authorization_data.data = authorization_data;
+    response->Accept.authorization_data.length = authorization_data_length;
     send_packet (socket, address, response);
     xdmcp_packet_free (response);
 }
@@ -351,6 +385,7 @@ handle_manage (XDMCPServer *server, GSocket *socket, GSocketAddress *address, XD
     if (session)
     {
         gchar *ip_address, *display_address;
+        xcb_auth_info_t auth_info;
 
         /* Ignore duplicate requests */
         if (session->priv->started)
@@ -365,9 +400,12 @@ handle_manage (XDMCPServer *server, GSocket *socket, GSocketAddress *address, XD
         ip_address = g_inet_address_to_string (G_INET_ADDRESS (session->priv->address));
         display_address = g_strdup_printf ("%s:%d", ip_address, packet->Manage.display_number);
         g_free (ip_address);
-        session->priv->connection = xcb_connect (display_address, NULL);
-        // TODO: xcb_connect_to_display_with_auth_info (display_address, NULL);
-      
+        auth_info.namelen = strlen (server->priv->authorization_name);
+        auth_info.name = server->priv->authorization_name;
+        auth_info.datalen = server->priv->authorization_data_length;
+        auth_info.data = (char *) server->priv->authorization_data;
+        session->priv->connection = xcb_connect_to_display_with_auth_info (display_address, &auth_info, NULL);
+
         if (!session->priv->connection)
         {
             XDMCPPacket *response;
@@ -380,6 +418,9 @@ handle_manage (XDMCPServer *server, GSocket *socket, GSocketAddress *address, XD
         }
         else
         {
+            /* Cancel the inactive timer */
+            g_source_remove (session->priv->inactive_timeout);
+
             session->priv->started = TRUE;
             session->priv->display_number = packet->Manage.display_number;  
             session->priv->display_class = g_strdup (packet->Manage.display_class);
@@ -506,64 +547,8 @@ xdmcp_server_init (XDMCPServer *server)
     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);
-}
-
-static void
-xdmcp_server_set_property (GObject      *object,
-                           guint         prop_id,
-                           const GValue *value,
-                           GParamSpec   *pspec)
-{
-    XDMCPServer *self;
-
-    self = XDMCP_SERVER (object);
-
-    switch (prop_id) {
-    case PROP_PORT:
-        xdmcp_server_set_port (self, g_value_get_int (value));
-        break;
-    case PROP_HOSTNAME:
-        xdmcp_server_set_hostname (self, g_value_get_string (value));
-        break;
-    case PROP_STATUS:
-        xdmcp_server_set_status (self, g_value_get_string (value));      
-        break;
-    case PROP_AUTHENTICATION_KEY:
-        xdmcp_server_set_authentication_key (self, g_value_get_string (value));      
-        break;
-    default:
-        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-        break;
-    }
-}
-
-static void
-xdmcp_server_get_property (GObject    *object,
-                           guint       prop_id,
-                           GValue     *value,
-                           GParamSpec *pspec)
-{
-    XDMCPServer *self;
-
-    self = XDMCP_SERVER (object);
-
-    switch (prop_id) {
-    case PROP_PORT:
-        g_value_set_int (value, self->priv->port);
-        break;
-    case PROP_HOSTNAME:
-        g_value_set_string (value, self->priv->hostname);
-        break;
-    case PROP_STATUS:
-        g_value_set_string (value, self->priv->status);
-        break;
-    case PROP_AUTHENTICATION_KEY:
-        g_value_set_string (value, xdmcp_server_get_authentication_key (self));
-        break;
-    default:
-        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-        break;
-    }
+    server->priv->authentication_name = g_strdup ("");
+    server->priv->authorization_name = g_strdup ("");
 }
 
 static void
@@ -577,7 +562,10 @@ xdmcp_server_finalize (GObject *object)
         g_object_unref (self->priv->socket);
     g_free (self->priv->hostname);
     g_free (self->priv->status);
-    g_free (self->priv->authentication_key_string);
+    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_hash_table_unref (self->priv->sessions);
 }
 
@@ -586,41 +574,10 @@ xdmcp_server_class_init (XDMCPServerClass *klass)
 {
     GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
-    object_class->set_property = xdmcp_server_set_property;
-    object_class->get_property = xdmcp_server_get_property;
     object_class->finalize = xdmcp_server_finalize;  
 
     g_type_class_add_private (klass, sizeof (XDMCPServerPrivate));
 
-    g_object_class_install_property (object_class,
-                                     PROP_PORT,
-                                     g_param_spec_int ("port",
-                                                       "port",
-                                                       "UDP/IP port to listen on",
-                                                       1, G_MAXUINT16, XDM_UDP_PORT,
-                                                       G_PARAM_READWRITE));
-    g_object_class_install_property (object_class,
-                                     PROP_HOSTNAME,
-                                     g_param_spec_string ("hostname",
-                                                          "hostname",
-                                                          "Hostname",
-                                                          NULL,
-                                                          G_PARAM_READWRITE));
-    g_object_class_install_property (object_class,
-                                     PROP_STATUS,
-                                     g_param_spec_string ("status",
-                                                          "status",
-                                                          "Server status",
-                                                          NULL,
-                                                          G_PARAM_READWRITE));
-    g_object_class_install_property (object_class,
-                                     PROP_AUTHENTICATION_KEY,
-                                     g_param_spec_string ("authentication-key",
-                                                          "authentication-key",
-                                                          "Authentication key",
-                                                          NULL,
-                                                          G_PARAM_READWRITE));
-
     signals[SESSION_ADDED] =
         g_signal_new ("session-added",
                       G_TYPE_FROM_CLASS (klass),
index 5e828b10d3b9f892c332696b7a2000b4c520fab4..5ae051254cb2b82d03e058b83a81754c360f690c 100644 (file)
@@ -53,9 +53,21 @@ void xdmcp_server_set_status (XDMCPServer *server, const gchar *status);
 
 const gchar *xdmcp_server_get_status (XDMCPServer *server);
 
-void xdmcp_server_set_authentication_key (XDMCPServer *server, const gchar *key);
+void xdmcp_server_set_authentication (XDMCPServer *server, const gchar *name, const guchar *data, gsize data_length);
 
-const gchar *xdmcp_server_get_authentication_key (XDMCPServer *server);
+const gchar *xdmcp_server_get_authentication_name (XDMCPServer *server);
+
+const guchar *xdmcp_server_get_authentication_data (XDMCPServer *server);
+
+gsize xdmcp_server_get_authentication_data_length (XDMCPServer *server);
+
+void xdmcp_server_set_authorization (XDMCPServer *server, const gchar *name, const guchar *data, gsize data_length);
+
+const gchar *xdmcp_server_get_authorization_name (XDMCPServer *server);
+
+const guchar *xdmcp_server_get_authorization_data (XDMCPServer *server);
+
+gsize xdmcp_server_get_authorization_data_length (XDMCPServer *server);
 
 gboolean xdmcp_server_start (XDMCPServer *server);
 
index 2feddf3521c2b3a70b88770e5959a3d82bc8a174..1d532827baba5176b9602cf99a8b5fcbd5d65d9c 100644 (file)
 #ifndef _XDMCP_SESSION_PRIVATE_H_
 #define _XDMCP_SESSION_PRIVATE_H_
 
+#include "xdmcp-server.h"
 #include <xcb/xcb.h>
 
 struct XDMCPSessionPrivate
 {
+    XDMCPServer *server;
+
     guint16 id;
 
     gchar *manufacturer_display_id;
 
     GInetAddress *address;
 
+    guint inactive_timeout;
+
     gchar *authorization_name;
   
     gboolean started;
index 587e0dce041e62796da5abf8406cb0590804e73d..ed8286c662c20f6920ddad5ffffe97f4459e450e 100644 (file)
@@ -10,6 +10,7 @@
  */
 
 #include <stdlib.h>
+#include <string.h>
 #include <sys/wait.h>
 
 #include "xserver.h"
@@ -20,7 +21,6 @@ enum {
     PROP_COMMAND,
     PROP_HOSTNAME,
     PROP_PORT,
-    PROP_COOKIE,
     PROP_DISPLAY_NUMBER,
     PROP_ADDRESS
 };
@@ -51,8 +51,19 @@ struct XServerPrivate
     /* UDP/IP port to connect to XDMCP manager */
     guint port;
 
-    /* Auhentication cookie to use */
-    gchar *cookie;
+    /* Auhentication scheme to use */
+    gchar *authentication_name;
+
+    /* Auhentication data */  
+    guchar *authentication_data;
+    gsize authentication_data_length;
+
+    /* Authorization scheme to use */
+    gchar *authorization_name;
+
+    /* Authorization data */
+    guchar *authorization_data;
+    gsize authorization_data_length;
 
     /* Display number */
     gint display_number;
@@ -75,10 +86,7 @@ xserver_handle_signal (GPid pid)
 
     server = g_hash_table_lookup (servers, GINT_TO_POINTER (pid));
     if (!server)
-    {
-        g_warning ("Ignoring signal from unknown process %d", pid);
         return;
-    }
 
     if (!server->priv->ready)
     {
@@ -124,19 +132,6 @@ guint xserver_get_port (XServer *server)
     return server->priv->port;
 }
 
-void
-xserver_set_cookie (XServer *server, const gchar *cookie)
-{
-    g_free (server->priv->cookie);
-    server->priv->cookie = g_strdup (cookie);
-}
-
-const gchar *
-xserver_get_cookie (XServer *server)
-{
-    return server->priv->cookie;
-}
-
 const gchar *
 xserver_get_hostname (XServer *server)
 {
@@ -163,6 +158,64 @@ xserver_get_address (XServer *server)
     return server->priv->address;
 }
 
+void
+xserver_set_authentication (XServer *server, const gchar *name, const guchar *data, gsize data_length)
+{
+    g_free (server->priv->authentication_name);
+    server->priv->authentication_name = g_strdup (name);
+    g_free (server->priv->authentication_data);
+    server->priv->authentication_data = g_malloc (data_length);
+    server->priv->authentication_data_length = data_length;
+    memcpy (server->priv->authentication_data, data, data_length);
+}
+
+const gchar *
+xserver_get_authentication_name (XServer *server)
+{
+    return server->priv->authentication_name;
+}
+
+const guchar *
+xserver_get_authentication_data (XServer *server)
+{
+    return server->priv->authentication_data;
+}
+
+gsize
+xserver_get_authentication_data_length (XServer *server)
+{
+    return server->priv->authentication_data_length;
+}
+
+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)
+{
+    return server->priv->authorization_name;
+}
+
+const guchar *
+xserver_get_authorization_data (XServer *server)
+{
+    return server->priv->authorization_data;
+}
+
+gsize
+xserver_get_authorization_data_length (XServer *server)
+{
+    return server->priv->authorization_data_length;
+}
+
 static void
 xserver_watch_cb (GPid pid, gint status, gpointer data)
 {
@@ -225,8 +278,17 @@ xserver_start (XServer *server)
         if (server->priv->port != 0)
             g_string_append_printf (command, " -port %d", server->priv->port);
         g_string_append_printf (command, " -query %s", server->priv->hostname);
-        if (server->priv->cookie)
-            g_string_append_printf (command, " -cookie %s", server->priv->cookie);
+        if (strcmp (server->priv->authentication_name, "XDM-AUTHENTICATION-1") == 0 && server->priv->authentication_data_length > 0)
+        {
+            GString *cookie;
+            gsize i;
+
+            cookie = g_string_new ("0x");
+            for (i = 0; i < server->priv->authentication_data_length; i++)
+                g_string_append_printf (cookie, "%02X", server->priv->authentication_data[i]);
+            g_string_append_printf (command, " -cookie %s", cookie->str);
+            g_string_free (cookie, TRUE);
+        }
     }
     else
         g_string_append (command, " -nolisten tcp");
@@ -271,6 +333,8 @@ 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
@@ -296,9 +360,6 @@ xserver_set_property (GObject      *object,
     case PROP_PORT:
         self->priv->port = g_value_get_int (value);
         break;
-    case PROP_COOKIE:
-        xserver_set_cookie (self, g_value_get_string (value));
-        break;
     case PROP_DISPLAY_NUMBER:
         self->priv->display_number = g_value_get_int (value);
         break;
@@ -332,9 +393,6 @@ xserver_get_property (GObject    *object,
     case PROP_PORT:
         g_value_set_int (value, self->priv->port);
         break;
-    case PROP_COOKIE:
-        g_value_set_string (value, self->priv->cookie);
-        break;
     case PROP_DISPLAY_NUMBER:
         g_value_set_int (value, self->priv->display_number);
         break;
@@ -357,9 +415,12 @@ xserver_finalize (GObject *object)
     if (self->priv->pid)
         kill (self->priv->pid, SIGTERM);
 
-    g_free (self->priv->command);  
+    g_free (self->priv->command);
     g_free (self->priv->hostname);
-    g_free (self->priv->cookie);
+    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);
 }
 
@@ -409,13 +470,6 @@ xserver_class_init (XServerClass *klass)
                                                        "UDP/IP port to connect XDMCP on",
                                                        0, G_MAXINT, 0,
                                                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-    g_object_class_install_property (object_class,
-                                     PROP_COOKIE,
-                                     g_param_spec_string ("cookie",
-                                                          "cookie",
-                                                          "Authentication key to use for XDMCP",
-                                                          NULL,
-                                                          G_PARAM_READWRITE));
     g_object_class_install_property (object_class,
                                      PROP_ADDRESS,
                                      g_param_spec_string ("address",
index 8bb741ba788b43ba19043306ef2b7433305b20f4..c0710a610dd599213c76680e22cc1189bb2dc638 100644 (file)
@@ -64,16 +64,28 @@ void xserver_set_port (XServer *server, guint port);
 
 guint xserver_get_port (XServer *server);
 
-void xserver_set_cookie (XServer *server, const gchar *cookie);
-
-const gchar *xserver_get_cookie (XServer *server);
-
 const gchar *xserver_get_hostname (XServer *server);
 
 gint xserver_get_display_number (XServer *server);
 
 const gchar *xserver_get_address (XServer *server);
 
+void xserver_set_authentication (XServer *server, const gchar *name, const guchar *data, gsize data_length);
+
+const gchar *xserver_get_authentication_name (XServer *server);
+
+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);
+
+gsize xserver_get_authorization_data_length (XServer *server);
+
 gboolean xserver_start (XServer *server);
 
 G_END_DECLS