xace.c revision 541282ce
1/************************************************************ 2 3Author: Eamon Walsh <ewalsh@epoch.ncsc.mil> 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 32CallbackListPtr XaceHooks[XACE_NUM_HOOKS] = {0}; 33 34/* Special-cased hook functions. Called by Xserver. 35 */ 36int XaceHookDispatch(ClientPtr client, int major) 37{ 38 /* Call the audit begin callback, there is no return value. */ 39 XaceAuditRec rec = { client, 0 }; 40 CallCallbacks(&XaceHooks[XACE_AUDIT_BEGIN], &rec); 41 42 if (major < 128) { 43 /* Call the core dispatch hook */ 44 XaceCoreDispatchRec rec = { client, Success /* default allow */ }; 45 CallCallbacks(&XaceHooks[XACE_CORE_DISPATCH], &rec); 46 return rec.status; 47 } else { 48 /* Call the extension dispatch hook */ 49 ExtensionEntry *ext = GetExtensionEntry(major); 50 XaceExtAccessRec rec = { client, ext, DixUseAccess, Success }; 51 if (ext) 52 CallCallbacks(&XaceHooks[XACE_EXT_DISPATCH], &rec); 53 /* On error, pretend extension doesn't exist */ 54 return (rec.status == Success) ? Success : BadRequest; 55 } 56} 57 58int XaceHookPropertyAccess(ClientPtr client, WindowPtr pWin, 59 PropertyPtr *ppProp, Mask access_mode) 60{ 61 XacePropertyAccessRec rec = { client, pWin, ppProp, access_mode, Success }; 62 CallCallbacks(&XaceHooks[XACE_PROPERTY_ACCESS], &rec); 63 return rec.status; 64} 65 66int XaceHookSelectionAccess(ClientPtr client, 67 Selection **ppSel, Mask access_mode) 68{ 69 XaceSelectionAccessRec rec = { client, ppSel, access_mode, Success }; 70 CallCallbacks(&XaceHooks[XACE_SELECTION_ACCESS], &rec); 71 return rec.status; 72} 73 74void XaceHookAuditEnd(ClientPtr ptr, int result) 75{ 76 XaceAuditRec rec = { ptr, result }; 77 /* call callbacks, there is no return value. */ 78 CallCallbacks(&XaceHooks[XACE_AUDIT_END], &rec); 79} 80 81/* Entry point for hook functions. Called by Xserver. 82 */ 83int XaceHook(int hook, ...) 84{ 85 pointer calldata; /* data passed to callback */ 86 int *prv = NULL; /* points to return value from callback */ 87 va_list ap; /* argument list */ 88 va_start(ap, hook); 89 90 /* Marshal arguments for passing to callback. 91 * Each callback has its own case, which sets up a structure to hold 92 * the arguments and integer return parameter, or in some cases just 93 * sets calldata directly to a single argument (with no return result) 94 */ 95 switch (hook) 96 { 97 case XACE_RESOURCE_ACCESS: { 98 XaceResourceAccessRec rec; 99 rec.client = va_arg(ap, ClientPtr); 100 rec.id = va_arg(ap, XID); 101 rec.rtype = va_arg(ap, RESTYPE); 102 rec.res = va_arg(ap, pointer); 103 rec.ptype = va_arg(ap, RESTYPE); 104 rec.parent = va_arg(ap, pointer); 105 rec.access_mode = va_arg(ap, Mask); 106 rec.status = Success; /* default allow */ 107 calldata = &rec; 108 prv = &rec.status; 109 break; 110 } 111 case XACE_DEVICE_ACCESS: { 112 XaceDeviceAccessRec rec; 113 rec.client = va_arg(ap, ClientPtr); 114 rec.dev = va_arg(ap, DeviceIntPtr); 115 rec.access_mode = va_arg(ap, Mask); 116 rec.status = Success; /* default allow */ 117 calldata = &rec; 118 prv = &rec.status; 119 break; 120 } 121 case XACE_SEND_ACCESS: { 122 XaceSendAccessRec rec; 123 rec.client = va_arg(ap, ClientPtr); 124 rec.dev = va_arg(ap, DeviceIntPtr); 125 rec.pWin = va_arg(ap, WindowPtr); 126 rec.events = va_arg(ap, xEventPtr); 127 rec.count = va_arg(ap, int); 128 rec.status = Success; /* default allow */ 129 calldata = &rec; 130 prv = &rec.status; 131 break; 132 } 133 case XACE_RECEIVE_ACCESS: { 134 XaceReceiveAccessRec rec; 135 rec.client = va_arg(ap, ClientPtr); 136 rec.pWin = va_arg(ap, WindowPtr); 137 rec.events = va_arg(ap, xEventPtr); 138 rec.count = va_arg(ap, int); 139 rec.status = Success; /* default allow */ 140 calldata = &rec; 141 prv = &rec.status; 142 break; 143 } 144 case XACE_CLIENT_ACCESS: { 145 XaceClientAccessRec rec; 146 rec.client = va_arg(ap, ClientPtr); 147 rec.target = va_arg(ap, ClientPtr); 148 rec.access_mode = va_arg(ap, Mask); 149 rec.status = Success; /* default allow */ 150 calldata = &rec; 151 prv = &rec.status; 152 break; 153 } 154 case XACE_EXT_ACCESS: { 155 XaceExtAccessRec rec; 156 rec.client = va_arg(ap, ClientPtr); 157 rec.ext = va_arg(ap, ExtensionEntry*); 158 rec.access_mode = DixGetAttrAccess; 159 rec.status = Success; /* default allow */ 160 calldata = &rec; 161 prv = &rec.status; 162 break; 163 } 164 case XACE_SERVER_ACCESS: { 165 XaceServerAccessRec rec; 166 rec.client = va_arg(ap, ClientPtr); 167 rec.access_mode = va_arg(ap, Mask); 168 rec.status = Success; /* default allow */ 169 calldata = &rec; 170 prv = &rec.status; 171 break; 172 } 173 case XACE_SCREEN_ACCESS: 174 case XACE_SCREENSAVER_ACCESS: { 175 XaceScreenAccessRec rec; 176 rec.client = va_arg(ap, ClientPtr); 177 rec.screen = va_arg(ap, ScreenPtr); 178 rec.access_mode = va_arg(ap, Mask); 179 rec.status = Success; /* default allow */ 180 calldata = &rec; 181 prv = &rec.status; 182 break; 183 } 184 case XACE_AUTH_AVAIL: { 185 XaceAuthAvailRec rec; 186 rec.client = va_arg(ap, ClientPtr); 187 rec.authId = va_arg(ap, XID); 188 calldata = &rec; 189 break; 190 } 191 case XACE_KEY_AVAIL: { 192 XaceKeyAvailRec rec; 193 rec.event = va_arg(ap, xEventPtr); 194 rec.keybd = va_arg(ap, DeviceIntPtr); 195 rec.count = va_arg(ap, int); 196 calldata = &rec; 197 break; 198 } 199 default: { 200 va_end(ap); 201 return 0; /* unimplemented hook number */ 202 } 203 } 204 va_end(ap); 205 206 /* call callbacks and return result, if any. */ 207 CallCallbacks(&XaceHooks[hook], calldata); 208 return prv ? *prv : Success; 209} 210 211/* XaceCensorImage 212 * 213 * Called after pScreen->GetImage to prevent pieces or trusted windows from 214 * being returned in image data from an untrusted window. 215 * 216 * Arguments: 217 * client is the client doing the GetImage. 218 * pVisibleRegion is the visible region of the window. 219 * widthBytesLine is the width in bytes of one horizontal line in pBuf. 220 * pDraw is the source window. 221 * x, y, w, h is the rectangle of image data from pDraw in pBuf. 222 * format is the format of the image data in pBuf: ZPixmap or XYPixmap. 223 * pBuf is the image data. 224 * 225 * Returns: nothing. 226 * 227 * Side Effects: 228 * Any part of the rectangle (x, y, w, h) that is outside the visible 229 * region of the window will be destroyed (overwritten) in pBuf. 230 */ 231void 232XaceCensorImage(client, pVisibleRegion, widthBytesLine, pDraw, x, y, w, h, 233 format, pBuf) 234 ClientPtr client; 235 RegionPtr pVisibleRegion; 236 long widthBytesLine; 237 DrawablePtr pDraw; 238 int x, y, w, h; 239 unsigned int format; 240 char * pBuf; 241{ 242 ScreenPtr pScreen; 243 RegionRec imageRegion; /* region representing x,y,w,h */ 244 RegionRec censorRegion; /* region to obliterate */ 245 BoxRec imageBox; 246 int nRects; 247 248 pScreen = pDraw->pScreen; 249 250 imageBox.x1 = x; 251 imageBox.y1 = y; 252 imageBox.x2 = x + w; 253 imageBox.y2 = y + h; 254 REGION_INIT(pScreen, &imageRegion, &imageBox, 1); 255 REGION_NULL(pScreen, &censorRegion); 256 257 /* censorRegion = imageRegion - visibleRegion */ 258 REGION_SUBTRACT(pScreen, &censorRegion, &imageRegion, pVisibleRegion); 259 nRects = REGION_NUM_RECTS(&censorRegion); 260 if (nRects > 0) 261 { /* we have something to censor */ 262 GCPtr pScratchGC = NULL; 263 PixmapPtr pPix = NULL; 264 xRectangle *pRects = NULL; 265 Bool failed = FALSE; 266 int depth = 1; 267 int bitsPerPixel = 1; 268 int i; 269 BoxPtr pBox; 270 271 /* convert region to list-of-rectangles for PolyFillRect */ 272 273 pRects = (xRectangle *)xalloc(nRects * sizeof(xRectangle)); 274 if (!pRects) 275 { 276 failed = TRUE; 277 goto failSafe; 278 } 279 for (pBox = REGION_RECTS(&censorRegion), i = 0; 280 i < nRects; 281 i++, pBox++) 282 { 283 pRects[i].x = pBox->x1; 284 pRects[i].y = pBox->y1 - imageBox.y1; 285 pRects[i].width = pBox->x2 - pBox->x1; 286 pRects[i].height = pBox->y2 - pBox->y1; 287 } 288 289 /* use pBuf as a fake pixmap */ 290 291 if (format == ZPixmap) 292 { 293 depth = pDraw->depth; 294 bitsPerPixel = pDraw->bitsPerPixel; 295 } 296 297 pPix = GetScratchPixmapHeader(pDraw->pScreen, w, h, 298 depth, bitsPerPixel, 299 widthBytesLine, (pointer)pBuf); 300 if (!pPix) 301 { 302 failed = TRUE; 303 goto failSafe; 304 } 305 306 pScratchGC = GetScratchGC(depth, pPix->drawable.pScreen); 307 if (!pScratchGC) 308 { 309 failed = TRUE; 310 goto failSafe; 311 } 312 313 ValidateGC(&pPix->drawable, pScratchGC); 314 (* pScratchGC->ops->PolyFillRect)(&pPix->drawable, 315 pScratchGC, nRects, pRects); 316 317 failSafe: 318 if (failed) 319 { 320 /* Censoring was not completed above. To be safe, wipe out 321 * all the image data so that nothing trusted gets out. 322 */ 323 bzero(pBuf, (int)(widthBytesLine * h)); 324 } 325 if (pRects) xfree(pRects); 326 if (pScratchGC) FreeScratchGC(pScratchGC); 327 if (pPix) FreeScratchPixmapHeader(pPix); 328 } 329 REGION_UNINIT(pScreen, &imageRegion); 330 REGION_UNINIT(pScreen, &censorRegion); 331} /* XaceCensorImage */ 332