1706f2543Smrg/************************************************************ 2706f2543Smrg 3706f2543SmrgAuthor: Eamon Walsh <ewalsh@tycho.nsa.gov> 4706f2543Smrg 5706f2543SmrgPermission to use, copy, modify, distribute, and sell this software and its 6706f2543Smrgdocumentation for any purpose is hereby granted without fee, provided that 7706f2543Smrgthis permission notice appear in supporting documentation. This permission 8706f2543Smrgnotice shall be included in all copies or substantial portions of the 9706f2543SmrgSoftware. 10706f2543Smrg 11706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12706f2543SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13706f2543SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14706f2543SmrgAUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 15706f2543SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 16706f2543SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17706f2543Smrg 18706f2543Smrg********************************************************/ 19706f2543Smrg 20706f2543Smrg#ifdef HAVE_DIX_CONFIG_H 21706f2543Smrg#include <dix-config.h> 22706f2543Smrg#endif 23706f2543Smrg 24706f2543Smrg#include <stdarg.h> 25706f2543Smrg#include "scrnintstr.h" 26706f2543Smrg#include "extnsionst.h" 27706f2543Smrg#include "pixmapstr.h" 28706f2543Smrg#include "regionstr.h" 29706f2543Smrg#include "gcstruct.h" 30706f2543Smrg#include "xacestr.h" 31706f2543Smrg 32706f2543Smrg#define XSERV_t 33706f2543Smrg#define TRANS_SERVER 34706f2543Smrg#include <X11/Xtrans/Xtrans.h> 35706f2543Smrg#include "../os/osdep.h" 36706f2543Smrg 37706f2543Smrg_X_EXPORT CallbackListPtr XaceHooks[XACE_NUM_HOOKS] = {0}; 38706f2543Smrg 39706f2543Smrg/* Special-cased hook functions. Called by Xserver. 40706f2543Smrg */ 41706f2543Smrgint XaceHookDispatch(ClientPtr client, int major) 42706f2543Smrg{ 43706f2543Smrg /* Call the audit begin callback, there is no return value. */ 44706f2543Smrg XaceAuditRec rec = { client, 0 }; 45706f2543Smrg CallCallbacks(&XaceHooks[XACE_AUDIT_BEGIN], &rec); 46706f2543Smrg 47706f2543Smrg if (major < 128) { 48706f2543Smrg /* Call the core dispatch hook */ 49706f2543Smrg XaceCoreDispatchRec rec = { client, Success /* default allow */ }; 50706f2543Smrg CallCallbacks(&XaceHooks[XACE_CORE_DISPATCH], &rec); 51706f2543Smrg return rec.status; 52706f2543Smrg } else { 53706f2543Smrg /* Call the extension dispatch hook */ 54706f2543Smrg ExtensionEntry *ext = GetExtensionEntry(major); 55706f2543Smrg XaceExtAccessRec rec = { client, ext, DixUseAccess, Success }; 56706f2543Smrg if (ext) 57706f2543Smrg CallCallbacks(&XaceHooks[XACE_EXT_DISPATCH], &rec); 58706f2543Smrg /* On error, pretend extension doesn't exist */ 59706f2543Smrg return (rec.status == Success) ? Success : BadRequest; 60706f2543Smrg } 61706f2543Smrg} 62706f2543Smrg 63706f2543Smrgint XaceHookPropertyAccess(ClientPtr client, WindowPtr pWin, 64706f2543Smrg PropertyPtr *ppProp, Mask access_mode) 65706f2543Smrg{ 66706f2543Smrg XacePropertyAccessRec rec = { client, pWin, ppProp, access_mode, Success }; 67706f2543Smrg CallCallbacks(&XaceHooks[XACE_PROPERTY_ACCESS], &rec); 68706f2543Smrg return rec.status; 69706f2543Smrg} 70706f2543Smrg 71706f2543Smrgint XaceHookSelectionAccess(ClientPtr client, 72706f2543Smrg Selection **ppSel, Mask access_mode) 73706f2543Smrg{ 74706f2543Smrg XaceSelectionAccessRec rec = { client, ppSel, access_mode, Success }; 75706f2543Smrg CallCallbacks(&XaceHooks[XACE_SELECTION_ACCESS], &rec); 76706f2543Smrg return rec.status; 77706f2543Smrg} 78706f2543Smrg 79706f2543Smrgvoid XaceHookAuditEnd(ClientPtr ptr, int result) 80706f2543Smrg{ 81706f2543Smrg XaceAuditRec rec = { ptr, result }; 82706f2543Smrg /* call callbacks, there is no return value. */ 83706f2543Smrg CallCallbacks(&XaceHooks[XACE_AUDIT_END], &rec); 84706f2543Smrg} 85706f2543Smrg 86706f2543Smrg/* Entry point for hook functions. Called by Xserver. 87706f2543Smrg */ 88706f2543Smrgint XaceHook(int hook, ...) 89706f2543Smrg{ 90706f2543Smrg union { 91706f2543Smrg XaceResourceAccessRec res; 92706f2543Smrg XaceDeviceAccessRec dev; 93706f2543Smrg XaceSendAccessRec send; 94706f2543Smrg XaceReceiveAccessRec recv; 95706f2543Smrg XaceClientAccessRec client; 96706f2543Smrg XaceExtAccessRec ext; 97706f2543Smrg XaceServerAccessRec server; 98706f2543Smrg XaceScreenAccessRec screen; 99706f2543Smrg XaceAuthAvailRec auth; 100706f2543Smrg XaceKeyAvailRec key; 101706f2543Smrg } u; 102706f2543Smrg int *prv = NULL; /* points to return value from callback */ 103706f2543Smrg va_list ap; /* argument list */ 104706f2543Smrg 105706f2543Smrg if (!XaceHooks[hook]) 106706f2543Smrg return Success; 107706f2543Smrg 108706f2543Smrg va_start(ap, hook); 109706f2543Smrg 110706f2543Smrg /* Marshal arguments for passing to callback. 111706f2543Smrg * Each callback has its own case, which sets up a structure to hold 112706f2543Smrg * the arguments and integer return parameter, or in some cases just 113706f2543Smrg * sets calldata directly to a single argument (with no return result) 114706f2543Smrg */ 115706f2543Smrg switch (hook) 116706f2543Smrg { 117706f2543Smrg case XACE_RESOURCE_ACCESS: 118706f2543Smrg u.res.client = va_arg(ap, ClientPtr); 119706f2543Smrg u.res.id = va_arg(ap, XID); 120706f2543Smrg u.res.rtype = va_arg(ap, RESTYPE); 121706f2543Smrg u.res.res = va_arg(ap, pointer); 122706f2543Smrg u.res.ptype = va_arg(ap, RESTYPE); 123706f2543Smrg u.res.parent = va_arg(ap, pointer); 124706f2543Smrg u.res.access_mode = va_arg(ap, Mask); 125706f2543Smrg u.res.status = Success; /* default allow */ 126706f2543Smrg prv = &u.res.status; 127706f2543Smrg break; 128706f2543Smrg case XACE_DEVICE_ACCESS: 129706f2543Smrg u.dev.client = va_arg(ap, ClientPtr); 130706f2543Smrg u.dev.dev = va_arg(ap, DeviceIntPtr); 131706f2543Smrg u.dev.access_mode = va_arg(ap, Mask); 132706f2543Smrg u.dev.status = Success; /* default allow */ 133706f2543Smrg prv = &u.dev.status; 134706f2543Smrg break; 135706f2543Smrg case XACE_SEND_ACCESS: 136706f2543Smrg u.send.client = va_arg(ap, ClientPtr); 137706f2543Smrg u.send.dev = va_arg(ap, DeviceIntPtr); 138706f2543Smrg u.send.pWin = va_arg(ap, WindowPtr); 139706f2543Smrg u.send.events = va_arg(ap, xEventPtr); 140706f2543Smrg u.send.count = va_arg(ap, int); 141706f2543Smrg u.send.status = Success; /* default allow */ 142706f2543Smrg prv = &u.send.status; 143706f2543Smrg break; 144706f2543Smrg case XACE_RECEIVE_ACCESS: 145706f2543Smrg u.recv.client = va_arg(ap, ClientPtr); 146706f2543Smrg u.recv.pWin = va_arg(ap, WindowPtr); 147706f2543Smrg u.recv.events = va_arg(ap, xEventPtr); 148706f2543Smrg u.recv.count = va_arg(ap, int); 149706f2543Smrg u.recv.status = Success; /* default allow */ 150706f2543Smrg prv = &u.recv.status; 151706f2543Smrg break; 152706f2543Smrg case XACE_CLIENT_ACCESS: 153706f2543Smrg u.client.client = va_arg(ap, ClientPtr); 154706f2543Smrg u.client.target = va_arg(ap, ClientPtr); 155706f2543Smrg u.client.access_mode = va_arg(ap, Mask); 156706f2543Smrg u.client.status = Success; /* default allow */ 157706f2543Smrg prv = &u.client.status; 158706f2543Smrg break; 159706f2543Smrg case XACE_EXT_ACCESS: 160706f2543Smrg u.ext.client = va_arg(ap, ClientPtr); 161706f2543Smrg u.ext.ext = va_arg(ap, ExtensionEntry*); 162706f2543Smrg u.ext.access_mode = DixGetAttrAccess; 163706f2543Smrg u.ext.status = Success; /* default allow */ 164706f2543Smrg prv = &u.ext.status; 165706f2543Smrg break; 166706f2543Smrg case XACE_SERVER_ACCESS: 167706f2543Smrg u.server.client = va_arg(ap, ClientPtr); 168706f2543Smrg u.server.access_mode = va_arg(ap, Mask); 169706f2543Smrg u.server.status = Success; /* default allow */ 170706f2543Smrg prv = &u.server.status; 171706f2543Smrg break; 172706f2543Smrg case XACE_SCREEN_ACCESS: 173706f2543Smrg case XACE_SCREENSAVER_ACCESS: 174706f2543Smrg u.screen.client = va_arg(ap, ClientPtr); 175706f2543Smrg u.screen.screen = va_arg(ap, ScreenPtr); 176706f2543Smrg u.screen.access_mode = va_arg(ap, Mask); 177706f2543Smrg u.screen.status = Success; /* default allow */ 178706f2543Smrg prv = &u.screen.status; 179706f2543Smrg break; 180706f2543Smrg case XACE_AUTH_AVAIL: 181706f2543Smrg u.auth.client = va_arg(ap, ClientPtr); 182706f2543Smrg u.auth.authId = va_arg(ap, XID); 183706f2543Smrg break; 184706f2543Smrg case XACE_KEY_AVAIL: 185706f2543Smrg u.key.event = va_arg(ap, xEventPtr); 186706f2543Smrg u.key.keybd = va_arg(ap, DeviceIntPtr); 187706f2543Smrg u.key.count = va_arg(ap, int); 188706f2543Smrg break; 189706f2543Smrg default: 190706f2543Smrg va_end(ap); 191706f2543Smrg return 0; /* unimplemented hook number */ 192706f2543Smrg } 193706f2543Smrg va_end(ap); 194706f2543Smrg 195706f2543Smrg /* call callbacks and return result, if any. */ 196706f2543Smrg CallCallbacks(&XaceHooks[hook], &u); 197706f2543Smrg return prv ? *prv : Success; 198706f2543Smrg} 199706f2543Smrg 200706f2543Smrg/* XaceCensorImage 201706f2543Smrg * 202706f2543Smrg * Called after pScreen->GetImage to prevent pieces or trusted windows from 203706f2543Smrg * being returned in image data from an untrusted window. 204706f2543Smrg * 205706f2543Smrg * Arguments: 206706f2543Smrg * client is the client doing the GetImage. 207706f2543Smrg * pVisibleRegion is the visible region of the window. 208706f2543Smrg * widthBytesLine is the width in bytes of one horizontal line in pBuf. 209706f2543Smrg * pDraw is the source window. 210706f2543Smrg * x, y, w, h is the rectangle of image data from pDraw in pBuf. 211706f2543Smrg * format is the format of the image data in pBuf: ZPixmap or XYPixmap. 212706f2543Smrg * pBuf is the image data. 213706f2543Smrg * 214706f2543Smrg * Returns: nothing. 215706f2543Smrg * 216706f2543Smrg * Side Effects: 217706f2543Smrg * Any part of the rectangle (x, y, w, h) that is outside the visible 218706f2543Smrg * region of the window will be destroyed (overwritten) in pBuf. 219706f2543Smrg */ 220706f2543Smrgvoid 221706f2543SmrgXaceCensorImage( 222706f2543Smrg ClientPtr client, 223706f2543Smrg RegionPtr pVisibleRegion, 224706f2543Smrg long widthBytesLine, 225706f2543Smrg DrawablePtr pDraw, 226706f2543Smrg int x, int y, int w, int h, 227706f2543Smrg unsigned int format, 228706f2543Smrg char *pBuf) 229706f2543Smrg{ 230706f2543Smrg RegionRec imageRegion; /* region representing x,y,w,h */ 231706f2543Smrg RegionRec censorRegion; /* region to obliterate */ 232706f2543Smrg BoxRec imageBox; 233706f2543Smrg int nRects; 234706f2543Smrg 235706f2543Smrg imageBox.x1 = x; 236706f2543Smrg imageBox.y1 = y; 237706f2543Smrg imageBox.x2 = x + w; 238706f2543Smrg imageBox.y2 = y + h; 239706f2543Smrg RegionInit(&imageRegion, &imageBox, 1); 240706f2543Smrg RegionNull(&censorRegion); 241706f2543Smrg 242706f2543Smrg /* censorRegion = imageRegion - visibleRegion */ 243706f2543Smrg RegionSubtract(&censorRegion, &imageRegion, pVisibleRegion); 244706f2543Smrg nRects = RegionNumRects(&censorRegion); 245706f2543Smrg if (nRects > 0) 246706f2543Smrg { /* we have something to censor */ 247706f2543Smrg GCPtr pScratchGC = NULL; 248706f2543Smrg PixmapPtr pPix = NULL; 249706f2543Smrg xRectangle *pRects = NULL; 250706f2543Smrg Bool failed = FALSE; 251706f2543Smrg int depth = 1; 252706f2543Smrg int bitsPerPixel = 1; 253706f2543Smrg int i; 254706f2543Smrg BoxPtr pBox; 255706f2543Smrg 256706f2543Smrg /* convert region to list-of-rectangles for PolyFillRect */ 257706f2543Smrg 258706f2543Smrg pRects = malloc(nRects * sizeof(xRectangle)); 259706f2543Smrg if (!pRects) 260706f2543Smrg { 261706f2543Smrg failed = TRUE; 262706f2543Smrg goto failSafe; 263706f2543Smrg } 264706f2543Smrg for (pBox = RegionRects(&censorRegion), i = 0; 265706f2543Smrg i < nRects; 266706f2543Smrg i++, pBox++) 267706f2543Smrg { 268706f2543Smrg pRects[i].x = pBox->x1; 269706f2543Smrg pRects[i].y = pBox->y1 - imageBox.y1; 270706f2543Smrg pRects[i].width = pBox->x2 - pBox->x1; 271706f2543Smrg pRects[i].height = pBox->y2 - pBox->y1; 272706f2543Smrg } 273706f2543Smrg 274706f2543Smrg /* use pBuf as a fake pixmap */ 275706f2543Smrg 276706f2543Smrg if (format == ZPixmap) 277706f2543Smrg { 278706f2543Smrg depth = pDraw->depth; 279706f2543Smrg bitsPerPixel = pDraw->bitsPerPixel; 280706f2543Smrg } 281706f2543Smrg 282706f2543Smrg pPix = GetScratchPixmapHeader(pDraw->pScreen, w, h, 283706f2543Smrg depth, bitsPerPixel, 284706f2543Smrg widthBytesLine, (pointer)pBuf); 285706f2543Smrg if (!pPix) 286706f2543Smrg { 287706f2543Smrg failed = TRUE; 288706f2543Smrg goto failSafe; 289706f2543Smrg } 290706f2543Smrg 291706f2543Smrg pScratchGC = GetScratchGC(depth, pPix->drawable.pScreen); 292706f2543Smrg if (!pScratchGC) 293706f2543Smrg { 294706f2543Smrg failed = TRUE; 295706f2543Smrg goto failSafe; 296706f2543Smrg } 297706f2543Smrg 298706f2543Smrg ValidateGC(&pPix->drawable, pScratchGC); 299706f2543Smrg (* pScratchGC->ops->PolyFillRect)(&pPix->drawable, 300706f2543Smrg pScratchGC, nRects, pRects); 301706f2543Smrg 302706f2543Smrg failSafe: 303706f2543Smrg if (failed) 304706f2543Smrg { 305706f2543Smrg /* Censoring was not completed above. To be safe, wipe out 306706f2543Smrg * all the image data so that nothing trusted gets out. 307706f2543Smrg */ 308706f2543Smrg memset(pBuf, 0, (int)(widthBytesLine * h)); 309706f2543Smrg } 310706f2543Smrg free(pRects); 311706f2543Smrg if (pScratchGC) FreeScratchGC(pScratchGC); 312706f2543Smrg if (pPix) FreeScratchPixmapHeader(pPix); 313706f2543Smrg } 314706f2543Smrg RegionUninit(&imageRegion); 315706f2543Smrg RegionUninit(&censorRegion); 316706f2543Smrg} /* XaceCensorImage */ 317706f2543Smrg 318706f2543Smrg/* 319706f2543Smrg * Xtrans wrappers for use by modules 320706f2543Smrg */ 321706f2543Smrgint XaceGetConnectionNumber(ClientPtr client) 322706f2543Smrg{ 323706f2543Smrg XtransConnInfo ci = ((OsCommPtr)client->osPrivate)->trans_conn; 324706f2543Smrg return _XSERVTransGetConnectionNumber(ci); 325706f2543Smrg} 326706f2543Smrg 327706f2543Smrgint XaceIsLocal(ClientPtr client) 328706f2543Smrg{ 329706f2543Smrg XtransConnInfo ci = ((OsCommPtr)client->osPrivate)->trans_conn; 330706f2543Smrg return _XSERVTransIsLocal(ci); 331706f2543Smrg} 332