Home | History | Annotate | Line # | Download | only in os
      1 /***********************************************************
      2 
      3 Copyright 1987, 1989, 1998  The Open Group
      4 
      5 Permission to use, copy, modify, distribute, and sell this software and its
      6 documentation for any purpose is hereby granted without fee, provided that
      7 the above copyright notice appear in all copies and that both that
      8 copyright notice and this permission notice appear in supporting
      9 documentation.
     10 
     11 The above copyright notice and this permission notice shall be included in
     12 all copies or substantial portions of the Software.
     13 
     14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
     17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     20 
     21 Except as contained in this notice, the name of The Open Group shall not be
     22 used in advertising or otherwise to promote the sale, use or other dealings
     23 in this Software without prior written authorization from The Open Group.
     24 
     25 
     26 Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
     27 
     28                         All Rights Reserved
     29 
     30 Permission to use, copy, modify, and distribute this software and its
     31 documentation for any purpose and without fee is hereby granted,
     32 provided that the above copyright notice appear in all copies and that
     33 both that copyright notice and this permission notice appear in
     34 supporting documentation, and that the name of Digital not be
     35 used in advertising or publicity pertaining to distribution of the
     36 software without specific, written prior permission.
     37 
     38 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
     39 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
     40 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
     41 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
     42 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
     43 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
     44 SOFTWARE.
     45 
     46 ******************************************************************/
     47 /*****************************************************************
     48  *  Stuff to create connections --- OS dependent
     49  *
     50  *      EstablishNewConnections, CreateWellKnownSockets, ResetWellKnownSockets,
     51  *      CloseDownConnection, CheckConnections, AddEnabledDevice,
     52  *	RemoveEnabledDevice, OnlyListToOneClient,
     53  *      ListenToAllClients,
     54  *
     55  *      (WaitForSomething is in its own file)
     56  *
     57  *      In this implementation, a client socket table is not kept.
     58  *      Instead, what would be the index into the table is just the
     59  *      file descriptor of the socket.  This won't work for if the
     60  *      socket ids aren't small nums (0 - 2^8)
     61  *
     62  *****************************************************************/
     63 
     64 #include <X11/Xpoll.h>
     65 
     66 #ifdef HAVE_DIX_CONFIG_H
     67 #include <dix-config.h>
     68 #endif
     69 
     70 #ifdef WIN32
     71 #include <X11/Xwinsock.h>
     72 #endif
     73 #include <X11/X.h>
     74 #include <X11/Xproto.h>
     75 #define XSERV_t
     76 #define TRANS_SERVER
     77 #define TRANS_REOPEN
     78 #include <X11/Xtrans/Xtrans.h>
     79 #include <X11/Xtrans/Xtransint.h>
     80 #include <errno.h>
     81 #include <signal.h>
     82 #include <stdio.h>
     83 #include <stdlib.h>
     84 
     85 #ifndef WIN32
     86 #include <sys/socket.h>
     87 
     88 
     89 
     90 #if defined(TCPCONN) || defined(STREAMSCONN)
     91 # include <netinet/in.h>
     92 # include <arpa/inet.h>
     93 #  ifdef apollo
     94 #   ifndef NO_TCP_H
     95 #    include <netinet/tcp.h>
     96 #   endif
     97 #  else
     98 #   ifdef CSRG_BASED
     99 #    include <sys/param.h>
    100 #   endif
    101 #   include <netinet/tcp.h>
    102 #  endif
    103 # include <arpa/inet.h>
    104 #endif
    105 
    106 #include <sys/uio.h>
    107 
    108 #endif /* WIN32 */
    109 #include "misc.h"		/* for typedef of pointer */
    110 #include "osdep.h"
    111 #include "opaque.h"
    112 #include "dixstruct.h"
    113 #include "xace.h"
    114 
    115 #define Pid_t pid_t
    116 
    117 
    118 #ifdef HAS_GETPEERUCRED
    119 # include <ucred.h>
    120 # include <zone.h>
    121 #endif
    122 
    123 #ifdef XSERVER_DTRACE
    124 # include <sys/types.h>
    125 typedef const char *string;
    126 # ifndef HAS_GETPEERUCRED
    127 #  define zoneid_t int
    128 # endif
    129 # include "../dix/Xserver-dtrace.h"
    130 #endif
    131 
    132 static int lastfdesc;		/* maximum file descriptor */
    133 
    134 fd_set WellKnownConnections;	/* Listener mask */
    135 fd_set EnabledDevices;		/* mask for input devices that are on */
    136 fd_set AllSockets;		/* select on this */
    137 fd_set AllClients;		/* available clients */
    138 fd_set LastSelectMask;		/* mask returned from last select call */
    139 fd_set ClientsWithInput;	/* clients with FULL requests in buffer */
    140 fd_set ClientsWriteBlocked;	/* clients who cannot receive output */
    141 fd_set OutputPending;		/* clients with reply/event data ready to go */
    142 int MaxClients = 0;
    143 Bool NewOutputPending;		/* not yet attempted to write some new output */
    144 Bool AnyClientsWriteBlocked;	/* true if some client blocked on write */
    145 
    146 static Bool RunFromSmartParent;	/* send SIGUSR1 to parent process */
    147 Bool RunFromSigStopParent;	/* send SIGSTOP to our own process; Upstart (or
    148 				   equivalent) will send SIGCONT back. */
    149 Bool PartialNetwork;	/* continue even if unable to bind all addrs */
    150 static Pid_t ParentProcess;
    151 
    152 static Bool debug_conns = FALSE;
    153 
    154 fd_set IgnoredClientsWithInput;
    155 static fd_set GrabImperviousClients;
    156 static fd_set SavedAllClients;
    157 static fd_set SavedAllSockets;
    158 static fd_set SavedClientsWithInput;
    159 int GrabInProgress = 0;
    160 
    161 #if !defined(WIN32)
    162 int *ConnectionTranslation = NULL;
    163 #else
    164 /*
    165  * On NT fds are not between 0 and MAXSOCKS, they are unrelated, and there is
    166  * not even a known maximum value, so use something quite arbitrary for now.
    167  * Do storage is a hash table of size 256. Collisions are handled in a linked
    168  * list.
    169  */
    170 
    171 #undef MAXSOCKS
    172 #define MAXSOCKS 500
    173 #undef MAXSELECT
    174 #define MAXSELECT 500
    175 
    176 struct _ct_node {
    177     struct _ct_node *next;
    178     int key;
    179     int value;
    180 };
    181 
    182 struct _ct_node *ct_head[256];
    183 
    184 void InitConnectionTranslation(void)
    185 {
    186     memset(ct_head, 0, sizeof(ct_head));
    187 }
    188 
    189 int GetConnectionTranslation(int conn)
    190 {
    191     struct _ct_node *node = ct_head[conn & 0xff];
    192     while (node != NULL)
    193     {
    194         if (node->key == conn)
    195             return node->value;
    196         node = node->next;
    197     }
    198     return 0;
    199 }
    200 
    201 void SetConnectionTranslation(int conn, int client)
    202 {
    203     struct _ct_node **node = ct_head + (conn & 0xff);
    204     if (client == 0) /* remove entry */
    205     {
    206         while (*node != NULL)
    207         {
    208             if ((*node)->key == conn)
    209             {
    210                 struct _ct_node *temp = *node;
    211                 *node = (*node)->next;
    212                 free(temp);
    213                 return;
    214             }
    215             node = &((*node)->next);
    216         }
    217         return;
    218     } else
    219     {
    220         while (*node != NULL)
    221         {
    222             if ((*node)->key == conn)
    223             {
    224                 (*node)->value = client;
    225                 return;
    226             }
    227             node = &((*node)->next);
    228         }
    229         *node = malloc(sizeof(struct _ct_node));
    230         (*node)->next = NULL;
    231         (*node)->key = conn;
    232         (*node)->value = client;
    233         return;
    234     }
    235 }
    236 
    237 void ClearConnectionTranslation(void)
    238 {
    239     unsigned i;
    240     for (i = 0; i < 256; i++)
    241     {
    242         struct _ct_node *node = ct_head[i];
    243         while (node != NULL)
    244         {
    245             struct _ct_node *temp = node;
    246             node = node->next;
    247             free(temp);
    248         }
    249     }
    250 }
    251 #endif
    252 
    253 static XtransConnInfo 	*ListenTransConns = NULL;
    254 static int	       	*ListenTransFds = NULL;
    255 static int		ListenTransCount;
    256 
    257 static void ErrorConnMax(XtransConnInfo /* trans_conn */);
    258 
    259 static XtransConnInfo
    260 lookup_trans_conn (int fd)
    261 {
    262     if (ListenTransFds)
    263     {
    264 	int i;
    265 	for (i = 0; i < ListenTransCount; i++)
    266 	    if (ListenTransFds[i] == fd)
    267 		return ListenTransConns[i];
    268     }
    269 
    270     return NULL;
    271 }
    272 
    273 /* Set MaxClients and lastfdesc, and allocate ConnectionTranslation */
    274 
    275 void
    276 InitConnectionLimits(void)
    277 {
    278     lastfdesc = -1;
    279 
    280 #ifndef __CYGWIN__
    281 
    282 #if !defined(XNO_SYSCONF) && defined(_SC_OPEN_MAX)
    283     lastfdesc = sysconf(_SC_OPEN_MAX) - 1;
    284 #endif
    285 
    286 #ifdef HAS_GETDTABLESIZE
    287     if (lastfdesc < 0)
    288 	lastfdesc = getdtablesize() - 1;
    289 #endif
    290 
    291 #ifdef _NFILE
    292     if (lastfdesc < 0)
    293 	lastfdesc = _NFILE - 1;
    294 #endif
    295 
    296 #endif /* __CYGWIN__ */
    297 
    298     /* This is the fallback */
    299     if (lastfdesc < 0)
    300 	lastfdesc = MAXSOCKS;
    301 
    302     if (lastfdesc > MAXSELECT)
    303 	lastfdesc = MAXSELECT;
    304 
    305     if (lastfdesc > MAXCLIENTS)
    306     {
    307 	lastfdesc = MAXCLIENTS;
    308 	if (debug_conns)
    309 	    ErrorF( "REACHED MAXIMUM CLIENTS LIMIT %d\n", MAXCLIENTS);
    310     }
    311     MaxClients = lastfdesc;
    312 
    313 #ifdef DEBUG
    314     ErrorF("InitConnectionLimits: MaxClients = %d\n", MaxClients);
    315 #endif
    316 
    317 #if !defined(WIN32)
    318     if (!ConnectionTranslation)
    319         ConnectionTranslation = (int *)xnfalloc(sizeof(int)*(lastfdesc + 1));
    320 #else
    321     InitConnectionTranslation();
    322 #endif
    323 }
    324 
    325 /*
    326  * If SIGUSR1 was set to SIG_IGN when the server started, assume that either
    327  *
    328  *  a- The parent process is ignoring SIGUSR1
    329  *
    330  * or
    331  *
    332  *  b- The parent process is expecting a SIGUSR1
    333  *     when the server is ready to accept connections
    334  *
    335  * In the first case, the signal will be harmless, in the second case,
    336  * the signal will be quite useful.
    337  */
    338 static void
    339 InitParentProcess(void)
    340 {
    341 #if !defined(WIN32)
    342     OsSigHandlerPtr handler;
    343     handler = OsSignal (SIGUSR1, SIG_IGN);
    344     if ( handler == SIG_IGN)
    345 	RunFromSmartParent = TRUE;
    346     OsSignal(SIGUSR1, handler);
    347     ParentProcess = getppid ();
    348 #endif
    349 }
    350 
    351 void
    352 NotifyParentProcess(void)
    353 {
    354 #if !defined(WIN32)
    355     if (RunFromSmartParent) {
    356 	if (ParentProcess > 1) {
    357 	    kill (ParentProcess, SIGUSR1);
    358 	}
    359     }
    360     if (RunFromSigStopParent)
    361 	raise (SIGSTOP);
    362 #endif
    363 }
    364 
    365 /*****************
    366  * CreateWellKnownSockets
    367  *    At initialization, create the sockets to listen on for new clients.
    368  *****************/
    369 
    370 void
    371 CreateWellKnownSockets(void)
    372 {
    373     int		i;
    374     int		partial;
    375     char 	port[20];
    376 
    377     FD_ZERO(&AllSockets);
    378     FD_ZERO(&AllClients);
    379     FD_ZERO(&LastSelectMask);
    380     FD_ZERO(&ClientsWithInput);
    381 
    382 #if !defined(WIN32)
    383     for (i=0; i<MaxClients; i++) ConnectionTranslation[i] = 0;
    384 #else
    385     ClearConnectionTranslation();
    386 #endif
    387 
    388     FD_ZERO (&WellKnownConnections);
    389 
    390     sprintf (port, "%d", atoi (display));
    391 
    392     if ((_XSERVTransMakeAllCOTSServerListeners (port, &partial,
    393 	&ListenTransCount, &ListenTransConns) >= 0) &&
    394 	(ListenTransCount >= 1))
    395     {
    396 	if (!PartialNetwork && partial)
    397 	{
    398 	    FatalError ("Failed to establish all listening sockets");
    399 	}
    400 	else
    401 	{
    402 	    ListenTransFds = malloc(ListenTransCount * sizeof (int));
    403 
    404 	    for (i = 0; i < ListenTransCount; i++)
    405 	    {
    406 		int fd = _XSERVTransGetConnectionNumber (ListenTransConns[i]);
    407 
    408 		ListenTransFds[i] = fd;
    409 		FD_SET (fd, &WellKnownConnections);
    410 
    411 		if (!_XSERVTransIsLocal (ListenTransConns[i]))
    412 		{
    413 		    DefineSelf (fd);
    414 		}
    415 	    }
    416 	}
    417     }
    418 
    419     if (!XFD_ANYSET (&WellKnownConnections))
    420         FatalError ("Cannot establish any listening sockets - Make sure an X server isn't already running");
    421 #if !defined(WIN32)
    422     OsSignal (SIGPIPE, SIG_IGN);
    423     OsSignal (SIGHUP, AutoResetServer);
    424 #endif
    425     OsSignal (SIGINT, GiveUp);
    426     OsSignal (SIGTERM, GiveUp);
    427     XFD_COPYSET (&WellKnownConnections, &AllSockets);
    428     ResetHosts(display);
    429 
    430     InitParentProcess();
    431 
    432 #ifdef XDMCP
    433     XdmcpInit ();
    434 #endif
    435 }
    436 
    437 void
    438 ResetWellKnownSockets (void)
    439 {
    440     int i;
    441 
    442     ResetOsBuffers();
    443 
    444     for (i = 0; i < ListenTransCount; i++)
    445     {
    446 	int status = _XSERVTransResetListener (ListenTransConns[i]);
    447 
    448 	if (status != TRANS_RESET_NOOP)
    449 	{
    450 	    if (status == TRANS_RESET_FAILURE)
    451 	    {
    452 		/*
    453 		 * ListenTransConns[i] freed by xtrans.
    454 		 * Remove it from out list.
    455 		 */
    456 
    457 		FD_CLR (ListenTransFds[i], &WellKnownConnections);
    458 		ListenTransFds[i] = ListenTransFds[ListenTransCount - 1];
    459 		ListenTransConns[i] = ListenTransConns[ListenTransCount - 1];
    460 		ListenTransCount -= 1;
    461 		i -= 1;
    462 	    }
    463 	    else if (status == TRANS_RESET_NEW_FD)
    464 	    {
    465 		/*
    466 		 * A new file descriptor was allocated (the old one was closed)
    467 		 */
    468 
    469 		int newfd = _XSERVTransGetConnectionNumber (ListenTransConns[i]);
    470 
    471 		FD_CLR (ListenTransFds[i], &WellKnownConnections);
    472 		ListenTransFds[i] = newfd;
    473 		FD_SET(newfd, &WellKnownConnections);
    474 	    }
    475 	}
    476     }
    477 
    478     ResetAuthorization ();
    479     ResetHosts(display);
    480     /*
    481      * restart XDMCP
    482      */
    483 #ifdef XDMCP
    484     XdmcpReset ();
    485 #endif
    486 }
    487 
    488 void
    489 CloseWellKnownConnections(void)
    490 {
    491     int i;
    492 
    493     for (i = 0; i < ListenTransCount; i++)
    494 	_XSERVTransClose (ListenTransConns[i]);
    495 }
    496 
    497 static void
    498 AuthAudit (ClientPtr client, Bool letin,
    499     struct sockaddr *saddr, int len,
    500     unsigned int proto_n, char *auth_proto, int auth_id)
    501 {
    502     char addr[128];
    503     char *out = addr;
    504     char client_uid_string[64];
    505     LocalClientCredRec *lcc;
    506 #ifdef XSERVER_DTRACE
    507     pid_t client_pid = -1;
    508     zoneid_t client_zid = -1;
    509 #endif
    510 
    511     if (!len)
    512         strcpy(out, "local host");
    513     else
    514 	switch (saddr->sa_family)
    515 	{
    516 	case AF_UNSPEC:
    517 #if defined(UNIXCONN) || defined(LOCALCONN)
    518 	case AF_UNIX:
    519 #endif
    520 	    strcpy(out, "local host");
    521 	    break;
    522 #if defined(TCPCONN) || defined(STREAMSCONN)
    523 	case AF_INET:
    524 	    sprintf(out, "IP %s",
    525 		inet_ntoa(((struct sockaddr_in *) saddr)->sin_addr));
    526 	    break;
    527 #if defined(IPv6) && defined(AF_INET6)
    528 	case AF_INET6: {
    529 	    char ipaddr[INET6_ADDRSTRLEN];
    530 	    inet_ntop(AF_INET6, &((struct sockaddr_in6 *) saddr)->sin6_addr,
    531 	      ipaddr, sizeof(ipaddr));
    532 	    sprintf(out, "IP %s", ipaddr);
    533 	}
    534 	    break;
    535 #endif
    536 #endif
    537 	default:
    538 	    strcpy(out, "unknown address");
    539 	}
    540 
    541     if (GetLocalClientCreds(client, &lcc) != -1) {
    542 	int slen; /* length written to client_uid_string */
    543 
    544 	strcpy(client_uid_string, " ( ");
    545 	slen = 3;
    546 
    547 	if (lcc->fieldsSet & LCC_UID_SET) {
    548 	    snprintf(client_uid_string + slen,
    549 		     sizeof(client_uid_string) - slen,
    550 		     "uid=%ld ", (long) lcc->euid);
    551 	    slen = strlen(client_uid_string);
    552 	}
    553 
    554 	if (lcc->fieldsSet & LCC_GID_SET) {
    555 	    snprintf(client_uid_string + slen,
    556 		     sizeof(client_uid_string) - slen,
    557 		     "gid=%ld ", (long) lcc->egid);
    558 	    slen = strlen(client_uid_string);
    559 	}
    560 
    561 	if (lcc->fieldsSet & LCC_PID_SET) {
    562 #ifdef XSERVER_DTRACE
    563 	    client_pid = lcc->pid;
    564 #endif
    565 	    snprintf(client_uid_string + slen,
    566 		     sizeof(client_uid_string) - slen,
    567 		     "pid=%ld ", (long) lcc->pid);
    568 	    slen = strlen(client_uid_string);
    569 	}
    570 
    571 	if (lcc->fieldsSet & LCC_ZID_SET) {
    572 #ifdef XSERVER_DTRACE
    573 	    client_zid = lcc->zoneid;
    574 #endif
    575 	    snprintf(client_uid_string + slen,
    576 		     sizeof(client_uid_string) - slen,
    577 		     "zoneid=%ld ", (long) lcc->zoneid);
    578 	    slen = strlen(client_uid_string);
    579 	}
    580 
    581 	snprintf(client_uid_string + slen, sizeof(client_uid_string) - slen,
    582 		 ")");
    583 	FreeLocalClientCreds(lcc);
    584     }
    585     else {
    586 	client_uid_string[0] = '\0';
    587     }
    588 
    589 #ifdef XSERVER_DTRACE
    590     XSERVER_CLIENT_AUTH(client->index, addr, client_pid, client_zid);
    591 #endif
    592     if (auditTrailLevel > 1) {
    593       if (proto_n)
    594 	AuditF("client %d %s from %s%s\n  Auth name: %.*s ID: %d\n",
    595 	       client->index, letin ? "connected" : "rejected", addr,
    596 	       client_uid_string, (int)proto_n, auth_proto, auth_id);
    597       else
    598 	AuditF("client %d %s from %s%s\n",
    599 	       client->index, letin ? "connected" : "rejected", addr,
    600 	       client_uid_string);
    601 
    602     }
    603 }
    604 
    605 XID
    606 AuthorizationIDOfClient(ClientPtr client)
    607 {
    608     if (client->osPrivate)
    609 	return ((OsCommPtr)client->osPrivate)->auth_id;
    610     else
    611 	return None;
    612 }
    613 
    614 
    615 /*****************************************************************
    616  * ClientAuthorized
    617  *
    618  *    Sent by the client at connection setup:
    619  *                typedef struct _xConnClientPrefix {
    620  *                   CARD8	byteOrder;
    621  *                   BYTE	pad;
    622  *                   CARD16	majorVersion, minorVersion;
    623  *                   CARD16	nbytesAuthProto;
    624  *                   CARD16	nbytesAuthString;
    625  *                 } xConnClientPrefix;
    626  *
    627  *     	It is hoped that eventually one protocol will be agreed upon.  In the
    628  *        mean time, a server that implements a different protocol than the
    629  *        client expects, or a server that only implements the host-based
    630  *        mechanism, will simply ignore this information.
    631  *
    632  *****************************************************************/
    633 
    634 char *
    635 ClientAuthorized(ClientPtr client,
    636     unsigned int proto_n, char *auth_proto,
    637     unsigned int string_n, char *auth_string)
    638 {
    639     OsCommPtr 		priv;
    640     Xtransaddr		*from = NULL;
    641     int 		family;
    642     int			fromlen;
    643     XID	 		auth_id;
    644     char	 	*reason = NULL;
    645     XtransConnInfo	trans_conn;
    646 
    647     priv = (OsCommPtr)client->osPrivate;
    648     trans_conn = priv->trans_conn;
    649 
    650     /* Allow any client to connect without authorization on a launchd socket,
    651        because it is securely created -- this prevents a race condition on launch */
    652     if(trans_conn->flags & TRANS_NOXAUTH) {
    653         auth_id = (XID) 0L;
    654     } else {
    655         auth_id = CheckAuthorization (proto_n, auth_proto, string_n, auth_string, client, &reason);
    656     }
    657 
    658     if (auth_id == (XID) ~0L)
    659     {
    660 	if (_XSERVTransGetPeerAddr(trans_conn, &family, &fromlen, &from) != -1)
    661 	{
    662 	    if (InvalidHost ((struct sockaddr *) from, fromlen, client))
    663 		AuthAudit(client, FALSE, (struct sockaddr *) from,
    664 			  fromlen, proto_n, auth_proto, auth_id);
    665 	    else
    666 	    {
    667 		auth_id = (XID) 0;
    668 #ifdef XSERVER_DTRACE
    669 		if ((auditTrailLevel > 1) || XSERVER_CLIENT_AUTH_ENABLED())
    670 #else
    671 		if (auditTrailLevel > 1)
    672 #endif
    673 		    AuthAudit(client, TRUE,
    674 			(struct sockaddr *) from, fromlen,
    675 			proto_n, auth_proto, auth_id);
    676 	    }
    677 
    678 	    free(from);
    679 	}
    680 
    681 	if (auth_id == (XID) ~0L) {
    682 	    if (reason)
    683 		return reason;
    684 	    else
    685 		return "Client is not authorized to connect to Server";
    686 	}
    687     }
    688 #ifdef XSERVER_DTRACE
    689     else if ((auditTrailLevel > 1) || XSERVER_CLIENT_AUTH_ENABLED())
    690 #else
    691     else if (auditTrailLevel > 1)
    692 #endif
    693     {
    694 	if (_XSERVTransGetPeerAddr (trans_conn,
    695 	    &family, &fromlen, &from) != -1)
    696 	{
    697 	    AuthAudit(client, TRUE, (struct sockaddr *) from, fromlen,
    698 		      proto_n, auth_proto, auth_id);
    699 
    700 	    free(from);
    701 	}
    702     }
    703     priv->auth_id = auth_id;
    704     priv->conn_time = 0;
    705 
    706 #ifdef XDMCP
    707     /* indicate to Xdmcp protocol that we've opened new client */
    708     XdmcpOpenDisplay(priv->fd);
    709 #endif /* XDMCP */
    710 
    711     XaceHook(XACE_AUTH_AVAIL, client, auth_id);
    712 
    713     /* At this point, if the client is authorized to change the access control
    714      * list, we should getpeername() information, and add the client to
    715      * the selfhosts list.  It's not really the host machine, but the
    716      * true purpose of the selfhosts list is to see who may change the
    717      * access control list.
    718      */
    719     return((char *)NULL);
    720 }
    721 
    722 static ClientPtr
    723 AllocNewConnection (XtransConnInfo trans_conn, int fd, CARD32 conn_time)
    724 {
    725     OsCommPtr	oc;
    726     ClientPtr	client;
    727 
    728     if (
    729 #ifndef WIN32
    730 	fd >= lastfdesc
    731 #else
    732 	XFD_SETCOUNT(&AllClients) >= MaxClients
    733 #endif
    734 	)
    735 	return NullClient;
    736     oc = malloc(sizeof(OsCommRec));
    737     if (!oc)
    738 	return NullClient;
    739     oc->trans_conn = trans_conn;
    740     oc->fd = fd;
    741     oc->input = (ConnectionInputPtr)NULL;
    742     oc->output = (ConnectionOutputPtr)NULL;
    743     oc->auth_id = None;
    744     oc->conn_time = conn_time;
    745     if (!(client = NextAvailableClient((pointer)oc)))
    746     {
    747 	free(oc);
    748 	return NullClient;
    749     }
    750     oc->local_client = ComputeLocalClient(client);
    751 #if !defined(WIN32)
    752     ConnectionTranslation[fd] = client->index;
    753 #else
    754     SetConnectionTranslation(fd, client->index);
    755 #endif
    756     if (GrabInProgress)
    757     {
    758         FD_SET(fd, &SavedAllClients);
    759         FD_SET(fd, &SavedAllSockets);
    760     }
    761     else
    762     {
    763         FD_SET(fd, &AllClients);
    764         FD_SET(fd, &AllSockets);
    765     }
    766 
    767 #ifdef DEBUG
    768     ErrorF("AllocNewConnection: client index = %d, socket fd = %d\n",
    769 	   client->index, fd);
    770 #endif
    771 #ifdef XSERVER_DTRACE
    772     XSERVER_CLIENT_CONNECT(client->index, fd);
    773 #endif
    774 
    775     return client;
    776 }
    777 
    778 /*****************
    779  * EstablishNewConnections
    780  *    If anyone is waiting on listened sockets, accept them.
    781  *    Returns a mask with indices of new clients.  Updates AllClients
    782  *    and AllSockets.
    783  *****************/
    784 
    785 /*ARGSUSED*/
    786 Bool
    787 EstablishNewConnections(ClientPtr clientUnused, pointer closure)
    788 {
    789     fd_set  readyconnections;     /* set of listeners that are ready */
    790     int curconn;                  /* fd of listener that's ready */
    791     register int newconn;         /* fd of new client */
    792     CARD32 connect_time;
    793     register int i;
    794     register ClientPtr client;
    795     register OsCommPtr oc;
    796     fd_set tmask;
    797 
    798     XFD_ANDSET (&tmask, (fd_set*)closure, &WellKnownConnections);
    799     XFD_COPYSET(&tmask, &readyconnections);
    800     if (!XFD_ANYSET(&readyconnections))
    801 	return TRUE;
    802     connect_time = GetTimeInMillis();
    803     /* kill off stragglers */
    804     for (i=1; i<currentMaxClients; i++)
    805     {
    806 	if ((client = clients[i]))
    807 	{
    808 	    oc = (OsCommPtr)(client->osPrivate);
    809 	    if ((oc && (oc->conn_time != 0) &&
    810 		(connect_time - oc->conn_time) >= TimeOutValue) ||
    811 		(client->noClientException != Success && !client->clientGone))
    812 		CloseDownClient(client);
    813 	}
    814     }
    815 #ifndef WIN32
    816     for (i = 0; i < howmany(XFD_SETSIZE, NFDBITS); i++)
    817     {
    818       while (readyconnections.fds_bits[i])
    819 #else
    820       for (i = 0; i < XFD_SETCOUNT(&readyconnections); i++)
    821 #endif
    822       {
    823 	XtransConnInfo trans_conn, new_trans_conn;
    824 	int status;
    825 
    826 #ifndef WIN32
    827 	curconn = mffs (readyconnections.fds_bits[i]) - 1;
    828 	readyconnections.fds_bits[i] &= ~((fd_mask)1 << curconn);
    829 	curconn += (i * (sizeof(fd_mask)*8));
    830 #else
    831 	curconn = XFD_FD(&readyconnections, i);
    832 #endif
    833 
    834 	if ((trans_conn = lookup_trans_conn (curconn)) == NULL)
    835 	    continue;
    836 
    837 	if ((new_trans_conn = _XSERVTransAccept (trans_conn, &status)) == NULL)
    838 	    continue;
    839 
    840 	newconn = _XSERVTransGetConnectionNumber (new_trans_conn);
    841 
    842 	if (newconn < lastfdesc)
    843 	{
    844 		int clientid;
    845 #if !defined(WIN32)
    846   		clientid = ConnectionTranslation[newconn];
    847 #else
    848   		clientid = GetConnectionTranslation(newconn);
    849 #endif
    850 		if(clientid && (client = clients[clientid]))
    851  			CloseDownClient(client);
    852 	}
    853 
    854 	_XSERVTransSetOption(new_trans_conn, TRANS_NONBLOCKING, 1);
    855 
    856 	if (!AllocNewConnection (new_trans_conn, newconn, connect_time))
    857 	{
    858 	    ErrorConnMax(new_trans_conn);
    859 	    _XSERVTransClose(new_trans_conn);
    860 	}
    861 
    862 	if(trans_conn->flags & TRANS_NOXAUTH)
    863 	    new_trans_conn->flags = new_trans_conn->flags | TRANS_NOXAUTH;
    864 
    865       }
    866 #ifndef WIN32
    867     }
    868 #endif
    869     return TRUE;
    870 }
    871 
    872 #define NOROOM "Maximum number of clients reached"
    873 
    874 /************
    875  *   ErrorConnMax
    876  *     Fail a connection due to lack of client or file descriptor space
    877  ************/
    878 
    879 static void
    880 ErrorConnMax(XtransConnInfo trans_conn)
    881 {
    882     int fd = _XSERVTransGetConnectionNumber (trans_conn);
    883     xConnSetupPrefix csp;
    884     char pad[3];
    885     struct iovec iov[3];
    886     char byteOrder = 0;
    887     int whichbyte = 1;
    888     struct timeval waittime;
    889     fd_set mask;
    890 
    891     /* if these seems like a lot of trouble to go to, it probably is */
    892     waittime.tv_sec = BOTIMEOUT / MILLI_PER_SECOND;
    893     waittime.tv_usec = (BOTIMEOUT % MILLI_PER_SECOND) *
    894 		       (1000000 / MILLI_PER_SECOND);
    895     FD_ZERO(&mask);
    896     FD_SET(fd, &mask);
    897     (void)Select(fd + 1, &mask, NULL, NULL, &waittime);
    898     /* try to read the byte-order of the connection */
    899     (void)_XSERVTransRead(trans_conn, &byteOrder, 1);
    900     if ((byteOrder == 'l') || (byteOrder == 'B'))
    901     {
    902 	csp.success = xFalse;
    903 	csp.lengthReason = sizeof(NOROOM) - 1;
    904 	csp.length = (sizeof(NOROOM) + 2) >> 2;
    905 	csp.majorVersion = X_PROTOCOL;
    906 	csp.minorVersion = X_PROTOCOL_REVISION;
    907 	if (((*(char *) &whichbyte) && (byteOrder == 'B')) ||
    908 	    (!(*(char *) &whichbyte) && (byteOrder == 'l')))
    909 	{
    910 	    swaps(&csp.majorVersion, whichbyte);
    911 	    swaps(&csp.minorVersion, whichbyte);
    912 	    swaps(&csp.length, whichbyte);
    913 	}
    914 	iov[0].iov_len = sz_xConnSetupPrefix;
    915 	iov[0].iov_base = (char *) &csp;
    916 	iov[1].iov_len = csp.lengthReason;
    917 	iov[1].iov_base = NOROOM;
    918 	iov[2].iov_len = (4 - (csp.lengthReason & 3)) & 3;
    919 	iov[2].iov_base = pad;
    920 	(void)_XSERVTransWritev(trans_conn, iov, 3);
    921     }
    922 }
    923 
    924 /************
    925  *   CloseDownFileDescriptor:
    926  *     Remove this file descriptor and it's I/O buffers, etc.
    927  ************/
    928 
    929 static void
    930 CloseDownFileDescriptor(OsCommPtr oc)
    931 {
    932     int connection = oc->fd;
    933 
    934     if (oc->trans_conn) {
    935 	_XSERVTransDisconnect(oc->trans_conn);
    936 	_XSERVTransClose(oc->trans_conn);
    937     }
    938 #ifndef WIN32
    939     ConnectionTranslation[connection] = 0;
    940 #else
    941     SetConnectionTranslation(connection, 0);
    942 #endif
    943     FD_CLR(connection, &AllSockets);
    944     FD_CLR(connection, &AllClients);
    945     FD_CLR(connection, &ClientsWithInput);
    946     FD_CLR(connection, &GrabImperviousClients);
    947     if (GrabInProgress)
    948     {
    949 	FD_CLR(connection, &SavedAllSockets);
    950 	FD_CLR(connection, &SavedAllClients);
    951 	FD_CLR(connection, &SavedClientsWithInput);
    952     }
    953     FD_CLR(connection, &ClientsWriteBlocked);
    954     if (!XFD_ANYSET(&ClientsWriteBlocked))
    955     	AnyClientsWriteBlocked = FALSE;
    956     FD_CLR(connection, &OutputPending);
    957 }
    958 
    959 /*****************
    960  * CheckConnections
    961  *    Some connection has died, go find which one and shut it down
    962  *    The file descriptor has been closed, but is still in AllClients.
    963  *    If would truly be wonderful if select() would put the bogus
    964  *    file descriptors in the exception mask, but nooooo.  So we have
    965  *    to check each and every socket individually.
    966  *****************/
    967 
    968 void
    969 CheckConnections(void)
    970 {
    971 #ifndef WIN32
    972     fd_mask		mask;
    973 #endif
    974     fd_set		tmask;
    975     int			curclient, curoff;
    976     int			i;
    977     struct timeval	notime;
    978     int r;
    979 #ifdef WIN32
    980     fd_set savedAllClients;
    981 #endif
    982 
    983     notime.tv_sec = 0;
    984     notime.tv_usec = 0;
    985 
    986 #ifndef WIN32
    987     for (i=0; i<howmany(XFD_SETSIZE, NFDBITS); i++)
    988     {
    989 	mask = AllClients.fds_bits[i];
    990         while (mask)
    991     	{
    992 	    curoff = mffs (mask) - 1;
    993 	    curclient = curoff + (i * (sizeof(fd_mask)*8));
    994             FD_ZERO(&tmask);
    995             FD_SET(curclient, &tmask);
    996             do {
    997                 r = Select (curclient + 1, &tmask, NULL, NULL, &notime);
    998             } while (r < 0 && (errno == EINTR || errno == EAGAIN));
    999             if (r < 0)
   1000                 if (ConnectionTranslation[curclient] > 0)
   1001                     CloseDownClient(clients[ConnectionTranslation[curclient]]);
   1002 	    mask &= ~((fd_mask)1 << curoff);
   1003 	}
   1004     }
   1005 #else
   1006     XFD_COPYSET(&AllClients, &savedAllClients);
   1007     for (i = 0; i < XFD_SETCOUNT(&savedAllClients); i++)
   1008     {
   1009 	curclient = XFD_FD(&savedAllClients, i);
   1010 	FD_ZERO(&tmask);
   1011 	FD_SET(curclient, &tmask);
   1012         do {
   1013             r = Select (curclient + 1, &tmask, NULL, NULL, &notime);
   1014         } while (r < 0 && (errno == EINTR || errno == EAGAIN));
   1015 	if (r < 0)
   1016             if (GetConnectionTranslation(curclient) > 0)
   1017                 CloseDownClient(clients[GetConnectionTranslation(curclient)]);
   1018     }
   1019 #endif
   1020 }
   1021 
   1022 
   1023 /*****************
   1024  * CloseDownConnection
   1025  *    Delete client from AllClients and free resources
   1026  *****************/
   1027 
   1028 void
   1029 CloseDownConnection(ClientPtr client)
   1030 {
   1031     OsCommPtr oc = (OsCommPtr)client->osPrivate;
   1032 
   1033     if (FlushCallback)
   1034 	CallCallbacks(&FlushCallback, NULL);
   1035 
   1036     if (oc->output && oc->output->count)
   1037 	FlushClient(client, oc, (char *)NULL, 0);
   1038 #ifdef XDMCP
   1039     XdmcpCloseDisplay(oc->fd);
   1040 #endif
   1041     CloseDownFileDescriptor(oc);
   1042     FreeOsBuffers(oc);
   1043     free(client->osPrivate);
   1044     client->osPrivate = (pointer)NULL;
   1045     if (auditTrailLevel > 1)
   1046 	AuditF("client %d disconnected\n", client->index);
   1047 }
   1048 
   1049 void
   1050 AddGeneralSocket(int fd)
   1051 {
   1052     FD_SET(fd, &AllSockets);
   1053     if (GrabInProgress)
   1054 	FD_SET(fd, &SavedAllSockets);
   1055 }
   1056 
   1057 void
   1058 AddEnabledDevice(int fd)
   1059 {
   1060     FD_SET(fd, &EnabledDevices);
   1061     AddGeneralSocket(fd);
   1062 }
   1063 
   1064 void
   1065 RemoveGeneralSocket(int fd)
   1066 {
   1067     FD_CLR(fd, &AllSockets);
   1068     if (GrabInProgress)
   1069 	FD_CLR(fd, &SavedAllSockets);
   1070 }
   1071 
   1072 void
   1073 RemoveEnabledDevice(int fd)
   1074 {
   1075     FD_CLR(fd, &EnabledDevices);
   1076     RemoveGeneralSocket(fd);
   1077 }
   1078 
   1079 /*****************
   1080  * OnlyListenToOneClient:
   1081  *    Only accept requests from  one client.  Continue to handle new
   1082  *    connections, but don't take any protocol requests from the new
   1083  *    ones.  Note that if GrabInProgress is set, EstablishNewConnections
   1084  *    needs to put new clients into SavedAllSockets and SavedAllClients.
   1085  *    Note also that there is no timeout for this in the protocol.
   1086  *    This routine is "undone" by ListenToAllClients()
   1087  *****************/
   1088 
   1089 int
   1090 OnlyListenToOneClient(ClientPtr client)
   1091 {
   1092     OsCommPtr oc = (OsCommPtr)client->osPrivate;
   1093     int rc, connection = oc->fd;
   1094 
   1095     rc = XaceHook(XACE_SERVER_ACCESS, client, DixGrabAccess);
   1096     if (rc != Success)
   1097 	return rc;
   1098 
   1099     if (! GrabInProgress)
   1100     {
   1101 	XFD_COPYSET(&ClientsWithInput, &SavedClientsWithInput);
   1102 	XFD_ANDSET(&ClientsWithInput,
   1103 		       &ClientsWithInput, &GrabImperviousClients);
   1104 	if (FD_ISSET(connection, &SavedClientsWithInput))
   1105 	{
   1106 	    FD_CLR(connection, &SavedClientsWithInput);
   1107 	    FD_SET(connection, &ClientsWithInput);
   1108 	}
   1109 	XFD_UNSET(&SavedClientsWithInput, &GrabImperviousClients);
   1110 	XFD_COPYSET(&AllSockets, &SavedAllSockets);
   1111 	XFD_COPYSET(&AllClients, &SavedAllClients);
   1112 	XFD_UNSET(&AllSockets, &AllClients);
   1113 	XFD_ANDSET(&AllClients, &AllClients, &GrabImperviousClients);
   1114 	FD_SET(connection, &AllClients);
   1115 	XFD_ORSET(&AllSockets, &AllSockets, &AllClients);
   1116 	GrabInProgress = client->index;
   1117     }
   1118     return rc;
   1119 }
   1120 
   1121 /****************
   1122  * ListenToAllClients:
   1123  *    Undoes OnlyListentToOneClient()
   1124  ****************/
   1125 
   1126 void
   1127 ListenToAllClients(void)
   1128 {
   1129     if (GrabInProgress)
   1130     {
   1131 	XFD_ORSET(&AllSockets, &AllSockets, &SavedAllSockets);
   1132 	XFD_ORSET(&AllClients, &AllClients, &SavedAllClients);
   1133 	XFD_ORSET(&ClientsWithInput, &ClientsWithInput, &SavedClientsWithInput);
   1134 	GrabInProgress = 0;
   1135     }
   1136 }
   1137 
   1138 /****************
   1139  * IgnoreClient
   1140  *    Removes one client from input masks.
   1141  *    Must have cooresponding call to AttendClient.
   1142  ****************/
   1143 
   1144 void
   1145 IgnoreClient (ClientPtr client)
   1146 {
   1147     OsCommPtr oc = (OsCommPtr)client->osPrivate;
   1148     int connection = oc->fd;
   1149 
   1150     client->ignoreCount++;
   1151     if (client->ignoreCount > 1)
   1152 	return;
   1153 
   1154     isItTimeToYield = TRUE;
   1155     if (!GrabInProgress || FD_ISSET(connection, &AllClients))
   1156     {
   1157     	if (FD_ISSET (connection, &ClientsWithInput))
   1158 	    FD_SET(connection, &IgnoredClientsWithInput);
   1159     	else
   1160 	    FD_CLR(connection, &IgnoredClientsWithInput);
   1161     	FD_CLR(connection, &ClientsWithInput);
   1162     	FD_CLR(connection, &AllSockets);
   1163     	FD_CLR(connection, &AllClients);
   1164 	FD_CLR(connection, &LastSelectMask);
   1165     }
   1166     else
   1167     {
   1168     	if (FD_ISSET (connection, &SavedClientsWithInput))
   1169 	    FD_SET(connection, &IgnoredClientsWithInput);
   1170     	else
   1171 	    FD_CLR(connection, &IgnoredClientsWithInput);
   1172 	FD_CLR(connection, &SavedClientsWithInput);
   1173 	FD_CLR(connection, &SavedAllSockets);
   1174 	FD_CLR(connection, &SavedAllClients);
   1175     }
   1176 }
   1177 
   1178 /****************
   1179  * AttendClient
   1180  *    Adds one client back into the input masks.
   1181  ****************/
   1182 
   1183 void
   1184 AttendClient (ClientPtr client)
   1185 {
   1186     OsCommPtr oc = (OsCommPtr)client->osPrivate;
   1187     int connection = oc->fd;
   1188 
   1189     client->ignoreCount--;
   1190     if (client->ignoreCount)
   1191 	return;
   1192 
   1193     if (!GrabInProgress || GrabInProgress == client->index ||
   1194 	FD_ISSET(connection, &GrabImperviousClients))
   1195     {
   1196     	FD_SET(connection, &AllClients);
   1197     	FD_SET(connection, &AllSockets);
   1198 	FD_SET(connection, &LastSelectMask);
   1199     	if (FD_ISSET (connection, &IgnoredClientsWithInput))
   1200 	    FD_SET(connection, &ClientsWithInput);
   1201     }
   1202     else
   1203     {
   1204 	FD_SET(connection, &SavedAllClients);
   1205 	FD_SET(connection, &SavedAllSockets);
   1206 	if (FD_ISSET(connection, &IgnoredClientsWithInput))
   1207 	    FD_SET(connection, &SavedClientsWithInput);
   1208     }
   1209 }
   1210 
   1211 /* make client impervious to grabs; assume only executing client calls this */
   1212 
   1213 void
   1214 MakeClientGrabImpervious(ClientPtr client)
   1215 {
   1216     OsCommPtr oc = (OsCommPtr)client->osPrivate;
   1217     int connection = oc->fd;
   1218 
   1219     FD_SET(connection, &GrabImperviousClients);
   1220 
   1221     if (ServerGrabCallback)
   1222     {
   1223 	ServerGrabInfoRec grabinfo;
   1224 	grabinfo.client = client;
   1225 	grabinfo.grabstate  = CLIENT_IMPERVIOUS;
   1226 	CallCallbacks(&ServerGrabCallback, &grabinfo);
   1227     }
   1228 }
   1229 
   1230 /* make client pervious to grabs; assume only executing client calls this */
   1231 
   1232 void
   1233 MakeClientGrabPervious(ClientPtr client)
   1234 {
   1235     OsCommPtr oc = (OsCommPtr)client->osPrivate;
   1236     int connection = oc->fd;
   1237 
   1238     FD_CLR(connection, &GrabImperviousClients);
   1239     if (GrabInProgress && (GrabInProgress != client->index))
   1240     {
   1241 	if (FD_ISSET(connection, &ClientsWithInput))
   1242 	{
   1243 	    FD_SET(connection, &SavedClientsWithInput);
   1244 	    FD_CLR(connection, &ClientsWithInput);
   1245 	}
   1246 	FD_CLR(connection, &AllSockets);
   1247 	FD_CLR(connection, &AllClients);
   1248 	isItTimeToYield = TRUE;
   1249     }
   1250 
   1251     if (ServerGrabCallback)
   1252     {
   1253 	ServerGrabInfoRec grabinfo;
   1254 	grabinfo.client = client;
   1255 	grabinfo.grabstate  = CLIENT_PERVIOUS;
   1256 	CallCallbacks(&ServerGrabCallback, &grabinfo);
   1257     }
   1258 }
   1259 
   1260 #ifdef XQUARTZ
   1261 /* Add a fd (from launchd) to our listeners */
   1262 void ListenOnOpenFD(int fd, int noxauth) {
   1263     char port[256];
   1264     XtransConnInfo ciptr;
   1265     const char *display_env = getenv("DISPLAY");
   1266 
   1267     if(display_env && (strncmp(display_env, "/tmp/launch", 11) == 0)) {
   1268         /* Make the path the launchd socket if our DISPLAY is set right */
   1269         strcpy(port, display_env);
   1270     } else {
   1271         /* Just some default so things don't break and die. */
   1272         sprintf(port, ":%d", atoi(display));
   1273     }
   1274 
   1275     /* Make our XtransConnInfo
   1276      * TRANS_SOCKET_LOCAL_INDEX = 5 from Xtrans.c
   1277      */
   1278     ciptr = _XSERVTransReopenCOTSServer(5, fd, port);
   1279     if(ciptr == NULL) {
   1280         ErrorF("Got NULL while trying to Reopen launchd port.\n");
   1281         return;
   1282     }
   1283 
   1284     if(noxauth)
   1285         ciptr->flags = ciptr->flags | TRANS_NOXAUTH;
   1286 
   1287     /* Allocate space to store it */
   1288     ListenTransFds = (int *) realloc(ListenTransFds, (ListenTransCount + 1) * sizeof (int));
   1289     ListenTransConns = (XtransConnInfo *) realloc(ListenTransConns, (ListenTransCount + 1) * sizeof (XtransConnInfo));
   1290 
   1291     /* Store it */
   1292     ListenTransConns[ListenTransCount] = ciptr;
   1293     ListenTransFds[ListenTransCount] = fd;
   1294 
   1295     FD_SET(fd, &WellKnownConnections);
   1296     FD_SET(fd, &AllSockets);
   1297 
   1298     /* Increment the count */
   1299     ListenTransCount++;
   1300 
   1301     /* This *might* not be needed... /shrug */
   1302     ResetAuthorization();
   1303     ResetHosts(display);
   1304 #ifdef XDMCP
   1305     XdmcpReset();
   1306 #endif
   1307 }
   1308 
   1309 #endif
   1310