xace.c revision 4642e01f
105b261ecSmrg/************************************************************
205b261ecSmrg
305b261ecSmrgAuthor: Eamon Walsh <ewalsh@epoch.ncsc.mil>
405b261ecSmrg
505b261ecSmrgPermission to use, copy, modify, distribute, and sell this software and its
605b261ecSmrgdocumentation for any purpose is hereby granted without fee, provided that
705b261ecSmrgthis permission notice appear in supporting documentation.  This permission
805b261ecSmrgnotice shall be included in all copies or substantial portions of the
905b261ecSmrgSoftware.
1005b261ecSmrg
1105b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1205b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1305b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
1405b261ecSmrgAUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1505b261ecSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1605b261ecSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1705b261ecSmrg
1805b261ecSmrg********************************************************/
1905b261ecSmrg
2005b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
2105b261ecSmrg#include <dix-config.h>
2205b261ecSmrg#endif
2305b261ecSmrg
2405b261ecSmrg#include <stdarg.h>
2505b261ecSmrg#include "scrnintstr.h"
264642e01fSmrg#include "extnsionst.h"
274642e01fSmrg#include "pixmapstr.h"
284642e01fSmrg#include "regionstr.h"
2905b261ecSmrg#include "gcstruct.h"
3005b261ecSmrg#include "xacestr.h"
3105b261ecSmrg
3205b261ecSmrgCallbackListPtr XaceHooks[XACE_NUM_HOOKS] = {0};
3305b261ecSmrg
344642e01fSmrg/* Special-cased hook functions.  Called by Xserver.
3505b261ecSmrg */
364642e01fSmrgint XaceHookDispatch(ClientPtr client, int major)
374642e01fSmrg{
384642e01fSmrg    /* Call the audit begin callback, there is no return value. */
394642e01fSmrg    XaceAuditRec rec = { client, 0 };
404642e01fSmrg    CallCallbacks(&XaceHooks[XACE_AUDIT_BEGIN], &rec);
414642e01fSmrg
424642e01fSmrg    if (major < 128) {
434642e01fSmrg	/* Call the core dispatch hook */
444642e01fSmrg	XaceCoreDispatchRec rec = { client, Success /* default allow */ };
454642e01fSmrg	CallCallbacks(&XaceHooks[XACE_CORE_DISPATCH], &rec);
464642e01fSmrg	return rec.status;
474642e01fSmrg    } else {
484642e01fSmrg	/* Call the extension dispatch hook */
494642e01fSmrg	ExtensionEntry *ext = GetExtensionEntry(major);
504642e01fSmrg	XaceExtAccessRec rec = { client, ext, DixUseAccess, Success };
514642e01fSmrg	if (ext)
524642e01fSmrg	    CallCallbacks(&XaceHooks[XACE_EXT_DISPATCH], &rec);
534642e01fSmrg	/* On error, pretend extension doesn't exist */
544642e01fSmrg	return (rec.status == Success) ? Success : BadRequest;
554642e01fSmrg    }
564642e01fSmrg}
574642e01fSmrg
584642e01fSmrgint XaceHookPropertyAccess(ClientPtr client, WindowPtr pWin,
594642e01fSmrg			   PropertyPtr *ppProp, Mask access_mode)
604642e01fSmrg{
614642e01fSmrg    XacePropertyAccessRec rec = { client, pWin, ppProp, access_mode, Success };
624642e01fSmrg    CallCallbacks(&XaceHooks[XACE_PROPERTY_ACCESS], &rec);
634642e01fSmrg    return rec.status;
644642e01fSmrg}
654642e01fSmrg
664642e01fSmrgint XaceHookSelectionAccess(ClientPtr client,
674642e01fSmrg			    Selection **ppSel, Mask access_mode)
684642e01fSmrg{
694642e01fSmrg    XaceSelectionAccessRec rec = { client, ppSel, access_mode, Success };
704642e01fSmrg    CallCallbacks(&XaceHooks[XACE_SELECTION_ACCESS], &rec);
714642e01fSmrg    return rec.status;
724642e01fSmrg}
734642e01fSmrg
744642e01fSmrgvoid XaceHookAuditEnd(ClientPtr ptr, int result)
754642e01fSmrg{
764642e01fSmrg    XaceAuditRec rec = { ptr, result };
774642e01fSmrg    /* call callbacks, there is no return value. */
784642e01fSmrg    CallCallbacks(&XaceHooks[XACE_AUDIT_END], &rec);
794642e01fSmrg}
8005b261ecSmrg
8105b261ecSmrg/* Entry point for hook functions.  Called by Xserver.
8205b261ecSmrg */
8305b261ecSmrgint XaceHook(int hook, ...)
8405b261ecSmrg{
8505b261ecSmrg    pointer calldata;	/* data passed to callback */
8605b261ecSmrg    int *prv = NULL;	/* points to return value from callback */
8705b261ecSmrg    va_list ap;		/* argument list */
8805b261ecSmrg    va_start(ap, hook);
8905b261ecSmrg
9005b261ecSmrg    /* Marshal arguments for passing to callback.
9105b261ecSmrg     * Each callback has its own case, which sets up a structure to hold
9205b261ecSmrg     * the arguments and integer return parameter, or in some cases just
9305b261ecSmrg     * sets calldata directly to a single argument (with no return result)
9405b261ecSmrg     */
9505b261ecSmrg    switch (hook)
9605b261ecSmrg    {
9705b261ecSmrg	case XACE_RESOURCE_ACCESS: {
9805b261ecSmrg	    XaceResourceAccessRec rec = {
9905b261ecSmrg		va_arg(ap, ClientPtr),
10005b261ecSmrg		va_arg(ap, XID),
10105b261ecSmrg		va_arg(ap, RESTYPE),
10205b261ecSmrg		va_arg(ap, pointer),
1034642e01fSmrg		va_arg(ap, RESTYPE),
1044642e01fSmrg		va_arg(ap, pointer),
1054642e01fSmrg		va_arg(ap, Mask),
1064642e01fSmrg		Success /* default allow */
10705b261ecSmrg	    };
10805b261ecSmrg	    calldata = &rec;
1094642e01fSmrg	    prv = &rec.status;
11005b261ecSmrg	    break;
11105b261ecSmrg	}
11205b261ecSmrg	case XACE_DEVICE_ACCESS: {
11305b261ecSmrg	    XaceDeviceAccessRec rec = {
11405b261ecSmrg		va_arg(ap, ClientPtr),
11505b261ecSmrg		va_arg(ap, DeviceIntPtr),
1164642e01fSmrg		va_arg(ap, Mask),
1174642e01fSmrg		Success /* default allow */
11805b261ecSmrg	    };
11905b261ecSmrg	    calldata = &rec;
1204642e01fSmrg	    prv = &rec.status;
12105b261ecSmrg	    break;
12205b261ecSmrg	}
1234642e01fSmrg	case XACE_SEND_ACCESS: {
1244642e01fSmrg	    XaceSendAccessRec rec = {
12505b261ecSmrg		va_arg(ap, ClientPtr),
1264642e01fSmrg		va_arg(ap, DeviceIntPtr),
12705b261ecSmrg		va_arg(ap, WindowPtr),
1284642e01fSmrg		va_arg(ap, xEventPtr),
1294642e01fSmrg		va_arg(ap, int),
1304642e01fSmrg		Success /* default allow */
13105b261ecSmrg	    };
13205b261ecSmrg	    calldata = &rec;
1334642e01fSmrg	    prv = &rec.status;
13405b261ecSmrg	    break;
13505b261ecSmrg	}
1364642e01fSmrg	case XACE_RECEIVE_ACCESS: {
1374642e01fSmrg	    XaceReceiveAccessRec rec = {
13805b261ecSmrg		va_arg(ap, ClientPtr),
1394642e01fSmrg		va_arg(ap, WindowPtr),
1404642e01fSmrg		va_arg(ap, xEventPtr),
1414642e01fSmrg		va_arg(ap, int),
1424642e01fSmrg		Success /* default allow */
14305b261ecSmrg	    };
14405b261ecSmrg	    calldata = &rec;
1454642e01fSmrg	    prv = &rec.status;
14605b261ecSmrg	    break;
14705b261ecSmrg	}
1484642e01fSmrg	case XACE_CLIENT_ACCESS: {
1494642e01fSmrg	    XaceClientAccessRec rec = {
15005b261ecSmrg		va_arg(ap, ClientPtr),
1514642e01fSmrg		va_arg(ap, ClientPtr),
1524642e01fSmrg		va_arg(ap, Mask),
1534642e01fSmrg		Success /* default allow */
15405b261ecSmrg	    };
15505b261ecSmrg	    calldata = &rec;
1564642e01fSmrg	    prv = &rec.status;
15705b261ecSmrg	    break;
15805b261ecSmrg	}
15905b261ecSmrg	case XACE_EXT_ACCESS: {
16005b261ecSmrg	    XaceExtAccessRec rec = {
16105b261ecSmrg		va_arg(ap, ClientPtr),
16205b261ecSmrg		va_arg(ap, ExtensionEntry*),
1634642e01fSmrg		DixGetAttrAccess,
1644642e01fSmrg		Success /* default allow */
16505b261ecSmrg	    };
16605b261ecSmrg	    calldata = &rec;
1674642e01fSmrg	    prv = &rec.status;
16805b261ecSmrg	    break;
16905b261ecSmrg	}
1704642e01fSmrg	case XACE_SERVER_ACCESS: {
1714642e01fSmrg	    XaceServerAccessRec rec = {
17205b261ecSmrg		va_arg(ap, ClientPtr),
17305b261ecSmrg		va_arg(ap, Mask),
1744642e01fSmrg		Success /* default allow */
17505b261ecSmrg	    };
17605b261ecSmrg	    calldata = &rec;
1774642e01fSmrg	    prv = &rec.status;
17805b261ecSmrg	    break;
17905b261ecSmrg	}
1804642e01fSmrg	case XACE_SCREEN_ACCESS:
1814642e01fSmrg	case XACE_SCREENSAVER_ACCESS: {
1824642e01fSmrg	    XaceScreenAccessRec rec = {
1834642e01fSmrg		va_arg(ap, ClientPtr),
1844642e01fSmrg		va_arg(ap, ScreenPtr),
1854642e01fSmrg		va_arg(ap, Mask),
1864642e01fSmrg		Success /* default allow */
18705b261ecSmrg	    };
18805b261ecSmrg	    calldata = &rec;
1894642e01fSmrg	    prv = &rec.status;
19005b261ecSmrg	    break;
19105b261ecSmrg	}
19205b261ecSmrg	case XACE_AUTH_AVAIL: {
19305b261ecSmrg	    XaceAuthAvailRec rec = {
19405b261ecSmrg		va_arg(ap, ClientPtr),
19505b261ecSmrg		va_arg(ap, XID)
19605b261ecSmrg	    };
19705b261ecSmrg	    calldata = &rec;
19805b261ecSmrg	    break;
19905b261ecSmrg	}
20005b261ecSmrg	case XACE_KEY_AVAIL: {
20105b261ecSmrg	    XaceKeyAvailRec rec = {
20205b261ecSmrg		va_arg(ap, xEventPtr),
20305b261ecSmrg		va_arg(ap, DeviceIntPtr),
20405b261ecSmrg		va_arg(ap, int)
20505b261ecSmrg	    };
20605b261ecSmrg	    calldata = &rec;
20705b261ecSmrg	    break;
20805b261ecSmrg	}
20905b261ecSmrg	default: {
21005b261ecSmrg	    va_end(ap);
21105b261ecSmrg	    return 0;	/* unimplemented hook number */
21205b261ecSmrg	}
21305b261ecSmrg    }
21405b261ecSmrg    va_end(ap);
21505b261ecSmrg
21605b261ecSmrg    /* call callbacks and return result, if any. */
21705b261ecSmrg    CallCallbacks(&XaceHooks[hook], calldata);
2184642e01fSmrg    return prv ? *prv : Success;
21905b261ecSmrg}
22005b261ecSmrg
22105b261ecSmrg/* XaceCensorImage
22205b261ecSmrg *
22305b261ecSmrg * Called after pScreen->GetImage to prevent pieces or trusted windows from
22405b261ecSmrg * being returned in image data from an untrusted window.
22505b261ecSmrg *
22605b261ecSmrg * Arguments:
22705b261ecSmrg *	client is the client doing the GetImage.
22805b261ecSmrg *      pVisibleRegion is the visible region of the window.
22905b261ecSmrg *	widthBytesLine is the width in bytes of one horizontal line in pBuf.
23005b261ecSmrg *	pDraw is the source window.
23105b261ecSmrg *	x, y, w, h is the rectangle of image data from pDraw in pBuf.
23205b261ecSmrg *	format is the format of the image data in pBuf: ZPixmap or XYPixmap.
23305b261ecSmrg *	pBuf is the image data.
23405b261ecSmrg *
23505b261ecSmrg * Returns: nothing.
23605b261ecSmrg *
23705b261ecSmrg * Side Effects:
23805b261ecSmrg *	Any part of the rectangle (x, y, w, h) that is outside the visible
23905b261ecSmrg *	region of the window will be destroyed (overwritten) in pBuf.
24005b261ecSmrg */
24105b261ecSmrgvoid
24205b261ecSmrgXaceCensorImage(client, pVisibleRegion, widthBytesLine, pDraw, x, y, w, h,
24305b261ecSmrg		format, pBuf)
24405b261ecSmrg    ClientPtr client;
24505b261ecSmrg    RegionPtr pVisibleRegion;
24605b261ecSmrg    long widthBytesLine;
24705b261ecSmrg    DrawablePtr pDraw;
24805b261ecSmrg    int x, y, w, h;
24905b261ecSmrg    unsigned int format;
25005b261ecSmrg    char * pBuf;
25105b261ecSmrg{
25205b261ecSmrg    ScreenPtr pScreen;
25305b261ecSmrg    RegionRec imageRegion;  /* region representing x,y,w,h */
25405b261ecSmrg    RegionRec censorRegion; /* region to obliterate */
25505b261ecSmrg    BoxRec imageBox;
25605b261ecSmrg    int nRects;
25705b261ecSmrg
25805b261ecSmrg    pScreen = pDraw->pScreen;
25905b261ecSmrg
26005b261ecSmrg    imageBox.x1 = x;
26105b261ecSmrg    imageBox.y1 = y;
26205b261ecSmrg    imageBox.x2 = x + w;
26305b261ecSmrg    imageBox.y2 = y + h;
26405b261ecSmrg    REGION_INIT(pScreen, &imageRegion, &imageBox, 1);
26505b261ecSmrg    REGION_NULL(pScreen, &censorRegion);
26605b261ecSmrg
26705b261ecSmrg    /* censorRegion = imageRegion - visibleRegion */
26805b261ecSmrg    REGION_SUBTRACT(pScreen, &censorRegion, &imageRegion, pVisibleRegion);
26905b261ecSmrg    nRects = REGION_NUM_RECTS(&censorRegion);
27005b261ecSmrg    if (nRects > 0)
27105b261ecSmrg    { /* we have something to censor */
27205b261ecSmrg	GCPtr pScratchGC = NULL;
27305b261ecSmrg	PixmapPtr pPix = NULL;
27405b261ecSmrg	xRectangle *pRects = NULL;
27505b261ecSmrg	Bool failed = FALSE;
27605b261ecSmrg	int depth = 1;
27705b261ecSmrg	int bitsPerPixel = 1;
27805b261ecSmrg	int i;
27905b261ecSmrg	BoxPtr pBox;
28005b261ecSmrg
28105b261ecSmrg	/* convert region to list-of-rectangles for PolyFillRect */
28205b261ecSmrg
2834642e01fSmrg	pRects = (xRectangle *)xalloc(nRects * sizeof(xRectangle));
28405b261ecSmrg	if (!pRects)
28505b261ecSmrg	{
28605b261ecSmrg	    failed = TRUE;
28705b261ecSmrg	    goto failSafe;
28805b261ecSmrg	}
28905b261ecSmrg	for (pBox = REGION_RECTS(&censorRegion), i = 0;
29005b261ecSmrg	     i < nRects;
29105b261ecSmrg	     i++, pBox++)
29205b261ecSmrg	{
29305b261ecSmrg	    pRects[i].x = pBox->x1;
29405b261ecSmrg	    pRects[i].y = pBox->y1 - imageBox.y1;
29505b261ecSmrg	    pRects[i].width  = pBox->x2 - pBox->x1;
29605b261ecSmrg	    pRects[i].height = pBox->y2 - pBox->y1;
29705b261ecSmrg	}
29805b261ecSmrg
29905b261ecSmrg	/* use pBuf as a fake pixmap */
30005b261ecSmrg
30105b261ecSmrg	if (format == ZPixmap)
30205b261ecSmrg	{
30305b261ecSmrg	    depth = pDraw->depth;
30405b261ecSmrg	    bitsPerPixel = pDraw->bitsPerPixel;
30505b261ecSmrg	}
30605b261ecSmrg
30705b261ecSmrg	pPix = GetScratchPixmapHeader(pDraw->pScreen, w, h,
30805b261ecSmrg		    depth, bitsPerPixel,
30905b261ecSmrg		    widthBytesLine, (pointer)pBuf);
31005b261ecSmrg	if (!pPix)
31105b261ecSmrg	{
31205b261ecSmrg	    failed = TRUE;
31305b261ecSmrg	    goto failSafe;
31405b261ecSmrg	}
31505b261ecSmrg
31605b261ecSmrg	pScratchGC = GetScratchGC(depth, pPix->drawable.pScreen);
31705b261ecSmrg	if (!pScratchGC)
31805b261ecSmrg	{
31905b261ecSmrg	    failed = TRUE;
32005b261ecSmrg	    goto failSafe;
32105b261ecSmrg	}
32205b261ecSmrg
32305b261ecSmrg	ValidateGC(&pPix->drawable, pScratchGC);
32405b261ecSmrg	(* pScratchGC->ops->PolyFillRect)(&pPix->drawable,
32505b261ecSmrg			    pScratchGC, nRects, pRects);
32605b261ecSmrg
32705b261ecSmrg    failSafe:
32805b261ecSmrg	if (failed)
32905b261ecSmrg	{
33005b261ecSmrg	    /* Censoring was not completed above.  To be safe, wipe out
33105b261ecSmrg	     * all the image data so that nothing trusted gets out.
33205b261ecSmrg	     */
33305b261ecSmrg	    bzero(pBuf, (int)(widthBytesLine * h));
33405b261ecSmrg	}
3354642e01fSmrg	if (pRects)     xfree(pRects);
33605b261ecSmrg	if (pScratchGC) FreeScratchGC(pScratchGC);
33705b261ecSmrg	if (pPix)       FreeScratchPixmapHeader(pPix);
33805b261ecSmrg    }
33905b261ecSmrg    REGION_UNINIT(pScreen, &imageRegion);
34005b261ecSmrg    REGION_UNINIT(pScreen, &censorRegion);
34105b261ecSmrg} /* XaceCensorImage */
342