105b261ecSmrg/************************************************************
205b261ecSmrg
34202a189SmrgAuthor: Eamon Walsh <ewalsh@tycho.nsa.gov>
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
32f7df2e56Smrg_X_EXPORT CallbackListPtr XaceHooks[XACE_NUM_HOOKS] = { 0 };
3305b261ecSmrg
344642e01fSmrg/* Special-cased hook functions.  Called by Xserver.
3505b261ecSmrg */
367e31ba66Smrg#undef XaceHookDispatch
37f7df2e56Smrgint
38f7df2e56SmrgXaceHookDispatch(ClientPtr client, int major)
394642e01fSmrg{
407e31ba66Smrg    /* Call the extension dispatch hook */
417e31ba66Smrg    ExtensionEntry *ext = GetExtensionEntry(major);
427e31ba66Smrg    XaceExtAccessRec erec = { client, ext, DixUseAccess, Success };
437e31ba66Smrg    if (ext)
447e31ba66Smrg        CallCallbacks(&XaceHooks[XACE_EXT_DISPATCH], &erec);
457e31ba66Smrg    /* On error, pretend extension doesn't exist */
467e31ba66Smrg    return (erec.status == Success) ? Success : BadRequest;
474642e01fSmrg}
484642e01fSmrg
49f7df2e56Smrgint
50f7df2e56SmrgXaceHookPropertyAccess(ClientPtr client, WindowPtr pWin,
51f7df2e56Smrg                       PropertyPtr *ppProp, Mask access_mode)
524642e01fSmrg{
534642e01fSmrg    XacePropertyAccessRec rec = { client, pWin, ppProp, access_mode, Success };
544642e01fSmrg    CallCallbacks(&XaceHooks[XACE_PROPERTY_ACCESS], &rec);
554642e01fSmrg    return rec.status;
564642e01fSmrg}
574642e01fSmrg
58f7df2e56Smrgint
59f7df2e56SmrgXaceHookSelectionAccess(ClientPtr client, Selection ** ppSel, Mask access_mode)
604642e01fSmrg{
614642e01fSmrg    XaceSelectionAccessRec rec = { client, ppSel, access_mode, Success };
624642e01fSmrg    CallCallbacks(&XaceHooks[XACE_SELECTION_ACCESS], &rec);
634642e01fSmrg    return rec.status;
644642e01fSmrg}
654642e01fSmrg
6605b261ecSmrg/* Entry point for hook functions.  Called by Xserver.
6705b261ecSmrg */
68f7df2e56Smrgint
69f7df2e56SmrgXaceHook(int hook, ...)
7005b261ecSmrg{
714202a189Smrg    union {
72f7df2e56Smrg        XaceResourceAccessRec res;
73f7df2e56Smrg        XaceDeviceAccessRec dev;
74f7df2e56Smrg        XaceSendAccessRec send;
75f7df2e56Smrg        XaceReceiveAccessRec recv;
76f7df2e56Smrg        XaceClientAccessRec client;
77f7df2e56Smrg        XaceExtAccessRec ext;
78f7df2e56Smrg        XaceServerAccessRec server;
79f7df2e56Smrg        XaceScreenAccessRec screen;
80f7df2e56Smrg        XaceAuthAvailRec auth;
81f7df2e56Smrg        XaceKeyAvailRec key;
824202a189Smrg    } u;
83f7df2e56Smrg    int *prv = NULL;            /* points to return value from callback */
84f7df2e56Smrg    va_list ap;                 /* argument list */
8545bb0b75Smrg
8645bb0b75Smrg    if (!XaceHooks[hook])
87f7df2e56Smrg        return Success;
8845bb0b75Smrg
8905b261ecSmrg    va_start(ap, hook);
9005b261ecSmrg
9105b261ecSmrg    /* Marshal arguments for passing to callback.
9205b261ecSmrg     * Each callback has its own case, which sets up a structure to hold
9305b261ecSmrg     * the arguments and integer return parameter, or in some cases just
9405b261ecSmrg     * sets calldata directly to a single argument (with no return result)
9505b261ecSmrg     */
96f7df2e56Smrg    switch (hook) {
97f7df2e56Smrg    case XACE_RESOURCE_ACCESS:
98f7df2e56Smrg        u.res.client = va_arg(ap, ClientPtr);
99f7df2e56Smrg        u.res.id = va_arg(ap, XID);
100f7df2e56Smrg        u.res.rtype = va_arg(ap, RESTYPE);
101f7df2e56Smrg        u.res.res = va_arg(ap, void *);
102f7df2e56Smrg        u.res.ptype = va_arg(ap, RESTYPE);
103f7df2e56Smrg        u.res.parent = va_arg(ap, void *);
104f7df2e56Smrg        u.res.access_mode = va_arg(ap, Mask);
105f7df2e56Smrg
106f7df2e56Smrg        u.res.status = Success; /* default allow */
107f7df2e56Smrg        prv = &u.res.status;
108f7df2e56Smrg        break;
109f7df2e56Smrg    case XACE_DEVICE_ACCESS:
110f7df2e56Smrg        u.dev.client = va_arg(ap, ClientPtr);
111f7df2e56Smrg        u.dev.dev = va_arg(ap, DeviceIntPtr);
112f7df2e56Smrg        u.dev.access_mode = va_arg(ap, Mask);
113f7df2e56Smrg
114f7df2e56Smrg        u.dev.status = Success; /* default allow */
115f7df2e56Smrg        prv = &u.dev.status;
116f7df2e56Smrg        break;
117f7df2e56Smrg    case XACE_SEND_ACCESS:
118f7df2e56Smrg        u.send.client = va_arg(ap, ClientPtr);
119f7df2e56Smrg        u.send.dev = va_arg(ap, DeviceIntPtr);
120f7df2e56Smrg        u.send.pWin = va_arg(ap, WindowPtr);
121f7df2e56Smrg
122f7df2e56Smrg        u.send.events = va_arg(ap, xEventPtr);
123f7df2e56Smrg        u.send.count = va_arg(ap, int);
124f7df2e56Smrg
125f7df2e56Smrg        u.send.status = Success;        /* default allow */
126f7df2e56Smrg        prv = &u.send.status;
127f7df2e56Smrg        break;
128f7df2e56Smrg    case XACE_RECEIVE_ACCESS:
129f7df2e56Smrg        u.recv.client = va_arg(ap, ClientPtr);
130f7df2e56Smrg        u.recv.pWin = va_arg(ap, WindowPtr);
131f7df2e56Smrg
132f7df2e56Smrg        u.recv.events = va_arg(ap, xEventPtr);
133f7df2e56Smrg        u.recv.count = va_arg(ap, int);
134f7df2e56Smrg
135f7df2e56Smrg        u.recv.status = Success;        /* default allow */
136f7df2e56Smrg        prv = &u.recv.status;
137f7df2e56Smrg        break;
138f7df2e56Smrg    case XACE_CLIENT_ACCESS:
139f7df2e56Smrg        u.client.client = va_arg(ap, ClientPtr);
140f7df2e56Smrg        u.client.target = va_arg(ap, ClientPtr);
141f7df2e56Smrg        u.client.access_mode = va_arg(ap, Mask);
142f7df2e56Smrg
143f7df2e56Smrg        u.client.status = Success;      /* default allow */
144f7df2e56Smrg        prv = &u.client.status;
145f7df2e56Smrg        break;
146f7df2e56Smrg    case XACE_EXT_ACCESS:
147f7df2e56Smrg        u.ext.client = va_arg(ap, ClientPtr);
148f7df2e56Smrg
149f7df2e56Smrg        u.ext.ext = va_arg(ap, ExtensionEntry *);
150f7df2e56Smrg        u.ext.access_mode = DixGetAttrAccess;
151f7df2e56Smrg        u.ext.status = Success; /* default allow */
152f7df2e56Smrg        prv = &u.ext.status;
153f7df2e56Smrg        break;
154f7df2e56Smrg    case XACE_SERVER_ACCESS:
155f7df2e56Smrg        u.server.client = va_arg(ap, ClientPtr);
156f7df2e56Smrg        u.server.access_mode = va_arg(ap, Mask);
157f7df2e56Smrg
158f7df2e56Smrg        u.server.status = Success;      /* default allow */
159f7df2e56Smrg        prv = &u.server.status;
160f7df2e56Smrg        break;
161f7df2e56Smrg    case XACE_SCREEN_ACCESS:
162f7df2e56Smrg    case XACE_SCREENSAVER_ACCESS:
163f7df2e56Smrg        u.screen.client = va_arg(ap, ClientPtr);
164f7df2e56Smrg        u.screen.screen = va_arg(ap, ScreenPtr);
165f7df2e56Smrg        u.screen.access_mode = va_arg(ap, Mask);
166f7df2e56Smrg
167f7df2e56Smrg        u.screen.status = Success;      /* default allow */
168f7df2e56Smrg        prv = &u.screen.status;
169f7df2e56Smrg        break;
170f7df2e56Smrg    case XACE_AUTH_AVAIL:
171f7df2e56Smrg        u.auth.client = va_arg(ap, ClientPtr);
172f7df2e56Smrg        u.auth.authId = va_arg(ap, XID);
173f7df2e56Smrg
174f7df2e56Smrg        break;
175f7df2e56Smrg    case XACE_KEY_AVAIL:
176f7df2e56Smrg        u.key.event = va_arg(ap, xEventPtr);
177f7df2e56Smrg        u.key.keybd = va_arg(ap, DeviceIntPtr);
178f7df2e56Smrg        u.key.count = va_arg(ap, int);
179f7df2e56Smrg
180f7df2e56Smrg        break;
181f7df2e56Smrg    default:
182f7df2e56Smrg        va_end(ap);
183f7df2e56Smrg        return 0;               /* unimplemented hook number */
18405b261ecSmrg    }
18505b261ecSmrg    va_end(ap);
186f7df2e56Smrg
18705b261ecSmrg    /* call callbacks and return result, if any. */
1884202a189Smrg    CallCallbacks(&XaceHooks[hook], &u);
1894642e01fSmrg    return prv ? *prv : Success;
19005b261ecSmrg}
19105b261ecSmrg
192f7df2e56Smrg/* XaceHookIsSet
193f7df2e56Smrg *
194f7df2e56Smrg * Utility function to determine whether there are any callbacks listening on a
195f7df2e56Smrg * particular XACE hook.
196f7df2e56Smrg *
197f7df2e56Smrg * Returns non-zero if there is a callback, zero otherwise.
198f7df2e56Smrg */
199f7df2e56Smrgint
200f7df2e56SmrgXaceHookIsSet(int hook)
201f7df2e56Smrg{
202f7df2e56Smrg    if (hook < 0 || hook >= XACE_NUM_HOOKS)
203f7df2e56Smrg        return 0;
204f7df2e56Smrg    return XaceHooks[hook] != NULL;
205f7df2e56Smrg}
206f7df2e56Smrg
20705b261ecSmrg/* XaceCensorImage
20805b261ecSmrg *
20905b261ecSmrg * Called after pScreen->GetImage to prevent pieces or trusted windows from
21005b261ecSmrg * being returned in image data from an untrusted window.
21105b261ecSmrg *
21205b261ecSmrg * Arguments:
21305b261ecSmrg *	client is the client doing the GetImage.
21405b261ecSmrg *      pVisibleRegion is the visible region of the window.
21505b261ecSmrg *	widthBytesLine is the width in bytes of one horizontal line in pBuf.
21605b261ecSmrg *	pDraw is the source window.
21705b261ecSmrg *	x, y, w, h is the rectangle of image data from pDraw in pBuf.
21805b261ecSmrg *	format is the format of the image data in pBuf: ZPixmap or XYPixmap.
21905b261ecSmrg *	pBuf is the image data.
22005b261ecSmrg *
22105b261ecSmrg * Returns: nothing.
22205b261ecSmrg *
22305b261ecSmrg * Side Effects:
22405b261ecSmrg *	Any part of the rectangle (x, y, w, h) that is outside the visible
22505b261ecSmrg *	region of the window will be destroyed (overwritten) in pBuf.
22605b261ecSmrg */
22705b261ecSmrgvoid
228f7df2e56SmrgXaceCensorImage(ClientPtr client,
229f7df2e56Smrg                RegionPtr pVisibleRegion,
230f7df2e56Smrg                long widthBytesLine,
231f7df2e56Smrg                DrawablePtr pDraw,
232f7df2e56Smrg                int x, int y, int w, int h, unsigned int format, char *pBuf)
23305b261ecSmrg{
234f7df2e56Smrg    RegionRec imageRegion;      /* region representing x,y,w,h */
235f7df2e56Smrg    RegionRec censorRegion;     /* region to obliterate */
23605b261ecSmrg    BoxRec imageBox;
23705b261ecSmrg    int nRects;
23805b261ecSmrg
2397e31ba66Smrg    imageBox.x1 = pDraw->x + x;
2407e31ba66Smrg    imageBox.y1 = pDraw->y + y;
2417e31ba66Smrg    imageBox.x2 = pDraw->x + x + w;
2427e31ba66Smrg    imageBox.y2 = pDraw->y + y + h;
2434202a189Smrg    RegionInit(&imageRegion, &imageBox, 1);
2444202a189Smrg    RegionNull(&censorRegion);
24505b261ecSmrg
24605b261ecSmrg    /* censorRegion = imageRegion - visibleRegion */
2474202a189Smrg    RegionSubtract(&censorRegion, &imageRegion, pVisibleRegion);
2484202a189Smrg    nRects = RegionNumRects(&censorRegion);
249f7df2e56Smrg    if (nRects > 0) {           /* we have something to censor */
250f7df2e56Smrg        GCPtr pScratchGC = NULL;
251f7df2e56Smrg        PixmapPtr pPix = NULL;
252f7df2e56Smrg        xRectangle *pRects = NULL;
253f7df2e56Smrg        Bool failed = FALSE;
254f7df2e56Smrg        int depth = 1;
255f7df2e56Smrg        int bitsPerPixel = 1;
256f7df2e56Smrg        int i;
257f7df2e56Smrg        BoxPtr pBox;
258f7df2e56Smrg
259f7df2e56Smrg        /* convert region to list-of-rectangles for PolyFillRect */
260f7df2e56Smrg
261f7df2e56Smrg        pRects = malloc(nRects * sizeof(xRectangle));
262f7df2e56Smrg        if (!pRects) {
263f7df2e56Smrg            failed = TRUE;
264f7df2e56Smrg            goto failSafe;
265f7df2e56Smrg        }
266f7df2e56Smrg        for (pBox = RegionRects(&censorRegion), i = 0; i < nRects; i++, pBox++) {
2677e31ba66Smrg            pRects[i].x = pBox->x1 - imageBox.x1;
268f7df2e56Smrg            pRects[i].y = pBox->y1 - imageBox.y1;
269f7df2e56Smrg            pRects[i].width = pBox->x2 - pBox->x1;
270f7df2e56Smrg            pRects[i].height = pBox->y2 - pBox->y1;
271f7df2e56Smrg        }
272f7df2e56Smrg
273f7df2e56Smrg        /* use pBuf as a fake pixmap */
274f7df2e56Smrg
275f7df2e56Smrg        if (format == ZPixmap) {
276f7df2e56Smrg            depth = pDraw->depth;
277f7df2e56Smrg            bitsPerPixel = pDraw->bitsPerPixel;
278f7df2e56Smrg        }
279f7df2e56Smrg
280f7df2e56Smrg        pPix = GetScratchPixmapHeader(pDraw->pScreen, w, h,
281f7df2e56Smrg                                      depth, bitsPerPixel,
282f7df2e56Smrg                                      widthBytesLine, (void *) pBuf);
283f7df2e56Smrg        if (!pPix) {
284f7df2e56Smrg            failed = TRUE;
285f7df2e56Smrg            goto failSafe;
286f7df2e56Smrg        }
287f7df2e56Smrg
288f7df2e56Smrg        pScratchGC = GetScratchGC(depth, pPix->drawable.pScreen);
289f7df2e56Smrg        if (!pScratchGC) {
290f7df2e56Smrg            failed = TRUE;
291f7df2e56Smrg            goto failSafe;
292f7df2e56Smrg        }
293f7df2e56Smrg
294f7df2e56Smrg        ValidateGC(&pPix->drawable, pScratchGC);
295f7df2e56Smrg        (*pScratchGC->ops->PolyFillRect) (&pPix->drawable,
296f7df2e56Smrg                                          pScratchGC, nRects, pRects);
297f7df2e56Smrg
298f7df2e56Smrg failSafe:
299f7df2e56Smrg        if (failed) {
300f7df2e56Smrg            /* Censoring was not completed above.  To be safe, wipe out
301f7df2e56Smrg             * all the image data so that nothing trusted gets out.
302f7df2e56Smrg             */
303f7df2e56Smrg            memset(pBuf, 0, (int) (widthBytesLine * h));
304f7df2e56Smrg        }
305f7df2e56Smrg        free(pRects);
306f7df2e56Smrg        if (pScratchGC)
307f7df2e56Smrg            FreeScratchGC(pScratchGC);
308f7df2e56Smrg        if (pPix)
309f7df2e56Smrg            FreeScratchPixmapHeader(pPix);
31005b261ecSmrg    }
3114202a189Smrg    RegionUninit(&imageRegion);
3124202a189Smrg    RegionUninit(&censorRegion);
313f7df2e56Smrg}                               /* XaceCensorImage */
3144202a189Smrg
3154202a189Smrg/*
3164202a189Smrg * Xtrans wrappers for use by modules
3174202a189Smrg */
318f7df2e56Smrgint
319f7df2e56SmrgXaceGetConnectionNumber(ClientPtr client)
3204202a189Smrg{
321f7df2e56Smrg    return GetClientFd(client);
3224202a189Smrg}
3234202a189Smrg
324f7df2e56Smrgint
325f7df2e56SmrgXaceIsLocal(ClientPtr client)
3264202a189Smrg{
327f7df2e56Smrg    return ClientIsLocal(client);
3284202a189Smrg}
329