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