~lightdm-team/lightdm/1.4

« back to all changes in this revision

Viewing changes to src/xdmcp-server.c

  • Committer: robert.ancell at gmail
  • Date: 2010-04-29 11:08:26 UTC
  • Revision ID: robert.ancell@gmail.com-20100429110826-eef3w3c9hl80pxxy
Compiles and does something

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2010 Robert Ancell.
3
 
 * Author: Robert Ancell <robert.ancell@canonical.com>
4
 
 * 
5
 
 * This program is free software: you can redistribute it and/or modify it under
6
 
 * the terms of the GNU General Public License as published by the Free Software
7
 
 * Foundation, either version 3 of the License, or (at your option) any later
8
 
 * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
9
 
 * license.
10
 
 */
11
 
 
12
 
#include <stdlib.h>
13
 
#include <string.h>
14
 
#include <X11/X.h>
15
 
#define HASXDMAUTH
16
 
#include <X11/Xdmcp.h>
17
 
#include <gio/gio.h>
18
 
#include "ldm-marshal.h"
19
 
 
20
 
#include "xdmcp-server.h"
21
 
#include "xdmcp-protocol.h"
22
 
#include "xdmcp-session-private.h"
23
 
#include "xauth.h"
24
 
 
25
 
enum {
26
 
    NEW_SESSION,
27
 
    LAST_SIGNAL
28
 
};
29
 
static guint signals[LAST_SIGNAL] = { 0 };
30
 
 
31
 
struct XDMCPServerPrivate
32
 
{
33
 
    /* Port to listen on */
34
 
    guint port;
35
 
 
36
 
    /* Listening sockets */
37
 
    GSocket *socket, *socket6;
38
 
 
39
 
    /* Hostname to report to client */
40
 
    gchar *hostname;
41
 
 
42
 
    /* Status to report to clients */
43
 
    gchar *status;
44
 
 
45
 
    /* Auhentication scheme to use */
46
 
    gchar *authentication_name;
47
 
 
48
 
    /* Auhentication data */  
49
 
    guchar *authentication_data;
50
 
    gsize authentication_data_length;
51
 
 
52
 
    /* Authorization scheme to use */
53
 
    gchar *authorization_name;
54
 
 
55
 
    /* Authorization data */
56
 
    guchar *authorization_data;
57
 
    gsize authorization_data_length;
58
 
 
59
 
    /* Active XDMCP sessions */
60
 
    GHashTable *sessions;
61
 
};
62
 
 
63
 
G_DEFINE_TYPE (XDMCPServer, xdmcp_server, G_TYPE_OBJECT);
64
 
 
65
 
XDMCPServer *
66
 
xdmcp_server_new (void)
67
 
{
68
 
    return g_object_new (XDMCP_SERVER_TYPE, NULL);
69
 
}
70
 
 
71
 
void
72
 
xdmcp_server_set_port (XDMCPServer *server, guint port)
73
 
{
74
 
    server->priv->port = port;
75
 
}
76
 
 
77
 
guint
78
 
xdmcp_server_get_port (XDMCPServer *server)
79
 
{
80
 
    return server->priv->port;
81
 
}
82
 
 
83
 
void
84
 
xdmcp_server_set_hostname (XDMCPServer *server, const gchar *hostname)
85
 
{
86
 
    g_free (server->priv->hostname);
87
 
    server->priv->hostname = g_strdup (hostname);
88
 
}
89
 
 
90
 
const gchar *
91
 
xdmcp_server_get_hostname (XDMCPServer *server)
92
 
{
93
 
    return server->priv->hostname;
94
 
}
95
 
 
96
 
void
97
 
xdmcp_server_set_status (XDMCPServer *server, const gchar *status)
98
 
{
99
 
    g_free (server->priv->status);
100
 
    server->priv->status = g_strdup (status);
101
 
}
102
 
 
103
 
const gchar *
104
 
xdmcp_server_get_status (XDMCPServer *server)
105
 
{
106
 
    return server->priv->status;
107
 
}
108
 
 
109
 
void
110
 
xdmcp_server_set_authentication (XDMCPServer *server, const gchar *name, const guchar *data, gsize data_length)
111
 
{
112
 
    g_free (server->priv->authentication_name);
113
 
    server->priv->authentication_name = g_strdup (name);
114
 
    g_free (server->priv->authentication_data);
115
 
    server->priv->authentication_data = g_malloc (data_length);
116
 
    server->priv->authentication_data_length = data_length;
117
 
    memcpy (server->priv->authentication_data, data, data_length);
118
 
}
119
 
 
120
 
const gchar *
121
 
xdmcp_server_get_authentication_name (XDMCPServer *server)
122
 
{
123
 
    return server->priv->authentication_name;
124
 
}
125
 
 
126
 
const guchar *
127
 
xdmcp_server_get_authentication_data (XDMCPServer *server)
128
 
{
129
 
    return server->priv->authentication_data;
130
 
}
131
 
 
132
 
gsize
133
 
xdmcp_server_get_authentication_data_length (XDMCPServer *server)
134
 
{
135
 
    return server->priv->authentication_data_length;
136
 
}
137
 
 
138
 
void
139
 
xdmcp_server_set_authorization (XDMCPServer *server, const gchar *name, const guchar *data, gsize data_length)
140
 
{
141
 
    g_free (server->priv->authorization_name);
142
 
    server->priv->authorization_name = g_strdup (name);
143
 
    g_free (server->priv->authorization_data);
144
 
    server->priv->authorization_data = g_malloc (data_length);
145
 
    server->priv->authorization_data_length = data_length;
146
 
    memcpy (server->priv->authorization_data, data, data_length);
147
 
}
148
 
 
149
 
const gchar *
150
 
xdmcp_server_get_authorization_name (XDMCPServer *server)
151
 
{
152
 
    return server->priv->authorization_name;
153
 
}
154
 
 
155
 
const guchar *
156
 
xdmcp_server_get_authorization_data (XDMCPServer *server)
157
 
{
158
 
    return server->priv->authorization_data;
159
 
}
160
 
 
161
 
gsize
162
 
xdmcp_server_get_authorization_data_length (XDMCPServer *server)
163
 
{
164
 
    return server->priv->authorization_data_length;
165
 
}
166
 
 
167
 
static gboolean
168
 
session_timeout_cb (XDMCPSession *session)
169
 
{
170
 
    g_debug ("Timing out unmanaged session %d", session->priv->id);
171
 
    g_hash_table_remove (session->priv->server->priv->sessions, GINT_TO_POINTER ((gint) session->priv->id));
172
 
    return FALSE;
173
 
}
174
 
 
175
 
static XDMCPSession *
176
 
add_session (XDMCPServer *server)
177
 
{
178
 
    XDMCPSession *session;
179
 
    guint16 id;
180
 
 
181
 
    do
182
 
    {
183
 
        id = g_random_int () & 0xFFFFFFFF;
184
 
    } while (g_hash_table_lookup (server->priv->sessions, GINT_TO_POINTER ((gint) id)));
185
 
 
186
 
    session = xdmcp_session_new (id);
187
 
    session->priv->server = server;
188
 
    g_hash_table_insert (server->priv->sessions, GINT_TO_POINTER ((gint) id), g_object_ref (session));
189
 
    session->priv->inactive_timeout = g_timeout_add (10, (GSourceFunc) session_timeout_cb, session);
190
 
 
191
 
    return session;
192
 
}
193
 
 
194
 
static XDMCPSession *
195
 
get_session (XDMCPServer *server, guint16 id)
196
 
{
197
 
    return g_hash_table_lookup (server->priv->sessions, GINT_TO_POINTER ((gint) id));
198
 
}
199
 
 
200
 
static void
201
 
send_packet (GSocket *socket, GSocketAddress *address, XDMCPPacket *packet)
202
 
{
203
 
    guchar data[1024];
204
 
    gssize n_written;
205
 
 
206
 
    g_debug ("Send %s", xdmcp_packet_tostring (packet));
207
 
              
208
 
    n_written = xdmcp_packet_encode (packet, data, 1024);
209
 
    if (n_written < 0)
210
 
      g_critical ("Failed to encode XDMCP packet");
211
 
    else
212
 
    {
213
 
        GError *error = NULL;
214
 
 
215
 
        if (g_socket_send_to (socket, address, (gchar *) data, n_written, NULL, &error) < 0)
216
 
            g_warning ("Error sending packet: %s", error->message);
217
 
 
218
 
        g_clear_error (&error);
219
 
    }
220
 
}
221
 
 
222
 
static void
223
 
handle_query (XDMCPServer *server, GSocket *socket, GSocketAddress *address, XDMCPPacket *packet)
224
 
{
225
 
    XDMCPPacket *response;
226
 
    gchar **i;
227
 
    gboolean match_authentication = FALSE;
228
 
 
229
 
    /* If no authentication requested and we are configured for none then allow */
230
 
    if (packet->Query.authentication_names[0] == NULL && strcmp (server->priv->authentication_name, "") == 0)
231
 
        match_authentication = TRUE;
232
 
 
233
 
    for (i = packet->Query.authentication_names; *i; i++)
234
 
    {
235
 
        if (strcmp (*i, server->priv->authentication_name) == 0)
236
 
        {
237
 
            match_authentication = TRUE;
238
 
            break;
239
 
        }
240
 
    }
241
 
 
242
 
    if (match_authentication)
243
 
    {
244
 
        response = xdmcp_packet_alloc (XDMCP_Willing);
245
 
        response->Willing.authentication_name = g_strdup (server->priv->authentication_name);
246
 
        response->Willing.hostname = g_strdup (server->priv->hostname);
247
 
        response->Willing.status = g_strdup (server->priv->status);
248
 
    }
249
 
    else
250
 
    {
251
 
        response = xdmcp_packet_alloc (XDMCP_Unwilling);
252
 
        response->Willing.hostname = g_strdup (server->priv->hostname);
253
 
        response->Willing.status = g_strdup (server->priv->status);
254
 
    }
255
 
  
256
 
    send_packet (socket, address, response);
257
 
 
258
 
    xdmcp_packet_free (response);
259
 
}
260
 
 
261
 
static void
262
 
handle_request (XDMCPServer *server, GSocket *socket, GSocketAddress *address, XDMCPPacket *packet)
263
 
{
264
 
    int i;
265
 
    XDMCPPacket *response;
266
 
    XDMCPSession *session;
267
 
    guchar *authentication_data = NULL;
268
 
    gsize authentication_data_length = 0;
269
 
    gboolean match_authorization = FALSE;
270
 
    guchar *authorization_data = NULL;
271
 
    gsize authorization_data_length = 0;
272
 
    guchar *session_authorization_data = NULL;
273
 
    gsize session_authorization_data_length = 0;
274
 
    gchar **j;
275
 
    GInetAddress *address4 = NULL, *address6 = NULL;
276
 
    XdmAuthKeyRec rho;
277
 
  
278
 
    /* Must be using our authentication scheme */
279
 
    if (strcmp (packet->Request.authentication_name, server->priv->authentication_name) != 0)
280
 
    {
281
 
        response = xdmcp_packet_alloc (XDMCP_Decline);
282
 
        if (strcmp (server->priv->authentication_name, "") == 0)
283
 
            response->Decline.status = g_strdup ("Server does not support authentication");
284
 
        else
285
 
            response->Decline.status = g_strdup_printf ("Server only supports %s authentication", server->priv->authentication_name);
286
 
        response->Decline.authentication_name = g_strdup ("");
287
 
        send_packet (socket, address, response);
288
 
        xdmcp_packet_free (response);
289
 
        return;
290
 
    }
291
 
 
292
 
    /* Perform requested authentication */
293
 
    if (strcmp (server->priv->authentication_name, "XDM-AUTHENTICATION-1") == 0)
294
 
    {
295
 
        guchar input[8], key[8];
296
 
 
297
 
        memset (input, 0, 8);
298
 
        memcpy (input, packet->Request.authentication_data.data, packet->Request.authentication_data.length > 8 ? 8 : packet->Request.authentication_data.length);
299
 
 
300
 
        /* Setup key */
301
 
        memset (key, 0, 8);
302
 
        memcpy (key, server->priv->authentication_data, server->priv->authentication_data_length > 8 ? 8 : server->priv->authentication_data_length);
303
 
 
304
 
        /* Decode message from server */
305
 
        authentication_data = g_malloc (sizeof (guchar) * 8);
306
 
        authentication_data_length = 8;
307
 
 
308
 
        XdmcpUnwrap (input, key, rho.data, authentication_data_length);
309
 
        XdmcpIncrementKey (&rho);
310
 
        XdmcpWrap (rho.data, key, authentication_data, authentication_data_length);
311
 
    }
312
 
 
313
 
    /* Check if they support our authorization */
314
 
    for (j = packet->Request.authorization_names; *j; j++)
315
 
    {
316
 
        if (strcmp (*j, server->priv->authorization_name) == 0)
317
 
        {
318
 
             match_authorization = TRUE;
319
 
             break;
320
 
        }
321
 
    }
322
 
  
323
 
    if (!match_authorization)
324
 
    {
325
 
        response = xdmcp_packet_alloc (XDMCP_Decline);
326
 
        if (strcmp (server->priv->authorization_name, "") == 0)
327
 
            response->Decline.status = g_strdup ("Server does not support authorization");
328
 
        else
329
 
            response->Decline.status = g_strdup_printf ("Server only supports %s authorization", server->priv->authorization_name);
330
 
        response->Decline.authentication_name = g_strdup (packet->Request.authentication_name);
331
 
        response->Decline.authentication_data.data = authentication_data;
332
 
        response->Decline.authentication_data.length = authentication_data_length;
333
 
        send_packet (socket, address, response);
334
 
        xdmcp_packet_free (response);
335
 
        return;
336
 
    }
337
 
 
338
 
    /* Perform requested authorization */
339
 
    if (strcmp (server->priv->authorization_name, "MIT-MAGIC-COOKIE-1") == 0)
340
 
    {
341
 
        /* Data is the cookie */
342
 
        authorization_data = g_malloc (sizeof (guchar) * server->priv->authorization_data_length);
343
 
        memcpy (authorization_data, server->priv->authorization_data, server->priv->authorization_data_length);
344
 
        authorization_data_length = server->priv->authorization_data_length;
345
 
    }
346
 
    else if (strcmp (server->priv->authorization_name, "XDM-AUTHORIZATION-1") == 0)
347
 
    {
348
 
        gint i;
349
 
        guchar key[8], session_key[8];
350
 
 
351
 
        /* Setup key */
352
 
        memset (key, 0, 8);
353
 
        memcpy (key, server->priv->authentication_data, server->priv->authentication_data_length > 8 ? 8 : server->priv->authentication_data_length);
354
 
 
355
 
        /* Generate a private session key */
356
 
        // FIXME: Pick a good DES key?
357
 
        session_key[0] = 0;
358
 
        for (i = 1; i < 8; i++)
359
 
            session_key[i] = g_random_int () & 0xFF;
360
 
 
361
 
        /* Encrypt the session key and send it to the server */
362
 
        authorization_data = g_malloc (8);
363
 
        authorization_data_length = 8;
364
 
        XdmcpWrap (session_key, key, authorization_data, authorization_data_length);
365
 
 
366
 
        /* Authorization data is the number received from the client followed by the private session key */
367
 
        session_authorization_data = g_malloc (16);
368
 
        session_authorization_data_length = 16;
369
 
        XdmcpDecrementKey (&rho);
370
 
        memcpy (session_authorization_data, rho.data, 8);
371
 
        memcpy (session_authorization_data + 8, session_key, 8);
372
 
    }
373
 
 
374
 
    for (i = 0; i < packet->Request.n_connections; i++)
375
 
    {
376
 
        XDMCPConnection *connection;
377
 
 
378
 
        connection = &packet->Request.connections[i];
379
 
        switch (connection->type)
380
 
        {
381
 
        case FamilyInternet:
382
 
            if (connection->address.length == 4)
383
 
                address4 = g_inet_address_new_from_bytes (connection->address.data, G_SOCKET_FAMILY_IPV4);
384
 
            break;
385
 
        case FamilyInternet6:
386
 
            if (connection->address.length == 16)
387
 
                address6 = g_inet_address_new_from_bytes (connection->address.data, G_SOCKET_FAMILY_IPV6);          
388
 
            break;
389
 
        }
390
 
    }
391
 
 
392
 
    if (!address4) // FIXME: && !address6)
393
 
    {
394
 
        response = xdmcp_packet_alloc (XDMCP_Decline);
395
 
        response->Decline.status = g_strdup ("No valid address found");
396
 
        response->Decline.authentication_name = g_strdup (packet->Request.authentication_name);
397
 
        response->Decline.authentication_data.data = authentication_data;
398
 
        response->Decline.authentication_data.length = authentication_data_length;
399
 
        send_packet (socket, address, response);
400
 
        xdmcp_packet_free (response);
401
 
        return;
402
 
    }
403
 
 
404
 
    session = add_session (server);
405
 
    session->priv->address = address4;
406
 
    session->priv->address6 = address6;
407
 
    session->priv->authorization_name = g_strdup (server->priv->authorization_name);
408
 
    session->priv->authorization_data = session_authorization_data;
409
 
    session->priv->authorization_data_length = session_authorization_data_length;
410
 
 
411
 
    response = xdmcp_packet_alloc (XDMCP_Accept);
412
 
    response->Accept.session_id = xdmcp_session_get_id (session);
413
 
    response->Accept.authentication_name = g_strdup (packet->Request.authentication_name);
414
 
    response->Accept.authentication_data.data = authentication_data;
415
 
    response->Accept.authentication_data.length = authentication_data_length;
416
 
    response->Accept.authorization_name = g_strdup (server->priv->authorization_name);
417
 
    response->Accept.authorization_data.data = authorization_data;
418
 
    response->Accept.authorization_data.length = authorization_data_length;
419
 
    send_packet (socket, address, response);
420
 
    xdmcp_packet_free (response);
421
 
}
422
 
 
423
 
static void
424
 
handle_manage (XDMCPServer *server, GSocket *socket, GSocketAddress *address, XDMCPPacket *packet)
425
 
{
426
 
    XDMCPSession *session;
427
 
 
428
 
    session = get_session (server, packet->Manage.session_id);
429
 
    if (session)
430
 
    {
431
 
        gchar *display_address;
432
 
        gboolean result;
433
 
 
434
 
        /* Ignore duplicate requests */
435
 
        if (session->priv->started)
436
 
        {
437
 
            if (session->priv->display_number != packet->Manage.display_number ||
438
 
                strcmp (session->priv->display_class, packet->Manage.display_class) != 0)
439
 
                g_warning ("Duplicate Manage received with different data");
440
 
            return;
441
 
        }
442
 
 
443
 
        session->priv->display_number = packet->Manage.display_number;  
444
 
        session->priv->display_class = g_strdup (packet->Manage.display_class);
445
 
 
446
 
        g_signal_emit (server, signals[NEW_SESSION], 0, session, &result);
447
 
        if (result)
448
 
        {
449
 
            /* Cancel the inactive timer */
450
 
            g_source_remove (session->priv->inactive_timeout);
451
 
 
452
 
            session->priv->started = TRUE;
453
 
        }
454
 
        else
455
 
        {
456
 
            XDMCPPacket *response;
457
 
 
458
 
            response = xdmcp_packet_alloc (XDMCP_Failed);
459
 
            response->Failed.session_id = packet->Manage.session_id;
460
 
            response->Failed.status = g_strdup_printf ("Failed to connect to display %s", display_address);
461
 
            send_packet (socket, address, response);
462
 
            xdmcp_packet_free (response);
463
 
        }
464
 
 
465
 
        g_free (display_address);
466
 
    }
467
 
    else
468
 
    {
469
 
        XDMCPPacket *response;
470
 
 
471
 
        response = xdmcp_packet_alloc (XDMCP_Refuse);
472
 
        response->Refuse.session_id = packet->Manage.session_id;
473
 
        send_packet (socket, address, response);
474
 
        xdmcp_packet_free (response);
475
 
    }
476
 
}
477
 
 
478
 
static void
479
 
handle_keep_alive (XDMCPServer *server, GSocket *socket, GSocketAddress *address, XDMCPPacket *packet)
480
 
{
481
 
    XDMCPPacket *response;
482
 
    XDMCPSession *session;
483
 
    gboolean alive = FALSE;
484
 
 
485
 
    session = get_session (server, packet->KeepAlive.session_id);
486
 
    if (session)
487
 
        alive = TRUE; //xdmcp_session_get_alive (session);
488
 
 
489
 
    response = xdmcp_packet_alloc (XDMCP_Alive);
490
 
    response->Alive.session_running = alive;
491
 
    response->Alive.session_id = alive ? packet->KeepAlive.session_id : 0;
492
 
    send_packet (socket, address, response);
493
 
    xdmcp_packet_free (response);
494
 
}
495
 
 
496
 
static gboolean
497
 
read_cb (GSocket *socket, GIOCondition condition, XDMCPServer *server)
498
 
{
499
 
    GSocketAddress *address;
500
 
    gchar data[1024];
501
 
    GError *error = NULL;
502
 
    gssize n_read;
503
 
 
504
 
    n_read = g_socket_receive_from (socket, &address, data, 1024, NULL, &error);
505
 
    if (n_read > 0)
506
 
    {
507
 
        XDMCPPacket *packet;
508
 
 
509
 
        packet = xdmcp_packet_decode ((guchar *)data, n_read);
510
 
        if (packet)
511
 
        {        
512
 
            g_debug ("Got %s", xdmcp_packet_tostring (packet));
513
 
 
514
 
            switch (packet->opcode)
515
 
            {
516
 
            case XDMCP_BroadcastQuery:
517
 
            case XDMCP_Query:
518
 
            case XDMCP_IndirectQuery:
519
 
                handle_query (server, socket, address, packet);
520
 
                break;
521
 
            case XDMCP_Request:
522
 
                handle_request (server, socket, address, packet);
523
 
                break;
524
 
            case XDMCP_Manage:
525
 
                handle_manage (server, socket, address, packet);              
526
 
                break;
527
 
            case XDMCP_KeepAlive:
528
 
                handle_keep_alive (server, socket, address, packet);
529
 
                break;
530
 
            default:
531
 
                g_warning ("Got unexpected XDMCP packet %d", packet->opcode);
532
 
                break;
533
 
            }
534
 
 
535
 
            xdmcp_packet_free (packet);
536
 
        }
537
 
    }
538
 
    else
539
 
        g_warning ("Failed to read from XDMCP socket: %s", error->message);
540
 
 
541
 
    g_clear_error (&error);
542
 
 
543
 
    return TRUE;
544
 
}
545
 
 
546
 
static GSocket *
547
 
open_udp_socket (GSocketFamily family, guint port, GError **error)
548
 
{
549
 
    GSocket *socket;
550
 
    GSocketAddress *address;
551
 
    gboolean result;
552
 
  
553
 
    socket = g_socket_new (family, G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, error);
554
 
    if (!socket)
555
 
        return NULL;
556
 
 
557
 
    address = g_inet_socket_address_new (g_inet_address_new_any (family), port);
558
 
    result = g_socket_bind (socket, address, TRUE, error);
559
 
    if (!result)
560
 
    {
561
 
        g_object_unref (socket);
562
 
        return NULL;
563
 
    }
564
 
 
565
 
    return socket;
566
 
}
567
 
 
568
 
gboolean
569
 
xdmcp_server_start (XDMCPServer *server)
570
 
{
571
 
    GSource *source;
572
 
    GError *error = NULL;
573
 
  
574
 
    server->priv->socket = open_udp_socket (G_SOCKET_FAMILY_IPV4, server->priv->port, &error);
575
 
    if (server->priv->socket)
576
 
    {
577
 
        source = g_socket_create_source (server->priv->socket, G_IO_IN, NULL);
578
 
        g_source_set_callback (source, (GSourceFunc) read_cb, server, NULL);
579
 
        g_source_attach (source, NULL);
580
 
    }
581
 
    else
582
 
        g_warning ("Failed to create IPv4 XDMCP socket: %s", error->message);
583
 
    g_clear_error (&error);
584
 
    server->priv->socket6 = open_udp_socket (G_SOCKET_FAMILY_IPV6, server->priv->port, &error);  
585
 
    if (server->priv->socket6)
586
 
    {
587
 
        source = g_socket_create_source (server->priv->socket6, G_IO_IN, NULL);
588
 
        g_source_set_callback (source, (GSourceFunc) read_cb, server, NULL);
589
 
        g_source_attach (source, NULL);
590
 
    }
591
 
    else
592
 
        g_warning ("Failed to create IPv6 XDMCP socket: %s", error->message);
593
 
    g_clear_error (&error);
594
 
 
595
 
    if (!server->priv->socket && !server->priv->socket6)
596
 
        return FALSE;
597
 
 
598
 
    return TRUE;
599
 
}
600
 
 
601
 
static void
602
 
xdmcp_server_init (XDMCPServer *server)
603
 
{
604
 
    server->priv = G_TYPE_INSTANCE_GET_PRIVATE (server, XDMCP_SERVER_TYPE, XDMCPServerPrivate);
605
 
 
606
 
    server->priv->port = XDM_UDP_PORT;
607
 
    server->priv->hostname = g_strdup ("");
608
 
    server->priv->status = g_strdup ("");
609
 
    server->priv->sessions = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref);
610
 
    server->priv->authentication_name = g_strdup ("");
611
 
    server->priv->authorization_name = g_strdup ("");
612
 
}
613
 
 
614
 
static void
615
 
xdmcp_server_finalize (GObject *object)
616
 
{
617
 
    XDMCPServer *self;
618
 
 
619
 
    self = XDMCP_SERVER (object);
620
 
  
621
 
    if (self->priv->socket)
622
 
        g_object_unref (self->priv->socket);
623
 
    if (self->priv->socket6)
624
 
        g_object_unref (self->priv->socket6);
625
 
    g_free (self->priv->hostname);
626
 
    g_free (self->priv->status);
627
 
    g_free (self->priv->authentication_name);
628
 
    g_free (self->priv->authentication_data);
629
 
    g_free (self->priv->authorization_name);
630
 
    g_free (self->priv->authorization_data);
631
 
    g_hash_table_unref (self->priv->sessions);
632
 
}
633
 
 
634
 
static void
635
 
xdmcp_server_class_init (XDMCPServerClass *klass)
636
 
{
637
 
    GObjectClass *object_class = G_OBJECT_CLASS (klass);
638
 
 
639
 
    object_class->finalize = xdmcp_server_finalize;  
640
 
 
641
 
    g_type_class_add_private (klass, sizeof (XDMCPServerPrivate));
642
 
 
643
 
    signals[NEW_SESSION] =
644
 
        g_signal_new ("new-session",
645
 
                      G_TYPE_FROM_CLASS (klass),
646
 
                      G_SIGNAL_RUN_LAST,
647
 
                      G_STRUCT_OFFSET (XDMCPServerClass, new_session),
648
 
                      g_signal_accumulator_true_handled,
649
 
                      NULL,
650
 
                      ldm_marshal_BOOLEAN__OBJECT,
651
 
                      G_TYPE_BOOLEAN, 1, XDMCP_SESSION_TYPE);
652
 
}