diff options
Diffstat (limited to 'daemon/xdmcp.c')
-rw-r--r-- | daemon/xdmcp.c | 2788 |
1 files changed, 0 insertions, 2788 deletions
diff --git a/daemon/xdmcp.c b/daemon/xdmcp.c deleted file mode 100644 index 42062d80..00000000 --- a/daemon/xdmcp.c +++ /dev/null @@ -1,2788 +0,0 @@ -/* GDM - The GNOME Display Manager - * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* This file contains the XDMCP implementation for managing remote - * displays. - */ - -/* Theory of operation: - * - * Process idles waiting for UDP packets on port 177. - * Incoming packets are decoded and checked against tcp_wrapper. - * - * A typical session looks like this: - * - * Display sends Query/BroadcastQuery to Manager. - * - * Manager selects an appropriate authentication scheme from the - * display's list of supported ones and sends Willing/Unwilling. - * - * Assuming the display accepts the auth. scheme it sends back a - * Request. - * - * If the manager accepts to service the display (i.e. loadavg is low) - * it sends back an Accept containing a unique SessionID. The - * SessionID is stored in an accept queue by the Manager. Should the - * manager refuse to start a session a Decline is sent to the display. - * - * The display returns a Manage request containing the supplied - * SessionID. The manager will then start a session on the display. In - * case the SessionID is not on the accept queue the manager returns - * Refuse. If the manager fails to open the display for connections - * Failed is returned. - * - * During the session the display periodically sends KeepAlive packets - * to the manager. The manager responds with Alive. - * - * Similarly the manager xpings the display once in a while and shuts - * down the connection on failure. - * - */ - -#include "config.h" - -#ifdef HAVE_LIBXDMCP -#include <stdio.h> -#include <unistd.h> -#include <time.h> -#include <stdlib.h> -#include <syslog.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <errno.h> -#include <X11/Xlib.h> -#include <X11/Xmd.h> -#include <X11/Xdmcp.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <netdb.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/utsname.h> -#include <sys/ioctl.h> -#include <net/if.h> -#include <fcntl.h> -#ifdef HAVE_SYS_SOCKIO_H -#include <sys/sockio.h> -#endif - -#ifdef HAVE_TCPWRAPPERS - #include <tcpd.h> -#endif -#endif /* HAVE_LIBXDMCP */ - -#include <glib/gi18n.h> - -#ifdef HAVE_LIBXDMCP -#include "gdm.h" -#include "display.h" -#include "auth.h" -#endif /* HAVE_LIBXDMCP */ - -#include "misc.h" -#include "choose.h" -#include "xdmcp.h" -#include "cookie.h" -#include "gdmconfig.h" - -#define XDMCP_MULTICAST_ADDRESS "ff02::1" /*This is to be changed when the Xdmcp Multicast address is decided */ - -int gdm_xdmcpfd = -1; - -#ifdef HAVE_LIBXDMCP - -/* TCP Wrapper syslog control */ -gint allow_severity = LOG_INFO; -gint deny_severity = LOG_WARNING; - -static guint xdmcp_source = 0; -static CARD32 globsessid; -static gchar *sysid; -static ARRAY8 servhost; -static XdmcpBuffer buf; -static gboolean initted = FALSE; - -extern GSList *displays; -extern gint xdmcp_pending; -extern gint xdmcp_sessions; - -/* Local prototypes */ -static gboolean gdm_xdmcp_decode_packet (GIOChannel *source, - GIOCondition cond, - gpointer data); -/*************************** IPv6 specific prototypes *****************************/ - -#ifdef ENABLE_IPV6 -static void gdm_xdmcp_handle_query (struct sockaddr_storage *clnt_sa, - gint len, - gint type); -static void gdm_xdmcp_handle_forward_query (struct sockaddr_storage *clnt_sa, gint len); -static void gdm_xdmcp_handle_request (struct sockaddr_storage *clnt_sa, gint len); -static void gdm_xdmcp_handle_manage (struct sockaddr_storage *clnt_sa, gint len); -static void gdm_xdmcp_handle_managed_forward (struct sockaddr_storage *clnt_sa, gint len); -static void gdm_xdmcp_handle_got_managed_forward (struct sockaddr_storage *clnt_sa, gint len); -static void gdm_xdmcp_handle_keepalive (struct sockaddr_storage *clnt_sa, gint len); -static void gdm_xdmcp_send_willing (struct sockaddr_storage *clnt_sa); -static void gdm_xdmcp_send_unwilling (struct sockaddr_storage *clnt_sa, gint type); -static void gdm_xdmcp_send_accept (GdmHostent *he, struct sockaddr_storage *clnt_sa, - gint displaynum); -static void gdm_xdmcp_send_decline (struct sockaddr_storage *clnt_sa, const char *reason); -static void gdm_xdmcp_send_refuse (struct sockaddr_storage *clnt_sa, CARD32 sessid); -static void gdm_xdmcp_send_failed (struct sockaddr_storage *clnt_sa, CARD32 sessid); -static void gdm_xdmcp_send_alive (struct sockaddr_storage *clnt_sa, CARD16 dspnum, CARD32 sessid); -static void gdm_xdmcp_send_managed_forward (struct sockaddr_storage *clnt_sa, - struct sockaddr_storage *origin); -static void gdm_xdmcp_send_forward_query6 (GdmIndirectDisplay *id, - struct sockaddr_in6 *clnt_sa, - struct in6_addr *display_addr, - ARRAYofARRAY8Ptr authlist); -static gboolean gdm_xdmcp_host_allow (struct sockaddr_storage *clnt_sa); -static GdmForwardQuery * gdm_forward_query_alloc (struct sockaddr_storage *mgr_sa, - struct sockaddr_storage *dsp_sa); -static GdmForwardQuery * gdm_forward_query_lookup (struct sockaddr_storage *clnt_sa); -static void gdm_xdmcp_whack_queued_managed_forwards6 (struct sockaddr_in6 *clnt_sa, - struct in6_addr *origin); -static void gdm_xdmcp_send_got_managed_forward6 (struct sockaddr_in6 *clnt_sa, - struct in6_addr *origin); -static int gdm_xdmcp_displays_from_host (struct sockaddr_storage *addr); -static GdmDisplay *gdm_xdmcp_display_lookup_by_host (struct sockaddr_storage *addr, int dspnum); -static GdmDisplay *gdm_xdmcp_display_alloc (struct sockaddr_storage *addr, GdmHostent *he, int displaynum); - -#else - -static void gdm_xdmcp_handle_forward_query (struct sockaddr_in *clnt_sa, gint len); -static void gdm_xdmcp_handle_query (struct sockaddr_in *clnt_sa, - gint len, - gint type); - static void gdm_xdmcp_handle_request (struct sockaddr_in *clnt_sa, gint len); - static void gdm_xdmcp_handle_manage (struct sockaddr_in *clnt_sa, gint len); - static void gdm_xdmcp_handle_managed_forward (struct sockaddr_in *clnt_sa, gint len); - static void gdm_xdmcp_handle_got_managed_forward (struct sockaddr_in *clnt_sa, gint len); - static void gdm_xdmcp_handle_keepalive (struct sockaddr_in *clnt_sa, gint len); - static void gdm_xdmcp_send_willing (struct sockaddr_in *clnt_sa); - static void gdm_xdmcp_send_unwilling (struct sockaddr_in *clnt_sa, gint type); - static void gdm_xdmcp_send_accept (GdmHostent *he /* eaten and freed */, - struct sockaddr_in *clnt_sa, - int displaynum); -static void gdm_xdmcp_send_decline (struct sockaddr_in *clnt_sa, const char *reason); - static void gdm_xdmcp_send_refuse (struct sockaddr_in *clnt_sa, CARD32 sessid); - static void gdm_xdmcp_send_failed (struct sockaddr_in *clnt_sa, CARD32 sessid); - static void gdm_xdmcp_send_alive (struct sockaddr_in *clnt_sa, CARD16 dspnum, CARD32 sessid); - static void gdm_xdmcp_send_managed_forward (struct sockaddr_in *clnt_sa, - struct sockaddr_in *origin); - static gboolean gdm_xdmcp_host_allow (struct sockaddr_in *clnt_sa); -static GdmForwardQuery * gdm_forward_query_alloc (struct sockaddr_in *mgr_sa, - struct sockaddr_in *dsp_sa); -static GdmForwardQuery * gdm_forward_query_lookup (struct sockaddr_in *clnt_sa); -static int gdm_xdmcp_displays_from_host (struct sockaddr_in *addr); -static GdmDisplay *gdm_xdmcp_display_lookup_by_host (struct sockaddr_in *addr, int dspnum); -static GdmDisplay *gdm_xdmcp_display_alloc (struct sockaddr_in *addr, GdmHostent *he, int displaynum); - -#endif /*IPv4 / IPv6*/ - -static void gdm_xdmcp_whack_queued_managed_forwards (struct sockaddr_in *clnt_sa, - struct in_addr *origin); -static void gdm_xdmcp_send_got_managed_forward (struct sockaddr_in *clnt_sa, - struct in_addr *origin); -static void gdm_xdmcp_send_forward_query (GdmIndirectDisplay *id, - struct sockaddr_in *clnt_sa, - struct in_addr *display_addr, - ARRAYofARRAY8Ptr authlist); -static void gdm_xdmcp_whack_queued_managed_forwards (struct sockaddr_in *clnt_sa, - struct in_addr *origin); -static void gdm_xdmcp_send_got_managed_forward (struct sockaddr_in *clnt_sa, - struct in_addr *origin); -static GdmDisplay *gdm_xdmcp_display_lookup (CARD32 sessid); -static void gdm_xdmcp_display_dispose_check (const gchar *hostname, int dspnum); -static void gdm_xdmcp_displays_check (void); -static void gdm_forward_query_dispose (GdmForwardQuery *q); - -static GSList *forward_queries = NULL; - -typedef struct { - int times; - guint handler; -#ifdef ENABLE_IPV6 - struct sockaddr_storage manager; - struct sockaddr_storage origin; -#else - struct sockaddr_in manager; - struct sockaddr_in origin; -#endif -} ManagedForward; -#define MANAGED_FORWARD_INTERVAL 1500 /* 1.5 seconds */ - -static GSList *managed_forwards = NULL; - - -/* - * We don't support XDM-AUTHENTICATION-1 and XDM-AUTHORIZATION-1. - * - * The latter would be quite useful to avoid sending unencrypted - * cookies over the wire. Unfortunately it isn't supported without - * XDM-AUTHENTICATION-1 which requires a key database with private - * keys from all X terminals on your LAN. Fun, fun, fun. - * - * Furthermore user passwords go over the wire in cleartext anyway so - * protecting cookies is not that important. - */ - -typedef struct _XdmAuth { - ARRAY8 authentication; - ARRAY8 authorization; -} XdmAuthRec, *XdmAuthPtr; - -static XdmAuthRec serv_authlist = { - { (CARD16) 0, (CARD8 *) 0 }, - { (CARD16) 0, (CARD8 *) 0 } -}; - -#ifdef ENABLE_IPV6 -static gboolean have_ipv6 (void) -{ - int s; - - s = socket (AF_INET6, SOCK_STREAM, 0); - if (s != -1) { - VE_IGNORE_EINTR (close (s)); - return TRUE; - } - - return FALSE; -} -#endif - -static int -#ifdef ENABLE_IPV6 -gdm_xdmcp_displays_from_host (struct sockaddr_storage *addr) -#else -gdm_xdmcp_displays_from_host (struct sockaddr_in *addr) -#endif -{ - GSList *li; - int count = 0; - - for (li = displays; li != NULL; li = li->next) { - GdmDisplay *disp = li->data; - if (SERVER_IS_XDMCP (disp)) { -#ifdef ENABLE_IPV6 - if (disp->addrtype == AF_INET6 && - memcmp (&disp->addr6, &((struct sockaddr_in6 *)addr)->sin6_addr, sizeof (struct in6_addr)) == 0) - count++; - else -#endif - if (disp->addrtype == AF_INET && - memcmp (&disp->addr, &((struct sockaddr_in *)addr)->sin_addr, sizeof (struct in_addr)) == 0) - count++; - } - } - - return count; -} - -static GdmDisplay * -#ifdef ENABLE_IPV6 -gdm_xdmcp_display_lookup_by_host (struct sockaddr_storage *addr, int dspnum) -#else -gdm_xdmcp_display_lookup_by_host (struct sockaddr_in *addr, int dspnum) -#endif -{ - GSList *li; - - for (li = displays; li != NULL; li = li->next) { - GdmDisplay *disp = li->data; - if (SERVER_IS_XDMCP (disp)) { -#ifdef ENABLE_IPV6 - if (disp->addrtype == AF_INET6) { - if ((memcmp (&disp->addr6, &((struct sockaddr_in6 *)addr)->sin6_addr, sizeof (struct in6_addr)) == 0) && disp->xdmcp_dispnum == dspnum) - return disp; - } - else -#endif - if ((memcmp (&disp->addr, &((struct sockaddr_in *)addr)->sin_addr, sizeof (struct in_addr)) == 0) && disp->xdmcp_dispnum == dspnum) - return disp; - } - } - - return NULL; -} - - -gboolean -gdm_xdmcp_init (void) -{ -#ifdef ENABLE_IPV6 - struct sockaddr_storage serv_sa = {0}; -#else - struct sockaddr_in serv_sa = {0}; -#endif - gint addrlen; - gchar hostbuf[1024]; - struct utsname name; - int udpport = gdm_get_value_int (GDM_KEY_UDP_PORT); - - if ( ! gdm_get_value_bool (GDM_KEY_XDMCP)) - return TRUE; - - globsessid = g_random_int (); - - /* Fetch and store local hostname in XDMCP friendly format */ - hostbuf[1023] = '\0'; - if G_UNLIKELY (gethostname (hostbuf, 1023) != 0) { - gdm_error (_("%s: Could not get server hostname: %s!"), - "gdm_xdmcp_init", strerror (errno)); - strcmp (hostbuf, "localhost.localdomain"); - } - - if ( ! initted) { - uname (&name); - sysid = g_strconcat (name.sysname, " ", name.release, NULL); - - servhost.data = (CARD8 *) g_strdup (hostbuf); - servhost.length = strlen ((char *) servhost.data); - - initted = TRUE; - } - - gdm_debug ("XDMCP: Start up on host %s, port %d", hostbuf, udpport); - - /* Open socket for communications */ -#ifdef ENABLE_IPV6 - gdm_xdmcpfd = socket (AF_INET6, SOCK_DGRAM, 0); /* UDP */ - if (gdm_xdmcpfd < 0) -#endif - gdm_xdmcpfd = socket (AF_INET, SOCK_DGRAM, 0); /* UDP */ - - if G_UNLIKELY (gdm_xdmcpfd < 0) { - gdm_error (_("%s: Could not create socket!"), "gdm_xdmcp_init"); - gdm_set_value_bool (GDM_KEY_XDMCP, FALSE); - return FALSE; - } - -#ifdef ENABLE_IPV6 - if (have_ipv6 ()) { - ((struct sockaddr_in6 *)(&serv_sa))->sin6_family = AF_INET6; - ((struct sockaddr_in6 *)(&serv_sa))->sin6_port = htons (udpport); /* UDP 177 */ - ((struct sockaddr_in6 *)(&serv_sa))->sin6_addr = in6addr_any; - addrlen = sizeof (struct sockaddr_in6); - - /* Checking and Setting Multicast options */ - if (gdm_get_value_bool (GDM_KEY_MULTICAST)) { - int socktemp; /* temporary socket for getting info about available interfaces*/ - int i, num; - char *buf; - struct ipv6_mreq mreq; - - /* For interfaces' list */ - struct ifconf ifc; - struct ifreq *ifr; - - /* Extract Multicast address for IPv6 */ - if (ve_string_empty (gdm_get_value_string (GDM_KEY_MULTICAST_ADDR))) { - - /* Stuff it with all-node multicast address */ - gdm_set_value_string (GDM_KEY_MULTICAST_ADDR, XDMCP_MULTICAST_ADDRESS); - } - - socktemp = socket (AF_INET, SOCK_DGRAM, 0); -#ifdef SIOCGIFNUM - if (ioctl (socktemp, SIOCGIFNUM, &num) < 0) { - num = 64; - } -#else - num = 64; -#endif - ifc.ifc_len = sizeof (struct ifreq) * num; - ifc.ifc_buf = buf = malloc (ifc.ifc_len); - if (ioctl (socktemp, SIOCGIFCONF, &ifc) >= 0) { - ifr = ifc.ifc_req; - num = ifc.ifc_len / sizeof (struct ifreq); /* No of interfaces */ - - /* Joining multicast group with all interfaces*/ - for (i = 0 ; i < num ; i++) { - struct ifreq ifreq; - int ifindex; - - memset (&ifreq, 0, sizeof (ifreq)); - strncpy (ifreq.ifr_name, ifr[i].ifr_name, sizeof (ifreq.ifr_name)); - /* paranoia */ - ifreq.ifr_name[sizeof (ifreq.ifr_name) - 1] = '\0'; - - if (ioctl (socktemp, SIOCGIFFLAGS, &ifreq) < 0) - gdm_debug ("XDMCP: Could not get SIOCGIFFLAGS for %s", ifr[i].ifr_name); - - ifindex = if_nametoindex (ifr[i].ifr_name); - - if ((!(ifreq.ifr_flags & IFF_UP) || - (ifreq.ifr_flags & IFF_LOOPBACK)) || - ((ifindex == 0 ) && (errno == ENXIO))) { - /* Not a valid interface or loopback interface*/ - continue; - } - - mreq.ipv6mr_interface = ifindex; - inet_pton (AF_INET6, gdm_get_value_string (GDM_KEY_MULTICAST_ADDR), &mreq.ipv6mr_multiaddr); - setsockopt (gdm_xdmcpfd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof (mreq)); - } - } - g_free (buf); - close (socktemp); - } - } - else -#endif - { - ((struct sockaddr_in *)(&serv_sa))->sin_family = AF_INET; - ((struct sockaddr_in *)(&serv_sa))->sin_port = htons (udpport); /* UDP 177 */ - ((struct sockaddr_in *)(&serv_sa))->sin_addr.s_addr = htonl (INADDR_ANY); - addrlen = sizeof (struct sockaddr_in); - } - - if G_UNLIKELY (bind (gdm_xdmcpfd, (struct sockaddr*) &serv_sa, addrlen) == -1) { - gdm_error (_("%s: Could not bind to XDMCP socket!"), "gdm_xdmcp_init"); - gdm_xdmcp_close (); - gdm_set_value_bool (GDM_KEY_XDMCP, FALSE); - return FALSE; - } - - return TRUE; -} - - -void -gdm_xdmcp_run (void) -{ - GIOChannel *xdmcpchan; - - xdmcpchan = g_io_channel_unix_new (gdm_xdmcpfd); - g_io_channel_set_encoding (xdmcpchan, NULL, NULL); - g_io_channel_set_buffered (xdmcpchan, FALSE); - - xdmcp_source = g_io_add_watch_full - (xdmcpchan, G_PRIORITY_DEFAULT, - G_IO_IN|G_IO_PRI|G_IO_ERR|G_IO_HUP|G_IO_NVAL, - gdm_xdmcp_decode_packet, NULL, NULL); - g_io_channel_unref (xdmcpchan); -} - - -void -gdm_xdmcp_close (void) -{ - if (xdmcp_source > 0) { - g_source_remove (xdmcp_source); - xdmcp_source = 0; - } - - if (gdm_xdmcpfd > 0) { - VE_IGNORE_EINTR (close (gdm_xdmcpfd)); - gdm_xdmcpfd = -1; - } -} - - -static gboolean -gdm_xdmcp_decode_packet (GIOChannel *source, GIOCondition cond, gpointer data) -{ -#ifdef ENABLE_IPV6 - struct sockaddr_storage clnt_sa; -#else - struct sockaddr_in clnt_sa; -#endif - gint sa_len = sizeof (clnt_sa); - XdmcpHeader header; - static const char * const opcode_names[] = { - NULL, - "BROADCAST_QUERY", "QUERY", "INDIRECT_QUERY", "FORWARD_QUERY", - "WILLING", "UNWILLING", "REQUEST", "ACCEPT", "DECLINE", "MANAGE", "REFUSE", - "FAILED", "KEEPALIVE", "ALIVE" - }; - static const char * const gdm_opcode_names[] = { - "MANAGED_FORWARD", "GOT_MANAGED_FORWARD" - }; - - /* packets come at somewhat random times */ - gdm_random_tick (); - - if (cond != G_IO_IN) - gdm_debug ("gdm_xdmcp_decode_packet: GIOCondition %d", (int)cond); - - if ( ! (cond & G_IO_IN)) - return TRUE; - - if G_UNLIKELY (!XdmcpFill (gdm_xdmcpfd, &buf, (XdmcpNetaddr)&clnt_sa, &sa_len)) { - gdm_debug (_("%s: Could not create XDMCP buffer!"), - "gdm_xdmcp_decode_packet"); - return TRUE; - } - - if G_UNLIKELY (!XdmcpReadHeader (&buf, &header)) { - gdm_error (_("%s: Could not read XDMCP header!"), - "gdm_xdmcp_decode_packet"); - return TRUE; - } - - if G_UNLIKELY (header.version != XDM_PROTOCOL_VERSION && - header.version != GDM_XDMCP_PROTOCOL_VERSION) { - gdm_error (_("%s: Incorrect XDMCP version!"), - "gdm_xdmcp_decode_packet"); - return TRUE; - } - - if (header.opcode <= ALIVE) { -#ifdef ENABLE_IPV6 - if (clnt_sa.ss_family == AF_INET6) { - char buffer6[INET6_ADDRSTRLEN]; - - gdm_debug ("gdm_xdmcp_decode: Received opcode %s from client %s", opcode_names[header.opcode], inet_ntop (AF_INET6, &((struct sockaddr_in6 *)(&clnt_sa))->sin6_addr, buffer6, INET6_ADDRSTRLEN)); - } - else -#endif - { - gdm_debug ("gdm_xdmcp_decode: Received opcode %s from client %s", opcode_names[header.opcode], inet_ntoa (((struct sockaddr_in *)(&clnt_sa))->sin_addr)); - } - } - - if (header.opcode >= GDM_XDMCP_FIRST_OPCODE && - header.opcode < GDM_XDMCP_LAST_OPCODE) { -#ifdef ENABLE_IPV6 - if (clnt_sa.ss_family == AF_INET6) { - - char buffer6[INET6_ADDRSTRLEN]; - - gdm_debug ("gdm_xdmcp_decode: Received opcode %s from client %s", gdm_opcode_names[header.opcode - GDM_XDMCP_FIRST_OPCODE], inet_ntop (AF_INET6, &((struct sockaddr_in6 *)(&clnt_sa))->sin6_addr, buffer6, INET6_ADDRSTRLEN)); - } - else -#endif - { - char buffer[INET_ADDRSTRLEN]; - - gdm_debug ("gdm_xdmcp_decode: Received opcode %s from client %s", gdm_opcode_names[header.opcode - GDM_XDMCP_FIRST_OPCODE], inet_ntop (AF_INET, &((struct sockaddr_in *)(&clnt_sa))->sin_addr, buffer, INET_ADDRSTRLEN)); - } - } - - switch (header.opcode) { - - case BROADCAST_QUERY: - gdm_xdmcp_handle_query (&clnt_sa, header.length, BROADCAST_QUERY); - break; - - case QUERY: - gdm_xdmcp_handle_query (&clnt_sa, header.length, QUERY); - break; - - case INDIRECT_QUERY: - gdm_xdmcp_handle_query (&clnt_sa, header.length, INDIRECT_QUERY); - break; - - case FORWARD_QUERY: - gdm_xdmcp_handle_forward_query (&clnt_sa, header.length); - break; - - case REQUEST: - gdm_xdmcp_handle_request (&clnt_sa, header.length); - break; - - case MANAGE: - gdm_xdmcp_handle_manage (&clnt_sa, header.length); - break; - - case KEEPALIVE: - gdm_xdmcp_handle_keepalive (&clnt_sa, header.length); - break; - - case GDM_XDMCP_MANAGED_FORWARD: - gdm_xdmcp_handle_managed_forward (&clnt_sa, header.length); - break; - - case GDM_XDMCP_GOT_MANAGED_FORWARD: - gdm_xdmcp_handle_got_managed_forward (&clnt_sa, header.length); - break; - - default: -#ifdef ENABLE_IPV6 - if (clnt_sa.ss_family == AF_INET6) { - char buffer6[INET6_ADDRSTRLEN]; - - gdm_error (_("%s: Unknown opcode from host %s"), - "gdm_xdmcp_decode_packet", - inet_ntop (AF_INET6, &(((struct sockaddr_in6 *)(&clnt_sa))->sin6_addr), buffer6, INET6_ADDRSTRLEN)); - } - else -#endif - { - gdm_error (_("%s: Unknown opcode from host %s"), - "gdm_xdmcp_decode_packet", - inet_ntoa (((struct sockaddr_in *)(&clnt_sa))->sin_addr)); - } - break; - } - - return TRUE; -} - -static void -#ifdef ENABLE_IPV6 -gdm_xdmcp_handle_query (struct sockaddr_storage *clnt_sa, gint len, gint type) -#else -gdm_xdmcp_handle_query (struct sockaddr_in *clnt_sa, gint len, gint type) -#endif -{ - ARRAYofARRAY8 clnt_authlist; - gint i = 0, explen = 1; - -#ifdef ENABLE_IPV6 - if (clnt_sa->ss_family == AF_INET6) { - char buffer6[INET6_ADDRSTRLEN]; - - gdm_debug ("gdm_xdmcp_handle_query: Opcode %d from %s", type, inet_ntop (AF_INET6, &((struct sockaddr_in6 *)(clnt_sa))->sin6_addr, buffer6, INET6_ADDRSTRLEN)); - } - else -#endif - { - gdm_debug ("gdm_xdmcp_handle_query: Opcode %d from %s", type, inet_ntoa (((struct sockaddr_in *)(clnt_sa))->sin_addr)); - } - - /* Extract array of authentication names from Xdmcp packet */ - if G_UNLIKELY (! XdmcpReadARRAYofARRAY8 (&buf, &clnt_authlist)) { - gdm_error (_("%s: Could not extract authlist from packet"), - "gdm_xdmcp_handle_query"); - return; - } - - /* Crude checksumming */ - for (i = 0 ; i < clnt_authlist.length ; i++) { - if G_UNLIKELY (gdm_get_value_bool (GDM_KEY_DEBUG)) { - char *s = g_strndup ((char *) clnt_authlist.data[i].data, clnt_authlist.length); - gdm_debug ("gdm_xdmcp_handle_query: authlist: %s", ve_sure_string (s)); - g_free (s); - } - explen += 2+clnt_authlist.data[i].length; - } - - if G_UNLIKELY (len != explen) { - gdm_error (_("%s: Error in checksum"), - "gdm_xdmcp_handle_query"); - XdmcpDisposeARRAYofARRAY8 (&clnt_authlist); - return; - } - - /* Check with tcp_wrappers if client is allowed to access */ - if (gdm_xdmcp_host_allow (clnt_sa)) { - - /* If this is an INDIRECT_QUERY, try to look up the display in - * the pending list. If found send a FORWARD_QUERY to the - * chosen manager. Otherwise alloc a new indirect display. */ - - if (gdm_get_value_bool (GDM_KEY_INDIRECT) && - type == INDIRECT_QUERY) { - GdmIndirectDisplay *id = gdm_choose_indirect_lookup (clnt_sa); - - if (id != NULL && ( -#ifdef ENABLE_IPV6 - (id->chosen_host6 != NULL) || -#endif - (id->chosen_host != NULL))) - { - /* if user chose us, then just send willing */ - if ((((struct sockaddr_in *)clnt_sa)->sin_family == AF_INET && gdm_is_local_addr ((struct in_addr *)(id->chosen_host))) -#ifdef ENABLE_IPV6 - || (clnt_sa->ss_family == AF_INET6 && gdm_is_local_addr6 ((struct in6_addr *)(id->chosen_host6))) -#endif - ) { - - /* get rid of indirect, so that we don't get - * the chooser */ - gdm_choose_indirect_dispose (id); - gdm_xdmcp_send_willing (clnt_sa); - } - else - if ((((struct sockaddr_in *)clnt_sa)->sin_family == AF_INET && gdm_is_loopback_addr (&(((struct sockaddr_in *)clnt_sa)->sin_addr))) -#ifdef ENABLE_IPV6 - || (clnt_sa->ss_family == AF_INET6 && gdm_is_loopback_addr6 (&(((struct sockaddr_in6 *)clnt_sa)->sin6_addr))) -#endif - ) { - - /* woohoo! fun, I have no clue how to get - * the correct ip, SO I just send forward - * queries with all the different IPs */ - const GList *list = gdm_peek_local_address_list (); - - while (list != NULL) { - struct sockaddr *saddr = (struct sockaddr *)(list->data); -#ifdef ENABLE_IPV6 - struct in6_addr *addr6; -#endif - struct in_addr *addr; - -#ifdef ENABLE_IPV6 - if (saddr->sa_family == AF_INET6) { - addr6 = &(((struct sockaddr_in6 *)saddr)->sin6_addr); - if ( ! gdm_is_loopback_addr6 (addr6)) { - /* forward query to * chosen host */ - gdm_xdmcp_send_forward_query6 (id, (struct sockaddr_in6 *)clnt_sa, addr6, &clnt_authlist); - } - } - else -#endif - { - addr = &(((struct sockaddr_in *)saddr)->sin_addr); - if ( ! gdm_is_loopback_addr (addr)) { - /* forward query to * chosen host */ - gdm_xdmcp_send_forward_query (id, (struct sockaddr_in *)clnt_sa, addr, &clnt_authlist); - } - - } - - list = list->next; - } - } else { - /* or send forward query to chosen host */ - gdm_xdmcp_send_forward_query - (id, (struct sockaddr_in *)clnt_sa, - &(((struct sockaddr_in *)clnt_sa)->sin_addr), - &clnt_authlist); - } - } else if (id == NULL) { - id = gdm_choose_indirect_alloc (clnt_sa); - if (id != NULL) { - gdm_xdmcp_send_willing (clnt_sa); - } - } else { - gdm_xdmcp_send_willing (clnt_sa); - } - } else { - gdm_xdmcp_send_willing (clnt_sa); - } - } else if (type == QUERY) { - /* unwilling is ONLY sent for direct queries, never for broadcast - * nor indirects */ - gdm_xdmcp_send_unwilling (clnt_sa, type); - } - - /* Dispose authlist from remote display */ - XdmcpDisposeARRAYofARRAY8 (&clnt_authlist); -} - -#ifdef ENABLE_IPV6 -static void -gdm_xdmcp_send_forward_query6 (GdmIndirectDisplay *id, struct sockaddr_in6 *clnt_sa, struct in6_addr *display_addr, ARRAYofARRAY8Ptr authlist) -{ - struct sockaddr_in6 sock = {0}; - XdmcpHeader header; - int i, authlen; - ARRAY8 address; - ARRAY8 port; - char buffer6[INET6_ADDRSTRLEN]; - - g_assert (id != NULL); - g_assert (id->chosen_host != NULL); - - gdm_debug ("gdm_xdmcp_send_forward_query6: Sending forward query to %s", inet_ntop (AF_INET6, &(id->chosen_host6), buffer6, sizeof (buffer6))); - gdm_debug ("gdm_xdmcp_send_forward_query6: Query contains %s:%d", inet_ntop (AF_INET6, display_addr, buffer6, sizeof (buffer6)), (int) ntohs (clnt_sa->sin6_port)); - - authlen = 1; - for (i = 0 ; i < authlist->length ; i++) { - authlen += 2 + authlist->data[i].length; - } - - /* we depend on this being 2 elsewhere as well */ - port.length = 2; - port.data = g_new (char, 2); - memcpy (port.data, &(clnt_sa->sin6_port), 2); - address.length = sizeof (struct in6_addr); - address.data = (void *)g_new (struct in6_addr, 1); - memcpy (address.data, display_addr, sizeof (struct in6_addr)); - - - header.opcode = (CARD16) FORWARD_QUERY; - header.length = authlen; - header.length += 2 + address.length; - header.length += 2 + port.length; - header.version = XDM_PROTOCOL_VERSION; - XdmcpWriteHeader (&buf, &header); - - XdmcpWriteARRAY8 (&buf, &address); - XdmcpWriteARRAY8 (&buf, &port); - XdmcpWriteARRAYofARRAY8 (&buf, authlist); - - memset (&sock, 0, sizeof (sock)); - - sock.sin6_family = AF_INET6; - sock.sin6_port = htons (XDM_UDP_PORT); - memcpy (sock.sin6_addr.s6_addr, id->chosen_host6->s6_addr, sizeof (struct in6_addr)); - XdmcpFlush (gdm_xdmcpfd, &buf, (XdmcpNetaddr) &sock, (int)sizeof (struct sockaddr_in6)); - g_free (port.data); - g_free (address.data); -} -#endif - -static void -gdm_xdmcp_send_forward_query (GdmIndirectDisplay *id, - struct sockaddr_in *clnt_sa, - struct in_addr *display_addr, - ARRAYofARRAY8Ptr authlist) -{ - struct sockaddr_in sock = {0}; - XdmcpHeader header; - int i, authlen; - ARRAY8 address; - ARRAY8 port; - - gdm_assert (id != NULL); - gdm_assert (id->chosen_host != NULL); - - gdm_debug ("gdm_xdmcp_send_forward_query: Sending forward query to %s", - inet_ntoa (*id->chosen_host)); - gdm_debug ("gdm_xdmcp_send_forward_query: Query contains %s:%d", - inet_ntoa (*display_addr), - (int) ntohs (clnt_sa->sin_port)); - - authlen = 1; - for (i = 0 ; i < authlist->length ; i++) { - authlen += 2 + authlist->data[i].length; - } - - /* we depend on this being 2 elsewhere as well */ - port.length = 2; - port.data = (CARD8 *) g_new (char, 2); - memcpy (port.data, &(clnt_sa->sin_port), 2); - - address.length = sizeof (struct in_addr); - address.data = (void *)g_new (struct in_addr, 1); - memcpy (address.data, display_addr, sizeof (struct in_addr)); - - header.opcode = (CARD16) FORWARD_QUERY; - header.length = authlen; - header.length += 2 + address.length; - header.length += 2 + port.length; - header.version = XDM_PROTOCOL_VERSION; - XdmcpWriteHeader (&buf, &header); - - XdmcpWriteARRAY8 (&buf, &address); - XdmcpWriteARRAY8 (&buf, &port); - XdmcpWriteARRAYofARRAY8 (&buf, authlist); - - sock.sin_family = AF_INET; - sock.sin_port = htons (XDM_UDP_PORT); - sock.sin_addr.s_addr = id->chosen_host->s_addr; - XdmcpFlush (gdm_xdmcpfd, &buf, (XdmcpNetaddr) &sock, - (int)sizeof (struct sockaddr_in)); - - g_free (port.data); - g_free (address.data); -} - -static gboolean -remove_oldest_forward (void) -{ - GSList *li; - GdmForwardQuery *oldest = NULL; - - for (li = forward_queries; li != NULL; li = li->next) { - GdmForwardQuery *query = li->data; - - if (oldest == NULL || - query->acctime < oldest->acctime) { - oldest = query; - } - } - - if (oldest != NULL) { - gdm_forward_query_dispose (oldest); - return TRUE; - } else { - return FALSE; - } -} - -static GdmForwardQuery * -#ifdef ENABLE_IPV6 -gdm_forward_query_alloc (struct sockaddr_storage *mgr_sa, - struct sockaddr_storage *dsp_sa) -#else -gdm_forward_query_alloc (struct sockaddr_in *mgr_sa, - struct sockaddr_in *dsp_sa) -#endif -{ - GdmForwardQuery *q; - int count; - - count = g_slist_length (forward_queries); - - while (count > GDM_MAX_FORWARD_QUERIES && - remove_oldest_forward ()) - count --; - - q = g_new0 (GdmForwardQuery, 1); -#ifdef ENABLE_IPV6 - q->dsp_sa = g_new0 (struct sockaddr_storage, 1); - memcpy (q->dsp_sa, dsp_sa, sizeof (struct sockaddr_storage)); - q->from_sa = g_new0 (struct sockaddr_storage, 1); - memcpy (q->from_sa, mgr_sa, sizeof (struct sockaddr_storage)); -#else - q->dsp_sa = g_new0 (struct sockaddr_in, 1); - memcpy (q->dsp_sa, dsp_sa, sizeof (struct sockaddr_in)); - q->from_sa = g_new0 (struct sockaddr_in, 1); - memcpy (q->from_sa, mgr_sa, sizeof (struct sockaddr_in)); -#endif - - forward_queries = g_slist_prepend (forward_queries, q); - - return q; -} - -static GdmForwardQuery * -#ifdef ENABLE_IPV6 -gdm_forward_query_lookup (struct sockaddr_storage *clnt_sa) -#else -gdm_forward_query_lookup (struct sockaddr_in *clnt_sa) -#endif -{ - GSList *li, *qlist; - GdmForwardQuery *q; - time_t curtime = time (NULL); - - qlist = g_slist_copy (forward_queries); - - for (li = qlist; li != NULL; li = li->next) { - q = (GdmForwardQuery *) li->data; - if (q == NULL) - continue; -#ifdef ENABLE_IPV6 - if (clnt_sa->ss_family == AF_INET6) { - if (memcmp (((struct sockaddr_in6 *)(q->dsp_sa))->sin6_addr.s6_addr, ((struct sockaddr_in6 *)clnt_sa)->sin6_addr.s6_addr, sizeof (struct in6_addr)) == 0) { - g_slist_free (qlist); - return q; - } - - if (q->acctime > 0 && curtime > q->acctime + GDM_FORWARD_QUERY_TIMEOUT) { - char buffer6[INET6_ADDRSTRLEN]; - - gdm_debug ("gdm_forward_query_lookup: Disposing stale forward query from %s", inet_ntop (AF_INET6, &((struct sockaddr_in6 *)q->dsp_sa)->sin6_addr, buffer6, INET6_ADDRSTRLEN)); - gdm_forward_query_dispose (q); - continue; - } - } - else -#endif - { - if (((struct sockaddr_in *)(q->dsp_sa))->sin_addr.s_addr == ((struct sockaddr_in *)clnt_sa)->sin_addr.s_addr) { - g_slist_free (qlist); - return q; - } - - if (q->acctime > 0 && - curtime > q->acctime + GDM_FORWARD_QUERY_TIMEOUT) { - gdm_debug ("gdm_forward_query_lookup: Disposing stale forward query from %s", - inet_ntoa (((struct sockaddr_in*)q->dsp_sa)->sin_addr)); - gdm_forward_query_dispose (q); - continue; - } - } - - } - g_slist_free (qlist); - -#ifdef ENABLE_IPV6 - if (clnt_sa->ss_family == AF_INET6) { - char buffer6[INET6_ADDRSTRLEN]; - - gdm_debug ("gdm_forward_query_lookup: Host %s not found", inet_ntop (AF_INET6, &((struct sockaddr_in6 *)clnt_sa)->sin6_addr, buffer6, INET6_ADDRSTRLEN)); - } - else -#endif - { - gdm_debug ("gdm_forward_query_lookup: Host %s not found", - inet_ntoa (((struct sockaddr_in *)clnt_sa)->sin_addr)); - } - - return NULL; -} - - -static void -gdm_forward_query_dispose (GdmForwardQuery *q) -{ - if (q == NULL) - return; - - forward_queries = g_slist_remove (forward_queries, q); - - q->acctime = 0; - -#ifdef ENABLE_IPV6 - if (q->dsp_sa->ss_family == AF_INET6) { - char buffer6[INET6_ADDRSTRLEN]; - - gdm_debug ("gdm_forward_query_dispose: Disposing %s", inet_ntop (AF_INET6, &(((struct sockaddr_in6 *)(q->dsp_sa))->sin6_addr), buffer6, INET6_ADDRSTRLEN)); - } - else -#endif - { - gdm_debug ("gdm_forward_query_dispose: Disposing %s", - inet_ntoa (((struct sockaddr_in *)(q->dsp_sa))->sin_addr)); - } - - g_free (q->dsp_sa); - q->dsp_sa = NULL; - g_free (q->from_sa); - q->from_sa = NULL; - - g_free (q); -} - - -static void -#ifdef ENABLE_IPV6 -gdm_xdmcp_handle_forward_query (struct sockaddr_storage *clnt_sa, gint len) -#else -gdm_xdmcp_handle_forward_query (struct sockaddr_in *clnt_sa, gint len) -#endif -{ - ARRAY8 clnt_addr; - ARRAY8 clnt_port; - ARRAYofARRAY8 clnt_authlist; - gint i = 0, explen = 1; -#ifdef ENABLE_IPV6 - struct sockaddr_storage disp_sa = {0}; -#else - struct sockaddr_in disp_sa = {0}; -#endif - - /* Check with tcp_wrappers if client is allowed to access */ - if (! gdm_xdmcp_host_allow (clnt_sa)) { -#ifdef ENABLE_IPV6 - if (clnt_sa->ss_family == AF_INET6) { - char buffer6[INET6_ADDRSTRLEN]; - - gdm_error ("%s: Got FORWARD_QUERY from banned host %s", - "gdm_xdmcp_handle_forward query", - inet_ntop (AF_INET6, &(((struct sockaddr_in6 *)clnt_sa)->sin6_addr), buffer6, INET6_ADDRSTRLEN)); - } - else -#endif - { - gdm_error ("%s: Got FORWARD_QUERY from banned host %s", - "gdm_xdmcp_handle_forward query", - inet_ntoa (((struct sockaddr_in *)clnt_sa)->sin_addr)); - } - - return; - } - - /* Read display address */ - if G_UNLIKELY (! XdmcpReadARRAY8 (&buf, &clnt_addr)) { - gdm_error (_("%s: Could not read display address"), - "gdm_xdmcp_handle_forward_query"); - return; - } - - /* Read display port */ - if G_UNLIKELY (! XdmcpReadARRAY8 (&buf, &clnt_port)) { - XdmcpDisposeARRAY8 (&clnt_addr); - gdm_error (_("%s: Could not read display port number"), - "gdm_xdmcp_handle_forward_query"); - return; - } - - /* Extract array of authentication names from Xdmcp packet */ - if G_UNLIKELY (! XdmcpReadARRAYofARRAY8 (&buf, &clnt_authlist)) { - XdmcpDisposeARRAY8 (&clnt_addr); - XdmcpDisposeARRAY8 (&clnt_port); - gdm_error (_("%s: Could not extract authlist from packet"), - "gdm_xdmcp_handle_forward_query"); - return; - } - - /* Crude checksumming */ - explen = 1; - explen += 2+clnt_addr.length; - explen += 2+clnt_port.length; - - for (i = 0 ; i < clnt_authlist.length ; i++) { - if G_UNLIKELY (gdm_get_value_bool (GDM_KEY_DEBUG)) { - char *s = g_strndup ((char *) clnt_authlist.data[i].data, clnt_authlist.length); - gdm_debug ("gdm_xdmcp_handle_forward_query: authlist: %s", ve_sure_string (s)); - g_free (s); - } - explen += 2+clnt_authlist.data[i].length; - } - - if G_UNLIKELY (len != explen) { - gdm_error (_("%s: Error in checksum"), - "gdm_xdmcp_handle_forward_query"); - goto out; - } - -#ifdef ENABLE_IPV6 - if (clnt_sa->ss_family == AF_INET6) { - char buffer6[INET6_ADDRSTRLEN]; - - struct in6_addr ipv6_addr; - struct in6_addr * ipv6_addr_ptr = NULL; - - if (clnt_port.length == 2 && - clnt_addr.length == 4) { - char * ipv4_addr; - - /* Convert IPv4 address to IPv6 if needed */ - struct sockaddr_in tmp_disp_sa = {0}; - ((struct sockaddr_in *)(&tmp_disp_sa))->sin_family = AF_INET; - memcpy (&((struct sockaddr_in *)(&tmp_disp_sa))->sin_port, clnt_port.data, 2); - memcpy (&((struct sockaddr_in *)(&tmp_disp_sa))->sin_addr.s_addr, clnt_addr.data, 4); - - ipv4_addr = inet_ntoa (((struct sockaddr_in *)(&tmp_disp_sa))->sin_addr); - strcpy (buffer6, "::ffff:"); - strncat (buffer6, ipv4_addr, INET_ADDRSTRLEN); - - inet_pton (AF_INET6, buffer6, &ipv6_addr); - ipv6_addr_ptr = &ipv6_addr; - - } else if (clnt_port.length == 2 && - clnt_addr.length == 16) { - - ipv6_addr_ptr = (struct in6_addr *)clnt_addr.data; - - } else { - - gdm_error (_("%s: Bad address"), - "gdm_xdmcp_handle_forward_query"); - goto out; - } - - g_assert (16 == sizeof (struct in6_addr)); - - gdm_xdmcp_whack_queued_managed_forwards6 ((struct sockaddr_in6 *)clnt_sa, ipv6_addr_ptr); - - ((struct sockaddr_in6 *)(&disp_sa))->sin6_family = AF_INET6; - - /* Find client port number */ - memcpy (&((struct sockaddr_in6 *)(&disp_sa))->sin6_port, clnt_port.data, 2); - - /* Find client address */ - memcpy (&((struct sockaddr_in6 *)(&disp_sa))->sin6_addr.s6_addr, ipv6_addr_ptr, 16); - - gdm_debug ("gdm_xdmcp_handle_forward_query: Got FORWARD_QUERY for display: %s, port %d", inet_ntop (AF_INET6, &((struct sockaddr_in6 *)(&disp_sa))->sin6_addr, buffer6, INET6_ADDRSTRLEN), ntohs (((struct sockaddr_in6 *)(&disp_sa))->sin6_port)); - } - else -#endif - { - if (clnt_port.length != 2 || - clnt_addr.length != 4) { - gdm_error (_("%s: Bad address"), - "gdm_xdmcp_handle_forward_query"); - goto out; - } - - g_assert (4 == sizeof (struct in_addr)); - gdm_xdmcp_whack_queued_managed_forwards ((struct sockaddr_in *)clnt_sa, (struct in_addr *)clnt_addr.data); - ((struct sockaddr_in *)(&disp_sa))->sin_family = AF_INET; - /* Find client port number */ - memcpy (&((struct sockaddr_in *)(&disp_sa))->sin_port, clnt_port.data, 2); - /* Find client address */ - memcpy (&((struct sockaddr_in *)(&disp_sa))->sin_addr.s_addr, clnt_addr.data, 4); - gdm_debug ("gdm_xdmcp_handle_forward_query: Got FORWARD_QUERY for display: %s, port %d", inet_ntoa (((struct sockaddr_in *)(&disp_sa))->sin_addr), ntohs (((struct sockaddr_in *)(&disp_sa))->sin_port)); - } - - - - - - /* Check with tcp_wrappers if display is allowed to access */ - if (gdm_xdmcp_host_allow (&disp_sa)) { - GdmForwardQuery *q; - - q = gdm_forward_query_lookup (&disp_sa); - if (q != NULL) - gdm_forward_query_dispose (q); - gdm_forward_query_alloc (clnt_sa, &disp_sa); - - gdm_xdmcp_send_willing (&disp_sa); - } - - out: - /* Cleanup */ - XdmcpDisposeARRAYofARRAY8 (&clnt_authlist); - XdmcpDisposeARRAY8 (&clnt_port); - XdmcpDisposeARRAY8 (&clnt_addr); -} - - -static void -#ifdef ENABLE_IPV6 -gdm_xdmcp_send_willing (struct sockaddr_storage *clnt_sa) -#else -gdm_xdmcp_send_willing (struct sockaddr_in *clnt_sa) -#endif -{ - ARRAY8 status; - XdmcpHeader header; - static char *last_status = NULL; - static time_t last_willing = 0; - char *bin; - FILE *fd; - char *willing = gdm_get_value_string (GDM_KEY_WILLING); - int dispperhost = gdm_get_value_int (GDM_KEY_DISPLAYS_PER_HOST); - -#ifdef ENABLE_IPV6 - if (clnt_sa->ss_family == AF_INET6) { - char buffer6[INET6_ADDRSTRLEN]; - - gdm_debug ("gdm_xdmcp_send_willing: Sending WILLING to %s", inet_ntop (AF_INET6, &(((struct sockaddr_in6 *)clnt_sa)->sin6_addr), buffer6, INET6_ADDRSTRLEN)); - } - else -#endif - { - gdm_debug ("gdm_xdmcp_send_willing: Sending WILLING to %s", inet_ntoa (((struct sockaddr_in *)clnt_sa)->sin_addr)); - } - - if (last_willing == 0 || - time (NULL) - 3 > last_willing) { - char statusBuf[256] = ""; - bin = ve_first_word (willing); - if ( ! ve_string_empty (bin) && - g_access (bin, X_OK) == 0 && - (fd = popen (willing, "r")) != NULL) { - if (fgets (statusBuf, sizeof (statusBuf), fd) != NULL && - ! ve_string_empty (g_strstrip (statusBuf))) { - g_free (last_status); - last_status = g_strdup (statusBuf); - } else { - g_free (last_status); - last_status = g_strdup (sysid); - } - pclose (fd); - } else { - g_free (last_status); - last_status = g_strdup (sysid); - } - last_willing = time (NULL); - g_free (bin); - } -#ifdef ENABLE_IPV6 - if (clnt_sa->ss_family == AF_INET6) { - if ( ! gdm_is_local_addr6 (&(((struct sockaddr_in6 *)clnt_sa)->sin6_addr)) && - gdm_xdmcp_displays_from_host (clnt_sa) >= dispperhost) { - /* Don't translate, this goes over the wire to servers where we - * don't know the charset or language, so it must be ascii */ - status.data = (CARD8 *) g_strdup_printf ("%s (Server is busy)", last_status); - } else { - status.data = (CARD8 *) g_strdup (last_status); - } - } - else -#endif - { - if ( ! gdm_is_local_addr (&(((struct sockaddr_in *)clnt_sa)->sin_addr)) && - gdm_xdmcp_displays_from_host (clnt_sa) >= dispperhost) { - /* Don't translate, this goes over the wire to servers where we - * don't know the charset or language, so it must be ascii */ - status.data = (CARD8 *) g_strdup_printf ("%s (Server is busy)", last_status); - } else { - status.data = (CARD8 *) g_strdup (last_status); - } - } - - status.length = strlen ((char *) status.data); - - header.opcode = (CARD16) WILLING; - header.length = 6 + serv_authlist.authentication.length; - header.length += servhost.length + status.length; - header.version = XDM_PROTOCOL_VERSION; - XdmcpWriteHeader (&buf, &header); - - XdmcpWriteARRAY8 (&buf, &serv_authlist.authentication); /* Hardcoded authentication */ - XdmcpWriteARRAY8 (&buf, &servhost); - XdmcpWriteARRAY8 (&buf, &status); -#ifdef ENABLE_IPV6 - if (clnt_sa->ss_family == AF_INET6) { - XdmcpFlush (gdm_xdmcpfd, &buf, (XdmcpNetaddr)clnt_sa, (int)sizeof (struct sockaddr_in6)); - } - else -#endif - { - XdmcpFlush (gdm_xdmcpfd, &buf, (XdmcpNetaddr)clnt_sa, (int)sizeof (struct sockaddr_in)); - } - - g_free (status.data); -} - -static void -#ifdef ENABLE_IPV6 -gdm_xdmcp_send_unwilling (struct sockaddr_storage *clnt_sa, gint type) -#else -gdm_xdmcp_send_unwilling (struct sockaddr_in *clnt_sa, gint type) -#endif -{ - ARRAY8 status; - XdmcpHeader header; - static time_t last_time = 0; - - /* only send at most one packet per second, - no harm done if we don't send it at all */ - if (last_time + 1 >= time (NULL)) - return; - -#ifdef ENABLE_IPV6 - if (clnt_sa->ss_family == AF_INET6) { - char buffer6[INET6_ADDRSTRLEN]; - - gdm_debug ("gdm_xdmcp_send_unwilling: Sending UNWILLING to %s", inet_ntop (AF_INET6, &(((struct sockaddr_in6 *)clnt_sa)->sin6_addr), buffer6, INET6_ADDRSTRLEN)); - gdm_error (_("Denied XDMCP query from host %s"), buffer6); - } - else -#endif - { - gdm_debug ("gdm_xdmcp_send_unwilling: Sending UNWILLING to %s", inet_ntoa (((struct sockaddr_in *)clnt_sa)->sin_addr)); - - gdm_error (_("Denied XDMCP query from host %s"), inet_ntoa (((struct sockaddr_in *)clnt_sa)->sin_addr)); - } - - /* Don't translate, this goes over the wire to servers where we - * don't know the charset or language, so it must be ascii */ - status.data = (CARD8 *) "Display not authorized to connect"; - status.length = strlen ((char *) status.data); - - header.opcode = (CARD16) UNWILLING; - header.length = 4 + servhost.length + status.length; - header.version = XDM_PROTOCOL_VERSION; - XdmcpWriteHeader (&buf, &header); - - XdmcpWriteARRAY8 (&buf, &servhost); - XdmcpWriteARRAY8 (&buf, &status); -#ifdef ENABLE_IPV6 - if (clnt_sa->ss_family == AF_INET6) { - XdmcpFlush (gdm_xdmcpfd, &buf, (XdmcpNetaddr)clnt_sa, (int)sizeof (struct sockaddr_in6)); - } - else -#endif - { - XdmcpFlush (gdm_xdmcpfd, &buf, (XdmcpNetaddr)clnt_sa, (int)sizeof (struct sockaddr_in)); - } - - last_time = time (NULL); -} - -static void -#ifdef ENABLE_IPV6 -gdm_xdmcp_really_send_managed_forward (struct sockaddr_storage *clnt_sa, - struct sockaddr_storage *origin) -#else -gdm_xdmcp_really_send_managed_forward (struct sockaddr_in *clnt_sa, - struct sockaddr_in *origin) -#endif -{ - ARRAY8 address; - XdmcpHeader header; - struct in_addr addr; - -#ifdef ENABLE_IPV6 - struct in6_addr addr6; - - if (clnt_sa->ss_family == AF_INET6) { - char buffer6[INET6_ADDRSTRLEN]; - - gdm_debug ("gdm_xdmcp_really_send_managed_forward: " - "Sending MANAGED_FORWARD to %s", - inet_ntop (AF_INET6, &(((struct sockaddr_in6 *)clnt_sa)->sin6_addr), buffer6, INET6_ADDRSTRLEN)); - - address.length = sizeof (struct in6_addr); - address.data = (void *)&addr6; - memcpy (address.data, &(((struct sockaddr_in6 *)origin)->sin6_addr), sizeof (struct in6_addr)); - } - else -#endif - { - gdm_debug ("gdm_xdmcp_really_send_managed_forward: " - "Sending MANAGED_FORWARD to %s", - inet_ntoa (((struct sockaddr_in *)clnt_sa)->sin_addr)); - - address.length = sizeof (struct in_addr); - address.data = (void *)&addr; - memcpy (address.data, &(((struct sockaddr_in *)origin)->sin_addr), sizeof (struct in_addr)); - } - - header.opcode = (CARD16) GDM_XDMCP_MANAGED_FORWARD; - header.length = 4 + address.length; - header.version = GDM_XDMCP_PROTOCOL_VERSION; - XdmcpWriteHeader (&buf, &header); - - XdmcpWriteARRAY8 (&buf, &address); -#ifdef ENABLE_IPV6 - if (clnt_sa->ss_family == AF_INET6) { - XdmcpFlush (gdm_xdmcpfd, &buf, (XdmcpNetaddr)clnt_sa, (int)sizeof (struct sockaddr_in6)); - } - else -#endif - { - XdmcpFlush (gdm_xdmcpfd, &buf, (XdmcpNetaddr)clnt_sa, (int)sizeof (struct sockaddr_in)); - } - -} - -static gboolean -managed_forward_handler (gpointer data) -{ - ManagedForward *mf = data; - if (gdm_xdmcpfd > 0) - gdm_xdmcp_really_send_managed_forward (&(mf->manager), - &(mf->origin)); - mf->times++; - if (gdm_xdmcpfd <= 0 || mf->times >= 2) { - managed_forwards = g_slist_remove (managed_forwards, mf); - mf->handler = 0; - /* mf freed by glib */ - return FALSE; - } - return TRUE; -} - -static void -#ifdef ENABLE_IPV6 -gdm_xdmcp_send_managed_forward (struct sockaddr_storage *clnt_sa, - struct sockaddr_storage *origin) -#else -gdm_xdmcp_send_managed_forward (struct sockaddr_in *clnt_sa, - struct sockaddr_in *origin) -#endif -{ - ManagedForward *mf; - - gdm_xdmcp_really_send_managed_forward (clnt_sa, origin); - - mf = g_new0 (ManagedForward, 1); - mf->times = 0; -#ifdef ENABLE_IPV6 - memcpy (&(mf->manager), clnt_sa, sizeof (struct sockaddr_storage)); - memcpy (&(mf->origin), origin, sizeof (struct sockaddr_storage)); -#else - memcpy (&(mf->manager), clnt_sa, sizeof (struct sockaddr_in)); - memcpy (&(mf->origin), origin, sizeof (struct sockaddr_in)); -#endif - - mf->handler = g_timeout_add_full (G_PRIORITY_DEFAULT, - MANAGED_FORWARD_INTERVAL, - managed_forward_handler, - mf, - (GDestroyNotify) g_free); - managed_forwards = g_slist_prepend (managed_forwards, mf); -} - -#ifdef ENABLE_IPV6 -static void -gdm_xdmcp_send_got_managed_forward6 (struct sockaddr_in6 *clnt_sa, - struct in6_addr *origin) -{ - ARRAY8 address; - XdmcpHeader header; - struct in6_addr addr; - char buffer6[INET6_ADDRSTRLEN]; - - gdm_debug ("gdm_xdmcp_send_managed_forward: " - "Sending GOT_MANAGED_FORWARD to %s", - inet_ntop (AF_INET6, &clnt_sa->sin6_addr, buffer6, INET6_ADDRSTRLEN)); - - address.length = sizeof (struct in6_addr); - address.data = (void *)&addr; - memcpy (address.data, origin, sizeof (struct in6_addr)); - - header.opcode = (CARD16) GDM_XDMCP_GOT_MANAGED_FORWARD; - header.length = 16 + address.length; - header.version = GDM_XDMCP_PROTOCOL_VERSION; - XdmcpWriteHeader (&buf, &header); - - XdmcpWriteARRAY8 (&buf, &address); - XdmcpFlush (gdm_xdmcpfd, &buf, (XdmcpNetaddr)clnt_sa, - (int)sizeof (struct sockaddr_in6)); -} -#endif - -static void -gdm_xdmcp_send_got_managed_forward (struct sockaddr_in *clnt_sa, - struct in_addr *origin) -{ - ARRAY8 address; - XdmcpHeader header; - struct in_addr addr; - - gdm_debug ("gdm_xdmcp_send_managed_forward: " - "Sending GOT_MANAGED_FORWARD to %s", - inet_ntoa (clnt_sa->sin_addr)); - - address.length = sizeof (struct in_addr); - address.data = (void *)&addr; - memcpy (address.data, origin, sizeof (struct in_addr)); - - header.opcode = (CARD16) GDM_XDMCP_GOT_MANAGED_FORWARD; - header.length = 4 + address.length; - header.version = GDM_XDMCP_PROTOCOL_VERSION; - XdmcpWriteHeader (&buf, &header); - - XdmcpWriteARRAY8 (&buf, &address); - XdmcpFlush (gdm_xdmcpfd, &buf, (XdmcpNetaddr)clnt_sa, - (int)sizeof (struct sockaddr_in)); -} - -static void -#ifdef ENABLE_IPV6 -gdm_xdmcp_handle_request (struct sockaddr_storage *clnt_sa, gint len) -#else -gdm_xdmcp_handle_request (struct sockaddr_in *clnt_sa, gint len) -#endif -{ - CARD16 clnt_dspnum; - ARRAY16 clnt_conntyp; - ARRAYofARRAY8 clnt_addr; - ARRAY8 clnt_authname; - ARRAY8 clnt_authdata; - ARRAYofARRAY8 clnt_authorization; - ARRAY8 clnt_manufacturer; - gint explen; - gint i; - gboolean mitauth = FALSE; - gboolean entered = FALSE; - int maxsessions = gdm_get_value_int (GDM_KEY_MAX_SESSIONS); - int maxpending = gdm_get_value_int (GDM_KEY_MAX_PENDING); - int dispperhost = gdm_get_value_int (GDM_KEY_DISPLAYS_PER_HOST); - -#ifdef ENABLE_IPV6 - char buffer6[INET6_ADDRSTRLEN]; - - inet_ntop (AF_INET6, &((struct sockaddr_in6 *)clnt_sa)->sin6_addr, buffer6, INET6_ADDRSTRLEN); - - if (clnt_sa->ss_family == AF_INET6) { - gdm_debug ("gdm_xdmcp_handle_request: Got REQUEST from %s",buffer6); - } - else -#endif - { - gdm_debug ("gdm_xdmcp_handle_request: Got REQUEST from %s", - inet_ntoa (((struct sockaddr_in *)clnt_sa)->sin_addr)); - } - - /* Check with tcp_wrappers if client is allowed to access */ - if (! gdm_xdmcp_host_allow (clnt_sa)) { -#ifdef ENABLE_IPV6 - if (clnt_sa->ss_family == AF_INET6) { - gdm_error (_("%s: Got REQUEST from banned host %s"), - "gdm_xdmcp_handle_request", - inet_ntop (AF_INET6, &((struct sockaddr_in6 *)clnt_sa)->sin6_addr, buffer6, INET6_ADDRSTRLEN)); - } - else -#endif - { - gdm_error (_("%s: Got REQUEST from banned host %s"), - "gdm_xdmcp_handle_request", - inet_ntoa (((struct sockaddr_in *)clnt_sa)->sin_addr)); - } - - return; - } - - gdm_xdmcp_displays_check (); /* Purge pending displays */ - - /* Remote display number */ - if G_UNLIKELY (! XdmcpReadCARD16 (&buf, &clnt_dspnum)) { - gdm_error (_("%s: Could not read Display Number"), - "gdm_xdmcp_handle_request"); - return; - } - - /* We don't care about connection type. Address says it all */ - if G_UNLIKELY (! XdmcpReadARRAY16 (&buf, &clnt_conntyp)) { - gdm_error (_("%s: Could not read Connection Type"), - "gdm_xdmcp_handle_request"); - return; - } - - /* This is TCP/IP - we don't care */ - if G_UNLIKELY (! XdmcpReadARRAYofARRAY8 (&buf, &clnt_addr)) { - gdm_error (_("%s: Could not read Client Address"), - "gdm_xdmcp_handle_request"); - XdmcpDisposeARRAY16 (&clnt_conntyp); - return; - } - - /* Read authentication type */ - if G_UNLIKELY (! XdmcpReadARRAY8 (&buf, &clnt_authname)) { - gdm_error (_("%s: Could not read Authentication Names"), - "gdm_xdmcp_handle_request"); - XdmcpDisposeARRAYofARRAY8 (&clnt_addr); - XdmcpDisposeARRAY16 (&clnt_conntyp); - return; - } - - /* Read authentication data */ - if G_UNLIKELY (! XdmcpReadARRAY8 (&buf, &clnt_authdata)) { - gdm_error (_("%s: Could not read Authentication Data"), - "gdm_xdmcp_handle_request"); - XdmcpDisposeARRAYofARRAY8 (&clnt_addr); - XdmcpDisposeARRAY16 (&clnt_conntyp); - XdmcpDisposeARRAY8 (&clnt_authname); - return; - } - - /* Read and select from supported authorization list */ - if G_UNLIKELY (! XdmcpReadARRAYofARRAY8 (&buf, &clnt_authorization)) { - gdm_error (_("%s: Could not read Authorization List"), - "gdm_xdmcp_handle_request"); - XdmcpDisposeARRAY8 (&clnt_authdata); - XdmcpDisposeARRAYofARRAY8 (&clnt_addr); - XdmcpDisposeARRAY16 (&clnt_conntyp); - XdmcpDisposeARRAY8 (&clnt_authname); - return; - } - - /* libXdmcp doesn't terminate strings properly so we cheat and use strncmp () */ - for (i = 0 ; i < clnt_authorization.length ; i++) - if (clnt_authorization.data[i].length == 18 && - strncmp ((char *) clnt_authorization.data[i].data, "MIT-MAGIC-COOKIE-1", 18) == 0) - mitauth = TRUE; - - /* Manufacturer ID */ - if G_UNLIKELY (! XdmcpReadARRAY8 (&buf, &clnt_manufacturer)) { - gdm_error (_("%s: Could not read Manufacturer ID"), - "gdm_xdmcp_handle_request"); - XdmcpDisposeARRAY8 (&clnt_authname); - XdmcpDisposeARRAY8 (&clnt_authdata); - XdmcpDisposeARRAYofARRAY8 (&clnt_addr); - XdmcpDisposeARRAYofARRAY8 (&clnt_authorization); - XdmcpDisposeARRAY16 (&clnt_conntyp); - return; - } - - /* Crude checksumming */ - explen = 2; /* Display Number */ - explen += 1+2*clnt_conntyp.length; /* Connection Type */ - explen += 1; /* Connection Address */ - for (i = 0 ; i < clnt_addr.length ; i++) - explen += 2+clnt_addr.data[i].length; - explen += 2+clnt_authname.length; /* Authentication Name */ - explen += 2+clnt_authdata.length; /* Authentication Data */ - explen += 1; /* Authorization Names */ - for (i = 0 ; i < clnt_authorization.length ; i++) - explen += 2+clnt_authorization.data[i].length; - explen += 2+clnt_manufacturer.length; - - if G_UNLIKELY (explen != len) { -#ifdef ENABLE_IPV6 - if (clnt_sa->ss_family == AF_INET6) { - gdm_error (_("%s: Failed checksum from %s"), - "gdm_xdmcp_handle_request", - inet_ntop (AF_INET6, &((struct sockaddr_in6 *)clnt_sa)->sin6_addr, buffer6, INET6_ADDRSTRLEN)); - } - else -#endif - { - gdm_error (_("%s: Failed checksum from %s"), - "gdm_xdmcp_handle_request", - inet_ntoa (((struct sockaddr_in *)clnt_sa)->sin_addr)); - } - - XdmcpDisposeARRAY8 (&clnt_authname); - XdmcpDisposeARRAY8 (&clnt_authdata); - XdmcpDisposeARRAY8 (&clnt_manufacturer); - XdmcpDisposeARRAYofARRAY8 (&clnt_addr); - XdmcpDisposeARRAYofARRAY8 (&clnt_authorization); - XdmcpDisposeARRAY16 (&clnt_conntyp); - return; - } - - if G_UNLIKELY (gdm_get_value_bool (GDM_KEY_DEBUG)) { - char *s = g_strndup ((char *) clnt_manufacturer.data, clnt_manufacturer.length); - gdm_debug ("gdm_xdmcp_handle_request: xdmcp_pending=%d, MaxPending=%d, xdmcp_sessions=%d, MaxSessions=%d, ManufacturerID=%s", - xdmcp_pending, maxpending, xdmcp_sessions, maxsessions, ve_sure_string (s)); - g_free (s); - } - - /* Check if ok to manage display */ -#ifdef ENABLE_IPV6 - if (clnt_sa->ss_family == AF_INET6) { - if (mitauth && - xdmcp_sessions < maxsessions && - (gdm_is_local_addr6 (&((struct sockaddr_in6 *)clnt_sa)->sin6_addr) || gdm_xdmcp_displays_from_host (clnt_sa) < dispperhost)) - - entered = TRUE; - } else -#endif - { - if (mitauth && - xdmcp_sessions < maxsessions && - (gdm_is_local_addr (&(((struct sockaddr_in *)clnt_sa)->sin_addr)) || - gdm_xdmcp_displays_from_host (clnt_sa) < dispperhost)) - - entered = TRUE; - } - - if (entered) { - GdmHostent *he; - he = gdm_gethostbyaddr (clnt_sa); - - /* Check if we are already talking to this host */ - gdm_xdmcp_display_dispose_check (he->hostname, clnt_dspnum); - - if (xdmcp_pending >= maxpending) { - gdm_debug ("gdm_xdmcp_handle_request: maximum pending"); - /* Don't translate, this goes over the wire to servers where we - * don't know the charset or language, so it must be ascii */ - gdm_xdmcp_send_decline (clnt_sa, "Maximum pending servers"); - gdm_hostent_free (he); - } else { - /* the addrs are NOT copied */ - gdm_xdmcp_send_accept (he /* eaten and freed */, clnt_sa, clnt_dspnum); - } - } else { - /* Don't translate, this goes over the wire to servers where we - * don't know the charset or language, so it must be ascii */ - if ( ! mitauth) { - gdm_xdmcp_send_decline (clnt_sa, "Only MIT-MAGIC-COOKIE-1 supported"); - } else if (xdmcp_sessions >= maxsessions) { - gdm_info ("Maximum number of open XDMCP sessions reached"); - gdm_xdmcp_send_decline (clnt_sa, "Maximum number of open sessions reached"); - } else { -#ifdef ENABLE_IPV6 - if (clnt_sa->ss_family == AF_INET6) - gdm_info ("Maximum number of open XDMCP sessions from host %s reached", buffer6); - else -#endif - gdm_info ("Maximum number of open XDMCP sessions from host %s reached", - inet_ntoa (((struct sockaddr_in *)clnt_sa)->sin_addr)); - gdm_xdmcp_send_decline (clnt_sa, "Maximum number of open sessions from your host reached"); - } - } - - XdmcpDisposeARRAY8 (&clnt_authname); - XdmcpDisposeARRAY8 (&clnt_authdata); - XdmcpDisposeARRAY8 (&clnt_manufacturer); - XdmcpDisposeARRAYofARRAY8 (&clnt_addr); - XdmcpDisposeARRAYofARRAY8 (&clnt_authorization); - XdmcpDisposeARRAY16 (&clnt_conntyp); -} - - -static void -gdm_xdmcp_send_accept (GdmHostent *he /* eaten and freed */, -#ifdef ENABLE_IPV6 - struct sockaddr_storage *clnt_sa, -#else - struct sockaddr_in *clnt_sa, -#endif - gint displaynum) -{ - XdmcpHeader header; - ARRAY8 authentype; - ARRAY8 authendata; - ARRAY8 authname; - ARRAY8 authdata; - GdmDisplay *d; - - d = gdm_xdmcp_display_alloc (clnt_sa, - he /* eaten and freed */, - displaynum); - - authentype.data = (CARD8 *) 0; - authentype.length = (CARD16) 0; - - authendata.data = (CARD8 *) 0; - authendata.length = (CARD16) 0; - - authname.data = (CARD8 *) "MIT-MAGIC-COOKIE-1"; - authname.length = strlen ((char *) authname.data); - - authdata.data = (CARD8 *) d->bcookie; - authdata.length = 16; - - header.version = XDM_PROTOCOL_VERSION; - header.opcode = (CARD16) ACCEPT; - header.length = 4; - header.length += 2 + authentype.length; - header.length += 2 + authendata.length; - header.length += 2 + authname.length; - header.length += 2 + authdata.length; - - XdmcpWriteHeader (&buf, &header); - - XdmcpWriteCARD32 (&buf, d->sessionid); - XdmcpWriteARRAY8 (&buf, &authentype); - XdmcpWriteARRAY8 (&buf, &authendata); - XdmcpWriteARRAY8 (&buf, &authname); - XdmcpWriteARRAY8 (&buf, &authdata); -#ifdef ENABLE_IPV6 - if (clnt_sa->ss_family == AF_INET6) { - char buffer6[INET6_ADDRSTRLEN]; - - XdmcpFlush (gdm_xdmcpfd, &buf, (XdmcpNetaddr)clnt_sa, - (int)sizeof (struct sockaddr_in6)); - - gdm_debug ("gdm_xdmcp_send_accept: Sending ACCEPT to %s with SessionID=%ld", inet_ntop (AF_INET6, &((struct sockaddr_in6 *)clnt_sa)->sin6_addr, buffer6, INET6_ADDRSTRLEN), (long)d->sessionid); - } - else -#endif - { - XdmcpFlush (gdm_xdmcpfd, &buf, (XdmcpNetaddr)clnt_sa, - (int)sizeof (struct sockaddr_in)); - - gdm_debug ("gdm_xdmcp_send_accept: Sending ACCEPT to %s with SessionID=%ld", - inet_ntoa (((struct sockaddr_in *)clnt_sa)->sin_addr), (long)d->sessionid); - } - -} - - -static void -#ifdef ENABLE_IPV6 -gdm_xdmcp_send_decline (struct sockaddr_storage *clnt_sa, const char *reason) -#else -gdm_xdmcp_send_decline (struct sockaddr_in *clnt_sa, const char *reason) -#endif -{ - XdmcpHeader header; - ARRAY8 authentype; - ARRAY8 authendata; - ARRAY8 status; - GdmForwardQuery *fq; - -#ifdef ENABLE_IPV6 - if (clnt_sa->ss_family == AF_INET6) { - char buffer6[INET6_ADDRSTRLEN]; - - gdm_debug ("gdm_xdmcp_send_decline: Sending DECLINE to %s", - inet_ntop (AF_INET6, &((struct sockaddr_in6 *)clnt_sa)->sin6_addr, buffer6, INET6_ADDRSTRLEN)); - } - else -#endif - { - gdm_debug ("gdm_xdmcp_send_decline: Sending DECLINE to %s", - inet_ntoa (((struct sockaddr_in *)clnt_sa)->sin_addr)); - } - - - authentype.data = (CARD8 *) 0; - authentype.length = (CARD16) 0; - - authendata.data = (CARD8 *) 0; - authendata.length = (CARD16) 0; - - status.data = (CARD8 *) reason; - status.length = strlen ((char *) status.data); - - header.version = XDM_PROTOCOL_VERSION; - header.opcode = (CARD16) DECLINE; - header.length = 2 + status.length; - header.length += 2 + authentype.length; - header.length += 2 + authendata.length; - XdmcpWriteHeader (&buf, &header); - - XdmcpWriteARRAY8 (&buf, &status); - XdmcpWriteARRAY8 (&buf, &authentype); - XdmcpWriteARRAY8 (&buf, &authendata); - -#ifdef ENABLE_IPV6 - if (clnt_sa->ss_family == AF_INET6) { - XdmcpFlush (gdm_xdmcpfd, &buf, (XdmcpNetaddr)clnt_sa, - (int)sizeof (struct sockaddr_in6)); - } - else -#endif - { - XdmcpFlush (gdm_xdmcpfd, &buf, (XdmcpNetaddr)clnt_sa, - (int)sizeof (struct sockaddr_in)); - } - - /* Send MANAGED_FORWARD to indicate that the connection - * reached some sort of resolution */ - fq = gdm_forward_query_lookup (clnt_sa); - if (fq != NULL) { - gdm_xdmcp_send_managed_forward (fq->from_sa, clnt_sa); - gdm_forward_query_dispose (fq); - } -} - - -static void -#ifdef ENABLE_IPV6 -gdm_xdmcp_handle_manage (struct sockaddr_storage *clnt_sa, gint len) -#else -gdm_xdmcp_handle_manage (struct sockaddr_in *clnt_sa, gint len) -#endif -{ - CARD32 clnt_sessid; - CARD16 clnt_dspnum; - ARRAY8 clnt_dspclass; - GdmDisplay *d; - GdmIndirectDisplay *id; - GdmForwardQuery *fq; - -#ifdef ENABLE_IPV6 - char buffer6[INET6_ADDRSTRLEN]; - - inet_ntop (AF_INET6, &((struct sockaddr_in6 *)clnt_sa)->sin6_addr, buffer6, INET6_ADDRSTRLEN); - - if (clnt_sa->ss_family == AF_INET6) { - gdm_debug ("gdm_xdmcp_handle_manage: Got MANAGE from %s", buffer6); - } - else -#endif - { - gdm_debug ("gdm_xdmcp_handle_manage: Got MANAGE from %s", inet_ntoa (((struct sockaddr_in *)clnt_sa)->sin_addr)); - } - - - /* Check with tcp_wrappers if client is allowed to access */ - if (! gdm_xdmcp_host_allow (clnt_sa)) { -#ifdef ENABLE_IPV6 - if (clnt_sa->ss_family == AF_INET6) { - gdm_error (_("%s: Got Manage from banned host %s"), - "gdm_xdmcp_handle_manage", - buffer6); - } - else -#endif - { - gdm_error (_("%s: Got Manage from banned host %s"), - "gdm_xdmcp_handle_manage", - inet_ntoa (((struct sockaddr_in *)clnt_sa)->sin_addr)); - } - - return; - } - - /* SessionID */ - if G_UNLIKELY (! XdmcpReadCARD32 (&buf, &clnt_sessid)) { - gdm_error (_("%s: Could not read Session ID"), - "gdm_xdmcp_handle_manage"); - return; - } - - /* Remote display number */ - if G_UNLIKELY (! XdmcpReadCARD16 (&buf, &clnt_dspnum)) { - gdm_error (_("%s: Could not read Display Number"), - "gdm_xdmcp_handle_manage"); - return; - } - - /* Display Class */ - if G_UNLIKELY (! XdmcpReadARRAY8 (&buf, &clnt_dspclass)) { - gdm_error (_("%s: Could not read Display Class"), - "gdm_xdmcp_handle_manage"); - return; - } - - if G_UNLIKELY (gdm_get_value_bool (GDM_KEY_DEBUG)) { - char *s = g_strndup ((char *) clnt_dspclass.data, clnt_dspclass.length); - -#ifdef ENABLE_IPV6 - if (clnt_sa->ss_family == AF_INET6) - gdm_debug ("gdm_xdmcp-handle_manage: Got display=%d, SessionID=%ld Class=%s from %s", (int)clnt_dspnum, (long)clnt_sessid, ve_sure_string (s), buffer6); - else -#endif - gdm_debug ("gdm_xdmcp_handle_manage: Got Display=%d, SessionID=%ld Class=%s from %s", - (int)clnt_dspnum, (long)clnt_sessid, ve_sure_string (s), inet_ntoa (((struct sockaddr_in *)clnt_sa)->sin_addr)); - - g_free (s); - } - - - d = gdm_xdmcp_display_lookup (clnt_sessid); - if (d != NULL && - d->dispstat == XDMCP_PENDING) { - - gdm_debug ("gdm_xdmcp_handle_manage: Looked up %s", d->name); - - if (gdm_get_value_bool (GDM_KEY_INDIRECT)) { - id = gdm_choose_indirect_lookup (clnt_sa); - - /* This was an indirect thingie and nothing was yet chosen, - * use a chooser */ - if (d->dispstat == XDMCP_PENDING && - id != NULL && - id->chosen_host == NULL) { - d->use_chooser = TRUE; - d->indirect_id = id->id; - } else { - d->indirect_id = 0; - d->use_chooser = FALSE; - if (id != NULL) - gdm_choose_indirect_dispose (id); - } - } else { - d->indirect_id = 0; - d->use_chooser = FALSE; - } - - /* this was from a forwarded query quite apparently so - * send MANAGED_FORWARD */ - fq = gdm_forward_query_lookup (clnt_sa); - if (fq != NULL) { - gdm_xdmcp_send_managed_forward (fq->from_sa, clnt_sa); - gdm_forward_query_dispose (fq); - } - - d->dispstat = XDMCP_MANAGED; - xdmcp_sessions++; - xdmcp_pending--; - - /* Start greeter/session */ - if G_UNLIKELY (!gdm_display_manage (d)) { - gdm_xdmcp_send_failed (clnt_sa, clnt_sessid); - XdmcpDisposeARRAY8(&clnt_dspclass); - return; - } - } - else if G_UNLIKELY (d != NULL && d->dispstat == XDMCP_MANAGED) { - gdm_debug ("gdm_xdmcp_handle_manage: Session id %ld already managed", - (long)clnt_sessid); - } - else { - gdm_debug ("gdm_xdmcp_handle_manage: Failed to look up session id %ld", - (long)clnt_sessid); - gdm_xdmcp_send_refuse (clnt_sa, clnt_sessid); - } - - XdmcpDisposeARRAY8(&clnt_dspclass); -} - -static void -#ifdef ENABLE_IPV6 -gdm_xdmcp_handle_managed_forward (struct sockaddr_storage *clnt_sa, gint len) -#else -gdm_xdmcp_handle_managed_forward (struct sockaddr_in *clnt_sa, gint len) -#endif -{ - ARRAY8 clnt_address; - GdmIndirectDisplay *id; -#ifdef ENABLE_IPV6 - char buffer6[INET6_ADDRSTRLEN]; - - inet_ntop (AF_INET6, &((struct sockaddr_in6 *)clnt_sa)->sin6_addr, buffer6, INET6_ADDRSTRLEN); - - if (clnt_sa->ss_family == AF_INET6) { - gdm_debug ("gdm_xdmcp_handle_managed_forward: " - "Got MANAGED_FORWARD from %s", - buffer6); - /* Check with tcp_wrappers if client is allowed to access */ - if (! gdm_xdmcp_host_allow (clnt_sa)) { - gdm_error ("%s: Got MANAGED_FORWARD from banned host %s", "gdm_xdmcp_handle_request", buffer6); - return; - } - } - else -#endif - { - gdm_debug ("gdm_xdmcp_handle_managed_forward: " - "Got MANAGED_FORWARD from %s", - inet_ntoa (((struct sockaddr_in *)clnt_sa)->sin_addr)); - - /* Check with tcp_wrappers if client is allowed to access */ - if (! gdm_xdmcp_host_allow (clnt_sa)) { - gdm_error ("%s: Got MANAGED_FORWARD from banned host %s", - "gdm_xdmcp_handle_request", - inet_ntoa (((struct sockaddr_in *)clnt_sa)->sin_addr)); - return; - } - } - - /* Hostname */ - if G_UNLIKELY ( ! XdmcpReadARRAY8 (&buf, &clnt_address)) { - gdm_error (_("%s: Could not read address"), - "gdm_xdmcp_handle_managed_forward"); - return; - } -#ifdef ENABLE_IPV6 - if (clnt_sa->ss_family == AF_INET6) { - if (clnt_address.length != sizeof (struct in6_addr)) { - gdm_error (_("%s: Could not read address"), - "gdm_xdmcp_handle_managed_forward"); - XdmcpDisposeARRAY8 (&clnt_address); - return; - } - - id = gdm_choose_indirect_lookup_by_chosen6 (&(((struct sockaddr_in6 *)clnt_sa)->sin6_addr), (struct in6_addr *)clnt_address.data); - } - else -#endif - { - if (clnt_address.length != sizeof (struct in_addr)) { - gdm_error (_("%s: Could not read address"), - "gdm_xdmcp_handle_managed_forward"); - XdmcpDisposeARRAY8 (&clnt_address); - return; - } - - id = gdm_choose_indirect_lookup_by_chosen - (&(((struct sockaddr_in *)clnt_sa)->sin_addr), (struct in_addr *)clnt_address.data); - } - - if (id != NULL) { - gdm_choose_indirect_dispose (id); - } - - /* Note: we send GOT even on not found, just in case our previous - * didn't get through and this was a second managed forward */ -#ifdef ENABLE_IPV6 - if (clnt_sa->ss_family == AF_INET6) { - gdm_xdmcp_send_got_managed_forward6 ((struct sockaddr_in6 *)clnt_sa, (struct in6_addr *)clnt_address.data); - } - else -#endif - { - gdm_xdmcp_send_got_managed_forward ((struct sockaddr_in *)clnt_sa, (struct in_addr *)clnt_address.data); - } - - XdmcpDisposeARRAY8 (&clnt_address); -} - -#ifdef ENABLE_IPV6 -static void -gdm_xdmcp_whack_queued_managed_forwards6 (struct sockaddr_in6 *clnt_sa, - struct in6_addr *origin) -{ - GSList *li; - - for (li = managed_forwards; li != NULL; li = li->next) { - ManagedForward *mf = li->data; - - if ((memcmp (((struct sockaddr_in6 *)(&(mf->manager)))->sin6_addr.s6_addr, (clnt_sa->sin6_addr.s6_addr), sizeof (struct in6_addr)) == 0) && - (memcmp (((struct sockaddr_in6 *)(&(mf->origin)))->sin6_addr.s6_addr, origin->s6_addr, sizeof (struct in6_addr)) == 0)) { - managed_forwards = g_slist_remove_link (managed_forwards, li); - g_slist_free_1 (li); - g_source_remove (mf->handler); - /* mf freed by glib */ - return; - } - } -} -#endif - -static void -gdm_xdmcp_whack_queued_managed_forwards (struct sockaddr_in *clnt_sa, - struct in_addr *origin) -{ - GSList *li; - - for (li = managed_forwards; li != NULL; li = li->next) { - ManagedForward *mf = li->data; - if (((struct sockaddr_in *)(&mf->manager))->sin_addr.s_addr == clnt_sa->sin_addr.s_addr && - ((struct sockaddr_in *)(&mf->origin))->sin_addr.s_addr == origin->s_addr) { - - managed_forwards = g_slist_remove_link (managed_forwards, li); - g_slist_free_1 (li); - g_source_remove (mf->handler); - /* mf freed by glib */ - return; - } - } -} - -static void -#ifdef ENABLE_IPV6 -gdm_xdmcp_handle_got_managed_forward (struct sockaddr_storage *clnt_sa, gint len) -#else -gdm_xdmcp_handle_got_managed_forward (struct sockaddr_in *clnt_sa, gint len) -#endif -{ - ARRAY8 clnt_address; - -#ifdef ENABLE_IPV6 - char buffer6[INET6_ADDRSTRLEN]; - - if (clnt_sa->ss_family == AF_INET6) { - gdm_debug ("gdm_xdmcp_handle_got_managed_forward: " - "Got MANAGED_FORWARD from %s", - inet_ntop (AF_INET6, &((struct sockaddr_in6 *)clnt_sa)->sin6_addr, buffer6, INET6_ADDRSTRLEN)); - if (! gdm_xdmcp_host_allow (clnt_sa)) { - gdm_error ("%s: Got GOT_MANAGED_FORWARD from banned host %s", "gdm_xdmcp_handle_request", buffer6); - return; - } - } - else -#endif - { - gdm_debug ("gdm_xdmcp_handle_got_managed_forward: " - "Got MANAGED_FORWARD from %s", - inet_ntoa (((struct sockaddr_in *)clnt_sa)->sin_addr)); - - /* Check with tcp_wrappers if client is allowed to access */ - if (! gdm_xdmcp_host_allow (clnt_sa)) { - gdm_error ("%s: Got GOT_MANAGED_FORWARD from banned host %s", - "gdm_xdmcp_handle_request", - inet_ntoa (((struct sockaddr_in *)clnt_sa)->sin_addr)); - return; - } - } - - /* Hostname */ - if G_UNLIKELY ( ! XdmcpReadARRAY8 (&buf, &clnt_address)) { - gdm_error (_("%s: Could not read address"), - "gdm_xdmcp_handle_got_managed_forward"); - return; - } -#ifdef ENABLE_IPV6 - if (clnt_sa->ss_family == AF_INET6) { - if (clnt_address.length != sizeof (struct in6_addr)) { - gdm_error (_("%s: Could not read address"), - "gdm_xdmcp_handle_got_managed_forward"); - XdmcpDisposeARRAY8 (&clnt_address); - return; - } - - gdm_xdmcp_whack_queued_managed_forwards6 ((struct sockaddr_in6 *)clnt_sa, (struct in6_addr *)clnt_address.data); - } - else -#endif - { - if (clnt_address.length != sizeof (struct in_addr)) { - gdm_error (_("%s: Could not read address"), - "gdm_xdmcp_handle_got_managed_forward"); - XdmcpDisposeARRAY8 (&clnt_address); - return; - } - gdm_xdmcp_whack_queued_managed_forwards ((struct sockaddr_in *)clnt_sa, (struct in_addr *)clnt_address.data); - } - - XdmcpDisposeARRAY8 (&clnt_address); -} - - -static void -#ifdef ENABLE_IPV6 -gdm_xdmcp_send_refuse (struct sockaddr_storage *clnt_sa, CARD32 sessid) -#else -gdm_xdmcp_send_refuse (struct sockaddr_in *clnt_sa, CARD32 sessid) -#endif -{ - XdmcpHeader header; - GdmForwardQuery *fq; - - gdm_debug ("gdm_xdmcp_send_refuse: Sending REFUSE to %ld", (long)sessid); - - header.version = XDM_PROTOCOL_VERSION; - header.opcode= (CARD16) REFUSE; - header.length = 4; - - XdmcpWriteHeader (&buf, &header); - XdmcpWriteCARD32 (&buf, sessid); -#ifdef ENABLE_IPV6 - if (clnt_sa->ss_family == AF_INET6) { - XdmcpFlush (gdm_xdmcpfd, &buf, (XdmcpNetaddr)clnt_sa, - (int)sizeof (struct sockaddr_in6)); - } - else -#endif - { - XdmcpFlush (gdm_xdmcpfd, &buf, (XdmcpNetaddr)clnt_sa, - (int)sizeof (struct sockaddr_in)); - } - - /* this was from a forwarded query quite apparently so - * send MANAGED_FORWARD */ - fq = gdm_forward_query_lookup (clnt_sa); - if (fq != NULL) { - gdm_xdmcp_send_managed_forward (fq->from_sa, clnt_sa); - gdm_forward_query_dispose (fq); - } -} - - -static void -#ifdef ENABLE_IPV6 -gdm_xdmcp_send_failed (struct sockaddr_storage *clnt_sa, CARD32 sessid) -#else -gdm_xdmcp_send_failed (struct sockaddr_in *clnt_sa, CARD32 sessid) -#endif -{ - XdmcpHeader header; - ARRAY8 status; - - gdm_debug ("gdm_xdmcp_send_failed: Sending FAILED to %ld", (long)sessid); - - /* Don't translate, this goes over the wire to servers where we - * don't know the charset or language, so it must be ascii */ - status.data = (CARD8 *) "Failed to start session"; - status.length = strlen ((char *) status.data); - - header.version = XDM_PROTOCOL_VERSION; - header.opcode = (CARD16) FAILED; - header.length = 6+status.length; - - XdmcpWriteHeader (&buf, &header); - XdmcpWriteCARD32 (&buf, sessid); - XdmcpWriteARRAY8 (&buf, &status); -#ifdef ENABLE_IPV6 - if (clnt_sa->ss_family == AF_INET6) { - XdmcpFlush (gdm_xdmcpfd, &buf, (XdmcpNetaddr)clnt_sa, - (int)sizeof (struct sockaddr_in6)); - } - else -#endif - { - XdmcpFlush (gdm_xdmcpfd, &buf, (XdmcpNetaddr)clnt_sa, - (int)sizeof (struct sockaddr_in)); - } - -} - - -static void -#ifdef ENABLE_IPV6 -gdm_xdmcp_handle_keepalive (struct sockaddr_storage *clnt_sa, gint len) -#else -gdm_xdmcp_handle_keepalive (struct sockaddr_in *clnt_sa, gint len) -#endif -{ - CARD16 clnt_dspnum; - CARD32 clnt_sessid; - -#ifdef ENABLE_IPV6 - char buffer6[INET6_ADDRSTRLEN]; - - if (clnt_sa->ss_family == AF_INET6) { - gdm_debug ("gdm_xdmcp_handle_keepalive: Got KEEPALIVE from %s", - inet_ntop (AF_INET6, &(((struct sockaddr_in6 *)clnt_sa)->sin6_addr), -buffer6, INET6_ADDRSTRLEN)); - - /* Check with tcp_wrappers if client is allowed to access */ - if (! gdm_xdmcp_host_allow (clnt_sa)) { - gdm_error (_("%s: Got KEEPALIVE from banned host %s"), - "gdm_xdmcp_handle_keepalive", buffer6); - return; - - } - } - else -#endif - { - gdm_debug ("gdm_xdmcp_handle_keepalive: Got KEEPALIVE from %s", - inet_ntoa (((struct sockaddr_in *)clnt_sa)->sin_addr)); - - /* Check with tcp_wrappers if client is allowed to access */ - if (! gdm_xdmcp_host_allow (clnt_sa)) { - gdm_error (_("%s: Got KEEPALIVE from banned host %s"), - "gdm_xdmcp_handle_keepalive", - inet_ntoa (((struct sockaddr_in *)clnt_sa)->sin_addr)); - return; - } - } - - /* Remote display number */ - if G_UNLIKELY (! XdmcpReadCARD16 (&buf, &clnt_dspnum)) { - gdm_error (_("%s: Could not read Display Number"), - "gdm_xdmcp_handle_keepalive"); - return; - } - - /* SessionID */ - if G_UNLIKELY (! XdmcpReadCARD32 (&buf, &clnt_sessid)) { - gdm_error (_("%s: Could not read Session ID"), - "gdm_xdmcp_handle_keepalive"); - return; - } - - gdm_xdmcp_send_alive (clnt_sa, clnt_dspnum, clnt_sessid); -} - - -static void -#ifdef ENABLE_IPV6 -gdm_xdmcp_send_alive (struct sockaddr_storage *clnt_sa, CARD16 dspnum, CARD32 sessid) -#else -gdm_xdmcp_send_alive (struct sockaddr_in *clnt_sa, CARD16 dspnum, CARD32 sessid) -#endif -{ - XdmcpHeader header; - GdmDisplay *d; - int send_running = 0; - CARD32 send_sessid = 0; - - d = gdm_xdmcp_display_lookup (sessid); - if (d == NULL) - d = gdm_xdmcp_display_lookup_by_host (clnt_sa, dspnum); - - if (d != NULL) { - send_sessid = d->sessionid; - if (d->dispstat == XDMCP_MANAGED) - send_running = 1; - } - - gdm_debug ("Sending ALIVE to %ld (running %d, sessid %ld)", - (long)sessid, send_running, (long)send_sessid); - - header.version = XDM_PROTOCOL_VERSION; - header.opcode = (CARD16) ALIVE; - header.length = 5; - - XdmcpWriteHeader (&buf, &header); - XdmcpWriteCARD8 (&buf, send_running); - XdmcpWriteCARD32 (&buf, send_sessid); -#ifdef ENABLE_IPV6 - if (clnt_sa->ss_family == AF_INET6) { - XdmcpFlush (gdm_xdmcpfd, &buf, (XdmcpNetaddr)clnt_sa, - (int)sizeof (struct sockaddr_in6)); - } - else -#endif - { - XdmcpFlush (gdm_xdmcpfd, &buf, (XdmcpNetaddr)clnt_sa, - (int)sizeof (struct sockaddr_in)); - } -} - - -static gboolean -gdm_xdmcp_host_allow ( -#ifdef ENABLE_IPV6 - struct sockaddr_storage *clnt_sa -#else - struct sockaddr_in *clnt_sa -#endif - ) -{ -#ifdef HAVE_TCPWRAPPERS - - /* avoids a warning, my tcpd.h file doesn't include this prototype, even - * though the library does include the function and the manpage mentions it - */ - extern int hosts_ctl (char *daemon, char *client_name, char *client_addr, char *client_user); - - GdmHostent *client_he; - char *client; - gboolean ret; - - /* Find client hostname */ - client_he = gdm_gethostbyaddr (clnt_sa); - - if (client_he->not_found) - client = "unknown"; - else { - gdm_debug ("gdm_xdmcp_host_allow: client->hostname is %s\n", client_he->hostname); - client = client_he->hostname; - } - - /* Check with tcp_wrappers if client is allowed to access */ -#ifdef ENABLE_IPV6 - if (clnt_sa->ss_family == AF_INET6) { - char buffer6[INET6_ADDRSTRLEN]; - - ret = (hosts_ctl ("gdm", client, (char *) inet_ntop (AF_INET6, &((struct sockaddr_in6 *)clnt_sa)->sin6_addr, buffer6, INET6_ADDRSTRLEN), "")); - } else -#endif - { - ret = (hosts_ctl ("gdm", client, inet_ntoa (((struct sockaddr_in *)clnt_sa)->sin_addr), "")); - } - - gdm_hostent_free (client_he); - - return ret; -#else /* HAVE_TCPWRAPPERS */ - return (TRUE); -#endif /* HAVE_TCPWRAPPERS */ -} - - -static GdmDisplay * -gdm_xdmcp_display_alloc ( -#ifdef ENABLE_IPV6 - struct sockaddr_storage *addr, -#else - struct sockaddr_in *addr, -#endif - GdmHostent *he /* eaten and freed */, - int displaynum) -{ - GdmDisplay *d = NULL; - char *proxycmd = gdm_get_value_string (GDM_KEY_XDMCP_PROXY_XSERVER); - - d = g_new0 (GdmDisplay, 1); - - if (gdm_get_value_bool (GDM_KEY_XDMCP_PROXY) && proxycmd != NULL) { - d->type = TYPE_XDMCP_PROXY; - d->command = g_strdup (proxycmd); - gdm_debug ("Using proxy server for XDMCP: %s\n", d->command); - } else { - d->type = TYPE_XDMCP; - } - - d->logout_action = GDM_LOGOUT_ACTION_NONE; - d->authfile = NULL; - d->auths = NULL; - d->userauth = NULL; - d->greetpid = 0; - d->servpid = 0; - d->servstat = 0; - d->sesspid = 0; - d->slavepid = 0; - d->attached = FALSE; - d->dispstat = XDMCP_PENDING; - d->sessionid = globsessid++; - if (d->sessionid == 0) - d->sessionid = globsessid++; - d->acctime = time (NULL); - d->dispnum = displaynum; - d->xdmcp_dispnum = displaynum; - - d->handled = TRUE; - d->tcp_disallowed = FALSE; - - d->vt = -1; - - d->x_servers_order = -1; - - d->logged_in = FALSE; - d->login = NULL; - - d->sleep_before_run = 0; - if (gdm_get_value_bool (GDM_KEY_ALLOW_REMOTE_AUTOLOGIN) && - ! ve_string_empty (gdm_get_value_string (GDM_KEY_TIMED_LOGIN))) { - d->timed_login_ok = TRUE; - } else { - d->timed_login_ok = FALSE; - } - - d->name = g_strdup_printf ("%s:%d", he->hostname, - displaynum); -#ifdef ENABLE_IPV6 - if (addr->ss_family == AF_INET6) { - memcpy (&d->addr6, &((struct sockaddr_in6 *)addr)->sin6_addr, sizeof (struct in6_addr)); - d->addrtype = AF_INET6; - } - else -#endif - { - memcpy (&d->addr, &((struct sockaddr_in *)addr)->sin_addr, sizeof (struct in_addr)); - d->addrtype = AF_INET; - } - - d->hostname = he->hostname; - he->hostname = NULL; - d->addrs = he->addrs; - he->addrs = NULL; - d->addr_count = he->addr_count; - he->addr_count = 0; - - gdm_hostent_free (he); - - d->slave_notify_fd = -1; - d->master_notify_fd = -1; - - d->xsession_errors_bytes = 0; - d->xsession_errors_fd = -1; - d->session_output_fd = -1; - - d->chooser_output_fd = -1; - d->chooser_last_line = NULL; - - d->theme_name = NULL; - - /* Secure display with cookie */ - if G_UNLIKELY (! gdm_auth_secure_display (d)) - gdm_error ("gdm_xdmcp_display_alloc: Error setting up cookies for %s", d->name); - - if (d->type == TYPE_XDMCP_PROXY) { - d->parent_disp = d->name; - d->name = g_strdup (":-1"); - d->dispnum = -1; - - d->server_uid = gdm_get_gdmuid (); - - d->parent_auth_file = d->authfile; - d->authfile = NULL; - } - - displays = g_slist_append (displays, d); - - xdmcp_pending++; - - gdm_debug ("gdm_xdmcp_display_alloc: display=%s, session id=%ld, xdmcp_pending=%d ", - d->name, (long)d->sessionid, xdmcp_pending); - - return d; -} - - -static GdmDisplay * -gdm_xdmcp_display_lookup (CARD32 sessid) -{ - GSList *dlist = displays; - GdmDisplay *d; - - if (!sessid) - return (NULL); - - while (dlist) { - d = (GdmDisplay *) dlist->data; - - if (d && d->sessionid == sessid) - return (d); - - dlist = dlist->next; - } - - return (NULL); -} - - -static void -gdm_xdmcp_display_dispose_check (const gchar *hostname, int dspnum) -{ - GSList *dlist; - - if (hostname == NULL) - return; - - gdm_debug ("gdm_xdmcp_display_dispose_check (%s:%d)", hostname, dspnum); - - dlist = displays; - while (dlist != NULL) { - GdmDisplay *d = dlist->data; - - if (d != NULL && - SERVER_IS_XDMCP (d) && - d->xdmcp_dispnum == dspnum && - strcmp (d->hostname, hostname) == 0) { - if (d->dispstat == XDMCP_MANAGED) - gdm_display_unmanage (d); - else - gdm_display_dispose (d); - - /* restart as the list is now broken */ - dlist = displays; - } else { - /* just go on */ - dlist = dlist->next; - } - } -} - - -static void -gdm_xdmcp_displays_check (void) -{ - GSList *dlist; - time_t curtime = time (NULL); - - dlist = displays; - while (dlist != NULL) { - GdmDisplay *d = dlist->data; - - if (d != NULL && - SERVER_IS_XDMCP (d) && - d->dispstat == XDMCP_PENDING && - curtime > d->acctime + gdm_get_value_int (GDM_KEY_MAX_WAIT)) { - gdm_debug ("gdm_xdmcp_displays_check: Disposing session id %ld", - (long)d->sessionid); - gdm_display_dispose (d); - - /* restart as the list is now broken */ - dlist = displays; - } else { - /* just go on */ - dlist = dlist->next; - } - } -} - -static void -reconnect_to_parent (GdmDisplay *to) -{ - GError *error; - gchar *command_argv[10]; - gchar *proxyreconnect = gdm_get_value_string (GDM_KEY_XDMCP_PROXY_RECONNECT); - - command_argv[0] = proxyreconnect; - command_argv[1] = "--display"; - command_argv[2] = to->parent_disp; - command_argv[3] = "--display-authfile"; - command_argv[4] = to->parent_auth_file; - command_argv[5] = "--to"; - command_argv[6] = to->name; - command_argv[7] = "--to-authfile"; - command_argv[8] = to->authfile; - command_argv[9] = NULL; - - gdm_debug ("XDMCP: migrating display by running " - "'%s --display %s --display-authfile %s --to %s --to-authfile %s'", - proxyreconnect, - to->parent_disp, to->parent_auth_file, - to->name, to->authfile); - - error = NULL; - if (!g_spawn_async (NULL, command_argv, NULL, 0, NULL, NULL, NULL, &error)) { - gdm_error (_("%s: Failed to run " - "'%s --display %s --display-authfile %s --to %s --to-authfile %s': %s"), - "gdm_xdmcp_migrate", - proxyreconnect, - to->parent_disp, to->parent_auth_file, - to->name, to->authfile, - error->message); - g_error_free (error); - } -} - -void -gdm_xdmcp_migrate (GdmDisplay *from, GdmDisplay *to) -{ - if (from->type != TYPE_XDMCP_PROXY || - to->type != TYPE_XDMCP_PROXY) - return; - - g_free (to->parent_disp); - to->parent_disp = from->parent_disp; - from->parent_disp = NULL; - - g_free (to->parent_auth_file); - to->parent_auth_file = from->parent_auth_file; - from->parent_auth_file = NULL; - - reconnect_to_parent (to); -} - -#else /* HAVE_LIBXDMCP */ - -/* Here come some empty stubs for no XDMCP support */ -int -gdm_xdmcp_init (void) -{ - gdm_error (_("%s: No XDMCP support"), "gdm_xdmcp_init"); - return FALSE; -} - -void -gdm_xdmcp_run (void) -{ - gdm_error (_("%s: No XDMCP support"), "gdm_xdmcp_run"); -} - -void -gdm_xdmcp_close (void) -{ - gdm_error (_("%s: No XDMCP support"), "gdm_xdmcp_close"); -} - -void -gdm_xdmcp_migrate (GdmDisplay *from, GdmDisplay *to) -{ - gdm_error (_("%s: No XDMCP support"), "gdm_xdmcp_migrate"); -} - -#endif /* HAVE_LIBXDMCP */ - -/* EOF */ |