xace.c revision 706f2543
1/************************************************************ 2 3Author: Eamon Walsh <ewalsh@tycho.nsa.gov> 4 5Permission to use, copy, modify, distribute, and sell this software and its 6documentation for any purpose is hereby granted without fee, provided that 7this permission notice appear in supporting documentation. This permission 8notice shall be included in all copies or substantial portions of the 9Software. 10 11THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 15AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 16CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 18********************************************************/ 19 20#ifdef HAVE_DIX_CONFIG_H 21#include <dix-config.h> 22#endif 23 24#include <stdarg.h> 25#include "scrnintstr.h" 26#include "extnsionst.h" 27#include "pixmapstr.h" 28#include "regionstr.h" 29#include "gcstruct.h" 30#include "xacestr.h" 31 32#define XSERV_t 33#define TRANS_SERVER 34#include <X11/Xtrans/Xtrans.h> 35#include "../os/osdep.h" 36 37_X_EXPORT CallbackListPtr XaceHooks[XACE_NUM_HOOKS] = {0}; 38 39/* Special-cased hook functions. Called by Xserver. 40 */ 41int XaceHookDispatch(ClientPtr client, int major) 42{ 43 /* Call the audit begin callback, there is no return value. */ 44 XaceAuditRec rec = { client, 0 }; 45 CallCallbacks(&XaceHooks[XACE_AUDIT_BEGIN], &rec); 46 47 if (major < 128) { 48 /* Call the core dispatch hook */ 49 XaceCoreDispatchRec rec = { client, Success /* default allow */ }; 50 CallCallbacks(&XaceHooks[XACE_CORE_DISPATCH], &rec); 51 return rec.status; 52 } else { 53 /* Call the extension dispatch hook */ 54 ExtensionEntry *ext = GetExtensionEntry(major); 55 XaceExtAccessRec rec = { client, ext, DixUseAccess, Success }; 56 if (ext) 57 CallCallbacks(&XaceHooks[XACE_EXT_DISPATCH], &rec); 58 /* On error, pretend extension doesn't exist */ 59 return (rec.status == Success) ? Success : BadRequest; 60 } 61} 62 63int XaceHookPropertyAccess(ClientPtr client, WindowPtr pWin, 64 PropertyPtr *ppProp, Mask access_mode) 65{ 66 XacePropertyAccessRec rec = { client, pWin, ppProp, access_mode, Success }; 67 CallCallbacks(&XaceHooks[XACE_PROPERTY_ACCESS], &rec); 68 return rec.status; 69} 70 71int XaceHookSelectionAccess(ClientPtr client, 72 Selection **ppSel, Mask access_mode) 73{ 74 XaceSelectionAccessRec rec = { client, ppSel, access_mode, Success }; 75 CallCallbacks(&XaceHooks[XACE_SELECTION_ACCESS], &rec); 76 return rec.status; 77} 78 79void XaceHookAuditEnd(ClientPtr ptr, int result) 80{ 81 XaceAuditRec rec = { ptr, result }; 82 /* call callbacks, there is no return value. */ 83 CallCallbacks(&XaceHooks[XACE_AUDIT_END], &rec); 84} 85 86/* Entry point for hook functions. Called by Xserver. 87 */ 88int XaceHook(int hook, ...) 89{ 90 union { 91 XaceResourceAccessRec res; 92 XaceDeviceAccessRec dev; 93 XaceSendAccessRec send; 94 XaceReceiveAccessRec recv; 95 XaceClientAccessRec client; 96 XaceExtAccessRec ext; 97 XaceServerAccessRec server; 98 XaceScreenAccessRec screen; 99 XaceAuthAvailRec auth; 100 XaceKeyAvailRec key; 101 } u; 102 int *prv = NULL; /* points to return value from callback */ 103 va_list ap; /* argument list */ 104 105 if (!XaceHooks[hook]) 106 return Success; 107 108 va_start(ap, hook); 109 110 /* Marshal arguments for passing to callback. 111 * Each callback has its own case, which sets up a structure to hold 112 * the arguments and integer return parameter, or in some cases just 113 * sets calldata directly to a single argument (with no return result) 114 */ 115 switch (hook) 116 { 117 case XACE_RESOURCE_ACCESS: 118 u.res.client = va_arg(ap, ClientPtr); 119 u.res.id = va_arg(ap, XID); 120 u.res.rtype = va_arg(ap, RESTYPE); 121 u.res.res = va_arg(ap, pointer); 122 u.res.ptype = va_arg(ap, RESTYPE); 123 u.res.parent = va_arg(ap, pointer); 124 u.res.access_mode = va_arg(ap, Mask); 125 u.res.status = Success; /* default allow */ 126 prv = &u.res.status; 127 break; 128 case XACE_DEVICE_ACCESS: 129 u.dev.client = va_arg(ap, ClientPtr); 130 u.dev.dev = va_arg(ap, DeviceIntPtr); 131 u.dev.access_mode = va_arg(ap, Mask); 132 u.dev.status = Success; /* default allow */ 133 prv = &u.dev.status; 134 break; 135 case XACE_SEND_ACCESS: 136 u.send.client = va_arg(ap, ClientPtr); 137 u.send.dev = va_arg(ap, DeviceIntPtr); 138 u.send.pWin = va_arg(ap, WindowPtr); 139 u.send.events = va_arg(ap, xEventPtr); 140 u.send.count = va_arg(ap, int); 141 u.send.status = Success; /* default allow */ 142 prv = &u.send.status; 143 break; 144 case XACE_RECEIVE_ACCESS: 145 u.recv.client = va_arg(ap, ClientPtr); 146 u.recv.pWin = va_arg(ap, WindowPtr); 147 u.recv.events = va_arg(ap, xEventPtr); 148 u.recv.count = va_arg(ap, int); 149 u.recv.status = Success; /* default allow */ 150 prv = &u.recv.status; 151 break; 152 case XACE_CLIENT_ACCESS: 153 u.client.client = va_arg(ap, ClientPtr); 154 u.client.target = va_arg(ap, ClientPtr); 155 u.client.access_mode = va_arg(ap, Mask); 156 u.client.status = Success; /* default allow */ 157 prv = &u.client.status; 158 break; 159 case XACE_EXT_ACCESS: 160 u.ext.client = va_arg(ap, ClientPtr); 161 u.ext.ext = va_arg(ap, ExtensionEntry*); 162 u.ext.access_mode = DixGetAttrAccess; 163 u.ext.status = Success; /* default allow */ 164 prv = &u.ext.status; 165 break; 166 case XACE_SERVER_ACCESS: 167 u.server.client = va_arg(ap, ClientPtr); 168 u.server.access_mode = va_arg(ap, Mask); 169 u.server.status = Success; /* default allow */ 170 prv = &u.server.status; 171 break; 172 case XACE_SCREEN_ACCESS: 173 case XACE_SCREENSAVER_ACCESS: 174 u.screen.client = va_arg(ap, ClientPtr); 175 u.screen.screen = va_arg(ap, ScreenPtr); 176 u.screen.access_mode = va_arg(ap, Mask); 177 u.screen.status = Success; /* default allow */ 178 prv = &u.screen.status; 179 break; 180 case XACE_AUTH_AVAIL: 181 u.auth.client = va_arg(ap, ClientPtr); 182 u.auth.authId = va_arg(ap, XID); 183 break; 184 case XACE_KEY_AVAIL: 185 u.key.event = va_arg(ap, xEventPtr); 186 u.key.keybd = va_arg(ap, DeviceIntPtr); 187 u.key.count = va_arg(ap, int); 188 break; 189 default: 190 va_end(ap); 191 return 0; /* unimplemented hook number */ 192 } 193 va_end(ap); 194 195 /* call callbacks and return result, if any. */ 196 CallCallbacks(&XaceHooks[hook], &u); 197 return prv ? *prv : Success; 198} 199 200/* XaceCensorImage 201 * 202 * Called after pScreen->GetImage to prevent pieces or trusted windows from 203 * being returned in image data from an untrusted window. 204 * 205 * Arguments: 206 * client is the client doing the GetImage. 207 * pVisibleRegion is the visible region of the window. 208 * widthBytesLine is the width in bytes of one horizontal line in pBuf. 209 * pDraw is the source window. 210 * x, y, w, h is the rectangle of image data from pDraw in pBuf. 211 * format is the format of the image data in pBuf: ZPixmap or XYPixmap. 212 * pBuf is the image data. 213 * 214 * Returns: nothing. 215 * 216 * Side Effects: 217 * Any part of the rectangle (x, y, w, h) that is outside the visible 218 * region of the window will be destroyed (overwritten) in pBuf. 219 */ 220void 221XaceCensorImage( 222 ClientPtr client, 223 RegionPtr pVisibleRegion, 224 long widthBytesLine, 225 DrawablePtr pDraw, 226 int x, int y, int w, int h, 227 unsigned int format, 228 char *pBuf) 229{ 230 RegionRec imageRegion; /* region representing x,y,w,h */ 231 RegionRec censorRegion; /* region to obliterate */ 232 BoxRec imageBox; 233 int nRects; 234 235 imageBox.x1 = x; 236 imageBox.y1 = y; 237 imageBox.x2 = x + w; 238 imageBox.y2 = y + h; 239 RegionInit(&imageRegion, &imageBox, 1); 240 RegionNull(&censorRegion); 241 242 /* censorRegion = imageRegion - visibleRegion */ 243 RegionSubtract(&censorRegion, &imageRegion, pVisibleRegion); 244 nRects = RegionNumRects(&censorRegion); 245 if (nRects > 0) 246 { /* we have something to censor */ 247 GCPtr pScratchGC = NULL; 248 PixmapPtr pPix = NULL; 249 xRectangle *pRects = NULL; 250 Bool failed = FALSE; 251 int depth = 1; 252 int bitsPerPixel = 1; 253 int i; 254 BoxPtr pBox; 255 256 /* convert region to list-of-rectangles for PolyFillRect */ 257 258 pRects = malloc(nRects * sizeof(xRectangle)); 259 if (!pRects) 260 { 261 failed = TRUE; 262 goto failSafe; 263 } 264 for (pBox = RegionRects(&censorRegion), i = 0; 265 i < nRects; 266 i++, pBox++) 267 { 268 pRects[i].x = pBox->x1; 269 pRects[i].y = pBox->y1 - imageBox.y1; 270 pRects[i].width = pBox->x2 - pBox->x1; 271 pRects[i].height = pBox->y2 - pBox->y1; 272 } 273 274 /* use pBuf as a fake pixmap */ 275 276 if (format == ZPixmap) 277 { 278 depth = pDraw->depth; 279 bitsPerPixel = pDraw->bitsPerPixel; 280 } 281 282 pPix = GetScratchPixmapHeader(pDraw->pScreen, w, h, 283 depth, bitsPerPixel, 284 widthBytesLine, (pointer)pBuf); 285 if (!pPix) 286 { 287 failed = TRUE; 288 goto failSafe; 289 } 290 291 pScratchGC = GetScratchGC(depth, pPix->drawable.pScreen); 292 if (!pScratchGC) 293 { 294 failed = TRUE; 295 goto failSafe; 296 } 297 298 ValidateGC(&pPix->drawable, pScratchGC); 299 (* pScratchGC->ops->PolyFillRect)(&pPix->drawable, 300 pScratchGC, nRects, pRects); 301 302 failSafe: 303 if (failed) 304 { 305 /* Censoring was not completed above. To be safe, wipe out 306 * all the image data so that nothing trusted gets out. 307 */ 308 memset(pBuf, 0, (int)(widthBytesLine * h)); 309 } 310 free(pRects); 311 if (pScratchGC) FreeScratchGC(pScratchGC); 312 if (pPix) FreeScratchPixmapHeader(pPix); 313 } 314 RegionUninit(&imageRegion); 315 RegionUninit(&censorRegion); 316} /* XaceCensorImage */ 317 318/* 319 * Xtrans wrappers for use by modules 320 */ 321int XaceGetConnectionNumber(ClientPtr client) 322{ 323 XtransConnInfo ci = ((OsCommPtr)client->osPrivate)->trans_conn; 324 return _XSERVTransGetConnectionNumber(ci); 325} 326 327int XaceIsLocal(ClientPtr client) 328{ 329 XtransConnInfo ci = ((OsCommPtr)client->osPrivate)->trans_conn; 330 return _XSERVTransIsLocal(ci); 331} 332