xace.c revision f7df2e56
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 */
36f7df2e56Smrgint
37f7df2e56SmrgXaceHookDispatch(ClientPtr client, int major)
384642e01fSmrg{
394642e01fSmrg    /* Call the audit begin callback, there is no return value. */
404642e01fSmrg    XaceAuditRec rec = { client, 0 };
414642e01fSmrg    CallCallbacks(&XaceHooks[XACE_AUDIT_BEGIN], &rec);
424642e01fSmrg
434642e01fSmrg    if (major < 128) {
44f7df2e56Smrg        /* Call the core dispatch hook */
45f7df2e56Smrg        XaceCoreDispatchRec drec = { client, Success /* default allow */  };
46f7df2e56Smrg        CallCallbacks(&XaceHooks[XACE_CORE_DISPATCH], &drec);
47f7df2e56Smrg        return drec.status;
48f7df2e56Smrg    }
49f7df2e56Smrg    else {
50f7df2e56Smrg        /* Call the extension dispatch hook */
51f7df2e56Smrg        ExtensionEntry *ext = GetExtensionEntry(major);
52f7df2e56Smrg        XaceExtAccessRec erec = { client, ext, DixUseAccess, Success };
53f7df2e56Smrg        if (ext)
54f7df2e56Smrg            CallCallbacks(&XaceHooks[XACE_EXT_DISPATCH], &erec);
55f7df2e56Smrg        /* On error, pretend extension doesn't exist */
56f7df2e56Smrg        return (erec.status == Success) ? Success : BadRequest;
574642e01fSmrg    }
584642e01fSmrg}
594642e01fSmrg
60f7df2e56Smrgint
61f7df2e56SmrgXaceHookPropertyAccess(ClientPtr client, WindowPtr pWin,
62f7df2e56Smrg                       PropertyPtr *ppProp, Mask access_mode)
634642e01fSmrg{
644642e01fSmrg    XacePropertyAccessRec rec = { client, pWin, ppProp, access_mode, Success };
654642e01fSmrg    CallCallbacks(&XaceHooks[XACE_PROPERTY_ACCESS], &rec);
664642e01fSmrg    return rec.status;
674642e01fSmrg}
684642e01fSmrg
69f7df2e56Smrgint
70f7df2e56SmrgXaceHookSelectionAccess(ClientPtr client, Selection ** ppSel, Mask access_mode)
714642e01fSmrg{
724642e01fSmrg    XaceSelectionAccessRec rec = { client, ppSel, access_mode, Success };
734642e01fSmrg    CallCallbacks(&XaceHooks[XACE_SELECTION_ACCESS], &rec);
744642e01fSmrg    return rec.status;
754642e01fSmrg}
764642e01fSmrg
77f7df2e56Smrgvoid
78f7df2e56SmrgXaceHookAuditEnd(ClientPtr ptr, int result)
794642e01fSmrg{
804642e01fSmrg    XaceAuditRec rec = { ptr, result };
814642e01fSmrg    /* call callbacks, there is no return value. */
824642e01fSmrg    CallCallbacks(&XaceHooks[XACE_AUDIT_END], &rec);
834642e01fSmrg}
8405b261ecSmrg
8505b261ecSmrg/* Entry point for hook functions.  Called by Xserver.
8605b261ecSmrg */
87f7df2e56Smrgint
88f7df2e56SmrgXaceHook(int hook, ...)
8905b261ecSmrg{
904202a189Smrg    union {
91f7df2e56Smrg        XaceResourceAccessRec res;
92f7df2e56Smrg        XaceDeviceAccessRec dev;
93f7df2e56Smrg        XaceSendAccessRec send;
94f7df2e56Smrg        XaceReceiveAccessRec recv;
95f7df2e56Smrg        XaceClientAccessRec client;
96f7df2e56Smrg        XaceExtAccessRec ext;
97f7df2e56Smrg        XaceServerAccessRec server;
98f7df2e56Smrg        XaceScreenAccessRec screen;
99f7df2e56Smrg        XaceAuthAvailRec auth;
100f7df2e56Smrg        XaceKeyAvailRec key;
1014202a189Smrg    } u;
102f7df2e56Smrg    int *prv = NULL;            /* points to return value from callback */
103f7df2e56Smrg    va_list ap;                 /* argument list */
10445bb0b75Smrg
10545bb0b75Smrg    if (!XaceHooks[hook])
106f7df2e56Smrg        return Success;
10745bb0b75Smrg
10805b261ecSmrg    va_start(ap, hook);
10905b261ecSmrg
11005b261ecSmrg    /* Marshal arguments for passing to callback.
11105b261ecSmrg     * Each callback has its own case, which sets up a structure to hold
11205b261ecSmrg     * the arguments and integer return parameter, or in some cases just
11305b261ecSmrg     * sets calldata directly to a single argument (with no return result)
11405b261ecSmrg     */
115f7df2e56Smrg    switch (hook) {
116f7df2e56Smrg    case XACE_RESOURCE_ACCESS:
117f7df2e56Smrg        u.res.client = va_arg(ap, ClientPtr);
118f7df2e56Smrg        u.res.id = va_arg(ap, XID);
119f7df2e56Smrg        u.res.rtype = va_arg(ap, RESTYPE);
120f7df2e56Smrg        u.res.res = va_arg(ap, void *);
121f7df2e56Smrg        u.res.ptype = va_arg(ap, RESTYPE);
122f7df2e56Smrg        u.res.parent = va_arg(ap, void *);
123f7df2e56Smrg        u.res.access_mode = va_arg(ap, Mask);
124f7df2e56Smrg
125f7df2e56Smrg        u.res.status = Success; /* default allow */
126f7df2e56Smrg        prv = &u.res.status;
127f7df2e56Smrg        break;
128f7df2e56Smrg    case XACE_DEVICE_ACCESS:
129f7df2e56Smrg        u.dev.client = va_arg(ap, ClientPtr);
130f7df2e56Smrg        u.dev.dev = va_arg(ap, DeviceIntPtr);
131f7df2e56Smrg        u.dev.access_mode = va_arg(ap, Mask);
132f7df2e56Smrg
133f7df2e56Smrg        u.dev.status = Success; /* default allow */
134f7df2e56Smrg        prv = &u.dev.status;
135f7df2e56Smrg        break;
136f7df2e56Smrg    case XACE_SEND_ACCESS:
137f7df2e56Smrg        u.send.client = va_arg(ap, ClientPtr);
138f7df2e56Smrg        u.send.dev = va_arg(ap, DeviceIntPtr);
139f7df2e56Smrg        u.send.pWin = va_arg(ap, WindowPtr);
140f7df2e56Smrg
141f7df2e56Smrg        u.send.events = va_arg(ap, xEventPtr);
142f7df2e56Smrg        u.send.count = va_arg(ap, int);
143f7df2e56Smrg
144f7df2e56Smrg        u.send.status = Success;        /* default allow */
145f7df2e56Smrg        prv = &u.send.status;
146f7df2e56Smrg        break;
147f7df2e56Smrg    case XACE_RECEIVE_ACCESS:
148f7df2e56Smrg        u.recv.client = va_arg(ap, ClientPtr);
149f7df2e56Smrg        u.recv.pWin = va_arg(ap, WindowPtr);
150f7df2e56Smrg
151f7df2e56Smrg        u.recv.events = va_arg(ap, xEventPtr);
152f7df2e56Smrg        u.recv.count = va_arg(ap, int);
153f7df2e56Smrg
154f7df2e56Smrg        u.recv.status = Success;        /* default allow */
155f7df2e56Smrg        prv = &u.recv.status;
156f7df2e56Smrg        break;
157f7df2e56Smrg    case XACE_CLIENT_ACCESS:
158f7df2e56Smrg        u.client.client = va_arg(ap, ClientPtr);
159f7df2e56Smrg        u.client.target = va_arg(ap, ClientPtr);
160f7df2e56Smrg        u.client.access_mode = va_arg(ap, Mask);
161f7df2e56Smrg
162f7df2e56Smrg        u.client.status = Success;      /* default allow */
163f7df2e56Smrg        prv = &u.client.status;
164f7df2e56Smrg        break;
165f7df2e56Smrg    case XACE_EXT_ACCESS:
166f7df2e56Smrg        u.ext.client = va_arg(ap, ClientPtr);
167f7df2e56Smrg
168f7df2e56Smrg        u.ext.ext = va_arg(ap, ExtensionEntry *);
169f7df2e56Smrg        u.ext.access_mode = DixGetAttrAccess;
170f7df2e56Smrg        u.ext.status = Success; /* default allow */
171f7df2e56Smrg        prv = &u.ext.status;
172f7df2e56Smrg        break;
173f7df2e56Smrg    case XACE_SERVER_ACCESS:
174f7df2e56Smrg        u.server.client = va_arg(ap, ClientPtr);
175f7df2e56Smrg        u.server.access_mode = va_arg(ap, Mask);
176f7df2e56Smrg
177f7df2e56Smrg        u.server.status = Success;      /* default allow */
178f7df2e56Smrg        prv = &u.server.status;
179f7df2e56Smrg        break;
180f7df2e56Smrg    case XACE_SCREEN_ACCESS:
181f7df2e56Smrg    case XACE_SCREENSAVER_ACCESS:
182f7df2e56Smrg        u.screen.client = va_arg(ap, ClientPtr);
183f7df2e56Smrg        u.screen.screen = va_arg(ap, ScreenPtr);
184f7df2e56Smrg        u.screen.access_mode = va_arg(ap, Mask);
185f7df2e56Smrg
186f7df2e56Smrg        u.screen.status = Success;      /* default allow */
187f7df2e56Smrg        prv = &u.screen.status;
188f7df2e56Smrg        break;
189f7df2e56Smrg    case XACE_AUTH_AVAIL:
190f7df2e56Smrg        u.auth.client = va_arg(ap, ClientPtr);
191f7df2e56Smrg        u.auth.authId = va_arg(ap, XID);
192f7df2e56Smrg
193f7df2e56Smrg        break;
194f7df2e56Smrg    case XACE_KEY_AVAIL:
195f7df2e56Smrg        u.key.event = va_arg(ap, xEventPtr);
196f7df2e56Smrg        u.key.keybd = va_arg(ap, DeviceIntPtr);
197f7df2e56Smrg        u.key.count = va_arg(ap, int);
198f7df2e56Smrg
199f7df2e56Smrg        break;
200f7df2e56Smrg    default:
201f7df2e56Smrg        va_end(ap);
202f7df2e56Smrg        return 0;               /* unimplemented hook number */
20305b261ecSmrg    }
20405b261ecSmrg    va_end(ap);
205f7df2e56Smrg
20605b261ecSmrg    /* call callbacks and return result, if any. */
2074202a189Smrg    CallCallbacks(&XaceHooks[hook], &u);
2084642e01fSmrg    return prv ? *prv : Success;
20905b261ecSmrg}
21005b261ecSmrg
211f7df2e56Smrg/* XaceHookIsSet
212f7df2e56Smrg *
213f7df2e56Smrg * Utility function to determine whether there are any callbacks listening on a
214f7df2e56Smrg * particular XACE hook.
215f7df2e56Smrg *
216f7df2e56Smrg * Returns non-zero if there is a callback, zero otherwise.
217f7df2e56Smrg */
218f7df2e56Smrgint
219f7df2e56SmrgXaceHookIsSet(int hook)
220f7df2e56Smrg{
221f7df2e56Smrg    if (hook < 0 || hook >= XACE_NUM_HOOKS)
222f7df2e56Smrg        return 0;
223f7df2e56Smrg    return XaceHooks[hook] != NULL;
224f7df2e56Smrg}
225f7df2e56Smrg
22605b261ecSmrg/* XaceCensorImage
22705b261ecSmrg *
22805b261ecSmrg * Called after pScreen->GetImage to prevent pieces or trusted windows from
22905b261ecSmrg * being returned in image data from an untrusted window.
23005b261ecSmrg *
23105b261ecSmrg * Arguments:
23205b261ecSmrg *	client is the client doing the GetImage.
23305b261ecSmrg *      pVisibleRegion is the visible region of the window.
23405b261ecSmrg *	widthBytesLine is the width in bytes of one horizontal line in pBuf.
23505b261ecSmrg *	pDraw is the source window.
23605b261ecSmrg *	x, y, w, h is the rectangle of image data from pDraw in pBuf.
23705b261ecSmrg *	format is the format of the image data in pBuf: ZPixmap or XYPixmap.
23805b261ecSmrg *	pBuf is the image data.
23905b261ecSmrg *
24005b261ecSmrg * Returns: nothing.
24105b261ecSmrg *
24205b261ecSmrg * Side Effects:
24305b261ecSmrg *	Any part of the rectangle (x, y, w, h) that is outside the visible
24405b261ecSmrg *	region of the window will be destroyed (overwritten) in pBuf.
24505b261ecSmrg */
24605b261ecSmrgvoid
247f7df2e56SmrgXaceCensorImage(ClientPtr client,
248f7df2e56Smrg                RegionPtr pVisibleRegion,
249f7df2e56Smrg                long widthBytesLine,
250f7df2e56Smrg                DrawablePtr pDraw,
251f7df2e56Smrg                int x, int y, int w, int h, unsigned int format, char *pBuf)
25205b261ecSmrg{
253f7df2e56Smrg    RegionRec imageRegion;      /* region representing x,y,w,h */
254f7df2e56Smrg    RegionRec censorRegion;     /* region to obliterate */
25505b261ecSmrg    BoxRec imageBox;
25605b261ecSmrg    int nRects;
25705b261ecSmrg
25805b261ecSmrg    imageBox.x1 = x;
25905b261ecSmrg    imageBox.y1 = y;
26005b261ecSmrg    imageBox.x2 = x + w;
26105b261ecSmrg    imageBox.y2 = y + h;
2624202a189Smrg    RegionInit(&imageRegion, &imageBox, 1);
2634202a189Smrg    RegionNull(&censorRegion);
26405b261ecSmrg
26505b261ecSmrg    /* censorRegion = imageRegion - visibleRegion */
2664202a189Smrg    RegionSubtract(&censorRegion, &imageRegion, pVisibleRegion);
2674202a189Smrg    nRects = RegionNumRects(&censorRegion);
268f7df2e56Smrg    if (nRects > 0) {           /* we have something to censor */
269f7df2e56Smrg        GCPtr pScratchGC = NULL;
270f7df2e56Smrg        PixmapPtr pPix = NULL;
271f7df2e56Smrg        xRectangle *pRects = NULL;
272f7df2e56Smrg        Bool failed = FALSE;
273f7df2e56Smrg        int depth = 1;
274f7df2e56Smrg        int bitsPerPixel = 1;
275f7df2e56Smrg        int i;
276f7df2e56Smrg        BoxPtr pBox;
277f7df2e56Smrg
278f7df2e56Smrg        /* convert region to list-of-rectangles for PolyFillRect */
279f7df2e56Smrg
280f7df2e56Smrg        pRects = malloc(nRects * sizeof(xRectangle));
281f7df2e56Smrg        if (!pRects) {
282f7df2e56Smrg            failed = TRUE;
283f7df2e56Smrg            goto failSafe;
284f7df2e56Smrg        }
285f7df2e56Smrg        for (pBox = RegionRects(&censorRegion), i = 0; i < nRects; i++, pBox++) {
286f7df2e56Smrg            pRects[i].x = pBox->x1;
287f7df2e56Smrg            pRects[i].y = pBox->y1 - imageBox.y1;
288f7df2e56Smrg            pRects[i].width = pBox->x2 - pBox->x1;
289f7df2e56Smrg            pRects[i].height = pBox->y2 - pBox->y1;
290f7df2e56Smrg        }
291f7df2e56Smrg
292f7df2e56Smrg        /* use pBuf as a fake pixmap */
293f7df2e56Smrg
294f7df2e56Smrg        if (format == ZPixmap) {
295f7df2e56Smrg            depth = pDraw->depth;
296f7df2e56Smrg            bitsPerPixel = pDraw->bitsPerPixel;
297f7df2e56Smrg        }
298f7df2e56Smrg
299f7df2e56Smrg        pPix = GetScratchPixmapHeader(pDraw->pScreen, w, h,
300f7df2e56Smrg                                      depth, bitsPerPixel,
301f7df2e56Smrg                                      widthBytesLine, (void *) pBuf);
302f7df2e56Smrg        if (!pPix) {
303f7df2e56Smrg            failed = TRUE;
304f7df2e56Smrg            goto failSafe;
305f7df2e56Smrg        }
306f7df2e56Smrg
307f7df2e56Smrg        pScratchGC = GetScratchGC(depth, pPix->drawable.pScreen);
308f7df2e56Smrg        if (!pScratchGC) {
309f7df2e56Smrg            failed = TRUE;
310f7df2e56Smrg            goto failSafe;
311f7df2e56Smrg        }
312f7df2e56Smrg
313f7df2e56Smrg        ValidateGC(&pPix->drawable, pScratchGC);
314f7df2e56Smrg        (*pScratchGC->ops->PolyFillRect) (&pPix->drawable,
315f7df2e56Smrg                                          pScratchGC, nRects, pRects);
316f7df2e56Smrg
317f7df2e56Smrg failSafe:
318f7df2e56Smrg        if (failed) {
319f7df2e56Smrg            /* Censoring was not completed above.  To be safe, wipe out
320f7df2e56Smrg             * all the image data so that nothing trusted gets out.
321f7df2e56Smrg             */
322f7df2e56Smrg            memset(pBuf, 0, (int) (widthBytesLine * h));
323f7df2e56Smrg        }
324f7df2e56Smrg        free(pRects);
325f7df2e56Smrg        if (pScratchGC)
326f7df2e56Smrg            FreeScratchGC(pScratchGC);
327f7df2e56Smrg        if (pPix)
328f7df2e56Smrg            FreeScratchPixmapHeader(pPix);
32905b261ecSmrg    }
3304202a189Smrg    RegionUninit(&imageRegion);
3314202a189Smrg    RegionUninit(&censorRegion);
332f7df2e56Smrg}                               /* XaceCensorImage */
3334202a189Smrg
3344202a189Smrg/*
3354202a189Smrg * Xtrans wrappers for use by modules
3364202a189Smrg */
337f7df2e56Smrgint
338f7df2e56SmrgXaceGetConnectionNumber(ClientPtr client)
3394202a189Smrg{
340f7df2e56Smrg    return GetClientFd(client);
3414202a189Smrg}
3424202a189Smrg
343f7df2e56Smrgint
344f7df2e56SmrgXaceIsLocal(ClientPtr client)
3454202a189Smrg{
346f7df2e56Smrg    return ClientIsLocal(client);
3474202a189Smrg}
348