1706f2543Smrg/************************************************************
2706f2543Smrg
3706f2543SmrgAuthor: Eamon Walsh <ewalsh@tycho.nsa.gov>
4706f2543Smrg
5706f2543SmrgPermission to use, copy, modify, distribute, and sell this software and its
6706f2543Smrgdocumentation for any purpose is hereby granted without fee, provided that
7706f2543Smrgthis permission notice appear in supporting documentation.  This permission
8706f2543Smrgnotice shall be included in all copies or substantial portions of the
9706f2543SmrgSoftware.
10706f2543Smrg
11706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12706f2543SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13706f2543SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
14706f2543SmrgAUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
15706f2543SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16706f2543SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17706f2543Smrg
18706f2543Smrg********************************************************/
19706f2543Smrg
20706f2543Smrg#ifdef HAVE_DIX_CONFIG_H
21706f2543Smrg#include <dix-config.h>
22706f2543Smrg#endif
23706f2543Smrg
24706f2543Smrg#include <stdarg.h>
25706f2543Smrg#include "scrnintstr.h"
26706f2543Smrg#include "extnsionst.h"
27706f2543Smrg#include "pixmapstr.h"
28706f2543Smrg#include "regionstr.h"
29706f2543Smrg#include "gcstruct.h"
30706f2543Smrg#include "xacestr.h"
31706f2543Smrg
32706f2543Smrg#define XSERV_t
33706f2543Smrg#define TRANS_SERVER
34706f2543Smrg#include <X11/Xtrans/Xtrans.h>
35706f2543Smrg#include "../os/osdep.h"
36706f2543Smrg
37706f2543Smrg_X_EXPORT CallbackListPtr XaceHooks[XACE_NUM_HOOKS] = {0};
38706f2543Smrg
39706f2543Smrg/* Special-cased hook functions.  Called by Xserver.
40706f2543Smrg */
41706f2543Smrgint XaceHookDispatch(ClientPtr client, int major)
42706f2543Smrg{
43706f2543Smrg    /* Call the audit begin callback, there is no return value. */
44706f2543Smrg    XaceAuditRec rec = { client, 0 };
45706f2543Smrg    CallCallbacks(&XaceHooks[XACE_AUDIT_BEGIN], &rec);
46706f2543Smrg
47706f2543Smrg    if (major < 128) {
48706f2543Smrg	/* Call the core dispatch hook */
49706f2543Smrg	XaceCoreDispatchRec rec = { client, Success /* default allow */ };
50706f2543Smrg	CallCallbacks(&XaceHooks[XACE_CORE_DISPATCH], &rec);
51706f2543Smrg	return rec.status;
52706f2543Smrg    } else {
53706f2543Smrg	/* Call the extension dispatch hook */
54706f2543Smrg	ExtensionEntry *ext = GetExtensionEntry(major);
55706f2543Smrg	XaceExtAccessRec rec = { client, ext, DixUseAccess, Success };
56706f2543Smrg	if (ext)
57706f2543Smrg	    CallCallbacks(&XaceHooks[XACE_EXT_DISPATCH], &rec);
58706f2543Smrg	/* On error, pretend extension doesn't exist */
59706f2543Smrg	return (rec.status == Success) ? Success : BadRequest;
60706f2543Smrg    }
61706f2543Smrg}
62706f2543Smrg
63706f2543Smrgint XaceHookPropertyAccess(ClientPtr client, WindowPtr pWin,
64706f2543Smrg			   PropertyPtr *ppProp, Mask access_mode)
65706f2543Smrg{
66706f2543Smrg    XacePropertyAccessRec rec = { client, pWin, ppProp, access_mode, Success };
67706f2543Smrg    CallCallbacks(&XaceHooks[XACE_PROPERTY_ACCESS], &rec);
68706f2543Smrg    return rec.status;
69706f2543Smrg}
70706f2543Smrg
71706f2543Smrgint XaceHookSelectionAccess(ClientPtr client,
72706f2543Smrg			    Selection **ppSel, Mask access_mode)
73706f2543Smrg{
74706f2543Smrg    XaceSelectionAccessRec rec = { client, ppSel, access_mode, Success };
75706f2543Smrg    CallCallbacks(&XaceHooks[XACE_SELECTION_ACCESS], &rec);
76706f2543Smrg    return rec.status;
77706f2543Smrg}
78706f2543Smrg
79706f2543Smrgvoid XaceHookAuditEnd(ClientPtr ptr, int result)
80706f2543Smrg{
81706f2543Smrg    XaceAuditRec rec = { ptr, result };
82706f2543Smrg    /* call callbacks, there is no return value. */
83706f2543Smrg    CallCallbacks(&XaceHooks[XACE_AUDIT_END], &rec);
84706f2543Smrg}
85706f2543Smrg
86706f2543Smrg/* Entry point for hook functions.  Called by Xserver.
87706f2543Smrg */
88706f2543Smrgint XaceHook(int hook, ...)
89706f2543Smrg{
90706f2543Smrg    union {
91706f2543Smrg	XaceResourceAccessRec res;
92706f2543Smrg	XaceDeviceAccessRec dev;
93706f2543Smrg	XaceSendAccessRec send;
94706f2543Smrg	XaceReceiveAccessRec recv;
95706f2543Smrg	XaceClientAccessRec client;
96706f2543Smrg	XaceExtAccessRec ext;
97706f2543Smrg	XaceServerAccessRec server;
98706f2543Smrg	XaceScreenAccessRec screen;
99706f2543Smrg	XaceAuthAvailRec auth;
100706f2543Smrg	XaceKeyAvailRec key;
101706f2543Smrg    } u;
102706f2543Smrg    int *prv = NULL;	/* points to return value from callback */
103706f2543Smrg    va_list ap;		/* argument list */
104706f2543Smrg
105706f2543Smrg    if (!XaceHooks[hook])
106706f2543Smrg	return Success;
107706f2543Smrg
108706f2543Smrg    va_start(ap, hook);
109706f2543Smrg
110706f2543Smrg    /* Marshal arguments for passing to callback.
111706f2543Smrg     * Each callback has its own case, which sets up a structure to hold
112706f2543Smrg     * the arguments and integer return parameter, or in some cases just
113706f2543Smrg     * sets calldata directly to a single argument (with no return result)
114706f2543Smrg     */
115706f2543Smrg    switch (hook)
116706f2543Smrg    {
117706f2543Smrg	case XACE_RESOURCE_ACCESS:
118706f2543Smrg	    u.res.client = va_arg(ap, ClientPtr);
119706f2543Smrg	    u.res.id = va_arg(ap, XID);
120706f2543Smrg	    u.res.rtype = va_arg(ap, RESTYPE);
121706f2543Smrg	    u.res.res = va_arg(ap, pointer);
122706f2543Smrg	    u.res.ptype = va_arg(ap, RESTYPE);
123706f2543Smrg	    u.res.parent = va_arg(ap, pointer);
124706f2543Smrg	    u.res.access_mode = va_arg(ap, Mask);
125706f2543Smrg	    u.res.status = Success; /* default allow */
126706f2543Smrg	    prv = &u.res.status;
127706f2543Smrg	    break;
128706f2543Smrg	case XACE_DEVICE_ACCESS:
129706f2543Smrg	    u.dev.client = va_arg(ap, ClientPtr);
130706f2543Smrg	    u.dev.dev = va_arg(ap, DeviceIntPtr);
131706f2543Smrg	    u.dev.access_mode = va_arg(ap, Mask);
132706f2543Smrg	    u.dev.status = Success; /* default allow */
133706f2543Smrg	    prv = &u.dev.status;
134706f2543Smrg	    break;
135706f2543Smrg	case XACE_SEND_ACCESS:
136706f2543Smrg	    u.send.client = va_arg(ap, ClientPtr);
137706f2543Smrg	    u.send.dev = va_arg(ap, DeviceIntPtr);
138706f2543Smrg	    u.send.pWin = va_arg(ap, WindowPtr);
139706f2543Smrg	    u.send.events = va_arg(ap, xEventPtr);
140706f2543Smrg	    u.send.count = va_arg(ap, int);
141706f2543Smrg	    u.send.status = Success; /* default allow */
142706f2543Smrg	    prv = &u.send.status;
143706f2543Smrg	    break;
144706f2543Smrg	case XACE_RECEIVE_ACCESS:
145706f2543Smrg	    u.recv.client = va_arg(ap, ClientPtr);
146706f2543Smrg	    u.recv.pWin = va_arg(ap, WindowPtr);
147706f2543Smrg	    u.recv.events = va_arg(ap, xEventPtr);
148706f2543Smrg	    u.recv.count = va_arg(ap, int);
149706f2543Smrg	    u.recv.status = Success; /* default allow */
150706f2543Smrg	    prv = &u.recv.status;
151706f2543Smrg	    break;
152706f2543Smrg	case XACE_CLIENT_ACCESS:
153706f2543Smrg	    u.client.client = va_arg(ap, ClientPtr);
154706f2543Smrg	    u.client.target = va_arg(ap, ClientPtr);
155706f2543Smrg	    u.client.access_mode = va_arg(ap, Mask);
156706f2543Smrg	    u.client.status = Success; /* default allow */
157706f2543Smrg	    prv = &u.client.status;
158706f2543Smrg	    break;
159706f2543Smrg	case XACE_EXT_ACCESS:
160706f2543Smrg	    u.ext.client = va_arg(ap, ClientPtr);
161706f2543Smrg	    u.ext.ext = va_arg(ap, ExtensionEntry*);
162706f2543Smrg	    u.ext.access_mode = DixGetAttrAccess;
163706f2543Smrg	    u.ext.status = Success; /* default allow */
164706f2543Smrg	    prv = &u.ext.status;
165706f2543Smrg	    break;
166706f2543Smrg	case XACE_SERVER_ACCESS:
167706f2543Smrg	    u.server.client = va_arg(ap, ClientPtr);
168706f2543Smrg	    u.server.access_mode = va_arg(ap, Mask);
169706f2543Smrg	    u.server.status = Success; /* default allow */
170706f2543Smrg	    prv = &u.server.status;
171706f2543Smrg	    break;
172706f2543Smrg	case XACE_SCREEN_ACCESS:
173706f2543Smrg	case XACE_SCREENSAVER_ACCESS:
174706f2543Smrg	    u.screen.client = va_arg(ap, ClientPtr);
175706f2543Smrg	    u.screen.screen = va_arg(ap, ScreenPtr);
176706f2543Smrg	    u.screen.access_mode = va_arg(ap, Mask);
177706f2543Smrg	    u.screen.status = Success; /* default allow */
178706f2543Smrg	    prv = &u.screen.status;
179706f2543Smrg	    break;
180706f2543Smrg	case XACE_AUTH_AVAIL:
181706f2543Smrg	    u.auth.client = va_arg(ap, ClientPtr);
182706f2543Smrg	    u.auth.authId = va_arg(ap, XID);
183706f2543Smrg	    break;
184706f2543Smrg	case XACE_KEY_AVAIL:
185706f2543Smrg	    u.key.event = va_arg(ap, xEventPtr);
186706f2543Smrg	    u.key.keybd = va_arg(ap, DeviceIntPtr);
187706f2543Smrg	    u.key.count = va_arg(ap, int);
188706f2543Smrg	    break;
189706f2543Smrg	default:
190706f2543Smrg	    va_end(ap);
191706f2543Smrg	    return 0;	/* unimplemented hook number */
192706f2543Smrg    }
193706f2543Smrg    va_end(ap);
194706f2543Smrg
195706f2543Smrg    /* call callbacks and return result, if any. */
196706f2543Smrg    CallCallbacks(&XaceHooks[hook], &u);
197706f2543Smrg    return prv ? *prv : Success;
198706f2543Smrg}
199706f2543Smrg
200706f2543Smrg/* XaceCensorImage
201706f2543Smrg *
202706f2543Smrg * Called after pScreen->GetImage to prevent pieces or trusted windows from
203706f2543Smrg * being returned in image data from an untrusted window.
204706f2543Smrg *
205706f2543Smrg * Arguments:
206706f2543Smrg *	client is the client doing the GetImage.
207706f2543Smrg *      pVisibleRegion is the visible region of the window.
208706f2543Smrg *	widthBytesLine is the width in bytes of one horizontal line in pBuf.
209706f2543Smrg *	pDraw is the source window.
210706f2543Smrg *	x, y, w, h is the rectangle of image data from pDraw in pBuf.
211706f2543Smrg *	format is the format of the image data in pBuf: ZPixmap or XYPixmap.
212706f2543Smrg *	pBuf is the image data.
213706f2543Smrg *
214706f2543Smrg * Returns: nothing.
215706f2543Smrg *
216706f2543Smrg * Side Effects:
217706f2543Smrg *	Any part of the rectangle (x, y, w, h) that is outside the visible
218706f2543Smrg *	region of the window will be destroyed (overwritten) in pBuf.
219706f2543Smrg */
220706f2543Smrgvoid
221706f2543SmrgXaceCensorImage(
222706f2543Smrg	ClientPtr client,
223706f2543Smrg	RegionPtr pVisibleRegion,
224706f2543Smrg	long widthBytesLine,
225706f2543Smrg	DrawablePtr pDraw,
226706f2543Smrg	int x, int y, int w, int h,
227706f2543Smrg	unsigned int format,
228706f2543Smrg	char *pBuf)
229706f2543Smrg{
230706f2543Smrg    RegionRec imageRegion;  /* region representing x,y,w,h */
231706f2543Smrg    RegionRec censorRegion; /* region to obliterate */
232706f2543Smrg    BoxRec imageBox;
233706f2543Smrg    int nRects;
234706f2543Smrg
235706f2543Smrg    imageBox.x1 = x;
236706f2543Smrg    imageBox.y1 = y;
237706f2543Smrg    imageBox.x2 = x + w;
238706f2543Smrg    imageBox.y2 = y + h;
239706f2543Smrg    RegionInit(&imageRegion, &imageBox, 1);
240706f2543Smrg    RegionNull(&censorRegion);
241706f2543Smrg
242706f2543Smrg    /* censorRegion = imageRegion - visibleRegion */
243706f2543Smrg    RegionSubtract(&censorRegion, &imageRegion, pVisibleRegion);
244706f2543Smrg    nRects = RegionNumRects(&censorRegion);
245706f2543Smrg    if (nRects > 0)
246706f2543Smrg    { /* we have something to censor */
247706f2543Smrg	GCPtr pScratchGC = NULL;
248706f2543Smrg	PixmapPtr pPix = NULL;
249706f2543Smrg	xRectangle *pRects = NULL;
250706f2543Smrg	Bool failed = FALSE;
251706f2543Smrg	int depth = 1;
252706f2543Smrg	int bitsPerPixel = 1;
253706f2543Smrg	int i;
254706f2543Smrg	BoxPtr pBox;
255706f2543Smrg
256706f2543Smrg	/* convert region to list-of-rectangles for PolyFillRect */
257706f2543Smrg
258706f2543Smrg	pRects = malloc(nRects * sizeof(xRectangle));
259706f2543Smrg	if (!pRects)
260706f2543Smrg	{
261706f2543Smrg	    failed = TRUE;
262706f2543Smrg	    goto failSafe;
263706f2543Smrg	}
264706f2543Smrg	for (pBox = RegionRects(&censorRegion), i = 0;
265706f2543Smrg	     i < nRects;
266706f2543Smrg	     i++, pBox++)
267706f2543Smrg	{
268706f2543Smrg	    pRects[i].x = pBox->x1;
269706f2543Smrg	    pRects[i].y = pBox->y1 - imageBox.y1;
270706f2543Smrg	    pRects[i].width  = pBox->x2 - pBox->x1;
271706f2543Smrg	    pRects[i].height = pBox->y2 - pBox->y1;
272706f2543Smrg	}
273706f2543Smrg
274706f2543Smrg	/* use pBuf as a fake pixmap */
275706f2543Smrg
276706f2543Smrg	if (format == ZPixmap)
277706f2543Smrg	{
278706f2543Smrg	    depth = pDraw->depth;
279706f2543Smrg	    bitsPerPixel = pDraw->bitsPerPixel;
280706f2543Smrg	}
281706f2543Smrg
282706f2543Smrg	pPix = GetScratchPixmapHeader(pDraw->pScreen, w, h,
283706f2543Smrg		    depth, bitsPerPixel,
284706f2543Smrg		    widthBytesLine, (pointer)pBuf);
285706f2543Smrg	if (!pPix)
286706f2543Smrg	{
287706f2543Smrg	    failed = TRUE;
288706f2543Smrg	    goto failSafe;
289706f2543Smrg	}
290706f2543Smrg
291706f2543Smrg	pScratchGC = GetScratchGC(depth, pPix->drawable.pScreen);
292706f2543Smrg	if (!pScratchGC)
293706f2543Smrg	{
294706f2543Smrg	    failed = TRUE;
295706f2543Smrg	    goto failSafe;
296706f2543Smrg	}
297706f2543Smrg
298706f2543Smrg	ValidateGC(&pPix->drawable, pScratchGC);
299706f2543Smrg	(* pScratchGC->ops->PolyFillRect)(&pPix->drawable,
300706f2543Smrg			    pScratchGC, nRects, pRects);
301706f2543Smrg
302706f2543Smrg    failSafe:
303706f2543Smrg	if (failed)
304706f2543Smrg	{
305706f2543Smrg	    /* Censoring was not completed above.  To be safe, wipe out
306706f2543Smrg	     * all the image data so that nothing trusted gets out.
307706f2543Smrg	     */
308706f2543Smrg	    memset(pBuf, 0, (int)(widthBytesLine * h));
309706f2543Smrg	}
310706f2543Smrg	free(pRects);
311706f2543Smrg	if (pScratchGC) FreeScratchGC(pScratchGC);
312706f2543Smrg	if (pPix)       FreeScratchPixmapHeader(pPix);
313706f2543Smrg    }
314706f2543Smrg    RegionUninit(&imageRegion);
315706f2543Smrg    RegionUninit(&censorRegion);
316706f2543Smrg} /* XaceCensorImage */
317706f2543Smrg
318706f2543Smrg/*
319706f2543Smrg * Xtrans wrappers for use by modules
320706f2543Smrg */
321706f2543Smrgint XaceGetConnectionNumber(ClientPtr client)
322706f2543Smrg{
323706f2543Smrg    XtransConnInfo ci = ((OsCommPtr)client->osPrivate)->trans_conn;
324706f2543Smrg    return _XSERVTransGetConnectionNumber(ci);
325706f2543Smrg}
326706f2543Smrg
327706f2543Smrgint XaceIsLocal(ClientPtr client)
328706f2543Smrg{
329706f2543Smrg    XtransConnInfo ci = ((OsCommPtr)client->osPrivate)->trans_conn;
330706f2543Smrg    return _XSERVTransIsLocal(ci);
331706f2543Smrg}
332