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