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