1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
3
* Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net>
4
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
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.
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.
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.
31
#include <sys/types.h>
32
#include <sys/utsname.h>
34
#include <sys/socket.h>
36
#include <arpa/inet.h>
38
#ifdef HAVE_SYS_SOCKIO_H
39
#include <sys/sockio.h>
41
#include <sys/ioctl.h>
46
#include <glib/gi18n.h>
47
#include <glib/gstdio.h>
48
#include <glib-object.h>
52
#include <X11/Xdmcp.h>
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"
64
* On Sun, we need to define allow_severity and deny_severity to link
69
int allow_severity = LOG_INFO;
70
int deny_severity = LOG_WARNING;
73
#define GDM_XDMCP_DISPLAY_FACTORY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_XDMCP_DISPLAY_FACTORY, GdmXdmcpDisplayFactoryPrivate))
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"
86
#define GDM_MAX_FORWARD_QUERIES 10
87
#define GDM_FORWARD_QUERY_TIMEOUT 30
88
#define MANAGED_FORWARD_INTERVAL 1500 /* 1.5 seconds */
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
94
GDM_XDMCP_FIRST_OPCODE = 1000, /*just a marker, not an opcode */
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
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.
116
* Argument is ARRAY8 with the address of the originating host */
117
GDM_XDMCP_LAST_OPCODE /*just a marker, not an opcode */
121
* We don't support XDM-AUTHENTICATION-1 and XDM-AUTHORIZATION-1.
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.
128
* Furthermore user passwords go over the wire in cleartext anyway,
129
* so protecting cookies is not that important.
132
typedef struct _XdmAuth {
133
ARRAY8 authentication;
134
ARRAY8 authorization;
135
} XdmAuthRec, *XdmAuthPtr;
137
static XdmAuthRec serv_authlist = {
138
{ (CARD16) 0, (CARD8 *) 0 },
139
{ (CARD16) 0, (CARD8 *) 0 }
142
/* NOTE: Timeout and max are hardcoded */
143
typedef struct _ForwardQuery {
145
GdmAddress *dsp_address;
146
GdmAddress *from_address;
149
typedef struct _IndirectClient {
151
GdmAddress *dsp_address;
152
GdmAddress *chosen_address;
161
GdmXdmcpDisplayFactory *xdmcp_display_factory;
164
struct GdmXdmcpDisplayFactoryPrivate
166
GSList *forward_queries;
167
GSList *managed_forwards;
168
GSList *indirect_clients;
171
gint32 session_serial;
172
guint socket_watch_id;
176
guint num_pending_sessions;
184
gboolean use_multicast;
185
char *multicast_address;
186
gboolean honor_indirect;
187
char *willing_script;
188
guint max_displays_per_host;
190
guint max_pending_displays;
192
guint max_wait_indirect;
199
PROP_MULTICAST_ADDRESS,
202
PROP_MAX_DISPLAYS_PER_HOST,
204
PROP_MAX_PENDING_DISPLAYS,
206
PROP_MAX_WAIT_INDIRECT,
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);
213
static gpointer xdmcp_display_factory_object = NULL;
215
G_DEFINE_TYPE (GdmXdmcpDisplayFactory, gdm_xdmcp_display_factory, GDM_TYPE_DISPLAY_FACTORY)
217
/* Theory of operation:
219
* Process idles waiting for UDP packets on port 177.
220
* Incoming packets are decoded and checked against tcp_wrapper.
222
* A typical session looks like this:
224
* Display sends Query/BroadcastQuery to Manager.
226
* Manager selects an appropriate authentication scheme from the
227
* display's list of supported ones and sends Willing/Unwilling.
229
* Assuming the display accepts the auth. scheme it sends back a
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.
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.
243
* During the session the display periodically sends KeepAlive packets
244
* to the manager. The manager responds with Alive.
246
* Similarly the manager xpings the display once in a while and shuts
247
* down the connection on failure.
252
gdm_xdmcp_display_factory_error_quark (void)
254
static GQuark ret = 0;
256
ret = g_quark_from_static_string ("gdm_xdmcp_display_factory_error");
263
get_next_session_serial (GdmXdmcpDisplayFactory *factory)
268
if (factory->priv->session_serial != G_MAXINT32) {
269
serial = factory->priv->session_serial++;
271
serial = g_random_int ();
283
ai_family_str (struct addrinfo *ai)
286
switch (ai->ai_family) {
308
ai_type_str (struct addrinfo *ai)
311
switch (ai->ai_socktype) {
333
ai_protocol_str (struct addrinfo *ai)
336
switch (ai->ai_protocol) {
359
ai_flags_str (struct addrinfo *ai)
363
str = g_string_new ("");
364
if (ai->ai_flags == 0) {
365
g_string_append (str, "none");
367
if (ai->ai_flags & AI_PASSIVE) {
368
g_string_append (str, "passive ");
370
if (ai->ai_flags & AI_CANONNAME) {
371
g_string_append (str, "canon ");
373
if (ai->ai_flags & AI_NUMERICHOST) {
374
g_string_append (str, "numhost ");
376
if (ai->ai_flags & AI_NUMERICSERV) {
377
g_string_append (str, "numserv ");
379
if (ai->ai_flags & AI_V4MAPPED) {
380
g_string_append (str, "v4mapped ");
382
if (ai->ai_flags & AI_ALL) {
383
g_string_append (str, "all ");
386
return g_string_free (str, FALSE);
391
debug_addrinfo (struct addrinfo *ai)
394
str = ai_flags_str (ai);
395
g_debug ("GdmXdmcpDisplayFactory: addrinfo family=%s type=%s proto=%s flags=%s",
398
ai_protocol_str (ai),
404
create_socket (struct addrinfo *ai)
408
sock = socket (ai->ai_family, ai->ai_socktype, ai->ai_protocol);
410
g_warning ("socket: %s", g_strerror (errno));
414
if (bind (sock, ai->ai_addr, ai->ai_addrlen) < 0) {
415
g_warning ("bind: %s", g_strerror (errno));
426
struct sockaddr_storage * hostaddr)
428
struct addrinfo hints;
429
struct addrinfo *ai_list;
431
char strport[NI_MAXSERV];
437
memset (&hints, 0, sizeof (hints));
438
hints.ai_family = family;
439
hints.ai_socktype = SOCK_DGRAM;
440
hints.ai_flags = AI_PASSIVE;
442
snprintf (strport, sizeof (strport), "%u", port);
445
if ((gaierr = getaddrinfo (NULL, strport, &hints, &ai_list)) != 0) {
446
g_error ("Unable to connect to socket: %s", gai_strerror (gaierr));
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) {
462
addr = gdm_address_new_from_sockaddr (ai->ai_addr, ai->ai_addrlen);
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)");
471
gdm_address_free (addr);
473
sock = create_socket (ai);
475
if (hostaddr != NULL) {
476
memcpy (hostaddr, ai->ai_addr, ai->ai_addrlen);
482
freeaddrinfo (ai_list);
488
setup_multicast (GdmXdmcpDisplayFactory *factory)
491
/* Checking and Setting Multicast options */
494
* socktemp is a temporary socket for getting info about
495
* available interfaces
501
struct ipv6_mreq mreq;
503
/* For interfaces' list */
507
socktemp = socket (AF_INET, SOCK_DGRAM, 0);
509
if (ioctl (socktemp, SIOCGIFNUM, &num) < 0) {
514
#endif /* SIOCGIFNUM */
515
ifc.ifc_len = sizeof (struct ifreq) * num;
516
ifc.ifc_buf = buf = malloc (ifc.ifc_len);
518
if (ioctl (socktemp, SIOCGIFCONF, &ifc) >= 0) {
520
num = ifc.ifc_len / sizeof (struct ifreq); /* No of interfaces */
522
/* Joining multicast group with all interfaces */
523
for (i = 0 ; i < num ; i++) {
527
memset (&ifreq, 0, sizeof (ifreq));
528
strncpy (ifreq.ifr_name, ifr[i].ifr_name, sizeof (ifreq.ifr_name));
530
ifreq.ifr_name[sizeof (ifreq.ifr_name) - 1] = '\0';
532
if (ioctl (socktemp, SIOCGIFFLAGS, &ifreq) < 0) {
533
g_debug ("GdmXdmcpDisplayFactory: Could not get SIOCGIFFLAGS for %s",
537
ifindex = if_nametoindex (ifr[i].ifr_name);
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*/
546
mreq.ipv6mr_interface = ifindex;
548
factory->priv->multicast_address,
549
&mreq.ipv6mr_multiaddr);
551
setsockopt (factory->priv->socket_fd,
561
#endif /* ENABLE_IPV6 */
565
fd_set_close_on_exec (int fd)
569
flags = fcntl (fd, F_GETFD, 0);
576
fcntl (fd, F_SETFD, flags);
580
open_port (GdmXdmcpDisplayFactory *factory)
582
struct sockaddr_storage serv_sa = { 0 };
584
g_debug ("GdmXdmcpDisplayFactory: Start up on host %s, port %d",
585
factory->priv->hostname ? factory->priv->hostname : "(null)",
586
factory->priv->port);
588
/* Open socket for communications */
590
factory->priv->socket_fd = do_bind (factory->priv->port, AF_INET6, &serv_sa);
591
if (factory->priv->socket_fd < 0)
593
factory->priv->socket_fd = do_bind (factory->priv->port, AF_INET, &serv_sa);
595
if G_UNLIKELY (factory->priv->socket_fd < 0) {
596
g_warning (_("Could not create socket!"));
600
fd_set_close_on_exec (factory->priv->socket_fd);
602
if (factory->priv->use_multicast) {
603
setup_multicast (factory);
609
#ifdef HAVE_TCPWRAPPERS
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
615
extern int hosts_ctl (char *daemon,
622
gdm_xdmcp_host_allow (GdmAddress *address)
624
#ifdef HAVE_TCPWRAPPERS
632
/* Find client hostname */
633
gdm_address_get_hostname (address, &client);
634
gdm_address_get_numeric_info (address, &host, NULL);
636
/* Check with tcp_wrappers if client is allowed to access */
637
ret = hosts_ctl ("gdm", client, host, "");
643
#else /* HAVE_TCPWRAPPERS */
645
#endif /* HAVE_TCPWRAPPERS */
654
count_displays_from_host (const char *id,
656
CountDisplayData *data)
660
if (GDM_IS_XDMCP_DISPLAY (display)) {
661
address = gdm_xdmcp_display_get_remote_address (GDM_XDMCP_DISPLAY (display));
663
if (gdm_address_equal (address, data->address)) {
672
gdm_xdmcp_num_displays_from_host (GdmXdmcpDisplayFactory *factory,
675
CountDisplayData data;
676
GdmDisplayStore *store;
679
data.address = address;
681
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
682
gdm_display_store_foreach (store,
683
(GdmDisplayStoreFunc)count_displays_from_host,
695
lookup_by_host (const char *id,
697
LookupHostData *data)
699
GdmAddress *this_address;
702
if (! GDM_IS_XDMCP_DISPLAY (display)) {
706
this_address = gdm_xdmcp_display_get_remote_address (GDM_XDMCP_DISPLAY (display));
707
gdm_display_get_x11_display_number (display, &disp_num, NULL);
709
if (gdm_address_equal (this_address, data->address)
710
&& disp_num == data->display_num) {
718
gdm_xdmcp_display_lookup_by_host (GdmXdmcpDisplayFactory *factory,
723
LookupHostData *data;
724
GdmDisplayStore *store;
726
data = g_new0 (LookupHostData, 1);
727
data->address = address;
728
data->display_num = display_num;
730
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
731
display = gdm_display_store_find (store,
732
(GdmDisplayStoreFunc)lookup_by_host,
740
get_willing_output (GdmXdmcpDisplayFactory *factory)
750
if (factory->priv->willing_script == NULL) {
755
if (! g_shell_parse_argv (factory->priv->willing_script, NULL, &argv, NULL)) {
761
g_access (argv[0], X_OK) != 0) {
765
fd = popen (factory->priv->willing_script, "r");
770
if (fgets (buf, sizeof (buf), fd) == NULL) {
777
output = g_strdup (buf);
784
gdm_xdmcp_send_willing (GdmXdmcpDisplayFactory *factory,
789
static char *last_status = NULL;
790
static time_t last_willing = 0;
794
gdm_address_get_numeric_info (address, &host, NULL);
795
g_debug ("GdmXdmcpDisplayFactory: Sending WILLING to %s",
796
host ? host : "(null)");
799
if (last_willing == 0 || time (NULL) - 3 > last_willing) {
802
g_free (last_status);
804
s = get_willing_output (factory);
808
last_status = g_strdup (factory->priv->sysid);
812
if (! gdm_address_is_local (address) &&
813
gdm_xdmcp_num_displays_from_host (factory, address) >= factory->priv->max_displays_per_host) {
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
818
status.data = (CARD8 *) g_strdup_printf ("%s (Server is busy)",
821
status.data = (CARD8 *) g_strdup (last_status);
824
status.length = strlen ((char *) status.data);
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);
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);
837
XdmcpFlush (factory->priv->socket_fd,
839
(XdmcpNetaddr)gdm_address_peek_sockaddr_storage (address),
840
(int)gdm_sockaddr_len (gdm_address_peek_sockaddr_storage (address)));
842
g_free (status.data);
846
gdm_xdmcp_send_unwilling (GdmXdmcpDisplayFactory *factory,
852
static time_t last_time = 0;
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)) {
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)");
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
873
status.data = (CARD8 *) "Display not authorized to connect";
874
status.length = strlen ((char *) status.data);
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);
881
XdmcpWriteARRAY8 (&factory->priv->buf, &factory->priv->servhost);
882
XdmcpWriteARRAY8 (&factory->priv->buf, &status);
883
XdmcpFlush (factory->priv->socket_fd,
885
(XdmcpNetaddr)gdm_address_peek_sockaddr_storage (address),
886
(int)gdm_sockaddr_len (gdm_address_peek_sockaddr_storage (address)));
888
last_time = time (NULL);
891
#define SIN(__s) ((struct sockaddr_in *) __s)
892
#define SIN6(__s) ((struct sockaddr_in6 *) __s)
895
set_port_for_request (GdmAddress *address,
898
struct sockaddr_storage *ss;
900
ss = gdm_address_peek_sockaddr_storage (address);
902
/* we depend on this being 2 elsewhere as well */
905
switch (ss->ss_family) {
907
port->data = (CARD8 *)g_memdup (&(SIN (ss)->sin_port), port->length);
910
port->data = (CARD8 *)g_memdup (&(SIN6 (ss)->sin6_port), port->length);
919
set_address_for_request (GdmAddress *address,
922
struct sockaddr_storage *ss;
924
ss = gdm_address_peek_sockaddr_storage (address);
926
switch (ss->ss_family) {
928
addr->length = sizeof (struct in_addr);
929
addr->data = g_memdup (&SIN (ss)->sin_addr, addr->length);
932
addr->length = sizeof (struct in6_addr);
933
addr->data = g_memdup (&SIN6 (ss)->sin6_addr, addr->length);
944
gdm_xdmcp_send_forward_query (GdmXdmcpDisplayFactory *factory,
947
GdmAddress *display_address,
948
ARRAYofARRAY8Ptr authlist)
957
g_assert (ic != NULL);
958
g_assert (ic->chosen_address != 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)");
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)");
974
set_port_for_request (address, &port);
975
set_address_for_request (display_address, &addr);
977
header.version = XDM_PROTOCOL_VERSION;
978
header.opcode = (CARD16) FORWARD_QUERY;
980
header.length += 2 + addr.length;
981
header.length += 2 + port.length;
983
for (i = 0; i < authlist->length; i++) {
984
header.length += 2 + authlist->data[i].length;
987
XdmcpWriteHeader (&factory->priv->buf, &header);
988
XdmcpWriteARRAY8 (&factory->priv->buf, &addr);
989
XdmcpWriteARRAY8 (&factory->priv->buf, &port);
990
XdmcpWriteARRAYofARRAY8 (&factory->priv->buf, authlist);
992
XdmcpFlush (factory->priv->socket_fd,
994
(XdmcpNetaddr)gdm_address_peek_sockaddr_storage (ic->chosen_address),
995
(int)gdm_sockaddr_len (gdm_address_peek_sockaddr_storage (ic->chosen_address)));
1002
handle_any_query (GdmXdmcpDisplayFactory *factory,
1003
GdmAddress *address,
1004
ARRAYofARRAY8Ptr authentication_names,
1007
gdm_xdmcp_send_willing (factory, address);
1011
handle_direct_query (GdmXdmcpDisplayFactory *factory,
1012
GdmAddress *address,
1016
ARRAYofARRAY8 clnt_authlist;
1021
res = XdmcpReadARRAYofARRAY8 (&factory->priv->buf, &clnt_authlist);
1022
if G_UNLIKELY (! res) {
1023
g_warning (_("Could not extract authlist from packet"));
1029
for (i = 0 ; i < clnt_authlist.length ; i++) {
1030
expected_len += 2 + clnt_authlist.data[i].length;
1033
if (len == expected_len) {
1034
handle_any_query (factory, address, &clnt_authlist, type);
1036
g_warning (_("Error in checksum"));
1039
XdmcpDisposeARRAYofARRAY8 (&clnt_authlist);
1043
gdm_xdmcp_handle_broadcast_query (GdmXdmcpDisplayFactory *factory,
1044
GdmAddress *address,
1047
if (gdm_xdmcp_host_allow (address)) {
1048
handle_direct_query (factory, address, len, BROADCAST_QUERY);
1050
/* just ignore it */
1055
gdm_xdmcp_handle_query (GdmXdmcpDisplayFactory *factory,
1056
GdmAddress *address,
1059
if (gdm_xdmcp_host_allow (address)) {
1060
handle_direct_query (factory, address, len, QUERY);
1062
gdm_xdmcp_send_unwilling (factory, address, QUERY);
1066
static IndirectClient *
1067
indirect_client_create (GdmXdmcpDisplayFactory *factory,
1068
GdmAddress *dsp_address)
1072
ic = g_new0 (IndirectClient, 1);
1073
ic->dsp_address = gdm_address_copy (dsp_address);
1075
factory->priv->indirect_clients = g_slist_prepend (factory->priv->indirect_clients, ic);
1081
indirect_client_destroy (GdmXdmcpDisplayFactory *factory,
1088
factory->priv->indirect_clients = g_slist_remove (factory->priv->indirect_clients, ic);
1096
gdm_address_get_numeric_info (ic->dsp_address, &host, NULL);
1097
g_debug ("GdmXdmcpDisplayFactory: Disposing IndirectClient for %s",
1098
host ? host : "(null)");
1102
g_free (ic->dsp_address);
1103
ic->dsp_address = NULL;
1104
g_free (ic->chosen_address);
1105
ic->chosen_address = NULL;
1110
static IndirectClient *
1111
indirect_client_lookup_by_chosen (GdmXdmcpDisplayFactory *factory,
1112
GdmAddress *chosen_address,
1113
GdmAddress *origin_address)
1117
IndirectClient *ret;
1119
g_assert (chosen_address != NULL);
1120
g_assert (origin_address != NULL);
1124
for (li = factory->priv->indirect_clients; li != NULL; li = li->next) {
1125
IndirectClient *ic = li->data;
1128
&& ic->chosen_address != NULL
1129
&& gdm_address_equal (ic->chosen_address, chosen_address)) {
1130
if (gdm_address_equal (ic->dsp_address, origin_address)) {
1133
} else if (gdm_address_is_loopback (ic->dsp_address)
1134
&& gdm_address_is_local (origin_address)) {
1141
gdm_address_get_numeric_info (chosen_address, &host, NULL);
1143
g_debug ("GdmXdmcpDisplayFactory: Chosen %s host not found",
1144
host ? host : "(null)");
1150
/* lookup by origin */
1151
static IndirectClient *
1152
indirect_client_lookup (GdmXdmcpDisplayFactory *factory,
1153
GdmAddress *address)
1157
IndirectClient *ret;
1160
g_assert (address != NULL);
1162
curtime = time (NULL);
1165
qlist = g_slist_copy (factory->priv->indirect_clients);
1167
for (li = qlist; li != NULL; li = li->next) {
1172
ic = (IndirectClient *) li->data;
1180
gdm_address_get_numeric_info (ic->dsp_address, &host, &serv);
1182
g_debug ("GdmXdmcpDisplayFactory: comparing %s:%s",
1183
host ? host : "(null)", serv ? serv : "(null)");
1184
if (gdm_address_equal (ic->dsp_address, address)) {
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)");
1195
indirect_client_destroy (factory, ic);
1202
g_slist_free (qlist);
1208
gdm_address_get_numeric_info (address, &host, NULL);
1209
g_debug ("GdmXdmcpDisplayFactory: Host %s not found",
1210
host ? host : "(null)");
1218
gdm_xdmcp_handle_indirect_query (GdmXdmcpDisplayFactory *factory,
1219
GdmAddress *address,
1222
ARRAYofARRAY8 clnt_authlist;
1228
if (! gdm_xdmcp_host_allow (address)) {
1229
/* ignore the request */
1233
if (! factory->priv->honor_indirect) {
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");
1245
res = XdmcpReadARRAYofARRAY8 (&factory->priv->buf, &clnt_authlist);
1246
if G_UNLIKELY (! res) {
1247
g_warning (_("Could not extract authlist from packet"));
1253
for (i = 0 ; i < clnt_authlist.length ; i++) {
1254
expected_len += 2 + clnt_authlist.data[i].length;
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. */
1261
if (len != expected_len) {
1262
g_warning (_("Error in checksum"));
1267
ic = indirect_client_lookup (factory, address);
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");
1274
/* get rid of indirect, so that we don't get
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 ();
1284
g_debug ("GdmXdmcpDisplayFactory: the chosen address is a loopback");
1286
while (list != NULL) {
1287
GdmAddress *saddr = list->data;
1289
if (! gdm_address_is_loopback (saddr)) {
1290
/* forward query to * chosen host */
1291
gdm_xdmcp_send_forward_query (factory,
1301
/* or send forward query to chosen host */
1302
gdm_xdmcp_send_forward_query (factory,
1308
} else if (ic == NULL) {
1309
ic = indirect_client_create (factory, address);
1311
gdm_xdmcp_send_willing (factory, address);
1314
gdm_xdmcp_send_willing (factory, address);
1318
XdmcpDisposeARRAYofARRAY8 (&clnt_authlist);
1322
forward_query_destroy (GdmXdmcpDisplayFactory *factory,
1329
factory->priv->forward_queries = g_slist_remove (factory->priv->forward_queries, q);
1337
gdm_address_get_numeric_info (q->dsp_address, &host, NULL);
1338
g_debug ("GdmXdmcpDisplayFactory: Disposing %s",
1339
host ? host : "(null)");
1343
g_free (q->dsp_address);
1344
q->dsp_address = NULL;
1345
g_free (q->from_address);
1346
q->from_address = NULL;
1352
remove_oldest_forward (GdmXdmcpDisplayFactory *factory)
1355
ForwardQuery *oldest = NULL;
1357
for (li = factory->priv->forward_queries; li != NULL; li = li->next) {
1358
ForwardQuery *query = li->data;
1360
if (oldest == NULL || query->acctime < oldest->acctime) {
1365
if (oldest != NULL) {
1366
forward_query_destroy (factory, oldest);
1373
static ForwardQuery *
1374
forward_query_create (GdmXdmcpDisplayFactory *factory,
1375
GdmAddress *mgr_address,
1376
GdmAddress *dsp_address)
1381
count = g_slist_length (factory->priv->forward_queries);
1383
while (count > GDM_MAX_FORWARD_QUERIES && remove_oldest_forward (factory)) {
1387
q = g_new0 (ForwardQuery, 1);
1388
q->dsp_address = gdm_address_copy (dsp_address);
1389
q->from_address = gdm_address_copy (mgr_address);
1391
factory->priv->forward_queries = g_slist_prepend (factory->priv->forward_queries, q);
1396
static ForwardQuery *
1397
forward_query_lookup (GdmXdmcpDisplayFactory *factory,
1398
GdmAddress *address)
1405
curtime = time (NULL);
1408
qlist = g_slist_copy (factory->priv->forward_queries);
1410
for (li = qlist; li != NULL; li = li->next) {
1415
q = (ForwardQuery *) li->data;
1423
gdm_address_get_numeric_info (q->dsp_address, &host, &serv);
1425
g_debug ("GdmXdmcpDisplayFactory: comparing %s:%s",
1426
host ? host : "(null)", serv ? serv : "(null)");
1427
if (gdm_address_equal (q->dsp_address, address)) {
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)");
1438
forward_query_destroy (factory, q);
1445
g_slist_free (qlist);
1451
gdm_address_get_numeric_info (address, &host, NULL);
1452
g_debug ("GdmXdmcpDisplayFactory: Host %s not found",
1453
host ? host : "(null)");
1461
create_address_from_request (ARRAY8 *req_addr,
1464
GdmAddress **address)
1467
char host_buf [NI_MAXHOST];
1468
char serv_buf [NI_MAXSERV];
1471
struct addrinfo hints;
1472
struct addrinfo *ai_list;
1473
struct addrinfo *ai;
1477
if (address != NULL) {
1481
if (req_addr == NULL) {
1486
if (req_port != NULL) {
1487
/* port must always be length 2 */
1488
if (req_port->length != 2) {
1492
memcpy (&port, req_port->data, 2);
1493
snprintf (serv_buf, sizeof (serv_buf), "%d", ntohs (port));
1496
/* assume XDM_UDP_PORT */
1497
snprintf (serv_buf, sizeof (serv_buf), "%d", XDM_UDP_PORT);
1502
if (req_addr->length == 4) {
1503
host = inet_ntop (AF_INET,
1504
(const void *)req_addr->data,
1507
} else if (req_addr->length == 16) {
1508
host = inet_ntop (AF_INET6,
1509
(const void *)req_addr->data,
1515
g_warning (_("Bad address"));
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;
1525
if ((gaierr = getaddrinfo (host, serv, &hints, &ai_list)) != 0) {
1526
g_warning ("Unable to get address: %s", gai_strerror (gaierr));
1530
/* just take the first one */
1536
if (address != NULL) {
1537
*address = gdm_address_new_from_sockaddr (ai->ai_addr, ai->ai_addrlen);
1541
freeaddrinfo (ai_list);
1547
gdm_xdmcp_whack_queued_managed_forwards (GdmXdmcpDisplayFactory *factory,
1548
GdmAddress *address,
1553
for (li = factory->priv->managed_forwards; li != NULL; li = li->next) {
1554
ManagedForward *mf = li->data;
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 */
1568
gdm_xdmcp_handle_forward_query (GdmXdmcpDisplayFactory *factory,
1569
GdmAddress *address,
1574
ARRAYofARRAY8 clnt_authlist;
1577
GdmAddress *disp_address;
1581
disp_address = NULL;
1583
/* Check with tcp_wrappers if client is allowed to access */
1584
if (! gdm_xdmcp_host_allow (address)) {
1588
gdm_address_get_numeric_info (address, &host2, NULL);
1590
g_warning ("%s: Got FORWARD_QUERY from banned host %s",
1591
"gdm_xdmcp_handle_forward query",
1592
host2 ? host2 : "(null)");
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");
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");
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");
1621
/* Crude checksumming */
1623
explen += 2 + clnt_addr.length;
1624
explen += 2 + clnt_port.length;
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);
1632
explen += 2 + clnt_authlist.data[i].length;
1635
if G_UNLIKELY (len != explen) {
1636
g_warning (_("%s: Error in checksum"),
1637
"gdm_xdmcp_handle_forward_query");
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");
1646
gdm_xdmcp_whack_queued_managed_forwards (factory,
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)");
1658
/* Check with tcp_wrappers if display is allowed to access */
1659
if (gdm_xdmcp_host_allow (disp_address)) {
1662
q = forward_query_lookup (factory, disp_address);
1664
forward_query_destroy (factory, q);
1667
forward_query_create (factory, address, disp_address);
1669
gdm_xdmcp_send_willing (factory, disp_address);
1674
gdm_address_free (disp_address);
1676
XdmcpDisposeARRAYofARRAY8 (&clnt_authlist);
1677
XdmcpDisposeARRAY8 (&clnt_port);
1678
XdmcpDisposeARRAY8 (&clnt_addr);
1682
gdm_xdmcp_really_send_managed_forward (GdmXdmcpDisplayFactory *factory,
1683
GdmAddress *address,
1691
gdm_address_get_numeric_info (address, &host, NULL);
1692
g_debug ("GdmXdmcpDisplayFactory: Sending MANAGED_FORWARD to %s",
1693
host ? host : "(null)");
1696
set_address_for_request (origin, &addr);
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);
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)));
1713
managed_forward_handler (ManagedForward *mf)
1715
if (mf->xdmcp_display_factory->priv->socket_fd > 0) {
1716
gdm_xdmcp_really_send_managed_forward (mf->xdmcp_display_factory,
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);
1725
/* mf freed by glib */
1732
managed_forward_free (ManagedForward *mf)
1734
gdm_address_free (mf->origin);
1735
gdm_address_free (mf->manager);
1740
gdm_xdmcp_send_managed_forward (GdmXdmcpDisplayFactory *factory,
1741
GdmAddress *address,
1746
gdm_xdmcp_really_send_managed_forward (factory, address, origin);
1748
mf = g_new0 (ManagedForward, 1);
1750
mf->xdmcp_display_factory = factory;
1752
mf->manager = gdm_address_copy (address);
1753
mf->origin = gdm_address_copy (origin);
1755
mf->handler = g_timeout_add_full (G_PRIORITY_DEFAULT,
1756
MANAGED_FORWARD_INTERVAL,
1757
(GSourceFunc)managed_forward_handler,
1759
(GDestroyNotify)managed_forward_free);
1760
factory->priv->managed_forwards = g_slist_prepend (factory->priv->managed_forwards, mf);
1764
gdm_xdmcp_send_got_managed_forward (GdmXdmcpDisplayFactory *factory,
1765
GdmAddress *address,
1773
gdm_address_get_numeric_info (address, &host, NULL);
1774
g_debug ("GdmXdmcpDisplayFactory: Sending GOT_MANAGED_FORWARD to %s",
1775
host ? host : "(null)");
1778
set_address_for_request (origin, &addr);
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);
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)));
1793
count_sessions (const char *id,
1794
GdmDisplay *display,
1795
GdmXdmcpDisplayFactory *factory)
1797
if (GDM_IS_XDMCP_DISPLAY (display)) {
1800
status = gdm_display_get_status (display);
1802
if (status == GDM_DISPLAY_MANAGED) {
1803
factory->priv->num_sessions++;
1804
} else if (status == GDM_DISPLAY_UNMANAGED) {
1805
factory->priv->num_pending_sessions++;
1813
gdm_xdmcp_recount_sessions (GdmXdmcpDisplayFactory *factory)
1815
GdmDisplayStore *store;
1817
factory->priv->num_sessions = 0;
1818
factory->priv->num_pending_sessions = 0;
1820
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
1821
gdm_display_store_foreach (store,
1822
(GdmDisplayStoreFunc)count_sessions,
1827
purge_displays (const char *id,
1828
GdmDisplay *display,
1829
GdmXdmcpDisplayFactory *factory)
1831
if (GDM_IS_XDMCP_DISPLAY (display)) {
1836
currtime = time (NULL);
1837
status = gdm_display_get_status (display);
1838
acctime = gdm_display_get_creation_time (display);
1840
if (status == GDM_DISPLAY_UNMANAGED &&
1841
currtime > acctime + factory->priv->max_wait) {
1842
/* return TRUE to remove display */
1851
gdm_xdmcp_displays_purge (GdmXdmcpDisplayFactory *factory)
1853
GdmDisplayStore *store;
1855
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
1857
gdm_display_store_foreach_remove (store,
1858
(GdmDisplayStoreFunc)purge_displays,
1861
gdm_xdmcp_recount_sessions (factory);
1865
const char *hostname;
1870
remove_host (const char *id,
1871
GdmDisplay *display,
1872
RemoveHostData *data)
1877
if (! GDM_IS_XDMCP_DISPLAY (display)) {
1881
gdm_display_get_remote_hostname (display, &hostname, NULL);
1882
gdm_display_get_x11_display_number (display, &disp_num, NULL);
1884
if (disp_num == data->display_num &&
1886
data->hostname != NULL &&
1887
strcmp (hostname, data->hostname) == 0) {
1888
/* return TRUE to remove */
1896
display_dispose_check (GdmXdmcpDisplayFactory *factory,
1897
const char *hostname,
1900
RemoveHostData *data;
1901
GdmDisplayStore *store;
1903
if (hostname == NULL) {
1907
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
1909
g_debug ("GdmXdmcpDisplayFactory: display_dispose_check (%s:%d)",
1910
hostname ? hostname : "(null)", display_num);
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,
1920
gdm_xdmcp_recount_sessions (factory);
1924
gdm_xdmcp_send_decline (GdmXdmcpDisplayFactory *factory,
1925
GdmAddress *address,
1936
gdm_address_get_numeric_info (address, &host, NULL);
1937
g_debug ("GdmXdmcpDisplayFactory: Sending DECLINE to %s",
1938
host ? host : "(null)");
1941
authentype.data = (CARD8 *) 0;
1942
authentype.length = (CARD16) 0;
1944
authendata.data = (CARD8 *) 0;
1945
authendata.length = (CARD16) 0;
1947
status.data = (CARD8 *) reason;
1948
status.length = strlen ((char *) status.data);
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;
1956
XdmcpWriteHeader (&factory->priv->buf, &header);
1957
XdmcpWriteARRAY8 (&factory->priv->buf, &status);
1958
XdmcpWriteARRAY8 (&factory->priv->buf, &authentype);
1959
XdmcpWriteARRAY8 (&factory->priv->buf, &authendata);
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)));
1966
/* Send MANAGED_FORWARD to indicate that the connection
1967
* reached some sort of resolution */
1968
fq = forward_query_lookup (factory, address);
1970
gdm_xdmcp_send_managed_forward (factory, fq->from_address, address);
1971
forward_query_destroy (factory, fq);
1976
on_hostname_selected (GdmXdmcpChooserDisplay *display,
1977
const char *hostname,
1978
GdmXdmcpDisplayFactory *factory)
1980
struct addrinfo hints;
1981
struct addrinfo *ai_list;
1982
struct addrinfo *ai;
1984
GdmAddress *address;
1987
g_debug ("GdmXdmcpDisplayFactory: hostname selected: %s",
1988
hostname ? hostname : "(null)");
1990
address = gdm_xdmcp_display_get_remote_address (GDM_XDMCP_DISPLAY (display));
1992
g_assert (address != NULL);
1994
ic = indirect_client_lookup (factory, address);
1996
if (ic->chosen_address != NULL) {
1997
gdm_address_free (ic->chosen_address);
1998
ic->chosen_address = NULL;
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;
2006
if ((gaierr = getaddrinfo (hostname, NULL, &hints, &ai_list)) != 0) {
2007
g_warning ("Unable to get address: %s", gai_strerror (gaierr));
2011
/* just take the first one */
2016
ic->chosen_address = gdm_address_new_from_sockaddr (ai->ai_addr, ai->ai_addrlen);
2019
gdm_address_get_numeric_info (ic->chosen_address, &ip, NULL);
2020
g_debug ("GdmXdmcpDisplayFactory: hostname resolves to %s",
2021
ip ? ip : "(null)");
2025
freeaddrinfo (ai_list);
2029
gdm_xdmcp_display_create (GdmXdmcpDisplayFactory *factory,
2030
const char *hostname,
2031
GdmAddress *address,
2034
GdmDisplay *display;
2035
GdmDisplayStore *store;
2036
gboolean use_chooser;
2038
g_debug ("GdmXdmcpDisplayFactory: Creating xdmcp display for %s:%d",
2039
hostname ? hostname : "(null)", displaynum);
2041
use_chooser = FALSE;
2042
if (factory->priv->honor_indirect) {
2045
ic = indirect_client_lookup (factory, address);
2047
/* This was an indirect thingie and nothing was yet chosen,
2049
if (ic != NULL && ic->chosen_address == NULL) {
2055
display = gdm_xdmcp_chooser_display_new (hostname,
2058
get_next_session_serial (factory));
2059
g_signal_connect (display, "hostname-selected", G_CALLBACK (on_hostname_selected), factory);
2061
display = gdm_xdmcp_greeter_display_new (hostname,
2064
get_next_session_serial (factory));
2067
if (display == NULL) {
2071
if (! gdm_display_prepare (display)) {
2072
gdm_display_unmanage (display);
2073
g_object_unref (display);
2078
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
2079
gdm_display_store_add (store, display);
2081
factory->priv->num_pending_sessions++;
2088
gdm_xdmcp_send_accept (GdmXdmcpDisplayFactory *factory,
2089
GdmAddress *address,
2091
ARRAY8Ptr authentication_name,
2092
ARRAY8Ptr authentication_data,
2093
ARRAY8Ptr authorization_name,
2094
ARRAY8Ptr authorization_data)
2099
header.version = XDM_PROTOCOL_VERSION;
2100
header.opcode = (CARD16) ACCEPT;
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;
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);
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)));
2120
gdm_address_get_numeric_info (address, &host, NULL);
2121
g_debug ("GdmXdmcpDisplayFactory: Sending ACCEPT to %s with SessionID=%ld",
2122
host ? host : "(null)",
2128
gdm_xdmcp_handle_request (GdmXdmcpDisplayFactory *factory,
2129
GdmAddress *address,
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;
2149
gdm_address_get_numeric_info (address, &hostname, NULL);
2150
g_debug ("GdmXdmcpDisplayFactory: Got REQUEST from %s",
2151
hostname ? hostname : "(null)");
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)");
2161
gdm_xdmcp_displays_purge (factory); /* Purge pending displays */
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");
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");
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);
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);
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);
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);
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) {
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);
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;
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;
2249
explen += 2 + clnt_manufacturer.length;
2251
if G_UNLIKELY (explen != len) {
2252
g_warning (_("%s: Failed checksum from %s"),
2253
"gdm_xdmcp_handle_request",
2254
hostname ? hostname : "(null)");
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);
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 : "");
2276
/* Check if ok to manage display */
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)) {
2286
/* Check if we are already talking to this host */
2287
display_dispose_check (factory, hostname, clnt_dspnum);
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");
2295
GdmDisplay *display;
2297
display = gdm_xdmcp_display_create (factory,
2302
if (display != NULL) {
2303
ARRAY8 authentication_name;
2304
ARRAY8 authentication_data;
2305
ARRAY8 authorization_name;
2306
ARRAY8 authorization_data;
2307
gint32 session_number;
2311
gdm_display_get_x11_cookie (display, &cookie, NULL);
2313
gdm_display_get_x11_display_name (display, &name, NULL);
2315
g_debug ("GdmXdmcpDisplayFactory: Sending authorization key for display %s", name ? name : "(null)");
2318
g_debug ("GdmXdmcpDisplayFactory: cookie len %d", (int) cookie->len);
2320
session_number = gdm_xdmcp_display_get_session_number (GDM_XDMCP_DISPLAY (display));
2322
/* the send accept will fail if cookie is null */
2323
g_assert (cookie != NULL);
2325
authentication_name.data = NULL;
2326
authentication_name.length = 0;
2327
authentication_data.data = NULL;
2328
authentication_data.length = 0;
2330
authorization_name.data = (CARD8 *) "MIT-MAGIC-COOKIE-1";
2331
authorization_name.length = strlen ((char *) authorization_name.data);
2333
authorization_data.data = (CARD8 *) cookie->data;
2334
authorization_data.length = cookie->len;
2336
/* the addrs are NOT copied */
2337
gdm_xdmcp_send_accept (factory,
2340
&authentication_name,
2341
&authentication_data,
2342
&authorization_name,
2343
&authorization_data);
2345
g_array_free (cookie, TRUE);
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 */
2352
gdm_xdmcp_send_decline (factory,
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,
2359
"Maximum number of open sessions reached");
2361
g_debug ("GdmXdmcpDisplayFactory: Maximum number of open XDMCP sessions from host %s reached",
2362
hostname ? hostname : "(null)");
2363
gdm_xdmcp_send_decline (factory,
2365
"Maximum number of open sessions from your host reached");
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);
2380
lookup_by_session_id (const char *id,
2381
GdmDisplay *display,
2387
sessid = GPOINTER_TO_INT (data);
2389
if (! GDM_IS_XDMCP_DISPLAY (display)) {
2393
session_id = gdm_xdmcp_display_get_session_number (GDM_XDMCP_DISPLAY (display));
2395
if (session_id == sessid) {
2403
gdm_xdmcp_display_lookup (GdmXdmcpDisplayFactory *factory,
2406
GdmDisplay *display;
2407
GdmDisplayStore *store;
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));
2422
gdm_xdmcp_send_failed (GdmXdmcpDisplayFactory *factory,
2423
GdmAddress *address,
2429
g_debug ("GdmXdmcpDisplayFactory: Sending FAILED to %ld", (long)sessid);
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
2435
status.data = (CARD8 *) "Failed to start session";
2436
status.length = strlen ((char *) status.data);
2438
header.version = XDM_PROTOCOL_VERSION;
2439
header.opcode = (CARD16) FAILED;
2440
header.length = 6 + status.length;
2442
XdmcpWriteHeader (&factory->priv->buf, &header);
2443
XdmcpWriteCARD32 (&factory->priv->buf, sessid);
2444
XdmcpWriteARRAY8 (&factory->priv->buf, &status);
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)));
2453
gdm_xdmcp_send_refuse (GdmXdmcpDisplayFactory *factory,
2454
GdmAddress *address,
2460
g_debug ("GdmXdmcpDisplayFactory: Sending REFUSE to %ld",
2463
header.version = XDM_PROTOCOL_VERSION;
2464
header.opcode = (CARD16) REFUSE;
2467
XdmcpWriteHeader (&factory->priv->buf, &header);
2468
XdmcpWriteCARD32 (&factory->priv->buf, sessid);
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)));
2476
* This was from a forwarded query quite apparently so
2477
* send MANAGED_FORWARD
2479
fq = forward_query_lookup (factory, address);
2481
gdm_xdmcp_send_managed_forward (factory, fq->from_address, address);
2482
forward_query_destroy (factory, fq);
2487
gdm_xdmcp_handle_manage (GdmXdmcpDisplayFactory *factory,
2488
GdmAddress *address,
2493
ARRAY8 clnt_dspclass;
2494
GdmDisplay *display;
2499
gdm_address_get_numeric_info (address, &host, NULL);
2500
g_debug ("GdmXdmcpDisplayFactory: Got MANAGE from %s",
2501
host ? host : "(null)");
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)");
2513
if G_UNLIKELY (! XdmcpReadCARD32 (&factory->priv->buf, &clnt_sessid)) {
2514
g_warning (_("%s: Could not read Session ID"),
2515
"gdm_xdmcp_handle_manage");
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");
2527
if G_UNLIKELY (! XdmcpReadARRAY8 (&factory->priv->buf, &clnt_dspclass)) {
2528
g_warning (_("%s: Could not read Display Class"),
2529
"gdm_xdmcp_handle_manage");
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",
2544
display = gdm_xdmcp_display_lookup (factory, clnt_sessid);
2545
if (display != NULL &&
2546
gdm_display_get_status (display) == GDM_DISPLAY_PREPARED) {
2550
gdm_display_get_x11_display_name (display, &name, NULL);
2551
g_debug ("GdmXdmcpDisplayFactory: Looked up %s",
2552
name ? name : "(null)");
2555
if (factory->priv->honor_indirect) {
2558
ic = indirect_client_lookup (factory, address);
2560
/* This was an indirect thingie and nothing was yet chosen,
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;*/
2567
/*d->indirect_id = 0;
2568
d->use_chooser = FALSE;*/
2570
indirect_client_destroy (factory, ic);
2577
/* this was from a forwarded query quite apparently so
2578
* send MANAGED_FORWARD */
2579
fq = forward_query_lookup (factory, address);
2581
gdm_xdmcp_send_managed_forward (factory, fq->from_address, address);
2582
forward_query_destroy (factory, fq);
2585
factory->priv->num_sessions++;
2586
factory->priv->num_pending_sessions--;
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");
2593
} else if (display != NULL &&
2594
gdm_display_get_status (display) == GDM_DISPLAY_MANAGED) {
2595
g_debug ("GdmXdmcpDisplayFactory: Session ID %ld already managed",
2598
g_warning ("GdmXdmcpDisplayFactory: Failed to look up session ID %ld",
2600
gdm_xdmcp_send_refuse (factory, address, clnt_sessid);
2604
XdmcpDisposeARRAY8 (&clnt_dspclass);
2609
gdm_xdmcp_handle_managed_forward (GdmXdmcpDisplayFactory *factory,
2610
GdmAddress *address,
2613
ARRAY8 clnt_address;
2615
GdmAddress *disp_address;
2619
gdm_address_get_numeric_info (address, &host, NULL);
2620
g_debug ("GdmXdmcpDisplayFactory: Got MANAGED_FORWARD from %s",
2621
host ? host : "(null)");
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)");
2633
if G_UNLIKELY ( ! XdmcpReadARRAY8 (&factory->priv->buf, &clnt_address)) {
2634
g_warning (_("%s: Could not read address"),
2635
"gdm_xdmcp_handle_managed_forward");
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);
2646
ic = indirect_client_lookup_by_chosen (factory, address, disp_address);
2648
indirect_client_destroy (factory, ic);
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);
2655
gdm_address_free (disp_address);
2657
XdmcpDisposeARRAY8 (&clnt_address);
2661
gdm_xdmcp_handle_got_managed_forward (GdmXdmcpDisplayFactory *factory,
2662
GdmAddress *address,
2665
GdmAddress *disp_address;
2666
ARRAY8 clnt_address;
2670
gdm_address_get_numeric_info (address, &host, NULL);
2671
g_debug ("GdmXdmcpDisplayFactory: Got MANAGED_FORWARD from %s",
2672
host ? host : "(null)");
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)");
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");
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);
2696
gdm_xdmcp_whack_queued_managed_forwards (factory, address, disp_address);
2698
gdm_address_free (disp_address);
2700
XdmcpDisposeARRAY8 (&clnt_address);
2704
gdm_xdmcp_send_alive (GdmXdmcpDisplayFactory *factory,
2705
GdmAddress *address,
2710
GdmDisplay *display;
2711
int send_running = 0;
2712
CARD32 send_sessid = 0;
2714
display = gdm_xdmcp_display_lookup (factory, sessid);
2715
if (display == NULL) {
2716
display = gdm_xdmcp_display_lookup_by_host (factory, address, dspnum);
2719
if (display != NULL) {
2722
send_sessid = gdm_xdmcp_display_get_session_number (GDM_XDMCP_DISPLAY (display));
2723
status = gdm_display_get_status (display);
2725
if (status == GDM_DISPLAY_MANAGED) {
2730
g_debug ("GdmXdmcpDisplayFactory: Sending ALIVE to %ld (running %d, sessid %ld)",
2735
header.version = XDM_PROTOCOL_VERSION;
2736
header.opcode = (CARD16) ALIVE;
2739
XdmcpWriteHeader (&factory->priv->buf, &header);
2740
XdmcpWriteCARD8 (&factory->priv->buf, send_running);
2741
XdmcpWriteCARD32 (&factory->priv->buf, send_sessid);
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)));
2750
gdm_xdmcp_handle_keepalive (GdmXdmcpDisplayFactory *factory,
2751
GdmAddress *address,
2759
gdm_address_get_numeric_info (address, &host, NULL);
2760
g_debug ("GdmXdmcpDisplayFactory: Got KEEPALIVE from %s",
2761
host ? host : "(null)");
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)");
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");
2781
if G_UNLIKELY (! XdmcpReadCARD32 (&factory->priv->buf, &clnt_sessid)) {
2782
g_warning (_("%s: Could not read Session ID"),
2783
"gdm_xdmcp_handle_keepalive");
2787
gdm_xdmcp_send_alive (factory, address, clnt_dspnum, clnt_sessid);
2791
opcode_string (int opcode)
2793
static const char * const opcode_names[] = {
2810
static const char * const gdm_opcode_names[] = {
2812
"GOT_MANAGED_FORWARD"
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];
2827
decode_packet (GIOChannel *source,
2829
GdmXdmcpDisplayFactory *factory)
2831
struct sockaddr_storage clnt_ss;
2832
GdmAddress *address;
2839
g_debug ("GdmXdmcpDisplayFactory: decode_packet: GIOCondition %d", (int)cond);
2841
if ( ! (cond & G_IO_IN)) {
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!");
2850
ss_len = (int)gdm_sockaddr_len (&clnt_ss);
2852
res = XdmcpReadHeader (&factory->priv->buf, &header);
2853
if G_UNLIKELY (! res) {
2854
g_warning (_("GdmXdmcpDisplayFactory: Could not read XDMCP header!"));
2858
if G_UNLIKELY (header.version != XDM_PROTOCOL_VERSION &&
2859
header.version != GDM_XDMCP_PROTOCOL_VERSION) {
2860
g_warning (_("XMDCP: Incorrect XDMCP version!"));
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"));
2870
gdm_address_debug (address);
2874
gdm_address_get_numeric_info (address, &host, &port);
2876
g_debug ("GdmXdmcpDisplayFactory: Received opcode %s from client %s : %s",
2877
opcode_string (header.opcode),
2878
host ? host : "(null)",
2879
port ? port : "(null)");
2881
switch (header.opcode) {
2882
case BROADCAST_QUERY:
2883
gdm_xdmcp_handle_broadcast_query (factory, address, header.length);
2887
gdm_xdmcp_handle_query (factory, address, header.length);
2890
case INDIRECT_QUERY:
2891
gdm_xdmcp_handle_indirect_query (factory, address, header.length);
2895
gdm_xdmcp_handle_forward_query (factory, address, header.length);
2899
gdm_xdmcp_handle_request (factory, address, header.length);
2903
gdm_xdmcp_handle_manage (factory, address, header.length);
2907
gdm_xdmcp_handle_keepalive (factory, address, header.length);
2910
case GDM_XDMCP_MANAGED_FORWARD:
2911
gdm_xdmcp_handle_managed_forward (factory, address, header.length);
2914
case GDM_XDMCP_GOT_MANAGED_FORWARD:
2915
gdm_xdmcp_handle_got_managed_forward (factory, address, header.length);
2919
g_debug ("GdmXdmcpDisplayFactory: Unknown opcode from client %s : %s",
2920
host ? host : "(null)",
2921
port ? port : "(null)");
2929
gdm_address_free (address);
2935
gdm_xdmcp_display_factory_start (GdmDisplayFactory *base_factory)
2939
GdmXdmcpDisplayFactory *factory = GDM_XDMCP_DISPLAY_FACTORY (base_factory);
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);
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));
2967
ret = open_port (factory);
2972
g_debug ("GdmXdmcpDisplayFactory: Starting to listen on XDMCP port");
2974
ioc = g_io_channel_unix_new (factory->priv->socket_fd);
2976
g_io_channel_set_encoding (ioc, NULL, NULL);
2977
g_io_channel_set_buffered (ioc, FALSE);
2979
factory->priv->socket_watch_id = g_io_add_watch_full (ioc,
2981
G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
2982
(GIOFunc)decode_packet,
2985
g_io_channel_unref (ioc);
2991
gdm_xdmcp_display_factory_stop (GdmDisplayFactory *base_factory)
2993
GdmXdmcpDisplayFactory *factory = GDM_XDMCP_DISPLAY_FACTORY (base_factory);
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);
2998
if (factory->priv->socket_watch_id > 0) {
2999
g_source_remove (factory->priv->socket_watch_id);
3000
factory->priv->socket_watch_id = 0;
3003
if (factory->priv->socket_fd > 0) {
3004
VE_IGNORE_EINTR (close (factory->priv->socket_fd));
3005
factory->priv->socket_fd = -1;
3012
gdm_xdmcp_display_factory_set_port (GdmXdmcpDisplayFactory *factory,
3015
g_return_if_fail (GDM_IS_XDMCP_DISPLAY_FACTORY (factory));
3017
factory->priv->port = port;
3021
gdm_xdmcp_display_factory_set_use_multicast (GdmXdmcpDisplayFactory *factory,
3022
gboolean use_multicast)
3024
g_return_if_fail (GDM_IS_XDMCP_DISPLAY_FACTORY (factory));
3026
factory->priv->use_multicast = use_multicast;
3030
gdm_xdmcp_display_factory_set_multicast_address (GdmXdmcpDisplayFactory *factory,
3031
const char *address)
3033
g_return_if_fail (GDM_IS_XDMCP_DISPLAY_FACTORY (factory));
3035
g_free (factory->priv->multicast_address);
3036
factory->priv->multicast_address = g_strdup (address);
3040
gdm_xdmcp_display_factory_set_honor_indirect (GdmXdmcpDisplayFactory *factory,
3041
gboolean honor_indirect)
3043
g_return_if_fail (GDM_IS_XDMCP_DISPLAY_FACTORY (factory));
3045
factory->priv->honor_indirect = honor_indirect;
3049
gdm_xdmcp_display_factory_set_max_displays_per_host (GdmXdmcpDisplayFactory *factory,
3052
g_return_if_fail (GDM_IS_XDMCP_DISPLAY_FACTORY (factory));
3054
factory->priv->max_displays_per_host = num;
3058
gdm_xdmcp_display_factory_set_max_displays (GdmXdmcpDisplayFactory *factory,
3061
g_return_if_fail (GDM_IS_XDMCP_DISPLAY_FACTORY (factory));
3063
factory->priv->max_displays = num;
3067
gdm_xdmcp_display_factory_set_max_pending_displays (GdmXdmcpDisplayFactory *factory,
3070
g_return_if_fail (GDM_IS_XDMCP_DISPLAY_FACTORY (factory));
3072
factory->priv->max_pending_displays = num;
3076
gdm_xdmcp_display_factory_set_max_wait (GdmXdmcpDisplayFactory *factory,
3079
g_return_if_fail (GDM_IS_XDMCP_DISPLAY_FACTORY (factory));
3081
factory->priv->max_wait = num;
3085
gdm_xdmcp_display_factory_set_max_wait_indirect (GdmXdmcpDisplayFactory *factory,
3088
g_return_if_fail (GDM_IS_XDMCP_DISPLAY_FACTORY (factory));
3090
factory->priv->max_wait_indirect = num;
3094
gdm_xdmcp_display_factory_set_willing_script (GdmXdmcpDisplayFactory *factory,
3097
g_return_if_fail (GDM_IS_XDMCP_DISPLAY_FACTORY (factory));
3099
g_free (factory->priv->willing_script);
3100
factory->priv->willing_script = g_strdup (script);
3104
gdm_xdmcp_display_factory_set_property (GObject *object,
3106
const GValue *value,
3109
GdmXdmcpDisplayFactory *self;
3111
self = GDM_XDMCP_DISPLAY_FACTORY (object);
3115
gdm_xdmcp_display_factory_set_port (self, g_value_get_uint (value));
3117
case PROP_USE_MULTICAST:
3118
gdm_xdmcp_display_factory_set_use_multicast (self, g_value_get_boolean (value));
3120
case PROP_MULTICAST_ADDRESS:
3121
gdm_xdmcp_display_factory_set_multicast_address (self, g_value_get_string (value));
3123
case PROP_HONOR_INDIRECT:
3124
gdm_xdmcp_display_factory_set_honor_indirect (self, g_value_get_boolean (value));
3126
case PROP_MAX_DISPLAYS_PER_HOST:
3127
gdm_xdmcp_display_factory_set_max_displays_per_host (self, g_value_get_uint (value));
3129
case PROP_MAX_DISPLAYS:
3130
gdm_xdmcp_display_factory_set_max_displays (self, g_value_get_uint (value));
3132
case PROP_MAX_PENDING_DISPLAYS:
3133
gdm_xdmcp_display_factory_set_max_pending_displays (self, g_value_get_uint (value));
3136
gdm_xdmcp_display_factory_set_max_wait (self, g_value_get_uint (value));
3138
case PROP_MAX_WAIT_INDIRECT:
3139
gdm_xdmcp_display_factory_set_max_wait_indirect (self, g_value_get_uint (value));
3141
case PROP_WILLING_SCRIPT:
3142
gdm_xdmcp_display_factory_set_willing_script (self, g_value_get_string (value));
3145
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3151
gdm_xdmcp_display_factory_get_property (GObject *object,
3156
GdmXdmcpDisplayFactory *self;
3158
self = GDM_XDMCP_DISPLAY_FACTORY (object);
3162
g_value_set_uint (value, self->priv->port);
3164
case PROP_USE_MULTICAST:
3165
g_value_set_boolean (value, self->priv->use_multicast);
3167
case PROP_MULTICAST_ADDRESS:
3168
g_value_set_string (value, self->priv->multicast_address);
3170
case PROP_HONOR_INDIRECT:
3171
g_value_set_boolean (value, self->priv->honor_indirect);
3173
case PROP_MAX_DISPLAYS_PER_HOST:
3174
g_value_set_uint (value, self->priv->max_displays_per_host);
3176
case PROP_MAX_DISPLAYS:
3177
g_value_set_uint (value, self->priv->max_displays);
3179
case PROP_MAX_PENDING_DISPLAYS:
3180
g_value_set_uint (value, self->priv->max_pending_displays);
3183
g_value_set_uint (value, self->priv->max_wait);
3185
case PROP_MAX_WAIT_INDIRECT:
3186
g_value_set_uint (value, self->priv->max_wait_indirect);
3188
case PROP_WILLING_SCRIPT:
3189
g_value_set_string (value, self->priv->willing_script);
3192
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3198
gdm_xdmcp_display_factory_class_init (GdmXdmcpDisplayFactoryClass *klass)
3200
GObjectClass *object_class = G_OBJECT_CLASS (klass);
3201
GdmDisplayFactoryClass *factory_class = GDM_DISPLAY_FACTORY_CLASS (klass);
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;
3207
factory_class->start = gdm_xdmcp_display_factory_start;
3208
factory_class->stop = gdm_xdmcp_display_factory_stop;
3210
g_object_class_install_property (object_class,
3212
g_param_spec_uint ("port",
3218
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
3219
g_object_class_install_property (object_class,
3221
g_param_spec_boolean ("use-multicast",
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",
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",
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",
3254
DEFAULT_MAX_DISPLAYS_PER_HOST,
3255
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
3256
g_object_class_install_property (object_class,
3258
g_param_spec_uint ("max-displays",
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",
3272
DEFAULT_MAX_PENDING_DISPLAYS,
3273
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
3274
g_object_class_install_property (object_class,
3276
g_param_spec_uint ("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",
3290
DEFAULT_MAX_WAIT_INDIRECT,
3291
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
3293
g_type_class_add_private (klass, sizeof (GdmXdmcpDisplayFactoryPrivate));
3297
gdm_xdmcp_display_factory_init (GdmXdmcpDisplayFactory *factory)
3300
struct utsname name;
3302
factory->priv = GDM_XDMCP_DISPLAY_FACTORY_GET_PRIVATE (factory);
3304
factory->priv->socket_fd = -1;
3306
factory->priv->session_serial = g_random_int ();
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");
3316
factory->priv->sysid = g_strconcat (name.sysname,
3321
factory->priv->hostname = g_strdup (hostbuf);
3323
factory->priv->servhost.data = (CARD8 *) g_strdup (hostbuf);
3324
factory->priv->servhost.length = strlen ((char *) factory->priv->servhost.data);
3328
gdm_xdmcp_display_factory_finalize (GObject *object)
3330
GdmXdmcpDisplayFactory *factory;
3332
g_return_if_fail (object != NULL);
3333
g_return_if_fail (GDM_IS_XDMCP_DISPLAY_FACTORY (object));
3335
factory = GDM_XDMCP_DISPLAY_FACTORY (object);
3337
g_return_if_fail (factory->priv != NULL);
3339
if (factory->priv->socket_watch_id > 0) {
3340
g_source_remove (factory->priv->socket_watch_id);
3343
if (factory->priv->socket_fd > 0) {
3344
close (factory->priv->socket_fd);
3345
factory->priv->socket_fd = -1;
3348
g_slist_free (factory->priv->forward_queries);
3349
g_slist_free (factory->priv->managed_forwards);
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);
3356
/* FIXME: Free servhost */
3358
G_OBJECT_CLASS (gdm_xdmcp_display_factory_parent_class)->finalize (object);
3361
GdmXdmcpDisplayFactory *
3362
gdm_xdmcp_display_factory_new (GdmDisplayStore *store)
3364
if (xdmcp_display_factory_object != NULL) {
3365
g_object_ref (xdmcp_display_factory_object);
3367
xdmcp_display_factory_object = g_object_new (GDM_TYPE_XDMCP_DISPLAY_FACTORY,
3368
"display-store", store,
3370
g_object_add_weak_pointer (xdmcp_display_factory_object,
3371
(gpointer *) &xdmcp_display_factory_object);
3374
return GDM_XDMCP_DISPLAY_FACTORY (xdmcp_display_factory_object);