105b261ecSmrg/*********************************************************** 205b261ecSmrg 305b261ecSmrgCopyright 1987, 1989, 1998 The Open Group 405b261ecSmrg 505b261ecSmrgPermission to use, copy, modify, distribute, and sell this software and its 605b261ecSmrgdocumentation for any purpose is hereby granted without fee, provided that 705b261ecSmrgthe above copyright notice appear in all copies and that both that 805b261ecSmrgcopyright notice and this permission notice appear in supporting 905b261ecSmrgdocumentation. 1005b261ecSmrg 1105b261ecSmrgThe above copyright notice and this permission notice shall be included in 1205b261ecSmrgall copies or substantial portions of the Software. 1305b261ecSmrg 1405b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1505b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1605b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1705b261ecSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 1805b261ecSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 1905b261ecSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2005b261ecSmrg 2105b261ecSmrgExcept as contained in this notice, the name of The Open Group shall not be 2205b261ecSmrgused in advertising or otherwise to promote the sale, use or other dealings 2305b261ecSmrgin this Software without prior written authorization from The Open Group. 2405b261ecSmrg 2505b261ecSmrgCopyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts. 2605b261ecSmrg 2705b261ecSmrg All Rights Reserved 2805b261ecSmrg 29f7df2e56SmrgPermission to use, copy, modify, and distribute this software and its 30f7df2e56Smrgdocumentation for any purpose and without fee is hereby granted, 3105b261ecSmrgprovided that the above copyright notice appear in all copies and that 32f7df2e56Smrgboth that copyright notice and this permission notice appear in 3305b261ecSmrgsupporting documentation, and that the name of Digital not be 3405b261ecSmrgused in advertising or publicity pertaining to distribution of the 35f7df2e56Smrgsoftware without specific, written prior permission. 3605b261ecSmrg 3705b261ecSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 3805b261ecSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 3905b261ecSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 4005b261ecSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 4105b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 4205b261ecSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 4305b261ecSmrgSOFTWARE. 4405b261ecSmrg 4505b261ecSmrg******************************************************************/ 4605b261ecSmrg/***************************************************************** 4705b261ecSmrg * Stuff to create connections --- OS dependent 4805b261ecSmrg * 4905b261ecSmrg * EstablishNewConnections, CreateWellKnownSockets, ResetWellKnownSockets, 507e31ba66Smrg * CloseDownConnection, 517e31ba66Smrg * OnlyListToOneClient, 5205b261ecSmrg * ListenToAllClients, 5305b261ecSmrg * 5405b261ecSmrg * (WaitForSomething is in its own file) 5505b261ecSmrg * 5605b261ecSmrg * In this implementation, a client socket table is not kept. 5705b261ecSmrg * Instead, what would be the index into the table is just the 5805b261ecSmrg * file descriptor of the socket. This won't work for if the 5905b261ecSmrg * socket ids aren't small nums (0 - 2^8) 6005b261ecSmrg * 6105b261ecSmrg *****************************************************************/ 6205b261ecSmrg 635bd42952Smrg#include <X11/Xpoll.h> 645bd42952Smrg 6505b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 6605b261ecSmrg#include <dix-config.h> 6705b261ecSmrg#endif 6805b261ecSmrg 6905b261ecSmrg#ifdef WIN32 7005b261ecSmrg#include <X11/Xwinsock.h> 7105b261ecSmrg#endif 7205b261ecSmrg#include <X11/X.h> 7305b261ecSmrg#include <X11/Xproto.h> 7405b261ecSmrg#define XSERV_t 7505b261ecSmrg#define TRANS_SERVER 7605b261ecSmrg#define TRANS_REOPEN 7705b261ecSmrg#include <X11/Xtrans/Xtrans.h> 784642e01fSmrg#include <X11/Xtrans/Xtransint.h> 7905b261ecSmrg#include <errno.h> 8005b261ecSmrg#include <signal.h> 8105b261ecSmrg#include <stdio.h> 8205b261ecSmrg#include <stdlib.h> 8305b261ecSmrg 8490bea6a0Smrg#include <sys/stat.h> 8590bea6a0Smrg 8605b261ecSmrg#ifndef WIN32 8705b261ecSmrg#include <sys/socket.h> 8805b261ecSmrg 897e31ba66Smrg#if defined(TCPCONN) 90f7df2e56Smrg#include <netinet/in.h> 91f7df2e56Smrg#include <arpa/inet.h> 92f7df2e56Smrg#ifdef apollo 93f7df2e56Smrg#ifndef NO_TCP_H 94f7df2e56Smrg#include <netinet/tcp.h> 95f7df2e56Smrg#endif 96f7df2e56Smrg#else 97f7df2e56Smrg#ifdef CSRG_BASED 98f7df2e56Smrg#include <sys/param.h> 99f7df2e56Smrg#endif 100f7df2e56Smrg#include <netinet/tcp.h> 101f7df2e56Smrg#endif 102f7df2e56Smrg#include <arpa/inet.h> 10305b261ecSmrg#endif 10405b261ecSmrg 10505b261ecSmrg#include <sys/uio.h> 1064642e01fSmrg 107f7df2e56Smrg#endif /* WIN32 */ 108f7df2e56Smrg#include "misc.h" /* for typedef of pointer */ 10905b261ecSmrg#include "osdep.h" 11005b261ecSmrg#include "opaque.h" 11105b261ecSmrg#include "dixstruct.h" 11205b261ecSmrg#include "xace.h" 11305b261ecSmrg 11405b261ecSmrg#define Pid_t pid_t 11505b261ecSmrg 116f7df2e56Smrg#ifdef HAVE_GETPEERUCRED 117f7df2e56Smrg#include <ucred.h> 118f7df2e56Smrg#include <zone.h> 119f7df2e56Smrg#else 120f7df2e56Smrg#define zoneid_t int 12105b261ecSmrg#endif 12205b261ecSmrg 1235a112b11Smrg#ifdef HAVE_SYSTEMD_DAEMON 1245a112b11Smrg#include <systemd/sd-daemon.h> 1255a112b11Smrg#endif 1265a112b11Smrg 127f7df2e56Smrg#include "probes.h" 12805b261ecSmrg 1297e31ba66Smrgstruct ospoll *server_poll; 13005b261ecSmrg 131f7df2e56SmrgBool NewOutputPending; /* not yet attempted to write some new output */ 132f7df2e56SmrgBool NoListenAll; /* Don't establish any listening sockets */ 133f7df2e56Smrg 134f7df2e56Smrgstatic Bool RunFromSmartParent; /* send SIGUSR1 to parent process */ 135f7df2e56SmrgBool RunFromSigStopParent; /* send SIGSTOP to our own process; Upstart (or 136f7df2e56Smrg equivalent) will send SIGCONT back. */ 137f7df2e56Smrgstatic char dynamic_display[7]; /* display name */ 138f7df2e56SmrgBool PartialNetwork; /* continue even if unable to bind all addrs */ 13905b261ecSmrgstatic Pid_t ParentProcess; 14005b261ecSmrg 1416747b715Smrgint GrabInProgress = 0; 14205b261ecSmrg 1437e31ba66Smrgstatic void 1445a112b11SmrgEstablishNewConnections(int curconn, int ready, void *data); 145f7df2e56Smrg 1467e31ba66Smrgstatic void 1477e31ba66Smrgset_poll_client(ClientPtr client); 148f7df2e56Smrg 1497e31ba66Smrgstatic void 1507e31ba66Smrgset_poll_clients(void); 15105b261ecSmrg 152f7df2e56Smrgstatic XtransConnInfo *ListenTransConns = NULL; 153f7df2e56Smrgstatic int *ListenTransFds = NULL; 154f7df2e56Smrgstatic int ListenTransCount; 15505b261ecSmrg 156f7df2e56Smrgstatic void ErrorConnMax(XtransConnInfo /* trans_conn */ ); 15705b261ecSmrg 15805b261ecSmrgstatic XtransConnInfo 159f7df2e56Smrglookup_trans_conn(int fd) 16005b261ecSmrg{ 161f7df2e56Smrg if (ListenTransFds) { 162f7df2e56Smrg int i; 163f7df2e56Smrg 164f7df2e56Smrg for (i = 0; i < ListenTransCount; i++) 165f7df2e56Smrg if (ListenTransFds[i] == fd) 166f7df2e56Smrg return ListenTransConns[i]; 16705b261ecSmrg } 16805b261ecSmrg 1696747b715Smrg return NULL; 17005b261ecSmrg} 17105b261ecSmrg 1724642e01fSmrg/* 1734642e01fSmrg * If SIGUSR1 was set to SIG_IGN when the server started, assume that either 1744642e01fSmrg * 1754642e01fSmrg * a- The parent process is ignoring SIGUSR1 1764642e01fSmrg * 1774642e01fSmrg * or 1784642e01fSmrg * 1794642e01fSmrg * b- The parent process is expecting a SIGUSR1 1804642e01fSmrg * when the server is ready to accept connections 1814642e01fSmrg * 1824642e01fSmrg * In the first case, the signal will be harmless, in the second case, 1834642e01fSmrg * the signal will be quite useful. 1844642e01fSmrg */ 1854642e01fSmrgstatic void 1864642e01fSmrgInitParentProcess(void) 1874642e01fSmrg{ 1884642e01fSmrg#if !defined(WIN32) 1894642e01fSmrg OsSigHandlerPtr handler; 190f7df2e56Smrg 191f7df2e56Smrg handler = OsSignal(SIGUSR1, SIG_IGN); 192f7df2e56Smrg if (handler == SIG_IGN) 193f7df2e56Smrg RunFromSmartParent = TRUE; 1944642e01fSmrg OsSignal(SIGUSR1, handler); 195f7df2e56Smrg ParentProcess = getppid(); 1964642e01fSmrg#endif 1974642e01fSmrg} 1984642e01fSmrg 1994642e01fSmrgvoid 2004642e01fSmrgNotifyParentProcess(void) 2014642e01fSmrg{ 2024642e01fSmrg#if !defined(WIN32) 203f7df2e56Smrg if (displayfd >= 0) { 204f7df2e56Smrg if (write(displayfd, display, strlen(display)) != strlen(display)) 205f7df2e56Smrg FatalError("Cannot write display number to fd %d\n", displayfd); 206f7df2e56Smrg if (write(displayfd, "\n", 1) != 1) 207f7df2e56Smrg FatalError("Cannot write display number to fd %d\n", displayfd); 208f7df2e56Smrg close(displayfd); 209f7df2e56Smrg displayfd = -1; 210f7df2e56Smrg } 2114642e01fSmrg if (RunFromSmartParent) { 212f7df2e56Smrg if (ParentProcess > 1) { 213f7df2e56Smrg kill(ParentProcess, SIGUSR1); 214f7df2e56Smrg } 2154642e01fSmrg } 2169ace9065Smrg if (RunFromSigStopParent) 217f7df2e56Smrg raise(SIGSTOP); 2185a112b11Smrg#ifdef HAVE_SYSTEMD_DAEMON 2195a112b11Smrg /* If we have been started as a systemd service, tell systemd that 2205a112b11Smrg we are ready. Otherwise sd_notify() won't do anything. */ 2215a112b11Smrg sd_notify(0, "READY=1"); 2225a112b11Smrg#endif 2234642e01fSmrg#endif 2244642e01fSmrg} 22505b261ecSmrg 226f7df2e56Smrgstatic Bool 227f7df2e56SmrgTryCreateSocket(int num, int *partial) 228f7df2e56Smrg{ 229f7df2e56Smrg char port[20]; 230f7df2e56Smrg 231f7df2e56Smrg snprintf(port, sizeof(port), "%d", num); 232f7df2e56Smrg 233f7df2e56Smrg return (_XSERVTransMakeAllCOTSServerListeners(port, partial, 234f7df2e56Smrg &ListenTransCount, 235f7df2e56Smrg &ListenTransConns) >= 0); 236f7df2e56Smrg} 237f7df2e56Smrg 23805b261ecSmrg/***************** 23905b261ecSmrg * CreateWellKnownSockets 24005b261ecSmrg * At initialization, create the sockets to listen on for new clients. 24105b261ecSmrg *****************/ 24205b261ecSmrg 24305b261ecSmrgvoid 24405b261ecSmrgCreateWellKnownSockets(void) 24505b261ecSmrg{ 246f7df2e56Smrg int i; 247d566a54bSmrg int partial = 0; 24805b261ecSmrg 249f7df2e56Smrg /* display is initialized to "0" by main(). It is then set to the display 250f7df2e56Smrg * number if specified on the command line. */ 25105b261ecSmrg 252f7df2e56Smrg if (NoListenAll) { 253f7df2e56Smrg ListenTransCount = 0; 254f7df2e56Smrg } 255f7df2e56Smrg else if ((displayfd < 0) || explicit_display) { 256f7df2e56Smrg if (TryCreateSocket(atoi(display), &partial) && 257f7df2e56Smrg ListenTransCount >= 1) 258f7df2e56Smrg if (!PartialNetwork && partial) 259f7df2e56Smrg FatalError ("Failed to establish all listening sockets"); 260f7df2e56Smrg } 261f7df2e56Smrg else { /* -displayfd and no explicit display number */ 262f7df2e56Smrg Bool found = 0; 263f7df2e56Smrg for (i = 0; i < 65536 - X_TCP_PORT; i++) { 264f7df2e56Smrg if (TryCreateSocket(i, &partial) && !partial) { 265f7df2e56Smrg found = 1; 266f7df2e56Smrg break; 267f7df2e56Smrg } 268f7df2e56Smrg else 269f7df2e56Smrg CloseWellKnownConnections(); 270f7df2e56Smrg } 271f7df2e56Smrg if (!found) 272f7df2e56Smrg FatalError("Failed to find a socket to listen on"); 273f7df2e56Smrg snprintf(dynamic_display, sizeof(dynamic_display), "%d", i); 274f7df2e56Smrg display = dynamic_display; 275f7df2e56Smrg LogSetDisplay(); 276f7df2e56Smrg } 277f7df2e56Smrg 278f7df2e56Smrg ListenTransFds = xallocarray(ListenTransCount, sizeof (int)); 279f7df2e56Smrg if (ListenTransFds == NULL) 280f7df2e56Smrg FatalError ("Failed to create listening socket array"); 281f7df2e56Smrg 282f7df2e56Smrg for (i = 0; i < ListenTransCount; i++) { 283f7df2e56Smrg int fd = _XSERVTransGetConnectionNumber(ListenTransConns[i]); 284f7df2e56Smrg 285f7df2e56Smrg ListenTransFds[i] = fd; 2865a112b11Smrg SetNotifyFd(fd, EstablishNewConnections, X_NOTIFY_READ, NULL); 287f7df2e56Smrg 288f7df2e56Smrg if (!_XSERVTransIsLocal(ListenTransConns[i])) 289f7df2e56Smrg DefineSelf (fd); 29005b261ecSmrg } 29105b261ecSmrg 2927e31ba66Smrg if (ListenTransCount == 0 && !NoListenAll) 293f7df2e56Smrg FatalError 294f7df2e56Smrg ("Cannot establish any listening sockets - Make sure an X server isn't already running"); 295f7df2e56Smrg 29605b261ecSmrg#if !defined(WIN32) 297f7df2e56Smrg OsSignal(SIGPIPE, SIG_IGN); 298f7df2e56Smrg OsSignal(SIGHUP, AutoResetServer); 29905b261ecSmrg#endif 300f7df2e56Smrg OsSignal(SIGINT, GiveUp); 301f7df2e56Smrg OsSignal(SIGTERM, GiveUp); 30205b261ecSmrg ResetHosts(display); 3034642e01fSmrg 3044642e01fSmrg InitParentProcess(); 3054642e01fSmrg 30605b261ecSmrg#ifdef XDMCP 307f7df2e56Smrg XdmcpInit(); 30805b261ecSmrg#endif 30905b261ecSmrg} 31005b261ecSmrg 31105b261ecSmrgvoid 312f7df2e56SmrgResetWellKnownSockets(void) 31305b261ecSmrg{ 31405b261ecSmrg int i; 31505b261ecSmrg 31605b261ecSmrg ResetOsBuffers(); 31705b261ecSmrg 318f7df2e56Smrg for (i = 0; i < ListenTransCount; i++) { 319f7df2e56Smrg int status = _XSERVTransResetListener(ListenTransConns[i]); 320f7df2e56Smrg 321f7df2e56Smrg if (status != TRANS_RESET_NOOP) { 322f7df2e56Smrg if (status == TRANS_RESET_FAILURE) { 323f7df2e56Smrg /* 324f7df2e56Smrg * ListenTransConns[i] freed by xtrans. 325f7df2e56Smrg * Remove it from out list. 326f7df2e56Smrg */ 327f7df2e56Smrg 3287e31ba66Smrg RemoveNotifyFd(ListenTransFds[i]); 329f7df2e56Smrg ListenTransFds[i] = ListenTransFds[ListenTransCount - 1]; 330f7df2e56Smrg ListenTransConns[i] = ListenTransConns[ListenTransCount - 1]; 331f7df2e56Smrg ListenTransCount -= 1; 332f7df2e56Smrg i -= 1; 333f7df2e56Smrg } 334f7df2e56Smrg else if (status == TRANS_RESET_NEW_FD) { 335f7df2e56Smrg /* 336f7df2e56Smrg * A new file descriptor was allocated (the old one was closed) 337f7df2e56Smrg */ 338f7df2e56Smrg 339f7df2e56Smrg int newfd = _XSERVTransGetConnectionNumber(ListenTransConns[i]); 340f7df2e56Smrg 341f7df2e56Smrg ListenTransFds[i] = newfd; 342f7df2e56Smrg } 343f7df2e56Smrg } 34405b261ecSmrg } 3457e31ba66Smrg for (i = 0; i < ListenTransCount; i++) 3465a112b11Smrg SetNotifyFd(ListenTransFds[i], EstablishNewConnections, X_NOTIFY_READ, 3475a112b11Smrg NULL); 34805b261ecSmrg 349f7df2e56Smrg ResetAuthorization(); 35005b261ecSmrg ResetHosts(display); 35105b261ecSmrg /* 35205b261ecSmrg * restart XDMCP 35305b261ecSmrg */ 35405b261ecSmrg#ifdef XDMCP 355f7df2e56Smrg XdmcpReset(); 35605b261ecSmrg#endif 35705b261ecSmrg} 35805b261ecSmrg 35905b261ecSmrgvoid 36005b261ecSmrgCloseWellKnownConnections(void) 36105b261ecSmrg{ 36205b261ecSmrg int i; 36305b261ecSmrg 364f7df2e56Smrg for (i = 0; i < ListenTransCount; i++) { 365f7df2e56Smrg if (ListenTransConns[i] != NULL) { 366f7df2e56Smrg _XSERVTransClose(ListenTransConns[i]); 367f7df2e56Smrg ListenTransConns[i] = NULL; 3687e31ba66Smrg if (ListenTransFds != NULL) 3697e31ba66Smrg RemoveNotifyFd(ListenTransFds[i]); 370f7df2e56Smrg } 371f7df2e56Smrg } 372f7df2e56Smrg ListenTransCount = 0; 37305b261ecSmrg} 37405b261ecSmrg 37505b261ecSmrgstatic void 376f7df2e56SmrgAuthAudit(ClientPtr client, Bool letin, 377f7df2e56Smrg struct sockaddr *saddr, int len, 378f7df2e56Smrg unsigned int proto_n, char *auth_proto, int auth_id) 37905b261ecSmrg{ 38005b261ecSmrg char addr[128]; 38105b261ecSmrg char client_uid_string[64]; 3824642e01fSmrg LocalClientCredRec *lcc; 383f7df2e56Smrg 3844642e01fSmrg#ifdef XSERVER_DTRACE 38505b261ecSmrg pid_t client_pid = -1; 38605b261ecSmrg zoneid_t client_zid = -1; 38705b261ecSmrg#endif 38805b261ecSmrg 38905b261ecSmrg if (!len) 390f7df2e56Smrg strlcpy(addr, "local host", sizeof(addr)); 39105b261ecSmrg else 392f7df2e56Smrg switch (saddr->sa_family) { 393f7df2e56Smrg case AF_UNSPEC: 39405b261ecSmrg#if defined(UNIXCONN) || defined(LOCALCONN) 395f7df2e56Smrg case AF_UNIX: 39605b261ecSmrg#endif 397f7df2e56Smrg strlcpy(addr, "local host", sizeof(addr)); 398f7df2e56Smrg break; 3997e31ba66Smrg#if defined(TCPCONN) 400f7df2e56Smrg case AF_INET: 401f7df2e56Smrg snprintf(addr, sizeof(addr), "IP %s", 402f7df2e56Smrg inet_ntoa(((struct sockaddr_in *) saddr)->sin_addr)); 403f7df2e56Smrg break; 40405b261ecSmrg#if defined(IPv6) && defined(AF_INET6) 405f7df2e56Smrg case AF_INET6:{ 406f7df2e56Smrg char ipaddr[INET6_ADDRSTRLEN]; 407f7df2e56Smrg 408f7df2e56Smrg inet_ntop(AF_INET6, &((struct sockaddr_in6 *) saddr)->sin6_addr, 409f7df2e56Smrg ipaddr, sizeof(ipaddr)); 410f7df2e56Smrg snprintf(addr, sizeof(addr), "IP %s", ipaddr); 411f7df2e56Smrg } 412f7df2e56Smrg break; 41305b261ecSmrg#endif 41405b261ecSmrg#endif 415f7df2e56Smrg default: 416f7df2e56Smrg strlcpy(addr, "unknown address", sizeof(addr)); 417f7df2e56Smrg } 41805b261ecSmrg 4194642e01fSmrg if (GetLocalClientCreds(client, &lcc) != -1) { 420f7df2e56Smrg int slen; /* length written to client_uid_string */ 421f7df2e56Smrg 422f7df2e56Smrg strcpy(client_uid_string, " ( "); 423f7df2e56Smrg slen = 3; 424f7df2e56Smrg 425f7df2e56Smrg if (lcc->fieldsSet & LCC_UID_SET) { 426f7df2e56Smrg snprintf(client_uid_string + slen, 427f7df2e56Smrg sizeof(client_uid_string) - slen, 428f7df2e56Smrg "uid=%ld ", (long) lcc->euid); 429f7df2e56Smrg slen = strlen(client_uid_string); 430f7df2e56Smrg } 431f7df2e56Smrg 432f7df2e56Smrg if (lcc->fieldsSet & LCC_GID_SET) { 433f7df2e56Smrg snprintf(client_uid_string + slen, 434f7df2e56Smrg sizeof(client_uid_string) - slen, 435f7df2e56Smrg "gid=%ld ", (long) lcc->egid); 436f7df2e56Smrg slen = strlen(client_uid_string); 437f7df2e56Smrg } 438f7df2e56Smrg 439f7df2e56Smrg if (lcc->fieldsSet & LCC_PID_SET) { 440f7df2e56Smrg#ifdef XSERVER_DTRACE 441f7df2e56Smrg client_pid = lcc->pid; 44205b261ecSmrg#endif 443f7df2e56Smrg snprintf(client_uid_string + slen, 444f7df2e56Smrg sizeof(client_uid_string) - slen, 445f7df2e56Smrg "pid=%ld ", (long) lcc->pid); 446f7df2e56Smrg slen = strlen(client_uid_string); 447f7df2e56Smrg } 448f7df2e56Smrg 449f7df2e56Smrg if (lcc->fieldsSet & LCC_ZID_SET) { 4504642e01fSmrg#ifdef XSERVER_DTRACE 451f7df2e56Smrg client_zid = lcc->zoneid; 452f7df2e56Smrg#endif 453f7df2e56Smrg snprintf(client_uid_string + slen, 454f7df2e56Smrg sizeof(client_uid_string) - slen, 455f7df2e56Smrg "zoneid=%ld ", (long) lcc->zoneid); 456f7df2e56Smrg slen = strlen(client_uid_string); 457f7df2e56Smrg } 458f7df2e56Smrg 459f7df2e56Smrg snprintf(client_uid_string + slen, sizeof(client_uid_string) - slen, 460f7df2e56Smrg ")"); 461f7df2e56Smrg FreeLocalClientCreds(lcc); 4624642e01fSmrg } 46305b261ecSmrg else { 464f7df2e56Smrg client_uid_string[0] = '\0'; 46505b261ecSmrg } 466f7df2e56Smrg 46705b261ecSmrg#ifdef XSERVER_DTRACE 46805b261ecSmrg XSERVER_CLIENT_AUTH(client->index, addr, client_pid, client_zid); 46905b261ecSmrg#endif 4704642e01fSmrg if (auditTrailLevel > 1) { 471f7df2e56Smrg if (proto_n) 472f7df2e56Smrg AuditF("client %d %s from %s%s\n Auth name: %.*s ID: %d\n", 473f7df2e56Smrg client->index, letin ? "connected" : "rejected", addr, 474f7df2e56Smrg client_uid_string, (int) proto_n, auth_proto, auth_id); 475f7df2e56Smrg else 476f7df2e56Smrg AuditF("client %d %s from %s%s\n", 477f7df2e56Smrg client->index, letin ? "connected" : "rejected", addr, 478f7df2e56Smrg client_uid_string); 47905b261ecSmrg 48005b261ecSmrg } 48105b261ecSmrg} 48205b261ecSmrg 48305b261ecSmrgXID 48405b261ecSmrgAuthorizationIDOfClient(ClientPtr client) 48505b261ecSmrg{ 48605b261ecSmrg if (client->osPrivate) 487f7df2e56Smrg return ((OsCommPtr) client->osPrivate)->auth_id; 48805b261ecSmrg else 489f7df2e56Smrg return None; 49005b261ecSmrg} 49105b261ecSmrg 49205b261ecSmrg/***************************************************************** 49305b261ecSmrg * ClientAuthorized 49405b261ecSmrg * 49505b261ecSmrg * Sent by the client at connection setup: 49605b261ecSmrg * typedef struct _xConnClientPrefix { 49705b261ecSmrg * CARD8 byteOrder; 49805b261ecSmrg * BYTE pad; 49905b261ecSmrg * CARD16 majorVersion, minorVersion; 500f7df2e56Smrg * CARD16 nbytesAuthProto; 501f7df2e56Smrg * CARD16 nbytesAuthString; 50205b261ecSmrg * } xConnClientPrefix; 50305b261ecSmrg * 50405b261ecSmrg * It is hoped that eventually one protocol will be agreed upon. In the 50505b261ecSmrg * mean time, a server that implements a different protocol than the 50605b261ecSmrg * client expects, or a server that only implements the host-based 50705b261ecSmrg * mechanism, will simply ignore this information. 50805b261ecSmrg * 50905b261ecSmrg *****************************************************************/ 51005b261ecSmrg 511f7df2e56Smrgconst char * 512f7df2e56SmrgClientAuthorized(ClientPtr client, 513f7df2e56Smrg unsigned int proto_n, char *auth_proto, 514f7df2e56Smrg unsigned int string_n, char *auth_string) 51505b261ecSmrg{ 516f7df2e56Smrg OsCommPtr priv; 517f7df2e56Smrg Xtransaddr *from = NULL; 518f7df2e56Smrg int family; 519f7df2e56Smrg int fromlen; 520f7df2e56Smrg XID auth_id; 521f7df2e56Smrg const char *reason = NULL; 522f7df2e56Smrg XtransConnInfo trans_conn; 523f7df2e56Smrg 524f7df2e56Smrg priv = (OsCommPtr) client->osPrivate; 52505b261ecSmrg trans_conn = priv->trans_conn; 52605b261ecSmrg 5274642e01fSmrg /* Allow any client to connect without authorization on a launchd socket, 5284642e01fSmrg because it is securely created -- this prevents a race condition on launch */ 529f7df2e56Smrg if (trans_conn->flags & TRANS_NOXAUTH) { 5304642e01fSmrg auth_id = (XID) 0L; 531f7df2e56Smrg } 532f7df2e56Smrg else { 533f7df2e56Smrg auth_id = 534f7df2e56Smrg CheckAuthorization(proto_n, auth_proto, string_n, auth_string, 535f7df2e56Smrg client, &reason); 5364642e01fSmrg } 53705b261ecSmrg 538f7df2e56Smrg if (auth_id == (XID) ~0L) { 539f7df2e56Smrg if (_XSERVTransGetPeerAddr(trans_conn, &family, &fromlen, &from) != -1) { 540f7df2e56Smrg if (InvalidHost((struct sockaddr *) from, fromlen, client)) 541f7df2e56Smrg AuthAudit(client, FALSE, (struct sockaddr *) from, 542f7df2e56Smrg fromlen, proto_n, auth_proto, auth_id); 543f7df2e56Smrg else { 544f7df2e56Smrg auth_id = (XID) 0; 54505b261ecSmrg#ifdef XSERVER_DTRACE 546f7df2e56Smrg if ((auditTrailLevel > 1) || XSERVER_CLIENT_AUTH_ENABLED()) 54705b261ecSmrg#else 548f7df2e56Smrg if (auditTrailLevel > 1) 54905b261ecSmrg#endif 550f7df2e56Smrg AuthAudit(client, TRUE, 551f7df2e56Smrg (struct sockaddr *) from, fromlen, 552f7df2e56Smrg proto_n, auth_proto, auth_id); 553f7df2e56Smrg } 554f7df2e56Smrg 555f7df2e56Smrg free(from); 556f7df2e56Smrg } 557f7df2e56Smrg 558f7df2e56Smrg if (auth_id == (XID) ~0L) { 559f7df2e56Smrg if (reason) 560f7df2e56Smrg return reason; 561f7df2e56Smrg else 562f7df2e56Smrg return "Client is not authorized to connect to Server"; 563f7df2e56Smrg } 56405b261ecSmrg } 56505b261ecSmrg#ifdef XSERVER_DTRACE 56605b261ecSmrg else if ((auditTrailLevel > 1) || XSERVER_CLIENT_AUTH_ENABLED()) 56705b261ecSmrg#else 56805b261ecSmrg else if (auditTrailLevel > 1) 56905b261ecSmrg#endif 57005b261ecSmrg { 571f7df2e56Smrg if (_XSERVTransGetPeerAddr(trans_conn, &family, &fromlen, &from) != -1) { 572f7df2e56Smrg AuthAudit(client, TRUE, (struct sockaddr *) from, fromlen, 573f7df2e56Smrg proto_n, auth_proto, auth_id); 574f7df2e56Smrg 575f7df2e56Smrg free(from); 576f7df2e56Smrg } 57705b261ecSmrg } 57805b261ecSmrg priv->auth_id = auth_id; 57905b261ecSmrg priv->conn_time = 0; 58005b261ecSmrg 58105b261ecSmrg#ifdef XDMCP 58205b261ecSmrg /* indicate to Xdmcp protocol that we've opened new client */ 58305b261ecSmrg XdmcpOpenDisplay(priv->fd); 584f7df2e56Smrg#endif /* XDMCP */ 58505b261ecSmrg 58605b261ecSmrg XaceHook(XACE_AUTH_AVAIL, client, auth_id); 58705b261ecSmrg 58805b261ecSmrg /* At this point, if the client is authorized to change the access control 58905b261ecSmrg * list, we should getpeername() information, and add the client to 59005b261ecSmrg * the selfhosts list. It's not really the host machine, but the 59105b261ecSmrg * true purpose of the selfhosts list is to see who may change the 59205b261ecSmrg * access control list. 59305b261ecSmrg */ 594f7df2e56Smrg return ((char *) NULL); 59505b261ecSmrg} 59605b261ecSmrg 5977e31ba66Smrgstatic void 5987e31ba66SmrgClientReady(int fd, int xevents, void *data) 5997e31ba66Smrg{ 6007e31ba66Smrg ClientPtr client = data; 6017e31ba66Smrg 6027e31ba66Smrg if (xevents & X_NOTIFY_ERROR) { 6037e31ba66Smrg CloseDownClient(client); 6047e31ba66Smrg return; 6057e31ba66Smrg } 6067e31ba66Smrg if (xevents & X_NOTIFY_READ) 6077e31ba66Smrg mark_client_ready(client); 6087e31ba66Smrg if (xevents & X_NOTIFY_WRITE) { 6097e31ba66Smrg ospoll_mute(server_poll, fd, X_NOTIFY_WRITE); 6107e31ba66Smrg NewOutputPending = TRUE; 6117e31ba66Smrg } 6127e31ba66Smrg} 6137e31ba66Smrg 61405b261ecSmrgstatic ClientPtr 615f7df2e56SmrgAllocNewConnection(XtransConnInfo trans_conn, int fd, CARD32 conn_time) 61605b261ecSmrg{ 617f7df2e56Smrg OsCommPtr oc; 618f7df2e56Smrg ClientPtr client; 619f7df2e56Smrg 6206747b715Smrg oc = malloc(sizeof(OsCommRec)); 62105b261ecSmrg if (!oc) 622f7df2e56Smrg return NullClient; 62305b261ecSmrg oc->trans_conn = trans_conn; 62405b261ecSmrg oc->fd = fd; 625f7df2e56Smrg oc->input = (ConnectionInputPtr) NULL; 626f7df2e56Smrg oc->output = (ConnectionOutputPtr) NULL; 62705b261ecSmrg oc->auth_id = None; 62805b261ecSmrg oc->conn_time = conn_time; 6297e31ba66Smrg oc->flags = 0; 630f7df2e56Smrg if (!(client = NextAvailableClient((void *) oc))) { 631f7df2e56Smrg free(oc); 632f7df2e56Smrg return NullClient; 63305b261ecSmrg } 634f7df2e56Smrg client->local = ComputeLocalClient(client); 6357e31ba66Smrg ospoll_add(server_poll, fd, 6367e31ba66Smrg ospoll_trigger_edge, 6377e31ba66Smrg ClientReady, 6387e31ba66Smrg client); 6397e31ba66Smrg set_poll_client(client); 64005b261ecSmrg 64105b261ecSmrg#ifdef DEBUG 6423138c4c0Smrg ErrorF("AllocNewConnection: client index = %d, socket fd = %d, local = %d\n", 6433138c4c0Smrg client->index, fd, client->local); 64405b261ecSmrg#endif 64505b261ecSmrg#ifdef XSERVER_DTRACE 64605b261ecSmrg XSERVER_CLIENT_CONNECT(client->index, fd); 647f7df2e56Smrg#endif 64805b261ecSmrg 64905b261ecSmrg return client; 65005b261ecSmrg} 65105b261ecSmrg 65205b261ecSmrg/***************** 65305b261ecSmrg * EstablishNewConnections 6545a112b11Smrg * If anyone is waiting on listened sockets, accept them. Drop pending 6555a112b11Smrg * connections if they've stuck around for more than one minute. 65605b261ecSmrg *****************/ 6575a112b11Smrg#define TimeOutValue 60 * MILLI_PER_SECOND 6585a112b11Smrgstatic void 6595a112b11SmrgEstablishNewConnections(int curconn, int ready, void *data) 66005b261ecSmrg{ 6617e31ba66Smrg int newconn; /* fd of new client */ 66205b261ecSmrg CARD32 connect_time; 6637e31ba66Smrg int i; 6647e31ba66Smrg ClientPtr client; 6657e31ba66Smrg OsCommPtr oc; 6667e31ba66Smrg XtransConnInfo trans_conn, new_trans_conn; 6677e31ba66Smrg int status; 6687e31ba66Smrg 66905b261ecSmrg connect_time = GetTimeInMillis(); 67005b261ecSmrg /* kill off stragglers */ 671f7df2e56Smrg for (i = 1; i < currentMaxClients; i++) { 672f7df2e56Smrg if ((client = clients[i])) { 673f7df2e56Smrg oc = (OsCommPtr) (client->osPrivate); 674f7df2e56Smrg if ((oc && (oc->conn_time != 0) && 675f7df2e56Smrg (connect_time - oc->conn_time) >= TimeOutValue) || 676f7df2e56Smrg (client->noClientException != Success && !client->clientGone)) 677f7df2e56Smrg CloseDownClient(client); 678f7df2e56Smrg } 67905b261ecSmrg } 68005b261ecSmrg 6817e31ba66Smrg if ((trans_conn = lookup_trans_conn(curconn)) == NULL) 6825a112b11Smrg return; 683f7df2e56Smrg 6847e31ba66Smrg if ((new_trans_conn = _XSERVTransAccept(trans_conn, &status)) == NULL) 6855a112b11Smrg return; 68605b261ecSmrg 6877e31ba66Smrg newconn = _XSERVTransGetConnectionNumber(new_trans_conn); 68805b261ecSmrg 6897e31ba66Smrg _XSERVTransSetOption(new_trans_conn, TRANS_NONBLOCKING, 1); 6904642e01fSmrg 6917e31ba66Smrg if (trans_conn->flags & TRANS_NOXAUTH) 6927e31ba66Smrg new_trans_conn->flags = new_trans_conn->flags | TRANS_NOXAUTH; 6934642e01fSmrg 6947e31ba66Smrg if (!AllocNewConnection(new_trans_conn, newconn, connect_time)) { 6957e31ba66Smrg ErrorConnMax(new_trans_conn); 69605b261ecSmrg } 6975a112b11Smrg return; 69805b261ecSmrg} 69905b261ecSmrg 70005b261ecSmrg#define NOROOM "Maximum number of clients reached" 70105b261ecSmrg 70205b261ecSmrg/************ 70305b261ecSmrg * ErrorConnMax 70405b261ecSmrg * Fail a connection due to lack of client or file descriptor space 70505b261ecSmrg ************/ 70605b261ecSmrg 70705b261ecSmrgstatic void 7087e31ba66SmrgConnMaxNotify(int fd, int events, void *data) 70905b261ecSmrg{ 7107e31ba66Smrg XtransConnInfo trans_conn = data; 711f7df2e56Smrg char order = 0; 7127e31ba66Smrg 71305b261ecSmrg /* try to read the byte-order of the connection */ 714f7df2e56Smrg (void) _XSERVTransRead(trans_conn, &order, 1); 715f7df2e56Smrg if (order == 'l' || order == 'B' || order == 'r' || order == 'R') { 7167e31ba66Smrg xConnSetupPrefix csp; 7177e31ba66Smrg char pad[3] = { 0, 0, 0 }; 7187e31ba66Smrg int whichbyte = 1; 7197e31ba66Smrg struct iovec iov[3]; 7207e31ba66Smrg 721f7df2e56Smrg csp.success = xFalse; 722f7df2e56Smrg csp.lengthReason = sizeof(NOROOM) - 1; 723f7df2e56Smrg csp.length = (sizeof(NOROOM) + 2) >> 2; 724f7df2e56Smrg csp.majorVersion = X_PROTOCOL; 725f7df2e56Smrg csp.minorVersion = X_PROTOCOL_REVISION; 7267e31ba66Smrg if (((*(char *) &whichbyte) && (order == 'B' || order == 'R')) || 7277e31ba66Smrg (!(*(char *) &whichbyte) && (order == 'l' || order == 'r'))) { 728f7df2e56Smrg swaps(&csp.majorVersion); 729f7df2e56Smrg swaps(&csp.minorVersion); 730f7df2e56Smrg swaps(&csp.length); 731f7df2e56Smrg } 732f7df2e56Smrg iov[0].iov_len = sz_xConnSetupPrefix; 733f7df2e56Smrg iov[0].iov_base = (char *) &csp; 734f7df2e56Smrg iov[1].iov_len = csp.lengthReason; 735f7df2e56Smrg iov[1].iov_base = (void *) NOROOM; 736f7df2e56Smrg iov[2].iov_len = (4 - (csp.lengthReason & 3)) & 3; 737f7df2e56Smrg iov[2].iov_base = pad; 738f7df2e56Smrg (void) _XSERVTransWritev(trans_conn, iov, 3); 73905b261ecSmrg } 7407e31ba66Smrg RemoveNotifyFd(trans_conn->fd); 7417e31ba66Smrg _XSERVTransClose(trans_conn); 7427e31ba66Smrg} 7437e31ba66Smrg 7447e31ba66Smrgstatic void 7457e31ba66SmrgErrorConnMax(XtransConnInfo trans_conn) 7467e31ba66Smrg{ 7477e31ba66Smrg if (!SetNotifyFd(trans_conn->fd, ConnMaxNotify, X_NOTIFY_READ, trans_conn)) 7487e31ba66Smrg _XSERVTransClose(trans_conn); 74905b261ecSmrg} 75005b261ecSmrg 75105b261ecSmrg/************ 75205b261ecSmrg * CloseDownFileDescriptor: 7537e31ba66Smrg * Remove this file descriptor 75405b261ecSmrg ************/ 75505b261ecSmrg 7567e31ba66Smrgvoid 75705b261ecSmrgCloseDownFileDescriptor(OsCommPtr oc) 75805b261ecSmrg{ 75905b261ecSmrg if (oc->trans_conn) { 7607e31ba66Smrg int connection = oc->fd; 7617e31ba66Smrg#ifdef XDMCP 7627e31ba66Smrg XdmcpCloseDisplay(connection); 7637e31ba66Smrg#endif 7647e31ba66Smrg ospoll_remove(server_poll, connection); 765f7df2e56Smrg _XSERVTransDisconnect(oc->trans_conn); 766f7df2e56Smrg _XSERVTransClose(oc->trans_conn); 7677e31ba66Smrg oc->trans_conn = NULL; 7687e31ba66Smrg oc->fd = -1; 76905b261ecSmrg } 77005b261ecSmrg} 77105b261ecSmrg 77205b261ecSmrg/***************** 77305b261ecSmrg * CloseDownConnection 774f7df2e56Smrg * Delete client from AllClients and free resources 77505b261ecSmrg *****************/ 77605b261ecSmrg 77705b261ecSmrgvoid 77805b261ecSmrgCloseDownConnection(ClientPtr client) 77905b261ecSmrg{ 780f7df2e56Smrg OsCommPtr oc = (OsCommPtr) client->osPrivate; 78105b261ecSmrg 7826747b715Smrg if (FlushCallback) 7837e31ba66Smrg CallCallbacks(&FlushCallback, client); 7846747b715Smrg 785f7df2e56Smrg if (oc->output) 786f7df2e56Smrg FlushClient(client, oc, (char *) NULL, 0); 78705b261ecSmrg CloseDownFileDescriptor(oc); 78805b261ecSmrg FreeOsBuffers(oc); 7896747b715Smrg free(client->osPrivate); 790f7df2e56Smrg client->osPrivate = (void *) NULL; 79105b261ecSmrg if (auditTrailLevel > 1) 792f7df2e56Smrg AuditF("client %d disconnected\n", client->index); 79305b261ecSmrg} 79405b261ecSmrg 7957e31ba66Smrgstruct notify_fd { 7967e31ba66Smrg int mask; 7977e31ba66Smrg NotifyFdProcPtr notify; 7987e31ba66Smrg void *data; 7997e31ba66Smrg}; 80005b261ecSmrg 8017e31ba66Smrg/***************** 8027e31ba66Smrg * HandleNotifyFd 8037e31ba66Smrg * A poll callback to be called when the registered 8047e31ba66Smrg * file descriptor is ready. 8057e31ba66Smrg *****************/ 80605b261ecSmrg 8077e31ba66Smrgstatic void 8087e31ba66SmrgHandleNotifyFd(int fd, int xevents, void *data) 80905b261ecSmrg{ 8107e31ba66Smrg struct notify_fd *n = data; 8117e31ba66Smrg n->notify(fd, xevents, n->data); 81205b261ecSmrg} 81305b261ecSmrg 8147e31ba66Smrg/***************** 8157e31ba66Smrg * SetNotifyFd 8167e31ba66Smrg * Registers a callback to be invoked when the specified 8177e31ba66Smrg * file descriptor becomes readable. 8187e31ba66Smrg *****************/ 8197e31ba66Smrg 8207e31ba66SmrgBool 8217e31ba66SmrgSetNotifyFd(int fd, NotifyFdProcPtr notify, int mask, void *data) 82205b261ecSmrg{ 8237e31ba66Smrg struct notify_fd *n; 8247e31ba66Smrg 8257e31ba66Smrg n = ospoll_data(server_poll, fd); 8267e31ba66Smrg if (!n) { 8277e31ba66Smrg if (mask == 0) 8287e31ba66Smrg return TRUE; 8297e31ba66Smrg 8307e31ba66Smrg n = calloc(1, sizeof (struct notify_fd)); 8317e31ba66Smrg if (!n) 8327e31ba66Smrg return FALSE; 8337e31ba66Smrg ospoll_add(server_poll, fd, 8347e31ba66Smrg ospoll_trigger_level, 8357e31ba66Smrg HandleNotifyFd, 8367e31ba66Smrg n); 8377e31ba66Smrg } 8387e31ba66Smrg 8397e31ba66Smrg if (mask == 0) { 8407e31ba66Smrg ospoll_remove(server_poll, fd); 8417e31ba66Smrg free(n); 8427e31ba66Smrg } else { 8437e31ba66Smrg int listen = mask & ~n->mask; 8447e31ba66Smrg int mute = n->mask & ~mask; 8457e31ba66Smrg 8467e31ba66Smrg if (listen) 8477e31ba66Smrg ospoll_listen(server_poll, fd, listen); 8487e31ba66Smrg if (mute) 8497e31ba66Smrg ospoll_mute(server_poll, fd, mute); 8507e31ba66Smrg n->mask = mask; 8517e31ba66Smrg n->data = data; 8527e31ba66Smrg n->notify = notify; 8537e31ba66Smrg } 8547e31ba66Smrg 8557e31ba66Smrg return TRUE; 85605b261ecSmrg} 85705b261ecSmrg 85805b261ecSmrg/***************** 85905b261ecSmrg * OnlyListenToOneClient: 86005b261ecSmrg * Only accept requests from one client. Continue to handle new 86105b261ecSmrg * connections, but don't take any protocol requests from the new 86205b261ecSmrg * ones. Note that if GrabInProgress is set, EstablishNewConnections 86305b261ecSmrg * needs to put new clients into SavedAllSockets and SavedAllClients. 86405b261ecSmrg * Note also that there is no timeout for this in the protocol. 86505b261ecSmrg * This routine is "undone" by ListenToAllClients() 86605b261ecSmrg *****************/ 86705b261ecSmrg 8684642e01fSmrgint 86905b261ecSmrgOnlyListenToOneClient(ClientPtr client) 87005b261ecSmrg{ 8717e31ba66Smrg int rc; 8724642e01fSmrg 8734642e01fSmrg rc = XaceHook(XACE_SERVER_ACCESS, client, DixGrabAccess); 8744642e01fSmrg if (rc != Success) 875f7df2e56Smrg return rc; 876f7df2e56Smrg 877f7df2e56Smrg if (!GrabInProgress) { 878f7df2e56Smrg GrabInProgress = client->index; 8797e31ba66Smrg set_poll_clients(); 88005b261ecSmrg } 8817e31ba66Smrg 8824642e01fSmrg return rc; 88305b261ecSmrg} 88405b261ecSmrg 88505b261ecSmrg/**************** 88605b261ecSmrg * ListenToAllClients: 88705b261ecSmrg * Undoes OnlyListentToOneClient() 88805b261ecSmrg ****************/ 88905b261ecSmrg 89005b261ecSmrgvoid 89105b261ecSmrgListenToAllClients(void) 89205b261ecSmrg{ 893f7df2e56Smrg if (GrabInProgress) { 894f7df2e56Smrg GrabInProgress = 0; 8957e31ba66Smrg set_poll_clients(); 896f7df2e56Smrg } 89705b261ecSmrg} 89805b261ecSmrg 89905b261ecSmrg/**************** 90005b261ecSmrg * IgnoreClient 90105b261ecSmrg * Removes one client from input masks. 9025a112b11Smrg * Must have corresponding call to AttendClient. 90305b261ecSmrg ****************/ 90405b261ecSmrg 9056747b715Smrgvoid 906f7df2e56SmrgIgnoreClient(ClientPtr client) 90705b261ecSmrg{ 908f7df2e56Smrg OsCommPtr oc = (OsCommPtr) client->osPrivate; 90905b261ecSmrg 9106747b715Smrg client->ignoreCount++; 9116747b715Smrg if (client->ignoreCount > 1) 912f7df2e56Smrg return; 9136747b715Smrg 91405b261ecSmrg isItTimeToYield = TRUE; 9157e31ba66Smrg mark_client_not_ready(client); 9167e31ba66Smrg 9177e31ba66Smrg oc->flags |= OS_COMM_IGNORED; 9187e31ba66Smrg set_poll_client(client); 91905b261ecSmrg} 92005b261ecSmrg 92105b261ecSmrg/**************** 92205b261ecSmrg * AttendClient 92305b261ecSmrg * Adds one client back into the input masks. 92405b261ecSmrg ****************/ 92505b261ecSmrg 9266747b715Smrgvoid 927f7df2e56SmrgAttendClient(ClientPtr client) 92805b261ecSmrg{ 929f7df2e56Smrg OsCommPtr oc = (OsCommPtr) client->osPrivate; 9306747b715Smrg 9314e185dc0Smrg if (client->clientGone) { 9324e185dc0Smrg /* 9334e185dc0Smrg * client is gone, so any pending requests will be dropped and its 9344e185dc0Smrg * ignore count doesn't matter. 9354e185dc0Smrg */ 9364e185dc0Smrg return; 9374e185dc0Smrg } 9384e185dc0Smrg 9396747b715Smrg client->ignoreCount--; 9406747b715Smrg if (client->ignoreCount) 941f7df2e56Smrg return; 9426747b715Smrg 9437e31ba66Smrg oc->flags &= ~OS_COMM_IGNORED; 9447e31ba66Smrg set_poll_client(client); 9457e31ba66Smrg if (listen_to_client(client)) 9467e31ba66Smrg mark_client_ready(client); 947f7df2e56Smrg else { 9487e31ba66Smrg /* grab active, mark ready when grab goes away */ 9497e31ba66Smrg mark_client_saved_ready(client); 95005b261ecSmrg } 95105b261ecSmrg} 95205b261ecSmrg 95305b261ecSmrg/* make client impervious to grabs; assume only executing client calls this */ 95405b261ecSmrg 9554642e01fSmrgvoid 95605b261ecSmrgMakeClientGrabImpervious(ClientPtr client) 95705b261ecSmrg{ 958f7df2e56Smrg OsCommPtr oc = (OsCommPtr) client->osPrivate; 95905b261ecSmrg 9607e31ba66Smrg oc->flags |= OS_COMM_GRAB_IMPERVIOUS; 9617e31ba66Smrg set_poll_client(client); 96205b261ecSmrg 963f7df2e56Smrg if (ServerGrabCallback) { 964f7df2e56Smrg ServerGrabInfoRec grabinfo; 965f7df2e56Smrg 966f7df2e56Smrg grabinfo.client = client; 967f7df2e56Smrg grabinfo.grabstate = CLIENT_IMPERVIOUS; 968f7df2e56Smrg CallCallbacks(&ServerGrabCallback, &grabinfo); 96905b261ecSmrg } 97005b261ecSmrg} 97105b261ecSmrg 97205b261ecSmrg/* make client pervious to grabs; assume only executing client calls this */ 97305b261ecSmrg 9744642e01fSmrgvoid 97505b261ecSmrgMakeClientGrabPervious(ClientPtr client) 97605b261ecSmrg{ 977f7df2e56Smrg OsCommPtr oc = (OsCommPtr) client->osPrivate; 97805b261ecSmrg 9797e31ba66Smrg oc->flags &= ~OS_COMM_GRAB_IMPERVIOUS; 9807e31ba66Smrg set_poll_client(client); 9817e31ba66Smrg isItTimeToYield = TRUE; 98205b261ecSmrg 983f7df2e56Smrg if (ServerGrabCallback) { 984f7df2e56Smrg ServerGrabInfoRec grabinfo; 985f7df2e56Smrg 986f7df2e56Smrg grabinfo.client = client; 987f7df2e56Smrg grabinfo.grabstate = CLIENT_PERVIOUS; 988f7df2e56Smrg CallCallbacks(&ServerGrabCallback, &grabinfo); 98905b261ecSmrg } 99005b261ecSmrg} 99105b261ecSmrg 992f7df2e56Smrg/* Add a fd (from launchd or similar) to our listeners */ 993f7df2e56Smrgvoid 994f7df2e56SmrgListenOnOpenFD(int fd, int noxauth) 995f7df2e56Smrg{ 99690bea6a0Smrg char port[PATH_MAX]; 9974642e01fSmrg XtransConnInfo ciptr; 9986747b715Smrg const char *display_env = getenv("DISPLAY"); 9994642e01fSmrg 100090bea6a0Smrg /* First check if display_env matches a <absolute path to unix socket>[.<screen number>] scheme (eg: launchd) */ 100190bea6a0Smrg if (display_env && display_env[0] == '/') { 100290bea6a0Smrg struct stat sbuf; 100390bea6a0Smrg 100490bea6a0Smrg strlcpy(port, display_env, sizeof(port)); 100590bea6a0Smrg 100690bea6a0Smrg /* If the path exists, we don't have do do anything else. 100790bea6a0Smrg * If it doesn't, we need to check for a .<screen number> to strip off and recheck. 100890bea6a0Smrg */ 100990bea6a0Smrg if (0 != stat(port, &sbuf)) { 101090bea6a0Smrg char *dot = strrchr(port, '.'); 101190bea6a0Smrg if (dot) { 101290bea6a0Smrg *dot = '\0'; 101390bea6a0Smrg 101490bea6a0Smrg if (0 != stat(port, &sbuf)) { 101590bea6a0Smrg display_env = NULL; 101690bea6a0Smrg } 101790bea6a0Smrg } else { 101890bea6a0Smrg display_env = NULL; 101990bea6a0Smrg } 102090bea6a0Smrg } 1021f7df2e56Smrg } 102290bea6a0Smrg 102390bea6a0Smrg if (!display_env) { 10244642e01fSmrg /* Just some default so things don't break and die. */ 1025f7df2e56Smrg snprintf(port, sizeof(port), ":%d", atoi(display)); 10264642e01fSmrg } 10274642e01fSmrg 10284642e01fSmrg /* Make our XtransConnInfo 10294642e01fSmrg * TRANS_SOCKET_LOCAL_INDEX = 5 from Xtrans.c 10304642e01fSmrg */ 10314642e01fSmrg ciptr = _XSERVTransReopenCOTSServer(5, fd, port); 1032f7df2e56Smrg if (ciptr == NULL) { 1033f7df2e56Smrg ErrorF("Got NULL while trying to Reopen listen port.\n"); 10344642e01fSmrg return; 10354642e01fSmrg } 1036f7df2e56Smrg 1037f7df2e56Smrg if (noxauth) 10384642e01fSmrg ciptr->flags = ciptr->flags | TRANS_NOXAUTH; 10394642e01fSmrg 10404642e01fSmrg /* Allocate space to store it */ 1041f7df2e56Smrg ListenTransFds = 1042f7df2e56Smrg xnfreallocarray(ListenTransFds, ListenTransCount + 1, sizeof(int)); 1043f7df2e56Smrg ListenTransConns = 1044f7df2e56Smrg xnfreallocarray(ListenTransConns, ListenTransCount + 1, 1045f7df2e56Smrg sizeof(XtransConnInfo)); 1046f7df2e56Smrg 10474642e01fSmrg /* Store it */ 10484642e01fSmrg ListenTransConns[ListenTransCount] = ciptr; 10494642e01fSmrg ListenTransFds[ListenTransCount] = fd; 10504642e01fSmrg 10515a112b11Smrg SetNotifyFd(fd, EstablishNewConnections, X_NOTIFY_READ, NULL); 1052f7df2e56Smrg 10534642e01fSmrg /* Increment the count */ 10544642e01fSmrg ListenTransCount++; 10554642e01fSmrg} 10564642e01fSmrg 1057f7df2e56Smrg/* based on TRANS(SocketUNIXAccept) (XtransConnInfo ciptr, int *status) */ 1058f7df2e56SmrgBool 1059f7df2e56SmrgAddClientOnOpenFD(int fd) 1060f7df2e56Smrg{ 1061f7df2e56Smrg XtransConnInfo ciptr; 1062f7df2e56Smrg CARD32 connect_time; 1063f7df2e56Smrg char port[20]; 1064f7df2e56Smrg 1065f7df2e56Smrg snprintf(port, sizeof(port), ":%d", atoi(display)); 1066f7df2e56Smrg ciptr = _XSERVTransReopenCOTSServer(5, fd, port); 1067f7df2e56Smrg if (ciptr == NULL) 1068f7df2e56Smrg return FALSE; 1069f7df2e56Smrg 1070f7df2e56Smrg _XSERVTransSetOption(ciptr, TRANS_NONBLOCKING, 1); 1071f7df2e56Smrg ciptr->flags |= TRANS_NOXAUTH; 1072f7df2e56Smrg 1073f7df2e56Smrg connect_time = GetTimeInMillis(); 1074f7df2e56Smrg 1075f7df2e56Smrg if (!AllocNewConnection(ciptr, fd, connect_time)) { 1076f7df2e56Smrg ErrorConnMax(ciptr); 1077f7df2e56Smrg return FALSE; 1078f7df2e56Smrg } 1079f7df2e56Smrg 1080f7df2e56Smrg return TRUE; 1081f7df2e56Smrg} 10827e31ba66Smrg 10837e31ba66SmrgBool 10847e31ba66Smrglisten_to_client(ClientPtr client) 10857e31ba66Smrg{ 10867e31ba66Smrg OsCommPtr oc = (OsCommPtr) client->osPrivate; 10877e31ba66Smrg 10887e31ba66Smrg if (oc->flags & OS_COMM_IGNORED) 10897e31ba66Smrg return FALSE; 10907e31ba66Smrg 10917e31ba66Smrg if (!GrabInProgress) 10927e31ba66Smrg return TRUE; 10937e31ba66Smrg 10947e31ba66Smrg if (client->index == GrabInProgress) 10957e31ba66Smrg return TRUE; 10967e31ba66Smrg 10977e31ba66Smrg if (oc->flags & OS_COMM_GRAB_IMPERVIOUS) 10987e31ba66Smrg return TRUE; 10997e31ba66Smrg 11007e31ba66Smrg return FALSE; 11017e31ba66Smrg} 11027e31ba66Smrg 11037e31ba66Smrgstatic void 11047e31ba66Smrgset_poll_client(ClientPtr client) 11057e31ba66Smrg{ 11067e31ba66Smrg OsCommPtr oc = (OsCommPtr) client->osPrivate; 11077e31ba66Smrg 11087e31ba66Smrg if (oc->trans_conn) { 11097e31ba66Smrg if (listen_to_client(client)) 11107e31ba66Smrg ospoll_listen(server_poll, oc->trans_conn->fd, X_NOTIFY_READ); 11117e31ba66Smrg else 11127e31ba66Smrg ospoll_mute(server_poll, oc->trans_conn->fd, X_NOTIFY_READ); 11137e31ba66Smrg } 11147e31ba66Smrg} 11157e31ba66Smrg 11167e31ba66Smrgstatic void 11177e31ba66Smrgset_poll_clients(void) 11187e31ba66Smrg{ 11197e31ba66Smrg int i; 11207e31ba66Smrg 11217e31ba66Smrg for (i = 1; i < currentMaxClients; i++) { 11227e31ba66Smrg ClientPtr client = clients[i]; 11237e31ba66Smrg if (client && !client->clientGone) 11247e31ba66Smrg set_poll_client(client); 11257e31ba66Smrg } 11267e31ba66Smrg} 1127