New upstream version 3.5.99.27

This commit is contained in:
geos_one
2025-08-08 20:00:36 +02:00
commit bc8d10cc33
4267 changed files with 1757978 additions and 0 deletions

View File

@@ -0,0 +1,270 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
/* */
/* nx-X11, NX protocol compression and NX extensions to this software */
/* are copyright of the aforementioned persons and companies. */
/* */
/* Redistribution and use of the present software is allowed according */
/* to terms specified in the file LICENSE which comes in the source */
/* distribution. */
/* */
/* All rights reserved. */
/* */
/* NOTE: This software has received contributions from various other */
/* contributors, only the core maintainers and supporters are listed as */
/* copyright holders. Please contact us, if you feel you should be listed */
/* as copyright holder, as well. */
/* */
/**************************************************************************/
#include <Server.tmpl>
NULL =
/*
* If you have any extra files to be put into the library, define them here.
*/
ZONEID_DEFINES = -UHAVE_GETZONEID
#if NXLibraries
NX_INCLUDES = -I../../../../nxcomp
NX_DEFINES = -DNX_TRANS_SOCKET \
-DNX_TRANS_AUTH \
-DNX_TRANS_FOPEN \
-DNX_TRANS_SLEEP \
-DNX_TRANS_EXIT \
-DNX_TRANS_WAKEUP \
-DNXAGENT_SERVER \
$(NULL)
# -DNX_TRANS_WARN \
# -DNX_TRANS_INFO \
# -DNX_TRANS_TEST \
# -DNX_TRANS_DEBUG \
#endif
/*
* do not modify the following two definitions
*/
#ifndef OtherSources
#define OtherSources
#endif
#ifndef OtherObjects
#define OtherObjects
#endif
#if HasXdmAuth
XDMAUTHDEFS = -DHASXDMAUTH
XDMAUTHOBJS = xdmauth.o
XDMAUTHSRCS = xdmauth.c
#else
XDMAUTHDEFS =
XDMAUTHOBJS =
XDMAUTHSCRS =
#endif
TIRPC_INCLUDES =
#if HasSecureRPC
RPCDEFS = -DSECURE_RPC
RPCOBJS = rpcauth.o
RPCSRCS = rpcauth.c
#if UseTIRPC
TIRPC_INCLUDES = $$(pkg-config --cflags-only-I 'libtirpc')
#endif
#else
RPCDEFS =
RPCOBJS =
RPCSRCS =
#endif
#if HasBSD44Sockets
SOCK_DEFINES = -DBSD44SOCKETS
#endif
#if HasGetIfAddrs
IFADDRS_DEFINES = -DHAS_GETIFADDRS
#endif
#if !defined(DDXOsColor)
COLOR_SRCS=oscolor.c
COLOR_OBJS=oscolor.o
#endif
#if !HasSnprintf
SNPRINTF_SRCS = snprintf.c
SNPRINTF_OBJS = snprintf.o
#endif
#if !HasStrlcat
STRLCAT_SRCS = strlcat.c strlcpy.c
STRLCAT_OBJS = strlcat.o strlcpy.o
#endif
#if !HasReallocarray
REALLOCARRAY_SRCS = reallocarray.c
REALLOCARRAY_OBJS = reallocarray.o
#endif
#if HasGetpeerucred
GETPEER_DEFINES = -DHAS_GETPEERUCRED
#else
# if HasGetpeereid
GETPEER_DEFINES = -DHAS_GETPEEREID
# endif
#endif
#if !HasTimingsafeMemcmp
TMEMCMP_SRCS = timingsafe_memcmp.c
TMEMCMP_OBJS = timingsafe_memcmp.o
#endif
BOOTSTRAPCFLAGS =
SRCS = WaitFor.c \
access.c \
client.c \
connection.c \
io.c \
$(COLOR_SRCS) \
osinit.c \
utils.c \
log.c \
auth.c \
mitauth.c \
secauth.c \
$(XDMAUTHSRCS) \
$(RPCSRCS) \
xdmcp.c \
OtherSources \
xstrans.c \
$(SNPRINTF_SRCS) \
$(STRLCAT_SRCS) \
$(REALLOCARRAY_SRCS) \
xprintf.c \
$(TMEMCMP_SRCS) \
$(NULL)
OBJS = WaitFor.o \
access.o \
client.o \
connection.o \
io.o \
$(COLOR_OBJS) \
osinit.o \
utils.o \
log.o \
auth.o \
mitauth.o \
secauth.o \
$(XDMAUTHOBJS) \
$(RPCOBJS) \
xdmcp.o \
OtherObjects \
xstrans.o \
$(SNPRINTF_OBJS) \
$(STRLCAT_OBJS) \
$(REALLOCARRAY_OBJS) \
xprintf.o \
$(TMEMCMP_OBJS) \
$(NULL)
#if UseMemLeak
MEM_DEFINES = -DMEMBUG
#endif
ADM_DEFINES = -DADMPATH=\"$(ADMDIR)/X\%smsgs\"
XDMCP_DEFINES = ServerXdmcpDefines
ERROR_DEFINES = ServerErrorDefines
#if HasPam && HasPamMisc
PAM_DEFINES = -DUSE_PAM
#endif
XTRANS_DEFINES = -DXTRANS_SEND_FDS=0
DEFINES = $(CONNECTION_FLAGS) \
$(MEM_DEFINES) \
$(XDMAUTHDEFS) \
$(RPCDEFS) \
$(SIGNAL_DEFINES) \
$(OS_DEFINES) \
$(GETPEER_DEFINES) \
$(RANDOM_DEFINES) \
$(BUGMSG) \
$(XTRANS_FAILDEFINES) \
$(XTRANS_DEFINES) \
$(NX_DEFINES) \
$(NULL)
INCLUDES = -I. \
-I../include \
-I$(XINCLUDESRC) \
-I$(EXTINCSRC) \
-I$(SERVERSRC)/Xext \
-I$(SERVERSRC)/render \
-I$(TOP)/lib/Xau \
$(NX_INCLUDES) \
`pkg-config --cflags-only-I pixman-1` \
$(TIRPC_INCLUDES) \
$(NULL)
DEPEND_DEFINES = $(XDMCP_DEFINES) \
$(EXT_DEFINES) \
$(TRANS_INCLUDES) \
$(CONNECTION_FLAGS) \
$(GETPEER_DEFINES) \
DependDefines \
$(NULL)
LINTLIBS = ../dix/llib-ldix.ln
#ifdef NEED_ALLOCA_FROM_LIBPW
PWLIB = /lib/libPW.a
#endif /* NEED_ALLOCA_FROM_LIBPW */
NormalLibraryObjectRule()
NormalLibraryTarget(os,$(OBJS))
LintLibraryTarget(os,$(SRCS))
NormalLintTarget($(SRCS))
#ifdef NEED_ALLOCA_FROM_LIBPW
XCOMM
XCOMM And this one is to get the version of alloca that lives in /lib/libPW.a
XCOMM without getting all of the rest of the stuff in there.
XCOMM
alloca.o: $(PWLIB)
rm -f alloca.o
ar x $(PWLIB) alloca.o
#endif /* NEED_ALLOCA_FROM_LIBPW */
SpecialCObjectRule(access,$(ICONFIGFILES),$(XDMCP_DEFINES) $(SOCK_DEFINES) $(IFADDRS_DEFINES) $(ZONEID_DEFINES))
SpecialCObjectRule(auth,$(ICONFIGFILES),$(XDMCP_DEFINES))
SpecialCObjectRule(xdmauth,$(ICONFIGFILES),$(XDMCP_DEFINES))
SpecialCObjectRule(xdmcp,$(ICONFIGFILES),$(SOCK_DEFINES) $(XDMCP_DEFINES))
SpecialCObjectRule(connection,$(ICONFIGFILES),$(SOCK_DEFINES) $(XDMCP_DEFINES))
SpecialCObjectRule(osinit,$(ICONFIGFILES),$(ADM_DEFINES))
SpecialCObjectRule(WaitFor,$(ICONFIGFILES),$(EXT_DEFINES))
SpecialCObjectRule(io,$(ICONFIGFILES),$(EXT_DEFINES))
SpecialCObjectRule(utils,$(ICONFIGFILES),$(XDMCP_DEFINES) $(EXT_DEFINES) $(ERROR_DEFINES) $(PAM_DEFINES))
#if defined(SparcArchitecture) && HasGcc && !HasGcc2
oscolor.o: oscolor.c $(ICONFIGFILES)
$(RM) $@
cc -c $(CDEBUGFLAGS) $(ALLDEFINES) $*.c
#endif
#if !HasSnprintf
LinkSourceFile(snprintf.c,$(LIBSRC)/misc)
#endif
DependTarget()

View File

@@ -0,0 +1,776 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
/* */
/* nx-X11, NX protocol compression and NX extensions to this software */
/* are copyright of the aforementioned persons and companies. */
/* */
/* Redistribution and use of the present software is allowed according */
/* to terms specified in the file LICENSE which comes in the source */
/* distribution. */
/* */
/* All rights reserved. */
/* */
/* NOTE: This software has received contributions from various other */
/* contributors, only the core maintainers and supporters are listed as */
/* copyright holders. Please contact us, if you feel you should be listed */
/* as copyright holder, as well. */
/* */
/**************************************************************************/
/***********************************************************
Copyright 1987, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Digital not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.
******************************************************************/
/*****************************************************************
* OS Dependent input routines:
*
* WaitForSomething
* TimerForce, TimerSet, TimerCheck, TimerFree
*
*****************************************************************/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <nx-X11/Xos.h> /* for strings, fcntl, time */
#include <errno.h>
#include <stdio.h>
#include <nx-X11/X.h>
#include "misc.h"
#include "osdep.h"
#include <nx-X11/Xpoll.h>
#include "dixstruct.h"
#include "opaque.h"
#ifdef DPMSExtension
#include "dpmsproc.h"
#endif
/*
* unset defines without NX_TRANS_SOCKET. This allows for shorter
* ifdefs below
*/
#ifndef NX_TRANS_SOCKET
#ifdef NX_TRANS_DEBUG
#undef NX_TRANS_DEBUG
#endif
#ifdef NX_TRANS_WAKEUP
#undef NX_TRANS_WAKEUP
#endif
#endif
#ifdef NX_TRANS_WAKEUP
static unsigned long startTimeInMillis;
#endif
/* This is just a fallback to errno to hide the differences between unix and
Windows in the code */
#define GetErrno() errno
/* like ffs, but uses fd_mask instead of int as argument, so it works
when fd_mask is longer than an int, such as common 64-bit platforms */
/* modifications by raphael */
int
mffs(fd_mask mask)
{
int i;
if (!mask) return 0;
i = 1;
while (!(mask & 1))
{
i++;
mask >>= 1;
}
return i;
}
#ifdef DPMSExtension
#define DPMS_SERVER
#include <nx-X11/extensions/dpms.h>
#endif
struct _OsTimerRec {
OsTimerPtr next;
CARD32 expires;
OsTimerCallback callback;
void * arg;
};
static void DoTimer(OsTimerPtr timer, CARD32 now, OsTimerPtr *prev);
static OsTimerPtr timers = NULL;
/*****************
* WaitForSomething:
* Make the server suspend until there is
* 1. data from clients or
* 2. input events available or
* 3. ddx notices something of interest (graphics
* queue ready, etc.) or
* 4. clients that have buffered replies/events are ready
*
* If the time between INPUT events is
* greater than ScreenSaverTime, the display is turned off (or
* saved, depending on the hardware). So, WaitForSomething()
* has to handle this also (that's why the select() has a timeout.
* For more info on ClientsWithInput, see ReadRequestFromClient().
* pClientsReady is an array to store ready client->index values into.
*****************/
int
WaitForSomething(int *pClientsReady)
{
int i;
struct timeval waittime, *wt;
INT32 timeout = 0;
fd_set clientsReadable;
fd_set clientsWritable;
int curclient;
int selecterr;
int nready;
CARD32 now = 0;
Bool someReady = FALSE;
Bool someNotifyWriteReady = FALSE;
#ifdef NX_TRANS_DEBUG
fprintf(stderr, "WaitForSomething: Got called.\n");
#endif
FD_ZERO(&clientsReadable);
#ifdef NX_TRANS_WAKEUP
startTimeInMillis = GetTimeInMillis();
#endif
/* We need a while loop here to handle
crashed connections and the screen saver timeout */
while (1)
{
/* deal with any blocked jobs */
if (workQueue)
ProcessWorkQueue();
if (XFD_ANYSET (&ClientsWithInput))
{
someReady = TRUE;
waittime.tv_sec = 0;
waittime.tv_usec = 0;
wt = &waittime;
}
if (someReady)
{
XFD_COPYSET(&AllSockets, &LastSelectMask);
XFD_UNSET(&LastSelectMask, &ClientsWithInput);
}
else
{
wt = NULL;
if (timers)
{
now = GetTimeInMillis();
timeout = timers->expires - now;
if (timeout < 0)
timeout = 0;
waittime.tv_sec = timeout / MILLI_PER_SECOND;
waittime.tv_usec = (timeout % MILLI_PER_SECOND) *
(1000000 / MILLI_PER_SECOND);
wt = &waittime;
}
XFD_COPYSET(&AllSockets, &LastSelectMask);
}
SmartScheduleStopTimer ();
BlockHandler((void *)&wt, (void *)&LastSelectMask);
if (NewOutputPending)
FlushAllOutput();
#ifdef NX_TRANS_WAKEUP
/*
* If caller has marked the first element of pClientsReady[],
* bail out of select after the timeout given in the second
* element. We need this to let the NX agent remove the splash
* screen when the timeout is expired even if there's no
* client. Otherwise WaitForSomething would block. A better
* option would be to use the existing screen-saver timeout
* but it can be modified by clients, so we would need a
* special handling. This hack is trivial and keeps
* WaitForSomething() backward compatible with the existing
* servers.
*/
if (pClientsReady[0] == -1)
{
unsigned long timeoutInMillis;
#ifdef NX_TRANS_DEBUG
fprintf(stderr, "WaitForSomething: pClientsReady[0] is [%d], pClientsReady[1] is [%d].\n",
pClientsReady[0], pClientsReady[1]);
#endif
timeoutInMillis = GetTimeInMillis();
if (timeoutInMillis - startTimeInMillis >= pClientsReady[1])
{
#ifdef NX_TRANS_DEBUG
fprintf(stderr, "WaitForSomething: Returning 0 because of wakeup timeout.\n");
#endif
return 0;
}
timeoutInMillis = pClientsReady[1] - (timeoutInMillis - startTimeInMillis);
#ifdef NX_TRANS_DEBUG
fprintf(stderr, "WaitForSomething: Milliseconds to next wakeup are %ld.\n",
timeoutInMillis);
#endif
if (wt == NULL || (wt -> tv_sec * MILLI_PER_SECOND +
wt -> tv_usec / MILLI_PER_SECOND) > timeoutInMillis)
{
if ((waittime.tv_sec * MILLI_PER_SECOND +
waittime.tv_usec / MILLI_PER_SECOND) > timeoutInMillis)
{
waittime.tv_sec = timeoutInMillis / MILLI_PER_SECOND;
waittime.tv_usec = (timeoutInMillis * MILLI_PER_SECOND) %
(MILLI_PER_SECOND * 1000);
wt = &waittime;
}
#ifdef NX_TRANS_DEBUG
fprintf(stderr, "WaitForSomething: Next wakeup timeout set to %ld milliseconds.\n",
(waittime.tv_sec * MILLI_PER_SECOND) +
(waittime.tv_usec / MILLI_PER_SECOND));
#endif
}
#ifdef NX_TRANS_DEBUG
else
{
fprintf(stderr, "WaitForSomething: Using existing timeout of %ld milliseconds.\n",
(waittime.tv_sec * MILLI_PER_SECOND) +
(waittime.tv_usec / MILLI_PER_SECOND));
}
#endif
}
#endif /* defined(NX_TRANS_WAKEUP) */
/* keep this check close to select() call to minimize race */
#ifdef NX_TRANS_DEBUG
if (dispatchException)
fprintf(stderr, "WaitForSomething: Value of dispatchException is true. Set i = -1.\n");
#endif
if (dispatchException)
i = -1;
else if (AnyWritesPending)
{
#ifdef NX_TRANS_DEBUG
if (wt == NULL)
{
fprintf(stderr, "WaitForSomething: Executing select with LastSelectMask and "
"clientsWritable and null timeout.\n");
}
else
{
fprintf(stderr, "WaitForSomething: Executing select with LastSelectMask, "
"clientsWritable, %ld secs and %ld usecs.\n",
wt -> tv_sec, wt -> tv_usec);
}
#endif
XFD_COPYSET(&ClientsWriteBlocked, &LastSelectWriteMask);
XFD_ORSET(&LastSelectWriteMask, &NotifyWriteFds, &LastSelectWriteMask);
i = Select(MaxClients, &LastSelectMask, &LastSelectWriteMask, NULL, wt);
}
else
{
#ifdef NX_TRANS_DEBUG
if (wt == NULL)
{
fprintf(stderr, "WaitForSomething: Executing select with LastSelectMask and null timeout.\n");
}
else
{
fprintf(stderr, "WaitForSomething: Executing select with LastSelectMask, %ld secs and %ld usecs.\n",
wt -> tv_sec, wt -> tv_usec);
}
#endif
i = Select (MaxClients, &LastSelectMask, NULL, NULL, wt);
}
#ifdef NX_TRANS_DEBUG
fprintf(stderr, "WaitForSomething: Bailed out with i = [%d] and errno = [%d].\n", i, errno);
if (i < 0)
{
fprintf(stderr, "WaitForSomething: Error is [%s].\n", strerror(errno));
}
#endif
selecterr = GetErrno();
WakeupHandler(i, (void *)&LastSelectMask);
SmartScheduleStartTimer ();
if (i <= 0) /* An error or timeout occurred */
{
#ifdef NX_TRANS_DEBUG
if (dispatchException)
{
fprintf(stderr, "WaitForSomething: Returning 0 because of (dispatchException).\n");
}
#endif
if (dispatchException)
return 0;
if (i < 0)
{
if (selecterr == EBADF) /* Some client disconnected */
{
CheckConnections ();
#ifdef NX_TRANS_DEBUG
if (! XFD_ANYSET (&AllClients))
{
fprintf(stderr, "WaitForSomething: Returning 0 because of (! XFD_ANYSET (&AllClients)).\n");
}
#endif
if (! XFD_ANYSET (&AllClients))
return 0;
}
else if (selecterr == EINVAL)
{
FatalError("WaitForSomething(): select: errno=%d\n",
selecterr);
}
else if (selecterr != EINTR)
{
ErrorF("WaitForSomething(): select: errno=%d\n",
selecterr);
}
}
else if (someReady)
{
/*
* If no-one else is home, bail quickly
*/
XFD_COPYSET(&ClientsWithInput, &LastSelectMask);
XFD_COPYSET(&ClientsWithInput, &clientsReadable);
break;
}
#ifdef NX_TRANS_DEBUG
if (*checkForInput[0] != *checkForInput[1])
{
fprintf(stderr, "WaitForSomething: Returning 0 because of (*checkForInput[0] != *checkForInput[1]).\n");
}
#endif
if (*checkForInput[0] != *checkForInput[1])
return 0;
if (timers)
{
int expired = 0;
now = GetTimeInMillis();
if ((int) (timers->expires - now) <= 0)
expired = 1;
while (timers && (int) (timers->expires - now) <= 0)
DoTimer(timers, now, &timers);
if (expired)
return 0;
}
}
else
{
fd_set tmp_set;
if (*checkForInput[0] == *checkForInput[1]) {
if (timers)
{
int expired = 0;
now = GetTimeInMillis();
if ((int) (timers->expires - now) <= 0)
expired = 1;
while (timers && (int) (timers->expires - now) <= 0)
DoTimer(timers, now, &timers);
if (expired)
return 0;
}
}
if (someReady)
XFD_ORSET(&LastSelectMask, &ClientsWithInput, &LastSelectMask);
if (AnyWritesPending) {
XFD_ANDSET(&clientsWritable, &LastSelectWriteMask, &ClientsWriteBlocked);
if (XFD_ANYSET(&clientsWritable)) {
NewOutputPending = TRUE;
XFD_ORSET(&OutputPending, &clientsWritable, &OutputPending);
XFD_UNSET(&ClientsWriteBlocked, &clientsWritable);
if (!XFD_ANYSET(&ClientsWriteBlocked) && NumNotifyWriteFd == 0)
AnyWritesPending = FALSE;
}
if (NumNotifyWriteFd != 0) {
XFD_ANDSET(&tmp_set, &LastSelectWriteMask, &NotifyWriteFds);
if (XFD_ANYSET(&tmp_set))
someNotifyWriteReady = TRUE;
}
}
XFD_ANDSET(&clientsReadable, &LastSelectMask, &AllClients);
XFD_ANDSET(&tmp_set, &LastSelectMask, &NotifyReadFds);
if (XFD_ANYSET(&tmp_set) || someNotifyWriteReady)
HandleNotifyFds();
if (XFD_ANYSET (&clientsReadable))
break;
}
}
nready = 0;
if (XFD_ANYSET (&clientsReadable))
{
for (i=0; i<howmany(XFD_SETSIZE, NFDBITS); i++)
{
while (clientsReadable.fds_bits[i])
{
int client_index;
curclient = mffs (clientsReadable.fds_bits[i]) - 1;
client_index = /* raphael: modified */
ConnectionTranslation[curclient + (i * (sizeof(fd_mask) * 8))];
pClientsReady[nready++] = client_index;
clientsReadable.fds_bits[i] &= ~(((fd_mask)1L) << curclient);
}
}
}
#ifdef NX_TRANS_DEBUG
fprintf(stderr, "WaitForSomething: Returning nready.\n");
#endif
return nready;
}
#if 0
/*
* This is not always a macro.
*/
ANYSET(FdMask *src)
{
int i;
for (i=0; i<mskcnt; i++)
if (src[ i ])
return (TRUE);
return (FALSE);
}
#endif
static void
DoTimer(OsTimerPtr timer, CARD32 now, OsTimerPtr *prev)
{
CARD32 newTime;
*prev = timer->next;
timer->next = NULL;
newTime = (*timer->callback)(timer, now, timer->arg);
if (newTime)
TimerSet(timer, 0, newTime, timer->callback, timer->arg);
}
OsTimerPtr
TimerSet(OsTimerPtr timer, int flags, CARD32 millis,
OsTimerCallback func, void * arg)
{
register OsTimerPtr *prev;
CARD32 now = GetTimeInMillis();
if (!timer)
{
timer = (OsTimerPtr)malloc(sizeof(struct _OsTimerRec));
if (!timer)
return NULL;
}
else
{
for (prev = &timers; *prev; prev = &(*prev)->next)
{
if (*prev == timer)
{
*prev = timer->next;
if (flags & TimerForceOld)
(void)(*timer->callback)(timer, now, timer->arg);
break;
}
}
}
if (!millis)
return timer;
if (!(flags & TimerAbsolute))
millis += now;
timer->expires = millis;
timer->callback = func;
timer->arg = arg;
if ((int) (millis - now) <= 0)
{
timer->next = NULL;
millis = (*timer->callback)(timer, now, timer->arg);
if (!millis)
return timer;
}
for (prev = &timers;
*prev && (int) ((*prev)->expires - millis) <= 0;
prev = &(*prev)->next)
;
timer->next = *prev;
*prev = timer;
return timer;
}
Bool
TimerForce(OsTimerPtr timer)
{
OsTimerPtr *prev;
for (prev = &timers; *prev; prev = &(*prev)->next)
{
if (*prev == timer)
{
DoTimer(timer, GetTimeInMillis(), prev);
return TRUE;
}
}
return FALSE;
}
void
TimerCancel(OsTimerPtr timer)
{
OsTimerPtr *prev;
if (!timer)
return;
for (prev = &timers; *prev; prev = &(*prev)->next)
{
if (*prev == timer)
{
*prev = timer->next;
break;
}
}
}
void
TimerFree(OsTimerPtr timer)
{
if (!timer)
return;
TimerCancel(timer);
free(timer);
}
void
TimerCheck(void)
{
CARD32 now = GetTimeInMillis();
while (timers && (int) (timers->expires - now) <= 0)
DoTimer(timers, now, &timers);
}
void
TimerInit(void)
{
OsTimerPtr timer;
while ((timer = timers))
{
timers = timer->next;
free(timer);
}
}
#ifdef DPMSExtension
#define DPMS_CHECK_MODE(mode,time)\
if (time > 0 && DPMSPowerLevel < mode && timeout >= time)\
DPMSSet(mode);
#define DPMS_CHECK_TIMEOUT(time)\
if (time > 0 && (time - timeout) > 0)\
return time - timeout;
static CARD32
NextDPMSTimeout(INT32 timeout)
{
/*
* Return the amount of time remaining until we should set
* the next power level. Fallthroughs are intentional.
*/
switch (DPMSPowerLevel)
{
case DPMSModeOn:
DPMS_CHECK_TIMEOUT(DPMSStandbyTime)
case DPMSModeStandby:
DPMS_CHECK_TIMEOUT(DPMSSuspendTime)
case DPMSModeSuspend:
DPMS_CHECK_TIMEOUT(DPMSOffTime)
default: /* DPMSModeOff */
return 0;
}
}
#endif /* DPMSExtension */
static CARD32
ScreenSaverTimeoutExpire(OsTimerPtr timer,CARD32 now,void * arg)
{
INT32 timeout = now - lastDeviceEventTime.milliseconds;
CARD32 nextTimeout = 0;
#ifdef DPMSExtension
/*
* Check each mode lowest to highest, since a lower mode can
* have the same timeout as a higher one.
*/
if (DPMSEnabled)
{
DPMS_CHECK_MODE(DPMSModeOff, DPMSOffTime)
DPMS_CHECK_MODE(DPMSModeSuspend, DPMSSuspendTime)
DPMS_CHECK_MODE(DPMSModeStandby, DPMSStandbyTime)
nextTimeout = NextDPMSTimeout(timeout);
}
/*
* Only do the screensaver checks if we're not in a DPMS
* power saving mode
*/
if (DPMSPowerLevel != DPMSModeOn)
return nextTimeout;
#endif /* DPMSExtension */
if (!ScreenSaverTime)
return nextTimeout;
if (timeout < ScreenSaverTime)
{
return nextTimeout > 0 ?
min(ScreenSaverTime - timeout, nextTimeout) :
ScreenSaverTime - timeout;
}
ResetOsBuffers(); /* not ideal, but better than nothing */
SaveScreens(SCREEN_SAVER_ON, ScreenSaverActive);
if (ScreenSaverInterval > 0)
{
nextTimeout = nextTimeout > 0 ?
min(ScreenSaverInterval, nextTimeout) :
ScreenSaverInterval;
}
return nextTimeout;
}
static OsTimerPtr ScreenSaverTimer = NULL;
void
FreeScreenSaverTimer(void)
{
if (ScreenSaverTimer) {
TimerFree(ScreenSaverTimer);
ScreenSaverTimer = NULL;
}
}
void
SetScreenSaverTimer(void)
{
CARD32 timeout = 0;
#ifdef DPMSExtension
if (DPMSEnabled)
{
/*
* A higher DPMS level has a timeout that's either less
* than or equal to that of a lower DPMS level.
*/
if (DPMSStandbyTime > 0)
timeout = DPMSStandbyTime;
else if (DPMSSuspendTime > 0)
timeout = DPMSSuspendTime;
else if (DPMSOffTime > 0)
timeout = DPMSOffTime;
}
#endif
if (ScreenSaverTime > 0)
{
timeout = timeout > 0 ?
min(ScreenSaverTime, timeout) :
ScreenSaverTime;
}
#ifdef SCREENSAVER
if (timeout && !screenSaverSuspended) {
#else
if (timeout) {
#endif
ScreenSaverTimer = TimerSet(ScreenSaverTimer, 0, timeout,
ScreenSaverTimeoutExpire, NULL);
}
else if (ScreenSaverTimer) {
FreeScreenSaverTimer();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,599 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
/* */
/* nx-X11, NX protocol compression and NX extensions to this software */
/* are copyright of the aforementioned persons and companies. */
/* */
/* Redistribution and use of the present software is allowed according */
/* to terms specified in the file LICENSE which comes in the source */
/* distribution. */
/* */
/* All rights reserved. */
/* */
/* NOTE: This software has received contributions from various other */
/* contributors, only the core maintainers and supporters are listed as */
/* copyright holders. Please contact us, if you feel you should be listed */
/* as copyright holder, as well. */
/* */
/**************************************************************************/
/*
Copyright 1988, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from The Open Group.
*/
/*
* authorization hooks for the server
* Author: Keith Packard, MIT X Consortium
*/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
# include <nx-X11/X.h>
# include <nx-X11/Xauth.h>
# include "misc.h"
# include "osdep.h"
# include "dixstruct.h"
# include <sys/types.h>
# include <sys/stat.h>
#ifdef XCSECURITY
#define _SECURITY_SERVER
# include <nx-X11/extensions/security.h>
#endif
struct protocol {
unsigned short name_length;
char *name;
AuthAddCFunc Add; /* new authorization data */
AuthCheckFunc Check; /* verify client authorization data */
AuthRstCFunc Reset; /* delete all authorization data entries */
AuthToIDFunc ToID; /* convert cookie to ID */
AuthFromIDFunc FromID; /* convert ID to cookie */
AuthRemCFunc Remove; /* remove a specific cookie */
#ifdef XCSECURITY
AuthGenCFunc Generate;
#endif
};
static struct protocol protocols[] = {
{ (unsigned short) 18, "MIT-MAGIC-COOKIE-1",
MitAddCookie, MitCheckCookie, MitResetCookie,
MitToID, MitFromID, MitRemoveCookie,
#ifdef XCSECURITY
MitGenerateCookie
#endif
},
#ifdef HASXDMAUTH
{ (unsigned short) 19, "XDM-AUTHORIZATION-1",
XdmAddCookie, XdmCheckCookie, XdmResetCookie,
XdmToID, XdmFromID, XdmRemoveCookie,
#ifdef XCSECURITY
NULL
#endif
},
#endif
#ifdef SECURE_RPC
{ (unsigned short) 9, "SUN-DES-1",
SecureRPCAdd, SecureRPCCheck, SecureRPCReset,
SecureRPCToID, SecureRPCFromID,SecureRPCRemove,
#ifdef XCSECURITY
NULL
#endif
},
#endif
#ifdef XCSECURITY
{ (unsigned short) XSecurityAuthorizationNameLen,
XSecurityAuthorizationName,
NULL, AuthSecurityCheck, NULL,
NULL, NULL, NULL,
NULL
},
#endif
};
# define NUM_AUTHORIZATION (sizeof (protocols) /\
sizeof (struct protocol))
/*
* Initialize all classes of authorization by reading the
* specified authorization file
*/
static char *authorization_file = (char *)NULL;
static Bool ShouldLoadAuth = TRUE;
void
InitAuthorization (char *file_name)
{
#ifdef __sun
char * envBuffer;
#endif
authorization_file = file_name;
#ifdef NX_TRANS_AUTH
#ifdef NX_TRANS_TEST
fprintf(stderr, "InitAuthorization: Going to propagate auth file '%s' to the environment.\n",
authorization_file);
#endif
#ifdef __sun
envBuffer = malloc(15+strlen(authorization_file));
sprintf(envBuffer,"NX_XAUTHORITY=%s",authorization_file);
putenv(envBuffer);
#else
setenv("NX_XAUTHORITY", authorization_file, 1);
#endif
#endif
}
static int
LoadAuthorization (void)
{
FILE *f;
Xauth *auth;
int i;
int count = 0;
ShouldLoadAuth = FALSE;
if (!authorization_file)
return 0;
#ifdef NX_TRANS_AUTH
/*
* We think that the way LoadAuthorization() is working is wrong.
* It doesn't reset the list of stored authorizations before reading
* the new cookies. Our take is that if a new auth file is to be
* read, the only cookies that are to be accepted are those that are
* in the new file, not those in the file -plus- those that have
* been in the file in the past. Furthermore, if the list can't be
* read or it is empty, it should assume that it ignores which co-
* okies are valid and thus it should disable any access. Your mile-
* age can vary. A less draconian approach could be to leave the old
* cookies if the file can't be read and remove them only if the
* file is empty.
*
* Adding the cookies without removing the old values for the same
* protocol has an important implication. If an user shares the co-
* okie with somebody and later wants to revoke the access to the
* display, changing the cookie will not work. This is especially
* important with NX. For security reasons, after reconnecting the
* session to a different display, it is advisable to generate a
* new set of cookies, but doing that it is useless with the current
* code, as the old cookies are going to be still accepted. On the
* same topic, consider that once an user has got access to the X
* server, he/she can freely enable host authentication from any
* host, so the safe behaviour should be to reset the host based
* authenthication at least at reconnection, and keep as valid only
* the cookies that are actually in the file. This behaviour would
* surely break many applications, among them a SSH connection run
* inside a NX session, as ssh -X reads the cookie for the display
* only at session startup and does not read the cookies again
* when the auth file is changed.
*
* Another bug (or feature, depending on how you want to consider
* it) is that if the authority file contains entries for different
* displays (as it is the norm when the authority file is the default
* .Xauthority in the user's home), the server will match -any- of
* the cookies, even cookies that are not for its own display. This
* means that you have be careful when passing an authority file to
* nxagent or Xnest and maybe keep separate files for letting nxagent
* find the cookie to be used to connect to the remote display and
* for letting it find what cookies to accept. If the file is the
* same, clients will be able to connect to nxagent with both the
* cookies.
*/
#ifdef NX_TRANS_AUTH_RESET
#ifdef NX_TRANS_TEST
fprintf(stderr, "LoadAuthorization: Resetting authorization info.\n");
#endif
for (i = 0; i < NUM_AUTHORIZATION; i++) {
if (protocols[i].Reset) {
(*protocols[i].Reset) ();
}
}
#endif
#endif /* #ifdef NX_TRANS_AUTH */
f = Fopen (authorization_file, "r");
if (!f)
return -1;
while ((auth = XauReadAuth (f)) != 0) {
for (i = 0; i < NUM_AUTHORIZATION; i++) {
if (protocols[i].name_length == auth->name_length &&
memcmp (protocols[i].name, auth->name, (int) auth->name_length) == 0 &&
protocols[i].Add)
{
#ifdef NX_TRANS_AUTH
#ifdef NX_TRANS_TEST
fprintf(stderr, "LoadAuthorization: Adding new record from file [%s].\n",
authorization_file);
#endif
#endif
++count;
(*protocols[i].Add) (auth->data_length, auth->data,
FakeClientID(0));
}
}
XauDisposeAuth (auth);
}
#ifdef NX_TRANS_AUTH
if (count == 0)
{
fprintf(stderr, "Warning: No authorization record could be read from file '%s'.\n",
authorization_file);
fprintf(stderr, "Warning: Please, create a valid authorization cookie using the command\n"
"Warning: 'xauth -f %s add <display> MIT-MAGIC-COOKIE-1 <cookie>'.\n",
authorization_file);
}
#endif
#ifdef NX_TRANS_AUTH
if (Fclose (f) != 0)
{
/*
* If the Fclose() fails, for example because of a signal,
* it's advisable to return the number of protocols read,
* if any, or otherwise the server would believe that no
* cookie is valid and eventually fall back to host based
* authentication. Note anyway that the new code in Check-
* Authorization() doesn't care the return value and gives
* a chance to the function to check the file at the next
* connection.
*/
if (count > 0)
{
return count;
}
else
{
return -1;
}
}
#else
Fclose (f);
#endif
return count;
}
#ifdef XDMCP
/*
* XdmcpInit calls this function to discover all authorization
* schemes supported by the display
*/
void
RegisterAuthorizations (void)
{
int i;
for (i = 0; i < NUM_AUTHORIZATION; i++)
XdmcpRegisterAuthorization (protocols[i].name,
(int)protocols[i].name_length);
}
#endif
XID
CheckAuthorization (
unsigned int name_length,
char *name,
unsigned int data_length,
char *data,
ClientPtr client,
char **reason) /* failure message. NULL for default msg */
{
int i;
struct stat buf;
static time_t lastmod = 0;
#ifndef NX_TRANS_AUTH
static Bool loaded = FALSE;
#endif
if (!authorization_file || stat(authorization_file, &buf))
{
if (lastmod != 0) {
lastmod = 0;
ShouldLoadAuth = TRUE; /* stat lost, so force reload */
}
}
else if (buf.st_mtime > lastmod)
{
lastmod = buf.st_mtime;
ShouldLoadAuth = TRUE;
}
if (ShouldLoadAuth)
{
int loadauth = LoadAuthorization();
/*
* If the authorization file has at least one entry for this server,
* disable local host access. (loadauth > 0)
*
* If there are zero entries (either initially or when the
* authorization file is later reloaded), or if a valid
* authorization file was never loaded, enable local host access.
* (loadauth == 0 || !loaded)
*
* If the authorization file was loaded initially (with valid
* entries for this server), and reloading it later fails, don't
* change anything. (loadauth == -1 && loaded)
*/
#ifdef NX_TRANS_AUTH
/*
* The implementation of CheckAuthorization() was changed. The way
* the auth file was handled previously was questionable and could
* open the way to a vast array of security problems. There might be
* ways for an attacker to prevent the server from reading the file
* and it was enough for the server to fail reading the file once
* (because of a not blocked signal, for example) to leave the dis-
* play open to all the users running a session on the same terminal
* server.
*
* In NX we want to have only two cases: either we have to check an
* authorization file or we don't. In the first case we need to do our
* best to read the file at any new client access and never fall back
* to host based authentication. Falling back to local host access has
* no way back, as it will always take precedence over the auth cookie
* (unless the user explicitly disables, one by one, all the rules
* allowing local access, if and only if he/she becomes aware of the
* problem). In the second case we assume that user doesn't care secu-
* rity and so allow unrestricted access from the local machine.
*/
#ifdef NX_TRANS_TEST
fprintf(stderr, "CheckAuthorization: Going to set authorization with loadauth [%d].\n",
loadauth);
#endif
if (authorization_file)
{
#ifdef NX_TRANS_TEST
fprintf(stderr, "CheckAuthorization: Disabling local host access.\n");
#endif
DisableLocalHost();
}
else
{
/*
* Enable host-based authentication only if
* the authorization file was not specified
* either on the command line or in the env-
* ironment.
*/
#ifdef NX_TRANS_TEST
fprintf(stderr, "CheckAuthorization: Enabling local host access.\n");
#endif
EnableLocalHost();
}
/*
* Avoid the 'unused variable' warning.
*/
loadauth = loadauth;
#else /* #ifdef NX_TRANS_AUTH */
if (loadauth > 0)
{
DisableLocalHost(); /* got at least one */
loaded = TRUE;
}
else if (loadauth == 0 || !loaded)
EnableLocalHost ();
#endif /* #ifdef NX_TRANS_AUTH */
}
if (name_length) {
for (i = 0; i < NUM_AUTHORIZATION; i++) {
if (protocols[i].name_length == name_length &&
memcmp (protocols[i].name, name, (int) name_length) == 0)
{
return (*protocols[i].Check) (data_length, data, client, reason);
}
*reason = "Protocol not supported by server\n";
}
} else *reason = "No protocol specified\n";
return (XID) ~0L;
}
void
ResetAuthorization (void)
{
int i;
for (i = 0; i < NUM_AUTHORIZATION; i++)
if (protocols[i].Reset)
(*protocols[i].Reset)();
ShouldLoadAuth = TRUE;
}
XID
AuthorizationToID (
unsigned short name_length,
char *name,
unsigned short data_length,
char *data)
{
int i;
for (i = 0; i < NUM_AUTHORIZATION; i++) {
if (protocols[i].name_length == name_length &&
memcmp (protocols[i].name, name, (int) name_length) == 0 &&
protocols[i].ToID)
{
return (*protocols[i].ToID) (data_length, data);
}
}
return (XID) ~0L;
}
int
AuthorizationFromID (
XID id,
unsigned short *name_lenp,
char **namep,
unsigned short *data_lenp,
char **datap)
{
int i;
for (i = 0; i < NUM_AUTHORIZATION; i++) {
if (protocols[i].FromID &&
(*protocols[i].FromID) (id, data_lenp, datap)) {
*name_lenp = protocols[i].name_length;
*namep = protocols[i].name;
return 1;
}
}
return 0;
}
int
RemoveAuthorization (
unsigned short name_length,
char *name,
unsigned short data_length,
char *data)
{
int i;
for (i = 0; i < NUM_AUTHORIZATION; i++) {
if (protocols[i].name_length == name_length &&
memcmp (protocols[i].name, name, (int) name_length) == 0 &&
protocols[i].Remove)
{
return (*protocols[i].Remove) (data_length, data);
}
}
return 0;
}
int
AddAuthorization (unsigned name_length, char *name, unsigned data_length, char *data)
{
int i;
for (i = 0; i < NUM_AUTHORIZATION; i++) {
if (protocols[i].name_length == name_length &&
memcmp (protocols[i].name, name, (int) name_length) == 0 &&
protocols[i].Add)
{
return (*protocols[i].Add) (data_length, data, FakeClientID(0));
}
}
return 0;
}
#ifdef XCSECURITY
XID
GenerateAuthorization(
unsigned name_length,
char *name,
unsigned data_length,
char *data,
unsigned *data_length_return,
char **data_return)
{
int i;
for (i = 0; i < NUM_AUTHORIZATION; i++) {
if (protocols[i].name_length == name_length &&
memcmp (protocols[i].name, name, (int) name_length) == 0 &&
protocols[i].Generate)
{
return (*protocols[i].Generate) (data_length, data,
FakeClientID(0), data_length_return, data_return);
}
}
return -1;
}
/* A random number generator that is more unpredictable
than that shipped with some systems.
This code is taken from the C standard. */
static unsigned long int next = 1;
static int
xdm_rand(void)
{
next = next * 1103515245 + 12345;
return (unsigned int)(next/65536) % 32768;
}
static void
xdm_srand(unsigned int seed)
{
next = seed;
}
void
GenerateRandomData (int len, char *buf)
{
static int seed;
int value;
int i;
seed += GetTimeInMillis();
xdm_srand (seed);
for (i = 0; i < len; i++)
{
value = xdm_rand ();
buf[i] ^= (value & 0xff00) >> 8;
}
/* XXX add getrusage, popen("ps -ale") */
}
#endif /* XCSECURITY */

View File

@@ -0,0 +1,397 @@
/*
* Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All
* rights reserved.
* Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/**
* @file
*
* This file contains functionality for identifying clients by various
* means. The primary purpose of identification is to simply aid in
* finding out which clients are using X server and how they are using
* it. For example, it's often necessary to monitor what requests
* clients are executing (to spot bad behaviour) and how they are
* allocating resources in X server (to spot excessive resource
* usage).
*
* This framework automatically allocates information, that can be
* used for client identification, when a client connects to the
* server. The information is freed when the client disconnects. The
* allocated information is just a collection of various IDs, such as
* PID and process name for local clients, that are likely to be
* useful in analyzing X server usage.
*
* Users of the framework can query ID information about clients at
* any time. To avoid repeated polling of IDs the users can also
* subscribe for notifications about the availability of ID
* information. IDs have been allocated before ClientStateCallback is
* called with ClientStateInitial state. Similarly the IDs will be
* released after ClientStateCallback is called with ClientStateGone
* state.
*
* Author: Rami Ylimäki <rami.ylimaki@vincit.fi>
*/
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "client.h"
#include "os.h"
#include "dixstruct.h"
#ifdef __sun
#include <errno.h>
#include <procfs.h>
#endif
#ifdef __OpenBSD__
#include <sys/param.h>
#include <sys/sysctl.h>
#include <sys/types.h>
#include <kvm.h>
#include <limits.h>
#endif
/**
* Try to determine a PID for a client from its connection
* information. This should be called only once when new client has
* connected, use GetClientPid to determine the PID at other times.
*
* @param[in] client Connection linked to some process.
*
* @return PID of the client. Error (-1) if PID can't be determined
* for the client.
*
* @see GetClientPid
*/
pid_t
DetermineClientPid(struct _Client * client)
{
LocalClientCredRec *lcc = NULL;
pid_t pid = -1;
if (client == NullClient)
return pid;
if (client == serverClient)
return getpid();
if (GetLocalClientCreds(client, &lcc) != -1) {
if (lcc->fieldsSet & LCC_PID_SET)
pid = lcc->pid;
FreeLocalClientCreds(lcc);
}
return pid;
}
/**
* Try to determine a command line string for a client based on its
* PID. Note that mapping PID to a command hasn't been implemented for
* some operating systems. This should be called only once when a new
* client has connected, use GetClientCmdName/Args to determine the
* string at other times.
*
* @param[in] pid Process ID of a client.
* @param[out] cmdname Client process name without arguments. You must
* release this by calling free. On error NULL is
* returned. Pass NULL if you aren't interested in
* this value.
* @param[out] cmdargs Arguments to client process. Useful for
* identifying a client that is executed from a
* launcher program. You must release this by
* calling free. On error NULL is returned. Pass
* NULL if you aren't interested in this value.
*
* @see GetClientCmdName/Args
*/
void
DetermineClientCmd(pid_t pid, const char **cmdname, const char **cmdargs)
{
char path[PATH_MAX + 1];
int totsize = 0;
int fd = 0;
if (cmdname)
*cmdname = NULL;
if (cmdargs)
*cmdargs = NULL;
if (pid == -1)
return;
#ifdef __sun /* Solaris */
/* Solaris does not support /proc/pid/cmdline, but makes information
* similar to what ps shows available in a binary structure in the
* /proc/pid/psinfo file. */
if (snprintf(path, sizeof(path), "/proc/%d/psinfo", pid) < 0)
return;
fd = open(path, O_RDONLY);
if (fd < 0) {
ErrorF("Failed to open %s: %s\n", path, strerror(errno));
return;
}
else {
psinfo_t psinfo = { 0 };
char *sp;
totsize = read(fd, &psinfo, sizeof(psinfo_t));
close(fd);
if (totsize <= 0)
return;
/* pr_psargs is the first PRARGSZ (80) characters of the command
* line string - assume up to the first space is the command name,
* since it's not delimited. While there is also pr_fname, that's
* more limited, giving only the first 16 chars of the basename of
* the file that was exec'ed, thus cutting off many long gnome
* command names, or returning "isapython2.6" for all python scripts.
*/
psinfo.pr_psargs[PRARGSZ - 1] = '\0';
sp = strchr(psinfo.pr_psargs, ' ');
if (sp)
*sp++ = '\0';
if (cmdname)
*cmdname = strdup(psinfo.pr_psargs);
if (cmdargs && sp)
*cmdargs = strdup(sp);
}
#elif defined(__OpenBSD__)
/* on OpenBSD use kvm_getargv() */
{
kvm_t *kd;
char errbuf[_POSIX2_LINE_MAX];
char **argv;
struct kinfo_proc *kp;
size_t len = 0;
int i, n;
kd = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, errbuf);
if (kd == NULL)
return;
kp = kvm_getprocs(kd, KERN_PROC_PID, pid, sizeof(struct kinfo_proc),
&n);
if (n != 1)
return;
argv = kvm_getargv(kd, kp, 0);
*cmdname = strdup(argv[0]);
i = 1;
while (argv[i] != NULL) {
len += strlen(argv[i]) + 1;
i++;
}
*cmdargs = calloc(1, len);
i = 1;
while (argv[i] != NULL) {
strlcat(*cmdargs, argv[i], len);
strlcat(*cmdargs, " ", len);
i++;
}
kvm_close(kd);
}
#else /* Linux using /proc/pid/cmdline */
/* Check if /proc/pid/cmdline exists. It's not supported on all
* operating systems. */
if (snprintf(path, sizeof(path), "/proc/%d/cmdline", pid) < 0)
return;
fd = open(path, O_RDONLY);
if (fd < 0)
return;
/* Read the contents of /proc/pid/cmdline. It should contain the
* process name and arguments. */
totsize = read(fd, path, sizeof(path));
close(fd);
if (totsize <= 0)
return;
path[totsize - 1] = '\0';
/* Contruct the process name without arguments. */
if (cmdname) {
*cmdname = strdup(path);
}
/* Construct the arguments for client process. */
if (cmdargs) {
int cmdsize = strlen(path) + 1;
int argsize = totsize - cmdsize;
char *args = NULL;
if (argsize > 0)
args = malloc(argsize);
if (args) {
int i = 0;
for (i = 0; i < (argsize - 1); ++i) {
const char c = path[cmdsize + i];
args[i] = (c == '\0') ? ' ' : c;
}
args[argsize - 1] = '\0';
*cmdargs = args;
}
}
#endif
}
/**
* Called when a new client connects. Allocates client ID information.
*
* @param[in] client Recently connected client.
*/
void
ReserveClientIds(struct _Client *client)
{
#ifdef CLIENTIDS
if (client == NullClient)
return;
assert(!client->clientIds);
client->clientIds = calloc(1, sizeof(ClientIdRec));
if (!client->clientIds)
return;
client->clientIds->pid = DetermineClientPid(client);
if (client->clientIds->pid != -1)
DetermineClientCmd(client->clientIds->pid, &client->clientIds->cmdname,
&client->clientIds->cmdargs);
DebugF("client(%lx): Reserved pid(%d).\n",
(unsigned long) client->clientAsMask, client->clientIds->pid);
DebugF("client(%lx): Reserved cmdname(%s) and cmdargs(%s).\n",
(unsigned long) client->clientAsMask,
client->clientIds->cmdname ? client->clientIds->cmdname : "NULL",
client->clientIds->cmdargs ? client->clientIds->cmdargs : "NULL");
#endif /* CLIENTIDS */
}
/**
* Called when an existing client disconnects. Frees client ID
* information.
*
* @param[in] client Recently disconnected client.
*/
void
ReleaseClientIds(struct _Client *client)
{
#ifdef CLIENTIDS
if (client == NullClient)
return;
if (!client->clientIds)
return;
DebugF("client(%lx): Released pid(%d).\n",
(unsigned long) client->clientAsMask, client->clientIds->pid);
DebugF("client(%lx): Released cmdline(%s) and cmdargs(%s).\n",
(unsigned long) client->clientAsMask,
client->clientIds->cmdname ? client->clientIds->cmdname : "NULL",
client->clientIds->cmdargs ? client->clientIds->cmdargs : "NULL");
free((void *) client->clientIds->cmdname); /* const char * */
free((void *) client->clientIds->cmdargs); /* const char * */
free(client->clientIds);
client->clientIds = NULL;
#endif /* CLIENTIDS */
}
/**
* Get cached PID of a client.
*
* param[in] client Client whose PID has been already cached.
*
* @return Cached client PID. Error (-1) if called:
* - before ClientStateInitial client state notification
* - after ClientStateGone client state notification
* - for remote clients
*
* @see DetermineClientPid
*/
pid_t
GetClientPid(struct _Client *client)
{
if (client == NullClient)
return -1;
if (!client->clientIds)
return -1;
return client->clientIds->pid;
}
/**
* Get cached command name string of a client.
*
* param[in] client Client whose command line string has been already
* cached.
*
* @return Cached client command name. Error (NULL) if called:
* - before ClientStateInitial client state notification
* - after ClientStateGone client state notification
* - for remote clients
* - on OS that doesn't support mapping of PID to command line
*
* @see DetermineClientCmd
*/
const char *
GetClientCmdName(struct _Client *client)
{
if (client == NullClient)
return NULL;
if (!client->clientIds)
return NULL;
return client->clientIds->cmdname;
}
/**
* Get cached command arguments string of a client.
*
* param[in] client Client whose command line string has been already
* cached.
*
* @return Cached client command arguments. Error (NULL) if called:
* - before ClientStateInitial client state notification
* - after ClientStateGone client state notification
* - for remote clients
* - on OS that doesn't support mapping of PID to command line
*
* @see DetermineClientCmd
*/
const char *
GetClientCmdArgs(struct _Client *client)
{
if (client == NullClient)
return NULL;
if (!client->clientIds)
return NULL;
return client->clientIds->cmdargs;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,769 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
/* */
/* nx-X11, NX protocol compression and NX extensions to this software */
/* are copyright of the aforementioned persons and companies. */
/* */
/* Redistribution and use of the present software is allowed according */
/* to terms specified in the file LICENSE which comes in the source */
/* distribution. */
/* */
/* All rights reserved. */
/* */
/* NOTE: This software has received contributions from various other */
/* contributors, only the core maintainers and supporters are listed as */
/* copyright holders. Please contact us, if you feel you should be listed */
/* as copyright holder, as well. */
/* */
/**************************************************************************/
/*
Copyright 1987, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from The Open Group.
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
Copyright 1994 Quarterdeck Office Systems.
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the names of Digital and
Quarterdeck not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.
DIGITAL AND QUARTERDECK DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT
OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* Copyright (c) 1997-2003 by The XFree86 Project, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name of the copyright holder(s)
* and author(s) shall not be used in advertising or otherwise to promote
* the sale, use or other dealings in this Software without prior written
* authorization from the copyright holder(s) and author(s).
*/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <nx-X11/Xos.h>
#include <stdio.h>
#include <time.h>
#include <sys/stat.h>
#include <stdarg.h>
#include <stdlib.h> /* for malloc() */
#include <errno.h>
#include "input.h"
#include "site.h"
#include "opaque.h"
#ifdef NX_TRANS_SOCKET
#include <nx/NX.h>
#endif
#ifdef DDXOSVERRORF
void (*OsVendorVErrorFProc)(const char *, va_list args) = NULL;
#ifdef NX_TRANS_EXIT
int OsVendorVErrorFFatal = 0;
#endif
#endif
static FILE *logFile = NULL;
static Bool logFlush = FALSE;
static Bool logSync = FALSE;
static int logVerbosity = DEFAULT_LOG_VERBOSITY;
static int logFileVerbosity = DEFAULT_LOG_FILE_VERBOSITY;
/* Buffer to information logged before the log file is opened. */
static char *saveBuffer = NULL;
static int bufferSize = 0, bufferUnused = 0, bufferPos = 0;
static Bool needBuffer = TRUE;
/* Prefix strings for log messages. */
#ifndef X_UNKNOWN_STRING
#define X_UNKNOWN_STRING "(\?\?)"
#endif
#ifndef X_PROBE_STRING
#define X_PROBE_STRING "(--)"
#endif
#ifndef X_CONFIG_STRING
#define X_CONFIG_STRING "(**)"
#endif
#ifndef X_DEFAULT_STRING
#define X_DEFAULT_STRING "(==)"
#endif
#ifndef X_CMDLINE_STRING
#define X_CMDLINE_STRING "(++)"
#endif
#ifndef X_NOTICE_STRING
#define X_NOTICE_STRING "(!!)"
#endif
#ifndef X_ERROR_STRING
#define X_ERROR_STRING "(EE)"
#endif
#ifndef X_WARNING_STRING
#define X_WARNING_STRING "(WW)"
#endif
#ifndef X_INFO_STRING
#define X_INFO_STRING "(II)"
#endif
#ifndef X_NOT_IMPLEMENTED_STRING
#define X_NOT_IMPLEMENTED_STRING "(NI)"
#endif
/*
* LogFilePrep is called to setup files for logging, including getting
* an old file out of the way, but it doesn't actually open the file,
* since it may be used for renaming a file we're already logging to.
*/
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
static char *
LogFilePrep(const char *fname, const char *backup, const char *idstring)
{
char *logFileName = NULL;
if (asprintf(&logFileName, fname, idstring) == -1)
FatalError("Cannot allocate space for the log file name\n");
if (backup && *backup) {
struct stat buf;
if (!stat(logFileName, &buf) && S_ISREG(buf.st_mode)) {
char *suffix;
char *oldLog;
if ((asprintf(&suffix, backup, idstring) == -1) ||
(asprintf(&oldLog, "%s%s", logFileName, suffix) == -1)) {
FatalError("Cannot allocate space for the log file name\n");
}
free(suffix);
if (rename(logFileName, oldLog) == -1) {
FatalError("Cannot move old log file \"%s\" to \"%s\"\n",
logFileName, oldLog);
}
free(oldLog);
}
}
else {
if (remove(logFileName) != 0) {
FatalError("Cannot remove old log file \"%s\": %s\n",
logFileName, strerror(errno));
}
}
return logFileName;
}
#pragma GCC diagnostic pop
/*
* LogInit is called to start logging to a file. It is also called (with
* NULL arguments) when logging to a file is not wanted. It must always be
* called, otherwise log messages will continue to accumulate in a buffer.
*
* %s, if present in the fname or backup strings, is expanded to the display
* string (or to a string containing the pid if the display is not yet set).
*/
static char *saved_log_fname;
static char *saved_log_backup;
static char *saved_log_tempname;
const char *
LogInit(const char *fname, const char *backup)
{
char *logFileName = NULL;
if (fname && *fname) {
if (displayfd != -1) {
/* Display isn't set yet, so we can't use it in filenames yet. */
char pidstring[32];
snprintf(pidstring, sizeof(pidstring), "pid-%ld",
(unsigned long) getpid());
logFileName = LogFilePrep(fname, backup, pidstring);
saved_log_tempname = logFileName;
/* Save the patterns for use when the display is named. */
saved_log_fname = strdup(fname);
if (backup == NULL)
saved_log_backup = NULL;
else
saved_log_backup = strdup(backup);
} else
logFileName = LogFilePrep(fname, backup, display);
if ((logFile = fopen(logFileName, "w")) == NULL)
FatalError("Cannot open log file \"%s\"\n", logFileName);
setvbuf(logFile, NULL, _IONBF, 0);
/* Flush saved log information. */
if (saveBuffer && bufferSize > 0) {
fwrite(saveBuffer, bufferPos, 1, logFile);
fflush(logFile);
fsync(fileno(logFile));
}
}
/*
* Unconditionally free the buffer, and flag that the buffer is no longer
* needed.
*/
if (saveBuffer && bufferSize > 0) {
free(saveBuffer); /* Must be free(), not free() */
saveBuffer = NULL;
bufferSize = 0;
}
needBuffer = FALSE;
return logFileName;
}
void
LogSetDisplay(void)
{
if (saved_log_fname) {
char *logFileName;
logFileName = LogFilePrep(saved_log_fname, saved_log_backup, display);
if (rename(saved_log_tempname, logFileName) == 0) {
LogMessageVerb(X_PROBED, 0,
"Log file renamed from \"%s\" to \"%s\"\n",
saved_log_tempname, logFileName);
if (strlen(saved_log_tempname) >= strlen(logFileName))
strncpy(saved_log_tempname, logFileName,
strlen(saved_log_tempname));
}
else {
ErrorF("Failed to rename log file \"%s\" to \"%s\": %s\n",
saved_log_tempname, logFileName, strerror(errno));
}
/* free newly allocated string - can't free old one since existing
pointers to it may exist in DDX callers. */
free(logFileName);
free(saved_log_fname);
free(saved_log_backup);
}
}
void
LogClose()
{
if (logFile) {
fclose(logFile);
logFile = NULL;
}
}
Bool
LogSetParameter(LogParameter param, int value)
{
switch (param) {
case XLOG_FLUSH:
logFlush = value ? TRUE : FALSE;
return TRUE;
case XLOG_SYNC:
logSync = value ? TRUE : FALSE;
return TRUE;
case XLOG_VERBOSITY:
logVerbosity = value;
return TRUE;
case XLOG_FILE_VERBOSITY:
logFileVerbosity = value;
return TRUE;
default:
return FALSE;
}
}
/* This function does the actual log message writes. */
void
LogVWrite(int verb, const char *f, va_list args)
{
static char tmpBuffer[1024];
int len = 0;
/*
* Since a va_list can only be processed once, write the string to a
* buffer, and then write the buffer out to the appropriate output
* stream(s).
*/
if (verb < 0 || logFileVerbosity >= verb || logVerbosity >= verb) {
vsnprintf(tmpBuffer, sizeof(tmpBuffer), f, args);
#ifdef NX_TRANS_EXIT
/*
* Beautify the message. Make the
* first letter uppercase.
*/
*tmpBuffer = toupper(*tmpBuffer);
/*
* Remove the trailing newline.
*/
if (strlen(tmpBuffer) > 0 &&
*(tmpBuffer + strlen(tmpBuffer) - 1) == '\n') {
*(tmpBuffer + strlen(tmpBuffer) - 1) = '\0';
}
/*
* Remove the trailing full-stop.
*/
if (strlen(tmpBuffer) > 0 &&
*(tmpBuffer + strlen(tmpBuffer) - 1) == '.') {
*(tmpBuffer + strlen(tmpBuffer) - 1) = '\0';
}
#endif /* #ifdef NX_TRANS_EXIT */
len = strlen(tmpBuffer);
}
if ((verb < 0 || logVerbosity >= verb) && len > 0)
fwrite(tmpBuffer, len, 1, stderr);
if ((verb < 0 || logFileVerbosity >= verb) && len > 0) {
if (logFile) {
fwrite(tmpBuffer, len, 1, logFile);
if (logFlush) {
fflush(logFile);
if (logSync)
fsync(fileno(logFile));
}
} else if (needBuffer) {
/*
* Note, this code is used before OsInit() has been called, so
* malloc() and friends can't be used.
*/
if (len > bufferUnused) {
bufferSize += 1024;
bufferUnused += 1024;
if (saveBuffer)
saveBuffer = realloc(saveBuffer, bufferSize);
else
saveBuffer = malloc(bufferSize);
if (!saveBuffer)
FatalError("realloc() failed while saving log messages\n");
}
bufferUnused -= len;
memcpy(saveBuffer + bufferPos, tmpBuffer, len);
bufferPos += len;
}
}
}
void
LogWrite(int verb, const char *f, ...)
{
va_list args;
va_start(args, f);
LogVWrite(verb, f, args);
va_end(args);
}
void
LogVMessageVerb(MessageType type, int verb, const char *format, va_list args)
{
const char *s = X_UNKNOWN_STRING;
char *tmpBuf = NULL;
/* Ignore verbosity for X_ERROR */
if (logVerbosity >= verb || logFileVerbosity >= verb || type == X_ERROR) {
switch (type) {
case X_PROBED:
s = X_PROBE_STRING;
break;
case X_CONFIG:
s = X_CONFIG_STRING;
break;
case X_DEFAULT:
s = X_DEFAULT_STRING;
break;
case X_CMDLINE:
s = X_CMDLINE_STRING;
break;
case X_NOTICE:
s = X_NOTICE_STRING;
break;
case X_ERROR:
s = X_ERROR_STRING;
if (verb > 0)
verb = 0;
break;
case X_WARNING:
s = X_WARNING_STRING;
break;
case X_INFO:
s = X_INFO_STRING;
break;
case X_NOT_IMPLEMENTED:
s = X_NOT_IMPLEMENTED_STRING;
break;
case X_UNKNOWN:
s = X_UNKNOWN_STRING;
break;
case X_NONE:
s = NULL;
break;
}
/*
* Prefix the format string with the message type. We do it this way
* so that LogVWrite() is only called once per message.
*/
if (s) {
tmpBuf = malloc(strlen(format) + strlen(s) + 1 + 1);
/* Silently return if malloc fails here. */
if (!tmpBuf)
return;
sprintf(tmpBuf, "%s ", s);
strcat(tmpBuf, format);
LogVWrite(verb, tmpBuf, args);
free(tmpBuf);
} else
LogVWrite(verb, format, args);
}
}
/* Log message with verbosity level specified. */
void
LogMessageVerb(MessageType type, int verb, const char *format, ...)
{
va_list ap;
va_start(ap, format);
LogVMessageVerb(type, verb, format, ap);
va_end(ap);
}
/* Log a message with the standard verbosity level of 1. */
void
LogMessage(MessageType type, const char *format, ...)
{
va_list ap;
va_start(ap, format);
LogVMessageVerb(type, 1, format, ap);
va_end(ap);
}
#ifdef __GNUC__
void AbortServer(void) __attribute__((noreturn));
#endif
void
AbortServer(void)
{
#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST)
fprintf(stderr, "AbortServer: Going to abort the current server.\n");
#endif
OsCleanup(TRUE);
AbortDDX();
fflush(stderr);
if (CoreDump)
abort();
#ifdef NX_TRANS_EXIT
#ifdef NX_TRANS_TEST
fprintf(stderr, "AbortServer: Going to clean up NX resources and exit.\n");
#endif
NXTransExit(1);
#else /* #ifdef NX_TRANS_EXIT */
exit (1);
#endif
}
#ifndef AUDIT_PREFIX
#define AUDIT_PREFIX "AUDIT: %s: %ld %s: "
#endif
#ifndef AUDIT_TIMEOUT
#define AUDIT_TIMEOUT ((CARD32)(120 * 1000)) /* 2 mn */
#endif
static int nrepeat = 0;
static int oldlen = -1;
static OsTimerPtr auditTimer = NULL;
void
FreeAuditTimer(void)
{
if (auditTimer != NULL) {
/* Force output of pending messages */
TimerForce(auditTimer);
TimerFree(auditTimer);
auditTimer = NULL;
}
}
static char *
AuditPrefix(void)
{
time_t tm;
char *autime, *s;
char *tmpBuf;
int len;
time(&tm);
autime = ctime(&tm);
if ((s = strchr(autime, '\n')))
*s = '\0';
if ((s = strrchr(argvGlobal[0], '/')))
s++;
else
s = argvGlobal[0];
len = strlen(AUDIT_PREFIX) + strlen(autime) + 10 + strlen(s) + 1;
tmpBuf = malloc(len);
if (!tmpBuf)
return NULL;
snprintf(tmpBuf, len, AUDIT_PREFIX, autime, (unsigned long)getpid(), s);
return tmpBuf;
}
void
AuditF(const char * f, ...)
{
va_list args;
va_start(args, f);
VAuditF(f, args);
va_end(args);
}
static CARD32
AuditFlush(OsTimerPtr timer, CARD32 now, void * arg)
{
char *prefix;
if (nrepeat > 0) {
prefix = AuditPrefix();
ErrorF("%slast message repeated %d times\n",
prefix != NULL ? prefix : "", nrepeat);
nrepeat = 0;
if (prefix != NULL)
free(prefix);
return AUDIT_TIMEOUT;
} else {
/* if the timer expires without anything to print, flush the message */
oldlen = -1;
return 0;
}
}
void
VAuditF(const char *f, va_list args)
{
char *prefix;
char buf[1024];
int len;
static char oldbuf[1024];
prefix = AuditPrefix();
len = vsnprintf(buf, sizeof(buf), f, args);
if (len == oldlen && strcmp(buf, oldbuf) == 0) {
/* Message already seen */
nrepeat++;
} else {
/* new message */
if (auditTimer != NULL)
TimerForce(auditTimer);
ErrorF("%s%s", prefix != NULL ? prefix : "", buf);
strlcpy(oldbuf, buf, sizeof(oldbuf));
oldlen = len;
nrepeat = 0;
auditTimer = TimerSet(auditTimer, 0, AUDIT_TIMEOUT, AuditFlush, NULL);
}
if (prefix != NULL)
free(prefix);
}
void
FatalError(const char *f, ...)
{
va_list args;
static Bool beenhere = FALSE;
#ifdef NX_TRANS_EXIT
if (beenhere) {
fprintf(stderr, "Error: Aborting session with fatal error function reentered.\n");
}
else {
/*
* Tell to the log function that this
* is a fatal error.
*/
OsVendorVErrorFFatal = 1;
fprintf(stderr, "Error: Aborting session with '");
va_start(args, f);
VErrorF(f, args);
va_end(args);
fprintf(stderr, "'.\n");
}
#else /* #ifdef NX_TRANS_EXIT */
if (beenhere)
ErrorF("\nFatalError re-entered, aborting\n");
else
ErrorF("\nFatal server error:\n");
va_start(args, f);
VErrorF(f, args);
va_end(args);
ErrorF("\n");
#endif /* #ifdef NX_TRANS_EXIT */
#ifdef DDXOSFATALERROR
if (!beenhere)
OsVendorFatalError();
#endif
#ifdef ABORTONFATALERROR
abort();
#endif
if (!beenhere) {
beenhere = TRUE;
AbortServer();
} else
abort();
/*NOTREACHED*/
}
void
VErrorF(const char *f, va_list args)
{
#ifdef DDXOSVERRORF
if (OsVendorVErrorFProc)
OsVendorVErrorFProc(f, args);
else
LogVWrite(-1, f, args);
#else
LogVWrite(-1, f, args);
#endif
}
void
ErrorF(const char * f, ...)
{
va_list args;
va_start(args, f);
VErrorF(f, args);
va_end(args);
}
/* A perror() workalike. */
#ifndef NEED_STRERROR
#ifdef SYSV
#define NEED_STRERROR
#endif
#endif
#if defined(NEED_STRERROR) && !defined(strerror)
extern char *sys_errlist[];
extern int sys_nerr;
#define strerror(n) \
((n) >= 0 && (n) < sys_nerr) ? sys_errlist[(n)] : "unknown error"
#endif
void
Error(char *str)
{
char *err = NULL;
int saveErrno = errno;
if (str) {
err = malloc(strlen(strerror(saveErrno)) + strlen(str) + 2 + 1);
if (!err)
return;
sprintf(err, "%s: ", str);
strcat(err, strerror(saveErrno));
LogWrite(-1, "%s", err);
} else
LogWrite(-1, "%s", strerror(saveErrno));
}
void
LogPrintMarkers()
{
/* Show what the message marker symbols mean. */
ErrorF("Markers: ");
LogMessageVerb(X_PROBED, -1, "probed, ");
LogMessageVerb(X_CONFIG, -1, "from config file, ");
LogMessageVerb(X_DEFAULT, -1, "default setting,\n\t");
LogMessageVerb(X_CMDLINE, -1, "from command line, ");
LogMessageVerb(X_NOTICE, -1, "notice, ");
LogMessageVerb(X_INFO, -1, "informational,\n\t");
LogMessageVerb(X_WARNING, -1, "warning, ");
LogMessageVerb(X_ERROR, -1, "error, ");
LogMessageVerb(X_NOT_IMPLEMENTED, -1, "not implemented, ");
LogMessageVerb(X_UNKNOWN, -1, "unknown.\n");
}

View File

@@ -0,0 +1,197 @@
/*
Copyright 1988, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from The Open Group.
*/
/*
* MIT-MAGIC-COOKIE-1 authorization scheme
* Author: Keith Packard, MIT X Consortium
*/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <nx-X11/X.h>
#include "os.h"
#include "osdep.h"
#include "dixstruct.h"
static struct auth {
struct auth *next;
unsigned short len;
char *data;
XID id;
} *mit_auth;
int
MitAddCookie (
unsigned short data_length,
char *data,
XID id)
{
struct auth *new;
new = (struct auth *) malloc (sizeof (struct auth));
if (!new)
return 0;
new->data = (char *) malloc ((unsigned) data_length);
if (!new->data) {
free(new);
return 0;
}
new->next = mit_auth;
mit_auth = new;
memmove(new->data, data, (int) data_length);
new->len = data_length;
new->id = id;
return 1;
}
XID
MitCheckCookie (
unsigned short data_length,
char *data,
ClientPtr client,
char **reason)
{
struct auth *auth;
for (auth = mit_auth; auth; auth=auth->next) {
if (data_length == auth->len &&
timingsafe_memcmp (data, auth->data, (int) data_length) == 0)
return auth->id;
}
*reason = "Invalid MIT-MAGIC-COOKIE-1 key";
return (XID) -1;
}
int
MitResetCookie (void)
{
struct auth *auth, *next;
for (auth = mit_auth; auth; auth=next) {
next = auth->next;
free (auth->data);
free (auth);
}
mit_auth = 0;
return 0;
}
XID
MitToID (
unsigned short data_length,
char *data)
{
struct auth *auth;
for (auth = mit_auth; auth; auth=auth->next) {
if (data_length == auth->len &&
memcmp (data, auth->data, data_length) == 0)
return auth->id;
}
return (XID) -1;
}
int
MitFromID (
XID id,
unsigned short *data_lenp,
char **datap)
{
struct auth *auth;
for (auth = mit_auth; auth; auth=auth->next) {
if (id == auth->id) {
*data_lenp = auth->len;
*datap = auth->data;
return 1;
}
}
return 0;
}
int
MitRemoveCookie (
unsigned short data_length,
char *data)
{
struct auth *auth, *prev;
prev = 0;
for (auth = mit_auth; auth; prev = auth, auth=auth->next) {
if (data_length == auth->len &&
memcmp (data, auth->data, data_length) == 0)
{
if (prev)
prev->next = auth->next;
else
mit_auth = auth->next;
free (auth->data);
free (auth);
return 1;
}
}
return 0;
}
#ifdef XCSECURITY
static char cookie[16]; /* 128 bits */
XID
MitGenerateCookie (
unsigned data_length,
char *data,
XID id,
unsigned *data_length_return,
char **data_return)
{
int i = 0;
int status;
while (data_length--)
{
cookie[i++] += *data++;
if (i >= sizeof (cookie)) i = 0;
}
GenerateRandomData(sizeof (cookie), cookie);
status = MitAddCookie(sizeof (cookie), cookie, id);
if (!status)
{
id = -1;
}
else
{
*data_return = cookie;
*data_length_return = sizeof (cookie);
}
return id;
}
#endif /* XCSECURITY */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,297 @@
/***********************************************************
Copyright 1987, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Digital not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.
******************************************************************/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#ifndef _OSDEP_H_
#define _OSDEP_H_ 1
#define BUFSIZE 4096
#define BUFWATERMARK 8192
#ifndef MAXBUFSIZE
#define MAXBUFSIZE (1 << 22)
#endif
#include <X11/Xdmcp.h>
#ifndef X_NOT_POSIX
#ifdef _POSIX_SOURCE
#include <limits.h>
#else
#define _POSIX_SOURCE
#include <limits.h>
#undef _POSIX_SOURCE
#endif
#else /* X_NOT_POSIX */
#endif /* X_NOT_POSIX */
#ifndef OPEN_MAX
#ifdef SVR4
#define OPEN_MAX 256
#else
#include <sys/param.h>
#ifndef OPEN_MAX
#if defined(NOFILE) && !defined(NOFILES_MAX)
#define OPEN_MAX NOFILE
#else
#define OPEN_MAX NOFILES_MAX
#endif
#endif
#endif
#endif
#include <nx-X11/Xpoll.h>
/*
* MAXSOCKS is used only for initialising MaxClients when no other method
* like sysconf(_SC_OPEN_MAX) is not supported.
*/
#if OPEN_MAX <= 256
#define MAXSOCKS (OPEN_MAX - 1)
#else
#define MAXSOCKS 256
#endif
/* MAXSELECT is the number of fds that select() can handle */
#define MAXSELECT (sizeof(fd_set) * NBBY)
#ifndef HAS_GETDTABLESIZE
#if !defined(SVR4) && !defined(SYSV)
#define HAS_GETDTABLESIZE
#endif
#endif
#include <stddef.h>
typedef Bool (*ValidatorFunc)(ARRAY8Ptr Auth, ARRAY8Ptr Data, int packet_type);
typedef Bool (*GeneratorFunc)(ARRAY8Ptr Auth, ARRAY8Ptr Data, int packet_type);
typedef Bool (*AddAuthorFunc)(unsigned name_length, char *name, unsigned data_length, char *data);
typedef struct _connectionInput {
struct _connectionInput *next;
char *buffer; /* contains current client input */
char *bufptr; /* pointer to current start of data */
int bufcnt; /* count of bytes in buffer */
int lenLastReq;
int size;
unsigned int ignoreBytes; /* bytes to ignore before the next request */
} ConnectionInput, *ConnectionInputPtr;
typedef struct _connectionOutput {
struct _connectionOutput *next;
int size;
unsigned char *buf;
int count;
} ConnectionOutput, *ConnectionOutputPtr;
struct _osComm;
#define AuthInitArgs void
typedef void (*AuthInitFunc) (AuthInitArgs);
#define AuthAddCArgs unsigned short data_length, char *data, XID id
typedef int (*AuthAddCFunc) (AuthAddCArgs);
#define AuthCheckArgs unsigned short data_length, char *data, ClientPtr client, char **reason
typedef XID (*AuthCheckFunc) (AuthCheckArgs);
#define AuthFromIDArgs XID id, unsigned short *data_lenp, char **datap
typedef int (*AuthFromIDFunc) (AuthFromIDArgs);
#define AuthGenCArgs unsigned data_length, char *data, XID id, unsigned *data_length_return, char **data_return
typedef XID (*AuthGenCFunc) (AuthGenCArgs);
#define AuthRemCArgs unsigned short data_length, char *data
typedef int (*AuthRemCFunc) (AuthRemCArgs);
#define AuthRstCArgs void
typedef int (*AuthRstCFunc) (AuthRstCArgs);
#define AuthToIDArgs unsigned short data_length, char *data
typedef XID (*AuthToIDFunc) (AuthToIDArgs);
typedef void (*OsCloseFunc)(ClientPtr);
typedef int (*OsFlushFunc)(ClientPtr who, struct _osComm * oc, char* extraBuf, int extraCount);
typedef struct _osComm {
int fd;
ConnectionInputPtr input;
ConnectionOutputPtr output;
XID auth_id; /* authorization id */
CARD32 conn_time; /* timestamp if not established, else 0 */
struct _XtransConnInfo *trans_conn; /* transport connection object */
} OsCommRec, *OsCommPtr;
extern int FlushClient(
ClientPtr /*who*/,
OsCommPtr /*oc*/,
const void * /*__extraBuf*/,
int /*extraCount*/
);
extern void FreeOsBuffers(
OsCommPtr /*oc*/
);
extern void InitNotifyFds(void);
extern void HandleNotifyFds(void);
#include "dix.h"
extern ConnectionInputPtr AllocateInputBuffer(void);
extern ConnectionOutputPtr AllocateOutputBuffer(void);
extern fd_set AllSockets;
extern fd_set AllClients;
extern fd_set LastSelectMask;
extern fd_set LastSelectWriteMask;
extern fd_set WellKnownConnections;
extern fd_set EnabledDevices;
extern fd_set NotifyReadFds;
extern fd_set NotifyWriteFds;
extern fd_set ClientsWithInput;
extern fd_set ClientsWriteBlocked;
extern fd_set OutputPending;
extern fd_set IgnoredClientsWithInput;
extern int *ConnectionTranslation;
extern Bool NewOutputPending;
extern Bool AnyWritesPending;
extern Bool NumNotifyWriteFd;
extern Bool CriticalOutputPending;
extern int timesThisConnection;
extern ConnectionInputPtr FreeInputs;
extern ConnectionOutputPtr FreeOutputs;
extern OsCommPtr AvailableInput;
extern WorkQueuePtr workQueue;
/* in WaitFor.c */
#define ffs mffs
extern int mffs(fd_mask);
/* in access.c */
extern Bool ComputeLocalClient(ClientPtr client);
/* in auth.c */
extern void GenerateRandomData (int len, char *buf);
/* in mitauth.c */
extern XID MitCheckCookie (AuthCheckArgs);
extern XID MitGenerateCookie (AuthGenCArgs);
extern XID MitToID (AuthToIDArgs);
extern int MitAddCookie (AuthAddCArgs);
extern int MitFromID (AuthFromIDArgs);
extern int MitRemoveCookie (AuthRemCArgs);
extern int MitResetCookie (AuthRstCArgs);
/* in xdmauth.c */
#ifdef HASXDMAUTH
extern XID XdmCheckCookie (AuthCheckArgs);
extern XID XdmToID (AuthToIDArgs);
extern int XdmAddCookie (AuthAddCArgs);
extern int XdmFromID (AuthFromIDArgs);
extern int XdmRemoveCookie (AuthRemCArgs);
extern int XdmResetCookie (AuthRstCArgs);
#endif
/* in rpcauth.c */
#ifdef SECURE_RPC
extern void SecureRPCInit (AuthInitArgs);
extern XID SecureRPCCheck (AuthCheckArgs);
extern XID SecureRPCToID (AuthToIDArgs);
extern int SecureRPCAdd (AuthAddCArgs);
extern int SecureRPCFromID (AuthFromIDArgs);
extern int SecureRPCRemove (AuthRemCArgs);
extern int SecureRPCReset (AuthRstCArgs);
#endif
/* in secauth.c */
extern XID AuthSecurityCheck (AuthCheckArgs);
/* in xdmcp.c */
extern void XdmcpUseMsg (void);
extern int XdmcpOptions(int argc, char **argv, int i);
extern void XdmcpSetAuthentication (ARRAY8Ptr name);
extern void XdmcpRegisterConnection (
int type,
char *address,
int addrlen);
extern void XdmcpRegisterAuthorizations (void);
extern void XdmcpRegisterAuthorization (char *name, int namelen);
extern void XdmcpRegisterDisplayClass (char *name, int length);
extern void XdmcpInit (void);
extern void XdmcpReset (void);
extern void XdmcpOpenDisplay(int sock);
extern void XdmcpCloseDisplay(int sock);
extern void XdmcpRegisterAuthentication (
char *name,
int namelen,
char *data,
int datalen,
ValidatorFunc Validator,
GeneratorFunc Generator,
AddAuthorFunc AddAuth);
extern int XdmcpCheckAuthentication (ARRAY8Ptr Name, ARRAY8Ptr Data, int packet_type);
extern int XdmcpAddAuthorization (ARRAY8Ptr name, ARRAY8Ptr data);
struct sockaddr_in;
extern void XdmcpRegisterBroadcastAddress (struct sockaddr_in *addr);
#ifdef HASXDMAUTH
extern void XdmAuthenticationInit (char *cookie, int cookie_length);
#endif
#endif /* _OSDEP_H_ */

View File

@@ -0,0 +1,228 @@
/***********************************************************
Copyright 1987, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Digital not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.
******************************************************************/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <stdio.h>
#include <nx-X11/X.h>
#include "os.h"
#include "osdep.h"
#include <nx-X11/Xos.h>
#include "dixstruct.h"
#ifndef PATH_MAX
#ifdef MAXPATHLEN
#define PATH_MAX MAXPATHLEN
#else
#define PATH_MAX 1024
#endif
#endif
#if !defined(SYSV)
#include <sys/resource.h>
#endif
#ifndef ADMPATH
#define ADMPATH "/usr/adm/X%smsgs"
#endif
extern char *display;
#ifdef RLIMIT_DATA
int limitDataSpace = -1;
#endif
#ifdef RLIMIT_STACK
int limitStackSpace = -1;
#endif
#ifdef RLIMIT_NOFILE
int limitNoFile = -1;
#endif
void
OsInit(void)
{
static Bool been_here = FALSE;
static char* admpath = ADMPATH;
static char* devnull = "/dev/null";
char fname[PATH_MAX];
#ifdef macII
set42sig();
#endif
if (!been_here) {
InitNotifyFds();
fclose(stdin);
fclose(stdout);
/*
* If a write of zero bytes to stderr returns non-zero, i.e. -1,
* then writing to stderr failed, and we'll write somewhere else
* instead. (Apparently this never happens in the Real World.)
*/
if (write (2, fname, 0) == -1)
{
FILE *err;
if (strlen (display) + strlen (admpath) + 1 < sizeof fname)
sprintf (fname, admpath, display);
else
strcpy (fname, devnull);
/*
* uses stdio to avoid os dependencies here,
* a real os would use
* open (fname, O_WRONLY|O_APPEND|O_CREAT, 0666)
*/
if (!(err = fopen (fname, "a+")))
err = fopen (devnull, "w");
if (err && (fileno(err) != 2)) {
dup2 (fileno (err), 2);
fclose (err);
}
#if defined(SYSV) || defined(SVR4)
{
static char buf[BUFSIZ];
setvbuf (stderr, buf, _IOLBF, BUFSIZ);
}
#else
setlinebuf(stderr);
#endif
}
#ifndef X_NOT_POSIX
if (getpgrp () == 0)
setpgid (0, 0);
#else
#if !defined(SYSV)
if (getpgrp (0) == 0)
setpgrp (0, getpid ());
#endif
#endif
#ifdef RLIMIT_DATA
if (limitDataSpace >= 0)
{
struct rlimit rlim;
if (!getrlimit(RLIMIT_DATA, &rlim))
{
if ((limitDataSpace > 0) && (limitDataSpace < rlim.rlim_max))
rlim.rlim_cur = limitDataSpace;
else
rlim.rlim_cur = rlim.rlim_max;
(void)setrlimit(RLIMIT_DATA, &rlim);
}
}
#endif
#ifdef RLIMIT_STACK
if (limitStackSpace >= 0)
{
struct rlimit rlim;
if (!getrlimit(RLIMIT_STACK, &rlim))
{
if ((limitStackSpace > 0) && (limitStackSpace < rlim.rlim_max))
rlim.rlim_cur = limitStackSpace;
else
rlim.rlim_cur = rlim.rlim_max;
(void)setrlimit(RLIMIT_STACK, &rlim);
}
}
#endif
#ifdef RLIMIT_NOFILE
if (limitNoFile >= 0)
{
struct rlimit rlim;
if (!getrlimit(RLIMIT_NOFILE, &rlim))
{
if ((limitNoFile > 0) && (limitNoFile < rlim.rlim_max))
rlim.rlim_cur = limitNoFile;
else
rlim.rlim_cur = rlim.rlim_max;
#if 0
if (rlim.rlim_cur > MAXSOCKS)
rlim.rlim_cur = MAXSOCKS;
#endif
(void)setrlimit(RLIMIT_NOFILE, &rlim);
}
}
#endif
#ifdef SERVER_LOCK
LockServer();
#endif
been_here = TRUE;
}
TimerInit();
#ifdef DDXOSINIT
OsVendorInit();
#endif
/*
* No log file by default. OsVendorInit() should call LogInit() with the
* log file name if logging to a file is desired.
*/
LogInit(NULL, NULL);
SmartScheduleInit();
OsInitAllocator();
}
void
OsCleanup(Bool terminating)
{
#ifdef SERVER_LOCK
if (terminating)
{
UnlockServer();
}
#endif
}

View File

@@ -0,0 +1,43 @@
/* $OpenBSD: reallocarray.c,v 1.2 2014/12/08 03:45:00 bcook Exp $ */
/*
* Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <sys/types.h>
#include <errno.h>
#include <stdint.h>
#include <stdlib.h>
#include "os.h"
/*
* This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
* if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
*/
#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
void *
reallocarray(void *optr, size_t nmemb, size_t size)
{
if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
nmemb > 0 && SIZE_MAX / nmemb < size) {
errno = ENOMEM;
return NULL;
}
return realloc(optr, size * nmemb);
}

View File

@@ -0,0 +1,201 @@
/*
Copyright 1991, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from The Open Group.
*/
/*
* SUN-DES-1 authentication mechanism
* Author: Mayank Choudhary, Sun Microsystems
*/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#ifdef SECURE_RPC
#include <nx-X11/X.h>
#include <nx-X11/Xauth.h>
#include "misc.h"
#include "os.h"
#include "dixstruct.h"
#include <rpc/rpc.h>
#ifdef sun
/* <rpc/auth.h> only includes this if _KERNEL is #defined... */
extern bool_t xdr_opaque_auth(XDR *, struct opaque_auth *);
#endif
#ifdef ultrix
#include <time.h>
#include <rpc/auth_des.h>
#endif
static enum auth_stat why;
static char *
authdes_ezdecode(char *inmsg, int len)
{
struct rpc_msg msg;
char cred_area[MAX_AUTH_BYTES];
char verf_area[MAX_AUTH_BYTES];
char *temp_inmsg;
struct svc_req r;
bool_t res0, res1;
XDR xdr;
SVCXPRT xprt;
temp_inmsg = (char *) malloc(len);
if (temp_inmsg == NULL) {
why = AUTH_FAILED; /* generic error, since there is no AUTH_BADALLOC */
return NULL;
}
memmove(temp_inmsg, inmsg, len);
memset((char *)&msg, 0, sizeof(msg));
memset((char *)&r, 0, sizeof(r));
memset(cred_area, 0, sizeof(cred_area));
memset(verf_area, 0, sizeof(verf_area));
msg.rm_call.cb_cred.oa_base = cred_area;
msg.rm_call.cb_verf.oa_base = verf_area;
why = AUTH_FAILED;
xdrmem_create(&xdr, temp_inmsg, len, XDR_DECODE);
if ((r.rq_clntcred = (caddr_t) malloc(MAX_AUTH_BYTES)) == NULL)
goto bad1;
r.rq_xprt = &xprt;
/* decode into msg */
res0 = xdr_opaque_auth(&xdr, &(msg.rm_call.cb_cred));
res1 = xdr_opaque_auth(&xdr, &(msg.rm_call.cb_verf));
if ( ! (res0 && res1) )
goto bad2;
/* do the authentication */
r.rq_cred = msg.rm_call.cb_cred; /* read by opaque stuff */
if (r.rq_cred.oa_flavor != AUTH_DES) {
why = AUTH_TOOWEAK;
goto bad2;
}
#ifdef SVR4
if ((why = __authenticate(&r, &msg)) != AUTH_OK) {
#else
if ((why = _authenticate(&r, &msg)) != AUTH_OK) {
#endif
goto bad2;
}
return (((struct authdes_cred *) r.rq_clntcred)->adc_fullname.name);
bad2:
free(r.rq_clntcred);
bad1:
return ((char *)0); /* ((struct authdes_cred *) NULL); */
}
static XID rpc_id = (XID) ~0L;
static Bool
CheckNetName (
unsigned char *addr,
short len,
void * closure
)
{
return (len == strlen ((char *) closure) &&
strncmp ((char *) addr, (char *) closure, len) == 0);
}
static char rpc_error[MAXNETNAMELEN+50];
XID
SecureRPCCheck (unsigned short data_length, char *data,
ClientPtr client, char **reason)
{
char *fullname;
if (rpc_id == (XID) ~0L) {
*reason = "Secure RPC authorization not initialized";
} else {
fullname = authdes_ezdecode(data, data_length);
if (fullname == (char *)0) {
sprintf(rpc_error, "Unable to authenticate secure RPC client (why=%d)", why);
*reason = rpc_error;
} else {
if (ForEachHostInFamily (FamilyNetname, CheckNetName, fullname))
return rpc_id;
sprintf(rpc_error, "Principal \"%s\" is not authorized to connect",
fullname);
*reason = rpc_error;
}
}
return (XID) ~0L;
}
void
SecureRPCInit (void)
{
if (rpc_id == ~0L)
AddAuthorization (9, "SUN-DES-1", 0, (char *) 0);
}
int
SecureRPCAdd (unsigned short data_length, char *data, XID id)
{
if (data_length)
AddHost ((void *) 0, FamilyNetname, data_length, data);
rpc_id = id;
return 1;
}
int
SecureRPCReset (void)
{
rpc_id = (XID) ~0L;
return 1;
}
XID
SecureRPCToID (unsigned short data_length, char *data)
{
return rpc_id;
}
int
SecureRPCFromID (XID id, unsigned short *data_lenp, char **datap)
{
return 0;
}
int
SecureRPCRemove (unsigned short data_length, char *data)
{
return 0;
}
#endif /* SECURE_RPC */

View File

@@ -0,0 +1,203 @@
/*
Copyright 1996, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from The Open Group.
*/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <nx-X11/X.h>
#include "os.h"
#include "osdep.h"
#include "dixstruct.h"
#include "swaprep.h"
#ifdef XCSECURITY
#define _SECURITY_SERVER
#include <nx-X11/extensions/security.h>
#endif
static char InvalidPolicyReason[] = "invalid policy specification";
static char PolicyViolationReason[] = "policy violation";
static Bool
AuthCheckSitePolicy(
unsigned short *data_lengthP,
char **dataP,
ClientPtr client,
char **reason)
{
CARD8 *policy = *(CARD8 **)dataP;
int length;
Bool permit;
int nPolicies;
char **sitePolicies;
int nSitePolicies;
Bool found = FALSE;
if ((length = *data_lengthP) < 2) {
*reason = InvalidPolicyReason;
return FALSE;
}
permit = (*policy++ == 0);
nPolicies = (CARD8) *policy++;
length -= 2;
sitePolicies = SecurityGetSitePolicyStrings(&nSitePolicies);
while (nPolicies) {
int strLen, sitePolicy;
if (length == 0) {
*reason = InvalidPolicyReason;
return FALSE;
}
strLen = (CARD8) *policy++;
if (--length < strLen) {
*reason = InvalidPolicyReason;
return FALSE;
}
if (!found)
{
for (sitePolicy = 0; sitePolicy < nSitePolicies; sitePolicy++)
{
char *testPolicy = sitePolicies[sitePolicy];
if ((strLen == strlen(testPolicy)) &&
(strncmp((char *)policy, testPolicy, strLen) == 0))
{
found = TRUE; /* need to continue parsing the policy... */
break;
}
}
}
policy += strLen;
length -= strLen;
nPolicies--;
}
if (found != permit)
{
*reason = PolicyViolationReason;
return FALSE;
}
*data_lengthP = length;
*dataP = (char *)policy;
return TRUE;
}
XID
AuthSecurityCheck (
unsigned short data_length,
char *data,
ClientPtr client,
char **reason)
{
#ifdef XCSECURITY
xConnSetupPrefix csp;
xReq freq;
if (client->clientState == ClientStateCheckedSecurity)
{
*reason = "repeated security check not permitted";
return (XID) -1;
}
else if (data_length > 0)
{
char policy_mask = *data++;
if (--data_length == 1) {
*reason = InvalidPolicyReason;
return (XID) -1;
}
if (policy_mask & 0x01) /* Extensions policy */
{
/* AuthCheckExtensionPolicy(&data_length, &data, client, reason) */
*reason = "security policy not implemented";
return (XID) -1;
}
if (policy_mask & 0x02) /* Site policy */
{
if (!AuthCheckSitePolicy(&data_length, &data, client, reason))
return (XID) -1;
}
if (data_length > 0) { /* did we consume the whole policy? */
*reason = InvalidPolicyReason;
return (XID) -1;
}
}
else if (!GetAccessControl())
{
/*
* The client - possibly the X FireWall Proxy - gave
* no auth data and host-based authorization is turned
* off. In this case, the client should be denied
* access to the X server.
*/
*reason = "server host access control is disabled";
return (XID) -1;
}
client->clientState = ClientStateCheckingSecurity;
csp.success = 2 /* Authenticate */;
csp.lengthReason = 0;
csp.length = 0;
csp.majorVersion = X_PROTOCOL;
csp.minorVersion = X_PROTOCOL_REVISION;
if (client->swapped)
WriteSConnSetupPrefix(client, &csp);
else
WriteToClient(client, sz_xConnSetupPrefix, &csp);
/*
* Next time the client sends the real auth data, we want
* ProcEstablishConnection to be called.
*/
freq.reqType = 1;
freq.length = (sz_xReq + sz_xConnClientPrefix) >> 2;
client->swapped = FALSE;
if (!InsertFakeRequest(client, (char *)&freq, sz_xReq))
{
*reason = "internal error";
return (XID) -1;
}
return (XID) 0;
#else
*reason = "method not supported";
return (XID) -1;
#endif
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE
* FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifdef HAVE_XORG_CONFIG_H
#include <xorg-config.h>
#endif
#include <sys/types.h>
#include <string.h>
/*
* Appends src to string dst of size siz (unlike strncat, siz is the
* full size of dst, not space left). At most siz-1 characters
* will be copied. Always NUL terminates (unless siz <= strlen(dst)).
* Returns strlen(src) + MIN(siz, strlen(initial dst)).
* If retval >= siz, truncation occurred.
*/
size_t
strlcat(char *dst, const char *src, size_t siz)
{
register char *d = dst;
register const char *s = src;
register size_t n = siz;
size_t dlen;
/* Find the end of dst and adjust bytes left but don't go past end */
while (n-- != 0 && *d != '\0')
d++;
dlen = d - dst;
n = siz - dlen;
if (n == 0)
return(dlen + strlen(s));
while (*s != '\0') {
if (n != 1) {
*d++ = *s;
n--;
}
s++;
}
*d = '\0';
return(dlen + (s - src)); /* count does not include NUL */
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE
* FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifdef HAVE_XORG_CONFIG_H
#include <xorg-config.h>
#endif
#include <sys/types.h>
#include <string.h>
/*
* Copy src to string dst of size siz. At most siz-1 characters
* will be copied. Always NUL terminates (unless siz == 0).
* Returns strlen(src); if retval >= siz, truncation occurred.
*/
size_t
strlcpy(char *dst, const char *src, size_t siz)
{
register char *d = dst;
register const char *s = src;
register size_t n = siz;
/* Copy as many bytes as will fit */
if (n != 0 && --n != 0) {
do {
if ((*d++ = *s++) == 0)
break;
} while (--n != 0);
}
/* Not enough room in dst, add NUL and traverse rest of src */
if (n == 0) {
if (siz != 0)
*d = '\0'; /* NUL-terminate dst */
while (*s++)
;
}
return(s - src - 1); /* count does not include NUL */
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) 2014 Google Inc.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <limits.h>
#include <string.h>
#include <nx-X11/Xfuncproto.h>
#include "os.h"
int
timingsafe_memcmp(const void *b1, const void *b2, size_t len)
{
const unsigned char *p1 = b1, *p2 = b2;
size_t i;
int res = 0, done = 0;
for (i = 0; i < len; i++) {
/* lt is -1 if p1[i] < p2[i]; else 0. */
int lt = (p1[i] - p2[i]) >> CHAR_BIT;
/* gt is -1 if p1[i] > p2[i]; else 0. */
int gt = (p2[i] - p1[i]) >> CHAR_BIT;
/* cmp is 1 if p1[i] > p2[i]; -1 if p1[i] < p2[i]; else 0. */
int cmp = lt - gt;
/* set res = cmp if !done. */
res |= cmp & ~done;
/* set done if p1[i] != p2[i]. */
done |= lt | gt;
}
return (res);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,499 @@
/*
Copyright 1988, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from The Open Group.
*/
/*
* XDM-AUTHENTICATION-1 (XDMCP authentication) and
* XDM-AUTHORIZATION-1 (client authorization) protocols
*
* Author: Keith Packard, MIT X Consortium
*/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <stdio.h>
#include <nx-X11/X.h>
#define XSERV_t
#define TRANS_SERVER
#define TRANS_REOPEN
#include <nx-X11/Xtrans/Xtrans.h>
#include "os.h"
#include "osdep.h"
#include "dixstruct.h"
#ifdef HASXDMAUTH
static Bool authFromXDMCP;
#ifdef XDMCP
#include <nx-X11/Xmd.h>
#undef REQUEST
#include <X11/Xdmcp.h>
/* XDM-AUTHENTICATION-1 */
static XdmAuthKeyRec privateKey;
static char XdmAuthenticationName[] = "XDM-AUTHENTICATION-1";
#define XdmAuthenticationNameLen (sizeof XdmAuthenticationName - 1)
static XdmAuthKeyRec global_rho;
static Bool
XdmAuthenticationValidator (ARRAY8Ptr privateData, ARRAY8Ptr incomingData,
xdmOpCode packet_type)
{
XdmAuthKeyPtr incoming;
XdmcpUnwrap (incomingData->data, (unsigned char *)&privateKey,
incomingData->data,incomingData->length);
if (packet_type == ACCEPT) {
if (incomingData->length != 8)
return FALSE;
incoming = (XdmAuthKeyPtr) incomingData->data;
XdmcpDecrementKey (incoming);
return XdmcpCompareKeys (incoming, &global_rho);
}
return FALSE;
}
static Bool
XdmAuthenticationGenerator (ARRAY8Ptr privateData, ARRAY8Ptr outgoingData,
xdmOpCode packet_type)
{
outgoingData->length = 0;
outgoingData->data = 0;
if (packet_type == REQUEST) {
if (XdmcpAllocARRAY8 (outgoingData, 8))
XdmcpWrap ((unsigned char *)&global_rho, (unsigned char *)&privateKey,
outgoingData->data, 8);
}
return TRUE;
}
static Bool
XdmAuthenticationAddAuth (int name_len, char *name,
int data_len, char *data)
{
Bool ret;
XdmcpUnwrap ((unsigned char *)data, (unsigned char *)&privateKey,
(unsigned char *)data, data_len);
authFromXDMCP = TRUE;
ret = AddAuthorization (name_len, name, data_len, data);
authFromXDMCP = FALSE;
return ret;
}
#define atox(c) ('0' <= c && c <= '9' ? c - '0' : \
'a' <= c && c <= 'f' ? c - 'a' + 10 : \
'A' <= c && c <= 'F' ? c - 'A' + 10 : -1)
static int
HexToBinary (char *in, char *out, int len)
{
int top, bottom;
while (len > 0)
{
top = atox(in[0]);
if (top == -1)
return 0;
bottom = atox(in[1]);
if (bottom == -1)
return 0;
*out++ = (top << 4) | bottom;
in += 2;
len -= 2;
}
if (len)
return 0;
*out++ = '\0';
return 1;
}
void
XdmAuthenticationInit (char *cookie, int cookie_len)
{
bzero (privateKey.data, 8);
if (!strncmp (cookie, "0x", 2) || !strncmp (cookie, "0X", 2))
{
if (cookie_len > 2 + 2 * 8)
cookie_len = 2 + 2 * 8;
HexToBinary (cookie + 2, (char *)privateKey.data, cookie_len - 2);
}
else
{
if (cookie_len > 7)
cookie_len = 7;
memmove (privateKey.data + 1, cookie, cookie_len);
}
XdmcpGenerateKey (&global_rho);
XdmcpRegisterAuthentication (XdmAuthenticationName, XdmAuthenticationNameLen,
(char *)&global_rho,
sizeof (global_rho),
(ValidatorFunc)XdmAuthenticationValidator,
(GeneratorFunc)XdmAuthenticationGenerator,
(AddAuthorFunc)XdmAuthenticationAddAuth);
}
#endif /* XDMCP */
/* XDM-AUTHORIZATION-1 */
typedef struct _XdmAuthorization {
struct _XdmAuthorization *next;
XdmAuthKeyRec rho;
XdmAuthKeyRec key;
XID id;
} XdmAuthorizationRec, *XdmAuthorizationPtr;
static XdmAuthorizationPtr xdmAuth;
typedef struct _XdmClientAuth {
struct _XdmClientAuth *next;
XdmAuthKeyRec rho;
char client[6];
long time;
} XdmClientAuthRec, *XdmClientAuthPtr;
static XdmClientAuthPtr xdmClients;
static long clockOffset;
static Bool gotClock;
#define TwentyMinutes (20 * 60)
#define TwentyFiveMinutes (25 * 60)
static Bool
XdmClientAuthCompare (XdmClientAuthPtr a, XdmClientAuthPtr b)
{
int i;
if (!XdmcpCompareKeys (&a->rho, &b->rho))
return FALSE;
for (i = 0; i < 6; i++)
if (a->client[i] != b->client[i])
return FALSE;
return a->time == b->time;
}
static void
XdmClientAuthDecode (unsigned char *plain, XdmClientAuthPtr auth)
{
int i, j;
j = 0;
for (i = 0; i < 8; i++)
{
auth->rho.data[i] = plain[j];
++j;
}
for (i = 0; i < 6; i++)
{
auth->client[i] = plain[j];
++j;
}
auth->time = 0;
for (i = 0; i < 4; i++)
{
auth->time |= plain[j] << ((3 - i) << 3);
j++;
}
}
static void
XdmClientAuthTimeout (long now)
{
XdmClientAuthPtr client, next, prev;
prev = 0;
for (client = xdmClients; client; client=next)
{
next = client->next;
if (abs (now - client->time) > TwentyFiveMinutes)
{
if (prev)
prev->next = next;
else
xdmClients = next;
free (client);
}
else
prev = client;
}
}
static XdmClientAuthPtr
XdmAuthorizationValidate (unsigned char *plain, int length,
XdmAuthKeyPtr rho, ClientPtr xclient, char **reason)
{
XdmClientAuthPtr client, existing;
long now;
int i;
if (length != (192 / 8)) {
if (reason)
*reason = "Bad XDM authorization key length";
return NULL;
}
client = (XdmClientAuthPtr) malloc (sizeof (XdmClientAuthRec));
if (!client)
return NULL;
XdmClientAuthDecode (plain, client);
if (!XdmcpCompareKeys (&client->rho, rho))
{
free (client);
if (reason)
*reason = "Invalid XDM-AUTHORIZATION-1 key (failed key comparison)";
return NULL;
}
for (i = 18; i < 24; i++)
if (plain[i] != 0) {
free (client);
if (reason)
*reason = "Invalid XDM-AUTHORIZATION-1 key (failed NULL check)";
return NULL;
}
if (xclient) {
int family, addr_len;
Xtransaddr *addr;
if (_XSERVTransGetPeerAddr(((OsCommPtr)xclient->osPrivate)->trans_conn,
&family, &addr_len, &addr) == 0
&& _XSERVTransConvertAddress(&family, &addr_len, &addr) == 0) {
#if defined(TCPCONN)
if (family == FamilyInternet &&
memcmp((char *)addr, client->client, 4) != 0) {
free (client);
free (addr);
if (reason)
*reason = "Invalid XDM-AUTHORIZATION-1 key (failed address comparison)";
return NULL;
}
#endif
free (addr);
}
}
now = time(0);
if (!gotClock)
{
clockOffset = client->time - now;
gotClock = TRUE;
}
now += clockOffset;
XdmClientAuthTimeout (now);
if (abs (client->time - now) > TwentyMinutes)
{
free (client);
if (reason)
*reason = "Excessive XDM-AUTHORIZATION-1 time offset";
return NULL;
}
for (existing = xdmClients; existing; existing=existing->next)
{
if (XdmClientAuthCompare (existing, client))
{
free (client);
if (reason)
*reason = "XDM authorization key matches an existing client!";
return NULL;
}
}
return client;
}
int
XdmAddCookie (unsigned short data_length, char *data, XID id)
{
XdmAuthorizationPtr new;
unsigned char *rho_bits, *key_bits;
switch (data_length)
{
case 16: /* auth from files is 16 bytes long */
#ifdef XDMCP
if (authFromXDMCP)
{
/* R5 xdm sent bogus authorization data in the accept packet,
* but we can recover */
rho_bits = global_rho.data;
key_bits = (unsigned char *) data;
key_bits[0] = '\0';
}
else
#endif
{
rho_bits = (unsigned char *) data;
key_bits = (unsigned char *) (data + 8);
}
break;
#ifdef XDMCP
case 8: /* auth from XDMCP is 8 bytes long */
rho_bits = global_rho.data;
key_bits = (unsigned char *) data;
break;
#endif
default:
return 0;
}
/* the first octet of the key must be zero */
if (key_bits[0] != '\0')
return 0;
new = (XdmAuthorizationPtr) malloc (sizeof (XdmAuthorizationRec));
if (!new)
return 0;
new->next = xdmAuth;
xdmAuth = new;
memmove (new->key.data, key_bits, (int) 8);
memmove (new->rho.data, rho_bits, (int) 8);
new->id = id;
return 1;
}
XID
XdmCheckCookie (unsigned short cookie_length, char *cookie,
ClientPtr xclient, char **reason)
{
XdmAuthorizationPtr auth;
XdmClientAuthPtr client;
unsigned char *plain;
/* Auth packets must be a multiple of 8 bytes long */
if (cookie_length & 7)
return (XID) -1;
plain = (unsigned char *) malloc (cookie_length);
if (!plain)
return (XID) -1;
for (auth = xdmAuth; auth; auth=auth->next) {
XdmcpUnwrap ((unsigned char *)cookie, (unsigned char *)&auth->key, plain, cookie_length);
if ((client = XdmAuthorizationValidate (plain, cookie_length, &auth->rho, xclient, reason)) != NULL)
{
client->next = xdmClients;
xdmClients = client;
free (plain);
return auth->id;
}
}
free (plain);
return (XID) -1;
}
int
XdmResetCookie (void)
{
XdmAuthorizationPtr auth, next_auth;
XdmClientAuthPtr client, next_client;
for (auth = xdmAuth; auth; auth=next_auth)
{
next_auth = auth->next;
free (auth);
}
xdmAuth = 0;
for (client = xdmClients; client; client=next_client)
{
next_client = client->next;
free (client);
}
xdmClients = (XdmClientAuthPtr) 0;
return 1;
}
XID
XdmToID (unsigned short cookie_length, char *cookie)
{
XdmAuthorizationPtr auth;
XdmClientAuthPtr client;
unsigned char *plain;
plain = (unsigned char *) malloc (cookie_length);
if (!plain)
return (XID) -1;
for (auth = xdmAuth; auth; auth=auth->next) {
XdmcpUnwrap ((unsigned char *)cookie, (unsigned char *)&auth->key, plain, cookie_length);
if ((client = XdmAuthorizationValidate (plain, cookie_length, &auth->rho, NULL, NULL)) != NULL)
{
free (client);
free (cookie);
free (plain);
return auth->id;
}
}
free (cookie);
free (plain);
return (XID) -1;
}
int
XdmFromID (XID id, unsigned short *data_lenp, char **datap)
{
XdmAuthorizationPtr auth;
for (auth = xdmAuth; auth; auth=auth->next) {
if (id == auth->id) {
*data_lenp = 16;
*datap = (char *) &auth->rho;
return 1;
}
}
return 0;
}
int
XdmRemoveCookie (unsigned short data_length, char *data)
{
XdmAuthorizationPtr auth;
XdmAuthKeyPtr key_bits, rho_bits;
switch (data_length)
{
case 16:
rho_bits = (XdmAuthKeyPtr) data;
key_bits = (XdmAuthKeyPtr) (data + 8);
break;
#ifdef XDMCP
case 8:
rho_bits = &global_rho;
key_bits = (XdmAuthKeyPtr) data;
break;
#endif
default:
return 0;
}
for (auth = xdmAuth; auth; auth=auth->next) {
if (XdmcpCompareKeys (rho_bits, &auth->rho) &&
XdmcpCompareKeys (key_bits, &auth->key))
{
xdmAuth = auth->next;
free (auth);
return 1;
}
}
return 0;
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,278 @@
/**
* @file
*
* @section DESCRIPTION
*
* These functions provide a portable implementation of the common (but not
* yet universal) asprintf & vasprintf routines to allocate a buffer big
* enough to sprintf the arguments to. The XNF variants terminate the server
* if the allocation fails.
*/
/*
* Copyright (c) 2004 Alexander Gottwald
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name(s) of the above copyright
* holders shall not be used in advertising or otherwise to promote the sale,
* use or other dealings in this Software without prior written authorization.
*/
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <nx-X11/Xos.h>
#include "os.h"
#include <stdarg.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#ifdef asprintf
#undef asprintf
#endif
#ifdef vasprintf
#undef vasprintf
#endif
#ifndef va_copy
#ifdef __va_copy
#define va_copy __va_copy
#else
#error "no working va_copy was found"
#endif
#endif
/**
* Varargs sprintf that allocates a string buffer the right size for
* the pattern & data provided and prints the requested data to it.
*
* @param ret Pointer to which the newly allocated buffer is written
* (contents undefined on error)
* @param format printf style format string
* @param va variable argument list
* @return size of allocated buffer, or -1 on error.
*/
int
Xvasprintf(char **ret, const char *_X_RESTRICT_KYWD format, va_list va)
{
#ifdef HAVE_VASPRINTF
return vasprintf(ret, format, va);
#else
int size;
va_list va2;
va_copy(va2, va);
size = vsnprintf(NULL, 0, format, va2);
va_end(va2);
*ret = malloc(size + 1);
if (*ret == NULL)
return -1;
vsnprintf(*ret, size + 1, format, va);
(*ret)[size] = 0;
return size;
#endif
}
#ifndef HAVE_VASPRINTF
#define vasprintf Xvasprintf
#endif
/**
* sprintf that allocates a string buffer the right size for
* the pattern & data provided and prints the requested data to it.
*
* @param ret Pointer to which the newly allocated buffer is written
* (contents undefined on error)
* @param format printf style format string
* @param ... arguments for specified format
* @return size of allocated buffer, or -1 on error.
*/
int
Xasprintf(char **ret, const char *_X_RESTRICT_KYWD format, ...)
{
int size;
va_list va;
va_start(va, format);
size = vasprintf(ret, format, va);
va_end(va);
return size;
}
/**
* Varargs sprintf that allocates a string buffer the right size for
* the pattern & data provided and prints the requested data to it.
* On failure, issues a FatalError message and aborts the server.
*
* @param ret Pointer to which the newly allocated buffer is written
* (contents undefined on error)
* @param format printf style format string
* @param va variable argument list
* @return size of allocated buffer
*/
int
XNFvasprintf(char **ret, const char *_X_RESTRICT_KYWD format, va_list va)
{
int size = vasprintf(ret, format, va);
if ((size == -1) || (*ret == NULL)) {
FatalError("XNFvasprintf failed: %s", strerror(errno));
}
return size;
}
/**
* sprintf that allocates a string buffer the right size for
* the pattern & data provided and prints the requested data to it.
* On failure, issues a FatalError message and aborts the server.
*
* @param ret Pointer to which the newly allocated buffer is written
* (contents undefined on error)
* @param format printf style format string
* @param ... arguments for specified format
* @return size of allocated buffer
*/
int
XNFasprintf(char **ret, const char *_X_RESTRICT_KYWD format, ...)
{
int size;
va_list va;
va_start(va, format);
size = XNFvasprintf(ret, format, va);
va_end(va);
return size;
}
/**
* Varargs snprintf that returns the actual number of bytes (excluding final
* '\0') that were copied into the buffer.
* This is opposed to the normal sprintf() usually returns the number of bytes
* that would have been written.
*
* @param s buffer to copy into
* @param n size of buffer s
* @param format printf style format string
* @param va variable argument list
* @return number of bytes actually copied, excluding final '\0'
*/
int
Xvscnprintf(char *s, int n, const char *format, va_list args)
{
int x;
if (n == 0)
return 0;
x = vsnprintf(s, n , format, args);
return (x >= n) ? (n - 1) : x;
}
/**
* snprintf that returns the actual number of bytes (excluding final '\0') that
* were copied into the buffer.
* This is opposed to the normal sprintf() usually returns the number of bytes
* that would have been written.
*
* @param s buffer to copy into
* @param n size of buffer s
* @param format printf style format string
* @param ... arguments for specified format
* @return number of bytes actually copied, excluding final '\0'
*/
int Xscnprintf(char *s, int n, const char *format, ...)
{
int x;
va_list ap;
va_start(ap, format);
x = Xvscnprintf(s, n, format, ap);
va_end(ap);
return x;
}
/* Old api, now deprecated, may be removed in the future */
char *
Xvprintf(const char *format, va_list va)
{
char *ret;
if (vasprintf(&ret, format, va) == -1)
ret = NULL;
return ret;
}
char *
Xprintf(const char *format, ...)
{
char *ret;
va_list va;
va_start(va, format);
if (vasprintf(&ret, format, va) == -1)
ret = NULL;
va_end(va);
return ret;
}
char *
XNFvprintf(const char *format, va_list va)
{
char *ret;
XNFvasprintf(&ret, format, va);
return ret;
}
char *
XNFprintf(const char *format, ...)
{
char *ret;
va_list va;
va_start(va, format);
XNFvasprintf(&ret, format, va);
va_end(va);
return ret;
}

View File

@@ -0,0 +1,17 @@
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <nx-X11/Xfuncproto.h>
/* ErrorF is used by xtrans */
#ifndef HAVE_DIX_CONFIG_H
extern _X_EXPORT void
ErrorF(const char *f, ...)
_X_ATTRIBUTE_PRINTF(1, 2);
#endif
#define TRANS_REOPEN
#define TRANS_SERVER
#define XSERV_t
#include <nx-X11/Xtrans/transport.c>