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