connection.c revision 5a112b11
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 8405b261ecSmrg#ifndef WIN32 8505b261ecSmrg#include <sys/socket.h> 8605b261ecSmrg 877e31ba66Smrg#if defined(TCPCONN) 88f7df2e56Smrg#include <netinet/in.h> 89f7df2e56Smrg#include <arpa/inet.h> 90f7df2e56Smrg#ifdef apollo 91f7df2e56Smrg#ifndef NO_TCP_H 92f7df2e56Smrg#include <netinet/tcp.h> 93f7df2e56Smrg#endif 94f7df2e56Smrg#else 95f7df2e56Smrg#ifdef CSRG_BASED 96f7df2e56Smrg#include <sys/param.h> 97f7df2e56Smrg#endif 98f7df2e56Smrg#include <netinet/tcp.h> 99f7df2e56Smrg#endif 100f7df2e56Smrg#include <arpa/inet.h> 10105b261ecSmrg#endif 10205b261ecSmrg 10305b261ecSmrg#include <sys/uio.h> 1044642e01fSmrg 105f7df2e56Smrg#endif /* WIN32 */ 106f7df2e56Smrg#include "misc.h" /* for typedef of pointer */ 10705b261ecSmrg#include "osdep.h" 10805b261ecSmrg#include "opaque.h" 10905b261ecSmrg#include "dixstruct.h" 11005b261ecSmrg#include "xace.h" 11105b261ecSmrg 11205b261ecSmrg#define Pid_t pid_t 11305b261ecSmrg 114f7df2e56Smrg#ifdef HAVE_GETPEERUCRED 115f7df2e56Smrg#include <ucred.h> 116f7df2e56Smrg#include <zone.h> 117f7df2e56Smrg#else 118f7df2e56Smrg#define zoneid_t int 11905b261ecSmrg#endif 12005b261ecSmrg 1215a112b11Smrg#ifdef HAVE_SYSTEMD_DAEMON 1225a112b11Smrg#include <systemd/sd-daemon.h> 1235a112b11Smrg#endif 1245a112b11Smrg 125f7df2e56Smrg#include "probes.h" 12605b261ecSmrg 1277e31ba66Smrgstruct ospoll *server_poll; 12805b261ecSmrg 129f7df2e56SmrgBool NewOutputPending; /* not yet attempted to write some new output */ 130f7df2e56SmrgBool NoListenAll; /* Don't establish any listening sockets */ 131f7df2e56Smrg 132f7df2e56Smrgstatic Bool RunFromSmartParent; /* send SIGUSR1 to parent process */ 133f7df2e56SmrgBool RunFromSigStopParent; /* send SIGSTOP to our own process; Upstart (or 134f7df2e56Smrg equivalent) will send SIGCONT back. */ 135f7df2e56Smrgstatic char dynamic_display[7]; /* display name */ 136f7df2e56SmrgBool PartialNetwork; /* continue even if unable to bind all addrs */ 13705b261ecSmrgstatic Pid_t ParentProcess; 13805b261ecSmrg 1396747b715Smrgint GrabInProgress = 0; 14005b261ecSmrg 1417e31ba66Smrgstatic void 1425a112b11SmrgEstablishNewConnections(int curconn, int ready, void *data); 143f7df2e56Smrg 1447e31ba66Smrgstatic void 1457e31ba66Smrgset_poll_client(ClientPtr client); 146f7df2e56Smrg 1477e31ba66Smrgstatic void 1487e31ba66Smrgset_poll_clients(void); 14905b261ecSmrg 150f7df2e56Smrgstatic XtransConnInfo *ListenTransConns = NULL; 151f7df2e56Smrgstatic int *ListenTransFds = NULL; 152f7df2e56Smrgstatic int ListenTransCount; 15305b261ecSmrg 154f7df2e56Smrgstatic void ErrorConnMax(XtransConnInfo /* trans_conn */ ); 15505b261ecSmrg 15605b261ecSmrgstatic XtransConnInfo 157f7df2e56Smrglookup_trans_conn(int fd) 15805b261ecSmrg{ 159f7df2e56Smrg if (ListenTransFds) { 160f7df2e56Smrg int i; 161f7df2e56Smrg 162f7df2e56Smrg for (i = 0; i < ListenTransCount; i++) 163f7df2e56Smrg if (ListenTransFds[i] == fd) 164f7df2e56Smrg return ListenTransConns[i]; 16505b261ecSmrg } 16605b261ecSmrg 1676747b715Smrg return NULL; 16805b261ecSmrg} 16905b261ecSmrg 1704642e01fSmrg/* 1714642e01fSmrg * If SIGUSR1 was set to SIG_IGN when the server started, assume that either 1724642e01fSmrg * 1734642e01fSmrg * a- The parent process is ignoring SIGUSR1 1744642e01fSmrg * 1754642e01fSmrg * or 1764642e01fSmrg * 1774642e01fSmrg * b- The parent process is expecting a SIGUSR1 1784642e01fSmrg * when the server is ready to accept connections 1794642e01fSmrg * 1804642e01fSmrg * In the first case, the signal will be harmless, in the second case, 1814642e01fSmrg * the signal will be quite useful. 1824642e01fSmrg */ 1834642e01fSmrgstatic void 1844642e01fSmrgInitParentProcess(void) 1854642e01fSmrg{ 1864642e01fSmrg#if !defined(WIN32) 1874642e01fSmrg OsSigHandlerPtr handler; 188f7df2e56Smrg 189f7df2e56Smrg handler = OsSignal(SIGUSR1, SIG_IGN); 190f7df2e56Smrg if (handler == SIG_IGN) 191f7df2e56Smrg RunFromSmartParent = TRUE; 1924642e01fSmrg OsSignal(SIGUSR1, handler); 193f7df2e56Smrg ParentProcess = getppid(); 1944642e01fSmrg#endif 1954642e01fSmrg} 1964642e01fSmrg 1974642e01fSmrgvoid 1984642e01fSmrgNotifyParentProcess(void) 1994642e01fSmrg{ 2004642e01fSmrg#if !defined(WIN32) 201f7df2e56Smrg if (displayfd >= 0) { 202f7df2e56Smrg if (write(displayfd, display, strlen(display)) != strlen(display)) 203f7df2e56Smrg FatalError("Cannot write display number to fd %d\n", displayfd); 204f7df2e56Smrg if (write(displayfd, "\n", 1) != 1) 205f7df2e56Smrg FatalError("Cannot write display number to fd %d\n", displayfd); 206f7df2e56Smrg close(displayfd); 207f7df2e56Smrg displayfd = -1; 208f7df2e56Smrg } 2094642e01fSmrg if (RunFromSmartParent) { 210f7df2e56Smrg if (ParentProcess > 1) { 211f7df2e56Smrg kill(ParentProcess, SIGUSR1); 212f7df2e56Smrg } 2134642e01fSmrg } 2149ace9065Smrg if (RunFromSigStopParent) 215f7df2e56Smrg raise(SIGSTOP); 2165a112b11Smrg#ifdef HAVE_SYSTEMD_DAEMON 2175a112b11Smrg /* If we have been started as a systemd service, tell systemd that 2185a112b11Smrg we are ready. Otherwise sd_notify() won't do anything. */ 2195a112b11Smrg sd_notify(0, "READY=1"); 2205a112b11Smrg#endif 2214642e01fSmrg#endif 2224642e01fSmrg} 22305b261ecSmrg 224f7df2e56Smrgstatic Bool 225f7df2e56SmrgTryCreateSocket(int num, int *partial) 226f7df2e56Smrg{ 227f7df2e56Smrg char port[20]; 228f7df2e56Smrg 229f7df2e56Smrg snprintf(port, sizeof(port), "%d", num); 230f7df2e56Smrg 231f7df2e56Smrg return (_XSERVTransMakeAllCOTSServerListeners(port, partial, 232f7df2e56Smrg &ListenTransCount, 233f7df2e56Smrg &ListenTransConns) >= 0); 234f7df2e56Smrg} 235f7df2e56Smrg 23605b261ecSmrg/***************** 23705b261ecSmrg * CreateWellKnownSockets 23805b261ecSmrg * At initialization, create the sockets to listen on for new clients. 23905b261ecSmrg *****************/ 24005b261ecSmrg 24105b261ecSmrgvoid 24205b261ecSmrgCreateWellKnownSockets(void) 24305b261ecSmrg{ 244f7df2e56Smrg int i; 245f7df2e56Smrg int partial; 24605b261ecSmrg 247f7df2e56Smrg /* display is initialized to "0" by main(). It is then set to the display 248f7df2e56Smrg * number if specified on the command line. */ 24905b261ecSmrg 250f7df2e56Smrg if (NoListenAll) { 251f7df2e56Smrg ListenTransCount = 0; 252f7df2e56Smrg } 253f7df2e56Smrg else if ((displayfd < 0) || explicit_display) { 254f7df2e56Smrg if (TryCreateSocket(atoi(display), &partial) && 255f7df2e56Smrg ListenTransCount >= 1) 256f7df2e56Smrg if (!PartialNetwork && partial) 257f7df2e56Smrg FatalError ("Failed to establish all listening sockets"); 258f7df2e56Smrg } 259f7df2e56Smrg else { /* -displayfd and no explicit display number */ 260f7df2e56Smrg Bool found = 0; 261f7df2e56Smrg for (i = 0; i < 65536 - X_TCP_PORT; i++) { 262f7df2e56Smrg if (TryCreateSocket(i, &partial) && !partial) { 263f7df2e56Smrg found = 1; 264f7df2e56Smrg break; 265f7df2e56Smrg } 266f7df2e56Smrg else 267f7df2e56Smrg CloseWellKnownConnections(); 268f7df2e56Smrg } 269f7df2e56Smrg if (!found) 270f7df2e56Smrg FatalError("Failed to find a socket to listen on"); 271f7df2e56Smrg snprintf(dynamic_display, sizeof(dynamic_display), "%d", i); 272f7df2e56Smrg display = dynamic_display; 273f7df2e56Smrg LogSetDisplay(); 274f7df2e56Smrg } 275f7df2e56Smrg 276f7df2e56Smrg ListenTransFds = xallocarray(ListenTransCount, sizeof (int)); 277f7df2e56Smrg if (ListenTransFds == NULL) 278f7df2e56Smrg FatalError ("Failed to create listening socket array"); 279f7df2e56Smrg 280f7df2e56Smrg for (i = 0; i < ListenTransCount; i++) { 281f7df2e56Smrg int fd = _XSERVTransGetConnectionNumber(ListenTransConns[i]); 282f7df2e56Smrg 283f7df2e56Smrg ListenTransFds[i] = fd; 2845a112b11Smrg SetNotifyFd(fd, EstablishNewConnections, X_NOTIFY_READ, NULL); 285f7df2e56Smrg 286f7df2e56Smrg if (!_XSERVTransIsLocal(ListenTransConns[i])) 287f7df2e56Smrg DefineSelf (fd); 28805b261ecSmrg } 28905b261ecSmrg 2907e31ba66Smrg if (ListenTransCount == 0 && !NoListenAll) 291f7df2e56Smrg FatalError 292f7df2e56Smrg ("Cannot establish any listening sockets - Make sure an X server isn't already running"); 293f7df2e56Smrg 29405b261ecSmrg#if !defined(WIN32) 295f7df2e56Smrg OsSignal(SIGPIPE, SIG_IGN); 296f7df2e56Smrg OsSignal(SIGHUP, AutoResetServer); 29705b261ecSmrg#endif 298f7df2e56Smrg OsSignal(SIGINT, GiveUp); 299f7df2e56Smrg OsSignal(SIGTERM, GiveUp); 30005b261ecSmrg ResetHosts(display); 3014642e01fSmrg 3024642e01fSmrg InitParentProcess(); 3034642e01fSmrg 30405b261ecSmrg#ifdef XDMCP 305f7df2e56Smrg XdmcpInit(); 30605b261ecSmrg#endif 30705b261ecSmrg} 30805b261ecSmrg 30905b261ecSmrgvoid 310f7df2e56SmrgResetWellKnownSockets(void) 31105b261ecSmrg{ 31205b261ecSmrg int i; 31305b261ecSmrg 31405b261ecSmrg ResetOsBuffers(); 31505b261ecSmrg 316f7df2e56Smrg for (i = 0; i < ListenTransCount; i++) { 317f7df2e56Smrg int status = _XSERVTransResetListener(ListenTransConns[i]); 318f7df2e56Smrg 319f7df2e56Smrg if (status != TRANS_RESET_NOOP) { 320f7df2e56Smrg if (status == TRANS_RESET_FAILURE) { 321f7df2e56Smrg /* 322f7df2e56Smrg * ListenTransConns[i] freed by xtrans. 323f7df2e56Smrg * Remove it from out list. 324f7df2e56Smrg */ 325f7df2e56Smrg 3267e31ba66Smrg RemoveNotifyFd(ListenTransFds[i]); 327f7df2e56Smrg ListenTransFds[i] = ListenTransFds[ListenTransCount - 1]; 328f7df2e56Smrg ListenTransConns[i] = ListenTransConns[ListenTransCount - 1]; 329f7df2e56Smrg ListenTransCount -= 1; 330f7df2e56Smrg i -= 1; 331f7df2e56Smrg } 332f7df2e56Smrg else if (status == TRANS_RESET_NEW_FD) { 333f7df2e56Smrg /* 334f7df2e56Smrg * A new file descriptor was allocated (the old one was closed) 335f7df2e56Smrg */ 336f7df2e56Smrg 337f7df2e56Smrg int newfd = _XSERVTransGetConnectionNumber(ListenTransConns[i]); 338f7df2e56Smrg 339f7df2e56Smrg ListenTransFds[i] = newfd; 340f7df2e56Smrg } 341f7df2e56Smrg } 34205b261ecSmrg } 3437e31ba66Smrg for (i = 0; i < ListenTransCount; i++) 3445a112b11Smrg SetNotifyFd(ListenTransFds[i], EstablishNewConnections, X_NOTIFY_READ, 3455a112b11Smrg NULL); 34605b261ecSmrg 347f7df2e56Smrg ResetAuthorization(); 34805b261ecSmrg ResetHosts(display); 34905b261ecSmrg /* 35005b261ecSmrg * restart XDMCP 35105b261ecSmrg */ 35205b261ecSmrg#ifdef XDMCP 353f7df2e56Smrg XdmcpReset(); 35405b261ecSmrg#endif 35505b261ecSmrg} 35605b261ecSmrg 35705b261ecSmrgvoid 35805b261ecSmrgCloseWellKnownConnections(void) 35905b261ecSmrg{ 36005b261ecSmrg int i; 36105b261ecSmrg 362f7df2e56Smrg for (i = 0; i < ListenTransCount; i++) { 363f7df2e56Smrg if (ListenTransConns[i] != NULL) { 364f7df2e56Smrg _XSERVTransClose(ListenTransConns[i]); 365f7df2e56Smrg ListenTransConns[i] = NULL; 3667e31ba66Smrg if (ListenTransFds != NULL) 3677e31ba66Smrg RemoveNotifyFd(ListenTransFds[i]); 368f7df2e56Smrg } 369f7df2e56Smrg } 370f7df2e56Smrg ListenTransCount = 0; 37105b261ecSmrg} 37205b261ecSmrg 37305b261ecSmrgstatic void 374f7df2e56SmrgAuthAudit(ClientPtr client, Bool letin, 375f7df2e56Smrg struct sockaddr *saddr, int len, 376f7df2e56Smrg unsigned int proto_n, char *auth_proto, int auth_id) 37705b261ecSmrg{ 37805b261ecSmrg char addr[128]; 37905b261ecSmrg char client_uid_string[64]; 3804642e01fSmrg LocalClientCredRec *lcc; 381f7df2e56Smrg 3824642e01fSmrg#ifdef XSERVER_DTRACE 38305b261ecSmrg pid_t client_pid = -1; 38405b261ecSmrg zoneid_t client_zid = -1; 38505b261ecSmrg#endif 38605b261ecSmrg 38705b261ecSmrg if (!len) 388f7df2e56Smrg strlcpy(addr, "local host", sizeof(addr)); 38905b261ecSmrg else 390f7df2e56Smrg switch (saddr->sa_family) { 391f7df2e56Smrg case AF_UNSPEC: 39205b261ecSmrg#if defined(UNIXCONN) || defined(LOCALCONN) 393f7df2e56Smrg case AF_UNIX: 39405b261ecSmrg#endif 395f7df2e56Smrg strlcpy(addr, "local host", sizeof(addr)); 396f7df2e56Smrg break; 3977e31ba66Smrg#if defined(TCPCONN) 398f7df2e56Smrg case AF_INET: 399f7df2e56Smrg snprintf(addr, sizeof(addr), "IP %s", 400f7df2e56Smrg inet_ntoa(((struct sockaddr_in *) saddr)->sin_addr)); 401f7df2e56Smrg break; 40205b261ecSmrg#if defined(IPv6) && defined(AF_INET6) 403f7df2e56Smrg case AF_INET6:{ 404f7df2e56Smrg char ipaddr[INET6_ADDRSTRLEN]; 405f7df2e56Smrg 406f7df2e56Smrg inet_ntop(AF_INET6, &((struct sockaddr_in6 *) saddr)->sin6_addr, 407f7df2e56Smrg ipaddr, sizeof(ipaddr)); 408f7df2e56Smrg snprintf(addr, sizeof(addr), "IP %s", ipaddr); 409f7df2e56Smrg } 410f7df2e56Smrg break; 41105b261ecSmrg#endif 41205b261ecSmrg#endif 413f7df2e56Smrg default: 414f7df2e56Smrg strlcpy(addr, "unknown address", sizeof(addr)); 415f7df2e56Smrg } 41605b261ecSmrg 4174642e01fSmrg if (GetLocalClientCreds(client, &lcc) != -1) { 418f7df2e56Smrg int slen; /* length written to client_uid_string */ 419f7df2e56Smrg 420f7df2e56Smrg strcpy(client_uid_string, " ( "); 421f7df2e56Smrg slen = 3; 422f7df2e56Smrg 423f7df2e56Smrg if (lcc->fieldsSet & LCC_UID_SET) { 424f7df2e56Smrg snprintf(client_uid_string + slen, 425f7df2e56Smrg sizeof(client_uid_string) - slen, 426f7df2e56Smrg "uid=%ld ", (long) lcc->euid); 427f7df2e56Smrg slen = strlen(client_uid_string); 428f7df2e56Smrg } 429f7df2e56Smrg 430f7df2e56Smrg if (lcc->fieldsSet & LCC_GID_SET) { 431f7df2e56Smrg snprintf(client_uid_string + slen, 432f7df2e56Smrg sizeof(client_uid_string) - slen, 433f7df2e56Smrg "gid=%ld ", (long) lcc->egid); 434f7df2e56Smrg slen = strlen(client_uid_string); 435f7df2e56Smrg } 436f7df2e56Smrg 437f7df2e56Smrg if (lcc->fieldsSet & LCC_PID_SET) { 438f7df2e56Smrg#ifdef XSERVER_DTRACE 439f7df2e56Smrg client_pid = lcc->pid; 44005b261ecSmrg#endif 441f7df2e56Smrg snprintf(client_uid_string + slen, 442f7df2e56Smrg sizeof(client_uid_string) - slen, 443f7df2e56Smrg "pid=%ld ", (long) lcc->pid); 444f7df2e56Smrg slen = strlen(client_uid_string); 445f7df2e56Smrg } 446f7df2e56Smrg 447f7df2e56Smrg if (lcc->fieldsSet & LCC_ZID_SET) { 4484642e01fSmrg#ifdef XSERVER_DTRACE 449f7df2e56Smrg client_zid = lcc->zoneid; 450f7df2e56Smrg#endif 451f7df2e56Smrg snprintf(client_uid_string + slen, 452f7df2e56Smrg sizeof(client_uid_string) - slen, 453f7df2e56Smrg "zoneid=%ld ", (long) lcc->zoneid); 454f7df2e56Smrg slen = strlen(client_uid_string); 455f7df2e56Smrg } 456f7df2e56Smrg 457f7df2e56Smrg snprintf(client_uid_string + slen, sizeof(client_uid_string) - slen, 458f7df2e56Smrg ")"); 459f7df2e56Smrg FreeLocalClientCreds(lcc); 4604642e01fSmrg } 46105b261ecSmrg else { 462f7df2e56Smrg client_uid_string[0] = '\0'; 46305b261ecSmrg } 464f7df2e56Smrg 46505b261ecSmrg#ifdef XSERVER_DTRACE 46605b261ecSmrg XSERVER_CLIENT_AUTH(client->index, addr, client_pid, client_zid); 46705b261ecSmrg#endif 4684642e01fSmrg if (auditTrailLevel > 1) { 469f7df2e56Smrg if (proto_n) 470f7df2e56Smrg AuditF("client %d %s from %s%s\n Auth name: %.*s ID: %d\n", 471f7df2e56Smrg client->index, letin ? "connected" : "rejected", addr, 472f7df2e56Smrg client_uid_string, (int) proto_n, auth_proto, auth_id); 473f7df2e56Smrg else 474f7df2e56Smrg AuditF("client %d %s from %s%s\n", 475f7df2e56Smrg client->index, letin ? "connected" : "rejected", addr, 476f7df2e56Smrg client_uid_string); 47705b261ecSmrg 47805b261ecSmrg } 47905b261ecSmrg} 48005b261ecSmrg 48105b261ecSmrgXID 48205b261ecSmrgAuthorizationIDOfClient(ClientPtr client) 48305b261ecSmrg{ 48405b261ecSmrg if (client->osPrivate) 485f7df2e56Smrg return ((OsCommPtr) client->osPrivate)->auth_id; 48605b261ecSmrg else 487f7df2e56Smrg return None; 48805b261ecSmrg} 48905b261ecSmrg 49005b261ecSmrg/***************************************************************** 49105b261ecSmrg * ClientAuthorized 49205b261ecSmrg * 49305b261ecSmrg * Sent by the client at connection setup: 49405b261ecSmrg * typedef struct _xConnClientPrefix { 49505b261ecSmrg * CARD8 byteOrder; 49605b261ecSmrg * BYTE pad; 49705b261ecSmrg * CARD16 majorVersion, minorVersion; 498f7df2e56Smrg * CARD16 nbytesAuthProto; 499f7df2e56Smrg * CARD16 nbytesAuthString; 50005b261ecSmrg * } xConnClientPrefix; 50105b261ecSmrg * 50205b261ecSmrg * It is hoped that eventually one protocol will be agreed upon. In the 50305b261ecSmrg * mean time, a server that implements a different protocol than the 50405b261ecSmrg * client expects, or a server that only implements the host-based 50505b261ecSmrg * mechanism, will simply ignore this information. 50605b261ecSmrg * 50705b261ecSmrg *****************************************************************/ 50805b261ecSmrg 509f7df2e56Smrgconst char * 510f7df2e56SmrgClientAuthorized(ClientPtr client, 511f7df2e56Smrg unsigned int proto_n, char *auth_proto, 512f7df2e56Smrg unsigned int string_n, char *auth_string) 51305b261ecSmrg{ 514f7df2e56Smrg OsCommPtr priv; 515f7df2e56Smrg Xtransaddr *from = NULL; 516f7df2e56Smrg int family; 517f7df2e56Smrg int fromlen; 518f7df2e56Smrg XID auth_id; 519f7df2e56Smrg const char *reason = NULL; 520f7df2e56Smrg XtransConnInfo trans_conn; 521f7df2e56Smrg 522f7df2e56Smrg priv = (OsCommPtr) client->osPrivate; 52305b261ecSmrg trans_conn = priv->trans_conn; 52405b261ecSmrg 5254642e01fSmrg /* Allow any client to connect without authorization on a launchd socket, 5264642e01fSmrg because it is securely created -- this prevents a race condition on launch */ 527f7df2e56Smrg if (trans_conn->flags & TRANS_NOXAUTH) { 5284642e01fSmrg auth_id = (XID) 0L; 529f7df2e56Smrg } 530f7df2e56Smrg else { 531f7df2e56Smrg auth_id = 532f7df2e56Smrg CheckAuthorization(proto_n, auth_proto, string_n, auth_string, 533f7df2e56Smrg client, &reason); 5344642e01fSmrg } 53505b261ecSmrg 536f7df2e56Smrg if (auth_id == (XID) ~0L) { 537f7df2e56Smrg if (_XSERVTransGetPeerAddr(trans_conn, &family, &fromlen, &from) != -1) { 538f7df2e56Smrg if (InvalidHost((struct sockaddr *) from, fromlen, client)) 539f7df2e56Smrg AuthAudit(client, FALSE, (struct sockaddr *) from, 540f7df2e56Smrg fromlen, proto_n, auth_proto, auth_id); 541f7df2e56Smrg else { 542f7df2e56Smrg auth_id = (XID) 0; 54305b261ecSmrg#ifdef XSERVER_DTRACE 544f7df2e56Smrg if ((auditTrailLevel > 1) || XSERVER_CLIENT_AUTH_ENABLED()) 54505b261ecSmrg#else 546f7df2e56Smrg if (auditTrailLevel > 1) 54705b261ecSmrg#endif 548f7df2e56Smrg AuthAudit(client, TRUE, 549f7df2e56Smrg (struct sockaddr *) from, fromlen, 550f7df2e56Smrg proto_n, auth_proto, auth_id); 551f7df2e56Smrg } 552f7df2e56Smrg 553f7df2e56Smrg free(from); 554f7df2e56Smrg } 555f7df2e56Smrg 556f7df2e56Smrg if (auth_id == (XID) ~0L) { 557f7df2e56Smrg if (reason) 558f7df2e56Smrg return reason; 559f7df2e56Smrg else 560f7df2e56Smrg return "Client is not authorized to connect to Server"; 561f7df2e56Smrg } 56205b261ecSmrg } 56305b261ecSmrg#ifdef XSERVER_DTRACE 56405b261ecSmrg else if ((auditTrailLevel > 1) || XSERVER_CLIENT_AUTH_ENABLED()) 56505b261ecSmrg#else 56605b261ecSmrg else if (auditTrailLevel > 1) 56705b261ecSmrg#endif 56805b261ecSmrg { 569f7df2e56Smrg if (_XSERVTransGetPeerAddr(trans_conn, &family, &fromlen, &from) != -1) { 570f7df2e56Smrg AuthAudit(client, TRUE, (struct sockaddr *) from, fromlen, 571f7df2e56Smrg proto_n, auth_proto, auth_id); 572f7df2e56Smrg 573f7df2e56Smrg free(from); 574f7df2e56Smrg } 57505b261ecSmrg } 57605b261ecSmrg priv->auth_id = auth_id; 57705b261ecSmrg priv->conn_time = 0; 57805b261ecSmrg 57905b261ecSmrg#ifdef XDMCP 58005b261ecSmrg /* indicate to Xdmcp protocol that we've opened new client */ 58105b261ecSmrg XdmcpOpenDisplay(priv->fd); 582f7df2e56Smrg#endif /* XDMCP */ 58305b261ecSmrg 58405b261ecSmrg XaceHook(XACE_AUTH_AVAIL, client, auth_id); 58505b261ecSmrg 58605b261ecSmrg /* At this point, if the client is authorized to change the access control 58705b261ecSmrg * list, we should getpeername() information, and add the client to 58805b261ecSmrg * the selfhosts list. It's not really the host machine, but the 58905b261ecSmrg * true purpose of the selfhosts list is to see who may change the 59005b261ecSmrg * access control list. 59105b261ecSmrg */ 592f7df2e56Smrg return ((char *) NULL); 59305b261ecSmrg} 59405b261ecSmrg 5957e31ba66Smrgstatic void 5967e31ba66SmrgClientReady(int fd, int xevents, void *data) 5977e31ba66Smrg{ 5987e31ba66Smrg ClientPtr client = data; 5997e31ba66Smrg 6007e31ba66Smrg if (xevents & X_NOTIFY_ERROR) { 6017e31ba66Smrg CloseDownClient(client); 6027e31ba66Smrg return; 6037e31ba66Smrg } 6047e31ba66Smrg if (xevents & X_NOTIFY_READ) 6057e31ba66Smrg mark_client_ready(client); 6067e31ba66Smrg if (xevents & X_NOTIFY_WRITE) { 6077e31ba66Smrg ospoll_mute(server_poll, fd, X_NOTIFY_WRITE); 6087e31ba66Smrg NewOutputPending = TRUE; 6097e31ba66Smrg } 6107e31ba66Smrg} 6117e31ba66Smrg 61205b261ecSmrgstatic ClientPtr 613f7df2e56SmrgAllocNewConnection(XtransConnInfo trans_conn, int fd, CARD32 conn_time) 61405b261ecSmrg{ 615f7df2e56Smrg OsCommPtr oc; 616f7df2e56Smrg ClientPtr client; 617f7df2e56Smrg 6186747b715Smrg oc = malloc(sizeof(OsCommRec)); 61905b261ecSmrg if (!oc) 620f7df2e56Smrg return NullClient; 62105b261ecSmrg oc->trans_conn = trans_conn; 62205b261ecSmrg oc->fd = fd; 623f7df2e56Smrg oc->input = (ConnectionInputPtr) NULL; 624f7df2e56Smrg oc->output = (ConnectionOutputPtr) NULL; 62505b261ecSmrg oc->auth_id = None; 62605b261ecSmrg oc->conn_time = conn_time; 6277e31ba66Smrg oc->flags = 0; 628f7df2e56Smrg if (!(client = NextAvailableClient((void *) oc))) { 629f7df2e56Smrg free(oc); 630f7df2e56Smrg return NullClient; 63105b261ecSmrg } 632f7df2e56Smrg client->local = ComputeLocalClient(client); 6337e31ba66Smrg ospoll_add(server_poll, fd, 6347e31ba66Smrg ospoll_trigger_edge, 6357e31ba66Smrg ClientReady, 6367e31ba66Smrg client); 6377e31ba66Smrg set_poll_client(client); 63805b261ecSmrg 63905b261ecSmrg#ifdef DEBUG 64005b261ecSmrg ErrorF("AllocNewConnection: client index = %d, socket fd = %d\n", 641f7df2e56Smrg client->index, fd); 64205b261ecSmrg#endif 64305b261ecSmrg#ifdef XSERVER_DTRACE 64405b261ecSmrg XSERVER_CLIENT_CONNECT(client->index, fd); 645f7df2e56Smrg#endif 64605b261ecSmrg 64705b261ecSmrg return client; 64805b261ecSmrg} 64905b261ecSmrg 65005b261ecSmrg/***************** 65105b261ecSmrg * EstablishNewConnections 6525a112b11Smrg * If anyone is waiting on listened sockets, accept them. Drop pending 6535a112b11Smrg * connections if they've stuck around for more than one minute. 65405b261ecSmrg *****************/ 6555a112b11Smrg#define TimeOutValue 60 * MILLI_PER_SECOND 6565a112b11Smrgstatic void 6575a112b11SmrgEstablishNewConnections(int curconn, int ready, void *data) 65805b261ecSmrg{ 6597e31ba66Smrg int newconn; /* fd of new client */ 66005b261ecSmrg CARD32 connect_time; 6617e31ba66Smrg int i; 6627e31ba66Smrg ClientPtr client; 6637e31ba66Smrg OsCommPtr oc; 6647e31ba66Smrg XtransConnInfo trans_conn, new_trans_conn; 6657e31ba66Smrg int status; 6667e31ba66Smrg 66705b261ecSmrg connect_time = GetTimeInMillis(); 66805b261ecSmrg /* kill off stragglers */ 669f7df2e56Smrg for (i = 1; i < currentMaxClients; i++) { 670f7df2e56Smrg if ((client = clients[i])) { 671f7df2e56Smrg oc = (OsCommPtr) (client->osPrivate); 672f7df2e56Smrg if ((oc && (oc->conn_time != 0) && 673f7df2e56Smrg (connect_time - oc->conn_time) >= TimeOutValue) || 674f7df2e56Smrg (client->noClientException != Success && !client->clientGone)) 675f7df2e56Smrg CloseDownClient(client); 676f7df2e56Smrg } 67705b261ecSmrg } 67805b261ecSmrg 6797e31ba66Smrg if ((trans_conn = lookup_trans_conn(curconn)) == NULL) 6805a112b11Smrg return; 681f7df2e56Smrg 6827e31ba66Smrg if ((new_trans_conn = _XSERVTransAccept(trans_conn, &status)) == NULL) 6835a112b11Smrg return; 68405b261ecSmrg 6857e31ba66Smrg newconn = _XSERVTransGetConnectionNumber(new_trans_conn); 68605b261ecSmrg 6877e31ba66Smrg _XSERVTransSetOption(new_trans_conn, TRANS_NONBLOCKING, 1); 6884642e01fSmrg 6897e31ba66Smrg if (trans_conn->flags & TRANS_NOXAUTH) 6907e31ba66Smrg new_trans_conn->flags = new_trans_conn->flags | TRANS_NOXAUTH; 6914642e01fSmrg 6927e31ba66Smrg if (!AllocNewConnection(new_trans_conn, newconn, connect_time)) { 6937e31ba66Smrg ErrorConnMax(new_trans_conn); 69405b261ecSmrg } 6955a112b11Smrg return; 69605b261ecSmrg} 69705b261ecSmrg 69805b261ecSmrg#define NOROOM "Maximum number of clients reached" 69905b261ecSmrg 70005b261ecSmrg/************ 70105b261ecSmrg * ErrorConnMax 70205b261ecSmrg * Fail a connection due to lack of client or file descriptor space 70305b261ecSmrg ************/ 70405b261ecSmrg 70505b261ecSmrgstatic void 7067e31ba66SmrgConnMaxNotify(int fd, int events, void *data) 70705b261ecSmrg{ 7087e31ba66Smrg XtransConnInfo trans_conn = data; 709f7df2e56Smrg char order = 0; 7107e31ba66Smrg 71105b261ecSmrg /* try to read the byte-order of the connection */ 712f7df2e56Smrg (void) _XSERVTransRead(trans_conn, &order, 1); 713f7df2e56Smrg if (order == 'l' || order == 'B' || order == 'r' || order == 'R') { 7147e31ba66Smrg xConnSetupPrefix csp; 7157e31ba66Smrg char pad[3] = { 0, 0, 0 }; 7167e31ba66Smrg int whichbyte = 1; 7177e31ba66Smrg struct iovec iov[3]; 7187e31ba66Smrg 719f7df2e56Smrg csp.success = xFalse; 720f7df2e56Smrg csp.lengthReason = sizeof(NOROOM) - 1; 721f7df2e56Smrg csp.length = (sizeof(NOROOM) + 2) >> 2; 722f7df2e56Smrg csp.majorVersion = X_PROTOCOL; 723f7df2e56Smrg csp.minorVersion = X_PROTOCOL_REVISION; 7247e31ba66Smrg if (((*(char *) &whichbyte) && (order == 'B' || order == 'R')) || 7257e31ba66Smrg (!(*(char *) &whichbyte) && (order == 'l' || order == 'r'))) { 726f7df2e56Smrg swaps(&csp.majorVersion); 727f7df2e56Smrg swaps(&csp.minorVersion); 728f7df2e56Smrg swaps(&csp.length); 729f7df2e56Smrg } 730f7df2e56Smrg iov[0].iov_len = sz_xConnSetupPrefix; 731f7df2e56Smrg iov[0].iov_base = (char *) &csp; 732f7df2e56Smrg iov[1].iov_len = csp.lengthReason; 733f7df2e56Smrg iov[1].iov_base = (void *) NOROOM; 734f7df2e56Smrg iov[2].iov_len = (4 - (csp.lengthReason & 3)) & 3; 735f7df2e56Smrg iov[2].iov_base = pad; 736f7df2e56Smrg (void) _XSERVTransWritev(trans_conn, iov, 3); 73705b261ecSmrg } 7387e31ba66Smrg RemoveNotifyFd(trans_conn->fd); 7397e31ba66Smrg _XSERVTransClose(trans_conn); 7407e31ba66Smrg} 7417e31ba66Smrg 7427e31ba66Smrgstatic void 7437e31ba66SmrgErrorConnMax(XtransConnInfo trans_conn) 7447e31ba66Smrg{ 7457e31ba66Smrg if (!SetNotifyFd(trans_conn->fd, ConnMaxNotify, X_NOTIFY_READ, trans_conn)) 7467e31ba66Smrg _XSERVTransClose(trans_conn); 74705b261ecSmrg} 74805b261ecSmrg 74905b261ecSmrg/************ 75005b261ecSmrg * CloseDownFileDescriptor: 7517e31ba66Smrg * Remove this file descriptor 75205b261ecSmrg ************/ 75305b261ecSmrg 7547e31ba66Smrgvoid 75505b261ecSmrgCloseDownFileDescriptor(OsCommPtr oc) 75605b261ecSmrg{ 75705b261ecSmrg if (oc->trans_conn) { 7587e31ba66Smrg int connection = oc->fd; 7597e31ba66Smrg#ifdef XDMCP 7607e31ba66Smrg XdmcpCloseDisplay(connection); 7617e31ba66Smrg#endif 7627e31ba66Smrg ospoll_remove(server_poll, connection); 763f7df2e56Smrg _XSERVTransDisconnect(oc->trans_conn); 764f7df2e56Smrg _XSERVTransClose(oc->trans_conn); 7657e31ba66Smrg oc->trans_conn = NULL; 7667e31ba66Smrg oc->fd = -1; 76705b261ecSmrg } 76805b261ecSmrg} 76905b261ecSmrg 77005b261ecSmrg/***************** 77105b261ecSmrg * CloseDownConnection 772f7df2e56Smrg * Delete client from AllClients and free resources 77305b261ecSmrg *****************/ 77405b261ecSmrg 77505b261ecSmrgvoid 77605b261ecSmrgCloseDownConnection(ClientPtr client) 77705b261ecSmrg{ 778f7df2e56Smrg OsCommPtr oc = (OsCommPtr) client->osPrivate; 77905b261ecSmrg 7806747b715Smrg if (FlushCallback) 7817e31ba66Smrg CallCallbacks(&FlushCallback, client); 7826747b715Smrg 783f7df2e56Smrg if (oc->output) 784f7df2e56Smrg FlushClient(client, oc, (char *) NULL, 0); 78505b261ecSmrg CloseDownFileDescriptor(oc); 78605b261ecSmrg FreeOsBuffers(oc); 7876747b715Smrg free(client->osPrivate); 788f7df2e56Smrg client->osPrivate = (void *) NULL; 78905b261ecSmrg if (auditTrailLevel > 1) 790f7df2e56Smrg AuditF("client %d disconnected\n", client->index); 79105b261ecSmrg} 79205b261ecSmrg 7937e31ba66Smrgstruct notify_fd { 7947e31ba66Smrg int mask; 7957e31ba66Smrg NotifyFdProcPtr notify; 7967e31ba66Smrg void *data; 7977e31ba66Smrg}; 79805b261ecSmrg 7997e31ba66Smrg/***************** 8007e31ba66Smrg * HandleNotifyFd 8017e31ba66Smrg * A poll callback to be called when the registered 8027e31ba66Smrg * file descriptor is ready. 8037e31ba66Smrg *****************/ 80405b261ecSmrg 8057e31ba66Smrgstatic void 8067e31ba66SmrgHandleNotifyFd(int fd, int xevents, void *data) 80705b261ecSmrg{ 8087e31ba66Smrg struct notify_fd *n = data; 8097e31ba66Smrg n->notify(fd, xevents, n->data); 81005b261ecSmrg} 81105b261ecSmrg 8127e31ba66Smrg/***************** 8137e31ba66Smrg * SetNotifyFd 8147e31ba66Smrg * Registers a callback to be invoked when the specified 8157e31ba66Smrg * file descriptor becomes readable. 8167e31ba66Smrg *****************/ 8177e31ba66Smrg 8187e31ba66SmrgBool 8197e31ba66SmrgSetNotifyFd(int fd, NotifyFdProcPtr notify, int mask, void *data) 82005b261ecSmrg{ 8217e31ba66Smrg struct notify_fd *n; 8227e31ba66Smrg 8237e31ba66Smrg n = ospoll_data(server_poll, fd); 8247e31ba66Smrg if (!n) { 8257e31ba66Smrg if (mask == 0) 8267e31ba66Smrg return TRUE; 8277e31ba66Smrg 8287e31ba66Smrg n = calloc(1, sizeof (struct notify_fd)); 8297e31ba66Smrg if (!n) 8307e31ba66Smrg return FALSE; 8317e31ba66Smrg ospoll_add(server_poll, fd, 8327e31ba66Smrg ospoll_trigger_level, 8337e31ba66Smrg HandleNotifyFd, 8347e31ba66Smrg n); 8357e31ba66Smrg } 8367e31ba66Smrg 8377e31ba66Smrg if (mask == 0) { 8387e31ba66Smrg ospoll_remove(server_poll, fd); 8397e31ba66Smrg free(n); 8407e31ba66Smrg } else { 8417e31ba66Smrg int listen = mask & ~n->mask; 8427e31ba66Smrg int mute = n->mask & ~mask; 8437e31ba66Smrg 8447e31ba66Smrg if (listen) 8457e31ba66Smrg ospoll_listen(server_poll, fd, listen); 8467e31ba66Smrg if (mute) 8477e31ba66Smrg ospoll_mute(server_poll, fd, mute); 8487e31ba66Smrg n->mask = mask; 8497e31ba66Smrg n->data = data; 8507e31ba66Smrg n->notify = notify; 8517e31ba66Smrg } 8527e31ba66Smrg 8537e31ba66Smrg return TRUE; 85405b261ecSmrg} 85505b261ecSmrg 85605b261ecSmrg/***************** 85705b261ecSmrg * OnlyListenToOneClient: 85805b261ecSmrg * Only accept requests from one client. Continue to handle new 85905b261ecSmrg * connections, but don't take any protocol requests from the new 86005b261ecSmrg * ones. Note that if GrabInProgress is set, EstablishNewConnections 86105b261ecSmrg * needs to put new clients into SavedAllSockets and SavedAllClients. 86205b261ecSmrg * Note also that there is no timeout for this in the protocol. 86305b261ecSmrg * This routine is "undone" by ListenToAllClients() 86405b261ecSmrg *****************/ 86505b261ecSmrg 8664642e01fSmrgint 86705b261ecSmrgOnlyListenToOneClient(ClientPtr client) 86805b261ecSmrg{ 8697e31ba66Smrg int rc; 8704642e01fSmrg 8714642e01fSmrg rc = XaceHook(XACE_SERVER_ACCESS, client, DixGrabAccess); 8724642e01fSmrg if (rc != Success) 873f7df2e56Smrg return rc; 874f7df2e56Smrg 875f7df2e56Smrg if (!GrabInProgress) { 876f7df2e56Smrg GrabInProgress = client->index; 8777e31ba66Smrg set_poll_clients(); 87805b261ecSmrg } 8797e31ba66Smrg 8804642e01fSmrg return rc; 88105b261ecSmrg} 88205b261ecSmrg 88305b261ecSmrg/**************** 88405b261ecSmrg * ListenToAllClients: 88505b261ecSmrg * Undoes OnlyListentToOneClient() 88605b261ecSmrg ****************/ 88705b261ecSmrg 88805b261ecSmrgvoid 88905b261ecSmrgListenToAllClients(void) 89005b261ecSmrg{ 891f7df2e56Smrg if (GrabInProgress) { 892f7df2e56Smrg GrabInProgress = 0; 8937e31ba66Smrg set_poll_clients(); 894f7df2e56Smrg } 89505b261ecSmrg} 89605b261ecSmrg 89705b261ecSmrg/**************** 89805b261ecSmrg * IgnoreClient 89905b261ecSmrg * Removes one client from input masks. 9005a112b11Smrg * Must have corresponding call to AttendClient. 90105b261ecSmrg ****************/ 90205b261ecSmrg 9036747b715Smrgvoid 904f7df2e56SmrgIgnoreClient(ClientPtr client) 90505b261ecSmrg{ 906f7df2e56Smrg OsCommPtr oc = (OsCommPtr) client->osPrivate; 90705b261ecSmrg 9086747b715Smrg client->ignoreCount++; 9096747b715Smrg if (client->ignoreCount > 1) 910f7df2e56Smrg return; 9116747b715Smrg 91205b261ecSmrg isItTimeToYield = TRUE; 9137e31ba66Smrg mark_client_not_ready(client); 9147e31ba66Smrg 9157e31ba66Smrg oc->flags |= OS_COMM_IGNORED; 9167e31ba66Smrg set_poll_client(client); 91705b261ecSmrg} 91805b261ecSmrg 91905b261ecSmrg/**************** 92005b261ecSmrg * AttendClient 92105b261ecSmrg * Adds one client back into the input masks. 92205b261ecSmrg ****************/ 92305b261ecSmrg 9246747b715Smrgvoid 925f7df2e56SmrgAttendClient(ClientPtr client) 92605b261ecSmrg{ 927f7df2e56Smrg OsCommPtr oc = (OsCommPtr) client->osPrivate; 9286747b715Smrg 9294e185dc0Smrg if (client->clientGone) { 9304e185dc0Smrg /* 9314e185dc0Smrg * client is gone, so any pending requests will be dropped and its 9324e185dc0Smrg * ignore count doesn't matter. 9334e185dc0Smrg */ 9344e185dc0Smrg return; 9354e185dc0Smrg } 9364e185dc0Smrg 9376747b715Smrg client->ignoreCount--; 9386747b715Smrg if (client->ignoreCount) 939f7df2e56Smrg return; 9406747b715Smrg 9417e31ba66Smrg oc->flags &= ~OS_COMM_IGNORED; 9427e31ba66Smrg set_poll_client(client); 9437e31ba66Smrg if (listen_to_client(client)) 9447e31ba66Smrg mark_client_ready(client); 945f7df2e56Smrg else { 9467e31ba66Smrg /* grab active, mark ready when grab goes away */ 9477e31ba66Smrg mark_client_saved_ready(client); 94805b261ecSmrg } 94905b261ecSmrg} 95005b261ecSmrg 95105b261ecSmrg/* make client impervious to grabs; assume only executing client calls this */ 95205b261ecSmrg 9534642e01fSmrgvoid 95405b261ecSmrgMakeClientGrabImpervious(ClientPtr client) 95505b261ecSmrg{ 956f7df2e56Smrg OsCommPtr oc = (OsCommPtr) client->osPrivate; 95705b261ecSmrg 9587e31ba66Smrg oc->flags |= OS_COMM_GRAB_IMPERVIOUS; 9597e31ba66Smrg set_poll_client(client); 96005b261ecSmrg 961f7df2e56Smrg if (ServerGrabCallback) { 962f7df2e56Smrg ServerGrabInfoRec grabinfo; 963f7df2e56Smrg 964f7df2e56Smrg grabinfo.client = client; 965f7df2e56Smrg grabinfo.grabstate = CLIENT_IMPERVIOUS; 966f7df2e56Smrg CallCallbacks(&ServerGrabCallback, &grabinfo); 96705b261ecSmrg } 96805b261ecSmrg} 96905b261ecSmrg 97005b261ecSmrg/* make client pervious to grabs; assume only executing client calls this */ 97105b261ecSmrg 9724642e01fSmrgvoid 97305b261ecSmrgMakeClientGrabPervious(ClientPtr client) 97405b261ecSmrg{ 975f7df2e56Smrg OsCommPtr oc = (OsCommPtr) client->osPrivate; 97605b261ecSmrg 9777e31ba66Smrg oc->flags &= ~OS_COMM_GRAB_IMPERVIOUS; 9787e31ba66Smrg set_poll_client(client); 9797e31ba66Smrg isItTimeToYield = TRUE; 98005b261ecSmrg 981f7df2e56Smrg if (ServerGrabCallback) { 982f7df2e56Smrg ServerGrabInfoRec grabinfo; 983f7df2e56Smrg 984f7df2e56Smrg grabinfo.client = client; 985f7df2e56Smrg grabinfo.grabstate = CLIENT_PERVIOUS; 986f7df2e56Smrg CallCallbacks(&ServerGrabCallback, &grabinfo); 98705b261ecSmrg } 98805b261ecSmrg} 98905b261ecSmrg 990f7df2e56Smrg/* Add a fd (from launchd or similar) to our listeners */ 991f7df2e56Smrgvoid 992f7df2e56SmrgListenOnOpenFD(int fd, int noxauth) 993f7df2e56Smrg{ 9944642e01fSmrg char port[256]; 9954642e01fSmrg XtransConnInfo ciptr; 9966747b715Smrg const char *display_env = getenv("DISPLAY"); 9974642e01fSmrg 998f7df2e56Smrg if (display_env && (strncmp(display_env, "/tmp/launch", 11) == 0)) { 9994642e01fSmrg /* Make the path the launchd socket if our DISPLAY is set right */ 10006747b715Smrg strcpy(port, display_env); 1001f7df2e56Smrg } 1002f7df2e56Smrg else { 10034642e01fSmrg /* Just some default so things don't break and die. */ 1004f7df2e56Smrg snprintf(port, sizeof(port), ":%d", atoi(display)); 10054642e01fSmrg } 10064642e01fSmrg 10074642e01fSmrg /* Make our XtransConnInfo 10084642e01fSmrg * TRANS_SOCKET_LOCAL_INDEX = 5 from Xtrans.c 10094642e01fSmrg */ 10104642e01fSmrg ciptr = _XSERVTransReopenCOTSServer(5, fd, port); 1011f7df2e56Smrg if (ciptr == NULL) { 1012f7df2e56Smrg ErrorF("Got NULL while trying to Reopen listen port.\n"); 10134642e01fSmrg return; 10144642e01fSmrg } 1015f7df2e56Smrg 1016f7df2e56Smrg if (noxauth) 10174642e01fSmrg ciptr->flags = ciptr->flags | TRANS_NOXAUTH; 10184642e01fSmrg 10194642e01fSmrg /* Allocate space to store it */ 1020f7df2e56Smrg ListenTransFds = 1021f7df2e56Smrg xnfreallocarray(ListenTransFds, ListenTransCount + 1, sizeof(int)); 1022f7df2e56Smrg ListenTransConns = 1023f7df2e56Smrg xnfreallocarray(ListenTransConns, ListenTransCount + 1, 1024f7df2e56Smrg sizeof(XtransConnInfo)); 1025f7df2e56Smrg 10264642e01fSmrg /* Store it */ 10274642e01fSmrg ListenTransConns[ListenTransCount] = ciptr; 10284642e01fSmrg ListenTransFds[ListenTransCount] = fd; 10294642e01fSmrg 10305a112b11Smrg SetNotifyFd(fd, EstablishNewConnections, X_NOTIFY_READ, NULL); 1031f7df2e56Smrg 10324642e01fSmrg /* Increment the count */ 10334642e01fSmrg ListenTransCount++; 10344642e01fSmrg} 10354642e01fSmrg 1036f7df2e56Smrg/* based on TRANS(SocketUNIXAccept) (XtransConnInfo ciptr, int *status) */ 1037f7df2e56SmrgBool 1038f7df2e56SmrgAddClientOnOpenFD(int fd) 1039f7df2e56Smrg{ 1040f7df2e56Smrg XtransConnInfo ciptr; 1041f7df2e56Smrg CARD32 connect_time; 1042f7df2e56Smrg char port[20]; 1043f7df2e56Smrg 1044f7df2e56Smrg snprintf(port, sizeof(port), ":%d", atoi(display)); 1045f7df2e56Smrg ciptr = _XSERVTransReopenCOTSServer(5, fd, port); 1046f7df2e56Smrg if (ciptr == NULL) 1047f7df2e56Smrg return FALSE; 1048f7df2e56Smrg 1049f7df2e56Smrg _XSERVTransSetOption(ciptr, TRANS_NONBLOCKING, 1); 1050f7df2e56Smrg ciptr->flags |= TRANS_NOXAUTH; 1051f7df2e56Smrg 1052f7df2e56Smrg connect_time = GetTimeInMillis(); 1053f7df2e56Smrg 1054f7df2e56Smrg if (!AllocNewConnection(ciptr, fd, connect_time)) { 1055f7df2e56Smrg ErrorConnMax(ciptr); 1056f7df2e56Smrg return FALSE; 1057f7df2e56Smrg } 1058f7df2e56Smrg 1059f7df2e56Smrg return TRUE; 1060f7df2e56Smrg} 10617e31ba66Smrg 10627e31ba66SmrgBool 10637e31ba66Smrglisten_to_client(ClientPtr client) 10647e31ba66Smrg{ 10657e31ba66Smrg OsCommPtr oc = (OsCommPtr) client->osPrivate; 10667e31ba66Smrg 10677e31ba66Smrg if (oc->flags & OS_COMM_IGNORED) 10687e31ba66Smrg return FALSE; 10697e31ba66Smrg 10707e31ba66Smrg if (!GrabInProgress) 10717e31ba66Smrg return TRUE; 10727e31ba66Smrg 10737e31ba66Smrg if (client->index == GrabInProgress) 10747e31ba66Smrg return TRUE; 10757e31ba66Smrg 10767e31ba66Smrg if (oc->flags & OS_COMM_GRAB_IMPERVIOUS) 10777e31ba66Smrg return TRUE; 10787e31ba66Smrg 10797e31ba66Smrg return FALSE; 10807e31ba66Smrg} 10817e31ba66Smrg 10827e31ba66Smrgstatic void 10837e31ba66Smrgset_poll_client(ClientPtr client) 10847e31ba66Smrg{ 10857e31ba66Smrg OsCommPtr oc = (OsCommPtr) client->osPrivate; 10867e31ba66Smrg 10877e31ba66Smrg if (oc->trans_conn) { 10887e31ba66Smrg if (listen_to_client(client)) 10897e31ba66Smrg ospoll_listen(server_poll, oc->trans_conn->fd, X_NOTIFY_READ); 10907e31ba66Smrg else 10917e31ba66Smrg ospoll_mute(server_poll, oc->trans_conn->fd, X_NOTIFY_READ); 10927e31ba66Smrg } 10937e31ba66Smrg} 10947e31ba66Smrg 10957e31ba66Smrgstatic void 10967e31ba66Smrgset_poll_clients(void) 10977e31ba66Smrg{ 10987e31ba66Smrg int i; 10997e31ba66Smrg 11007e31ba66Smrg for (i = 1; i < currentMaxClients; i++) { 11017e31ba66Smrg ClientPtr client = clients[i]; 11027e31ba66Smrg if (client && !client->clientGone) 11037e31ba66Smrg set_poll_client(client); 11047e31ba66Smrg } 11057e31ba66Smrg} 1106