xace.c revision 4202a189
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 va_start(ap, hook); 105 106 /* Marshal arguments for passing to callback. 107 * Each callback has its own case, which sets up a structure to hold 108 * the arguments and integer return parameter, or in some cases just 109 * sets calldata directly to a single argument (with no return result) 110 */ 111 switch (hook) 112 { 113 case XACE_RESOURCE_ACCESS: 114 u.res.client = va_arg(ap, ClientPtr); 115 u.res.id = va_arg(ap, XID); 116 u.res.rtype = va_arg(ap, RESTYPE); 117 u.res.res = va_arg(ap, pointer); 118 u.res.ptype = va_arg(ap, RESTYPE); 119 u.res.parent = va_arg(ap, pointer); 120 u.res.access_mode = va_arg(ap, Mask); 121 u.res.status = Success; /* default allow */ 122 prv = &u.res.status; 123 break; 124 case XACE_DEVICE_ACCESS: 125 u.dev.client = va_arg(ap, ClientPtr); 126 u.dev.dev = va_arg(ap, DeviceIntPtr); 127 u.dev.access_mode = va_arg(ap, Mask); 128 u.dev.status = Success; /* default allow */ 129 prv = &u.dev.status; 130 break; 131 case XACE_SEND_ACCESS: 132 u.send.client = va_arg(ap, ClientPtr); 133 u.send.dev = va_arg(ap, DeviceIntPtr); 134 u.send.pWin = va_arg(ap, WindowPtr); 135 u.send.events = va_arg(ap, xEventPtr); 136 u.send.count = va_arg(ap, int); 137 u.send.status = Success; /* default allow */ 138 prv = &u.send.status; 139 break; 140 case XACE_RECEIVE_ACCESS: 141 u.recv.client = va_arg(ap, ClientPtr); 142 u.recv.pWin = va_arg(ap, WindowPtr); 143 u.recv.events = va_arg(ap, xEventPtr); 144 u.recv.count = va_arg(ap, int); 145 u.recv.status = Success; /* default allow */ 146 prv = &u.recv.status; 147 break; 148 case XACE_CLIENT_ACCESS: 149 u.client.client = va_arg(ap, ClientPtr); 150 u.client.target = va_arg(ap, ClientPtr); 151 u.client.access_mode = va_arg(ap, Mask); 152 u.client.status = Success; /* default allow */ 153 prv = &u.client.status; 154 break; 155 case XACE_EXT_ACCESS: 156 u.ext.client = va_arg(ap, ClientPtr); 157 u.ext.ext = va_arg(ap, ExtensionEntry*); 158 u.ext.access_mode = DixGetAttrAccess; 159 u.ext.status = Success; /* default allow */ 160 prv = &u.ext.status; 161 break; 162 case XACE_SERVER_ACCESS: 163 u.server.client = va_arg(ap, ClientPtr); 164 u.server.access_mode = va_arg(ap, Mask); 165 u.server.status = Success; /* default allow */ 166 prv = &u.server.status; 167 break; 168 case XACE_SCREEN_ACCESS: 169 case XACE_SCREENSAVER_ACCESS: 170 u.screen.client = va_arg(ap, ClientPtr); 171 u.screen.screen = va_arg(ap, ScreenPtr); 172 u.screen.access_mode = va_arg(ap, Mask); 173 u.screen.status = Success; /* default allow */ 174 prv = &u.screen.status; 175 break; 176 case XACE_AUTH_AVAIL: 177 u.auth.client = va_arg(ap, ClientPtr); 178 u.auth.authId = va_arg(ap, XID); 179 break; 180 case XACE_KEY_AVAIL: 181 u.key.event = va_arg(ap, xEventPtr); 182 u.key.keybd = va_arg(ap, DeviceIntPtr); 183 u.key.count = va_arg(ap, int); 184 break; 185 default: 186 va_end(ap); 187 return 0; /* unimplemented hook number */ 188 } 189 va_end(ap); 190 191 /* call callbacks and return result, if any. */ 192 CallCallbacks(&XaceHooks[hook], &u); 193 return prv ? *prv : Success; 194} 195 196/* XaceCensorImage 197 * 198 * Called after pScreen->GetImage to prevent pieces or trusted windows from 199 * being returned in image data from an untrusted window. 200 * 201 * Arguments: 202 * client is the client doing the GetImage. 203 * pVisibleRegion is the visible region of the window. 204 * widthBytesLine is the width in bytes of one horizontal line in pBuf. 205 * pDraw is the source window. 206 * x, y, w, h is the rectangle of image data from pDraw in pBuf. 207 * format is the format of the image data in pBuf: ZPixmap or XYPixmap. 208 * pBuf is the image data. 209 * 210 * Returns: nothing. 211 * 212 * Side Effects: 213 * Any part of the rectangle (x, y, w, h) that is outside the visible 214 * region of the window will be destroyed (overwritten) in pBuf. 215 */ 216void 217XaceCensorImage( 218 ClientPtr client, 219 RegionPtr pVisibleRegion, 220 long widthBytesLine, 221 DrawablePtr pDraw, 222 int x, int y, int w, int h, 223 unsigned int format, 224 char *pBuf) 225{ 226 RegionRec imageRegion; /* region representing x,y,w,h */ 227 RegionRec censorRegion; /* region to obliterate */ 228 BoxRec imageBox; 229 int nRects; 230 231 imageBox.x1 = x; 232 imageBox.y1 = y; 233 imageBox.x2 = x + w; 234 imageBox.y2 = y + h; 235 RegionInit(&imageRegion, &imageBox, 1); 236 RegionNull(&censorRegion); 237 238 /* censorRegion = imageRegion - visibleRegion */ 239 RegionSubtract(&censorRegion, &imageRegion, pVisibleRegion); 240 nRects = RegionNumRects(&censorRegion); 241 if (nRects > 0) 242 { /* we have something to censor */ 243 GCPtr pScratchGC = NULL; 244 PixmapPtr pPix = NULL; 245 xRectangle *pRects = NULL; 246 Bool failed = FALSE; 247 int depth = 1; 248 int bitsPerPixel = 1; 249 int i; 250 BoxPtr pBox; 251 252 /* convert region to list-of-rectangles for PolyFillRect */ 253 254 pRects = malloc(nRects * sizeof(xRectangle)); 255 if (!pRects) 256 { 257 failed = TRUE; 258 goto failSafe; 259 } 260 for (pBox = RegionRects(&censorRegion), i = 0; 261 i < nRects; 262 i++, pBox++) 263 { 264 pRects[i].x = pBox->x1; 265 pRects[i].y = pBox->y1 - imageBox.y1; 266 pRects[i].width = pBox->x2 - pBox->x1; 267 pRects[i].height = pBox->y2 - pBox->y1; 268 } 269 270 /* use pBuf as a fake pixmap */ 271 272 if (format == ZPixmap) 273 { 274 depth = pDraw->depth; 275 bitsPerPixel = pDraw->bitsPerPixel; 276 } 277 278 pPix = GetScratchPixmapHeader(pDraw->pScreen, w, h, 279 depth, bitsPerPixel, 280 widthBytesLine, (pointer)pBuf); 281 if (!pPix) 282 { 283 failed = TRUE; 284 goto failSafe; 285 } 286 287 pScratchGC = GetScratchGC(depth, pPix->drawable.pScreen); 288 if (!pScratchGC) 289 { 290 failed = TRUE; 291 goto failSafe; 292 } 293 294 ValidateGC(&pPix->drawable, pScratchGC); 295 (* pScratchGC->ops->PolyFillRect)(&pPix->drawable, 296 pScratchGC, nRects, pRects); 297 298 failSafe: 299 if (failed) 300 { 301 /* Censoring was not completed above. To be safe, wipe out 302 * all the image data so that nothing trusted gets out. 303 */ 304 memset(pBuf, 0, (int)(widthBytesLine * h)); 305 } 306 free(pRects); 307 if (pScratchGC) FreeScratchGC(pScratchGC); 308 if (pPix) FreeScratchPixmapHeader(pPix); 309 } 310 RegionUninit(&imageRegion); 311 RegionUninit(&censorRegion); 312} /* XaceCensorImage */ 313 314/* 315 * Xtrans wrappers for use by modules 316 */ 317int XaceGetConnectionNumber(ClientPtr client) 318{ 319 XtransConnInfo ci = ((OsCommPtr)client->osPrivate)->trans_conn; 320 return _XSERVTransGetConnectionNumber(ci); 321} 322 323int XaceIsLocal(ClientPtr client) 324{ 325 XtransConnInfo ci = ((OsCommPtr)client->osPrivate)->trans_conn; 326 return _XSERVTransIsLocal(ci); 327} 328