~ubuntu-branches/ubuntu/oneiric/gdm3/oneiric

« back to all changes in this revision

Viewing changes to daemon/gdm-xdmcp-display-factory.c

  • Committer: Bazaar Package Importer
  • Author(s): Josselin Mouette
  • Date: 2010-03-25 20:02:20 UTC
  • Revision ID: james.westby@ubuntu.com-20100325200220-12cap62s6p304nuh
Tags: upstream-2.29.92
ImportĀ upstreamĀ versionĀ 2.29.92

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
 
2
 *
 
3
 * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net>
 
4
 * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 2 of the License, or
 
9
 * (at your option) any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write to the Free Software
 
18
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
19
 *
 
20
 */
 
21
 
 
22
#include "config.h"
 
23
 
 
24
#include <stdlib.h>
 
25
#include <stdio.h>
 
26
#include <fcntl.h>
 
27
#include <unistd.h>
 
28
#include <string.h>
 
29
#include <signal.h>
 
30
#include <sys/stat.h>
 
31
#include <sys/types.h>
 
32
#include <sys/utsname.h>
 
33
 
 
34
#include <sys/socket.h>
 
35
#include <netdb.h>
 
36
#include <arpa/inet.h>
 
37
#include <net/if.h>
 
38
#ifdef HAVE_SYS_SOCKIO_H
 
39
#include <sys/sockio.h>
 
40
#endif
 
41
#include <sys/ioctl.h>
 
42
 
 
43
#include <errno.h>
 
44
 
 
45
#include <glib.h>
 
46
#include <glib/gi18n.h>
 
47
#include <glib/gstdio.h>
 
48
#include <glib-object.h>
 
49
 
 
50
#include <X11/Xlib.h>
 
51
#include <X11/Xmd.h>
 
52
#include <X11/Xdmcp.h>
 
53
 
 
54
#include "gdm-common.h"
 
55
#include "gdm-xdmcp-greeter-display.h"
 
56
#include "gdm-xdmcp-chooser-display.h"
 
57
#include "gdm-display-factory.h"
 
58
#include "gdm-xdmcp-display-factory.h"
 
59
#include "gdm-display-store.h"
 
60
#include "gdm-settings-direct.h"
 
61
#include "gdm-settings-keys.h"
 
62
 
 
63
/*
 
64
 * On Sun, we need to define allow_severity and deny_severity to link
 
65
 * against libwrap.
 
66
 */
 
67
#ifdef __sun
 
68
#include <syslog.h>
 
69
int allow_severity = LOG_INFO;
 
70
int deny_severity = LOG_WARNING;
 
71
#endif
 
72
 
 
73
#define GDM_XDMCP_DISPLAY_FACTORY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_XDMCP_DISPLAY_FACTORY, GdmXdmcpDisplayFactoryPrivate))
 
74
 
 
75
#define DEFAULT_PORT                  177
 
76
#define DEFAULT_USE_MULTICAST         FALSE
 
77
#define DEFAULT_MULTICAST_ADDRESS     "ff02::1"
 
78
#define DEFAULT_HONOR_INDIRECT        TRUE
 
79
#define DEFAULT_MAX_DISPLAYS_PER_HOST 1
 
80
#define DEFAULT_MAX_DISPLAYS          16
 
81
#define DEFAULT_MAX_PENDING_DISPLAYS  4
 
82
#define DEFAULT_MAX_WAIT              30
 
83
#define DEFAULT_MAX_WAIT_INDIRECT     30
 
84
#define DEFAULT_WILLING_SCRIPT        GDMCONFDIR "/Xwilling"
 
85
 
 
86
#define GDM_MAX_FORWARD_QUERIES 10
 
87
#define GDM_FORWARD_QUERY_TIMEOUT 30
 
88
#define MANAGED_FORWARD_INTERVAL 1500 /* 1.5 seconds */
 
89
 
 
90
/* some extra XDMCP opcodes that xdm will happily ignore since they'll be
 
91
 * the wrong XDMCP version anyway */
 
92
#define GDM_XDMCP_PROTOCOL_VERSION 1001
 
93
enum {
 
94
        GDM_XDMCP_FIRST_OPCODE = 1000, /*just a marker, not an opcode */
 
95
 
 
96
        GDM_XDMCP_MANAGED_FORWARD = 1000,
 
97
                /* manager (master) -> manager
 
98
                 * A packet with MANAGED_FORWARD is sent to the
 
99
                 * manager that sent the forward query from the manager to
 
100
                 * which forward query was sent.  It indicates that the forward
 
101
                 * was fully processed and that the client now has either
 
102
                 * a managed session, or has been sent denial, refuse or failed.
 
103
                 * (if the denial gets lost then client gets dumped into the
 
104
                 * chooser again).  This should be resent a few times
 
105
                 * until some (short) timeout or until GOT_MANAGED_FORWARD
 
106
                 * is sent.  GDM sends at most 3 packates with 1.5 seconds
 
107
                 * between each.
 
108
                 *
 
109
                 * Argument is ARRAY8 with the address of the originating host */
 
110
        GDM_XDMCP_GOT_MANAGED_FORWARD,
 
111
                /* manager -> manager (master)
 
112
                 * A single packet with GOT_MANAGED_FORWARD is sent to indicate
 
113
                 * that we did receive the MANAGED_FORWARD packet.  The argument
 
114
                 * must match the MANAGED_FORWARD one or it will just be ignored.
 
115
                 *
 
116
                 * Argument is ARRAY8 with the address of the originating host */
 
117
        GDM_XDMCP_LAST_OPCODE /*just a marker, not an opcode */
 
118
};
 
119
 
 
120
/*
 
121
 * We don't support XDM-AUTHENTICATION-1 and XDM-AUTHORIZATION-1.
 
122
 *
 
123
 * The latter would be quite useful to avoid sending unencrypted
 
124
 * cookies over the wire. Unfortunately it isn't supported without
 
125
 * XDM-AUTHENTICATION-1 which requires a key database with private
 
126
 * keys from all X terminals on your LAN. Fun, fun, fun.
 
127
 *
 
128
 * Furthermore user passwords go over the wire in cleartext anyway,
 
129
 * so protecting cookies is not that important.
 
130
 */
 
131
 
 
132
typedef struct _XdmAuth {
 
133
        ARRAY8 authentication;
 
134
        ARRAY8 authorization;
 
135
} XdmAuthRec, *XdmAuthPtr;
 
136
 
 
137
static XdmAuthRec serv_authlist = {
 
138
        { (CARD16) 0, (CARD8 *) 0 },
 
139
        { (CARD16) 0, (CARD8 *) 0 }
 
140
};
 
141
 
 
142
/* NOTE: Timeout and max are hardcoded */
 
143
typedef struct _ForwardQuery {
 
144
        time_t      acctime;
 
145
        GdmAddress *dsp_address;
 
146
        GdmAddress *from_address;
 
147
} ForwardQuery;
 
148
 
 
149
typedef struct _IndirectClient {
 
150
        int         id;
 
151
        GdmAddress *dsp_address;
 
152
        GdmAddress *chosen_address;
 
153
        time_t      acctime;
 
154
} IndirectClient;
 
155
 
 
156
typedef struct {
 
157
        int                     times;
 
158
        guint                   handler;
 
159
        GdmAddress             *manager;
 
160
        GdmAddress             *origin;
 
161
        GdmXdmcpDisplayFactory *xdmcp_display_factory;
 
162
} ManagedForward;
 
163
 
 
164
struct GdmXdmcpDisplayFactoryPrivate
 
165
{
 
166
        GSList          *forward_queries;
 
167
        GSList          *managed_forwards;
 
168
        GSList          *indirect_clients;
 
169
 
 
170
        int              socket_fd;
 
171
        gint32           session_serial;
 
172
        guint            socket_watch_id;
 
173
        XdmcpBuffer      buf;
 
174
 
 
175
        guint            num_sessions;
 
176
        guint            num_pending_sessions;
 
177
 
 
178
        char            *sysid;
 
179
        char            *hostname;
 
180
        ARRAY8           servhost;
 
181
 
 
182
        /* configuration */
 
183
        guint            port;
 
184
        gboolean         use_multicast;
 
185
        char            *multicast_address;
 
186
        gboolean         honor_indirect;
 
187
        char            *willing_script;
 
188
        guint            max_displays_per_host;
 
189
        guint            max_displays;
 
190
        guint            max_pending_displays;
 
191
        guint            max_wait;
 
192
        guint            max_wait_indirect;
 
193
};
 
194
 
 
195
enum {
 
196
        PROP_0,
 
197
        PROP_PORT,
 
198
        PROP_USE_MULTICAST,
 
199
        PROP_MULTICAST_ADDRESS,
 
200
        PROP_HONOR_INDIRECT,
 
201
        PROP_WILLING_SCRIPT,
 
202
        PROP_MAX_DISPLAYS_PER_HOST,
 
203
        PROP_MAX_DISPLAYS,
 
204
        PROP_MAX_PENDING_DISPLAYS,
 
205
        PROP_MAX_WAIT,
 
206
        PROP_MAX_WAIT_INDIRECT,
 
207
};
 
208
 
 
209
static void     gdm_xdmcp_display_factory_class_init    (GdmXdmcpDisplayFactoryClass *klass);
 
210
static void     gdm_xdmcp_display_factory_init          (GdmXdmcpDisplayFactory      *manager);
 
211
static void     gdm_xdmcp_display_factory_finalize      (GObject                     *object);
 
212
 
 
213
static gpointer xdmcp_display_factory_object = NULL;
 
214
 
 
215
G_DEFINE_TYPE (GdmXdmcpDisplayFactory, gdm_xdmcp_display_factory, GDM_TYPE_DISPLAY_FACTORY)
 
216
 
 
217
/* Theory of operation:
 
218
 *
 
219
 * Process idles waiting for UDP packets on port 177.
 
220
 * Incoming packets are decoded and checked against tcp_wrapper.
 
221
 *
 
222
 * A typical session looks like this:
 
223
 *
 
224
 * Display sends Query/BroadcastQuery to Manager.
 
225
 *
 
226
 * Manager selects an appropriate authentication scheme from the
 
227
 * display's list of supported ones and sends Willing/Unwilling.
 
228
 *
 
229
 * Assuming the display accepts the auth. scheme it sends back a
 
230
 * Request.
 
231
 *
 
232
 * If the manager accepts to service the display (i.e. loadavg is low)
 
233
 * it sends back an Accept containing a unique SessionID. The
 
234
 * SessionID is stored in an accept queue by the Manager. Should the
 
235
 * manager refuse to start a session a Decline is sent to the display.
 
236
 *
 
237
 * The display returns a Manage request containing the supplied
 
238
 * SessionID. The manager will then start a session on the display. In
 
239
 * case the SessionID is not on the accept queue the manager returns
 
240
 * Refuse. If the manager fails to open the display for connections
 
241
 * Failed is returned.
 
242
 *
 
243
 * During the session the display periodically sends KeepAlive packets
 
244
 * to the manager. The manager responds with Alive.
 
245
 *
 
246
 * Similarly the manager xpings the display once in a while and shuts
 
247
 * down the connection on failure.
 
248
 *
 
249
 */
 
250
 
 
251
GQuark
 
252
gdm_xdmcp_display_factory_error_quark (void)
 
253
{
 
254
        static GQuark ret = 0;
 
255
        if (ret == 0) {
 
256
                ret = g_quark_from_static_string ("gdm_xdmcp_display_factory_error");
 
257
        }
 
258
 
 
259
        return ret;
 
260
}
 
261
 
 
262
static gint32
 
263
get_next_session_serial (GdmXdmcpDisplayFactory *factory)
 
264
{
 
265
        gint32 serial;
 
266
 
 
267
 again:
 
268
        if (factory->priv->session_serial != G_MAXINT32) {
 
269
                serial = factory->priv->session_serial++;
 
270
        } else {
 
271
                serial = g_random_int ();
 
272
        }
 
273
 
 
274
        if (serial == 0) {
 
275
                goto again;
 
276
        }
 
277
 
 
278
        return serial;
 
279
}
 
280
 
 
281
/* for debugging */
 
282
static const char *
 
283
ai_family_str (struct addrinfo *ai)
 
284
{
 
285
        const char *str;
 
286
        switch (ai->ai_family) {
 
287
        case AF_INET:
 
288
                str = "inet";
 
289
                break;
 
290
        case AF_INET6:
 
291
                str = "inet6";
 
292
                break;
 
293
        case AF_UNIX:
 
294
                str = "unix";
 
295
                break;
 
296
        case AF_UNSPEC:
 
297
                str = "unspecified";
 
298
                break;
 
299
        default:
 
300
                str = "unknown";
 
301
                break;
 
302
        }
 
303
        return str;
 
304
}
 
305
 
 
306
/* for debugging */
 
307
static const char *
 
308
ai_type_str (struct addrinfo *ai)
 
309
{
 
310
        const char *str;
 
311
        switch (ai->ai_socktype) {
 
312
        case SOCK_STREAM:
 
313
                str = "stream";
 
314
                break;
 
315
        case SOCK_DGRAM:
 
316
                str = "datagram";
 
317
                break;
 
318
        case SOCK_SEQPACKET:
 
319
                str = "seqpacket";
 
320
                break;
 
321
        case SOCK_RAW:
 
322
                str = "raw";
 
323
                break;
 
324
        default:
 
325
                str = "unknown";
 
326
                break;
 
327
        }
 
328
        return str;
 
329
}
 
330
 
 
331
/* for debugging */
 
332
static const char *
 
333
ai_protocol_str (struct addrinfo *ai)
 
334
{
 
335
        const char *str;
 
336
        switch (ai->ai_protocol) {
 
337
        case 0:
 
338
                str = "default";
 
339
                break;
 
340
        case IPPROTO_TCP:
 
341
                str = "TCP";
 
342
                break;
 
343
        case IPPROTO_UDP:
 
344
                str = "UDP";
 
345
                break;
 
346
        case IPPROTO_RAW:
 
347
                str = "raw";
 
348
                break;
 
349
        default:
 
350
                str = "unknown";
 
351
                break;
 
352
        }
 
353
 
 
354
        return str;
 
355
}
 
356
 
 
357
/* for debugging */
 
358
static char *
 
359
ai_flags_str (struct addrinfo *ai)
 
360
{
 
361
        GString *str;
 
362
 
 
363
        str = g_string_new ("");
 
364
        if (ai->ai_flags == 0) {
 
365
                g_string_append (str, "none");
 
366
        } else {
 
367
                if (ai->ai_flags & AI_PASSIVE) {
 
368
                        g_string_append (str, "passive ");
 
369
                }
 
370
                if (ai->ai_flags & AI_CANONNAME) {
 
371
                        g_string_append (str, "canon ");
 
372
                }
 
373
                if (ai->ai_flags & AI_NUMERICHOST) {
 
374
                        g_string_append (str, "numhost ");
 
375
                }
 
376
                if (ai->ai_flags & AI_NUMERICSERV) {
 
377
                        g_string_append (str, "numserv ");
 
378
                }
 
379
                if (ai->ai_flags & AI_V4MAPPED) {
 
380
                        g_string_append (str, "v4mapped ");
 
381
                }
 
382
                if (ai->ai_flags & AI_ALL) {
 
383
                        g_string_append (str, "all ");
 
384
                }
 
385
        }
 
386
        return g_string_free (str, FALSE);
 
387
}
 
388
 
 
389
/* for debugging */
 
390
static void
 
391
debug_addrinfo (struct addrinfo *ai)
 
392
{
 
393
        char *str;
 
394
        str = ai_flags_str (ai);
 
395
        g_debug ("GdmXdmcpDisplayFactory: addrinfo family=%s type=%s proto=%s flags=%s",
 
396
                 ai_family_str (ai),
 
397
                 ai_type_str (ai),
 
398
                 ai_protocol_str (ai),
 
399
                 str);
 
400
        g_free (str);
 
401
}
 
402
 
 
403
static int
 
404
create_socket (struct addrinfo *ai)
 
405
{
 
406
        int sock;
 
407
 
 
408
        sock = socket (ai->ai_family, ai->ai_socktype, ai->ai_protocol);
 
409
        if (sock < 0) {
 
410
                g_warning ("socket: %s", g_strerror (errno));
 
411
                return sock;
 
412
        }
 
413
 
 
414
        if (bind (sock, ai->ai_addr, ai->ai_addrlen) < 0) {
 
415
                g_warning ("bind: %s", g_strerror (errno));
 
416
                close (sock);
 
417
                return -1;
 
418
        }
 
419
 
 
420
        return sock;
 
421
}
 
422
 
 
423
static int
 
424
do_bind (guint                     port,
 
425
         int                       family,
 
426
         struct sockaddr_storage * hostaddr)
 
427
{
 
428
        struct addrinfo  hints;
 
429
        struct addrinfo *ai_list;
 
430
        struct addrinfo *ai;
 
431
        char             strport[NI_MAXSERV];
 
432
        int              gaierr;
 
433
        int              sock;
 
434
 
 
435
        sock = -1;
 
436
 
 
437
        memset (&hints, 0, sizeof (hints));
 
438
        hints.ai_family = family;
 
439
        hints.ai_socktype = SOCK_DGRAM;
 
440
        hints.ai_flags = AI_PASSIVE;
 
441
 
 
442
        snprintf (strport, sizeof (strport), "%u", port);
 
443
 
 
444
        ai_list = NULL;
 
445
        if ((gaierr = getaddrinfo (NULL, strport, &hints, &ai_list)) != 0) {
 
446
                g_error ("Unable to connect to socket: %s", gai_strerror (gaierr));
 
447
        }
 
448
 
 
449
        /* should only be one but.. */
 
450
        for (ai = ai_list; ai != NULL; ai = ai->ai_next) {
 
451
                if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) {
 
452
                        continue;
 
453
                }
 
454
 
 
455
                debug_addrinfo (ai);
 
456
 
 
457
                if (sock < 0) {
 
458
                        char       *host;
 
459
                        char       *serv;
 
460
                        GdmAddress *addr;
 
461
 
 
462
                        addr = gdm_address_new_from_sockaddr (ai->ai_addr, ai->ai_addrlen);
 
463
 
 
464
                        host = NULL;
 
465
                        serv = NULL;
 
466
                        gdm_address_get_numeric_info (addr, &host, &serv);
 
467
                        g_debug ("GdmXdmcpDisplayFactory: Attempting to bind to host %s port %s",
 
468
                                host ? host : "(null)", serv ? serv : "(null)");
 
469
                        g_free (host);
 
470
                        g_free (serv);
 
471
                        gdm_address_free (addr);
 
472
 
 
473
                        sock = create_socket (ai);
 
474
                        if (sock >= 0) {
 
475
                                if (hostaddr != NULL) {
 
476
                                        memcpy (hostaddr, ai->ai_addr, ai->ai_addrlen);
 
477
                                }
 
478
                        }
 
479
                }
 
480
        }
 
481
 
 
482
        freeaddrinfo (ai_list);
 
483
 
 
484
        return sock;
 
485
}
 
486
 
 
487
static void
 
488
setup_multicast (GdmXdmcpDisplayFactory *factory)
 
489
{
 
490
#ifdef ENABLE_IPV6
 
491
        /* Checking and Setting Multicast options */
 
492
        {
 
493
                /*
 
494
                 * socktemp is a temporary socket for getting info about
 
495
                 * available interfaces
 
496
                 */
 
497
                int              socktemp;
 
498
                int              i;
 
499
                int              num;
 
500
                char            *buf;
 
501
                struct ipv6_mreq mreq;
 
502
 
 
503
                /* For interfaces' list */
 
504
                struct ifconf    ifc;
 
505
                struct ifreq    *ifr;
 
506
 
 
507
                socktemp = socket (AF_INET, SOCK_DGRAM, 0);
 
508
#ifdef SIOCGIFNUM
 
509
                if (ioctl (socktemp, SIOCGIFNUM, &num) < 0) {
 
510
                        num = 64;
 
511
                }
 
512
#else
 
513
                num = 64;
 
514
#endif /* SIOCGIFNUM */
 
515
                ifc.ifc_len = sizeof (struct ifreq) * num;
 
516
                ifc.ifc_buf = buf = malloc (ifc.ifc_len);
 
517
 
 
518
                if (ioctl (socktemp, SIOCGIFCONF, &ifc) >= 0) {
 
519
                        ifr = ifc.ifc_req;
 
520
                        num = ifc.ifc_len / sizeof (struct ifreq); /* No of interfaces */
 
521
 
 
522
                        /* Joining multicast group with all interfaces */
 
523
                        for (i = 0 ; i < num ; i++) {
 
524
                                struct ifreq ifreq;
 
525
                                int          ifindex;
 
526
 
 
527
                                memset (&ifreq, 0, sizeof (ifreq));
 
528
                                strncpy (ifreq.ifr_name, ifr[i].ifr_name, sizeof (ifreq.ifr_name));
 
529
                                /* paranoia */
 
530
                                ifreq.ifr_name[sizeof (ifreq.ifr_name) - 1] = '\0';
 
531
 
 
532
                                if (ioctl (socktemp, SIOCGIFFLAGS, &ifreq) < 0) {
 
533
                                        g_debug ("GdmXdmcpDisplayFactory: Could not get SIOCGIFFLAGS for %s",
 
534
                                                 ifr[i].ifr_name);
 
535
                                }
 
536
 
 
537
                                ifindex = if_nametoindex (ifr[i].ifr_name);
 
538
 
 
539
                                if ((!(ifreq.ifr_flags & IFF_UP) ||
 
540
                                     (ifreq.ifr_flags & IFF_LOOPBACK)) ||
 
541
                                    ((ifindex == 0 ) && (errno == ENXIO))) {
 
542
                                        /* Not a valid interface or loopback interface*/
 
543
                                        continue;
 
544
                                }
 
545
 
 
546
                                mreq.ipv6mr_interface = ifindex;
 
547
                                inet_pton (AF_INET6,
 
548
                                           factory->priv->multicast_address,
 
549
                                           &mreq.ipv6mr_multiaddr);
 
550
 
 
551
                                setsockopt (factory->priv->socket_fd,
 
552
                                            IPPROTO_IPV6,
 
553
                                            IPV6_JOIN_GROUP,
 
554
                                            &mreq,
 
555
                                            sizeof (mreq));
 
556
                        }
 
557
                }
 
558
                g_free (buf);
 
559
                close (socktemp);
 
560
        }
 
561
#endif /* ENABLE_IPV6 */
 
562
}
 
563
 
 
564
static void
 
565
fd_set_close_on_exec (int fd)
 
566
{
 
567
        int flags;
 
568
 
 
569
        flags = fcntl (fd, F_GETFD, 0);
 
570
        if (flags < 0) {
 
571
                return;
 
572
        }
 
573
 
 
574
        flags |= FD_CLOEXEC;
 
575
 
 
576
        fcntl (fd, F_SETFD, flags);
 
577
}
 
578
 
 
579
static gboolean
 
580
open_port (GdmXdmcpDisplayFactory *factory)
 
581
{
 
582
        struct sockaddr_storage serv_sa = { 0 };
 
583
 
 
584
        g_debug ("GdmXdmcpDisplayFactory: Start up on host %s, port %d",
 
585
                 factory->priv->hostname ? factory->priv->hostname : "(null)",
 
586
                 factory->priv->port);
 
587
 
 
588
        /* Open socket for communications */
 
589
#ifdef ENABLE_IPV6
 
590
        factory->priv->socket_fd = do_bind (factory->priv->port, AF_INET6, &serv_sa);
 
591
        if (factory->priv->socket_fd < 0)
 
592
#endif
 
593
                factory->priv->socket_fd = do_bind (factory->priv->port, AF_INET, &serv_sa);
 
594
 
 
595
        if G_UNLIKELY (factory->priv->socket_fd < 0) {
 
596
                g_warning (_("Could not create socket!"));
 
597
                return FALSE;
 
598
        }
 
599
 
 
600
        fd_set_close_on_exec (factory->priv->socket_fd);
 
601
 
 
602
        if (factory->priv->use_multicast) {
 
603
                setup_multicast (factory);
 
604
        }
 
605
 
 
606
        return TRUE;
 
607
}
 
608
 
 
609
#ifdef HAVE_TCPWRAPPERS
 
610
 
 
611
        /*
 
612
         * Avoids a warning, my tcpd.h file doesn't include this prototype, even
 
613
         * though the library does include the function and the manpage mentions it
 
614
         */
 
615
        extern int hosts_ctl (char *daemon,
 
616
                              char *client_name,
 
617
                              char *client_addr,
 
618
                              char *client_user);
 
619
#endif
 
620
 
 
621
static gboolean
 
622
gdm_xdmcp_host_allow (GdmAddress *address)
 
623
{
 
624
#ifdef HAVE_TCPWRAPPERS
 
625
        char       *client;
 
626
        char       *host;
 
627
        gboolean    ret;
 
628
 
 
629
        host = NULL;
 
630
        client = NULL;
 
631
 
 
632
        /* Find client hostname */
 
633
        gdm_address_get_hostname (address, &client);
 
634
        gdm_address_get_numeric_info (address, &host, NULL);
 
635
 
 
636
        /* Check with tcp_wrappers if client is allowed to access */
 
637
        ret = hosts_ctl ("gdm", client, host, "");
 
638
 
 
639
        g_free (host);
 
640
        g_free (client);
 
641
 
 
642
        return ret;
 
643
#else /* HAVE_TCPWRAPPERS */
 
644
        return (TRUE);
 
645
#endif /* HAVE_TCPWRAPPERS */
 
646
}
 
647
 
 
648
typedef struct {
 
649
        GdmAddress *address;
 
650
        int         count;
 
651
} CountDisplayData;
 
652
 
 
653
static gboolean
 
654
count_displays_from_host (const char       *id,
 
655
                          GdmDisplay       *display,
 
656
                          CountDisplayData *data)
 
657
{
 
658
        GdmAddress *address;
 
659
 
 
660
        if (GDM_IS_XDMCP_DISPLAY (display)) {
 
661
                address = gdm_xdmcp_display_get_remote_address (GDM_XDMCP_DISPLAY (display));
 
662
 
 
663
                if (gdm_address_equal (address, data->address)) {
 
664
                        data->count++;
 
665
                }
 
666
        }
 
667
 
 
668
        return TRUE;
 
669
}
 
670
 
 
671
static int
 
672
gdm_xdmcp_num_displays_from_host (GdmXdmcpDisplayFactory *factory,
 
673
                                  GdmAddress             *address)
 
674
{
 
675
        CountDisplayData data;
 
676
        GdmDisplayStore *store;
 
677
 
 
678
        data.count = 0;
 
679
        data.address = address;
 
680
 
 
681
        store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
 
682
        gdm_display_store_foreach (store,
 
683
                                   (GdmDisplayStoreFunc)count_displays_from_host,
 
684
                                   &data);
 
685
 
 
686
        return data.count;
 
687
}
 
688
 
 
689
typedef struct {
 
690
        GdmAddress *address;
 
691
        int         display_num;
 
692
} LookupHostData;
 
693
 
 
694
static gboolean
 
695
lookup_by_host (const char     *id,
 
696
                GdmDisplay     *display,
 
697
                LookupHostData *data)
 
698
{
 
699
        GdmAddress *this_address;
 
700
        int         disp_num;
 
701
 
 
702
        if (! GDM_IS_XDMCP_DISPLAY (display)) {
 
703
                return FALSE;
 
704
        }
 
705
 
 
706
        this_address = gdm_xdmcp_display_get_remote_address (GDM_XDMCP_DISPLAY (display));
 
707
        gdm_display_get_x11_display_number (display, &disp_num, NULL);
 
708
 
 
709
        if (gdm_address_equal (this_address, data->address)
 
710
            && disp_num == data->display_num) {
 
711
                return TRUE;
 
712
        }
 
713
 
 
714
        return FALSE;
 
715
}
 
716
 
 
717
static GdmDisplay *
 
718
gdm_xdmcp_display_lookup_by_host (GdmXdmcpDisplayFactory *factory,
 
719
                                  GdmAddress             *address,
 
720
                                  int                     display_num)
 
721
{
 
722
        GdmDisplay      *display;
 
723
        LookupHostData  *data;
 
724
        GdmDisplayStore *store;
 
725
 
 
726
        data = g_new0 (LookupHostData, 1);
 
727
        data->address = address;
 
728
        data->display_num = display_num;
 
729
 
 
730
        store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
 
731
        display = gdm_display_store_find (store,
 
732
                                          (GdmDisplayStoreFunc)lookup_by_host,
 
733
                                          data);
 
734
        g_free (data);
 
735
 
 
736
        return display;
 
737
}
 
738
 
 
739
static char *
 
740
get_willing_output (GdmXdmcpDisplayFactory *factory)
 
741
{
 
742
        char  *output;
 
743
        char **argv;
 
744
        FILE  *fd;
 
745
        char   buf[256];
 
746
 
 
747
        output = NULL;
 
748
        buf[0] = '\0';
 
749
 
 
750
        if (factory->priv->willing_script == NULL) {
 
751
                goto out;
 
752
        }
 
753
 
 
754
        argv = NULL;
 
755
        if (! g_shell_parse_argv (factory->priv->willing_script, NULL, &argv, NULL)) {
 
756
                goto out;
 
757
        }
 
758
 
 
759
        if (argv == NULL ||
 
760
            argv[0] == NULL ||
 
761
            g_access (argv[0], X_OK) != 0) {
 
762
                goto out;
 
763
        }
 
764
 
 
765
        fd = popen (factory->priv->willing_script, "r");
 
766
        if (fd == NULL) {
 
767
                goto out;
 
768
        }
 
769
 
 
770
        if (fgets (buf, sizeof (buf), fd) == NULL) {
 
771
                pclose (fd);
 
772
                goto out;
 
773
        }
 
774
 
 
775
        pclose (fd);
 
776
 
 
777
        output = g_strdup (buf);
 
778
 
 
779
 out:
 
780
        return output;
 
781
}
 
782
 
 
783
static void
 
784
gdm_xdmcp_send_willing (GdmXdmcpDisplayFactory *factory,
 
785
                        GdmAddress             *address)
 
786
{
 
787
        ARRAY8        status;
 
788
        XdmcpHeader   header;
 
789
        static char  *last_status = NULL;
 
790
        static time_t last_willing = 0;
 
791
        char         *host;
 
792
 
 
793
        host = NULL;
 
794
        gdm_address_get_numeric_info (address, &host, NULL);
 
795
        g_debug ("GdmXdmcpDisplayFactory: Sending WILLING to %s",
 
796
                host ? host : "(null)");
 
797
        g_free (host);
 
798
 
 
799
        if (last_willing == 0 || time (NULL) - 3 > last_willing) {
 
800
                char *s;
 
801
 
 
802
                g_free (last_status);
 
803
 
 
804
                s = get_willing_output (factory);
 
805
                if (s != NULL) {
 
806
                        last_status = s;
 
807
                } else {
 
808
                        last_status = g_strdup (factory->priv->sysid);
 
809
                }
 
810
        }
 
811
 
 
812
        if (! gdm_address_is_local (address) &&
 
813
            gdm_xdmcp_num_displays_from_host (factory, address) >= factory->priv->max_displays_per_host) {
 
814
                /*
 
815
                 * Don't translate, this goes over the wire to servers where we
 
816
                 * don't know the charset or language, so it must be ascii
 
817
                 */
 
818
                status.data = (CARD8 *) g_strdup_printf ("%s (Server is busy)",
 
819
                                                         last_status);
 
820
        } else {
 
821
                status.data = (CARD8 *) g_strdup (last_status);
 
822
        }
 
823
 
 
824
        status.length = strlen ((char *) status.data);
 
825
 
 
826
        header.opcode   = (CARD16) WILLING;
 
827
        header.length   = 6 + serv_authlist.authentication.length;
 
828
        header.length  += factory->priv->servhost.length + status.length;
 
829
        header.version  = XDM_PROTOCOL_VERSION;
 
830
        XdmcpWriteHeader (&factory->priv->buf, &header);
 
831
 
 
832
        /* Hardcoded authentication */
 
833
        XdmcpWriteARRAY8 (&factory->priv->buf, &serv_authlist.authentication);
 
834
        XdmcpWriteARRAY8 (&factory->priv->buf, &factory->priv->servhost);
 
835
        XdmcpWriteARRAY8 (&factory->priv->buf, &status);
 
836
 
 
837
        XdmcpFlush (factory->priv->socket_fd,
 
838
                    &factory->priv->buf,
 
839
                    (XdmcpNetaddr)gdm_address_peek_sockaddr_storage (address),
 
840
                    (int)gdm_sockaddr_len (gdm_address_peek_sockaddr_storage (address)));
 
841
 
 
842
        g_free (status.data);
 
843
}
 
844
 
 
845
static void
 
846
gdm_xdmcp_send_unwilling (GdmXdmcpDisplayFactory *factory,
 
847
                          GdmAddress             *address,
 
848
                          int                     type)
 
849
{
 
850
        ARRAY8        status;
 
851
        XdmcpHeader   header;
 
852
        static time_t last_time = 0;
 
853
        char         *host;
 
854
 
 
855
        /* only send at most one packet per second,
 
856
           no harm done if we don't send it at all */
 
857
        if (last_time + 1 >= time (NULL)) {
 
858
                return;
 
859
        }
 
860
 
 
861
        host = NULL;
 
862
        gdm_address_get_numeric_info (address, &host, NULL);
 
863
        g_debug ("GdmXdmcpDisplayFactory: Sending UNWILLING to %s",
 
864
                 host ? host : "(null)");
 
865
        g_warning (_("Denied XDMCP query from host %s"),
 
866
                 host ? host : "(null)");
 
867
        g_free (host);
 
868
 
 
869
        /*
 
870
         * Don't translate, this goes over the wire to servers where we
 
871
         * don't know the charset or language, so it must be ascii
 
872
         */
 
873
        status.data = (CARD8 *) "Display not authorized to connect";
 
874
        status.length = strlen ((char *) status.data);
 
875
 
 
876
        header.opcode = (CARD16) UNWILLING;
 
877
        header.length = 4 + factory->priv->servhost.length + status.length;
 
878
        header.version = XDM_PROTOCOL_VERSION;
 
879
        XdmcpWriteHeader (&factory->priv->buf, &header);
 
880
 
 
881
        XdmcpWriteARRAY8 (&factory->priv->buf, &factory->priv->servhost);
 
882
        XdmcpWriteARRAY8 (&factory->priv->buf, &status);
 
883
        XdmcpFlush (factory->priv->socket_fd,
 
884
                    &factory->priv->buf,
 
885
                    (XdmcpNetaddr)gdm_address_peek_sockaddr_storage (address),
 
886
                    (int)gdm_sockaddr_len (gdm_address_peek_sockaddr_storage (address)));
 
887
 
 
888
        last_time = time (NULL);
 
889
}
 
890
 
 
891
#define SIN(__s)   ((struct sockaddr_in *) __s)
 
892
#define SIN6(__s)  ((struct sockaddr_in6 *) __s)
 
893
 
 
894
static void
 
895
set_port_for_request (GdmAddress *address,
 
896
                      ARRAY8     *port)
 
897
{
 
898
        struct sockaddr_storage *ss;
 
899
 
 
900
        ss = gdm_address_peek_sockaddr_storage (address);
 
901
 
 
902
        /* we depend on this being 2 elsewhere as well */
 
903
        port->length = 2;
 
904
 
 
905
        switch (ss->ss_family) {
 
906
        case AF_INET:
 
907
                port->data = (CARD8 *)g_memdup (&(SIN (ss)->sin_port), port->length);
 
908
                break;
 
909
        case AF_INET6:
 
910
                port->data = (CARD8 *)g_memdup (&(SIN6 (ss)->sin6_port), port->length);
 
911
                break;
 
912
        default:
 
913
                port->data = NULL;
 
914
                break;
 
915
        }
 
916
}
 
917
 
 
918
static void
 
919
set_address_for_request (GdmAddress *address,
 
920
                         ARRAY8     *addr)
 
921
{
 
922
        struct sockaddr_storage *ss;
 
923
 
 
924
        ss = gdm_address_peek_sockaddr_storage (address);
 
925
 
 
926
        switch (ss->ss_family) {
 
927
        case AF_INET:
 
928
                addr->length = sizeof (struct in_addr);
 
929
                addr->data = g_memdup (&SIN (ss)->sin_addr, addr->length);
 
930
                break;
 
931
        case AF_INET6:
 
932
                addr->length = sizeof (struct in6_addr);
 
933
                addr->data = g_memdup (&SIN6 (ss)->sin6_addr, addr->length);
 
934
                break;
 
935
        default:
 
936
                addr->length = 0;
 
937
                addr->data = NULL;
 
938
                break;
 
939
        }
 
940
 
 
941
}
 
942
 
 
943
static void
 
944
gdm_xdmcp_send_forward_query (GdmXdmcpDisplayFactory  *factory,
 
945
                              IndirectClient          *ic,
 
946
                              GdmAddress              *address,
 
947
                              GdmAddress              *display_address,
 
948
                              ARRAYofARRAY8Ptr         authlist)
 
949
{
 
950
        XdmcpHeader              header;
 
951
        int                      i;
 
952
        ARRAY8                   addr;
 
953
        ARRAY8                   port;
 
954
        char                    *host;
 
955
        char                    *serv;
 
956
 
 
957
        g_assert (ic != NULL);
 
958
        g_assert (ic->chosen_address != NULL);
 
959
 
 
960
        host = NULL;
 
961
        gdm_address_get_numeric_info (ic->chosen_address, &host, NULL);
 
962
        g_debug ("GdmXdmcpDisplayFactory: Sending forward query to %s",
 
963
                   host ? host : "(null)");
 
964
        g_free (host);
 
965
 
 
966
        host = NULL;
 
967
        serv = NULL;
 
968
        gdm_address_get_numeric_info (display_address, &host, &serv);
 
969
        g_debug ("GdmXdmcpDisplayFactory: Query contains %s:%s",
 
970
                 host ? host : "(null)", serv ? serv : "(null)");
 
971
        g_free (host);
 
972
        g_free (serv);
 
973
 
 
974
        set_port_for_request (address, &port);
 
975
        set_address_for_request (display_address, &addr);
 
976
 
 
977
        header.version = XDM_PROTOCOL_VERSION;
 
978
        header.opcode = (CARD16) FORWARD_QUERY;
 
979
        header.length = 0;
 
980
        header.length += 2 + addr.length;
 
981
        header.length += 2 + port.length;
 
982
        header.length += 1;
 
983
        for (i = 0; i < authlist->length; i++) {
 
984
                header.length += 2 + authlist->data[i].length;
 
985
        }
 
986
 
 
987
        XdmcpWriteHeader (&factory->priv->buf, &header);
 
988
        XdmcpWriteARRAY8 (&factory->priv->buf, &addr);
 
989
        XdmcpWriteARRAY8 (&factory->priv->buf, &port);
 
990
        XdmcpWriteARRAYofARRAY8 (&factory->priv->buf, authlist);
 
991
 
 
992
        XdmcpFlush (factory->priv->socket_fd,
 
993
                    &factory->priv->buf,
 
994
                    (XdmcpNetaddr)gdm_address_peek_sockaddr_storage (ic->chosen_address),
 
995
                    (int)gdm_sockaddr_len (gdm_address_peek_sockaddr_storage (ic->chosen_address)));
 
996
 
 
997
        g_free (port.data);
 
998
        g_free (addr.data);
 
999
}
 
1000
 
 
1001
static void
 
1002
handle_any_query (GdmXdmcpDisplayFactory  *factory,
 
1003
                  GdmAddress              *address,
 
1004
                  ARRAYofARRAY8Ptr         authentication_names,
 
1005
                  int                      type)
 
1006
{
 
1007
        gdm_xdmcp_send_willing (factory, address);
 
1008
}
 
1009
 
 
1010
static void
 
1011
handle_direct_query (GdmXdmcpDisplayFactory  *factory,
 
1012
                     GdmAddress              *address,
 
1013
                     int                      len,
 
1014
                     int                      type)
 
1015
{
 
1016
        ARRAYofARRAY8 clnt_authlist;
 
1017
        int           expected_len;
 
1018
        int           i;
 
1019
        int           res;
 
1020
 
 
1021
        res = XdmcpReadARRAYofARRAY8 (&factory->priv->buf, &clnt_authlist);
 
1022
        if G_UNLIKELY (! res) {
 
1023
                g_warning (_("Could not extract authlist from packet"));
 
1024
                return;
 
1025
        }
 
1026
 
 
1027
        expected_len = 1;
 
1028
 
 
1029
        for (i = 0 ; i < clnt_authlist.length ; i++) {
 
1030
                expected_len += 2 + clnt_authlist.data[i].length;
 
1031
        }
 
1032
 
 
1033
        if (len == expected_len) {
 
1034
                handle_any_query (factory, address, &clnt_authlist, type);
 
1035
        } else {
 
1036
                g_warning (_("Error in checksum"));
 
1037
        }
 
1038
 
 
1039
        XdmcpDisposeARRAYofARRAY8 (&clnt_authlist);
 
1040
}
 
1041
 
 
1042
static void
 
1043
gdm_xdmcp_handle_broadcast_query (GdmXdmcpDisplayFactory *factory,
 
1044
                                  GdmAddress             *address,
 
1045
                                  int                     len)
 
1046
{
 
1047
        if (gdm_xdmcp_host_allow (address)) {
 
1048
                handle_direct_query (factory, address, len, BROADCAST_QUERY);
 
1049
        } else {
 
1050
                /* just ignore it */
 
1051
        }
 
1052
}
 
1053
 
 
1054
static void
 
1055
gdm_xdmcp_handle_query (GdmXdmcpDisplayFactory *factory,
 
1056
                        GdmAddress             *address,
 
1057
                        int                     len)
 
1058
{
 
1059
        if (gdm_xdmcp_host_allow (address)) {
 
1060
                handle_direct_query (factory, address, len, QUERY);
 
1061
        } else {
 
1062
                gdm_xdmcp_send_unwilling (factory, address, QUERY);
 
1063
        }
 
1064
}
 
1065
 
 
1066
static IndirectClient *
 
1067
indirect_client_create (GdmXdmcpDisplayFactory *factory,
 
1068
                        GdmAddress             *dsp_address)
 
1069
{
 
1070
        IndirectClient *ic;
 
1071
 
 
1072
        ic = g_new0 (IndirectClient, 1);
 
1073
        ic->dsp_address = gdm_address_copy (dsp_address);
 
1074
 
 
1075
        factory->priv->indirect_clients = g_slist_prepend (factory->priv->indirect_clients, ic);
 
1076
 
 
1077
        return ic;
 
1078
}
 
1079
 
 
1080
static void
 
1081
indirect_client_destroy (GdmXdmcpDisplayFactory *factory,
 
1082
                         IndirectClient         *ic)
 
1083
{
 
1084
        if (ic == NULL) {
 
1085
                return;
 
1086
        }
 
1087
 
 
1088
        factory->priv->indirect_clients = g_slist_remove (factory->priv->indirect_clients, ic);
 
1089
 
 
1090
        ic->acctime = 0;
 
1091
 
 
1092
        {
 
1093
                char *host;
 
1094
 
 
1095
                host = NULL;
 
1096
                gdm_address_get_numeric_info (ic->dsp_address, &host, NULL);
 
1097
                g_debug ("GdmXdmcpDisplayFactory: Disposing IndirectClient for %s",
 
1098
                        host ? host : "(null)");
 
1099
                g_free (host);
 
1100
        }
 
1101
 
 
1102
        g_free (ic->dsp_address);
 
1103
        ic->dsp_address = NULL;
 
1104
        g_free (ic->chosen_address);
 
1105
        ic->chosen_address = NULL;
 
1106
 
 
1107
        g_free (ic);
 
1108
}
 
1109
 
 
1110
static IndirectClient *
 
1111
indirect_client_lookup_by_chosen (GdmXdmcpDisplayFactory *factory,
 
1112
                                  GdmAddress             *chosen_address,
 
1113
                                  GdmAddress             *origin_address)
 
1114
{
 
1115
        GSList         *li;
 
1116
        char           *host;
 
1117
        IndirectClient *ret;
 
1118
 
 
1119
        g_assert (chosen_address != NULL);
 
1120
        g_assert (origin_address != NULL);
 
1121
 
 
1122
        ret = NULL;
 
1123
 
 
1124
        for (li = factory->priv->indirect_clients; li != NULL; li = li->next) {
 
1125
                IndirectClient *ic = li->data;
 
1126
 
 
1127
                if (ic != NULL
 
1128
                    && ic->chosen_address != NULL
 
1129
                    && gdm_address_equal (ic->chosen_address, chosen_address)) {
 
1130
                        if (gdm_address_equal (ic->dsp_address, origin_address)) {
 
1131
                                ret = ic;
 
1132
                                goto out;
 
1133
                        } else if (gdm_address_is_loopback (ic->dsp_address)
 
1134
                                   && gdm_address_is_local (origin_address)) {
 
1135
                                ret = ic;
 
1136
                                goto out;
 
1137
                        }
 
1138
                }
 
1139
        }
 
1140
 
 
1141
        gdm_address_get_numeric_info (chosen_address, &host, NULL);
 
1142
 
 
1143
        g_debug ("GdmXdmcpDisplayFactory: Chosen %s host not found",
 
1144
                 host ? host : "(null)");
 
1145
        g_free (host);
 
1146
 out:
 
1147
        return ret;
 
1148
}
 
1149
 
 
1150
/* lookup by origin */
 
1151
static IndirectClient *
 
1152
indirect_client_lookup (GdmXdmcpDisplayFactory *factory,
 
1153
                        GdmAddress             *address)
 
1154
{
 
1155
        GSList         *li;
 
1156
        GSList         *qlist;
 
1157
        IndirectClient *ret;
 
1158
        time_t          curtime;
 
1159
 
 
1160
        g_assert (address != NULL);
 
1161
 
 
1162
        curtime = time (NULL);
 
1163
        ret = NULL;
 
1164
 
 
1165
        qlist = g_slist_copy (factory->priv->indirect_clients);
 
1166
 
 
1167
        for (li = qlist; li != NULL; li = li->next) {
 
1168
                IndirectClient *ic;
 
1169
                char           *host;
 
1170
                char           *serv;
 
1171
 
 
1172
                ic = (IndirectClient *) li->data;
 
1173
 
 
1174
                if (ic == NULL) {
 
1175
                        continue;
 
1176
                }
 
1177
 
 
1178
                host = NULL;
 
1179
                serv = NULL;
 
1180
                gdm_address_get_numeric_info (ic->dsp_address, &host, &serv);
 
1181
 
 
1182
                g_debug ("GdmXdmcpDisplayFactory: comparing %s:%s",
 
1183
                        host ? host : "(null)", serv ? serv : "(null)");
 
1184
                if (gdm_address_equal (ic->dsp_address, address)) {
 
1185
                        ret = ic;
 
1186
                        g_free (host);
 
1187
                        g_free (serv);
 
1188
                        break;
 
1189
                }
 
1190
 
 
1191
                if (ic->acctime > 0 && curtime > ic->acctime + factory->priv->max_wait_indirect) {
 
1192
                        g_debug ("GdmXdmcpDisplayFactory: Disposing stale forward query from %s:%s",
 
1193
                                 host ? host : "(null)", serv ? serv : "(null)");
 
1194
 
 
1195
                        indirect_client_destroy (factory, ic);
 
1196
                }
 
1197
 
 
1198
                g_free (host);
 
1199
                g_free (serv);
 
1200
        }
 
1201
 
 
1202
        g_slist_free (qlist);
 
1203
 
 
1204
        if (ret == NULL) {
 
1205
                char *host;
 
1206
 
 
1207
                host = NULL;
 
1208
                gdm_address_get_numeric_info (address, &host, NULL);
 
1209
                g_debug ("GdmXdmcpDisplayFactory: Host %s not found",
 
1210
                         host ? host : "(null)");
 
1211
                g_free (host);
 
1212
        }
 
1213
 
 
1214
        return ret;
 
1215
}
 
1216
 
 
1217
static void
 
1218
gdm_xdmcp_handle_indirect_query (GdmXdmcpDisplayFactory *factory,
 
1219
                                 GdmAddress             *address,
 
1220
                                 int                     len)
 
1221
{
 
1222
        ARRAYofARRAY8    clnt_authlist;
 
1223
        int              expected_len;
 
1224
        int              i;
 
1225
        int              res;
 
1226
        IndirectClient  *ic;
 
1227
 
 
1228
        if (! gdm_xdmcp_host_allow (address)) {
 
1229
                /* ignore the request */
 
1230
                return;
 
1231
        }
 
1232
 
 
1233
        if (! factory->priv->honor_indirect) {
 
1234
                /* ignore it */
 
1235
                return;
 
1236
        }
 
1237
 
 
1238
        if (factory->priv->num_sessions > factory->priv->max_displays ||
 
1239
            (!gdm_address_is_local (address) &&
 
1240
             gdm_xdmcp_num_displays_from_host (factory, address) > factory->priv->max_displays_per_host)) {
 
1241
                g_debug ("GdmXdmcpDisplayFactory: reached maximum number of clients - ignoring indirect query");
 
1242
                return;
 
1243
        }
 
1244
 
 
1245
        res = XdmcpReadARRAYofARRAY8 (&factory->priv->buf, &clnt_authlist);
 
1246
        if G_UNLIKELY (! res) {
 
1247
                g_warning (_("Could not extract authlist from packet"));
 
1248
                return;
 
1249
        }
 
1250
 
 
1251
        expected_len = 1;
 
1252
 
 
1253
        for (i = 0 ; i < clnt_authlist.length ; i++) {
 
1254
                expected_len += 2 + clnt_authlist.data[i].length;
 
1255
        }
 
1256
 
 
1257
        /* Try to look up the display in
 
1258
         * the pending list. If found send a FORWARD_QUERY to the
 
1259
         * chosen manager. Otherwise alloc a new indirect display. */
 
1260
 
 
1261
        if (len != expected_len) {
 
1262
                g_warning (_("Error in checksum"));
 
1263
                goto out;
 
1264
        }
 
1265
 
 
1266
 
 
1267
        ic = indirect_client_lookup (factory, address);
 
1268
 
 
1269
        if (ic != NULL && ic->chosen_address != NULL) {
 
1270
                /* if user chose us, then just send willing */
 
1271
                if (gdm_address_is_local (ic->chosen_address)) {
 
1272
                        g_debug ("GdmXdmcpDisplayFactory: the chosen address is local - dropping indirect");
 
1273
 
 
1274
                        /* get rid of indirect, so that we don't get
 
1275
                         * the chooser */
 
1276
                        indirect_client_destroy (factory, ic);
 
1277
                        gdm_xdmcp_send_willing (factory, address);
 
1278
                } else if (gdm_address_is_loopback (address)) {
 
1279
                        /* woohoo! fun, I have no clue how to get
 
1280
                         * the correct ip, SO I just send forward
 
1281
                         * queries with all the different IPs */
 
1282
                        const GList *list = gdm_address_peek_local_list ();
 
1283
 
 
1284
                        g_debug ("GdmXdmcpDisplayFactory: the chosen address is a loopback");
 
1285
 
 
1286
                        while (list != NULL) {
 
1287
                                GdmAddress *saddr = list->data;
 
1288
 
 
1289
                                if (! gdm_address_is_loopback (saddr)) {
 
1290
                                        /* forward query to * chosen host */
 
1291
                                        gdm_xdmcp_send_forward_query (factory,
 
1292
                                                                      ic,
 
1293
                                                                      address,
 
1294
                                                                      saddr,
 
1295
                                                                      &clnt_authlist);
 
1296
                                }
 
1297
 
 
1298
                                list = list->next;
 
1299
                        }
 
1300
                } else {
 
1301
                        /* or send forward query to chosen host */
 
1302
                        gdm_xdmcp_send_forward_query (factory,
 
1303
                                                      ic,
 
1304
                                                      address,
 
1305
                                                      address,
 
1306
                                                      &clnt_authlist);
 
1307
                }
 
1308
        } else if (ic == NULL) {
 
1309
                ic = indirect_client_create (factory, address);
 
1310
                if (ic != NULL) {
 
1311
                        gdm_xdmcp_send_willing (factory, address);
 
1312
                }
 
1313
        } else  {
 
1314
                gdm_xdmcp_send_willing (factory, address);
 
1315
        }
 
1316
 
 
1317
out:
 
1318
        XdmcpDisposeARRAYofARRAY8 (&clnt_authlist);
 
1319
}
 
1320
 
 
1321
static void
 
1322
forward_query_destroy (GdmXdmcpDisplayFactory *factory,
 
1323
                       ForwardQuery           *q)
 
1324
{
 
1325
        if (q == NULL) {
 
1326
                return;
 
1327
        }
 
1328
 
 
1329
        factory->priv->forward_queries = g_slist_remove (factory->priv->forward_queries, q);
 
1330
 
 
1331
        q->acctime = 0;
 
1332
 
 
1333
        {
 
1334
                char *host;
 
1335
 
 
1336
                host = NULL;
 
1337
                gdm_address_get_numeric_info (q->dsp_address, &host, NULL);
 
1338
                g_debug ("GdmXdmcpDisplayFactory: Disposing %s",
 
1339
                        host ? host : "(null)");
 
1340
                g_free (host);
 
1341
        }
 
1342
 
 
1343
        g_free (q->dsp_address);
 
1344
        q->dsp_address = NULL;
 
1345
        g_free (q->from_address);
 
1346
        q->from_address = NULL;
 
1347
 
 
1348
        g_free (q);
 
1349
}
 
1350
 
 
1351
static gboolean
 
1352
remove_oldest_forward (GdmXdmcpDisplayFactory *factory)
 
1353
{
 
1354
        GSList       *li;
 
1355
        ForwardQuery *oldest = NULL;
 
1356
 
 
1357
        for (li = factory->priv->forward_queries; li != NULL; li = li->next) {
 
1358
                ForwardQuery *query = li->data;
 
1359
 
 
1360
                if (oldest == NULL || query->acctime < oldest->acctime) {
 
1361
                        oldest = query;
 
1362
                }
 
1363
        }
 
1364
 
 
1365
        if (oldest != NULL) {
 
1366
                forward_query_destroy (factory, oldest);
 
1367
                return TRUE;
 
1368
        } else {
 
1369
                return FALSE;
 
1370
        }
 
1371
}
 
1372
 
 
1373
static ForwardQuery *
 
1374
forward_query_create (GdmXdmcpDisplayFactory *factory,
 
1375
                         GdmAddress             *mgr_address,
 
1376
                         GdmAddress             *dsp_address)
 
1377
{
 
1378
        ForwardQuery *q;
 
1379
        int           count;
 
1380
 
 
1381
        count = g_slist_length (factory->priv->forward_queries);
 
1382
 
 
1383
        while (count > GDM_MAX_FORWARD_QUERIES && remove_oldest_forward (factory)) {
 
1384
                count--;
 
1385
        }
 
1386
 
 
1387
        q = g_new0 (ForwardQuery, 1);
 
1388
        q->dsp_address = gdm_address_copy (dsp_address);
 
1389
        q->from_address = gdm_address_copy (mgr_address);
 
1390
 
 
1391
        factory->priv->forward_queries = g_slist_prepend (factory->priv->forward_queries, q);
 
1392
 
 
1393
        return q;
 
1394
}
 
1395
 
 
1396
static ForwardQuery *
 
1397
forward_query_lookup (GdmXdmcpDisplayFactory *factory,
 
1398
                          GdmAddress             *address)
 
1399
{
 
1400
        GSList       *li;
 
1401
        GSList       *qlist;
 
1402
        ForwardQuery *ret;
 
1403
        time_t        curtime;
 
1404
 
 
1405
        curtime = time (NULL);
 
1406
        ret = NULL;
 
1407
 
 
1408
        qlist = g_slist_copy (factory->priv->forward_queries);
 
1409
 
 
1410
        for (li = qlist; li != NULL; li = li->next) {
 
1411
                ForwardQuery *q;
 
1412
                char         *host;
 
1413
                char         *serv;
 
1414
 
 
1415
                q = (ForwardQuery *) li->data;
 
1416
 
 
1417
                if (q == NULL) {
 
1418
                        continue;
 
1419
                }
 
1420
 
 
1421
                host = NULL;
 
1422
                serv = NULL;
 
1423
                gdm_address_get_numeric_info (q->dsp_address, &host, &serv);
 
1424
 
 
1425
                g_debug ("GdmXdmcpDisplayFactory: comparing %s:%s",
 
1426
                        host ? host : "(null)", serv ? serv : "(null)");
 
1427
                if (gdm_address_equal (q->dsp_address, address)) {
 
1428
                        ret = q;
 
1429
                        g_free (host);
 
1430
                        g_free (serv);
 
1431
                        break;
 
1432
                }
 
1433
 
 
1434
                if (q->acctime > 0 &&  curtime > q->acctime + GDM_FORWARD_QUERY_TIMEOUT) {
 
1435
                        g_debug ("GdmXdmcpDisplayFactory: Disposing stale forward query from %s:%s",
 
1436
                                 host ? host : "(null)", serv ? serv : "(null)");
 
1437
 
 
1438
                        forward_query_destroy (factory, q);
 
1439
                }
 
1440
 
 
1441
                g_free (host);
 
1442
                g_free (serv);
 
1443
        }
 
1444
 
 
1445
        g_slist_free (qlist);
 
1446
 
 
1447
        if (ret == NULL) {
 
1448
                char *host;
 
1449
 
 
1450
                host = NULL;
 
1451
                gdm_address_get_numeric_info (address, &host, NULL);
 
1452
                g_debug ("GdmXdmcpDisplayFactory: Host %s not found",
 
1453
                         host ? host : "(null)");
 
1454
                g_free (host);
 
1455
        }
 
1456
 
 
1457
        return ret;
 
1458
}
 
1459
 
 
1460
static gboolean
 
1461
create_address_from_request (ARRAY8      *req_addr,
 
1462
                             ARRAY8      *req_port,
 
1463
                             int          family,
 
1464
                             GdmAddress **address)
 
1465
{
 
1466
        uint16_t         port;
 
1467
        char             host_buf [NI_MAXHOST];
 
1468
        char             serv_buf [NI_MAXSERV];
 
1469
        char            *serv;
 
1470
        const char      *host;
 
1471
        struct addrinfo  hints;
 
1472
        struct addrinfo *ai_list;
 
1473
        struct addrinfo *ai;
 
1474
        int              gaierr;
 
1475
        gboolean         found;
 
1476
 
 
1477
        if (address != NULL) {
 
1478
                *address = NULL;
 
1479
        }
 
1480
 
 
1481
        if (req_addr == NULL) {
 
1482
                return FALSE;
 
1483
        }
 
1484
 
 
1485
        serv = NULL;
 
1486
        if (req_port != NULL) {
 
1487
                /* port must always be length 2 */
 
1488
                if (req_port->length != 2) {
 
1489
                        return FALSE;
 
1490
                }
 
1491
 
 
1492
                memcpy (&port, req_port->data, 2);
 
1493
                snprintf (serv_buf, sizeof (serv_buf), "%d", ntohs (port));
 
1494
                serv = serv_buf;
 
1495
        } else {
 
1496
                /* assume XDM_UDP_PORT */
 
1497
                snprintf (serv_buf, sizeof (serv_buf), "%d", XDM_UDP_PORT);
 
1498
                serv = serv_buf;
 
1499
        }
 
1500
 
 
1501
        host = NULL;
 
1502
        if (req_addr->length == 4) {
 
1503
                host = inet_ntop (AF_INET,
 
1504
                                  (const void *)req_addr->data,
 
1505
                                  host_buf,
 
1506
                                  sizeof (host_buf));
 
1507
        } else if (req_addr->length == 16) {
 
1508
                host = inet_ntop (AF_INET6,
 
1509
                                  (const void *)req_addr->data,
 
1510
                                  host_buf,
 
1511
                                  sizeof (host_buf));
 
1512
        }
 
1513
 
 
1514
        if (host == NULL) {
 
1515
                g_warning (_("Bad address"));
 
1516
                return FALSE;
 
1517
        }
 
1518
 
 
1519
        memset (&hints, 0, sizeof (hints));
 
1520
        hints.ai_family = family;
 
1521
        /* this should convert IPv4 address to IPv6 if needed */
 
1522
        hints.ai_flags = AI_V4MAPPED;
 
1523
        hints.ai_socktype = SOCK_DGRAM;
 
1524
 
 
1525
        if ((gaierr = getaddrinfo (host, serv, &hints, &ai_list)) != 0) {
 
1526
                g_warning ("Unable to get address: %s", gai_strerror (gaierr));
 
1527
                return FALSE;
 
1528
        }
 
1529
 
 
1530
        /* just take the first one */
 
1531
        ai = ai_list;
 
1532
 
 
1533
        found = FALSE;
 
1534
        if (ai != NULL) {
 
1535
                found = TRUE;
 
1536
                if (address != NULL) {
 
1537
                        *address = gdm_address_new_from_sockaddr (ai->ai_addr, ai->ai_addrlen);
 
1538
                }
 
1539
        }
 
1540
 
 
1541
        freeaddrinfo (ai_list);
 
1542
 
 
1543
        return found;
 
1544
}
 
1545
 
 
1546
static void
 
1547
gdm_xdmcp_whack_queued_managed_forwards (GdmXdmcpDisplayFactory *factory,
 
1548
                                         GdmAddress             *address,
 
1549
                                         GdmAddress             *origin)
 
1550
{
 
1551
        GSList *li;
 
1552
 
 
1553
        for (li = factory->priv->managed_forwards; li != NULL; li = li->next) {
 
1554
                ManagedForward *mf = li->data;
 
1555
 
 
1556
                if (gdm_address_equal (mf->manager, address) &&
 
1557
                    gdm_address_equal (mf->origin, origin)) {
 
1558
                        factory->priv->managed_forwards = g_slist_remove_link (factory->priv->managed_forwards, li);
 
1559
                        g_slist_free_1 (li);
 
1560
                        g_source_remove (mf->handler);
 
1561
                        /* mf freed by glib */
 
1562
                        return;
 
1563
                }
 
1564
        }
 
1565
}
 
1566
 
 
1567
static void
 
1568
gdm_xdmcp_handle_forward_query (GdmXdmcpDisplayFactory *factory,
 
1569
                                GdmAddress             *address,
 
1570
                                int                     len)
 
1571
{
 
1572
        ARRAY8                   clnt_addr;
 
1573
        ARRAY8                   clnt_port;
 
1574
        ARRAYofARRAY8            clnt_authlist;
 
1575
        int                      i;
 
1576
        int                      explen;
 
1577
        GdmAddress              *disp_address;
 
1578
        char                    *host;
 
1579
        char                    *serv;
 
1580
 
 
1581
        disp_address = NULL;
 
1582
 
 
1583
        /* Check with tcp_wrappers if client is allowed to access */
 
1584
        if (! gdm_xdmcp_host_allow (address)) {
 
1585
                char *host2;
 
1586
 
 
1587
                host2 = NULL;
 
1588
                gdm_address_get_numeric_info (address, &host2, NULL);
 
1589
 
 
1590
                g_warning ("%s: Got FORWARD_QUERY from banned host %s",
 
1591
                           "gdm_xdmcp_handle_forward query",
 
1592
                           host2 ? host2 : "(null)");
 
1593
                g_free (host2);
 
1594
                return;
 
1595
        }
 
1596
 
 
1597
        /* Read display address */
 
1598
        if G_UNLIKELY (! XdmcpReadARRAY8 (&factory->priv->buf, &clnt_addr)) {
 
1599
                g_warning (_("%s: Could not read display address"),
 
1600
                           "gdm_xdmcp_handle_forward_query");
 
1601
                return;
 
1602
        }
 
1603
 
 
1604
        /* Read display port */
 
1605
        if G_UNLIKELY (! XdmcpReadARRAY8 (&factory->priv->buf, &clnt_port)) {
 
1606
                XdmcpDisposeARRAY8 (&clnt_addr);
 
1607
                g_warning (_("%s: Could not read display port number"),
 
1608
                           "gdm_xdmcp_handle_forward_query");
 
1609
                return;
 
1610
        }
 
1611
 
 
1612
        /* Extract array of authentication names from Xdmcp packet */
 
1613
        if G_UNLIKELY (! XdmcpReadARRAYofARRAY8 (&factory->priv->buf, &clnt_authlist)) {
 
1614
                XdmcpDisposeARRAY8 (&clnt_addr);
 
1615
                XdmcpDisposeARRAY8 (&clnt_port);
 
1616
                g_warning (_("%s: Could not extract authlist from packet"),
 
1617
                           "gdm_xdmcp_handle_forward_query");
 
1618
                return;
 
1619
        }
 
1620
 
 
1621
        /* Crude checksumming */
 
1622
        explen = 1;
 
1623
        explen += 2 + clnt_addr.length;
 
1624
        explen += 2 + clnt_port.length;
 
1625
 
 
1626
        for (i = 0 ; i < clnt_authlist.length ; i++) {
 
1627
                char *s = g_strndup ((char *) clnt_authlist.data[i].data,
 
1628
                                     clnt_authlist.length);
 
1629
                g_debug ("GdmXdmcpDisplayFactory: authlist: %s", s);
 
1630
                g_free (s);
 
1631
 
 
1632
                explen += 2 + clnt_authlist.data[i].length;
 
1633
        }
 
1634
 
 
1635
        if G_UNLIKELY (len != explen) {
 
1636
                g_warning (_("%s: Error in checksum"),
 
1637
                           "gdm_xdmcp_handle_forward_query");
 
1638
                goto out;
 
1639
        }
 
1640
 
 
1641
        if (! create_address_from_request (&clnt_addr, &clnt_port, gdm_address_get_family_type (address), &disp_address)) {
 
1642
                g_warning ("Unable to parse address for request");
 
1643
                goto out;
 
1644
        }
 
1645
 
 
1646
        gdm_xdmcp_whack_queued_managed_forwards (factory,
 
1647
                                                 address,
 
1648
                                                 disp_address);
 
1649
 
 
1650
        host = NULL;
 
1651
        serv = NULL;
 
1652
        gdm_address_get_numeric_info (disp_address, &host, &serv);
 
1653
        g_debug ("GdmXdmcpDisplayFactory: Got FORWARD_QUERY for display: %s, port %s",
 
1654
                 host ? host : "(null)", serv ? serv : "(null)");
 
1655
        g_free (host);
 
1656
        g_free (serv);
 
1657
 
 
1658
        /* Check with tcp_wrappers if display is allowed to access */
 
1659
        if (gdm_xdmcp_host_allow (disp_address)) {
 
1660
                ForwardQuery *q;
 
1661
 
 
1662
                q = forward_query_lookup (factory, disp_address);
 
1663
                if (q != NULL) {
 
1664
                        forward_query_destroy (factory, q);
 
1665
                }
 
1666
 
 
1667
                forward_query_create (factory, address, disp_address);
 
1668
 
 
1669
                gdm_xdmcp_send_willing (factory, disp_address);
 
1670
        }
 
1671
 
 
1672
 out:
 
1673
 
 
1674
        gdm_address_free (disp_address);
 
1675
 
 
1676
        XdmcpDisposeARRAYofARRAY8 (&clnt_authlist);
 
1677
        XdmcpDisposeARRAY8 (&clnt_port);
 
1678
        XdmcpDisposeARRAY8 (&clnt_addr);
 
1679
}
 
1680
 
 
1681
static void
 
1682
gdm_xdmcp_really_send_managed_forward (GdmXdmcpDisplayFactory *factory,
 
1683
                                       GdmAddress      *address,
 
1684
                                       GdmAddress      *origin)
 
1685
{
 
1686
        ARRAY8      addr;
 
1687
        XdmcpHeader header;
 
1688
        char       *host;
 
1689
 
 
1690
        host = NULL;
 
1691
        gdm_address_get_numeric_info (address, &host, NULL);
 
1692
        g_debug ("GdmXdmcpDisplayFactory: Sending MANAGED_FORWARD to %s",
 
1693
                host ? host : "(null)");
 
1694
        g_free (host);
 
1695
 
 
1696
        set_address_for_request (origin, &addr);
 
1697
 
 
1698
        header.opcode = (CARD16) GDM_XDMCP_MANAGED_FORWARD;
 
1699
        header.length = 4 + addr.length;
 
1700
        header.version = GDM_XDMCP_PROTOCOL_VERSION;
 
1701
        XdmcpWriteHeader (&factory->priv->buf, &header);
 
1702
 
 
1703
        XdmcpWriteARRAY8 (&factory->priv->buf, &addr);
 
1704
        XdmcpFlush (factory->priv->socket_fd,
 
1705
                    &factory->priv->buf,
 
1706
                    (XdmcpNetaddr)gdm_address_peek_sockaddr_storage (address),
 
1707
                    (int)gdm_sockaddr_len (gdm_address_peek_sockaddr_storage (address)));
 
1708
 
 
1709
        g_free (addr.data);
 
1710
}
 
1711
 
 
1712
static gboolean
 
1713
managed_forward_handler (ManagedForward *mf)
 
1714
{
 
1715
        if (mf->xdmcp_display_factory->priv->socket_fd > 0) {
 
1716
                gdm_xdmcp_really_send_managed_forward (mf->xdmcp_display_factory,
 
1717
                                                       mf->manager,
 
1718
                                                       mf->origin);
 
1719
        }
 
1720
 
 
1721
        mf->times++;
 
1722
        if (mf->xdmcp_display_factory->priv->socket_fd <= 0 || mf->times >= 2) {
 
1723
                mf->xdmcp_display_factory->priv->managed_forwards = g_slist_remove (mf->xdmcp_display_factory->priv->managed_forwards, mf);
 
1724
                mf->handler = 0;
 
1725
                /* mf freed by glib */
 
1726
                return FALSE;
 
1727
        }
 
1728
        return TRUE;
 
1729
}
 
1730
 
 
1731
static void
 
1732
managed_forward_free (ManagedForward *mf)
 
1733
{
 
1734
        gdm_address_free (mf->origin);
 
1735
        gdm_address_free (mf->manager);
 
1736
        g_free (mf);
 
1737
}
 
1738
 
 
1739
static void
 
1740
gdm_xdmcp_send_managed_forward (GdmXdmcpDisplayFactory *factory,
 
1741
                                GdmAddress             *address,
 
1742
                                GdmAddress             *origin)
 
1743
{
 
1744
        ManagedForward *mf;
 
1745
 
 
1746
        gdm_xdmcp_really_send_managed_forward (factory, address, origin);
 
1747
 
 
1748
        mf = g_new0 (ManagedForward, 1);
 
1749
        mf->times = 0;
 
1750
        mf->xdmcp_display_factory = factory;
 
1751
 
 
1752
        mf->manager = gdm_address_copy (address);
 
1753
        mf->origin = gdm_address_copy (origin);
 
1754
 
 
1755
        mf->handler = g_timeout_add_full (G_PRIORITY_DEFAULT,
 
1756
                                          MANAGED_FORWARD_INTERVAL,
 
1757
                                          (GSourceFunc)managed_forward_handler,
 
1758
                                          mf,
 
1759
                                          (GDestroyNotify)managed_forward_free);
 
1760
        factory->priv->managed_forwards = g_slist_prepend (factory->priv->managed_forwards, mf);
 
1761
}
 
1762
 
 
1763
static void
 
1764
gdm_xdmcp_send_got_managed_forward (GdmXdmcpDisplayFactory *factory,
 
1765
                                    GdmAddress             *address,
 
1766
                                    GdmAddress             *origin)
 
1767
{
 
1768
        ARRAY8      addr;
 
1769
        XdmcpHeader header;
 
1770
        char       *host;
 
1771
 
 
1772
        host = NULL;
 
1773
        gdm_address_get_numeric_info (address, &host, NULL);
 
1774
        g_debug ("GdmXdmcpDisplayFactory: Sending GOT_MANAGED_FORWARD to %s",
 
1775
                host ? host : "(null)");
 
1776
        g_free (host);
 
1777
 
 
1778
        set_address_for_request (origin, &addr);
 
1779
 
 
1780
        header.opcode = (CARD16) GDM_XDMCP_GOT_MANAGED_FORWARD;
 
1781
        header.length = 4 + addr.length;
 
1782
        header.version = GDM_XDMCP_PROTOCOL_VERSION;
 
1783
        XdmcpWriteHeader (&factory->priv->buf, &header);
 
1784
 
 
1785
        XdmcpWriteARRAY8 (&factory->priv->buf, &addr);
 
1786
        XdmcpFlush (factory->priv->socket_fd,
 
1787
                    &factory->priv->buf,
 
1788
                    (XdmcpNetaddr)gdm_address_peek_sockaddr_storage (address),
 
1789
                    (int)gdm_sockaddr_len (gdm_address_peek_sockaddr_storage (address)));
 
1790
}
 
1791
 
 
1792
static gboolean
 
1793
count_sessions (const char             *id,
 
1794
                GdmDisplay             *display,
 
1795
                GdmXdmcpDisplayFactory *factory)
 
1796
{
 
1797
        if (GDM_IS_XDMCP_DISPLAY (display)) {
 
1798
                int status;
 
1799
 
 
1800
                status = gdm_display_get_status (display);
 
1801
 
 
1802
                if (status == GDM_DISPLAY_MANAGED) {
 
1803
                        factory->priv->num_sessions++;
 
1804
                } else if (status == GDM_DISPLAY_UNMANAGED) {
 
1805
                        factory->priv->num_pending_sessions++;
 
1806
                }
 
1807
        }
 
1808
 
 
1809
        return TRUE;
 
1810
}
 
1811
 
 
1812
static void
 
1813
gdm_xdmcp_recount_sessions (GdmXdmcpDisplayFactory *factory)
 
1814
{
 
1815
        GdmDisplayStore *store;
 
1816
 
 
1817
        factory->priv->num_sessions = 0;
 
1818
        factory->priv->num_pending_sessions = 0;
 
1819
 
 
1820
        store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
 
1821
        gdm_display_store_foreach (store,
 
1822
                                   (GdmDisplayStoreFunc)count_sessions,
 
1823
                                   factory);
 
1824
}
 
1825
 
 
1826
static gboolean
 
1827
purge_displays (const char             *id,
 
1828
                GdmDisplay             *display,
 
1829
                GdmXdmcpDisplayFactory *factory)
 
1830
{
 
1831
        if (GDM_IS_XDMCP_DISPLAY (display)) {
 
1832
                int status;
 
1833
                time_t currtime;
 
1834
                time_t acctime;
 
1835
 
 
1836
                currtime = time (NULL);
 
1837
                status = gdm_display_get_status (display);
 
1838
                acctime = gdm_display_get_creation_time (display);
 
1839
 
 
1840
                if (status == GDM_DISPLAY_UNMANAGED &&
 
1841
                    currtime > acctime + factory->priv->max_wait) {
 
1842
                        /* return TRUE to remove display */
 
1843
                        return TRUE;
 
1844
                }
 
1845
        }
 
1846
 
 
1847
        return FALSE;
 
1848
}
 
1849
 
 
1850
static void
 
1851
gdm_xdmcp_displays_purge (GdmXdmcpDisplayFactory *factory)
 
1852
{
 
1853
        GdmDisplayStore *store;
 
1854
 
 
1855
        store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
 
1856
 
 
1857
        gdm_display_store_foreach_remove (store,
 
1858
                                          (GdmDisplayStoreFunc)purge_displays,
 
1859
                                          factory);
 
1860
 
 
1861
        gdm_xdmcp_recount_sessions (factory);
 
1862
}
 
1863
 
 
1864
typedef struct {
 
1865
        const char *hostname;
 
1866
        int         display_num;
 
1867
} RemoveHostData;
 
1868
 
 
1869
static gboolean
 
1870
remove_host (const char     *id,
 
1871
             GdmDisplay     *display,
 
1872
             RemoveHostData *data)
 
1873
{
 
1874
        char *hostname;
 
1875
        int   disp_num;
 
1876
 
 
1877
        if (! GDM_IS_XDMCP_DISPLAY (display)) {
 
1878
                return FALSE;
 
1879
        }
 
1880
 
 
1881
        gdm_display_get_remote_hostname (display, &hostname, NULL);
 
1882
        gdm_display_get_x11_display_number (display, &disp_num, NULL);
 
1883
 
 
1884
        if (disp_num == data->display_num &&
 
1885
            hostname != NULL &&
 
1886
            data->hostname != NULL &&
 
1887
            strcmp (hostname, data->hostname) == 0) {
 
1888
                /* return TRUE to remove */
 
1889
                return TRUE;
 
1890
        }
 
1891
 
 
1892
        return FALSE;
 
1893
}
 
1894
 
 
1895
static void
 
1896
display_dispose_check (GdmXdmcpDisplayFactory *factory,
 
1897
                       const char             *hostname,
 
1898
                       int                     display_num)
 
1899
{
 
1900
        RemoveHostData  *data;
 
1901
        GdmDisplayStore *store;
 
1902
 
 
1903
        if (hostname == NULL) {
 
1904
                return;
 
1905
        }
 
1906
 
 
1907
        store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
 
1908
 
 
1909
        g_debug ("GdmXdmcpDisplayFactory: display_dispose_check (%s:%d)",
 
1910
                hostname ? hostname : "(null)", display_num);
 
1911
 
 
1912
        data = g_new0 (RemoveHostData, 1);
 
1913
        data->hostname = hostname;
 
1914
        data->display_num = display_num;
 
1915
        gdm_display_store_foreach_remove (store,
 
1916
                                          (GdmDisplayStoreFunc)remove_host,
 
1917
                                          data);
 
1918
        g_free (data);
 
1919
 
 
1920
        gdm_xdmcp_recount_sessions (factory);
 
1921
}
 
1922
 
 
1923
static void
 
1924
gdm_xdmcp_send_decline (GdmXdmcpDisplayFactory *factory,
 
1925
                        GdmAddress             *address,
 
1926
                        const char             *reason)
 
1927
{
 
1928
        XdmcpHeader      header;
 
1929
        ARRAY8           authentype;
 
1930
        ARRAY8           authendata;
 
1931
        ARRAY8           status;
 
1932
        ForwardQuery    *fq;
 
1933
        char            *host;
 
1934
 
 
1935
        host = NULL;
 
1936
        gdm_address_get_numeric_info (address, &host, NULL);
 
1937
        g_debug ("GdmXdmcpDisplayFactory: Sending DECLINE to %s",
 
1938
                host ? host : "(null)");
 
1939
        g_free (host);
 
1940
 
 
1941
        authentype.data   = (CARD8 *) 0;
 
1942
        authentype.length = (CARD16)  0;
 
1943
 
 
1944
        authendata.data   = (CARD8 *) 0;
 
1945
        authendata.length = (CARD16)  0;
 
1946
 
 
1947
        status.data       = (CARD8 *) reason;
 
1948
        status.length     = strlen ((char *) status.data);
 
1949
 
 
1950
        header.version    = XDM_PROTOCOL_VERSION;
 
1951
        header.opcode     = (CARD16) DECLINE;
 
1952
        header.length     = 2 + status.length;
 
1953
        header.length    += 2 + authentype.length;
 
1954
        header.length    += 2 + authendata.length;
 
1955
 
 
1956
        XdmcpWriteHeader (&factory->priv->buf, &header);
 
1957
        XdmcpWriteARRAY8 (&factory->priv->buf, &status);
 
1958
        XdmcpWriteARRAY8 (&factory->priv->buf, &authentype);
 
1959
        XdmcpWriteARRAY8 (&factory->priv->buf, &authendata);
 
1960
 
 
1961
        XdmcpFlush (factory->priv->socket_fd,
 
1962
                    &factory->priv->buf,
 
1963
                    (XdmcpNetaddr)gdm_address_peek_sockaddr_storage (address),
 
1964
                    (int)gdm_sockaddr_len (gdm_address_peek_sockaddr_storage (address)));
 
1965
 
 
1966
        /* Send MANAGED_FORWARD to indicate that the connection
 
1967
         * reached some sort of resolution */
 
1968
        fq = forward_query_lookup (factory, address);
 
1969
        if (fq != NULL) {
 
1970
                gdm_xdmcp_send_managed_forward (factory, fq->from_address, address);
 
1971
                forward_query_destroy (factory, fq);
 
1972
        }
 
1973
}
 
1974
 
 
1975
static void
 
1976
on_hostname_selected (GdmXdmcpChooserDisplay *display,
 
1977
                      const char             *hostname,
 
1978
                      GdmXdmcpDisplayFactory *factory)
 
1979
{
 
1980
        struct addrinfo  hints;
 
1981
        struct addrinfo *ai_list;
 
1982
        struct addrinfo *ai;
 
1983
        int              gaierr;
 
1984
        GdmAddress      *address;
 
1985
        IndirectClient  *ic;
 
1986
 
 
1987
        g_debug ("GdmXdmcpDisplayFactory: hostname selected: %s",
 
1988
                hostname ? hostname : "(null)");
 
1989
 
 
1990
        address = gdm_xdmcp_display_get_remote_address (GDM_XDMCP_DISPLAY (display));
 
1991
 
 
1992
        g_assert (address != NULL);
 
1993
 
 
1994
        ic = indirect_client_lookup (factory, address);
 
1995
 
 
1996
        if (ic->chosen_address != NULL) {
 
1997
                gdm_address_free (ic->chosen_address);
 
1998
                ic->chosen_address = NULL;
 
1999
        }
 
2000
 
 
2001
        memset (&hints, 0, sizeof (hints));
 
2002
        hints.ai_family = gdm_address_get_family_type (address);
 
2003
        /* this should convert IPv4 address to IPv6 if needed */
 
2004
        hints.ai_flags = AI_V4MAPPED;
 
2005
 
 
2006
        if ((gaierr = getaddrinfo (hostname, NULL, &hints, &ai_list)) != 0) {
 
2007
                g_warning ("Unable to get address: %s", gai_strerror (gaierr));
 
2008
                return;
 
2009
        }
 
2010
 
 
2011
        /* just take the first one */
 
2012
        ai = ai_list;
 
2013
 
 
2014
        if (ai != NULL) {
 
2015
                char *ip;
 
2016
                ic->chosen_address = gdm_address_new_from_sockaddr (ai->ai_addr, ai->ai_addrlen);
 
2017
 
 
2018
                ip = NULL;
 
2019
                gdm_address_get_numeric_info (ic->chosen_address, &ip, NULL);
 
2020
                g_debug ("GdmXdmcpDisplayFactory: hostname resolves to %s",
 
2021
                        ip ? ip : "(null)");
 
2022
                g_free (ip);
 
2023
        }
 
2024
 
 
2025
        freeaddrinfo (ai_list);
 
2026
}
 
2027
 
 
2028
static GdmDisplay *
 
2029
gdm_xdmcp_display_create (GdmXdmcpDisplayFactory *factory,
 
2030
                          const char             *hostname,
 
2031
                          GdmAddress             *address,
 
2032
                          int                     displaynum)
 
2033
{
 
2034
        GdmDisplay      *display;
 
2035
        GdmDisplayStore *store;
 
2036
        gboolean         use_chooser;
 
2037
 
 
2038
        g_debug ("GdmXdmcpDisplayFactory: Creating xdmcp display for %s:%d",
 
2039
                hostname ? hostname : "(null)", displaynum);
 
2040
 
 
2041
        use_chooser = FALSE;
 
2042
        if (factory->priv->honor_indirect) {
 
2043
                IndirectClient *ic;
 
2044
 
 
2045
                ic = indirect_client_lookup (factory, address);
 
2046
 
 
2047
                /* This was an indirect thingie and nothing was yet chosen,
 
2048
                 * use a chooser */
 
2049
                if (ic != NULL && ic->chosen_address == NULL) {
 
2050
                        use_chooser = TRUE;
 
2051
                }
 
2052
        }
 
2053
 
 
2054
        if (use_chooser) {
 
2055
                display = gdm_xdmcp_chooser_display_new (hostname,
 
2056
                                                         displaynum,
 
2057
                                                         address,
 
2058
                                                         get_next_session_serial (factory));
 
2059
                g_signal_connect (display, "hostname-selected", G_CALLBACK (on_hostname_selected), factory);
 
2060
        } else {
 
2061
                display = gdm_xdmcp_greeter_display_new (hostname,
 
2062
                                                         displaynum,
 
2063
                                                         address,
 
2064
                                                         get_next_session_serial (factory));
 
2065
        }
 
2066
 
 
2067
        if (display == NULL) {
 
2068
                goto out;
 
2069
        }
 
2070
 
 
2071
        if (! gdm_display_prepare (display)) {
 
2072
                gdm_display_unmanage (display);
 
2073
                g_object_unref (display);
 
2074
                display = NULL;
 
2075
                goto out;
 
2076
        }
 
2077
 
 
2078
        store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
 
2079
        gdm_display_store_add (store, display);
 
2080
 
 
2081
        factory->priv->num_pending_sessions++;
 
2082
 out:
 
2083
 
 
2084
        return display;
 
2085
}
 
2086
 
 
2087
static void
 
2088
gdm_xdmcp_send_accept (GdmXdmcpDisplayFactory *factory,
 
2089
                       GdmAddress             *address,
 
2090
                       CARD32                  session_id,
 
2091
                       ARRAY8Ptr               authentication_name,
 
2092
                       ARRAY8Ptr               authentication_data,
 
2093
                       ARRAY8Ptr               authorization_name,
 
2094
                       ARRAY8Ptr               authorization_data)
 
2095
{
 
2096
        XdmcpHeader header;
 
2097
        char       *host;
 
2098
 
 
2099
        header.version    = XDM_PROTOCOL_VERSION;
 
2100
        header.opcode     = (CARD16) ACCEPT;
 
2101
        header.length     = 4;
 
2102
        header.length    += 2 + authentication_name->length;
 
2103
        header.length    += 2 + authentication_data->length;
 
2104
        header.length    += 2 + authorization_name->length;
 
2105
        header.length    += 2 + authorization_data->length;
 
2106
 
 
2107
        XdmcpWriteHeader (&factory->priv->buf, &header);
 
2108
        XdmcpWriteCARD32 (&factory->priv->buf, session_id);
 
2109
        XdmcpWriteARRAY8 (&factory->priv->buf, authentication_name);
 
2110
        XdmcpWriteARRAY8 (&factory->priv->buf, authentication_data);
 
2111
        XdmcpWriteARRAY8 (&factory->priv->buf, authorization_name);
 
2112
        XdmcpWriteARRAY8 (&factory->priv->buf, authorization_data);
 
2113
 
 
2114
        XdmcpFlush (factory->priv->socket_fd,
 
2115
                    &factory->priv->buf,
 
2116
                    (XdmcpNetaddr)gdm_address_peek_sockaddr_storage (address),
 
2117
                    (int)gdm_sockaddr_len (gdm_address_peek_sockaddr_storage (address)));
 
2118
 
 
2119
        host = NULL;
 
2120
        gdm_address_get_numeric_info (address, &host, NULL);
 
2121
        g_debug ("GdmXdmcpDisplayFactory: Sending ACCEPT to %s with SessionID=%ld",
 
2122
                 host ? host : "(null)",
 
2123
                 (long)session_id);
 
2124
        g_free (host);
 
2125
}
 
2126
 
 
2127
static void
 
2128
gdm_xdmcp_handle_request (GdmXdmcpDisplayFactory *factory,
 
2129
                          GdmAddress             *address,
 
2130
                          int                     len)
 
2131
{
 
2132
        CARD16        clnt_dspnum;
 
2133
        ARRAY16       clnt_conntyp;
 
2134
        ARRAYofARRAY8 clnt_addr;
 
2135
        ARRAY8        clnt_authname;
 
2136
        ARRAY8        clnt_authdata;
 
2137
        ARRAYofARRAY8 clnt_authorization_names;
 
2138
        ARRAY8        clnt_manufacturer;
 
2139
        int           explen;
 
2140
        int           i;
 
2141
        gboolean      mitauth;
 
2142
        gboolean      entered;
 
2143
        char         *hostname;
 
2144
 
 
2145
        mitauth = FALSE;
 
2146
        entered = FALSE;
 
2147
 
 
2148
        hostname = NULL;
 
2149
        gdm_address_get_numeric_info (address, &hostname, NULL);
 
2150
        g_debug ("GdmXdmcpDisplayFactory: Got REQUEST from %s",
 
2151
                hostname ? hostname : "(null)");
 
2152
 
 
2153
        /* Check with tcp_wrappers if client is allowed to access */
 
2154
        if (! gdm_xdmcp_host_allow (address)) {
 
2155
                g_warning (_("%s: Got REQUEST from banned host %s"),
 
2156
                           "gdm_xdmcp_handle_request",
 
2157
                           hostname ? hostname : "(null)");
 
2158
                goto out;
 
2159
        }
 
2160
 
 
2161
        gdm_xdmcp_displays_purge (factory); /* Purge pending displays */
 
2162
 
 
2163
        /* Remote display number */
 
2164
        if G_UNLIKELY (! XdmcpReadCARD16 (&factory->priv->buf, &clnt_dspnum)) {
 
2165
                g_warning (_("%s: Could not read Display Number"),
 
2166
                           "gdm_xdmcp_handle_request");
 
2167
                goto out;
 
2168
        }
 
2169
 
 
2170
        /* We don't care about connection type. Address says it all */
 
2171
        if G_UNLIKELY (! XdmcpReadARRAY16 (&factory->priv->buf, &clnt_conntyp)) {
 
2172
                g_warning (_("%s: Could not read Connection Type"),
 
2173
                           "gdm_xdmcp_handle_request");
 
2174
                goto out;
 
2175
        }
 
2176
 
 
2177
        /* This is TCP/IP - we don't care */
 
2178
        if G_UNLIKELY (! XdmcpReadARRAYofARRAY8 (&factory->priv->buf, &clnt_addr)) {
 
2179
                g_warning (_("%s: Could not read Client Address"),
 
2180
                           "gdm_xdmcp_handle_request");
 
2181
                XdmcpDisposeARRAY16 (&clnt_conntyp);
 
2182
                goto out;
 
2183
        }
 
2184
 
 
2185
        /* Read authentication type */
 
2186
        if G_UNLIKELY (! XdmcpReadARRAY8 (&factory->priv->buf, &clnt_authname)) {
 
2187
                g_warning (_("%s: Could not read Authentication Names"),
 
2188
                           "gdm_xdmcp_handle_request");
 
2189
                XdmcpDisposeARRAYofARRAY8 (&clnt_addr);
 
2190
                XdmcpDisposeARRAY16 (&clnt_conntyp);
 
2191
                goto out;
 
2192
        }
 
2193
 
 
2194
        /* Read authentication data */
 
2195
        if G_UNLIKELY (! XdmcpReadARRAY8 (&factory->priv->buf, &clnt_authdata)) {
 
2196
                g_warning (_("%s: Could not read Authentication Data"),
 
2197
                           "gdm_xdmcp_handle_request");
 
2198
                XdmcpDisposeARRAYofARRAY8 (&clnt_addr);
 
2199
                XdmcpDisposeARRAY16 (&clnt_conntyp);
 
2200
                XdmcpDisposeARRAY8 (&clnt_authname);
 
2201
                goto out;
 
2202
        }
 
2203
 
 
2204
        /* Read and select from supported authorization list */
 
2205
        if G_UNLIKELY (! XdmcpReadARRAYofARRAY8 (&factory->priv->buf, &clnt_authorization_names)) {
 
2206
                g_warning (_("%s: Could not read Authorization List"),
 
2207
                           "gdm_xdmcp_handle_request");
 
2208
                XdmcpDisposeARRAY8 (&clnt_authdata);
 
2209
                XdmcpDisposeARRAYofARRAY8 (&clnt_addr);
 
2210
                XdmcpDisposeARRAY16 (&clnt_conntyp);
 
2211
                XdmcpDisposeARRAY8 (&clnt_authname);
 
2212
                goto out;
 
2213
        }
 
2214
 
 
2215
        /* libXdmcp doesn't terminate strings properly so we cheat and use strncmp () */
 
2216
        for (i = 0 ; i < clnt_authorization_names.length ; i++) {
 
2217
                if (clnt_authorization_names.data[i].length == 18 &&
 
2218
                    strncmp ((char *) clnt_authorization_names.data[i].data, "MIT-MAGIC-COOKIE-1", 18) == 0) {
 
2219
                        mitauth = TRUE;
 
2220
                }
 
2221
        }
 
2222
 
 
2223
        /* Manufacturer ID */
 
2224
        if G_UNLIKELY (! XdmcpReadARRAY8 (&factory->priv->buf, &clnt_manufacturer)) {
 
2225
                g_warning (_("%s: Could not read Manufacturer ID"),
 
2226
                           "gdm_xdmcp_handle_request");
 
2227
                XdmcpDisposeARRAY8 (&clnt_authname);
 
2228
                XdmcpDisposeARRAY8 (&clnt_authdata);
 
2229
                XdmcpDisposeARRAYofARRAY8 (&clnt_addr);
 
2230
                XdmcpDisposeARRAYofARRAY8 (&clnt_authorization_names);
 
2231
                XdmcpDisposeARRAY16 (&clnt_conntyp);
 
2232
                goto out;
 
2233
        }
 
2234
 
 
2235
        /* Crude checksumming */
 
2236
        explen = 2;                 /* Display Number */
 
2237
        explen += 1 + 2 * clnt_conntyp.length; /* Connection Type */
 
2238
        explen += 1;                /* Connection Address */
 
2239
        for (i = 0 ; i < clnt_addr.length ; i++) {
 
2240
                explen += 2 + clnt_addr.data[i].length;
 
2241
        }
 
2242
        explen += 2 + clnt_authname.length; /* Authentication Name */
 
2243
        explen += 2 + clnt_authdata.length; /* Authentication Data */
 
2244
        explen += 1;                /* Authorization Names */
 
2245
        for (i = 0 ; i < clnt_authorization_names.length ; i++) {
 
2246
                explen += 2 + clnt_authorization_names.data[i].length;
 
2247
        }
 
2248
 
 
2249
        explen += 2 + clnt_manufacturer.length;
 
2250
 
 
2251
        if G_UNLIKELY (explen != len) {
 
2252
                g_warning (_("%s: Failed checksum from %s"),
 
2253
                           "gdm_xdmcp_handle_request",
 
2254
                           hostname ? hostname : "(null)");
 
2255
 
 
2256
                XdmcpDisposeARRAY8 (&clnt_authname);
 
2257
                XdmcpDisposeARRAY8 (&clnt_authdata);
 
2258
                XdmcpDisposeARRAY8 (&clnt_manufacturer);
 
2259
                XdmcpDisposeARRAYofARRAY8 (&clnt_addr);
 
2260
                XdmcpDisposeARRAYofARRAY8 (&clnt_authorization_names);
 
2261
                XdmcpDisposeARRAY16 (&clnt_conntyp);
 
2262
                goto out;
 
2263
        }
 
2264
 
 
2265
        {
 
2266
                char *s = g_strndup ((char *) clnt_manufacturer.data, clnt_manufacturer.length);
 
2267
                g_debug ("GdmXdmcpDisplayFactory: xdmcp_pending=%d, MaxPending=%d, xdmcp_sessions=%d, MaxSessions=%d, ManufacturerID=%s",
 
2268
                         factory->priv->num_pending_sessions,
 
2269
                         factory->priv->max_pending_displays,
 
2270
                         factory->priv->num_sessions,
 
2271
                         factory->priv->max_displays,
 
2272
                         s != NULL ? s : "");
 
2273
                g_free (s);
 
2274
        }
 
2275
 
 
2276
        /* Check if ok to manage display */
 
2277
        if (mitauth &&
 
2278
            factory->priv->num_sessions < factory->priv->max_displays &&
 
2279
            (gdm_address_is_local (address) ||
 
2280
             gdm_xdmcp_num_displays_from_host (factory, address) < factory->priv->max_displays_per_host)) {
 
2281
                entered = TRUE;
 
2282
        }
 
2283
 
 
2284
        if (entered) {
 
2285
 
 
2286
                /* Check if we are already talking to this host */
 
2287
                display_dispose_check (factory, hostname, clnt_dspnum);
 
2288
 
 
2289
                if (factory->priv->num_pending_sessions >= factory->priv->max_pending_displays) {
 
2290
                        g_debug ("GdmXdmcpDisplayFactory: maximum pending");
 
2291
                        /* Don't translate, this goes over the wire to servers where we
 
2292
                         * don't know the charset or language, so it must be ascii */
 
2293
                        gdm_xdmcp_send_decline (factory, address, "Maximum pending servers");
 
2294
                } else {
 
2295
                        GdmDisplay *display;
 
2296
 
 
2297
                        display = gdm_xdmcp_display_create (factory,
 
2298
                                                            hostname,
 
2299
                                                            address,
 
2300
                                                            clnt_dspnum);
 
2301
 
 
2302
                        if (display != NULL) {
 
2303
                                ARRAY8  authentication_name;
 
2304
                                ARRAY8  authentication_data;
 
2305
                                ARRAY8  authorization_name;
 
2306
                                ARRAY8  authorization_data;
 
2307
                                gint32  session_number;
 
2308
                                GArray *cookie;
 
2309
                                char   *name;
 
2310
 
 
2311
                                gdm_display_get_x11_cookie (display, &cookie, NULL);
 
2312
 
 
2313
                                gdm_display_get_x11_display_name (display, &name, NULL);
 
2314
 
 
2315
                                g_debug ("GdmXdmcpDisplayFactory: Sending authorization key for display %s", name ? name : "(null)");
 
2316
                                g_free (name);
 
2317
 
 
2318
                                g_debug ("GdmXdmcpDisplayFactory: cookie len %d", (int) cookie->len);
 
2319
 
 
2320
                                session_number = gdm_xdmcp_display_get_session_number (GDM_XDMCP_DISPLAY (display));
 
2321
 
 
2322
                                /* the send accept will fail if cookie is null */
 
2323
                                g_assert (cookie != NULL);
 
2324
 
 
2325
                                authentication_name.data   = NULL;
 
2326
                                authentication_name.length = 0;
 
2327
                                authentication_data.data   = NULL;
 
2328
                                authentication_data.length = 0;
 
2329
 
 
2330
                                authorization_name.data     = (CARD8 *) "MIT-MAGIC-COOKIE-1";
 
2331
                                authorization_name.length   = strlen ((char *) authorization_name.data);
 
2332
 
 
2333
                                authorization_data.data     = (CARD8 *) cookie->data;
 
2334
                                authorization_data.length   = cookie->len;
 
2335
 
 
2336
                                /* the addrs are NOT copied */
 
2337
                                gdm_xdmcp_send_accept (factory,
 
2338
                                                       address,
 
2339
                                                       session_number,
 
2340
                                                       &authentication_name,
 
2341
                                                       &authentication_data,
 
2342
                                                       &authorization_name,
 
2343
                                                       &authorization_data);
 
2344
 
 
2345
                                g_array_free (cookie, TRUE);
 
2346
                        }
 
2347
                }
 
2348
        } else {
 
2349
                /* Don't translate, this goes over the wire to servers where we
 
2350
                 * don't know the charset or language, so it must be ascii */
 
2351
                if ( ! mitauth) {
 
2352
                        gdm_xdmcp_send_decline (factory,
 
2353
                                                address,
 
2354
                                                "Only MIT-MAGIC-COOKIE-1 supported");
 
2355
                } else if (factory->priv->num_sessions >= factory->priv->max_displays) {
 
2356
                        g_warning ("Maximum number of open XDMCP sessions reached");
 
2357
                        gdm_xdmcp_send_decline (factory,
 
2358
                                                address,
 
2359
                                                "Maximum number of open sessions reached");
 
2360
                } else {
 
2361
                        g_debug ("GdmXdmcpDisplayFactory: Maximum number of open XDMCP sessions from host %s reached",
 
2362
                                 hostname ? hostname : "(null)");
 
2363
                        gdm_xdmcp_send_decline (factory,
 
2364
                                                address,
 
2365
                                                "Maximum number of open sessions from your host reached");
 
2366
                }
 
2367
        }
 
2368
 
 
2369
        XdmcpDisposeARRAY8 (&clnt_authname);
 
2370
        XdmcpDisposeARRAY8 (&clnt_authdata);
 
2371
        XdmcpDisposeARRAY8 (&clnt_manufacturer);
 
2372
        XdmcpDisposeARRAYofARRAY8 (&clnt_addr);
 
2373
        XdmcpDisposeARRAYofARRAY8 (&clnt_authorization_names);
 
2374
        XdmcpDisposeARRAY16 (&clnt_conntyp);
 
2375
 out:
 
2376
        g_free (hostname);
 
2377
}
 
2378
 
 
2379
static gboolean
 
2380
lookup_by_session_id (const char *id,
 
2381
                      GdmDisplay *display,
 
2382
                      gpointer    data)
 
2383
{
 
2384
        CARD32 sessid;
 
2385
        CARD32 session_id;
 
2386
 
 
2387
        sessid = GPOINTER_TO_INT (data);
 
2388
 
 
2389
        if (! GDM_IS_XDMCP_DISPLAY (display)) {
 
2390
                return FALSE;
 
2391
        }
 
2392
 
 
2393
        session_id = gdm_xdmcp_display_get_session_number (GDM_XDMCP_DISPLAY (display));
 
2394
 
 
2395
        if (session_id == sessid) {
 
2396
                return TRUE;
 
2397
        }
 
2398
 
 
2399
        return FALSE;
 
2400
}
 
2401
 
 
2402
static GdmDisplay *
 
2403
gdm_xdmcp_display_lookup (GdmXdmcpDisplayFactory *factory,
 
2404
                          CARD32                  sessid)
 
2405
{
 
2406
        GdmDisplay      *display;
 
2407
        GdmDisplayStore *store;
 
2408
 
 
2409
        if (sessid == 0) {
 
2410
                return NULL;
 
2411
        }
 
2412
 
 
2413
        store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
 
2414
        display = gdm_display_store_find (store,
 
2415
                                          (GdmDisplayStoreFunc)lookup_by_session_id,
 
2416
                                          GINT_TO_POINTER (sessid));
 
2417
 
 
2418
        return display;
 
2419
}
 
2420
 
 
2421
static void
 
2422
gdm_xdmcp_send_failed (GdmXdmcpDisplayFactory *factory,
 
2423
                       GdmAddress             *address,
 
2424
                       CARD32                  sessid)
 
2425
{
 
2426
        XdmcpHeader header;
 
2427
        ARRAY8      status;
 
2428
 
 
2429
        g_debug ("GdmXdmcpDisplayFactory: Sending FAILED to %ld", (long)sessid);
 
2430
 
 
2431
        /*
 
2432
         * Don't translate, this goes over the wire to servers where we
 
2433
         * don't know the charset or language, so it must be ascii
 
2434
         */
 
2435
        status.data    = (CARD8 *) "Failed to start session";
 
2436
        status.length  = strlen ((char *) status.data);
 
2437
 
 
2438
        header.version = XDM_PROTOCOL_VERSION;
 
2439
        header.opcode  = (CARD16) FAILED;
 
2440
        header.length  = 6 + status.length;
 
2441
 
 
2442
        XdmcpWriteHeader (&factory->priv->buf, &header);
 
2443
        XdmcpWriteCARD32 (&factory->priv->buf, sessid);
 
2444
        XdmcpWriteARRAY8 (&factory->priv->buf, &status);
 
2445
 
 
2446
        XdmcpFlush (factory->priv->socket_fd,
 
2447
                    &factory->priv->buf,
 
2448
                    (XdmcpNetaddr)gdm_address_peek_sockaddr_storage (address),
 
2449
                    (int)gdm_sockaddr_len (gdm_address_peek_sockaddr_storage (address)));
 
2450
}
 
2451
 
 
2452
static void
 
2453
gdm_xdmcp_send_refuse (GdmXdmcpDisplayFactory *factory,
 
2454
                       GdmAddress             *address,
 
2455
                       CARD32                  sessid)
 
2456
{
 
2457
        XdmcpHeader   header;
 
2458
        ForwardQuery *fq;
 
2459
 
 
2460
        g_debug ("GdmXdmcpDisplayFactory: Sending REFUSE to %ld",
 
2461
                 (long)sessid);
 
2462
 
 
2463
        header.version = XDM_PROTOCOL_VERSION;
 
2464
        header.opcode  = (CARD16) REFUSE;
 
2465
        header.length  = 4;
 
2466
 
 
2467
        XdmcpWriteHeader (&factory->priv->buf, &header);
 
2468
        XdmcpWriteCARD32 (&factory->priv->buf, sessid);
 
2469
 
 
2470
        XdmcpFlush (factory->priv->socket_fd,
 
2471
                    &factory->priv->buf,
 
2472
                    (XdmcpNetaddr)gdm_address_peek_sockaddr_storage (address),
 
2473
                    (int)gdm_sockaddr_len (gdm_address_peek_sockaddr_storage (address)));
 
2474
 
 
2475
        /*
 
2476
         * This was from a forwarded query quite apparently so
 
2477
         * send MANAGED_FORWARD
 
2478
         */
 
2479
        fq = forward_query_lookup (factory, address);
 
2480
        if (fq != NULL) {
 
2481
                gdm_xdmcp_send_managed_forward (factory, fq->from_address, address);
 
2482
                forward_query_destroy (factory, fq);
 
2483
        }
 
2484
}
 
2485
 
 
2486
static void
 
2487
gdm_xdmcp_handle_manage (GdmXdmcpDisplayFactory *factory,
 
2488
                         GdmAddress             *address,
 
2489
                         int                     len)
 
2490
{
 
2491
        CARD32              clnt_sessid;
 
2492
        CARD16              clnt_dspnum;
 
2493
        ARRAY8              clnt_dspclass;
 
2494
        GdmDisplay         *display;
 
2495
        ForwardQuery       *fq;
 
2496
        char               *host;
 
2497
 
 
2498
        host = NULL;
 
2499
        gdm_address_get_numeric_info (address, &host, NULL);
 
2500
        g_debug ("GdmXdmcpDisplayFactory: Got MANAGE from %s",
 
2501
                host ? host : "(null)");
 
2502
 
 
2503
        /* Check with tcp_wrappers if client is allowed to access */
 
2504
        if (! gdm_xdmcp_host_allow (address)) {
 
2505
                g_warning (_("%s: Got Manage from banned host %s"),
 
2506
                           "gdm_xdmcp_handle_manage",
 
2507
                           host ? host : "(null)");
 
2508
                g_free (host);
 
2509
                return;
 
2510
        }
 
2511
 
 
2512
        /* SessionID */
 
2513
        if G_UNLIKELY (! XdmcpReadCARD32 (&factory->priv->buf, &clnt_sessid)) {
 
2514
                g_warning (_("%s: Could not read Session ID"),
 
2515
                           "gdm_xdmcp_handle_manage");
 
2516
                goto out;
 
2517
        }
 
2518
 
 
2519
        /* Remote display number */
 
2520
        if G_UNLIKELY (! XdmcpReadCARD16 (&factory->priv->buf, &clnt_dspnum)) {
 
2521
                g_warning (_("%s: Could not read Display Number"),
 
2522
                           "gdm_xdmcp_handle_manage");
 
2523
                goto out;
 
2524
        }
 
2525
 
 
2526
        /* Display Class */
 
2527
        if G_UNLIKELY (! XdmcpReadARRAY8 (&factory->priv->buf, &clnt_dspclass)) {
 
2528
                g_warning (_("%s: Could not read Display Class"),
 
2529
                           "gdm_xdmcp_handle_manage");
 
2530
                goto out;
 
2531
        }
 
2532
 
 
2533
        {
 
2534
                char *s = g_strndup ((char *) clnt_dspclass.data, clnt_dspclass.length);
 
2535
                g_debug ("GdmXdmcpDisplayFactory: Got display=%d, SessionID=%ld Class=%s from %s",
 
2536
                         (int)clnt_dspnum,
 
2537
                         (long)clnt_sessid,
 
2538
                         s != NULL ? s : "",
 
2539
                         host);
 
2540
 
 
2541
                g_free (s);
 
2542
        }
 
2543
 
 
2544
        display = gdm_xdmcp_display_lookup (factory, clnt_sessid);
 
2545
        if (display != NULL &&
 
2546
            gdm_display_get_status (display) == GDM_DISPLAY_PREPARED) {
 
2547
                char *name;
 
2548
 
 
2549
                name = NULL;
 
2550
                gdm_display_get_x11_display_name (display, &name, NULL);
 
2551
                g_debug ("GdmXdmcpDisplayFactory: Looked up %s",
 
2552
                        name ? name : "(null)");
 
2553
                g_free (name);
 
2554
 
 
2555
                if (factory->priv->honor_indirect) {
 
2556
                        IndirectClient *ic;
 
2557
 
 
2558
                        ic = indirect_client_lookup (factory, address);
 
2559
 
 
2560
                        /* This was an indirect thingie and nothing was yet chosen,
 
2561
                         * use a chooser */
 
2562
                        if (ic != NULL && ic->chosen_address == NULL) {
 
2563
                                g_debug ("GdmXdmcpDisplayFactory: use chooser");
 
2564
                                /*d->use_chooser = TRUE;
 
2565
                                  d->indirect_id = ic->id;*/
 
2566
                        } else {
 
2567
                                /*d->indirect_id = 0;
 
2568
                                  d->use_chooser = FALSE;*/
 
2569
                                if (ic != NULL) {
 
2570
                                        indirect_client_destroy (factory, ic);
 
2571
                                }
 
2572
                        }
 
2573
                } else {
 
2574
 
 
2575
                }
 
2576
 
 
2577
                /* this was from a forwarded query quite apparently so
 
2578
                 * send MANAGED_FORWARD */
 
2579
                fq = forward_query_lookup (factory, address);
 
2580
                if (fq != NULL) {
 
2581
                        gdm_xdmcp_send_managed_forward (factory, fq->from_address, address);
 
2582
                        forward_query_destroy (factory, fq);
 
2583
                }
 
2584
 
 
2585
                factory->priv->num_sessions++;
 
2586
                factory->priv->num_pending_sessions--;
 
2587
 
 
2588
                /* Start greeter/session */
 
2589
                if (! gdm_display_manage (display)) {
 
2590
                        gdm_xdmcp_send_failed (factory, address, clnt_sessid);
 
2591
                        g_debug ("GdmXdmcpDisplayFactory: Failed to manage display");
 
2592
                }
 
2593
        } else if (display != NULL &&
 
2594
                   gdm_display_get_status (display) == GDM_DISPLAY_MANAGED) {
 
2595
                g_debug ("GdmXdmcpDisplayFactory: Session ID %ld already managed",
 
2596
                         (long)clnt_sessid);
 
2597
        } else {
 
2598
                g_warning ("GdmXdmcpDisplayFactory: Failed to look up session ID %ld",
 
2599
                           (long)clnt_sessid);
 
2600
                gdm_xdmcp_send_refuse (factory, address, clnt_sessid);
 
2601
        }
 
2602
 
 
2603
 out:
 
2604
        XdmcpDisposeARRAY8 (&clnt_dspclass);
 
2605
        g_free (host);
 
2606
}
 
2607
 
 
2608
static void
 
2609
gdm_xdmcp_handle_managed_forward (GdmXdmcpDisplayFactory *factory,
 
2610
                                  GdmAddress             *address,
 
2611
                                  int                     len)
 
2612
{
 
2613
        ARRAY8              clnt_address;
 
2614
        char               *host;
 
2615
        GdmAddress         *disp_address;
 
2616
        IndirectClient     *ic;
 
2617
 
 
2618
        host = NULL;
 
2619
        gdm_address_get_numeric_info (address, &host, NULL);
 
2620
        g_debug ("GdmXdmcpDisplayFactory: Got MANAGED_FORWARD from %s",
 
2621
                   host ? host : "(null)");
 
2622
 
 
2623
        /* Check with tcp_wrappers if client is allowed to access */
 
2624
        if (! gdm_xdmcp_host_allow (address)) {
 
2625
                g_warning ("GdmXdmcpDisplayFactory: Got MANAGED_FORWARD from banned host %s",
 
2626
                           host ? host : "(null)");
 
2627
                g_free (host);
 
2628
                return;
 
2629
        }
 
2630
        g_free (host);
 
2631
 
 
2632
        /* Hostname */
 
2633
        if G_UNLIKELY ( ! XdmcpReadARRAY8 (&factory->priv->buf, &clnt_address)) {
 
2634
                g_warning (_("%s: Could not read address"),
 
2635
                           "gdm_xdmcp_handle_managed_forward");
 
2636
                return;
 
2637
        }
 
2638
 
 
2639
        disp_address = NULL;
 
2640
        if (! create_address_from_request (&clnt_address, NULL, gdm_address_get_family_type (address), &disp_address)) {
 
2641
                g_warning ("Unable to parse address for request");
 
2642
                XdmcpDisposeARRAY8 (&clnt_address);
 
2643
                return;
 
2644
        }
 
2645
 
 
2646
        ic = indirect_client_lookup_by_chosen (factory, address, disp_address);
 
2647
        if (ic != NULL) {
 
2648
                indirect_client_destroy (factory, ic);
 
2649
        }
 
2650
 
 
2651
        /* Note: we send GOT even on not found, just in case our previous
 
2652
         * didn't get through and this was a second managed forward */
 
2653
        gdm_xdmcp_send_got_managed_forward (factory, address, disp_address);
 
2654
 
 
2655
        gdm_address_free (disp_address);
 
2656
 
 
2657
        XdmcpDisposeARRAY8 (&clnt_address);
 
2658
}
 
2659
 
 
2660
static void
 
2661
gdm_xdmcp_handle_got_managed_forward (GdmXdmcpDisplayFactory *factory,
 
2662
                                      GdmAddress             *address,
 
2663
                                      int                     len)
 
2664
{
 
2665
        GdmAddress *disp_address;
 
2666
        ARRAY8      clnt_address;
 
2667
        char       *host;
 
2668
 
 
2669
        host = NULL;
 
2670
        gdm_address_get_numeric_info (address, &host, NULL);
 
2671
        g_debug ("GdmXdmcpDisplayFactory: Got MANAGED_FORWARD from %s",
 
2672
                   host ? host : "(null)");
 
2673
 
 
2674
        if (! gdm_xdmcp_host_allow (address)) {
 
2675
                g_warning ("%s: Got GOT_MANAGED_FORWARD from banned host %s",
 
2676
                           "gdm_xdmcp_handle_request", host ? host : "(null)");
 
2677
                g_free (host);
 
2678
                return;
 
2679
        }
 
2680
        g_free (host);
 
2681
 
 
2682
        /* Hostname */
 
2683
        if G_UNLIKELY ( ! XdmcpReadARRAY8 (&factory->priv->buf, &clnt_address)) {
 
2684
                g_warning (_("%s: Could not read address"),
 
2685
                           "gdm_xdmcp_handle_got_managed_forward");
 
2686
                return;
 
2687
        }
 
2688
 
 
2689
        if (! create_address_from_request (&clnt_address, NULL, gdm_address_get_family_type (address), &disp_address)) {
 
2690
                g_warning (_("%s: Could not read address"),
 
2691
                           "gdm_xdmcp_handle_got_managed_forward");
 
2692
                XdmcpDisposeARRAY8 (&clnt_address);
 
2693
                return;
 
2694
        }
 
2695
 
 
2696
        gdm_xdmcp_whack_queued_managed_forwards (factory, address, disp_address);
 
2697
 
 
2698
        gdm_address_free (disp_address);
 
2699
 
 
2700
        XdmcpDisposeARRAY8 (&clnt_address);
 
2701
}
 
2702
 
 
2703
static void
 
2704
gdm_xdmcp_send_alive (GdmXdmcpDisplayFactory *factory,
 
2705
                      GdmAddress             *address,
 
2706
                      CARD16                  dspnum,
 
2707
                      CARD32                  sessid)
 
2708
{
 
2709
        XdmcpHeader header;
 
2710
        GdmDisplay *display;
 
2711
        int         send_running = 0;
 
2712
        CARD32      send_sessid = 0;
 
2713
 
 
2714
        display = gdm_xdmcp_display_lookup (factory, sessid);
 
2715
        if (display == NULL) {
 
2716
                display = gdm_xdmcp_display_lookup_by_host (factory, address, dspnum);
 
2717
        }
 
2718
 
 
2719
        if (display != NULL) {
 
2720
                int status;
 
2721
 
 
2722
                send_sessid = gdm_xdmcp_display_get_session_number (GDM_XDMCP_DISPLAY (display));
 
2723
                status = gdm_display_get_status (display);
 
2724
 
 
2725
                if (status == GDM_DISPLAY_MANAGED) {
 
2726
                        send_running = 1;
 
2727
                }
 
2728
        }
 
2729
 
 
2730
        g_debug ("GdmXdmcpDisplayFactory: Sending ALIVE to %ld (running %d, sessid %ld)",
 
2731
                 (long)sessid,
 
2732
                 send_running,
 
2733
                 (long)send_sessid);
 
2734
 
 
2735
        header.version = XDM_PROTOCOL_VERSION;
 
2736
        header.opcode = (CARD16) ALIVE;
 
2737
        header.length = 5;
 
2738
 
 
2739
        XdmcpWriteHeader (&factory->priv->buf, &header);
 
2740
        XdmcpWriteCARD8 (&factory->priv->buf, send_running);
 
2741
        XdmcpWriteCARD32 (&factory->priv->buf, send_sessid);
 
2742
 
 
2743
        XdmcpFlush (factory->priv->socket_fd,
 
2744
                    &factory->priv->buf,
 
2745
                    (XdmcpNetaddr)gdm_address_peek_sockaddr_storage (address),
 
2746
                    (int)gdm_sockaddr_len (gdm_address_peek_sockaddr_storage (address)));
 
2747
}
 
2748
 
 
2749
static void
 
2750
gdm_xdmcp_handle_keepalive (GdmXdmcpDisplayFactory *factory,
 
2751
                            GdmAddress             *address,
 
2752
                            int                     len)
 
2753
{
 
2754
        CARD16 clnt_dspnum;
 
2755
        CARD32 clnt_sessid;
 
2756
        char *host;
 
2757
 
 
2758
        host = NULL;
 
2759
        gdm_address_get_numeric_info (address, &host, NULL);
 
2760
        g_debug ("GdmXdmcpDisplayFactory: Got KEEPALIVE from %s",
 
2761
                host ? host : "(null)");
 
2762
 
 
2763
        /* Check with tcp_wrappers if client is allowed to access */
 
2764
        if (! gdm_xdmcp_host_allow (address)) {
 
2765
                g_warning (_("%s: Got KEEPALIVE from banned host %s"),
 
2766
                           "gdm_xdmcp_handle_keepalive",
 
2767
                           host ? host : "(null)");
 
2768
                g_free (host);
 
2769
                return;
 
2770
        }
 
2771
        g_free (host);
 
2772
 
 
2773
        /* Remote display number */
 
2774
        if G_UNLIKELY (! XdmcpReadCARD16 (&factory->priv->buf, &clnt_dspnum)) {
 
2775
                g_warning (_("%s: Could not read Display Number"),
 
2776
                           "gdm_xdmcp_handle_keepalive");
 
2777
                return;
 
2778
        }
 
2779
 
 
2780
        /* SessionID */
 
2781
        if G_UNLIKELY (! XdmcpReadCARD32 (&factory->priv->buf, &clnt_sessid)) {
 
2782
                g_warning (_("%s: Could not read Session ID"),
 
2783
                           "gdm_xdmcp_handle_keepalive");
 
2784
                return;
 
2785
        }
 
2786
 
 
2787
        gdm_xdmcp_send_alive (factory, address, clnt_dspnum, clnt_sessid);
 
2788
}
 
2789
 
 
2790
static const char *
 
2791
opcode_string (int opcode)
 
2792
{
 
2793
        static const char * const opcode_names[] = {
 
2794
                NULL,
 
2795
                "BROADCAST_QUERY",
 
2796
                "QUERY",
 
2797
                "INDIRECT_QUERY",
 
2798
                "FORWARD_QUERY",
 
2799
                "WILLING",
 
2800
                "UNWILLING",
 
2801
                "REQUEST",
 
2802
                "ACCEPT",
 
2803
                "DECLINE",
 
2804
                "MANAGE",
 
2805
                "REFUSE",
 
2806
                "FAILED",
 
2807
                "KEEPALIVE",
 
2808
                "ALIVE"
 
2809
        };
 
2810
        static const char * const gdm_opcode_names[] = {
 
2811
                "MANAGED_FORWARD",
 
2812
                "GOT_MANAGED_FORWARD"
 
2813
        };
 
2814
 
 
2815
 
 
2816
        if (opcode < G_N_ELEMENTS (opcode_names)) {
 
2817
                return opcode_names [opcode];
 
2818
        } else if (opcode >= GDM_XDMCP_FIRST_OPCODE &&
 
2819
                   opcode < GDM_XDMCP_LAST_OPCODE) {
 
2820
                return gdm_opcode_names [opcode - GDM_XDMCP_FIRST_OPCODE];
 
2821
        } else {
 
2822
                return "UNKNOWN";
 
2823
        }
 
2824
}
 
2825
 
 
2826
static gboolean
 
2827
decode_packet (GIOChannel             *source,
 
2828
               GIOCondition            cond,
 
2829
               GdmXdmcpDisplayFactory *factory)
 
2830
{
 
2831
        struct sockaddr_storage clnt_ss;
 
2832
        GdmAddress             *address;
 
2833
        gint                    ss_len;
 
2834
        XdmcpHeader             header;
 
2835
        char                   *host;
 
2836
        char                   *port;
 
2837
        int                     res;
 
2838
 
 
2839
        g_debug ("GdmXdmcpDisplayFactory: decode_packet: GIOCondition %d", (int)cond);
 
2840
 
 
2841
        if ( ! (cond & G_IO_IN)) {
 
2842
                return TRUE;
 
2843
        }
 
2844
 
 
2845
        res = XdmcpFill (factory->priv->socket_fd, &factory->priv->buf, (XdmcpNetaddr)&clnt_ss, &ss_len);
 
2846
        if G_UNLIKELY (! res) {
 
2847
                g_debug ("GdmXdmcpDisplayFactory: Could not create XDMCP buffer!");
 
2848
                return TRUE;
 
2849
        }
 
2850
        ss_len = (int)gdm_sockaddr_len (&clnt_ss);
 
2851
 
 
2852
        res = XdmcpReadHeader (&factory->priv->buf, &header);
 
2853
        if G_UNLIKELY (! res) {
 
2854
                g_warning (_("GdmXdmcpDisplayFactory: Could not read XDMCP header!"));
 
2855
                return TRUE;
 
2856
        }
 
2857
 
 
2858
        if G_UNLIKELY (header.version != XDM_PROTOCOL_VERSION &&
 
2859
                       header.version != GDM_XDMCP_PROTOCOL_VERSION) {
 
2860
                g_warning (_("XMDCP: Incorrect XDMCP version!"));
 
2861
                return TRUE;
 
2862
        }
 
2863
 
 
2864
        address = gdm_address_new_from_sockaddr ((struct sockaddr *) &clnt_ss, ss_len);
 
2865
        if (address == NULL) {
 
2866
                g_warning (_("XMDCP: Unable to parse address"));
 
2867
                return TRUE;
 
2868
        }
 
2869
 
 
2870
        gdm_address_debug (address);
 
2871
 
 
2872
        host = NULL;
 
2873
        port = NULL;
 
2874
        gdm_address_get_numeric_info (address, &host, &port);
 
2875
 
 
2876
        g_debug ("GdmXdmcpDisplayFactory: Received opcode %s from client %s : %s",
 
2877
                 opcode_string (header.opcode),
 
2878
                 host ? host : "(null)",
 
2879
                 port ? port : "(null)");
 
2880
 
 
2881
        switch (header.opcode) {
 
2882
        case BROADCAST_QUERY:
 
2883
                gdm_xdmcp_handle_broadcast_query (factory, address, header.length);
 
2884
                break;
 
2885
 
 
2886
        case QUERY:
 
2887
                gdm_xdmcp_handle_query (factory, address, header.length);
 
2888
                break;
 
2889
 
 
2890
        case INDIRECT_QUERY:
 
2891
                gdm_xdmcp_handle_indirect_query (factory, address, header.length);
 
2892
                break;
 
2893
 
 
2894
        case FORWARD_QUERY:
 
2895
                gdm_xdmcp_handle_forward_query (factory, address, header.length);
 
2896
                break;
 
2897
 
 
2898
        case REQUEST:
 
2899
                gdm_xdmcp_handle_request (factory, address, header.length);
 
2900
                break;
 
2901
 
 
2902
        case MANAGE:
 
2903
                gdm_xdmcp_handle_manage (factory, address, header.length);
 
2904
                break;
 
2905
 
 
2906
        case KEEPALIVE:
 
2907
                gdm_xdmcp_handle_keepalive (factory, address, header.length);
 
2908
                break;
 
2909
 
 
2910
        case GDM_XDMCP_MANAGED_FORWARD:
 
2911
                gdm_xdmcp_handle_managed_forward (factory, address, header.length);
 
2912
                break;
 
2913
 
 
2914
        case GDM_XDMCP_GOT_MANAGED_FORWARD:
 
2915
                gdm_xdmcp_handle_got_managed_forward (factory, address, header.length);
 
2916
                break;
 
2917
 
 
2918
        default:
 
2919
                g_debug ("GdmXdmcpDisplayFactory: Unknown opcode from client %s : %s",
 
2920
                         host ? host : "(null)",
 
2921
                         port ? port : "(null)");
 
2922
 
 
2923
                break;
 
2924
        }
 
2925
 
 
2926
        g_free (host);
 
2927
        g_free (port);
 
2928
 
 
2929
        gdm_address_free (address);
 
2930
 
 
2931
        return TRUE;
 
2932
}
 
2933
 
 
2934
static gboolean
 
2935
gdm_xdmcp_display_factory_start (GdmDisplayFactory *base_factory)
 
2936
{
 
2937
        gboolean                ret;
 
2938
        GIOChannel             *ioc;
 
2939
        GdmXdmcpDisplayFactory *factory = GDM_XDMCP_DISPLAY_FACTORY (base_factory);
 
2940
        gboolean                res;
 
2941
 
 
2942
        g_return_val_if_fail (GDM_IS_XDMCP_DISPLAY_FACTORY (factory), FALSE);
 
2943
        g_return_val_if_fail (factory->priv->socket_fd == -1, FALSE);
 
2944
 
 
2945
        /* read configuration */
 
2946
        res = gdm_settings_direct_get_uint    (GDM_KEY_UDP_PORT,
 
2947
                                               &(factory->priv->port));
 
2948
        res = gdm_settings_direct_get_boolean (GDM_KEY_MULTICAST,
 
2949
                                               &(factory->priv->use_multicast));
 
2950
        res = gdm_settings_direct_get_string  (GDM_KEY_MULTICAST_ADDR,
 
2951
                                               &(factory->priv->multicast_address));
 
2952
        res = gdm_settings_direct_get_boolean (GDM_KEY_INDIRECT,
 
2953
                                               &(factory->priv->honor_indirect));
 
2954
        res = gdm_settings_direct_get_uint    (GDM_KEY_DISPLAYS_PER_HOST,
 
2955
                                               &(factory->priv->max_displays_per_host));
 
2956
        res = gdm_settings_direct_get_uint    (GDM_KEY_MAX_SESSIONS,
 
2957
                                               &(factory->priv->max_displays));
 
2958
        res = gdm_settings_direct_get_uint    (GDM_KEY_MAX_PENDING,
 
2959
                                               &(factory->priv->max_pending_displays));
 
2960
        res = gdm_settings_direct_get_uint    (GDM_KEY_MAX_WAIT,
 
2961
                                               &(factory->priv->max_wait));
 
2962
        res = gdm_settings_direct_get_uint    (GDM_KEY_MAX_WAIT_INDIRECT,
 
2963
                                               &(factory->priv->max_wait_indirect));
 
2964
        res = gdm_settings_direct_get_string  (GDM_KEY_WILLING,
 
2965
                                               &(factory->priv->willing_script));
 
2966
 
 
2967
        ret = open_port (factory);
 
2968
        if (! ret) {
 
2969
                return ret;
 
2970
        }
 
2971
 
 
2972
        g_debug ("GdmXdmcpDisplayFactory: Starting to listen on XDMCP port");
 
2973
 
 
2974
        ioc = g_io_channel_unix_new (factory->priv->socket_fd);
 
2975
 
 
2976
        g_io_channel_set_encoding (ioc, NULL, NULL);
 
2977
        g_io_channel_set_buffered (ioc, FALSE);
 
2978
 
 
2979
        factory->priv->socket_watch_id = g_io_add_watch_full (ioc,
 
2980
                                                              G_PRIORITY_DEFAULT,
 
2981
                                                              G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
 
2982
                                                              (GIOFunc)decode_packet,
 
2983
                                                              factory,
 
2984
                                                              NULL);
 
2985
        g_io_channel_unref (ioc);
 
2986
 
 
2987
        return ret;
 
2988
}
 
2989
 
 
2990
static gboolean
 
2991
gdm_xdmcp_display_factory_stop (GdmDisplayFactory *base_factory)
 
2992
{
 
2993
        GdmXdmcpDisplayFactory *factory = GDM_XDMCP_DISPLAY_FACTORY (base_factory);
 
2994
 
 
2995
        g_return_val_if_fail (GDM_IS_XDMCP_DISPLAY_FACTORY (factory), FALSE);
 
2996
        g_return_val_if_fail (factory->priv->socket_fd != -1, FALSE);
 
2997
 
 
2998
        if (factory->priv->socket_watch_id > 0) {
 
2999
                g_source_remove (factory->priv->socket_watch_id);
 
3000
                factory->priv->socket_watch_id = 0;
 
3001
        }
 
3002
 
 
3003
        if (factory->priv->socket_fd > 0) {
 
3004
                VE_IGNORE_EINTR (close (factory->priv->socket_fd));
 
3005
                factory->priv->socket_fd = -1;
 
3006
        }
 
3007
 
 
3008
        return TRUE;
 
3009
}
 
3010
 
 
3011
void
 
3012
gdm_xdmcp_display_factory_set_port (GdmXdmcpDisplayFactory *factory,
 
3013
                                    guint                   port)
 
3014
{
 
3015
        g_return_if_fail (GDM_IS_XDMCP_DISPLAY_FACTORY (factory));
 
3016
 
 
3017
        factory->priv->port = port;
 
3018
}
 
3019
 
 
3020
static void
 
3021
gdm_xdmcp_display_factory_set_use_multicast (GdmXdmcpDisplayFactory *factory,
 
3022
                                             gboolean                use_multicast)
 
3023
{
 
3024
        g_return_if_fail (GDM_IS_XDMCP_DISPLAY_FACTORY (factory));
 
3025
 
 
3026
        factory->priv->use_multicast = use_multicast;
 
3027
}
 
3028
 
 
3029
static void
 
3030
gdm_xdmcp_display_factory_set_multicast_address (GdmXdmcpDisplayFactory *factory,
 
3031
                                                 const char             *address)
 
3032
{
 
3033
        g_return_if_fail (GDM_IS_XDMCP_DISPLAY_FACTORY (factory));
 
3034
 
 
3035
        g_free (factory->priv->multicast_address);
 
3036
        factory->priv->multicast_address = g_strdup (address);
 
3037
}
 
3038
 
 
3039
static void
 
3040
gdm_xdmcp_display_factory_set_honor_indirect (GdmXdmcpDisplayFactory *factory,
 
3041
                                              gboolean                honor_indirect)
 
3042
{
 
3043
        g_return_if_fail (GDM_IS_XDMCP_DISPLAY_FACTORY (factory));
 
3044
 
 
3045
        factory->priv->honor_indirect = honor_indirect;
 
3046
}
 
3047
 
 
3048
static void
 
3049
gdm_xdmcp_display_factory_set_max_displays_per_host (GdmXdmcpDisplayFactory *factory,
 
3050
                                                     guint                   num)
 
3051
{
 
3052
        g_return_if_fail (GDM_IS_XDMCP_DISPLAY_FACTORY (factory));
 
3053
 
 
3054
        factory->priv->max_displays_per_host = num;
 
3055
}
 
3056
 
 
3057
static void
 
3058
gdm_xdmcp_display_factory_set_max_displays (GdmXdmcpDisplayFactory *factory,
 
3059
                                            guint                   num)
 
3060
{
 
3061
        g_return_if_fail (GDM_IS_XDMCP_DISPLAY_FACTORY (factory));
 
3062
 
 
3063
        factory->priv->max_displays = num;
 
3064
}
 
3065
 
 
3066
static void
 
3067
gdm_xdmcp_display_factory_set_max_pending_displays (GdmXdmcpDisplayFactory *factory,
 
3068
                                                    guint                   num)
 
3069
{
 
3070
        g_return_if_fail (GDM_IS_XDMCP_DISPLAY_FACTORY (factory));
 
3071
 
 
3072
        factory->priv->max_pending_displays = num;
 
3073
}
 
3074
 
 
3075
static void
 
3076
gdm_xdmcp_display_factory_set_max_wait (GdmXdmcpDisplayFactory *factory,
 
3077
                                        guint                   num)
 
3078
{
 
3079
        g_return_if_fail (GDM_IS_XDMCP_DISPLAY_FACTORY (factory));
 
3080
 
 
3081
        factory->priv->max_wait = num;
 
3082
}
 
3083
 
 
3084
static void
 
3085
gdm_xdmcp_display_factory_set_max_wait_indirect (GdmXdmcpDisplayFactory *factory,
 
3086
                                                 guint                   num)
 
3087
{
 
3088
        g_return_if_fail (GDM_IS_XDMCP_DISPLAY_FACTORY (factory));
 
3089
 
 
3090
        factory->priv->max_wait_indirect = num;
 
3091
}
 
3092
 
 
3093
static void
 
3094
gdm_xdmcp_display_factory_set_willing_script (GdmXdmcpDisplayFactory *factory,
 
3095
                                              const char             *script)
 
3096
{
 
3097
        g_return_if_fail (GDM_IS_XDMCP_DISPLAY_FACTORY (factory));
 
3098
 
 
3099
        g_free (factory->priv->willing_script);
 
3100
        factory->priv->willing_script = g_strdup (script);
 
3101
}
 
3102
 
 
3103
static void
 
3104
gdm_xdmcp_display_factory_set_property (GObject       *object,
 
3105
                                        guint          prop_id,
 
3106
                                        const GValue  *value,
 
3107
                                        GParamSpec    *pspec)
 
3108
{
 
3109
        GdmXdmcpDisplayFactory *self;
 
3110
 
 
3111
        self = GDM_XDMCP_DISPLAY_FACTORY (object);
 
3112
 
 
3113
        switch (prop_id) {
 
3114
        case PROP_PORT:
 
3115
                gdm_xdmcp_display_factory_set_port (self, g_value_get_uint (value));
 
3116
                break;
 
3117
        case PROP_USE_MULTICAST:
 
3118
                gdm_xdmcp_display_factory_set_use_multicast (self, g_value_get_boolean (value));
 
3119
                break;
 
3120
        case PROP_MULTICAST_ADDRESS:
 
3121
                gdm_xdmcp_display_factory_set_multicast_address (self, g_value_get_string (value));
 
3122
                break;
 
3123
        case PROP_HONOR_INDIRECT:
 
3124
                gdm_xdmcp_display_factory_set_honor_indirect (self, g_value_get_boolean (value));
 
3125
                break;
 
3126
        case PROP_MAX_DISPLAYS_PER_HOST:
 
3127
                gdm_xdmcp_display_factory_set_max_displays_per_host (self, g_value_get_uint (value));
 
3128
                break;
 
3129
        case PROP_MAX_DISPLAYS:
 
3130
                gdm_xdmcp_display_factory_set_max_displays (self, g_value_get_uint (value));
 
3131
                break;
 
3132
        case PROP_MAX_PENDING_DISPLAYS:
 
3133
                gdm_xdmcp_display_factory_set_max_pending_displays (self, g_value_get_uint (value));
 
3134
                break;
 
3135
        case PROP_MAX_WAIT:
 
3136
                gdm_xdmcp_display_factory_set_max_wait (self, g_value_get_uint (value));
 
3137
                break;
 
3138
        case PROP_MAX_WAIT_INDIRECT:
 
3139
                gdm_xdmcp_display_factory_set_max_wait_indirect (self, g_value_get_uint (value));
 
3140
                break;
 
3141
        case PROP_WILLING_SCRIPT:
 
3142
                gdm_xdmcp_display_factory_set_willing_script (self, g_value_get_string (value));
 
3143
                break;
 
3144
        default:
 
3145
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
3146
                break;
 
3147
        }
 
3148
}
 
3149
 
 
3150
static void
 
3151
gdm_xdmcp_display_factory_get_property (GObject    *object,
 
3152
                                        guint       prop_id,
 
3153
                                        GValue     *value,
 
3154
                                        GParamSpec *pspec)
 
3155
{
 
3156
        GdmXdmcpDisplayFactory *self;
 
3157
 
 
3158
        self = GDM_XDMCP_DISPLAY_FACTORY (object);
 
3159
 
 
3160
        switch (prop_id) {
 
3161
        case PROP_PORT:
 
3162
                g_value_set_uint (value, self->priv->port);
 
3163
                break;
 
3164
        case PROP_USE_MULTICAST:
 
3165
                g_value_set_boolean (value, self->priv->use_multicast);
 
3166
                break;
 
3167
        case PROP_MULTICAST_ADDRESS:
 
3168
                g_value_set_string (value, self->priv->multicast_address);
 
3169
                break;
 
3170
        case PROP_HONOR_INDIRECT:
 
3171
                g_value_set_boolean (value, self->priv->honor_indirect);
 
3172
                break;
 
3173
        case PROP_MAX_DISPLAYS_PER_HOST:
 
3174
                g_value_set_uint (value, self->priv->max_displays_per_host);
 
3175
                break;
 
3176
        case PROP_MAX_DISPLAYS:
 
3177
                g_value_set_uint (value, self->priv->max_displays);
 
3178
                break;
 
3179
        case PROP_MAX_PENDING_DISPLAYS:
 
3180
                g_value_set_uint (value, self->priv->max_pending_displays);
 
3181
                break;
 
3182
        case PROP_MAX_WAIT:
 
3183
                g_value_set_uint (value, self->priv->max_wait);
 
3184
                break;
 
3185
        case PROP_MAX_WAIT_INDIRECT:
 
3186
                g_value_set_uint (value, self->priv->max_wait_indirect);
 
3187
                break;
 
3188
        case PROP_WILLING_SCRIPT:
 
3189
                g_value_set_string (value, self->priv->willing_script);
 
3190
                break;
 
3191
        default:
 
3192
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
3193
                break;
 
3194
        }
 
3195
}
 
3196
 
 
3197
static void
 
3198
gdm_xdmcp_display_factory_class_init (GdmXdmcpDisplayFactoryClass *klass)
 
3199
{
 
3200
        GObjectClass           *object_class = G_OBJECT_CLASS (klass);
 
3201
        GdmDisplayFactoryClass *factory_class = GDM_DISPLAY_FACTORY_CLASS (klass);
 
3202
 
 
3203
        object_class->get_property = gdm_xdmcp_display_factory_get_property;
 
3204
        object_class->set_property = gdm_xdmcp_display_factory_set_property;
 
3205
        object_class->finalize = gdm_xdmcp_display_factory_finalize;
 
3206
 
 
3207
        factory_class->start = gdm_xdmcp_display_factory_start;
 
3208
        factory_class->stop = gdm_xdmcp_display_factory_stop;
 
3209
 
 
3210
        g_object_class_install_property (object_class,
 
3211
                                         PROP_PORT,
 
3212
                                         g_param_spec_uint ("port",
 
3213
                                                            "UDP port",
 
3214
                                                            "UDP port",
 
3215
                                                            0,
 
3216
                                                            G_MAXINT,
 
3217
                                                            DEFAULT_PORT,
 
3218
                                                            G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
3219
        g_object_class_install_property (object_class,
 
3220
                                         PROP_USE_MULTICAST,
 
3221
                                         g_param_spec_boolean ("use-multicast",
 
3222
                                                               NULL,
 
3223
                                                               NULL,
 
3224
                                                               DEFAULT_USE_MULTICAST,
 
3225
                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
3226
        g_object_class_install_property (object_class,
 
3227
                                         PROP_MULTICAST_ADDRESS,
 
3228
                                         g_param_spec_string ("multicast-address",
 
3229
                                                              "multicast-address",
 
3230
                                                              "multicast-address",
 
3231
                                                              DEFAULT_MULTICAST_ADDRESS,
 
3232
                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
3233
        g_object_class_install_property (object_class,
 
3234
                                         PROP_HONOR_INDIRECT,
 
3235
                                         g_param_spec_boolean ("honor-indirect",
 
3236
                                                               NULL,
 
3237
                                                               NULL,
 
3238
                                                               DEFAULT_HONOR_INDIRECT,
 
3239
                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
3240
        g_object_class_install_property (object_class,
 
3241
                                         PROP_WILLING_SCRIPT,
 
3242
                                         g_param_spec_string ("willing-script",
 
3243
                                                              "willing-script",
 
3244
                                                              "willing-script",
 
3245
                                                              DEFAULT_WILLING_SCRIPT,
 
3246
                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
3247
        g_object_class_install_property (object_class,
 
3248
                                         PROP_MAX_DISPLAYS_PER_HOST,
 
3249
                                         g_param_spec_uint ("max-displays-per-host",
 
3250
                                                            "max-displays-per-host",
 
3251
                                                            "max-displays-per-host",
 
3252
                                                            0,
 
3253
                                                            G_MAXINT,
 
3254
                                                            DEFAULT_MAX_DISPLAYS_PER_HOST,
 
3255
                                                            G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
3256
        g_object_class_install_property (object_class,
 
3257
                                         PROP_MAX_DISPLAYS,
 
3258
                                         g_param_spec_uint ("max-displays",
 
3259
                                                            "max-displays",
 
3260
                                                            "max-displays",
 
3261
                                                            0,
 
3262
                                                            G_MAXINT,
 
3263
                                                            DEFAULT_MAX_DISPLAYS,
 
3264
                                                            G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
3265
        g_object_class_install_property (object_class,
 
3266
                                         PROP_MAX_PENDING_DISPLAYS,
 
3267
                                         g_param_spec_uint ("max-pending-displays",
 
3268
                                                            "max-pending-displays",
 
3269
                                                            "max-pending-displays",
 
3270
                                                            0,
 
3271
                                                            G_MAXINT,
 
3272
                                                            DEFAULT_MAX_PENDING_DISPLAYS,
 
3273
                                                            G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
3274
        g_object_class_install_property (object_class,
 
3275
                                         PROP_MAX_WAIT,
 
3276
                                         g_param_spec_uint ("max-wait",
 
3277
                                                            "max-wait",
 
3278
                                                            "max-wait",
 
3279
                                                            0,
 
3280
                                                            G_MAXINT,
 
3281
                                                            DEFAULT_MAX_WAIT,
 
3282
                                                            G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
3283
        g_object_class_install_property (object_class,
 
3284
                                         PROP_MAX_WAIT_INDIRECT,
 
3285
                                         g_param_spec_uint ("max-wait-indirect",
 
3286
                                                            "max-wait-indirect",
 
3287
                                                            "max-wait-indirect",
 
3288
                                                            0,
 
3289
                                                            G_MAXINT,
 
3290
                                                            DEFAULT_MAX_WAIT_INDIRECT,
 
3291
                                                            G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
3292
 
 
3293
        g_type_class_add_private (klass, sizeof (GdmXdmcpDisplayFactoryPrivate));
 
3294
}
 
3295
 
 
3296
static void
 
3297
gdm_xdmcp_display_factory_init (GdmXdmcpDisplayFactory *factory)
 
3298
{
 
3299
        char           hostbuf[1024];
 
3300
        struct utsname name;
 
3301
 
 
3302
        factory->priv = GDM_XDMCP_DISPLAY_FACTORY_GET_PRIVATE (factory);
 
3303
 
 
3304
        factory->priv->socket_fd = -1;
 
3305
 
 
3306
        factory->priv->session_serial = g_random_int ();
 
3307
 
 
3308
        /* Fetch and store local hostname in XDMCP friendly format */
 
3309
        hostbuf[1023] = '\0';
 
3310
        if G_UNLIKELY (gethostname (hostbuf, 1023) != 0) {
 
3311
                g_warning (_("Could not get server hostname: %s!"), g_strerror (errno));
 
3312
                strcpy (hostbuf, "localhost.localdomain");
 
3313
        }
 
3314
 
 
3315
        uname (&name);
 
3316
        factory->priv->sysid = g_strconcat (name.sysname,
 
3317
                                            " ",
 
3318
                                            name.release,
 
3319
                                            NULL);
 
3320
 
 
3321
        factory->priv->hostname = g_strdup (hostbuf);
 
3322
 
 
3323
        factory->priv->servhost.data   = (CARD8 *) g_strdup (hostbuf);
 
3324
        factory->priv->servhost.length = strlen ((char *) factory->priv->servhost.data);
 
3325
}
 
3326
 
 
3327
static void
 
3328
gdm_xdmcp_display_factory_finalize (GObject *object)
 
3329
{
 
3330
        GdmXdmcpDisplayFactory *factory;
 
3331
 
 
3332
        g_return_if_fail (object != NULL);
 
3333
        g_return_if_fail (GDM_IS_XDMCP_DISPLAY_FACTORY (object));
 
3334
 
 
3335
        factory = GDM_XDMCP_DISPLAY_FACTORY (object);
 
3336
 
 
3337
        g_return_if_fail (factory->priv != NULL);
 
3338
 
 
3339
        if (factory->priv->socket_watch_id > 0) {
 
3340
                g_source_remove (factory->priv->socket_watch_id);
 
3341
        }
 
3342
 
 
3343
        if (factory->priv->socket_fd > 0) {
 
3344
                close (factory->priv->socket_fd);
 
3345
                factory->priv->socket_fd = -1;
 
3346
        }
 
3347
 
 
3348
        g_slist_free (factory->priv->forward_queries);
 
3349
        g_slist_free (factory->priv->managed_forwards);
 
3350
 
 
3351
        g_free (factory->priv->sysid);
 
3352
        g_free (factory->priv->hostname);
 
3353
        g_free (factory->priv->multicast_address);
 
3354
        g_free (factory->priv->willing_script);
 
3355
 
 
3356
        /* FIXME: Free servhost */
 
3357
 
 
3358
        G_OBJECT_CLASS (gdm_xdmcp_display_factory_parent_class)->finalize (object);
 
3359
}
 
3360
 
 
3361
GdmXdmcpDisplayFactory *
 
3362
gdm_xdmcp_display_factory_new (GdmDisplayStore *store)
 
3363
{
 
3364
        if (xdmcp_display_factory_object != NULL) {
 
3365
                g_object_ref (xdmcp_display_factory_object);
 
3366
        } else {
 
3367
                xdmcp_display_factory_object = g_object_new (GDM_TYPE_XDMCP_DISPLAY_FACTORY,
 
3368
                                                             "display-store", store,
 
3369
                                                             NULL);
 
3370
                g_object_add_weak_pointer (xdmcp_display_factory_object,
 
3371
                                           (gpointer *) &xdmcp_display_factory_object);
 
3372
        }
 
3373
 
 
3374
        return GDM_XDMCP_DISPLAY_FACTORY (xdmcp_display_factory_object);
 
3375
}