tsolprotocol.c revision 633
606N/A/* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
0N/A *
0N/A * Permission is hereby granted, free of charge, to any person obtaining a
0N/A * copy of this software and associated documentation files (the
0N/A * "Software"), to deal in the Software without restriction, including
0N/A * without limitation the rights to use, copy, modify, merge, publish,
0N/A * distribute, and/or sell copies of the Software, and to permit persons
0N/A * to whom the Software is furnished to do so, provided that the above
0N/A * copyright notice(s) and this permission notice appear in all copies of
0N/A * the Software and that both the above copyright notice(s) and this
0N/A * permission notice appear in supporting documentation.
0N/A *
0N/A * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
0N/A * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
0N/A * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
0N/A * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
0N/A * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
0N/A * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
0N/A * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
0N/A * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
0N/A * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
0N/A *
0N/A * Except as contained in this notice, the name of a copyright holder
0N/A * shall not be used in advertising or otherwise to promote the sale, use
0N/A * or other dealings in this Software without prior written authorization
0N/A * of the copyright holder.
606N/A */
606N/A
633N/A#pragma ident "@(#)tsolprotocol.c 1.27 09/02/10 SMI"
606N/A
606N/A#ifdef HAVE_DIX_CONFIG_H
606N/A#include <dix-config.h>
606N/A#endif
0N/A
0N/A#include <sys/param.h>
0N/A#include <fcntl.h>
0N/A#include <sys/types.h>
0N/A#include <sys/stat.h>
0N/A#include <unistd.h>
0N/A#include <ucred.h>
0N/A#include <pwd.h>
0N/A#include <strings.h>
0N/A#include <sys/wait.h>
196N/A#include "auditwrite.h"
0N/A#include <bsm/libbsm.h>
0N/A#include <bsm/audit_uevents.h>
0N/A#include "tsol.h"
0N/A
0N/A#include "inputstr.h"
0N/A
0N/A#define NEED_REPLIES
0N/A
0N/A#include "selection.h"
0N/A#include "osdep.h"
0N/A#include "tsolpolicy.h"
0N/A#include "swaprep.h"
0N/A#include "swapreq.h"
0N/A#include "servermd.h"
0N/A#ifdef PANORAMIX
0N/A#include "../Xext/panoramiXsrv.h"
0N/A#endif
0N/A#ifdef XCSECURITY
606N/A#include "../Xext/securitysrv.h"
0N/A#endif
606N/A#include "xace.h"
606N/A#include "xacestr.h"
606N/A
0N/A/*
0N/A * The event # here match those in /usr/include/bsm/audit_uevents.h.
0N/A * Changes in one should go with corresponding changes in another.
0N/A */
0N/A
0N/A#define MAX_AUDIT_EVENTS 100
0N/A
0N/Aint audit_eventsid[100][2] = {
606N/A { X_CreateWindow, AUE_CreateWindow },
606N/A { X_ChangeWindowAttributes, AUE_ChangeWindowAttributes },
606N/A { X_GetWindowAttributes, AUE_GetWindowAttributes },
606N/A { X_DestroyWindow, AUE_DestroyWindow },
606N/A { X_DestroySubwindows, AUE_DestroySubwindows },
606N/A { X_ChangeSaveSet, AUE_ChangeSaveSet },
606N/A { X_ReparentWindow, AUE_ReparentWindow },
606N/A { X_MapWindow, AUE_MapWindow },
606N/A { X_MapSubwindows, AUE_MapSubwindows },
606N/A { X_UnmapWindow, AUE_UnmapWindow },
606N/A { X_UnmapSubwindows, AUE_UnmapSubwindows },
606N/A { X_ConfigureWindow, AUE_ConfigureWindow },
606N/A { X_CirculateWindow, AUE_CirculateWindow },
606N/A { X_GetGeometry, AUE_GetGeometry },
606N/A { X_QueryTree, AUE_QueryTree },
606N/A { X_InternAtom, AUE_InternAtom },
606N/A { X_GetAtomName, AUE_GetAtomName },
606N/A { X_ChangeProperty, AUE_ChangeProperty },
606N/A { X_DeleteProperty, AUE_DeleteProperty },
606N/A { X_GetProperty, AUE_GetProperty },
606N/A { X_ListProperties, AUE_ListProperties },
606N/A { X_SetSelectionOwner, AUE_SetSelectionOwner },
606N/A { X_GetSelectionOwner, AUE_GetSelectionOwner },
606N/A { X_ConvertSelection, AUE_ConvertSelection },
606N/A { X_SendEvent, AUE_SendEvent },
606N/A { X_GrabPointer, AUE_GrabPointer },
606N/A { X_UngrabPointer, AUE_UngrabPointer },
606N/A { X_GrabButton, AUE_GrabButton },
606N/A { X_UngrabButton, AUE_UngrabButton },
606N/A { X_ChangeActivePointerGrab, AUE_ChangeActivePointerGrab },
606N/A { X_GrabKeyboard, AUE_GrabKeyboard },
606N/A { X_UngrabKeyboard, AUE_UngrabKeyboard },
606N/A { X_GrabKey, AUE_GrabKey },
606N/A { X_UngrabKey, AUE_UngrabKey },
606N/A { X_GrabServer, AUE_GrabServer },
606N/A { X_UngrabServer, AUE_UngrabServer },
606N/A { X_QueryPointer, AUE_QueryPointer },
606N/A { X_GetMotionEvents, AUE_GetMotionEvents },
606N/A { X_TranslateCoords, AUE_TranslateCoords },
606N/A { X_WarpPointer, AUE_WarpPointer },
606N/A { X_SetInputFocus, AUE_SetInputFocus },
606N/A { X_GetInputFocus, AUE_GetInputFocus },
606N/A { X_QueryKeymap, AUE_QueryKeymap },
606N/A { X_SetFontPath, AUE_SetFontPath },
606N/A { X_FreePixmap, AUE_FreePixmap },
606N/A { X_ChangeGC, AUE_ChangeGC },
606N/A { X_CopyGC, AUE_CopyGC },
606N/A { X_SetDashes, AUE_SetDashes },
606N/A { X_SetClipRectangles, AUE_SetClipRectangles },
606N/A { X_FreeGC, AUE_FreeGC },
606N/A { X_ClearArea, AUE_ClearArea },
606N/A { X_CopyArea, AUE_CopyArea },
606N/A { X_CopyPlane, AUE_CopyPlane },
606N/A { X_PolyPoint, AUE_PolyPoint },
606N/A { X_PolyLine, AUE_PolyLine },
606N/A { X_PolySegment, AUE_PolySegment },
606N/A { X_PolyRectangle, AUE_PolyRectangle },
606N/A { X_PolyArc, AUE_PolyArc },
606N/A { X_FillPoly, AUE_FillPolygon },
606N/A { X_PolyFillRectangle, AUE_PolyFillRectangle },
606N/A { X_PolyFillArc, AUE_PolyFillArc },
606N/A { X_PutImage, AUE_PutImage },
606N/A { X_GetImage, AUE_GetImage },
606N/A { X_PolyText8, AUE_PolyText8 },
606N/A { X_PolyText16, AUE_PolyText16 },
606N/A { X_ImageText8, AUE_ImageText8 },
606N/A { X_ImageText16, AUE_ImageText16 },
606N/A { X_CreateColormap, AUE_CreateColormap },
606N/A { X_FreeColormap, AUE_FreeColormap },
606N/A { X_CopyColormapAndFree, AUE_CopyColormapAndFree },
606N/A { X_InstallColormap, AUE_InstallColormap },
606N/A { X_UninstallColormap, AUE_UninstallColormap },
606N/A { X_ListInstalledColormaps, AUE_ListInstalledColormaps },
606N/A { X_AllocColor, AUE_AllocColor },
606N/A { X_AllocNamedColor, AUE_AllocNamedColor },
606N/A { X_AllocColorCells, AUE_AllocColorCells },
606N/A { X_AllocColorPlanes, AUE_AllocColorPlanes },
606N/A { X_FreeColors, AUE_FreeColors },
606N/A { X_StoreColors, AUE_StoreColors },
606N/A { X_StoreNamedColor, AUE_StoreNamedColor },
606N/A { X_QueryColors, AUE_QueryColors },
606N/A { X_LookupColor, AUE_LookupColor },
606N/A { X_CreateCursor, AUE_CreateCursor },
606N/A { X_CreateGlyphCursor, AUE_CreateGlyphCursor },
606N/A { X_FreeCursor, AUE_FreeCursor },
606N/A { X_RecolorCursor, AUE_RecolorCursor },
606N/A { X_ChangeKeyboardMapping, AUE_ChangeKeyboardMapping },
606N/A { X_ChangeKeyboardControl, AUE_ChangeKeyboardControl },
606N/A { X_Bell, AUE_Bell },
606N/A { X_ChangePointerControl, AUE_ChangePointerControl },
606N/A { X_SetScreenSaver, AUE_SetScreenSaver },
606N/A { X_ChangeHosts, AUE_ChangeHosts },
606N/A { X_SetAccessControl, AUE_SetAccessControl },
606N/A { X_SetCloseDownMode, AUE_SetCloseDownMode },
606N/A { X_KillClient, AUE_KillClient },
606N/A { X_RotateProperties, AUE_RotateProperties },
606N/A { X_ForceScreenSaver, AUE_ForceScreenSaver },
606N/A { X_SetPointerMapping, AUE_SetPointerMapping },
606N/A { X_SetModifierMapping, AUE_SetModifierMapping },
606N/A { X_NoOperation, AUE_XExtensions }
0N/A};
633N/A
633N/Astatic Atom MakeTSOLAtom(ClientPtr client, char *string,
633N/A unsigned int len, Bool makeit);
0N/A
0N/A#define INITIAL_TSOL_NODELENGTH 1500
0N/A
0N/Astatic int tsol_sel_agnt = -1; /* index this to CurrentSelection to get seln */
0N/A
0N/A/*
0N/A * Get number of atoms defined in the system
0N/A */
0N/Astatic Atom
606N/AGetLastAtom(void)
0N/A{
0N/A Atom a = (Atom) 1; /* atoms start at 1 */
0N/A
0N/A while (ValidAtom(a)) {
0N/A a++;
0N/A }
0N/A
0N/A return (--a);
0N/A}
0N/A
0N/A/*
0N/A * Update Tsol info for atoms. This function gets
0N/A * called typically during initialization. But, it could also get
0N/A * called if some atoms are created internally by server.
0N/A */
0N/Avoid
606N/AUpdateTsolNode(void)
0N/A{
0N/A Atom lastAtom = GetLastAtom();
0N/A Atom ia;
0N/A
0N/A /* Update may not be needed */
0N/A if (lastAtom == None || lastAtom == tsol_lastAtom)
0N/A return;
606N/A
0N/A if (tsol_node == NULL) {
0N/A int newsize = (lastAtom > INITIAL_TSOL_NODELENGTH ? lastAtom : INITIAL_TSOL_NODELENGTH);
0N/A
0N/A /* Initialize */
0N/A tsol_node = (TsolNodePtr )xalloc((newsize + 1) * sizeof(TsolNodeRec));
0N/A tsol_nodelength = newsize;
0N/A
0N/A if (tsol_node != NULL) {
0N/A /* Atom id 0 is invalid */
0N/A tsol_lastAtom = 0;
0N/A tsol_node[0].flags = 0;
0N/A tsol_node[0].slcount = 0;
0N/A tsol_node[0].sl = NULL;
0N/A tsol_node[0].slsize = 0;
0N/A tsol_node[0].IsSpecial = 0;
0N/A }
0N/A }
0N/A
0N/A if (tsol_nodelength <= lastAtom) {
0N/A tsol_node = (TsolNodePtr )xrealloc(tsol_node, (lastAtom + 1) * sizeof(TsolNodeRec));
0N/A tsol_nodelength = lastAtom + 1;
0N/A }
0N/A
0N/A if (tsol_node == NULL) {
0N/A ErrorF("Cannot allocate memory for Tsol node\n");
0N/A return;
0N/A }
0N/A
606N/A /*
0N/A * Initialize the tsol node for each atom
0N/A */
0N/A for (ia = tsol_lastAtom + 1; ia <= lastAtom; ia++) {
633N/A const char *atomname = NameForAtom(ia);
0N/A
0N/A tsol_node[ia].slcount = 0;
0N/A tsol_node[ia].sl = NULL;
0N/A tsol_node[ia].slsize= 0;
0N/A tsol_node[ia].flags = MatchTsolConfig(atomname, strlen(atomname));
0N/A tsol_node[ia].IsSpecial = SpecialName(atomname, strlen(atomname));
0N/A
0N/A }
0N/A tsol_lastAtom = lastAtom;
0N/A}
0N/A
0N/Aint
606N/AProcTsolInternAtom(ClientPtr client)
0N/A{
0N/A Atom atom;
0N/A char *tchar;
0N/A REQUEST(xInternAtomReq);
0N/A
0N/A REQUEST_FIXED_SIZE(xInternAtomReq, stuff->nbytes);
0N/A if ((stuff->onlyIfExists != xTrue) && (stuff->onlyIfExists != xFalse))
0N/A {
0N/A client->errorValue = stuff->onlyIfExists;
0N/A return(BadValue);
0N/A }
0N/A tchar = (char *) &stuff[1];
0N/A atom = MakeTSOLAtom(client, tchar, stuff->nbytes, !stuff->onlyIfExists);
0N/A if (atom != BAD_RESOURCE)
0N/A {
0N/A xInternAtomReply reply;
0N/A reply.type = X_Reply;
0N/A reply.length = 0;
0N/A reply.sequenceNumber = client->sequence;
0N/A reply.atom = atom;
0N/A WriteReplyToClient(client, sizeof(xInternAtomReply), &reply);
0N/A return(client->noClientException);
0N/A }
0N/A else
0N/A return (BadAlloc);
0N/A}
0N/A
633N/A#ifdef UNUSED
0N/Aint
606N/AProcTsolGetAtomName(ClientPtr client)
0N/A{
0N/A char *str;
0N/A xGetAtomNameReply reply;
0N/A int len;
0N/A REQUEST(xResourceReq);
0N/A
0N/A REQUEST_SIZE_MATCH(xResourceReq);
0N/A /* TBD: NameForTSOLAtom */
0N/A if ( (str = NameForAtom(stuff->id)) )
0N/A {
0N/A len = strlen(str);
0N/A reply.type = X_Reply;
0N/A reply.length = (len + 3) >> 2;
0N/A reply.sequenceNumber = client->sequence;
0N/A reply.nameLength = len;
0N/A WriteReplyToClient(client, sizeof(xGetAtomNameReply), &reply);
0N/A (void)WriteToClient(client, len, str);
0N/A return(client->noClientException);
0N/A }
606N/A else
606N/A {
0N/A client->errorValue = stuff->id;
0N/A return (BadAtom);
0N/A }
0N/A}
633N/A#endif /* UNUSED */
633N/A
633N/Astatic Atom
0N/AMakeTSOLAtom(ClientPtr client, char *string, unsigned int len, Bool makeit)
0N/A{
0N/A TsolNodePtr tndp;
0N/A int k;
0N/A int newsize;
0N/A Atom newAtom;
0N/A
0N/A TsolInfoPtr tsolinfo;
0N/A
0N/A /* Make the atom as usual */
0N/A newAtom = MakeAtom(string, len, makeit);
0N/A if (newAtom == None || newAtom == BAD_RESOURCE) {
0N/A return (newAtom);
0N/A }
0N/A
0N/A tsolinfo = GetClientTsolInfo(client);
0N/A
0N/A
0N/A /* tsol node info already present? */
0N/A if (newAtom <= tsol_lastAtom) {
0N/A tndp = &(tsol_node[newAtom]);
0N/A
0N/A /* public atoms have null sl */
0N/A if (tndp->sl == NULL) {
0N/A return newAtom;
0N/A }
0N/A
0N/A /* private atoms must have a matching sl */
0N/A for (k = 0; k < tndp->slcount; k++) {
0N/A if (tsolinfo->sl == tndp->sl[k]) {
0N/A return newAtom; /* found one */
0N/A }
0N/A }
0N/A
0N/A } else {
0N/A /* tsol node table not big enough, expand it */
0N/A UpdateTsolNode();
0N/A tndp = &(tsol_node[newAtom]);
0N/A }
0N/A
0N/A /* Allocate storage for sl if needed */
0N/A if (tndp->sl == NULL) {
0N/A tndp->sl = (bslabel_t **)xalloc(NODE_SLSIZE * (sizeof(bslabel_t *)));
0N/A tndp->slcount = 0;
0N/A tndp->slsize = NODE_SLSIZE;
0N/A }
0N/A
0N/A /* Expand storage space for sl if needed */
0N/A if (tndp->slsize < tndp->slcount) {
0N/A newsize = tndp->slsize + NODE_SLSIZE;
0N/A tndp->sl = (bslabel_t **)xrealloc(tndp->sl, newsize * (sizeof(bslabel_t *)));
0N/A tndp->slsize = newsize;
0N/A }
0N/A
0N/A if (tndp->sl == NULL) {
0N/A ErrorF("Not enough memory for atoms\n");
0N/A return (Atom)None;
0N/A }
0N/A
0N/A /* Store client's sl */
0N/A tndp->sl[tndp->slcount] = tsolinfo->sl;
0N/A tndp->slcount++;
0N/A
0N/A return newAtom;
0N/A}
0N/A
0N/A
0N/Aint
606N/AProcTsolSetSelectionOwner(ClientPtr client)
0N/A{
606N/A WindowPtr pWin = NULL;
0N/A TimeStamp time;
606N/A Selection *pSel;
606N/A int rc;
0N/A
0N/A#ifdef TSOL
0N/A TsolSelnPtr tsolseln = NULL;
0N/A TsolSelnPtr prevtsolseln = NULL;
0N/A TsolInfoPtr tsolinfo = GetClientTsolInfo(client);
0N/A#endif /* TSOL */
0N/A
606N/A REQUEST(xSetSelectionOwnerReq);
0N/A REQUEST_SIZE_MATCH(xSetSelectionOwnerReq);
606N/A
0N/A UpdateCurrentTime();
0N/A time = ClientTimeToServerTime(stuff->time);
0N/A
0N/A /* If the client's time stamp is in the future relative to the server's
0N/A time stamp, do not set the selection, just return success. */
0N/A if (CompareTimeStamps(time, currentTime) == LATER)
0N/A return Success;
606N/A
0N/A if (stuff->window != None)
0N/A {
606N/A rc = dixLookupWindow(&pWin, stuff->window, client, DixSetAttrAccess);
606N/A if (rc != Success)
606N/A return rc;
606N/A }
606N/A if (!ValidAtom(stuff->selection)) {
606N/A client->errorValue = stuff->selection;
606N/A return BadAtom;
0N/A }
606N/A
606N/A /*
606N/A * First, see if the selection is already set...
606N/A */
606N/A rc = dixLookupSelection(&pSel, stuff->selection, client, DixSetAttrAccess);
606N/A
606N/A if (rc == Success) {
606N/A xEvent event;
606N/A
606N/A#ifdef TSOL
0N/A int i = 0;
0N/A
606N/A for (pSel = CurrentSelections;
606N/A (pSel != NULL) && pSel->selection != stuff->selection;
606N/A pSel = pSel->next) {
606N/A i++;
606N/A }
606N/A
0N/A /*
0N/A * special processing for selection agent. Just note
0N/A * the owner of this special selection
0N/A */
0N/A if (stuff->selection == MakeAtom("_TSOL_SEL_AGNT", 14, 1))
0N/A {
0N/A if (HasWinSelection(tsolinfo))
0N/A {
606N/A if (tsolinfo->flags & TSOL_AUDITEVENT)
606N/A auditwrite(AW_USEOFPRIV, 1, PRIV_WIN_SELECTION,
606N/A AW_APPEND, AW_END);
606N/A tsol_sel_agnt = i; /* owner of this seln */
0N/A }
0N/A else
0N/A {
606N/A if (tsolinfo->flags & TSOL_AUDITEVENT)
606N/A auditwrite(AW_USEOFPRIV, 0, PRIV_WIN_SELECTION,
606N/A AW_APPEND, AW_END);
606N/A client->errorValue = stuff->selection;
606N/A return(BadAtom);
0N/A }
606N/A }
606N/A
606N/A /* for poly-selections, search further to see if sl,uid match */
606N/A tsolseln = *(TsolSelectionPriv(pSel));
606N/A if (PolySelection(pSel->selection))
606N/A {
606N/A prevtsolseln = tsolseln;
606N/A while (tsolseln)
0N/A {
606N/A if (tsolseln->uid == tsolinfo->uid &&
606N/A tsolseln->sl == tsolinfo->sl)
606N/A break; /* match found */
606N/A prevtsolseln = tsolseln;
606N/A tsolseln = tsolseln->next;
0N/A }
606N/A }
606N/A if (PolySelection(pSel->selection) && tsolseln)
606N/A {
606N/A if (CompareTimeStamps(time, tsolseln->lastTimeChanged)
0N/A == EARLIER)
0N/A return Success;
606N/A if (tsolseln->client &&
606N/A (!pWin || (tsolseln->client != client)))
0N/A {
0N/A event.u.u.type = SelectionClear;
0N/A event.u.selectionClear.time = time.milliseconds;
606N/A event.u.selectionClear.window = tsolseln->window;
606N/A event.u.selectionClear.atom = pSel->selection;
606N/A (void)TryClientEvents (tsolseln->client,
606N/A &event,
606N/A 1,
606N/A NoEventMask,
606N/A NoEventMask /* CantBeFiltered */,
606N/A NullGrab);
0N/A }
0N/A }
606N/A else if (tsolseln)
0N/A {
606N/A /* we use the existing code. So we left it unindented */
606N/A#endif /* TSOL */
606N/A
606N/A /* If the timestamp in client's request is in the past relative
606N/A to the time stamp indicating the last time the owner of the
606N/A selection was set, do not set the selection, just return
606N/A success. */
606N/A if (CompareTimeStamps(time, pSel->lastTimeChanged) == EARLIER)
606N/A return Success;
606N/A if (pSel->client && (!pWin || (pSel->client != client)))
606N/A {
606N/A event.u.u.type = SelectionClear;
606N/A event.u.selectionClear.time = time.milliseconds;
606N/A event.u.selectionClear.window = pSel->window;
606N/A event.u.selectionClear.atom = pSel->selection;
606N/A TryClientEvents(pSel->client, &event, 1, NoEventMask,
606N/A NoEventMask /* CantBeFiltered */, NullGrab);
0N/A }
0N/A#ifdef TSOL
606N/A }
606N/A#endif /* TSOL */
606N/A }
606N/A else if (rc == BadMatch)
606N/A {
606N/A /*
606N/A * It doesn't exist, so add it...
0N/A */
606N/A pSel = xalloc(sizeof(Selection));
606N/A if (!pSel)
606N/A return BadAlloc;
606N/A
606N/A pSel->selection = stuff->selection;
606N/A pSel->devPrivates = NULL;
606N/A
606N/A /* security creation/labeling check */
606N/A rc = XaceHookSelectionAccess(client, &pSel,
606N/A DixCreateAccess|DixSetAttrAccess);
606N/A if (rc != Success) {
606N/A xfree(pSel);
606N/A return rc;
606N/A }
606N/A
606N/A pSel->next = CurrentSelections;
606N/A CurrentSelections = pSel;
606N/A }
606N/A else
606N/A return rc;
606N/A
606N/A#ifdef TSOL
606N/A /*
606N/A * tsolseln == NULL, either seln does not exist,
606N/A * or there is no sl,uid match
606N/A */
606N/A if (!tsolseln)
606N/A {
606N/A /* create one & put it in place */
606N/A tsolseln = (TsolSelnPtr)xalloc(sizeof(TsolSelnRec));
0N/A if (!tsolseln)
606N/A return BadAlloc;
606N/A tsolseln->next = (TsolSelnPtr)NULL;
606N/A
606N/A /* if necessary put at the end of the list */
606N/A if (prevtsolseln)
606N/A prevtsolseln->next = tsolseln;
606N/A else
606N/A *(TsolSelectionPriv(pSel)) = tsolseln;
606N/A }
606N/A /* fill it in */
0N/A tsolseln->sl = tsolinfo->sl;
0N/A tsolseln->uid = tsolinfo->uid;
0N/A tsolseln->lastTimeChanged = time;
606N/A tsolseln->window = stuff->window;
606N/A tsolseln->pWin = pWin;
606N/A tsolseln->client = (pWin ? client : NullClient);
606N/A if (!PolySelection(pSel->selection))
606N/A {
0N/A /* no change to existing code. left as it is */
0N/A#endif /* TSOL */
0N/A
606N/A pSel->lastTimeChanged = time;
606N/A pSel->window = stuff->window;
606N/A pSel->pWin = pWin;
606N/A pSel->client = (pWin ? client : NullClient);
606N/A
606N/A if (SelectionCallback != NULL) {
606N/A SelectionInfoRec info = { pSel, client, SelectionSetOwner };
606N/A CallCallbacks(&SelectionCallback, &info);
606N/A }
606N/A#ifdef TSOL
606N/A }
0N/A#endif /* TSOL */
0N/A
606N/A return (client->noClientException);
0N/A}
0N/A
0N/Aint
606N/AProcTsolGetSelectionOwner(ClientPtr client)
0N/A{
606N/A int rc;
606N/A Selection *pSel;
606N/A xGetSelectionOwnerReply reply;
606N/A
0N/A REQUEST(xResourceReq);
0N/A REQUEST_SIZE_MATCH(xResourceReq);
606N/A
606N/A if (!ValidAtom(stuff->id)) {
606N/A client->errorValue = stuff->id;
606N/A return BadAtom;
606N/A }
606N/A
606N/A reply.type = X_Reply;
606N/A reply.length = 0;
606N/A reply.sequenceNumber = client->sequence;
606N/A
606N/A rc = dixLookupSelection(&pSel, stuff->id, client, DixGetAttrAccess);
606N/A if (rc == Success)
606N/A#ifdef TSOL
0N/A {
0N/A TsolSelnPtr tsolseln;
0N/A TsolInfoPtr tsolinfo; /* tsol client info */
0N/A tsolinfo = GetClientTsolInfo(client);
0N/A
0N/A /* find matching sl,uid in case of poly selns */
606N/A tsolseln = *(TsolSelectionPriv(pSel));
606N/A if (PolySelection(pSel->selection))
0N/A {
606N/A while (tsolseln)
606N/A {
606N/A if (tsolseln->uid == tsolinfo->uid &&
606N/A tsolseln->sl == tsolinfo->sl)
606N/A break; /* match found */
606N/A tsolseln = tsolseln->next;
606N/A }
606N/A if (tsolseln)
606N/A reply.owner = tsolseln->window;
606N/A else
606N/A reply.owner = None;
0N/A }
0N/A else
606N/A {
606N/A reply.owner = pSel->window;
0N/A }
606N/A /*
0N/A * Selection Agent processing. Override the owner
0N/A */
606N/A if (!HasWinSelection(tsolinfo) &&
606N/A client->index != CLIENT_ID(reply.owner) &&
606N/A reply.owner != None &&
606N/A tsol_sel_agnt != -1 &&
606N/A CurrentSelections[tsol_sel_agnt].client)
606N/A {
606N/A WindowPtr pWin;
606N/A pWin = (WindowPtr)LookupWindow(reply.owner, client);
606N/A if (tsolinfo->flags & TSOL_AUDITEVENT)
606N/A auditwrite(AW_USEOFPRIV, 0, PRIV_WIN_SELECTION,
606N/A AW_APPEND, AW_END);
606N/A }
606N/A else if (HasWinSelection(tsolinfo) &&
606N/A tsolinfo->flags & TSOL_AUDITEVENT)
606N/A {
606N/A auditwrite(AW_USEOFPRIV, 1, PRIV_WIN_SELECTION,
606N/A AW_APPEND, AW_END);
606N/A }
0N/A /* end seln agent processing */
0N/A }
0N/A#else /* TSOL */
606N/A reply.owner = pSel->window;
0N/A#endif /* TSOL */
606N/A else if (rc == BadMatch)
606N/A reply.owner = None;
606N/A else
606N/A return rc;
606N/A
606N/A WriteReplyToClient(client, sizeof(xGetSelectionOwnerReply), &reply);
606N/A return client->noClientException;
0N/A}
0N/A
0N/Aint
606N/AProcTsolConvertSelection(ClientPtr client)
0N/A{
0N/A Bool paramsOkay;
0N/A xEvent event;
0N/A WindowPtr pWin;
606N/A Selection *pSel;
606N/A int rc;
606N/A
0N/A REQUEST(xConvertSelectionReq);
0N/A REQUEST_SIZE_MATCH(xConvertSelectionReq);
606N/A
606N/A rc = dixLookupWindow(&pWin, stuff->requestor, client, DixSetAttrAccess);
606N/A if (rc != Success)
606N/A return rc;
606N/A
606N/A paramsOkay = ValidAtom(stuff->selection) && ValidAtom(stuff->target);
606N/A paramsOkay &= (stuff->property == None) || ValidAtom(stuff->property);
606N/A if (!paramsOkay) {
606N/A client->errorValue = stuff->property;
606N/A return BadAtom;
606N/A }
606N/A
606N/A rc = dixLookupSelection(&pSel, stuff->selection, client, DixReadAccess);
606N/A
606N/A if (rc != Success && rc != BadMatch)
606N/A return rc;
606N/A#ifdef TSOL
606N/A else if (rc == Success) {
0N/A TsolSelnPtr tsolseln;
0N/A TsolInfoPtr tsolinfo; /* tsol client info */
0N/A Window twin; /* temporary win */
0N/A ClientPtr tclient; /* temporary client */
0N/A
0N/A tsolinfo = GetClientTsolInfo(client);
0N/A
0N/A /* find matching sl,uid in case of poly selns */
606N/A tsolseln = *(TsolSelectionPriv(pSel));
606N/A if (PolySelection(pSel->selection))
0N/A {
606N/A while (tsolseln)
606N/A {
606N/A if (tsolseln->uid == tsolinfo->uid &&
606N/A tsolseln->sl == tsolinfo->sl)
606N/A break; /* match found */
606N/A tsolseln = tsolseln->next;
606N/A }
606N/A if (!tsolseln)
606N/A {
606N/A client->errorValue = stuff->property;
606N/A return (BadAtom);
606N/A }
606N/A twin = tsolseln->window;
606N/A tclient = tsolseln->client;
0N/A }
0N/A else
0N/A {
606N/A twin = pSel->window;
606N/A tclient = pSel->client;
0N/A }
0N/A /*
0N/A * Special case for seln agent.
0N/A * SelectionRequest event is redirected to selection
0N/A * agent for unpirvileged clients and who do not own
0N/A * the selection
606N/A */
0N/A if (tsol_sel_agnt != -1 && CurrentSelections[tsol_sel_agnt].client)
0N/A {
606N/A /* Redirect only if client other than owner & does not have priv */
0N/A if (!HasWinSelection(tsolinfo) && (client != tclient))
606N/A {
606N/A tclient = CurrentSelections[tsol_sel_agnt].client;
606N/A twin = CurrentSelections[tsol_sel_agnt].window;
606N/A if (tsolinfo->flags & TSOL_AUDITEVENT)
606N/A auditwrite(AW_USEOFPRIV, 1, PRIV_WIN_SELECTION,
606N/A AW_APPEND, AW_END);
0N/A }
606N/A else if (HasWinSelection(tsolinfo) &&
606N/A tsolinfo->flags & TSOL_AUDITEVENT)
606N/A {
606N/A auditwrite(AW_USEOFPRIV, 0, PRIV_WIN_SELECTION,
606N/A AW_APPEND, AW_END);
606N/A }
0N/A }
0N/A /* end of special case seln handling */
0N/A
0N/A if (twin != None)
0N/A {
606N/A event.u.u.type = SelectionRequest;
606N/A event.u.selectionRequest.time = stuff->time;
606N/A event.u.selectionRequest.owner = twin;
606N/A event.u.selectionRequest.requestor = stuff->requestor;
606N/A event.u.selectionRequest.selection = stuff->selection;
606N/A event.u.selectionRequest.target = stuff->target;
606N/A event.u.selectionRequest.property = stuff->property;
606N/A if (TryClientEvents(tclient, &event, 1,
606N/A NoEventMask,
606N/A NoEventMask /* CantBeFiltered */,
606N/A NullGrab))
606N/A return (client->noClientException);
0N/A }
606N/A }
0N/A#else /* TSOL */
606N/A else if (rc == Success && pSel->window != None) {
606N/A event.u.u.type = SelectionRequest;
606N/A event.u.selectionRequest.owner = pSel->window;
606N/A event.u.selectionRequest.time = stuff->time;
606N/A event.u.selectionRequest.requestor = stuff->requestor;
606N/A event.u.selectionRequest.selection = stuff->selection;
606N/A event.u.selectionRequest.target = stuff->target;
606N/A event.u.selectionRequest.property = stuff->property;
606N/A if (TryClientEvents(pSel->client, &event, 1, NoEventMask,
606N/A NoEventMask /* CantBeFiltered */, NullGrab))
606N/A return client->noClientException;
606N/A }
0N/A#endif /* TSOL */
0N/A
606N/A event.u.u.type = SelectionNotify;
606N/A event.u.selectionNotify.time = stuff->time;
606N/A event.u.selectionNotify.requestor = stuff->requestor;
606N/A event.u.selectionNotify.selection = stuff->selection;
606N/A event.u.selectionNotify.target = stuff->target;
606N/A event.u.selectionNotify.property = None;
606N/A TryClientEvents(client, &event, 1, NoEventMask,
606N/A NoEventMask /* CantBeFiltered */, NullGrab);
606N/A return client->noClientException;
0N/A}
0N/A
0N/A/* Allocate and initialize a tsolprop */
0N/A
0N/ATsolPropPtr
606N/AAllocTsolProp(void)
0N/A{
0N/A TsolPropPtr tsolprop;
0N/A
0N/A tsolprop = (TsolPropPtr)Xcalloc(sizeof(TsolPropRec));
0N/A
0N/A if (tsolprop)
0N/A {
0N/A tsolprop->size = 0;
0N/A tsolprop->data = NULL;
0N/A tsolprop->next = NULL;
168N/A tsolprop->serverOwned = FALSE;
168N/A }
168N/A
168N/A return tsolprop;
168N/A}
168N/A
606N/A/*
168N/A * Allocate and initialize tsolprop created
168N/A * internally by the X server
168N/A */
168N/A
168N/ATsolPropPtr
606N/AAllocServerTsolProp(void)
168N/A{
168N/A TsolPropPtr tsolprop;
168N/A
168N/A tsolprop = (TsolPropPtr)Xcalloc(sizeof(TsolPropRec));
168N/A
168N/A if (tsolprop)
168N/A {
168N/A tsolprop->size = 0;
168N/A tsolprop->data = NULL;
168N/A tsolprop->next = NULL;
168N/A
168N/A tsolprop->serverOwned = TRUE;
168N/A tsolprop->uid = getuid(); /* of server process */
168N/A tsolprop->pid = getpid(); /* of server process */
168N/A tsolprop->sl = (bslabel_t *)lookupSL_low();
0N/A }
0N/A
0N/A return tsolprop;
0N/A}
0N/A
0N/A/*
0N/A * property data/len is stored in pProp for single
0N/A * instantiated properties. Polyinstanticated property
0N/A * data/len stored in the tsolprop structure
0N/A */
0N/A
0N/Aint
606N/ATsolChangeWindowProperty(
606N/A ClientPtr client,
606N/A WindowPtr pWin,
606N/A Atom property,
606N/A Atom type,
606N/A int format,
606N/A int mode,
606N/A unsigned long len,
606N/A pointer value,
606N/A Bool sendevent)
0N/A{
0N/A PropertyPtr pProp;
0N/A xEvent event;
0N/A int sizeInBytes;
0N/A int totalSize;
0N/A pointer data;
0N/A TsolPropPtr tsolprop;
606N/A TsolPropPtr *tsolpropP;
0N/A TsolInfoPtr tsolinfo;
0N/A TsolResPtr tsolres;
0N/A int result;
614N/A int polyprop;
614N/A
614N/A /* first see if property already exists */
614N/A
614N/A pProp = wUserProps (pWin);
614N/A while (pProp)
614N/A {
614N/A if (pProp->propertyName == property)
614N/A break;
614N/A pProp = pProp->next;
614N/A }
614N/A
614N/A result = TsolCheckPropertyAccess(client, pWin, pProp,
614N/A property, DixWriteAccess);
614N/A if (result == XTSOL_IGNORE) {
614N/A return Success;
614N/A }
614N/A
614N/A polyprop = PolyProperty(property, pWin);
0N/A if (!polyprop)
0N/A {
606N/A result = dixChangeWindowProperty(client, pWin, property, type,
606N/A format, mode, len, value, sendevent);
0N/A if (result != Success)
0N/A return (result);
0N/A }
0N/A
0N/A sizeInBytes = format>>3;
0N/A totalSize = len * sizeInBytes;
0N/A
0N/A tsolinfo = GetClientTsolInfo(client);
606N/A tsolres = TsolWindowPriv(pWin);
0N/A
0N/A /* Initialize secPrviate if property is not polyinstantiated */
0N/A if (!polyprop && pProp)
0N/A {
0N/A /* Initialize for internally created properties */
606N/A tsolpropP = TsolPropertyPriv(pProp);
606N/A if (*tsolpropP == NULL)
606N/A {
606N/A *tsolpropP = (pointer)AllocTsolProp();
606N/A if (*tsolpropP == NULL)
606N/A return(BadAlloc);
606N/A }
606N/A tsolprop = *tsolpropP;
606N/A
0N/A if (WindowIsRoot(pWin))
0N/A {
0N/A tsolprop->sl = tsolinfo->sl; /* use client's sl/uid */
0N/A tsolprop->uid = tsolinfo->uid;
168N/A tsolprop->pid = tsolinfo->pid;
0N/A }
0N/A else
0N/A {
0N/A tsolprop->sl = tsolres->sl; /* use window's sl/uid */
0N/A tsolprop->uid = tsolres->uid;
168N/A tsolprop->pid = tsolres->pid;
0N/A }
0N/A
0N/A return (result);
0N/A }
0N/A
0N/A /* Handle polyinstantiated property */
0N/A if (!pProp) /* just add to list */
0N/A {
0N/A if (!pWin->optional && !MakeWindowOptional (pWin))
0N/A return(BadAlloc);
0N/A pProp = (PropertyPtr)xalloc(sizeof(PropertyRec));
0N/A if (!pProp)
0N/A return(BadAlloc);
614N/A pProp->devPrivates = NULL;
606N/A tsolpropP = TsolPropertyPriv(pProp);
606N/A *tsolpropP = (pointer)Xcalloc(sizeof(TsolPropRec));
606N/A if (!(*tsolpropP))
0N/A return(BadAlloc);
0N/A data = (pointer)xalloc(totalSize);
0N/A if (!data && len)
0N/A {
606N/A xfree(*tsolpropP);
0N/A xfree(pProp);
0N/A return(BadAlloc);
0N/A }
0N/A pProp->propertyName = property;
0N/A pProp->type = type;
0N/A pProp->format = format;
0N/A pProp->data = data;
0N/A if (len)
0N/A bcopy((char *)value, (char *)data, totalSize);
0N/A pProp->size = len;
606N/A tsolprop = *tsolpropP;
0N/A if (WindowIsRoot(pWin))
0N/A {
0N/A tsolprop->sl = tsolinfo->sl;
0N/A tsolprop->uid = tsolinfo->uid;
0N/A }
0N/A else
0N/A {
0N/A tsolprop->sl = tsolres->sl;
0N/A tsolprop->uid = tsolres->uid;
0N/A }
0N/A tsolprop->data = data;
0N/A tsolprop->size = len;
0N/A tsolprop->next = (TsolPropPtr)NULL;
0N/A pProp->next = pWin->optional->userProps;
0N/A pWin->optional->userProps = pProp;
0N/A } /* end if !prop */
0N/A else
0N/A {
0N/A /* To append or prepend to a property the request format and type
0N/A * must match those of the already defined property. The
0N/A * existing format and type are irrelevant when using the mode
0N/A * "PropModeReplace" since they will be written over.
0N/A */
0N/A if ((format != pProp->format) && (mode != PropModeReplace))
0N/A return(BadMatch);
0N/A if ((pProp->type != type) && (mode != PropModeReplace))
0N/A return(BadMatch);
0N/A
606N/A tsolpropP = TsolPropertyPriv(pProp);
606N/A tsolprop = *tsolpropP;
0N/A /* search for a matching (sl, uid) pair */
0N/A while (tsolprop)
0N/A {
0N/A if (tsolprop->uid == tsolinfo->uid && tsolprop->sl == tsolinfo->sl)
0N/A break; /* match found */
0N/A tsolprop = tsolprop->next;
0N/A }
0N/A
0N/A if (!tsolprop)
0N/A {
0N/A /* no match found. Create one */
0N/A TsolPropPtr newtsol = (TsolPropPtr)Xcalloc(sizeof(TsolPropRec));
0N/A if (!newtsol)
0N/A return(BadAlloc);
0N/A data = (pointer)Xcalloc(totalSize);
0N/A if (!data && totalSize)
0N/A {
0N/A xfree(newtsol);
0N/A return(BadAlloc);
0N/A }
0N/A if (len)
0N/A memcpy((char *)data, (char *)value, totalSize);
606N/A
0N/A newtsol->sl = tsolinfo->sl;
0N/A newtsol->uid = tsolinfo->uid;
0N/A newtsol->data = data;
0N/A newtsol->size = len;
606N/A tsolpropP = TsolPropertyPriv(pProp);
606N/A newtsol->next = *tsolpropP;
606N/A *tsolpropP = newtsol;
0N/A }
0N/A else
0N/A {
0N/A switch (mode)
0N/A {
606N/A case PropModeReplace:
0N/A if (totalSize != tsolprop->size * (pProp->format >> 3))
0N/A {
0N/A data = (pointer)xrealloc(tsolprop->data, totalSize);
0N/A if (!data && len)
0N/A return(BadAlloc);
0N/A tsolprop->data = data;
0N/A }
0N/A if (len)
0N/A bcopy((char *)value, (char *)tsolprop->data, totalSize);
0N/A tsolprop->size = len;
0N/A pProp->type = type;
0N/A pProp->format = format;
0N/A break;
606N/A
0N/A case PropModeAppend:
0N/A if (len)
0N/A {
0N/A data =
0N/A (pointer)xrealloc(tsolprop->data,
0N/A sizeInBytes*(len+tsolprop->size));
0N/A if (!data)
0N/A return(BadAlloc);
0N/A tsolprop->data = data;
0N/A bcopy((char *)value,
0N/A &((char *)data)[tsolprop->size * sizeInBytes],
0N/A totalSize);
0N/A tsolprop->size += len;
0N/A }
0N/A break;
606N/A
0N/A case PropModePrepend:
0N/A if (len)
0N/A {
0N/A data =
0N/A (pointer)xalloc(sizeInBytes*(len + tsolprop->size));
0N/A if (!data)
0N/A return(BadAlloc);
0N/A bcopy((char *)tsolprop->data,
0N/A &((char *)data)[totalSize],
0N/A (int)(tsolprop->size * sizeInBytes));
0N/A bcopy((char *)value, (char *)data, totalSize);
0N/A xfree(tsolprop->data);
0N/A tsolprop->data = data;
0N/A tsolprop->size += len;
0N/A }
0N/A break;
0N/A }
0N/A }
0N/A } /* end else if !prop */
0N/A
0N/A event.u.u.type = PropertyNotify;
0N/A event.u.property.window = pWin->drawable.id;
0N/A event.u.property.state = PropertyNewValue;
0N/A event.u.property.atom = pProp->propertyName;
0N/A event.u.property.time = currentTime.milliseconds;
0N/A DeliverEvents(pWin, &event, 1, (WindowPtr)NULL);
0N/A
0N/A return(Success);
0N/A}
0N/A
0N/Aint
606N/ATsolInitWindow(
606N/A ClientPtr client,
606N/A WindowPtr pWin)
0N/A{
0N/A TsolInfoPtr tsolinfo;
606N/A TsolResPtr tsolres = TsolWindowPriv(pWin);
0N/A
0N/A if (client == serverClient)
0N/A {
0N/A tsolres->uid = 0;
0N/A tsolres->sl = (bslabel_t *)lookupSL_low();
0N/A }
0N/A else
0N/A {
0N/A tsolinfo = GetClientTsolInfo(client);
0N/A tsolres->uid = tsolinfo->uid;
0N/A tsolres->sl = tsolinfo->sl;
0N/A }
36N/A
36N/A return (Success);
0N/A}
0N/A
0N/Aint
606N/ATsolDeleteProperty(
606N/A ClientPtr client,
606N/A WindowPtr pWin,
606N/A Atom propName)
0N/A{
0N/A PropertyPtr pProp, prevProp;
0N/A xEvent event;
0N/A TsolPropPtr tsolprop, tail_prop, prevtsolprop;
606N/A TsolPropPtr *tsolpropP;
0N/A TsolInfoPtr tsolinfo = GetClientTsolInfo(client);
0N/A
0N/A if (!(pProp = wUserProps (pWin)))
0N/A return(Success);
0N/A
0N/A if (!PolyProperty(propName, pWin))
606N/A return (DeleteProperty(client, pWin, propName));
0N/A
0N/A prevProp = (PropertyPtr)NULL;
0N/A while (pProp)
0N/A {
0N/A if (pProp->propertyName == propName)
0N/A {
606N/A tsolpropP = TsolPropertyPriv(pProp);
606N/A tsolprop = *tsolpropP;
0N/A /* Found a matching name. Further match for SL,UID */
0N/A prevtsolprop = (TsolPropPtr)NULL;
0N/A tail_prop = tsolprop;
0N/A while (tsolprop)
0N/A {
0N/A if (tsolpolyinstinfo.enabled)
0N/A {
0N/A if (tsolprop->uid == tsolpolyinstinfo.uid &&
0N/A tsolprop->sl == tsolpolyinstinfo.sl)
0N/A {
0N/A break;
0N/A }
0N/A }
0N/A else
0N/A {
0N/A if (tsolprop->uid == tsolinfo->uid &&
0N/A tsolprop->sl == tsolinfo->sl)
0N/A {
0N/A break;
0N/A }
0N/A }
0N/A prevtsolprop = tsolprop;
0N/A tsolprop = tsolprop->next;
0N/A }
0N/A break;
0N/A }
0N/A prevProp = pProp;
0N/A pProp = pProp->next;
0N/A }
0N/A
606N/A if (pProp)
606N/A {
0N/A event.u.u.type = PropertyNotify;
0N/A event.u.property.window = pWin->drawable.id;
0N/A event.u.property.state = PropertyDelete;
0N/A event.u.property.atom = pProp->propertyName;
0N/A event.u.property.time = currentTime.milliseconds;
0N/A DeliverEvents(pWin, &event, 1, (WindowPtr)NULL);
0N/A
0N/A if (tsolprop)
0N/A {
606N/A tsolpropP = TsolPropertyPriv(pProp);
606N/A if (*tsolpropP == tsolprop)
606N/A *tsolpropP = tsolprop->next;
0N/A
0N/A if (prevtsolprop)
0N/A {
0N/A prevtsolprop->next = tsolprop->next;
0N/A }
0N/A xfree(tsolprop->data);
0N/A xfree(tsolprop);
0N/A
0N/A }
0N/A }
0N/A return(Success);
0N/A}
0N/A
0N/Aint
606N/AProcTsolListProperties(ClientPtr client)
0N/A{
633N/A Atom *pAtoms = NULL, *temppAtoms;
0N/A xListPropertiesReply xlpr;
606N/A int rc, numProps = 0;
0N/A WindowPtr pWin;
0N/A PropertyPtr pProp;
0N/A REQUEST(xResourceReq);
0N/A
0N/A REQUEST_SIZE_MATCH(xResourceReq);
606N/A rc = dixLookupWindow(&pWin, stuff->id, client, DixListPropAccess);
606N/A if (rc != Success)
606N/A return rc;
0N/A
0N/A /* policy check for window */
633N/A if ((rc = xtsol_policy(TSOL_RES_PROPWIN, TSOL_READ, pWin, 0,
633N/A client, TSOL_ALL, &(MAJOROP))))
0N/A {
0N/A client->errorValue = stuff->id;
606N/A return (rc);
0N/A }
0N/A
606N/A for (pProp = wUserProps(pWin); pProp; pProp = pProp->next)
606N/A numProps++;
606N/A
606N/A if (numProps && !(pAtoms = (Atom *)xalloc(numProps * sizeof(Atom))))
606N/A return BadAlloc;
606N/A
606N/A numProps = 0;
606N/A temppAtoms = pAtoms;
606N/A for (pProp = wUserProps(pWin); pProp; pProp = pProp->next)
606N/A {
0N/A if (PolyProperty(pProp->propertyName, pWin))
0N/A {
606N/A if (PolyPropReadable(pProp, client)) {
606N/A *temppAtoms++ = pProp->propertyName;
606N/A numProps++;
606N/A }
0N/A }
0N/A else
0N/A {
0N/A /* error ignored */
633N/A if (!xtsol_policy(TSOL_RES_PROPERTY, TSOL_READ, pProp, 0,
633N/A client, TSOL_ALL, &(MAJOROP))) {
606N/A *temppAtoms++ = pProp->propertyName;
606N/A numProps++;
606N/A }
0N/A }
0N/A }
0N/A
0N/A xlpr.type = X_Reply;
0N/A xlpr.nProperties = numProps;
0N/A xlpr.length = (numProps * sizeof(Atom)) >> 2;
0N/A xlpr.sequenceNumber = client->sequence;
0N/A WriteReplyToClient(client, sizeof(xGenericReply), &xlpr);
0N/A if (numProps)
0N/A {
0N/A client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
0N/A WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms);
0N/A }
606N/A xfree(pAtoms);
0N/A return(client->noClientException);
0N/A}
0N/A
0N/Aint
606N/AProcTsolGetProperty(ClientPtr client)
0N/A{
0N/A PropertyPtr pProp, prevProp;
0N/A unsigned long n, len, ind;
606N/A int rc;
0N/A WindowPtr pWin;
0N/A xGetPropertyReply reply;
606N/A Mask win_mode = DixGetPropAccess, prop_mode = DixReadAccess;
606N/A
633N/A TsolPropPtr tsolprop = NULL;
633N/A TsolPropPtr prevtsolprop = NULL;
0N/A TsolInfoPtr tsolinfo = GetClientTsolInfo(client);
606N/A
0N/A REQUEST(xGetPropertyReq);
0N/A
0N/A REQUEST_SIZE_MATCH(xGetPropertyReq);
606N/A if (stuff->delete) {
606N/A UpdateCurrentTime();
606N/A win_mode |= DixSetPropAccess;
606N/A prop_mode |= DixDestroyAccess;
606N/A }
606N/A rc = dixLookupWindow(&pWin, stuff->window, client, win_mode);
606N/A if (rc != Success)
606N/A return rc;
0N/A
0N/A if (!ValidAtom(stuff->property))
0N/A {
0N/A client->errorValue = stuff->property;
0N/A return(BadAtom);
0N/A }
0N/A if ((stuff->delete != xTrue) && (stuff->delete != xFalse))
0N/A {
0N/A client->errorValue = stuff->delete;
0N/A return(BadValue);
0N/A }
0N/A
0N/A if ((stuff->type != AnyPropertyType) && !ValidAtom(stuff->type))
0N/A {
0N/A client->errorValue = stuff->type;
0N/A return(BadAtom);
0N/A }
0N/A
0N/A
0N/A /* policy check for window */
633N/A if ((rc = xtsol_policy(TSOL_RES_PROPWIN, TSOL_READ, pWin, 0,
633N/A client, TSOL_ALL, &(MAJOROP))))
0N/A {
0N/A client->errorValue = stuff->window;
606N/A return (rc);
0N/A }
0N/A
0N/A if (!PolyProperty(stuff->property, pWin))
0N/A {
0N/A return (*TsolSavedProcVector[X_GetProperty])(client);
0N/A }
0N/A
0N/A pProp = wUserProps (pWin);
0N/A prevProp = (PropertyPtr)NULL;
0N/A
0N/A while (pProp)
0N/A {
0N/A if (pProp->propertyName == stuff->property)
0N/A {
606N/A tsolprop = *(TsolPropertyPriv(pProp));
0N/A prevtsolprop = tsolprop;
0N/A while (tsolprop)
0N/A {
0N/A if (tsolpolyinstinfo.enabled)
0N/A {
0N/A if (tsolprop->uid == tsolpolyinstinfo.uid &&
0N/A tsolprop->sl == tsolpolyinstinfo.sl)
0N/A break;
0N/A }
0N/A else
0N/A {
0N/A if (tsolprop->uid == tsolinfo->uid &&
0N/A tsolprop->sl == tsolinfo->sl)
0N/A break; /* match found */
0N/A }
0N/A prevtsolprop = tsolprop;
0N/A tsolprop = tsolprop->next;
0N/A }
0N/A break;
0N/A }
0N/A prevProp = pProp;
0N/A pProp = pProp->next;
0N/A }
0N/A
0N/A reply.type = X_Reply;
0N/A reply.sequenceNumber = client->sequence;
0N/A
606N/A if ( (!pProp) || (!tsolprop) || rc)
0N/A {
0N/A reply.nItems = 0;
0N/A reply.length = 0;
0N/A reply.bytesAfter = 0;
0N/A reply.propertyType = None;
0N/A reply.format = 0;
0N/A WriteReplyToClient(client, sizeof(xGenericReply), &reply);
0N/A }
0N/A else
0N/A {
0N/A /* If the request type and actual type don't match. Return the
0N/A property information, but not the data. */
0N/A
0N/A if (((stuff->type != pProp->type) &&
0N/A (stuff->type != AnyPropertyType)))
0N/A {
0N/A reply.bytesAfter = tsolprop->size;
0N/A reply.format = pProp->format;
0N/A reply.length = 0;
0N/A reply.nItems = 0;
0N/A reply.propertyType = pProp->type;
0N/A WriteReplyToClient(client, sizeof(xGenericReply), &reply);
0N/A return(Success);
0N/A }
0N/A
0N/A /*
0N/A * Return type, format, value to client
0N/A */
606N/A n = (pProp->format/8) * tsolprop->size;
606N/A
606N/A ind = stuff->longOffset << 2;
0N/A
0N/A /* If longOffset is invalid such that it causes "len" to
0N/A be negative, it's a value error. */
0N/A
0N/A if (n < ind)
0N/A {
0N/A client->errorValue = stuff->longOffset;
0N/A return BadValue;
0N/A }
0N/A
0N/A len = min(n - ind, 4 * stuff->longLength);
0N/A
0N/A reply.bytesAfter = n - (ind + len);
0N/A reply.format = pProp->format;
0N/A reply.length = (len + 3) >> 2;
0N/A reply.nItems = len / (pProp->format / 8 );
0N/A reply.propertyType = pProp->type;
0N/A
0N/A /* policy check for delete error ignored */
0N/A if (stuff->delete && (reply.bytesAfter == 0) &&
633N/A (!xtsol_policy(TSOL_RES_PROPERTY, TSOL_DESTROY, pProp, 0,
633N/A client, TSOL_ALL, &(MAJOROP))))
0N/A { /* send the event */
0N/A xEvent event;
606N/A
0N/A event.u.u.type = PropertyNotify;
0N/A event.u.property.window = pWin->drawable.id;
0N/A event.u.property.state = PropertyDelete;
0N/A event.u.property.atom = pProp->propertyName;
0N/A event.u.property.time = currentTime.milliseconds;
0N/A DeliverEvents(pWin, &event, 1, (WindowPtr)NULL);
0N/A }
0N/A
0N/A WriteReplyToClient(client, sizeof(xGenericReply), &reply);
0N/A if (len)
0N/A {
0N/A switch (reply.format) {
0N/A case 32: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap32Write; break;
0N/A case 16: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; break;
0N/A default: client->pSwapReplyFunc = (ReplySwapPtr)WriteToClient; break;
0N/A }
0N/A WriteSwappedDataToClient(client, len, (char *)tsolprop->data + ind);
0N/A }
0N/A
0N/A if (stuff->delete && (reply.bytesAfter == 0))
0N/A { /* delete the Property */
0N/A if (prevProp == (PropertyPtr)NULL) /* takes care of head */
0N/A {
0N/A if (!(pWin->optional->userProps = pProp->next))
0N/A CheckWindowOptionalNeed (pWin);
0N/A }
0N/A else
0N/A prevProp->next = pProp->next;
0N/A
0N/A /* remove the tsol struct */
0N/A prevtsolprop->next = tsolprop->next;
0N/A xfree(tsolprop->data);
0N/A xfree(tsolprop);
0N/A /* delete the prop for last reference */
0N/A if (tsolprop == prevtsolprop)
0N/A xfree(pProp);
0N/A }
0N/A }
0N/A return (client->noClientException);
0N/A}
0N/A
606N/A/* Generic ProcVector wrapper for functions which just need to set the
606N/A client's TrustLevel to Trusted before executing. */
606N/Astatic inline int
606N/AProcTsolUnwrapWithTrust(ClientPtr client, int majorop)
606N/A{
606N/A int result, savedtrust;
606N/A
606N/A savedtrust = setClientTrustLevel(client, XSecurityClientTrusted);
606N/A result = (*TsolSavedProcVector[majorop])(client);
606N/A setClientTrustLevel(client, savedtrust);
606N/A
606N/A return result;
606N/A}
606N/A
606N/A/* Generic ProcVector wrapper for functions which need to check
606N/A a policy before executing. If policy check fails, and reportErrors
606N/A is False, ignores error and returns success to client even though it's
606N/A not actually doing anything. If policy check succeeds, and makeTrusted
606N/A is True, set the clients TrustLevel before calling the wrapped function.
606N/A*/
606N/A#define IGNORE_ERRORS FALSE
606N/A#define REPORT_ERRORS TRUE
606N/A#define KEEP_TRUSTLEVEL FALSE
606N/A#define RAISE_TRUSTLEVEL TRUE
606N/A
606N/Astatic inline int
606N/AProcTsolUnwrapResourceAccess(ClientPtr client, xresource_t res_type,
606N/A xmethod_t method, XID resource,
606N/A Bool reportErrors, Bool makeTrusted)
0N/A{
36N/A int status;
606N/A
633N/A status = xtsol_policy(res_type, method, NULL, resource, client,
633N/A TSOL_ALL, &(MAJOROP));
606N/A
606N/A if (status != PASSED)
0N/A {
606N/A if (!reportErrors) {
606N/A status = client->noClientException; /* ignore error */
606N/A } else if (resource != NULL) {
606N/A client->errorValue = resource;
606N/A }
606N/A }
606N/A else if (makeTrusted)
606N/A {
606N/A status = ProcTsolUnwrapWithTrust(client, MAJOROP);
0N/A }
0N/A else
0N/A {
606N/A status = (*TsolSavedProcVector[MAJOROP])(client);
0N/A }
36N/A
36N/A return (status);
0N/A}
0N/A
0N/Aint
606N/AProcTsolChangeKeyboardMapping(ClientPtr client)
0N/A{
606N/A return ProcTsolUnwrapResourceAccess(client, TSOL_RES_KEYMAP, TSOL_MODIFY,
606N/A NULL, IGNORE_ERRORS, RAISE_TRUSTLEVEL);
606N/A}
606N/A
606N/Aint
606N/AProcTsolSetPointerMapping(ClientPtr client)
606N/A{
606N/A return ProcTsolUnwrapResourceAccess(client, TSOL_RES_PTRMAP, TSOL_MODIFY,
606N/A NULL, IGNORE_ERRORS, RAISE_TRUSTLEVEL);
0N/A}
0N/A
0N/Aint
606N/AProcTsolChangeKeyboardControl(ClientPtr client)
0N/A{
606N/A return ProcTsolUnwrapResourceAccess(client, TSOL_RES_KBDCTL, TSOL_MODIFY,
606N/A NULL, IGNORE_ERRORS, RAISE_TRUSTLEVEL);
0N/A}
0N/A
0N/Aint
606N/AProcTsolBell(ClientPtr client)
0N/A{
606N/A return ProcTsolUnwrapResourceAccess(client, TSOL_RES_BELL, TSOL_MODIFY,
606N/A NULL, IGNORE_ERRORS, RAISE_TRUSTLEVEL);
0N/A}
0N/A
606N/Aint
606N/AProcTsolChangePointerControl(ClientPtr client)
606N/A{
606N/A return ProcTsolUnwrapResourceAccess(client, TSOL_RES_PTRCTL, TSOL_MODIFY,
606N/A NULL, IGNORE_ERRORS, RAISE_TRUSTLEVEL);
606N/A}
606N/A
606N/Aint
606N/AProcTsolSetModifierMapping(ClientPtr client)
0N/A{
36N/A
0N/A xSetModifierMappingReply rep;
0N/A REQUEST(xSetModifierMappingReq);
0N/A KeyCode *inputMap;
0N/A int inputMapLen;
0N/A register int i;
36N/A int status;
606N/A DeviceIntPtr pDev = NULL;
606N/A int savedtrust;
606N/A
0N/A REQUEST_AT_LEAST_SIZE(xSetModifierMappingReq);
0N/A
0N/A if (client->req_len != ((stuff->numKeyPerModifier<<1) +
0N/A (sizeof (xSetModifierMappingReq)>>2)))
0N/A return BadLength;
0N/A
606N/A inputMapLen = 8 * stuff->numKeyPerModifier;
0N/A inputMap = (KeyCode *)&stuff[1];
0N/A
0N/A /*
0N/A * Now enforce the restriction that "all of the non-zero keycodes must be
0N/A * in the range specified by min-keycode and max-keycode in the
0N/A * connection setup (else a Value error)"
0N/A */
606N/A for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
606N/A if ((pDev->coreEvents || pDev == inputInfo.keyboard) && pDev->key) {
606N/A for (i = 0; i < inputMapLen; i++) {
606N/A /* Check that all the new modifiers fall within the advertised
606N/A * keycode range, and are okay with the DDX. */
606N/A if (inputMap[i] && ((inputMap[i] < pDev->key->curKeySyms.minKeyCode ||
606N/A inputMap[i] > pDev->key->curKeySyms.maxKeyCode) ||
606N/A !LegalModifier(inputMap[i], pDev))) {
606N/A client->errorValue = inputMap[i];
606N/A return BadValue;
606N/A }
606N/A }
0N/A }
0N/A }
0N/A
0N/A rep.type = X_Reply;
0N/A rep.length = 0;
0N/A rep.sequenceNumber = client->sequence;
0N/A rep.success = MappingSuccess;
0N/A
606N/A savedtrust = setClientTrustLevel(client, XSecurityClientTrusted);
606N/A
606N/A
606N/A if (xtsol_policy(TSOL_RES_MODMAP, TSOL_MODIFY,
633N/A NULL, 0, client, TSOL_ALL, &(MAJOROP)))
0N/A {
606N/A /*
606N/A * silently ignore the request. xview apps
0N/A * complain if we return error code. If we don't
0N/A * send the map notify event application hangs
0N/A */
606N/A SendMappingNotify(MappingModifier, 0, 0, client);
606N/A WriteReplyToClient(client, sizeof(xSetModifierMappingReply), &rep);
606N/A status = client->noClientException;
0N/A }
0N/A else
0N/A {
36N/A status = (*TsolSavedProcVector[X_SetModifierMapping])(client);
0N/A }
36N/A
606N/A setClientTrustLevel(client, savedtrust);
36N/A return (status);
0N/A}
0N/A
36N/Astatic void
36N/AResetStripeWindow(ClientPtr client)
0N/A{
0N/A WindowPtr pParent;
36N/A WindowPtr pWin = NULL;
0N/A
606N/A#if defined(PANORAMIX)
311N/A if (!noPanoramiXExtension)
311N/A {
470N/A PanoramiXRes *panres = NULL;
470N/A int j;
470N/A
470N/A if (tpwin) {
470N/A if ((panres = (PanoramiXRes *)LookupIDByType(tpwin->drawable.id,
470N/A XRT_WINDOW)) == NULL)
470N/A return;
470N/A }
470N/A
470N/A FOR_NSCREENS_BACKWARD(j)
470N/A {
470N/A if (panres == NULL)
470N/A return;
470N/A /* Validate trusted stripe window */
470N/A pWin = LookupWindow(panres->info[j].id, client);
470N/A
470N/A if (tpwin == NullWindow || pWin == NullWindow)
470N/A return;
470N/A
470N/A pParent = pWin->parent;
470N/A if (!pParent || pParent->firstChild == pWin)
470N/A return;
470N/A
470N/A ReflectStackChange(pWin, pParent->firstChild, VTStack);
470N/A }
311N/A } else
311N/A#endif
311N/A {
311N/A /* Validate trusted stripe window */
311N/A if (tpwin)
311N/A pWin = LookupWindow(tpwin->drawable.id, client);
311N/A
311N/A if (tpwin == NullWindow || pWin == NullWindow)
311N/A return;
311N/A
311N/A pParent = tpwin->parent;
311N/A /* stripe is already at head, nothing to do */
311N/A if (!pParent || pParent->firstChild == tpwin)
311N/A return;
311N/A
311N/A ReflectStackChange(tpwin, pParent->firstChild, VTStack);
311N/A }
0N/A}
0N/A
0N/Aint
606N/AProcTsolCreateWindow(ClientPtr client)
0N/A{
606N/A int rc;
0N/A WindowPtr pParent;
0N/A WindowPtr pWin;
0N/A bslabel_t admin_low;
0N/A TsolInfoPtr tsolinfo = GetClientTsolInfo(client);
0N/A TsolResPtr tsolres;
0N/A
0N/A REQUEST(xCreateWindowReq);
0N/A
0N/A REQUEST_AT_LEAST_SIZE(xCreateWindowReq);
606N/A
0N/A LEGAL_NEW_RESOURCE(stuff->wid, client);
606N/A rc = dixLookupWindow(&pParent, stuff->parent, client, DixAddAccess);
606N/A if (rc != Success)
606N/A return rc;
606N/A
633N/A if ((rc = xtsol_policy(TSOL_RES_WINDOW, TSOL_CREATE, pParent, 0,
633N/A client, TSOL_ALL, &(MAJOROP))))
606N/A return rc;
0N/A
0N/A /* Initialize tsol security attributes */
606N/A rc = (*TsolSavedProcVector[X_CreateWindow])(client);
0N/A pWin = pParent->firstChild;
606N/A tsolres = TsolWindowPriv(pWin);
0N/A
0N/A /* stuff tsol info into window from client */
0N/A if (tsolinfo == NULL || client == serverClient) {
0N/A /* Client is Server itself */
0N/A tsolres->uid = 0;
0N/A tsolres->sl = (bslabel_t *)lookupSL_low();
0N/A }
0N/A else
0N/A {
0N/A tsolres->uid = tsolinfo->uid;
0N/A tsolres->sl = tsolinfo->sl;
0N/A }
0N/A
0N/A bsllow(&admin_low);
0N/A if (blequal(tsolres->sl, &admin_low))
0N/A tsolres->flags = TRUSTED_MASK;
0N/A else
0N/A tsolres->flags = 0;
0N/A
36N/A ResetStripeWindow(client);
0N/A
606N/A return rc;
0N/A}
0N/A
0N/Aint
606N/AProcTsolChangeWindowAttributes(ClientPtr client)
0N/A{
606N/A WindowPtr pWin;
0N/A REQUEST(xChangeWindowAttributesReq);
606N/A int rc;
606N/A Mask access_mode = 0;
0N/A
0N/A REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq);
606N/A access_mode |= (stuff->valueMask & CWEventMask) ? DixReceiveAccess : 0;
606N/A access_mode |= (stuff->valueMask & ~CWEventMask) ? DixSetAttrAccess : 0;
606N/A rc = dixLookupWindow(&pWin, stuff->window, client, access_mode);
606N/A if (rc != Success)
606N/A return rc;
606N/A
633N/A if ((rc = xtsol_policy(TSOL_RES_WINDOW, TSOL_MODIFY, pWin, 0,
633N/A client, TSOL_ALL, &(MAJOROP))))
0N/A {
0N/A if (!WindowIsRoot(pWin))
606N/A return (rc);
0N/A }
0N/A
606N/A rc = (*TsolSavedProcVector[X_ChangeWindowAttributes])(client);
606N/A ResetStripeWindow(client);
606N/A
606N/A return rc;
606N/A}
606N/A
606N/A/* Generic ProcVector wrapper for functions which just need to have
606N/A ResetStripeWindow called after executing. */
606N/Astatic inline int
606N/AProcTsolUnwrapAndResetStripe(ClientPtr client, int majorop)
606N/A{
606N/A int result;
606N/A
606N/A result = (*TsolSavedProcVector[majorop])(client);
36N/A ResetStripeWindow(client);
0N/A
0N/A return result;
0N/A}
0N/A
0N/Aint
606N/AProcTsolConfigureWindow(ClientPtr client)
0N/A{
606N/A return ProcTsolUnwrapAndResetStripe(client, X_ConfigureWindow);
0N/A}
0N/A
0N/Aint
606N/AProcTsolCirculateWindow(ClientPtr client)
0N/A{
606N/A return ProcTsolUnwrapAndResetStripe(client, X_CirculateWindow);
0N/A}
0N/A
0N/Aint
606N/AProcTsolReparentWindow(ClientPtr client)
0N/A{
606N/A return ProcTsolUnwrapAndResetStripe(client, X_ReparentWindow);
0N/A}
0N/A
0N/Aint
606N/AProcTsolSendEvent(ClientPtr client)
0N/A{
0N/A WindowPtr pWin;
0N/A REQUEST(xSendEventReq);
0N/A
0N/A REQUEST_SIZE_MATCH(xSendEventReq);
0N/A
606N/A dixLookupWindow(&pWin, stuff->destination, client, DixSendAccess);
0N/A
0N/A if (!pWin)
0N/A return BadWindow;
0N/A
0N/A if (xtsol_policy(TSOL_RES_EVENTWIN, TSOL_MODIFY,
633N/A pWin, 0, client, TSOL_ALL, &(MAJOROP)))
0N/A return Success; /* ignore error */
0N/A
0N/A return (*TsolSavedProcVector[X_SendEvent])(client);
0N/A}
0N/A
0N/A
0N/A/*
606N/A * HandleHotKey -
0N/A * HotKey is Meta(Diamond)+ Stop Key
0N/A * Breaks untusted Ptr and Kbd grabs.
606N/A * Trusted Grabs are NOT broken
0N/A * Warps pointer to the Trusted Stripe if not Trusted grabs in force.
0N/A */
0N/Avoid
606N/AHandleHotKey(void)
0N/A{
0N/A int x, y;
0N/A Bool trusted_grab = FALSE;
0N/A ClientPtr client;
0N/A DeviceIntPtr mouse = inputInfo.pointer;
0N/A DeviceIntPtr keybd = inputInfo.keyboard;
606N/A TsolInfoPtr tsolinfo;
0N/A GrabPtr ptrgrab = mouse->grab;
0N/A GrabPtr kbdgrab = keybd->grab;
0N/A ScreenPtr pScreen;
0N/A
0N/A if (kbdgrab)
0N/A {
0N/A client = clients[CLIENT_ID(kbdgrab->resource)];
0N/A tsolinfo = GetClientTsolInfo(client);
0N/A
0N/A if (tsolinfo)
0N/A {
0N/A if (HasTrustedPath(tsolinfo))
0N/A trusted_grab = TRUE;
0N/A else
0N/A (*keybd->DeactivateGrab)(keybd);
0N/A }
0N/A
0N/A if (ptrgrab)
0N/A {
0N/A client = clients[CLIENT_ID(ptrgrab->resource)];
0N/A tsolinfo = GetClientTsolInfo(client);
0N/A
0N/A if (tsolinfo)
0N/A {
0N/A if (HasTrustedPath(tsolinfo))
0N/A trusted_grab = TRUE;
0N/A else
0N/A (*mouse->DeactivateGrab)(mouse);
0N/A }
0N/A }
0N/A }
0N/A
0N/A if (!trusted_grab)
0N/A {
0N/A /*
0N/A * Warp the pointer to the Trusted Stripe
0N/A */
0N/A pScreen = screenInfo.screens[0];
0N/A x = pScreen->width/2;
0N/A y = pScreen->height - StripeHeight/2;
0N/A (*pScreen->SetCursorPosition)(pScreen, x, y, TRUE);
0N/A }
0N/A}
0N/A
0N/Aint
606N/AProcTsolSetInputFocus(ClientPtr client)
0N/A{
606N/A int rc;
0N/A
0N/A REQUEST(xSetInputFocusReq);
0N/A
0N/A REQUEST_SIZE_MATCH(xSetInputFocusReq);
0N/A
0N/A if (stuff->focus != None)
0N/A {
606N/A WindowPtr focusWin;
606N/A
606N/A rc = dixLookupWindow(&focusWin, stuff->focus,
606N/A client, DixSetAttrAccess);
606N/A if ((rc == Success) && (focusWin != NullWindow) &&
633N/A xtsol_policy(TSOL_RES_FOCUSWIN, TSOL_MODIFY, focusWin, 0,
633N/A client, TSOL_ALL, &(MAJOROP)))
0N/A {
0N/A return (client->noClientException);
0N/A }
0N/A }
0N/A return (*TsolSavedProcVector[X_SetInputFocus])(client);
0N/A}
0N/A
0N/Aint
606N/AProcTsolGetInputFocus(ClientPtr client)
0N/A{
0N/A xGetInputFocusReply rep;
633N/A /* REQUEST(xReq); */
0N/A FocusClassPtr focus = inputInfo.keyboard->focus;
606N/A int rc;
0N/A
0N/A REQUEST_SIZE_MATCH(xReq);
228N/A
606N/A rc = XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.keyboard,
606N/A DixGetFocusAccess);
606N/A if (rc != Success)
606N/A return rc;
606N/A
0N/A rep.type = X_Reply;
0N/A rep.length = 0;
0N/A rep.sequenceNumber = client->sequence;
0N/A if (focus->win == NoneWin)
0N/A rep.focus = None;
0N/A else if (focus->win == PointerRootWin)
0N/A rep.focus = PointerRoot;
0N/A else if (xtsol_policy(TSOL_RES_FOCUSWIN, TSOL_READ,
633N/A focus->win, 0, client, TSOL_ALL, &(MAJOROP)))
0N/A rep.focus = RootOf(focus->win); /* root window on access failure */
0N/A else rep.focus = focus->win->drawable.id;
0N/A rep.revertTo = focus->revert;
0N/A WriteReplyToClient(client, sizeof(xGetInputFocusReply), &rep);
0N/A return Success;
0N/A}
0N/A
633N/A#ifdef UNUSED
0N/Avoid
606N/APrintSiblings(WindowPtr p1)
0N/A{
0N/A WindowPtr p2;
0N/A
0N/A if (p1 == NULL || p1->parent == NULL) return;
0N/A
0N/A p2 = p1->parent->firstChild;
0N/A while (p2)
0N/A {
606N/A ErrorF( "(%x, %d, %d, %x)\n", p2, p2->drawable.width,
0N/A p2->drawable.height, p2->prevSib);
0N/A p2 = p2->nextSib;
0N/A }
0N/A}
0N/A
0N/A/*
0N/A * Checks that tpwin & its siblings have same
0N/A * parents. Returns 0 if OK, a # indicating which
0N/A * Sibling has a bad parent
0N/A */
0N/Aint
606N/ACheckTPWin(void)
0N/A{
0N/A WindowPtr pWin;
0N/A int count = 1;
0N/A
0N/A pWin = tpwin->nextSib;
0N/A while (pWin)
0N/A {
0N/A if (pWin->parent->parent)
0N/A return count;
0N/A pWin = pWin->nextSib;
0N/A ++count;
0N/A }
0N/A return 0;
0N/A}
633N/A#endif /* UNUSED */
0N/A
0N/A/* NEW */
0N/A
0N/Aint
606N/AProcTsolGetGeometry(ClientPtr client)
0N/A{
0N/A xGetGeometryReply rep;
0N/A int status;
0N/A
0N/A REQUEST(xResourceReq);
0N/A
196N/A if ( noPanoramiXExtension )
0N/A {
196N/A if ((status = GetGeometry(client, &rep)) != Success)
196N/A return status;
196N/A
196N/A /* Reduce root window height = stripe height */
196N/A if (stuff->id == rep.root)
196N/A {
196N/A rep.height -= StripeHeight;
196N/A }
196N/A
196N/A WriteReplyToClient(client, sizeof(xGetGeometryReply), &rep);
196N/A return(client->noClientException);
196N/A
606N/A } else
196N/A {
196N/A status = (*TsolSavedProcVector[X_GetGeometry])(client);
196N/A return (status);
0N/A }
0N/A}
0N/A
0N/Aint
606N/AProcTsolGrabServer(ClientPtr client)
0N/A{
0N/A TsolInfoPtr tsolinfo = GetClientTsolInfo(client);
0N/A
633N/A /* REQUEST(xResourceReq); */
0N/A REQUEST_SIZE_MATCH(xReq);
0N/A
633N/A if (xtsol_policy(TSOL_RES_SRVGRAB, TSOL_CREATE, NULL, 0,
633N/A client, TSOL_ALL, &(MAJOROP)))
0N/A {
0N/A /* turn off auditing because operation ignored */
0N/A tsolinfo->flags &= ~TSOL_DOXAUDIT;
0N/A tsolinfo->flags &= ~TSOL_AUDITEVENT;
0N/A
0N/A return(client->noClientException);
0N/A }
0N/A
0N/A return (*TsolSavedProcVector[X_GrabServer])(client);
0N/A}
0N/A
0N/Aint
606N/AProcTsolUngrabServer(ClientPtr client)
0N/A{
0N/A TsolInfoPtr tsolinfo = GetClientTsolInfo(client);
0N/A
633N/A /* REQUEST(xResourceReq); */
0N/A REQUEST_SIZE_MATCH(xReq);
0N/A
633N/A if (xtsol_policy(TSOL_RES_SRVGRAB, TSOL_DESTROY, NULL, 0,
633N/A client, TSOL_ALL, &(MAJOROP)))
0N/A {
0N/A /* turn off auditing because operation ignored */
0N/A tsolinfo->flags &= ~TSOL_DOXAUDIT;
0N/A tsolinfo->flags &= ~TSOL_AUDITEVENT;
0N/A
0N/A return(client->noClientException);
0N/A }
0N/A
0N/A return (*TsolSavedProcVector[X_UngrabServer])(client);
0N/A}
0N/A
0N/Aint
606N/AProcTsolCreatePixmap(ClientPtr client)
0N/A{
0N/A PixmapPtr pMap;
0N/A int result;
0N/A
0N/A REQUEST(xCreatePixmapReq);
0N/A
0N/A REQUEST_SIZE_MATCH(xCreatePixmapReq);
0N/A
0N/A result = (*TsolSavedProcVector[X_CreatePixmap])(client);
0N/A
0N/A pMap = (PixmapPtr)SecurityLookupIDByType(client, stuff->pid, RT_PIXMAP,
606N/A DixDestroyAccess);
606N/A if (pMap)
0N/A {
0N/A /* Initialize security info */
0N/A TsolInfoPtr tsolinfo = GetClientTsolInfo(client);
606N/A TsolResPtr tsolres = TsolPixmapPriv(pMap);
0N/A
0N/A if (tsolinfo == NULL || client == serverClient)
0N/A {
0N/A /* Client is Server itself */
0N/A tsolres->uid = 0;
0N/A tsolres->sl = (bslabel_t *)lookupSL_low();
0N/A }
0N/A else
0N/A {
0N/A tsolres->uid = tsolinfo->uid;
0N/A tsolres->sl = tsolinfo->sl;
0N/A }
0N/A tsolres->flags = 0;
0N/A }
0N/A
0N/A return result;
0N/A}
606N/A
0N/Aint
606N/AProcTsolSetScreenSaver(ClientPtr client)
0N/A{
633N/A /* REQUEST(xSetScreenSaverReq); */
0N/A REQUEST_SIZE_MATCH(xSetScreenSaverReq);
0N/A
606N/A return ProcTsolUnwrapResourceAccess(client, TSOL_RES_SCRSAVER, TSOL_MODIFY,
606N/A NULL, REPORT_ERRORS, KEEP_TRUSTLEVEL);
0N/A}
0N/A
0N/Aint
606N/AProcTsolChangeHosts(ClientPtr client)
0N/A{
606N/A return ProcTsolUnwrapResourceAccess(client, TSOL_RES_ACL, TSOL_MODIFY,
606N/A NULL, REPORT_ERRORS, RAISE_TRUSTLEVEL);
0N/A}
0N/A
0N/Aint
606N/AProcTsolChangeAccessControl(ClientPtr client)
0N/A{
0N/A REQUEST(xSetAccessControlReq);
0N/A REQUEST_SIZE_MATCH(xSetAccessControlReq);
0N/A
606N/A return ProcTsolUnwrapResourceAccess(client, TSOL_RES_ACL, TSOL_MODIFY,
606N/A stuff->mode, REPORT_ERRORS, RAISE_TRUSTLEVEL);
0N/A}
0N/A
0N/Aint
606N/AProcTsolKillClient(ClientPtr client)
0N/A{
0N/A REQUEST(xResourceReq);
0N/A REQUEST_SIZE_MATCH(xResourceReq);
0N/A
606N/A return ProcTsolUnwrapResourceAccess(client, TSOL_RES_CLIENT, TSOL_DESTROY,
606N/A stuff->id, REPORT_ERRORS, KEEP_TRUSTLEVEL);
0N/A}
0N/A
0N/Aint
606N/AProcTsolSetFontPath(ClientPtr client)
0N/A{
633N/A /* REQUEST(xSetFontPathReq); */
606N/A
0N/A REQUEST_AT_LEAST_SIZE(xSetFontPathReq);
606N/A
633N/A if (xtsol_policy(TSOL_RES_FONTPATH, TSOL_MODIFY, NULL, 0,
633N/A client, TSOL_ALL, &(MAJOROP)))
0N/A {
0N/A return (BadValue);
0N/A }
0N/A
0N/A return (*TsolSavedProcVector[X_SetFontPath])(client);
0N/A}
0N/A
0N/Aint
606N/AProcTsolChangeCloseDownMode(ClientPtr client)
0N/A{
633N/A /* REQUEST(xSetCloseDownModeReq); */
0N/A REQUEST_SIZE_MATCH(xSetCloseDownModeReq);
0N/A
606N/A return ProcTsolUnwrapResourceAccess(client, TSOL_RES_CLIENT, TSOL_MODIFY,
606N/A NULL, IGNORE_ERRORS, KEEP_TRUSTLEVEL);
0N/A}
0N/A
633N/A#ifdef UNUSED
606N/Aint
606N/AProcTsolForceScreenSaver(ClientPtr client)
606N/A{
633N/A /* REQUEST(xForceScreenSaverReq); */
0N/A REQUEST_SIZE_MATCH(xForceScreenSaverReq);
606N/A
606N/A return ProcTsolUnwrapResourceAccess(client, TSOL_RES_SCRSAVER, TSOL_MODIFY,
606N/A NULL, REPORT_ERRORS, KEEP_TRUSTLEVEL);
0N/A}
633N/A#endif /* UNUSED */
0N/A
0N/Avoid
606N/ATsolDeleteWindowFromAnySelections(WindowPtr pWin)
0N/A{
606N/A Selection *pSel;
0N/A TsolSelnPtr tsolseln = NULL;
0N/A TsolSelnPtr prevtsolseln = NULL;
0N/A
606N/A for (pSel = CurrentSelections; pSel; pSel = pSel->next)
0N/A {
606N/A if (PolySelection(pSel->selection))
0N/A {
606N/A tsolseln = *(TsolSelectionPriv(pSel));
0N/A prevtsolseln = tsolseln;
0N/A while (tsolseln)
0N/A {
0N/A if (tsolseln->pWin == pWin)
0N/A break; /* match found */
0N/A prevtsolseln = tsolseln;
0N/A tsolseln = tsolseln->next;
0N/A }
0N/A
0N/A if (tsolseln)
0N/A {
0N/A if (SelectionCallback)
0N/A {
0N/A SelectionInfoRec info;
0N/A
606N/A info.selection = pSel;
0N/A info.kind = SelectionClientClose;
0N/A CallCallbacks(&SelectionCallback, &info);
0N/A }
0N/A
0N/A /* first on the list */
0N/A if (prevtsolseln == tsolseln)
606N/A *(TsolSelectionPriv(pSel))
606N/A = tsolseln->next;
0N/A else
0N/A prevtsolseln->next = tsolseln->next;
0N/A xfree(tsolseln);
0N/A
0N/A /* handle the last reference */
606N/A if (*(TsolSelectionPriv(pSel)) == NULL)
0N/A {
606N/A pSel->pWin = (WindowPtr)NULL;
606N/A pSel->window = None;
606N/A pSel->client = NullClient;
0N/A }
0N/A }
0N/A }
0N/A else
0N/A {
606N/A if (pSel->pWin == pWin)
0N/A {
606N/A SelectionInfoRec info = { pSel, NULL, SelectionWindowDestroy };
606N/A CallCallbacks(&SelectionCallback, &info);
606N/A
606N/A pSel->pWin = (WindowPtr)NULL;
606N/A pSel->window = None;
606N/A pSel->client = NullClient;
0N/A }
0N/A }
0N/A }
0N/A}
0N/A
0N/Avoid
606N/ATsolDeleteClientFromAnySelections(ClientPtr client)
0N/A{
606N/A Selection *pSel;
0N/A TsolSelnPtr tsolseln = NULL;
0N/A TsolSelnPtr prevtsolseln = NULL;
0N/A
606N/A for (pSel = CurrentSelections; pSel; pSel = pSel->next)
0N/A {
606N/A if (PolySelection(pSel->selection))
0N/A {
606N/A tsolseln = *(TsolSelectionPriv(pSel));
0N/A prevtsolseln = tsolseln;
0N/A while (tsolseln)
0N/A {
0N/A if (tsolseln->client == client)
0N/A break; /* match found */
0N/A prevtsolseln = tsolseln;
0N/A tsolseln = tsolseln->next;
0N/A }
0N/A
0N/A if (tsolseln)
0N/A {
0N/A if (SelectionCallback)
0N/A {
0N/A SelectionInfoRec info;
0N/A
606N/A info.selection = pSel;
0N/A info.kind = SelectionClientClose;
0N/A CallCallbacks(&SelectionCallback, &info);
0N/A }
0N/A
0N/A /* first on the list */
0N/A if (prevtsolseln == tsolseln)
606N/A *(TsolSelectionPriv(pSel))
606N/A = tsolseln->next;
0N/A else
0N/A prevtsolseln->next = tsolseln->next;
0N/A xfree(tsolseln);
0N/A
0N/A /* handle the last reference */
606N/A if (*(TsolSelectionPriv(pSel)) == NULL)
0N/A {
606N/A pSel->pWin = (WindowPtr)NULL;
606N/A pSel->window = None;
606N/A pSel->client = NullClient;
0N/A }
0N/A }
0N/A }
0N/A else
0N/A {
606N/A if (pSel->client == client)
0N/A {
606N/A SelectionInfoRec info = { pSel, NULL, SelectionClientClose };
606N/A CallCallbacks(&SelectionCallback, &info);
606N/A
606N/A pSel->pWin = (WindowPtr)NULL;
606N/A pSel->window = None;
606N/A pSel->client = NullClient;
0N/A }
0N/A }
0N/A }
0N/A}
0N/A
0N/Aint
606N/AProcTsolListInstalledColormaps(ClientPtr client)
0N/A{
606N/A xListInstalledColormapsReply *preply;
606N/A int nummaps, rc;
0N/A WindowPtr pWin;
0N/A REQUEST(xResourceReq);
0N/A REQUEST_SIZE_MATCH(xResourceReq);
606N/A
606N/A rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
606N/A if (rc != Success)
606N/A return rc;
606N/A
606N/A rc = XaceHook(XACE_SCREEN_ACCESS, client, pWin->drawable.pScreen,
606N/A DixGetAttrAccess);
606N/A if (rc != Success)
606N/A return rc;
606N/A
606N/A preply = (xListInstalledColormapsReply *)
606N/A xalloc(sizeof(xListInstalledColormapsReply) +
0N/A pWin->drawable.pScreen->maxInstalledCmaps *
0N/A sizeof(Colormap));
0N/A if(!preply)
0N/A return(BadAlloc);
0N/A
0N/A preply->type = X_Reply;
0N/A preply->sequenceNumber = client->sequence;
0N/A nummaps = (*pWin->drawable.pScreen->ListInstalledColormaps)
0N/A (pWin->drawable.pScreen, (Colormap *)&preply[1]);
0N/A preply->nColormaps = nummaps;
0N/A preply->length = nummaps;
0N/A#ifdef TSOL
0N/A {
0N/A int err_code, i;
0N/A Colormap *pcmap = (Colormap *)&preply[1];
0N/A ColormapPtr pcmp;
0N/A
0N/A /*
606N/A * check every colormap id for access. return default colormap
0N/A * id in case of failure
0N/A */
0N/A for (i = 0; i < nummaps; i++, pcmap++)
0N/A {
0N/A pcmp = (ColormapPtr )LookupIDByType(*pcmap, RT_COLORMAP);
633N/A if ((err_code = xtsol_policy(TSOL_RES_CMAP, TSOL_READ, pcmp, 0,
633N/A client, TSOL_ALL, &(MAJOROP))))
0N/A {
0N/A *pcmap = pWin->drawable.pScreen->defColormap;
0N/A }
0N/A }
0N/A }
0N/A#endif /* TSOL */
0N/A WriteReplyToClient(client, sizeof (xListInstalledColormapsReply), preply);
0N/A client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
0N/A WriteSwappedDataToClient(client, nummaps * sizeof(Colormap), &preply[1]);
606N/A xfree(preply);
0N/A return(client->noClientException);
0N/A}
0N/A
0N/A
0N/Aint
606N/AProcTsolQueryTree(ClientPtr client)
0N/A{
0N/A xQueryTreeReply reply;
606N/A int rc, numChildren = 0;
606N/A WindowPtr pChild, pWin, pHead;
0N/A Window *childIDs = (Window *)NULL;
0N/A
0N/A#ifdef TSOL
0N/A TsolInfoPtr tsolinfo = GetClientTsolInfo(client);
0N/A#endif /* TSOL */
0N/A
0N/A REQUEST(xResourceReq);
0N/A
0N/A REQUEST_SIZE_MATCH(xResourceReq);
606N/A rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess);
606N/A if (rc != Success)
606N/A return rc;
0N/A
0N/A#ifdef TSOL
633N/A if (xtsol_policy(TSOL_RES_WINDOW, TSOL_READ, pWin, 0,
633N/A client, TSOL_ALL, &(MAJOROP)))
0N/A {
0N/A return(BadWindow);
0N/A }
0N/A /*
0N/A * Because of its recursive nature, QuerryTree can leave a huge trail
0N/A * of audit records which could make deciphering the audit log for
0N/A * critical records difficult. So we turn off any more auditing of
0N/A * this protocol.
0N/A */
0N/A tsolinfo->flags &= ~TSOL_DOXAUDIT;
0N/A tsolinfo->flags &= ~TSOL_AUDITEVENT;
0N/A#endif /* TSOL */
0N/A
0N/A reply.type = X_Reply;
0N/A reply.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id;
0N/A reply.sequenceNumber = client->sequence;
0N/A if (pWin->parent)
0N/A reply.parent = pWin->parent->drawable.id;
0N/A else
0N/A reply.parent = (Window)None;
0N/A pHead = RealChildHead(pWin);
0N/A for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib)
0N/A#ifdef TSOL
0N/A {
0N/A /* error ignored */
633N/A if (!xtsol_policy(TSOL_RES_WINDOW, TSOL_READ, pChild, 0,
633N/A client, TSOL_ALL, &(MAJOROP)))
0N/A {
0N/A numChildren++;
0N/A }
0N/A }
0N/A#else /* !TSOL */
0N/A numChildren++;
0N/A#endif /* TSOL */
0N/A if (numChildren)
0N/A {
0N/A int curChild = 0;
0N/A
606N/A childIDs = (Window *) xalloc(numChildren * sizeof(Window));
0N/A if (!childIDs)
0N/A return BadAlloc;
0N/A for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib)
0N/A#ifdef TSOL
0N/A {
0N/A
0N/A /* error ignored */
633N/A if (!xtsol_policy(TSOL_RES_WINDOW, TSOL_READ, pChild, 0,
633N/A client, TSOL_ALL, &(MAJOROP)))
606N/A {
0N/A childIDs[curChild++] = pChild->drawable.id;
606N/A }
0N/A }
0N/A#else /* !TSOL */
0N/A childIDs[curChild++] = pChild->drawable.id;
0N/A#endif /* TSOL */
0N/A }
606N/A
0N/A reply.nChildren = numChildren;
0N/A reply.length = (numChildren * sizeof(Window)) >> 2;
606N/A
0N/A WriteReplyToClient(client, sizeof(xQueryTreeReply), &reply);
0N/A if (numChildren)
0N/A {
0N/A client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
0N/A WriteSwappedDataToClient(client, numChildren * sizeof(Window), childIDs);
606N/A xfree(childIDs);
0N/A }
0N/A
0N/A return(client->noClientException);
0N/A}
0N/A
606N/ACALLBACK(
606N/ATsolAuditStart)
0N/A{
606N/A XaceAuditRec *rec = (XaceAuditRec *) calldata;
606N/A ClientPtr client = rec->client;
606N/A
0N/A unsigned int protocol;
633N/A int xevent_num = -1;
0N/A int count = 0;
0N/A int status = 0;
0N/A Bool do_x_audit = FALSE;
0N/A Bool audit_event = FALSE;
0N/A TsolInfoPtr tsolinfo = (TsolInfoPtr)NULL;
0N/A tsolinfo = GetClientTsolInfo(client);
606N/A if (system_audit_on &&
36N/A (tsolinfo->amask.am_success || tsolinfo->amask.am_failure)) {
36N/A
36N/A do_x_audit = TRUE;
36N/A auditwrite(AW_PRESELECT, &(tsolinfo->amask), AW_END);
606N/A
36N/A /*
36N/A * X audit events start from 9101 in audit_uevents.h. The first two
36N/A * events are non-protocol ones viz. ClientConnect, mapped to 9101
36N/A * and ClientDisconnect, mapped to 9102.
36N/A * The protocol events are mapped from 9103 onwards in the serial
36N/A * order of their respective protocol opcode, for eg, the protocol
36N/A * UngrabPointer which is has a protocol opcode 27 is mapped to
36N/A * 9129 (9102 + 27).
36N/A * All extension protocols are mapped to a single audit event
36N/A * AUE_XExtension as opcodes are assigined dynamically to these
36N/A * protocols. We set the extension protocol opcode to be 128, one
36N/A * more than the last standard opcode.
36N/A */
36N/A protocol = (unsigned int)MAJOROP;
36N/A if (protocol > X_NoOperation) {
36N/A xevent_num = audit_eventsid[MAX_AUDIT_EVENTS - 1][1];
36N/A audit_event = TRUE;
36N/A } else {
36N/A for (count = 0; count < MAX_AUDIT_EVENTS; count++) {
36N/A if (protocol == audit_eventsid[count][0]) {
36N/A xevent_num = audit_eventsid[count][1];
0N/A audit_event = TRUE;
0N/A break;
36N/A }
36N/A }
36N/A }
0N/A
36N/A /*
36N/A * Exclude Clients with Trusted Path such as tsoldtwm, tsoldtsession etc
36N/A * from generating the audit records for X protocols
36N/A */
36N/A if (audit_event && do_x_audit && !HasTrustedPath(tsolinfo) &&
36N/A (au_preselect(xevent_num, &(tsolinfo->amask), AU_PRS_BOTH,
36N/A AU_PRS_USECACHE) == 1)) {
36N/A tsolinfo->flags |= TSOL_AUDITEVENT;
36N/A status = auditwrite(AW_EVENTNUM, xevent_num, AW_APPEND, AW_END);
36N/A } else {
36N/A tsolinfo->flags &= ~TSOL_AUDITEVENT;
36N/A tsolinfo->flags &= ~TSOL_DOXAUDIT;
36N/A }
36N/A }
0N/A}
0N/A
606N/ACALLBACK(
606N/ATsolAuditEnd)
0N/A{
606N/A XaceAuditRec *rec = (XaceAuditRec *) calldata;
606N/A ClientPtr client = rec->client;
606N/A int result = rec->requestResult;
606N/A
0N/A char audit_ret = (char)NULL;
0N/A TsolInfoPtr tsolinfo = GetClientTsolInfo(client);
0N/A
0N/A if (tsolinfo->flags & TSOL_DOXAUDIT)
0N/A {
0N/A tsolinfo->flags &= ~TSOL_DOXAUDIT;
0N/A if (tsolinfo->flags & TSOL_AUDITEVENT)
0N/A tsolinfo->flags &= ~TSOL_AUDITEVENT;
0N/A if (result != Success)
0N/A audit_ret = -1;
0N/A else
0N/A audit_ret = 0;
0N/A auditwrite(AW_RETURN, audit_ret, (u_int)result,
0N/A AW_WRITE, AW_END);
0N/A }
0N/A else if (tsolinfo->flags & TSOL_AUDITEVENT)
0N/A {
0N/A tsolinfo->flags &= ~TSOL_AUDITEVENT;
0N/A auditwrite(AW_DISCARDRD, -1, AW_END);
0N/A }
0N/A}
0N/A
0N/Aint
606N/AProcTsolQueryPointer(ClientPtr client)
0N/A{
0N/A xQueryPointerReply rep;
606N/A WindowPtr pWin, ptrWin;
0N/A DeviceIntPtr mouse = inputInfo.pointer;
606N/A int rc;
606N/A REQUEST(xResourceReq);
0N/A REQUEST_SIZE_MATCH(xResourceReq);
606N/A
606N/A rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
606N/A if (rc != Success)
606N/A return rc;
606N/A rc = XaceHook(XACE_DEVICE_ACCESS, client, mouse, DixReadAccess);
606N/A if (rc != Success)
606N/A return rc;
0N/A
0N/A ptrWin = TsolPointerWindow();
633N/A if (!xtsol_policy(TSOL_RES_WINDOW, TSOL_READ, ptrWin, 0,
633N/A client, TSOL_ALL, &(MAJOROP)))
0N/A return (*TsolSavedProcVector[X_QueryPointer])(client);
0N/A
0N/A if (mouse->valuator->motionHintWindow)
0N/A MaybeStopHint(mouse, client);
0N/A rep.type = X_Reply;
0N/A rep.sequenceNumber = client->sequence;
0N/A rep.mask = mouse->button->state | inputInfo.keyboard->key->state;
0N/A rep.length = 0;
0N/A rep.root = RootOf(pWin);
0N/A rep.rootX = 0;
0N/A rep.rootY = 0;
0N/A rep.child = None;
0N/A rep.sameScreen = xTrue;
0N/A rep.winX = 0;
0N/A rep.winY = 0;
0N/A
0N/A WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep);
0N/A
606N/A return(Success);
606N/A}
606N/A
606N/A
606N/Aint
606N/AProcTsolQueryExtension(ClientPtr client)
606N/A{
606N/A /* Allow extensions in the labeled zones */
606N/A return ProcTsolUnwrapWithTrust(client, X_QueryExtension);
0N/A}
36N/A
36N/Aint
606N/AProcTsolListExtensions(ClientPtr client)
36N/A{
36N/A /* Allow extensions in the labeled zones */
606N/A return ProcTsolUnwrapWithTrust(client, X_ListExtensions);
36N/A}
36N/A
36N/Aint
606N/AProcTsolMapWindow(ClientPtr client)
36N/A{
606N/A return ProcTsolUnwrapWithTrust(client, X_MapWindow);
36N/A}
36N/A
36N/Aint
606N/AProcTsolMapSubwindows(ClientPtr client)
36N/A{
606N/A return ProcTsolUnwrapWithTrust(client, X_MapSubwindows);
36N/A}
64N/A
64N/Astatic int
606N/ATsolDoGetImage(
606N/A register ClientPtr client,
606N/A Drawable drawable,
606N/A int format,
606N/A int x, int y, int width, int height,
606N/A Mask planemask,
606N/A xGetImageReply **im_return)
64N/A{
606N/A DrawablePtr pDraw;
606N/A int nlines, linesPerBuf, rc;
64N/A register int linesDone;
64N/A long widthBytesLine, length;
64N/A Mask plane = 0;
64N/A char *pBuf;
64N/A xGetImageReply xgi;
64N/A
64N/A#ifdef TSOL
64N/A Bool getimage_ok = TRUE; /* if false get all 0s */
64N/A Bool overlap = FALSE;
64N/A Bool not_root_window = FALSE;
633N/A WindowPtr pHead = NULL, pWin = NULL, pRoot;
64N/A TsolResPtr tsolres_win;
64N/A BoxRec winbox, box;
64N/A BoxPtr pwinbox;
64N/A DrawablePtr pDrawtmp;
64N/A#endif /* TSOL */
64N/A
64N/A if ((format != XYPixmap) && (format != ZPixmap))
64N/A {
64N/A client->errorValue = format;
64N/A return(BadValue);
64N/A }
606N/A rc = dixLookupDrawable(&pDraw, drawable, client, 0, DixReadAccess);
606N/A if (rc != Success)
606N/A return rc;
606N/A
73N/A
73N/A#ifdef TSOL
606N/A if (!xtsol_policy(TSOL_RES_PIXEL, TSOL_READ,
633N/A pDraw, 0, client, TSOL_ALL, &(MAJOROP)) &&
73N/A (DrawableIsRoot(pDraw) || !tsolMultiLevel))
64N/A {
606N/A return DoGetImage(client, format, drawable, x, y,
73N/A width, height, planemask, im_return);
73N/A }
73N/A
73N/A if (pDraw->type == DRAWABLE_WINDOW)
73N/A {
64N/A if (DrawableIsRoot(pDraw))
64N/A {
73N/A pWin = XYToWindow(x, y);
64N/A if (!WindowIsRoot(pWin))
64N/A {
64N/A pDrawtmp = &(pWin->parent->drawable);
64N/A if (((WindowPtr) pDrawtmp)->realized)
64N/A {
73N/A int tmpx, tmpy;
73N/A
73N/A tmpx = x - pDrawtmp->x;
73N/A tmpy = y - pDrawtmp->y;
73N/A
73N/A /* requested area must be a subset of the window area */
73N/A if (tmpx >= 0 && tmpy >= 0 &&
73N/A width <= pDrawtmp->width &&
73N/A height <= pDrawtmp->height)
73N/A {
73N/A pDraw = pDrawtmp;
73N/A x = tmpx;
73N/A y = tmpy;
73N/A not_root_window = TRUE;
73N/A }
64N/A }
64N/A }
64N/A }
64N/A else
64N/A {
64N/A not_root_window = TRUE;
64N/A }
64N/A
64N/A if (not_root_window)
64N/A {
64N/A Window root;
64N/A WindowPtr tmpwin;
64N/A
73N/A not_root_window = TRUE;
64N/A tmpwin = (WindowPtr)LookupWindow(pDraw->id, client);
64N/A while (tmpwin)
64N/A {
64N/A if (tmpwin->parent && WindowIsRoot(tmpwin->parent))
64N/A {
64N/A pWin = tmpwin;
64N/A break;
64N/A }
64N/A tmpwin = tmpwin->parent;
64N/A }
64N/A pwinbox = WindowExtents(pWin, &winbox);
64N/A box.x1 = pwinbox->x1;
64N/A box.y1 = pwinbox->y1;
64N/A box.x2 = pwinbox->x2;
64N/A box.y2 = box.y1;
606N/A tsolres_win = TsolWindowPriv(pWin);
64N/A root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id;
64N/A pRoot = (WindowPtr)LookupIDByType(root, RT_WINDOW);
64N/A pHead = pRoot->firstChild;
64N/A }
64N/A
633N/A if (xtsol_policy(TSOL_RES_PIXEL, TSOL_READ, pDraw, 0,
633N/A client, TSOL_ALL, &(MAJOROP)))
64N/A getimage_ok = FALSE;
73N/A else
73N/A getimage_ok = TRUE;
73N/A }
64N/A#endif /* TSOL */
64N/A
73N/A if(pDraw->type == DRAWABLE_WINDOW)
73N/A {
73N/A
64N/A if( /* check for being viewable */
64N/A !((WindowPtr) pDraw)->realized ||
64N/A /* check for being on screen */
64N/A pDraw->x + x < 0 ||
64N/A pDraw->x + x + width > pDraw->pScreen->width ||
64N/A pDraw->y + y < 0 ||
64N/A pDraw->y + y + height > pDraw->pScreen->height ||
64N/A /* check for being inside of border */
64N/A x < - wBorderWidth((WindowPtr)pDraw) ||
64N/A x + width > wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width ||
64N/A y < -wBorderWidth((WindowPtr)pDraw) ||
64N/A y + height > wBorderWidth ((WindowPtr)pDraw) + (int)pDraw->height
64N/A )
64N/A return(BadMatch);
64N/A xgi.visual = wVisual (((WindowPtr) pDraw));
64N/A }
64N/A else
64N/A {
64N/A if(x < 0 ||
64N/A x+width > (int)pDraw->width ||
64N/A y < 0 ||
64N/A y+height > (int)pDraw->height
64N/A )
64N/A return(BadMatch);
64N/A xgi.visual = None;
64N/A }
64N/A
64N/A xgi.type = X_Reply;
64N/A xgi.sequenceNumber = client->sequence;
64N/A xgi.depth = pDraw->depth;
64N/A if(format == ZPixmap)
64N/A {
64N/A widthBytesLine = PixmapBytePad(width, pDraw->depth);
64N/A length = widthBytesLine * height;
64N/A
64N/A }
606N/A else
64N/A {
64N/A widthBytesLine = BitmapBytePad(width);
64N/A plane = ((Mask)1) << (pDraw->depth - 1);
64N/A /* only planes asked for */
64N/A length = widthBytesLine * height *
64N/A Ones(planemask & (plane | (plane - 1)));
64N/A
64N/A }
64N/A
64N/A xgi.length = length;
64N/A
64N/A if (im_return) {
64N/A pBuf = (char *)xalloc(sz_xGetImageReply + length);
64N/A if (!pBuf)
64N/A return (BadAlloc);
64N/A if (widthBytesLine == 0)
64N/A linesPerBuf = 0;
64N/A else
64N/A linesPerBuf = height;
64N/A *im_return = (xGetImageReply *)pBuf;
64N/A *(xGetImageReply *)pBuf = xgi;
64N/A pBuf += sz_xGetImageReply;
64N/A } else {
64N/A xgi.length = (xgi.length + 3) >> 2;
64N/A if (widthBytesLine == 0 || height == 0)
64N/A linesPerBuf = 0;
64N/A else if (widthBytesLine >= IMAGE_BUFSIZE)
64N/A linesPerBuf = 1;
64N/A else
64N/A {
64N/A linesPerBuf = IMAGE_BUFSIZE / widthBytesLine;
64N/A if (linesPerBuf > height)
64N/A linesPerBuf = height;
64N/A }
64N/A length = linesPerBuf * widthBytesLine;
64N/A if (linesPerBuf < height)
64N/A {
64N/A /* we have to make sure intermediate buffers don't need padding */
64N/A while ((linesPerBuf > 1) &&
64N/A (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD)-1)))
64N/A {
64N/A linesPerBuf--;
64N/A length -= widthBytesLine;
64N/A }
64N/A while (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD)-1))
64N/A {
64N/A linesPerBuf++;
64N/A length += widthBytesLine;
64N/A }
64N/A }
606N/A if(!(pBuf = (char *) xalloc(length)))
64N/A return (BadAlloc);
64N/A WriteReplyToClient(client, sizeof (xGetImageReply), &xgi);
64N/A }
64N/A
64N/A if (linesPerBuf == 0)
64N/A {
64N/A /* nothing to do */
64N/A }
64N/A else if (format == ZPixmap)
64N/A {
64N/A linesDone = 0;
64N/A while (height - linesDone > 0)
64N/A {
64N/A nlines = min(linesPerBuf, height - linesDone);
64N/A (*pDraw->pScreen->GetImage) (pDraw,
64N/A x,
64N/A y + linesDone,
606N/A width,
64N/A nlines,
64N/A format,
64N/A planemask,
64N/A (pointer) pBuf);
64N/A#ifdef TSOL
64N/A if (not_root_window)
64N/A {
64N/A WindowPtr over_win = (WindowPtr)NULL;
64N/A
64N/A box.y1 = y + linesDone + pDraw->y;
64N/A box.y2 = box.y1 + nlines;
64N/A over_win = AnyWindowOverlapsJustMe(pWin, pHead, &box);
64N/A if (over_win &&
633N/A xtsol_policy(TSOL_RES_PIXEL, TSOL_READ, over_win, 0,
633N/A client, TSOL_ALL, &(MAJOROP)))
64N/A {
64N/A overlap = TRUE;
64N/A }
64N/A }
64N/A
64N/A /*
64N/A * fill the buffer with zeros in case of security failure
64N/A */
64N/A if (!getimage_ok || overlap)
64N/A {
64N/A if (overlap)
64N/A overlap = FALSE;
64N/A memset(pBuf, 0, (int)(nlines * widthBytesLine));
64N/A
64N/A }
64N/A#endif /* TSOL */
64N/A
64N/A /* Note that this is NOT a call to WriteSwappedDataToClient,
64N/A as we do NOT byte swap */
64N/A if (!im_return)
64N/A {
64N/A/* Don't split me, gcc pukes when you do */
64N/A (void)WriteToClient(client,
64N/A (int)(nlines * widthBytesLine),
64N/A pBuf);
64N/A }
64N/A linesDone += nlines;
64N/A }
64N/A }
64N/A else /* XYPixmap */
64N/A {
64N/A for (; plane; plane >>= 1)
64N/A {
64N/A if (planemask & plane)
64N/A {
64N/A linesDone = 0;
64N/A while (height - linesDone > 0)
64N/A {
64N/A nlines = min(linesPerBuf, height - linesDone);
64N/A (*pDraw->pScreen->GetImage) (pDraw,
64N/A x,
64N/A y + linesDone,
606N/A width,
64N/A nlines,
64N/A format,
64N/A plane,
64N/A (pointer)pBuf);
64N/A#ifdef TSOL
64N/A if (not_root_window)
64N/A {
64N/A WindowPtr over_win = (WindowPtr)NULL;
64N/A
64N/A box.y1 = y + linesDone + pDraw->y;
64N/A box.y2 = box.y1 + nlines;
64N/A over_win = AnyWindowOverlapsJustMe(pWin, pHead, &box);
64N/A if (over_win &&
633N/A xtsol_policy(TSOL_RES_PIXEL, TSOL_READ, over_win, 0,
633N/A client, TSOL_ALL, &(MAJOROP)))
64N/A {
64N/A overlap = TRUE;
64N/A }
64N/A }
64N/A /*
64N/A * fill the buffer with zeros in case of security failure
64N/A */
64N/A if (!getimage_ok || overlap)
64N/A {
64N/A if (overlap)
64N/A overlap = FALSE;
64N/A memset(pBuf, 0, (int)(nlines * widthBytesLine));
64N/A
64N/A }
64N/A#endif /* TSOL */
64N/A
64N/A /* Note: NOT a call to WriteSwappedDataToClient,
64N/A as we do NOT byte swap */
64N/A if (im_return) {
64N/A pBuf += nlines * widthBytesLine;
64N/A } else {
64N/A/* Don't split me, gcc pukes when you do */
64N/A (void)WriteToClient(client,
64N/A (int)(nlines * widthBytesLine),
64N/A pBuf);
64N/A }
64N/A linesDone += nlines;
64N/A }
64N/A }
64N/A }
64N/A }
64N/A
64N/A if (!im_return)
606N/A xfree(pBuf);
64N/A return (client->noClientException);
64N/A}
64N/A
64N/Aint
606N/AProcTsolGetImage(ClientPtr client)
64N/A{
64N/A int status;
606N/A int savedtrust = setClientTrustLevel(client, XSecurityClientTrusted);
64N/A
64N/A REQUEST(xGetImageReq);
64N/A
64N/A REQUEST_SIZE_MATCH(xGetImageReq);
64N/A
64N/A status = TsolDoGetImage(client, stuff->format, stuff->drawable,
64N/A stuff->x, stuff->y,
64N/A (int)stuff->width, (int)stuff->height,
64N/A stuff->planeMask, (xGetImageReply **)NULL);
64N/A
606N/A setClientTrustLevel(client, savedtrust);
64N/A return (status);
64N/A}
64N/A
64N/Aint
606N/AProcTsolPolySegment(ClientPtr client)
64N/A{
64N/A int savedtrust;
64N/A int status;
64N/A GC *pGC;
64N/A DrawablePtr pDraw;
64N/A REQUEST(xPolySegmentReq);
64N/A
64N/A REQUEST_AT_LEAST_SIZE(xPolySegmentReq);
64N/A
606N/A savedtrust = setClientTrustLevel(client, XSecurityClientTrusted);
606N/A
606N/A VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
64N/A
633N/A if (xtsol_policy(TSOL_RES_PIXEL, TSOL_MODIFY, pDraw, 0,
633N/A client, TSOL_ALL, &(MAJOROP)))
64N/A {
64N/A /* ignore the error message for DnD zap effect */
64N/A return (client->noClientException);
64N/A }
633N/A if (xtsol_policy(TSOL_RES_GC, TSOL_READ, NULL, stuff->gc,
633N/A client, TSOL_ALL, &(MAJOROP)))
64N/A {
64N/A client->errorValue = stuff->gc;
64N/A return (BadGC);
64N/A }
64N/A
64N/A status = (*TsolSavedProcVector[X_PolySegment])(client);
606N/A setClientTrustLevel(client, savedtrust);
64N/A
64N/A return (status);
64N/A}
64N/A
64N/Aint
606N/AProcTsolPolyRectangle (ClientPtr client)
64N/A{
64N/A int savedtrust;
64N/A int status;
64N/A GC *pGC;
64N/A DrawablePtr pDraw;
64N/A
64N/A REQUEST(xPolyRectangleReq);
64N/A REQUEST_AT_LEAST_SIZE(xPolyRectangleReq);
64N/A
606N/A savedtrust = setClientTrustLevel(client, XSecurityClientTrusted);
606N/A
606N/A VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
64N/A
633N/A if (xtsol_policy(TSOL_RES_PIXEL, TSOL_MODIFY, pDraw, 0,
633N/A client, TSOL_ALL, &(MAJOROP)))
64N/A {
64N/A /* ignore the error message */
64N/A return (client->noClientException);
64N/A }
633N/A if (xtsol_policy(TSOL_RES_GC, TSOL_READ, NULL, stuff->gc,
633N/A client, TSOL_ALL, &(MAJOROP)))
64N/A {
64N/A client->errorValue = stuff->gc;
64N/A return (BadGC);
64N/A }
64N/A
64N/A status = (*TsolSavedProcVector[X_PolyRectangle])(client);
606N/A setClientTrustLevel(client, savedtrust);
64N/A
64N/A return (status);
64N/A}
64N/A
64N/Aint
606N/AProcTsolCopyArea (ClientPtr client)
64N/A{
64N/A int savedtrust;
64N/A int status;
606N/A DrawablePtr pDst;
606N/A DrawablePtr pSrc;
606N/A GC *pGC;
606N/A int rc;
606N/A
64N/A REQUEST(xCopyAreaReq);
64N/A
64N/A REQUEST_SIZE_MATCH(xCopyAreaReq);
64N/A
606N/A savedtrust = setClientTrustLevel(client, XSecurityClientTrusted);
606N/A
606N/A VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pDst, DixWriteAccess);
64N/A
64N/A if (stuff->dstDrawable != stuff->srcDrawable)
64N/A {
606N/A rc = dixLookupDrawable(&pSrc, stuff->srcDrawable, client, 0,
606N/A DixReadAccess);
606N/A if (rc != Success)
606N/A return rc;
64N/A if ((pDst->pScreen != pSrc->pScreen) || (pDst->depth != pSrc->depth))
64N/A {
64N/A client->errorValue = stuff->dstDrawable;
64N/A return (BadMatch);
64N/A }
64N/A }
64N/A else
64N/A pSrc = pDst;
64N/A
633N/A if (xtsol_policy(TSOL_RES_PIXEL, TSOL_READ, pSrc, 0,
633N/A client, TSOL_ALL, &(MAJOROP)))
64N/A {
64N/A /* ignore the error message for DnD zap effect */
64N/A return(client->noClientException);
64N/A }
633N/A if (xtsol_policy(TSOL_RES_PIXEL, TSOL_MODIFY, pDst, 0,
633N/A client, TSOL_ALL, &(MAJOROP)))
64N/A {
64N/A /* ignore the error message for DnD zap effect */
64N/A return(client->noClientException);
64N/A }
633N/A if (xtsol_policy(TSOL_RES_GC, TSOL_READ, NULL, stuff->gc,
633N/A client, TSOL_ALL, &(MAJOROP)))
64N/A {
64N/A client->errorValue = stuff->gc;
64N/A return (BadGC);
64N/A }
64N/A
64N/A status = (*TsolSavedProcVector[X_CopyArea])(client);
606N/A setClientTrustLevel(client, savedtrust);
64N/A
64N/A return (status);
64N/A}
64N/A
64N/Aint
606N/AProcTsolCopyPlane(ClientPtr client)
64N/A{
64N/A int savedtrust;
64N/A int status;
606N/A DrawablePtr psrcDraw, pdstDraw;
606N/A GC *pGC;
64N/A REQUEST(xCopyPlaneReq);
606N/A int rc;
64N/A
64N/A REQUEST_SIZE_MATCH(xCopyPlaneReq);
64N/A
606N/A savedtrust = setClientTrustLevel(client, XSecurityClientTrusted);
606N/A
606N/A VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pdstDraw, DixWriteAccess);
64N/A
64N/A if (stuff->dstDrawable != stuff->srcDrawable)
64N/A {
606N/A rc = dixLookupDrawable(&psrcDraw, stuff->srcDrawable, client, 0,
606N/A DixReadAccess);
606N/A if (rc != Success)
606N/A return rc;
606N/A
64N/A if (pdstDraw->pScreen != psrcDraw->pScreen)
64N/A {
64N/A client->errorValue = stuff->dstDrawable;
64N/A return (BadMatch);
64N/A }
64N/A }
64N/A else
64N/A psrcDraw = pdstDraw;
64N/A
633N/A if (xtsol_policy(TSOL_RES_PIXEL, TSOL_READ, psrcDraw, 0,
633N/A client, TSOL_ALL, &(MAJOROP)))
64N/A {
64N/A /* ignore the error message for DnD zap effect */
64N/A return(client->noClientException);
64N/A }
633N/A if (xtsol_policy(TSOL_RES_PIXEL, TSOL_MODIFY, pdstDraw, 0,
633N/A client, TSOL_ALL, &(MAJOROP)))
64N/A {
64N/A /* ignore the error message for DnD zap effect */
64N/A return(client->noClientException);
64N/A }
633N/A if (xtsol_policy(TSOL_RES_GC, TSOL_READ, NULL, stuff->gc,
633N/A client, TSOL_ALL, &(MAJOROP)))
64N/A {
64N/A client->errorValue = stuff->gc;
64N/A return (BadGC);
64N/A }
64N/A
64N/A status = (*TsolSavedProcVector[X_CopyPlane])(client);
606N/A setClientTrustLevel(client, savedtrust);
64N/A
64N/A return (status);
64N/A}