1307 lines
		
	
	
		
			33 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1307 lines
		
	
	
		
			33 KiB
		
	
	
	
		
			C
		
	
	
	
/***********************************************************
 | 
						|
 | 
						|
Copyright 1987, 1989, 1998  The Open Group
 | 
						|
 | 
						|
Permission to use, copy, modify, distribute, and sell this software and its
 | 
						|
documentation for any purpose is hereby granted without fee, provided that
 | 
						|
the above copyright notice appear in all copies and that both that
 | 
						|
copyright notice and this permission notice appear in supporting
 | 
						|
documentation.
 | 
						|
 | 
						|
The above copyright notice and this permission notice shall be included in
 | 
						|
all copies or substantial portions of the Software.
 | 
						|
 | 
						|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
						|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
						|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 | 
						|
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 | 
						|
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
						|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
						|
 | 
						|
Except as contained in this notice, the name of The Open Group shall not be
 | 
						|
used in advertising or otherwise to promote the sale, use or other dealings
 | 
						|
in this Software without prior written authorization from The Open Group.
 | 
						|
 | 
						|
 | 
						|
Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
 | 
						|
 | 
						|
                        All Rights Reserved
 | 
						|
 | 
						|
Permission to use, copy, modify, and distribute this software and its 
 | 
						|
documentation for any purpose and without fee is hereby granted, 
 | 
						|
provided that the above copyright notice appear in all copies and that
 | 
						|
both that copyright notice and this permission notice appear in 
 | 
						|
supporting documentation, and that the name of Digital not be
 | 
						|
used in advertising or publicity pertaining to distribution of the
 | 
						|
software without specific, written prior permission.  
 | 
						|
 | 
						|
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
 | 
						|
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
 | 
						|
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
 | 
						|
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 | 
						|
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 | 
						|
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 | 
						|
SOFTWARE.
 | 
						|
 | 
						|
******************************************************************/
 | 
						|
/*****************************************************************
 | 
						|
 *  Stuff to create connections --- OS dependent
 | 
						|
 *
 | 
						|
 *      EstablishNewConnections, CreateWellKnownSockets, ResetWellKnownSockets,
 | 
						|
 *      CloseDownConnection, CheckConnections, AddEnabledDevice,
 | 
						|
 *	RemoveEnabledDevice, OnlyListToOneClient,
 | 
						|
 *      ListenToAllClients,
 | 
						|
 *
 | 
						|
 *      (WaitForSomething is in its own file)
 | 
						|
 *
 | 
						|
 *      In this implementation, a client socket table is not kept.
 | 
						|
 *      Instead, what would be the index into the table is just the
 | 
						|
 *      file descriptor of the socket.  This won't work for if the
 | 
						|
 *      socket ids aren't small nums (0 - 2^8)
 | 
						|
 *
 | 
						|
 *****************************************************************/
 | 
						|
 | 
						|
#ifdef HAVE_DIX_CONFIG_H
 | 
						|
#include <dix-config.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef WIN32
 | 
						|
#include <X11/Xwinsock.h>
 | 
						|
#endif
 | 
						|
#include <X11/X.h>
 | 
						|
#include <X11/Xproto.h>
 | 
						|
#define XSERV_t
 | 
						|
#define TRANS_SERVER
 | 
						|
#define TRANS_REOPEN
 | 
						|
#include <X11/Xtrans/Xtrans.h>
 | 
						|
#include <X11/Xtrans/Xtransint.h>
 | 
						|
#include <errno.h>
 | 
						|
#include <signal.h>
 | 
						|
#include <stdio.h>
 | 
						|
#include <stdlib.h>
 | 
						|
 | 
						|
#ifndef WIN32
 | 
						|
#include <sys/socket.h>
 | 
						|
 | 
						|
 | 
						|
 | 
						|
#if defined(TCPCONN) || defined(STREAMSCONN)
 | 
						|
# include <netinet/in.h>
 | 
						|
# include <arpa/inet.h>
 | 
						|
#  ifdef apollo
 | 
						|
#   ifndef NO_TCP_H
 | 
						|
#    include <netinet/tcp.h>
 | 
						|
#   endif
 | 
						|
#  else
 | 
						|
#   ifdef CSRG_BASED
 | 
						|
#    include <sys/param.h>
 | 
						|
#   endif
 | 
						|
#   include <netinet/tcp.h>
 | 
						|
#  endif
 | 
						|
# include <arpa/inet.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#include <sys/uio.h>
 | 
						|
 | 
						|
#endif /* WIN32 */
 | 
						|
#include "misc.h"		/* for typedef of pointer */
 | 
						|
#include "osdep.h"
 | 
						|
#include <X11/Xpoll.h>
 | 
						|
#include "opaque.h"
 | 
						|
#include "dixstruct.h"
 | 
						|
#include "xace.h"
 | 
						|
 | 
						|
#define Pid_t pid_t
 | 
						|
 | 
						|
 | 
						|
#ifdef HAVE_GETPEERUCRED
 | 
						|
# include <ucred.h>
 | 
						|
# include <zone.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef XSERVER_DTRACE
 | 
						|
# include <sys/types.h>
 | 
						|
typedef const char *string;
 | 
						|
# ifndef HAVE_GETPEERUCRED
 | 
						|
#  define zoneid_t int
 | 
						|
# endif
 | 
						|
# include "../dix/Xserver-dtrace.h"
 | 
						|
#endif
 | 
						|
 | 
						|
static int lastfdesc;		/* maximum file descriptor */
 | 
						|
 | 
						|
fd_set WellKnownConnections;	/* Listener mask */
 | 
						|
fd_set EnabledDevices;		/* mask for input devices that are on */
 | 
						|
fd_set AllSockets;		/* select on this */
 | 
						|
fd_set AllClients;		/* available clients */
 | 
						|
fd_set LastSelectMask;		/* mask returned from last select call */
 | 
						|
fd_set ClientsWithInput;	/* clients with FULL requests in buffer */
 | 
						|
fd_set ClientsWriteBlocked;	/* clients who cannot receive output */
 | 
						|
fd_set OutputPending;		/* clients with reply/event data ready to go */
 | 
						|
int MaxClients = 0;
 | 
						|
Bool NewOutputPending;		/* not yet attempted to write some new output */
 | 
						|
Bool AnyClientsWriteBlocked;	/* true if some client blocked on write */
 | 
						|
 | 
						|
static Bool RunFromSmartParent;	/* send SIGUSR1 to parent process */
 | 
						|
Bool RunFromSigStopParent;	/* send SIGSTOP to our own process; Upstart (or
 | 
						|
				   equivalent) will send SIGCONT back. */
 | 
						|
Bool PartialNetwork;	/* continue even if unable to bind all addrs */
 | 
						|
static Pid_t ParentProcess;
 | 
						|
 | 
						|
static Bool debug_conns = FALSE;
 | 
						|
 | 
						|
fd_set IgnoredClientsWithInput;
 | 
						|
static fd_set GrabImperviousClients;
 | 
						|
static fd_set SavedAllClients;
 | 
						|
static fd_set SavedAllSockets;
 | 
						|
static fd_set SavedClientsWithInput;
 | 
						|
int GrabInProgress = 0;
 | 
						|
 | 
						|
#if !defined(WIN32)
 | 
						|
int *ConnectionTranslation = NULL;
 | 
						|
#else
 | 
						|
/*
 | 
						|
 * On NT fds are not between 0 and MAXSOCKS, they are unrelated, and there is
 | 
						|
 * not even a known maximum value, so use something quite arbitrary for now.
 | 
						|
 * Do storage is a hash table of size 256. Collisions are handled in a linked
 | 
						|
 * list.
 | 
						|
 */
 | 
						|
 | 
						|
#undef MAXSOCKS
 | 
						|
#define MAXSOCKS 500
 | 
						|
#undef MAXSELECT
 | 
						|
#define MAXSELECT 500
 | 
						|
 | 
						|
struct _ct_node {
 | 
						|
    struct _ct_node *next;
 | 
						|
    int key;
 | 
						|
    int value;
 | 
						|
};
 | 
						|
 | 
						|
struct _ct_node *ct_head[256];
 | 
						|
 | 
						|
void InitConnectionTranslation(void)
 | 
						|
{
 | 
						|
    memset(ct_head, 0, sizeof(ct_head));
 | 
						|
}
 | 
						|
 | 
						|
int GetConnectionTranslation(int conn)
 | 
						|
{
 | 
						|
    struct _ct_node *node = ct_head[conn & 0xff];
 | 
						|
    while (node != NULL)
 | 
						|
    {
 | 
						|
        if (node->key == conn)
 | 
						|
            return node->value;
 | 
						|
        node = node->next;
 | 
						|
    }
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
void SetConnectionTranslation(int conn, int client)
 | 
						|
{
 | 
						|
    struct _ct_node **node = ct_head + (conn & 0xff);
 | 
						|
    if (client == 0) /* remove entry */
 | 
						|
    {
 | 
						|
        while (*node != NULL)
 | 
						|
        {
 | 
						|
            if ((*node)->key == conn)
 | 
						|
            {
 | 
						|
                struct _ct_node *temp = *node;
 | 
						|
                *node = (*node)->next;
 | 
						|
                free(temp);
 | 
						|
                return;
 | 
						|
            }
 | 
						|
            node = &((*node)->next);
 | 
						|
        }
 | 
						|
        return;
 | 
						|
    } else 
 | 
						|
    {
 | 
						|
        while (*node != NULL)
 | 
						|
        {
 | 
						|
            if ((*node)->key == conn)
 | 
						|
            {
 | 
						|
                (*node)->value = client;
 | 
						|
                return;
 | 
						|
            }
 | 
						|
            node = &((*node)->next);
 | 
						|
        }
 | 
						|
        *node = malloc(sizeof(struct _ct_node));
 | 
						|
        (*node)->next = NULL;
 | 
						|
        (*node)->key = conn;
 | 
						|
        (*node)->value = client;
 | 
						|
        return;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void ClearConnectionTranslation(void)
 | 
						|
{
 | 
						|
    unsigned i;
 | 
						|
    for (i = 0; i < 256; i++)
 | 
						|
    {
 | 
						|
        struct _ct_node *node = ct_head[i];
 | 
						|
        while (node != NULL)
 | 
						|
        {
 | 
						|
            struct _ct_node *temp = node;
 | 
						|
            node = node->next;
 | 
						|
            free(temp);
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
static XtransConnInfo 	*ListenTransConns = NULL;
 | 
						|
static int	       	*ListenTransFds = NULL;
 | 
						|
static int		ListenTransCount;
 | 
						|
 | 
						|
static void ErrorConnMax(XtransConnInfo /* trans_conn */);
 | 
						|
 | 
						|
static XtransConnInfo
 | 
						|
lookup_trans_conn (int fd)
 | 
						|
{
 | 
						|
    if (ListenTransFds)
 | 
						|
    {
 | 
						|
	int i;
 | 
						|
	for (i = 0; i < ListenTransCount; i++)
 | 
						|
	    if (ListenTransFds[i] == fd)
 | 
						|
		return ListenTransConns[i];
 | 
						|
    }
 | 
						|
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
/* Set MaxClients and lastfdesc, and allocate ConnectionTranslation */
 | 
						|
 | 
						|
void
 | 
						|
InitConnectionLimits(void)
 | 
						|
{
 | 
						|
    lastfdesc = -1;
 | 
						|
 | 
						|
#ifndef __CYGWIN__
 | 
						|
 | 
						|
#if !defined(XNO_SYSCONF) && defined(_SC_OPEN_MAX)
 | 
						|
    lastfdesc = sysconf(_SC_OPEN_MAX) - 1;
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef HAVE_GETDTABLESIZE
 | 
						|
    if (lastfdesc < 0)
 | 
						|
	lastfdesc = getdtablesize() - 1;
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef _NFILE
 | 
						|
    if (lastfdesc < 0)
 | 
						|
	lastfdesc = _NFILE - 1;
 | 
						|
#endif
 | 
						|
 | 
						|
#endif /* __CYGWIN__ */
 | 
						|
 | 
						|
    /* This is the fallback */
 | 
						|
    if (lastfdesc < 0)
 | 
						|
	lastfdesc = MAXSOCKS;
 | 
						|
 | 
						|
    if (lastfdesc > MAXSELECT)
 | 
						|
	lastfdesc = MAXSELECT;
 | 
						|
 | 
						|
    if (lastfdesc > MAXCLIENTS)
 | 
						|
    {
 | 
						|
	lastfdesc = MAXCLIENTS;
 | 
						|
	if (debug_conns)
 | 
						|
	    ErrorF( "REACHED MAXIMUM CLIENTS LIMIT %d\n", MAXCLIENTS);
 | 
						|
    }
 | 
						|
    MaxClients = lastfdesc;
 | 
						|
 | 
						|
#ifdef DEBUG
 | 
						|
    ErrorF("InitConnectionLimits: MaxClients = %d\n", MaxClients);
 | 
						|
#endif
 | 
						|
 | 
						|
#if !defined(WIN32)
 | 
						|
    if (!ConnectionTranslation)
 | 
						|
        ConnectionTranslation = (int *)xnfalloc(sizeof(int)*(lastfdesc + 1));
 | 
						|
#else
 | 
						|
    InitConnectionTranslation();
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * If SIGUSR1 was set to SIG_IGN when the server started, assume that either
 | 
						|
 *
 | 
						|
 *  a- The parent process is ignoring SIGUSR1
 | 
						|
 *
 | 
						|
 * or
 | 
						|
 *
 | 
						|
 *  b- The parent process is expecting a SIGUSR1
 | 
						|
 *     when the server is ready to accept connections
 | 
						|
 *
 | 
						|
 * In the first case, the signal will be harmless, in the second case,
 | 
						|
 * the signal will be quite useful.
 | 
						|
 */
 | 
						|
static void
 | 
						|
InitParentProcess(void)
 | 
						|
{
 | 
						|
#if !defined(WIN32)
 | 
						|
    OsSigHandlerPtr handler;
 | 
						|
    handler = OsSignal (SIGUSR1, SIG_IGN);
 | 
						|
    if ( handler == SIG_IGN)
 | 
						|
	RunFromSmartParent = TRUE;
 | 
						|
    OsSignal(SIGUSR1, handler);
 | 
						|
    ParentProcess = getppid ();
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
NotifyParentProcess(void)
 | 
						|
{
 | 
						|
#if !defined(WIN32)
 | 
						|
    if (RunFromSmartParent) {
 | 
						|
	if (ParentProcess > 1) {
 | 
						|
	    kill (ParentProcess, SIGUSR1);
 | 
						|
	}
 | 
						|
    }
 | 
						|
    if (RunFromSigStopParent)
 | 
						|
	raise (SIGSTOP);
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
/*****************
 | 
						|
 * CreateWellKnownSockets
 | 
						|
 *    At initialization, create the sockets to listen on for new clients.
 | 
						|
 *****************/
 | 
						|
 | 
						|
void
 | 
						|
CreateWellKnownSockets(void)
 | 
						|
{
 | 
						|
    int		i;
 | 
						|
    int		partial;
 | 
						|
    char 	port[20];
 | 
						|
 | 
						|
    FD_ZERO(&AllSockets);
 | 
						|
    FD_ZERO(&AllClients);
 | 
						|
    FD_ZERO(&LastSelectMask);
 | 
						|
    FD_ZERO(&ClientsWithInput);
 | 
						|
 | 
						|
#if !defined(WIN32)
 | 
						|
    for (i=0; i<MaxClients; i++) ConnectionTranslation[i] = 0;
 | 
						|
#else
 | 
						|
    ClearConnectionTranslation();
 | 
						|
#endif
 | 
						|
 | 
						|
    FD_ZERO (&WellKnownConnections);
 | 
						|
 | 
						|
    snprintf (port, sizeof(port), "%d", atoi (display));
 | 
						|
 | 
						|
    if ((_XSERVTransMakeAllCOTSServerListeners (port, &partial,
 | 
						|
	&ListenTransCount, &ListenTransConns) >= 0) &&
 | 
						|
	(ListenTransCount >= 1))
 | 
						|
    {
 | 
						|
	if (!PartialNetwork && partial)
 | 
						|
	{
 | 
						|
	    FatalError ("Failed to establish all listening sockets");
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
	    ListenTransFds = malloc(ListenTransCount * sizeof (int));
 | 
						|
 | 
						|
	    for (i = 0; i < ListenTransCount; i++)
 | 
						|
	    {
 | 
						|
		int fd = _XSERVTransGetConnectionNumber (ListenTransConns[i]);
 | 
						|
		
 | 
						|
		ListenTransFds[i] = fd;
 | 
						|
		FD_SET (fd, &WellKnownConnections);
 | 
						|
 | 
						|
		if (!_XSERVTransIsLocal (ListenTransConns[i]))
 | 
						|
		{
 | 
						|
		    DefineSelf (fd);
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    if (!XFD_ANYSET (&WellKnownConnections))
 | 
						|
        FatalError ("Cannot establish any listening sockets - Make sure an X server isn't already running");
 | 
						|
#if !defined(WIN32)
 | 
						|
    OsSignal (SIGPIPE, SIG_IGN);
 | 
						|
    OsSignal (SIGHUP, AutoResetServer);
 | 
						|
#endif
 | 
						|
    OsSignal (SIGINT, GiveUp);
 | 
						|
    OsSignal (SIGTERM, GiveUp);
 | 
						|
    XFD_COPYSET (&WellKnownConnections, &AllSockets);
 | 
						|
    ResetHosts(display);
 | 
						|
 | 
						|
    InitParentProcess();
 | 
						|
 | 
						|
#ifdef XDMCP
 | 
						|
    XdmcpInit ();
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
ResetWellKnownSockets (void)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
 | 
						|
    ResetOsBuffers();
 | 
						|
 | 
						|
    for (i = 0; i < ListenTransCount; i++)
 | 
						|
    {
 | 
						|
	int status = _XSERVTransResetListener (ListenTransConns[i]);
 | 
						|
 | 
						|
	if (status != TRANS_RESET_NOOP)
 | 
						|
	{
 | 
						|
	    if (status == TRANS_RESET_FAILURE)
 | 
						|
	    {
 | 
						|
		/*
 | 
						|
		 * ListenTransConns[i] freed by xtrans.
 | 
						|
		 * Remove it from out list.
 | 
						|
		 */
 | 
						|
 | 
						|
		FD_CLR (ListenTransFds[i], &WellKnownConnections);
 | 
						|
		ListenTransFds[i] = ListenTransFds[ListenTransCount - 1];
 | 
						|
		ListenTransConns[i] = ListenTransConns[ListenTransCount - 1];
 | 
						|
		ListenTransCount -= 1;
 | 
						|
		i -= 1;
 | 
						|
	    }
 | 
						|
	    else if (status == TRANS_RESET_NEW_FD)
 | 
						|
	    {
 | 
						|
		/*
 | 
						|
		 * A new file descriptor was allocated (the old one was closed)
 | 
						|
		 */
 | 
						|
 | 
						|
		int newfd = _XSERVTransGetConnectionNumber (ListenTransConns[i]);
 | 
						|
 | 
						|
		FD_CLR (ListenTransFds[i], &WellKnownConnections);
 | 
						|
		ListenTransFds[i] = newfd;
 | 
						|
		FD_SET(newfd, &WellKnownConnections);
 | 
						|
	    }
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    ResetAuthorization ();
 | 
						|
    ResetHosts(display);
 | 
						|
    /*
 | 
						|
     * restart XDMCP
 | 
						|
     */
 | 
						|
#ifdef XDMCP
 | 
						|
    XdmcpReset ();
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
CloseWellKnownConnections(void)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
 | 
						|
    for (i = 0; i < ListenTransCount; i++)
 | 
						|
	_XSERVTransClose (ListenTransConns[i]);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
AuthAudit (ClientPtr client, Bool letin, 
 | 
						|
    struct sockaddr *saddr, int len, 
 | 
						|
    unsigned int proto_n, char *auth_proto, int auth_id)
 | 
						|
{
 | 
						|
    char addr[128];
 | 
						|
    char client_uid_string[64];
 | 
						|
    LocalClientCredRec *lcc;
 | 
						|
#ifdef XSERVER_DTRACE
 | 
						|
    pid_t client_pid = -1;
 | 
						|
    zoneid_t client_zid = -1;
 | 
						|
#endif
 | 
						|
 | 
						|
    if (!len)
 | 
						|
        strlcpy(addr, "local host", sizeof(addr));
 | 
						|
    else
 | 
						|
	switch (saddr->sa_family)
 | 
						|
	{
 | 
						|
	case AF_UNSPEC:
 | 
						|
#if defined(UNIXCONN) || defined(LOCALCONN)
 | 
						|
	case AF_UNIX:
 | 
						|
#endif
 | 
						|
	    strlcpy(addr, "local host", sizeof(addr));
 | 
						|
	    break;
 | 
						|
#if defined(TCPCONN) || defined(STREAMSCONN)
 | 
						|
	case AF_INET:
 | 
						|
	    snprintf(addr, sizeof(addr), "IP %s",
 | 
						|
		inet_ntoa(((struct sockaddr_in *) saddr)->sin_addr));
 | 
						|
	    break;
 | 
						|
#if defined(IPv6) && defined(AF_INET6)
 | 
						|
	case AF_INET6: {
 | 
						|
	    char ipaddr[INET6_ADDRSTRLEN];
 | 
						|
	    inet_ntop(AF_INET6, &((struct sockaddr_in6 *) saddr)->sin6_addr,
 | 
						|
	      ipaddr, sizeof(ipaddr));
 | 
						|
	    snprintf(addr, sizeof(addr), "IP %s", ipaddr);
 | 
						|
	}
 | 
						|
	    break;
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
	default:
 | 
						|
	    strlcpy(addr, "unknown address", sizeof(addr));
 | 
						|
	}
 | 
						|
 | 
						|
    if (GetLocalClientCreds(client, &lcc) != -1) {
 | 
						|
	int slen; /* length written to client_uid_string */
 | 
						|
 | 
						|
	strcpy(client_uid_string, " ( ");
 | 
						|
	slen = 3;
 | 
						|
 | 
						|
	if (lcc->fieldsSet & LCC_UID_SET) {
 | 
						|
	    snprintf(client_uid_string + slen,
 | 
						|
		     sizeof(client_uid_string) - slen,
 | 
						|
		     "uid=%ld ", (long) lcc->euid);
 | 
						|
	    slen = strlen(client_uid_string);
 | 
						|
	}
 | 
						|
 | 
						|
	if (lcc->fieldsSet & LCC_GID_SET) {
 | 
						|
	    snprintf(client_uid_string + slen,
 | 
						|
		     sizeof(client_uid_string) - slen,
 | 
						|
		     "gid=%ld ", (long) lcc->egid);
 | 
						|
	    slen = strlen(client_uid_string);
 | 
						|
	}
 | 
						|
 | 
						|
	if (lcc->fieldsSet & LCC_PID_SET) {
 | 
						|
#ifdef XSERVER_DTRACE	    
 | 
						|
	    client_pid = lcc->pid;
 | 
						|
#endif
 | 
						|
	    snprintf(client_uid_string + slen,
 | 
						|
		     sizeof(client_uid_string) - slen,
 | 
						|
		     "pid=%ld ", (long) lcc->pid);
 | 
						|
	    slen = strlen(client_uid_string);
 | 
						|
	}
 | 
						|
	
 | 
						|
	if (lcc->fieldsSet & LCC_ZID_SET) {
 | 
						|
#ifdef XSERVER_DTRACE
 | 
						|
	    client_zid = lcc->zoneid;
 | 
						|
#endif	    
 | 
						|
	    snprintf(client_uid_string + slen,
 | 
						|
		     sizeof(client_uid_string) - slen,
 | 
						|
		     "zoneid=%ld ", (long) lcc->zoneid);
 | 
						|
	    slen = strlen(client_uid_string);
 | 
						|
	}
 | 
						|
 | 
						|
	snprintf(client_uid_string + slen, sizeof(client_uid_string) - slen,
 | 
						|
		 ")");
 | 
						|
	FreeLocalClientCreds(lcc);
 | 
						|
    }
 | 
						|
    else {
 | 
						|
	client_uid_string[0] = '\0';
 | 
						|
    }
 | 
						|
    
 | 
						|
#ifdef XSERVER_DTRACE
 | 
						|
    XSERVER_CLIENT_AUTH(client->index, addr, client_pid, client_zid);
 | 
						|
#endif
 | 
						|
    if (auditTrailLevel > 1) {
 | 
						|
      if (proto_n)
 | 
						|
	AuditF("client %d %s from %s%s\n  Auth name: %.*s ID: %d\n", 
 | 
						|
	       client->index, letin ? "connected" : "rejected", addr,
 | 
						|
	       client_uid_string, (int)proto_n, auth_proto, auth_id);
 | 
						|
      else 
 | 
						|
	AuditF("client %d %s from %s%s\n", 
 | 
						|
	       client->index, letin ? "connected" : "rejected", addr,
 | 
						|
	       client_uid_string);
 | 
						|
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
XID
 | 
						|
AuthorizationIDOfClient(ClientPtr client)
 | 
						|
{
 | 
						|
    if (client->osPrivate)
 | 
						|
	return ((OsCommPtr)client->osPrivate)->auth_id;
 | 
						|
    else
 | 
						|
	return None;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*****************************************************************
 | 
						|
 * ClientAuthorized
 | 
						|
 *
 | 
						|
 *    Sent by the client at connection setup:
 | 
						|
 *                typedef struct _xConnClientPrefix {
 | 
						|
 *                   CARD8	byteOrder;
 | 
						|
 *                   BYTE	pad;
 | 
						|
 *                   CARD16	majorVersion, minorVersion;
 | 
						|
 *                   CARD16	nbytesAuthProto;    
 | 
						|
 *                   CARD16	nbytesAuthString;   
 | 
						|
 *                 } xConnClientPrefix;
 | 
						|
 *
 | 
						|
 *     	It is hoped that eventually one protocol will be agreed upon.  In the
 | 
						|
 *        mean time, a server that implements a different protocol than the
 | 
						|
 *        client expects, or a server that only implements the host-based
 | 
						|
 *        mechanism, will simply ignore this information.
 | 
						|
 *
 | 
						|
 *****************************************************************/
 | 
						|
 | 
						|
char *
 | 
						|
ClientAuthorized(ClientPtr client, 
 | 
						|
    unsigned int proto_n, char *auth_proto, 
 | 
						|
    unsigned int string_n, char *auth_string)
 | 
						|
{
 | 
						|
    OsCommPtr 		priv;
 | 
						|
    Xtransaddr		*from = NULL;
 | 
						|
    int 		family;
 | 
						|
    int			fromlen;
 | 
						|
    XID	 		auth_id;
 | 
						|
    char	 	*reason = NULL;
 | 
						|
    XtransConnInfo	trans_conn;
 | 
						|
 | 
						|
    priv = (OsCommPtr)client->osPrivate;
 | 
						|
    trans_conn = priv->trans_conn;
 | 
						|
 | 
						|
    /* Allow any client to connect without authorization on a launchd socket,
 | 
						|
       because it is securely created -- this prevents a race condition on launch */
 | 
						|
    if(trans_conn->flags & TRANS_NOXAUTH) {
 | 
						|
        auth_id = (XID) 0L;
 | 
						|
    } else {
 | 
						|
        auth_id = CheckAuthorization (proto_n, auth_proto, string_n, auth_string, client, &reason);
 | 
						|
    }
 | 
						|
 | 
						|
    if (auth_id == (XID) ~0L)
 | 
						|
    {
 | 
						|
	if (_XSERVTransGetPeerAddr(trans_conn, &family, &fromlen, &from) != -1)
 | 
						|
	{
 | 
						|
	    if (InvalidHost ((struct sockaddr *) from, fromlen, client))
 | 
						|
		AuthAudit(client, FALSE, (struct sockaddr *) from,
 | 
						|
			  fromlen, proto_n, auth_proto, auth_id);
 | 
						|
	    else
 | 
						|
	    {
 | 
						|
		auth_id = (XID) 0;
 | 
						|
#ifdef XSERVER_DTRACE
 | 
						|
		if ((auditTrailLevel > 1) || XSERVER_CLIENT_AUTH_ENABLED())
 | 
						|
#else
 | 
						|
		if (auditTrailLevel > 1)
 | 
						|
#endif
 | 
						|
		    AuthAudit(client, TRUE,
 | 
						|
			(struct sockaddr *) from, fromlen,
 | 
						|
			proto_n, auth_proto, auth_id);
 | 
						|
	    }
 | 
						|
 | 
						|
	    free(from);
 | 
						|
	}
 | 
						|
 | 
						|
	if (auth_id == (XID) ~0L) {
 | 
						|
	    if (reason)
 | 
						|
		return reason;
 | 
						|
	    else
 | 
						|
		return "Client is not authorized to connect to Server";
 | 
						|
	}
 | 
						|
    }
 | 
						|
#ifdef XSERVER_DTRACE
 | 
						|
    else if ((auditTrailLevel > 1) || XSERVER_CLIENT_AUTH_ENABLED())
 | 
						|
#else
 | 
						|
    else if (auditTrailLevel > 1)
 | 
						|
#endif
 | 
						|
    {
 | 
						|
	if (_XSERVTransGetPeerAddr (trans_conn,
 | 
						|
	    &family, &fromlen, &from) != -1)
 | 
						|
	{
 | 
						|
	    AuthAudit(client, TRUE, (struct sockaddr *) from, fromlen,
 | 
						|
		      proto_n, auth_proto, auth_id);
 | 
						|
 | 
						|
	    free(from);
 | 
						|
	}
 | 
						|
    }
 | 
						|
    priv->auth_id = auth_id;
 | 
						|
    priv->conn_time = 0;
 | 
						|
 | 
						|
#ifdef XDMCP
 | 
						|
    /* indicate to Xdmcp protocol that we've opened new client */
 | 
						|
    XdmcpOpenDisplay(priv->fd);
 | 
						|
#endif /* XDMCP */
 | 
						|
 | 
						|
    XaceHook(XACE_AUTH_AVAIL, client, auth_id);
 | 
						|
 | 
						|
    /* At this point, if the client is authorized to change the access control
 | 
						|
     * list, we should getpeername() information, and add the client to
 | 
						|
     * the selfhosts list.  It's not really the host machine, but the
 | 
						|
     * true purpose of the selfhosts list is to see who may change the
 | 
						|
     * access control list.
 | 
						|
     */
 | 
						|
    return((char *)NULL);
 | 
						|
}
 | 
						|
 | 
						|
static ClientPtr
 | 
						|
AllocNewConnection (XtransConnInfo trans_conn, int fd, CARD32 conn_time)
 | 
						|
{
 | 
						|
    OsCommPtr	oc;
 | 
						|
    ClientPtr	client;
 | 
						|
    
 | 
						|
    if (
 | 
						|
#ifndef WIN32
 | 
						|
	fd >= lastfdesc
 | 
						|
#else
 | 
						|
	XFD_SETCOUNT(&AllClients) >= MaxClients
 | 
						|
#endif
 | 
						|
	)
 | 
						|
	return NullClient;
 | 
						|
    oc = malloc(sizeof(OsCommRec));
 | 
						|
    if (!oc)
 | 
						|
	return NullClient;
 | 
						|
    oc->trans_conn = trans_conn;
 | 
						|
    oc->fd = fd;
 | 
						|
    oc->input = (ConnectionInputPtr)NULL;
 | 
						|
    oc->output = (ConnectionOutputPtr)NULL;
 | 
						|
    oc->auth_id = None;
 | 
						|
    oc->conn_time = conn_time;
 | 
						|
    if (!(client = NextAvailableClient((pointer)oc)))
 | 
						|
    {
 | 
						|
	free(oc);
 | 
						|
	return NullClient;
 | 
						|
    }
 | 
						|
    oc->local_client = ComputeLocalClient(client);
 | 
						|
#if !defined(WIN32)
 | 
						|
    ConnectionTranslation[fd] = client->index;
 | 
						|
#else
 | 
						|
    SetConnectionTranslation(fd, client->index);
 | 
						|
#endif
 | 
						|
    if (GrabInProgress)
 | 
						|
    {
 | 
						|
        FD_SET(fd, &SavedAllClients);
 | 
						|
        FD_SET(fd, &SavedAllSockets);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        FD_SET(fd, &AllClients);
 | 
						|
        FD_SET(fd, &AllSockets);
 | 
						|
    }
 | 
						|
 | 
						|
#ifdef DEBUG
 | 
						|
    ErrorF("AllocNewConnection: client index = %d, socket fd = %d\n",
 | 
						|
	   client->index, fd);
 | 
						|
#endif
 | 
						|
#ifdef XSERVER_DTRACE
 | 
						|
    XSERVER_CLIENT_CONNECT(client->index, fd);
 | 
						|
#endif	
 | 
						|
 | 
						|
    return client;
 | 
						|
}
 | 
						|
 | 
						|
/*****************
 | 
						|
 * EstablishNewConnections
 | 
						|
 *    If anyone is waiting on listened sockets, accept them.
 | 
						|
 *    Returns a mask with indices of new clients.  Updates AllClients
 | 
						|
 *    and AllSockets.
 | 
						|
 *****************/
 | 
						|
 | 
						|
/*ARGSUSED*/
 | 
						|
Bool
 | 
						|
EstablishNewConnections(ClientPtr clientUnused, pointer closure)
 | 
						|
{
 | 
						|
    fd_set  readyconnections;     /* set of listeners that are ready */
 | 
						|
    int curconn;                  /* fd of listener that's ready */
 | 
						|
    register int newconn;         /* fd of new client */
 | 
						|
    CARD32 connect_time;
 | 
						|
    register int i;
 | 
						|
    register ClientPtr client;
 | 
						|
    register OsCommPtr oc;
 | 
						|
    fd_set tmask;
 | 
						|
 | 
						|
    XFD_ANDSET (&tmask, (fd_set*)closure, &WellKnownConnections);
 | 
						|
    XFD_COPYSET(&tmask, &readyconnections);
 | 
						|
    if (!XFD_ANYSET(&readyconnections))
 | 
						|
	return TRUE;
 | 
						|
    connect_time = GetTimeInMillis();
 | 
						|
    /* kill off stragglers */
 | 
						|
    for (i=1; i<currentMaxClients; i++)
 | 
						|
    {
 | 
						|
	if ((client = clients[i]))
 | 
						|
	{
 | 
						|
	    oc = (OsCommPtr)(client->osPrivate);
 | 
						|
	    if ((oc && (oc->conn_time != 0) &&
 | 
						|
		(connect_time - oc->conn_time) >= TimeOutValue) || 
 | 
						|
		(client->noClientException != Success && !client->clientGone))
 | 
						|
		CloseDownClient(client);     
 | 
						|
	}
 | 
						|
    }
 | 
						|
#ifndef WIN32
 | 
						|
    for (i = 0; i < howmany(XFD_SETSIZE, NFDBITS); i++)
 | 
						|
    {
 | 
						|
      while (readyconnections.fds_bits[i])
 | 
						|
#else
 | 
						|
      for (i = 0; i < XFD_SETCOUNT(&readyconnections); i++) 
 | 
						|
#endif
 | 
						|
      {
 | 
						|
	XtransConnInfo trans_conn, new_trans_conn;
 | 
						|
	int status;
 | 
						|
 | 
						|
#ifndef WIN32
 | 
						|
	curconn = mffs (readyconnections.fds_bits[i]) - 1;
 | 
						|
	readyconnections.fds_bits[i] &= ~((fd_mask)1 << curconn);
 | 
						|
	curconn += (i * (sizeof(fd_mask)*8));
 | 
						|
#else
 | 
						|
	curconn = XFD_FD(&readyconnections, i);
 | 
						|
#endif
 | 
						|
 | 
						|
	if ((trans_conn = lookup_trans_conn (curconn)) == NULL)
 | 
						|
	    continue;
 | 
						|
 | 
						|
	if ((new_trans_conn = _XSERVTransAccept (trans_conn, &status)) == NULL)
 | 
						|
	    continue;
 | 
						|
 | 
						|
	newconn = _XSERVTransGetConnectionNumber (new_trans_conn);
 | 
						|
 | 
						|
	if (newconn < lastfdesc)
 | 
						|
	{
 | 
						|
		int clientid;
 | 
						|
#if !defined(WIN32)
 | 
						|
  		clientid = ConnectionTranslation[newconn];
 | 
						|
#else
 | 
						|
  		clientid = GetConnectionTranslation(newconn);
 | 
						|
#endif
 | 
						|
		if(clientid && (client = clients[clientid]))
 | 
						|
 			CloseDownClient(client);
 | 
						|
	}
 | 
						|
 | 
						|
	_XSERVTransSetOption(new_trans_conn, TRANS_NONBLOCKING, 1);
 | 
						|
 | 
						|
	if(trans_conn->flags & TRANS_NOXAUTH)
 | 
						|
	    new_trans_conn->flags = new_trans_conn->flags | TRANS_NOXAUTH;
 | 
						|
 | 
						|
	if (!AllocNewConnection (new_trans_conn, newconn, connect_time))
 | 
						|
	{
 | 
						|
	    ErrorConnMax(new_trans_conn);
 | 
						|
	    _XSERVTransClose(new_trans_conn);
 | 
						|
	}
 | 
						|
      }
 | 
						|
#ifndef WIN32
 | 
						|
    }
 | 
						|
#endif
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
#define NOROOM "Maximum number of clients reached"
 | 
						|
 | 
						|
/************
 | 
						|
 *   ErrorConnMax
 | 
						|
 *     Fail a connection due to lack of client or file descriptor space
 | 
						|
 ************/
 | 
						|
 | 
						|
static void
 | 
						|
ErrorConnMax(XtransConnInfo trans_conn)
 | 
						|
{
 | 
						|
    int fd = _XSERVTransGetConnectionNumber (trans_conn);
 | 
						|
    xConnSetupPrefix csp;
 | 
						|
    char pad[3];
 | 
						|
    struct iovec iov[3];
 | 
						|
    char byteOrder = 0;
 | 
						|
    int whichbyte = 1;
 | 
						|
    struct timeval waittime;
 | 
						|
    fd_set mask;
 | 
						|
 | 
						|
    /* if these seems like a lot of trouble to go to, it probably is */
 | 
						|
    waittime.tv_sec = BOTIMEOUT / MILLI_PER_SECOND;
 | 
						|
    waittime.tv_usec = (BOTIMEOUT % MILLI_PER_SECOND) *
 | 
						|
		       (1000000 / MILLI_PER_SECOND);
 | 
						|
    FD_ZERO(&mask);
 | 
						|
    FD_SET(fd, &mask);
 | 
						|
    (void)Select(fd + 1, &mask, NULL, NULL, &waittime);
 | 
						|
    /* try to read the byte-order of the connection */
 | 
						|
    (void)_XSERVTransRead(trans_conn, &byteOrder, 1);
 | 
						|
    if ((byteOrder == 'l') || (byteOrder == 'B'))
 | 
						|
    {
 | 
						|
	csp.success = xFalse;
 | 
						|
	csp.lengthReason = sizeof(NOROOM) - 1;
 | 
						|
	csp.length = (sizeof(NOROOM) + 2) >> 2;
 | 
						|
	csp.majorVersion = X_PROTOCOL;
 | 
						|
	csp.minorVersion = X_PROTOCOL_REVISION;
 | 
						|
	if (((*(char *) &whichbyte) && (byteOrder == 'B')) ||
 | 
						|
	    (!(*(char *) &whichbyte) && (byteOrder == 'l')))
 | 
						|
	{
 | 
						|
	    swaps(&csp.majorVersion);
 | 
						|
	    swaps(&csp.minorVersion);
 | 
						|
	    swaps(&csp.length);
 | 
						|
	}
 | 
						|
	iov[0].iov_len = sz_xConnSetupPrefix;
 | 
						|
	iov[0].iov_base = (char *) &csp;
 | 
						|
	iov[1].iov_len = csp.lengthReason;
 | 
						|
	iov[1].iov_base = NOROOM;
 | 
						|
	iov[2].iov_len = (4 - (csp.lengthReason & 3)) & 3;
 | 
						|
	iov[2].iov_base = pad;
 | 
						|
	(void)_XSERVTransWritev(trans_conn, iov, 3);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/************
 | 
						|
 *   CloseDownFileDescriptor:
 | 
						|
 *     Remove this file descriptor and it's I/O buffers, etc.
 | 
						|
 ************/
 | 
						|
 | 
						|
static void
 | 
						|
CloseDownFileDescriptor(OsCommPtr oc)
 | 
						|
{
 | 
						|
    int connection = oc->fd;
 | 
						|
 | 
						|
    if (oc->trans_conn) {
 | 
						|
	_XSERVTransDisconnect(oc->trans_conn);
 | 
						|
	_XSERVTransClose(oc->trans_conn);
 | 
						|
    }
 | 
						|
#ifndef WIN32
 | 
						|
    ConnectionTranslation[connection] = 0;
 | 
						|
#else
 | 
						|
    SetConnectionTranslation(connection, 0);
 | 
						|
#endif    
 | 
						|
    FD_CLR(connection, &AllSockets);
 | 
						|
    FD_CLR(connection, &AllClients);
 | 
						|
    FD_CLR(connection, &ClientsWithInput);
 | 
						|
    FD_CLR(connection, &GrabImperviousClients);
 | 
						|
    if (GrabInProgress)
 | 
						|
    {
 | 
						|
	FD_CLR(connection, &SavedAllSockets);
 | 
						|
	FD_CLR(connection, &SavedAllClients);
 | 
						|
	FD_CLR(connection, &SavedClientsWithInput);
 | 
						|
    }
 | 
						|
    FD_CLR(connection, &ClientsWriteBlocked);
 | 
						|
    if (!XFD_ANYSET(&ClientsWriteBlocked))
 | 
						|
    	AnyClientsWriteBlocked = FALSE;
 | 
						|
    FD_CLR(connection, &OutputPending);
 | 
						|
}
 | 
						|
 | 
						|
/*****************
 | 
						|
 * CheckConnections
 | 
						|
 *    Some connection has died, go find which one and shut it down 
 | 
						|
 *    The file descriptor has been closed, but is still in AllClients.
 | 
						|
 *    If would truly be wonderful if select() would put the bogus
 | 
						|
 *    file descriptors in the exception mask, but nooooo.  So we have
 | 
						|
 *    to check each and every socket individually.
 | 
						|
 *****************/
 | 
						|
 | 
						|
void
 | 
						|
CheckConnections(void)
 | 
						|
{
 | 
						|
#ifndef WIN32
 | 
						|
    fd_mask		mask;
 | 
						|
#endif
 | 
						|
    fd_set		tmask; 
 | 
						|
    int			curclient, curoff;
 | 
						|
    int			i;
 | 
						|
    struct timeval	notime;
 | 
						|
    int r;
 | 
						|
#ifdef WIN32
 | 
						|
    fd_set savedAllClients;
 | 
						|
#endif
 | 
						|
 | 
						|
    notime.tv_sec = 0;
 | 
						|
    notime.tv_usec = 0;
 | 
						|
 | 
						|
#ifndef WIN32
 | 
						|
    for (i=0; i<howmany(XFD_SETSIZE, NFDBITS); i++)
 | 
						|
    {
 | 
						|
	mask = AllClients.fds_bits[i];
 | 
						|
        while (mask)
 | 
						|
    	{
 | 
						|
	    curoff = mffs (mask) - 1;
 | 
						|
	    curclient = curoff + (i * (sizeof(fd_mask)*8));
 | 
						|
            FD_ZERO(&tmask);
 | 
						|
            FD_SET(curclient, &tmask);
 | 
						|
            do {
 | 
						|
                r = Select (curclient + 1, &tmask, NULL, NULL, ¬ime);
 | 
						|
            } while (r < 0 && (errno == EINTR || errno == EAGAIN));
 | 
						|
            if (r < 0)
 | 
						|
                if (ConnectionTranslation[curclient] > 0)
 | 
						|
                    CloseDownClient(clients[ConnectionTranslation[curclient]]);
 | 
						|
	    mask &= ~((fd_mask)1 << curoff);
 | 
						|
	}
 | 
						|
    }	
 | 
						|
#else
 | 
						|
    XFD_COPYSET(&AllClients, &savedAllClients);
 | 
						|
    for (i = 0; i < XFD_SETCOUNT(&savedAllClients); i++)
 | 
						|
    {
 | 
						|
	curclient = XFD_FD(&savedAllClients, i);
 | 
						|
	FD_ZERO(&tmask);
 | 
						|
	FD_SET(curclient, &tmask);
 | 
						|
        do {
 | 
						|
            r = Select (curclient + 1, &tmask, NULL, NULL, ¬ime);
 | 
						|
        } while (r < 0 && (errno == EINTR || errno == EAGAIN));
 | 
						|
	if (r < 0)
 | 
						|
            if (GetConnectionTranslation(curclient) > 0)
 | 
						|
                CloseDownClient(clients[GetConnectionTranslation(curclient)]);
 | 
						|
    }	
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*****************
 | 
						|
 * CloseDownConnection
 | 
						|
 *    Delete client from AllClients and free resources 
 | 
						|
 *****************/
 | 
						|
 | 
						|
void
 | 
						|
CloseDownConnection(ClientPtr client)
 | 
						|
{
 | 
						|
    OsCommPtr oc = (OsCommPtr)client->osPrivate;
 | 
						|
 | 
						|
    if (FlushCallback)
 | 
						|
	CallCallbacks(&FlushCallback, NULL);
 | 
						|
 | 
						|
    if (oc->output && oc->output->count)
 | 
						|
	FlushClient(client, oc, (char *)NULL, 0);
 | 
						|
#ifdef XDMCP
 | 
						|
    XdmcpCloseDisplay(oc->fd);
 | 
						|
#endif
 | 
						|
    CloseDownFileDescriptor(oc);
 | 
						|
    FreeOsBuffers(oc);
 | 
						|
    free(client->osPrivate);
 | 
						|
    client->osPrivate = (pointer)NULL;
 | 
						|
    if (auditTrailLevel > 1)
 | 
						|
	AuditF("client %d disconnected\n", client->index);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
AddGeneralSocket(int fd)
 | 
						|
{
 | 
						|
    FD_SET(fd, &AllSockets);
 | 
						|
    if (GrabInProgress)
 | 
						|
	FD_SET(fd, &SavedAllSockets);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
AddEnabledDevice(int fd)
 | 
						|
{
 | 
						|
    FD_SET(fd, &EnabledDevices);
 | 
						|
    AddGeneralSocket(fd);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
RemoveGeneralSocket(int fd)
 | 
						|
{
 | 
						|
    FD_CLR(fd, &AllSockets);
 | 
						|
    if (GrabInProgress)
 | 
						|
	FD_CLR(fd, &SavedAllSockets);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
RemoveEnabledDevice(int fd)
 | 
						|
{
 | 
						|
    FD_CLR(fd, &EnabledDevices);
 | 
						|
    RemoveGeneralSocket(fd);
 | 
						|
}
 | 
						|
 | 
						|
/*****************
 | 
						|
 * OnlyListenToOneClient:
 | 
						|
 *    Only accept requests from  one client.  Continue to handle new
 | 
						|
 *    connections, but don't take any protocol requests from the new
 | 
						|
 *    ones.  Note that if GrabInProgress is set, EstablishNewConnections
 | 
						|
 *    needs to put new clients into SavedAllSockets and SavedAllClients.
 | 
						|
 *    Note also that there is no timeout for this in the protocol.
 | 
						|
 *    This routine is "undone" by ListenToAllClients()
 | 
						|
 *****************/
 | 
						|
 | 
						|
int
 | 
						|
OnlyListenToOneClient(ClientPtr client)
 | 
						|
{
 | 
						|
    OsCommPtr oc = (OsCommPtr)client->osPrivate;
 | 
						|
    int rc, connection = oc->fd;
 | 
						|
 | 
						|
    rc = XaceHook(XACE_SERVER_ACCESS, client, DixGrabAccess);
 | 
						|
    if (rc != Success)
 | 
						|
	return rc;
 | 
						|
 | 
						|
    if (! GrabInProgress)
 | 
						|
    {
 | 
						|
	XFD_COPYSET(&ClientsWithInput, &SavedClientsWithInput);
 | 
						|
	XFD_ANDSET(&ClientsWithInput,
 | 
						|
		       &ClientsWithInput, &GrabImperviousClients);
 | 
						|
	if (FD_ISSET(connection, &SavedClientsWithInput))
 | 
						|
	{
 | 
						|
	    FD_CLR(connection, &SavedClientsWithInput);
 | 
						|
	    FD_SET(connection, &ClientsWithInput);
 | 
						|
	}
 | 
						|
	XFD_UNSET(&SavedClientsWithInput, &GrabImperviousClients);
 | 
						|
	XFD_COPYSET(&AllSockets, &SavedAllSockets);
 | 
						|
	XFD_COPYSET(&AllClients, &SavedAllClients);
 | 
						|
	XFD_UNSET(&AllSockets, &AllClients);
 | 
						|
	XFD_ANDSET(&AllClients, &AllClients, &GrabImperviousClients);
 | 
						|
	FD_SET(connection, &AllClients);
 | 
						|
	XFD_ORSET(&AllSockets, &AllSockets, &AllClients);
 | 
						|
	GrabInProgress = client->index;
 | 
						|
    }
 | 
						|
    return rc;
 | 
						|
}
 | 
						|
 | 
						|
/****************
 | 
						|
 * ListenToAllClients:
 | 
						|
 *    Undoes OnlyListentToOneClient()
 | 
						|
 ****************/
 | 
						|
 | 
						|
void
 | 
						|
ListenToAllClients(void)
 | 
						|
{
 | 
						|
    if (GrabInProgress)
 | 
						|
    {
 | 
						|
	XFD_ORSET(&AllSockets, &AllSockets, &SavedAllSockets);
 | 
						|
	XFD_ORSET(&AllClients, &AllClients, &SavedAllClients);
 | 
						|
	XFD_ORSET(&ClientsWithInput, &ClientsWithInput, &SavedClientsWithInput);
 | 
						|
	GrabInProgress = 0;
 | 
						|
    }	
 | 
						|
}
 | 
						|
 | 
						|
/****************
 | 
						|
 * IgnoreClient
 | 
						|
 *    Removes one client from input masks.
 | 
						|
 *    Must have cooresponding call to AttendClient.
 | 
						|
 ****************/
 | 
						|
 | 
						|
void
 | 
						|
IgnoreClient (ClientPtr client)
 | 
						|
{
 | 
						|
    OsCommPtr oc = (OsCommPtr)client->osPrivate;
 | 
						|
    int connection = oc->fd;
 | 
						|
 | 
						|
    client->ignoreCount++;
 | 
						|
    if (client->ignoreCount > 1)
 | 
						|
	return;
 | 
						|
 | 
						|
    isItTimeToYield = TRUE;
 | 
						|
    if (!GrabInProgress || FD_ISSET(connection, &AllClients))
 | 
						|
    {
 | 
						|
    	if (FD_ISSET (connection, &ClientsWithInput))
 | 
						|
	    FD_SET(connection, &IgnoredClientsWithInput);
 | 
						|
    	else
 | 
						|
	    FD_CLR(connection, &IgnoredClientsWithInput);
 | 
						|
    	FD_CLR(connection, &ClientsWithInput);
 | 
						|
    	FD_CLR(connection, &AllSockets);
 | 
						|
    	FD_CLR(connection, &AllClients);
 | 
						|
	FD_CLR(connection, &LastSelectMask);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
    	if (FD_ISSET (connection, &SavedClientsWithInput))
 | 
						|
	    FD_SET(connection, &IgnoredClientsWithInput);
 | 
						|
    	else
 | 
						|
	    FD_CLR(connection, &IgnoredClientsWithInput);
 | 
						|
	FD_CLR(connection, &SavedClientsWithInput);
 | 
						|
	FD_CLR(connection, &SavedAllSockets);
 | 
						|
	FD_CLR(connection, &SavedAllClients);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/****************
 | 
						|
 * AttendClient
 | 
						|
 *    Adds one client back into the input masks.
 | 
						|
 ****************/
 | 
						|
 | 
						|
void
 | 
						|
AttendClient (ClientPtr client)
 | 
						|
{
 | 
						|
    OsCommPtr oc = (OsCommPtr)client->osPrivate;
 | 
						|
    int connection = oc->fd;
 | 
						|
 | 
						|
    client->ignoreCount--;
 | 
						|
    if (client->ignoreCount)
 | 
						|
	return;
 | 
						|
 | 
						|
    if (!GrabInProgress || GrabInProgress == client->index ||
 | 
						|
	FD_ISSET(connection, &GrabImperviousClients))
 | 
						|
    {
 | 
						|
    	FD_SET(connection, &AllClients);
 | 
						|
    	FD_SET(connection, &AllSockets);
 | 
						|
	FD_SET(connection, &LastSelectMask);
 | 
						|
    	if (FD_ISSET (connection, &IgnoredClientsWithInput))
 | 
						|
	    FD_SET(connection, &ClientsWithInput);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
	FD_SET(connection, &SavedAllClients);
 | 
						|
	FD_SET(connection, &SavedAllSockets);
 | 
						|
	if (FD_ISSET(connection, &IgnoredClientsWithInput))
 | 
						|
	    FD_SET(connection, &SavedClientsWithInput);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/* make client impervious to grabs; assume only executing client calls this */
 | 
						|
 | 
						|
void
 | 
						|
MakeClientGrabImpervious(ClientPtr client)
 | 
						|
{
 | 
						|
    OsCommPtr oc = (OsCommPtr)client->osPrivate;
 | 
						|
    int connection = oc->fd;
 | 
						|
 | 
						|
    FD_SET(connection, &GrabImperviousClients);
 | 
						|
 | 
						|
    if (ServerGrabCallback)
 | 
						|
    {
 | 
						|
	ServerGrabInfoRec grabinfo;
 | 
						|
	grabinfo.client = client;
 | 
						|
	grabinfo.grabstate  = CLIENT_IMPERVIOUS;
 | 
						|
	CallCallbacks(&ServerGrabCallback, &grabinfo);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/* make client pervious to grabs; assume only executing client calls this */
 | 
						|
 | 
						|
void
 | 
						|
MakeClientGrabPervious(ClientPtr client)
 | 
						|
{
 | 
						|
    OsCommPtr oc = (OsCommPtr)client->osPrivate;
 | 
						|
    int connection = oc->fd;
 | 
						|
 | 
						|
    FD_CLR(connection, &GrabImperviousClients);
 | 
						|
    if (GrabInProgress && (GrabInProgress != client->index))
 | 
						|
    {
 | 
						|
	if (FD_ISSET(connection, &ClientsWithInput))
 | 
						|
	{
 | 
						|
	    FD_SET(connection, &SavedClientsWithInput);
 | 
						|
	    FD_CLR(connection, &ClientsWithInput);
 | 
						|
	}
 | 
						|
	FD_CLR(connection, &AllSockets);
 | 
						|
	FD_CLR(connection, &AllClients);
 | 
						|
	isItTimeToYield = TRUE;
 | 
						|
    }
 | 
						|
 | 
						|
    if (ServerGrabCallback)
 | 
						|
    {
 | 
						|
	ServerGrabInfoRec grabinfo;
 | 
						|
	grabinfo.client = client;
 | 
						|
	grabinfo.grabstate  = CLIENT_PERVIOUS;
 | 
						|
	CallCallbacks(&ServerGrabCallback, &grabinfo);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
#ifdef XQUARTZ
 | 
						|
/* Add a fd (from launchd) to our listeners */
 | 
						|
void ListenOnOpenFD(int fd, int noxauth) {
 | 
						|
    char port[256];
 | 
						|
    XtransConnInfo ciptr;
 | 
						|
    const char *display_env = getenv("DISPLAY");
 | 
						|
 | 
						|
    if(display_env && (strncmp(display_env, "/tmp/launch", 11) == 0)) {
 | 
						|
        /* Make the path the launchd socket if our DISPLAY is set right */
 | 
						|
        strcpy(port, display_env);
 | 
						|
    } else {
 | 
						|
        /* Just some default so things don't break and die. */
 | 
						|
        snprintf(port, sizeof(port), ":%d", atoi(display));
 | 
						|
    }
 | 
						|
 | 
						|
    /* Make our XtransConnInfo
 | 
						|
     * TRANS_SOCKET_LOCAL_INDEX = 5 from Xtrans.c
 | 
						|
     */
 | 
						|
    ciptr = _XSERVTransReopenCOTSServer(5, fd, port);
 | 
						|
    if(ciptr == NULL) {
 | 
						|
        ErrorF("Got NULL while trying to Reopen launchd port.\n");
 | 
						|
        return;
 | 
						|
    }
 | 
						|
    
 | 
						|
    if(noxauth)
 | 
						|
        ciptr->flags = ciptr->flags | TRANS_NOXAUTH;
 | 
						|
 | 
						|
    /* Allocate space to store it */
 | 
						|
    ListenTransFds = (int *) realloc(ListenTransFds, (ListenTransCount + 1) * sizeof (int));
 | 
						|
    ListenTransConns = (XtransConnInfo *) realloc(ListenTransConns, (ListenTransCount + 1) * sizeof (XtransConnInfo));
 | 
						|
    
 | 
						|
    /* Store it */
 | 
						|
    ListenTransConns[ListenTransCount] = ciptr;
 | 
						|
    ListenTransFds[ListenTransCount] = fd;
 | 
						|
 | 
						|
    FD_SET(fd, &WellKnownConnections);
 | 
						|
    FD_SET(fd, &AllSockets);
 | 
						|
    
 | 
						|
    /* Increment the count */
 | 
						|
    ListenTransCount++;
 | 
						|
 | 
						|
    /* This *might* not be needed... /shrug */
 | 
						|
    ResetAuthorization();
 | 
						|
    ResetHosts(display);
 | 
						|
#ifdef XDMCP
 | 
						|
    XdmcpReset();
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
#endif
 |