First import
[xorg_rtime.git] / xorg-server-1.4 / Xext / xace.c
blob63856315c89426d59d32452e5b8778cac8eb9a5d
1 /************************************************************
3 Author: Eamon Walsh <ewalsh@epoch.ncsc.mil>
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 this permission notice appear in supporting documentation. This permission
8 notice shall be included in all copies or substantial portions of the
9 Software.
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14 AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
15 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 ********************************************************/
20 #ifdef HAVE_DIX_CONFIG_H
21 #include <dix-config.h>
22 #endif
24 #include <stdarg.h>
25 #include "windowstr.h"
26 #include "scrnintstr.h"
27 #include "gcstruct.h"
28 #include "xacestr.h"
29 #include "modinit.h"
31 CallbackListPtr XaceHooks[XACE_NUM_HOOKS] = {0};
33 /* Proc vectors for untrusted clients, swapped and unswapped versions.
34 * These are the same as the normal proc vectors except that extensions
35 * that haven't declared themselves secure will have ProcBadRequest plugged
36 * in for their major opcode dispatcher. This prevents untrusted clients
37 * from guessing extension major opcodes and using the extension even though
38 * the extension can't be listed or queried.
40 static int (*UntrustedProcVector[256])(
41 ClientPtr /*client*/
43 static int (*SwappedUntrustedProcVector[256])(
44 ClientPtr /*client*/
47 /* Entry point for hook functions. Called by Xserver.
49 int XaceHook(int hook, ...)
51 pointer calldata; /* data passed to callback */
52 int *prv = NULL; /* points to return value from callback */
53 va_list ap; /* argument list */
54 va_start(ap, hook);
56 /* Marshal arguments for passing to callback.
57 * Each callback has its own case, which sets up a structure to hold
58 * the arguments and integer return parameter, or in some cases just
59 * sets calldata directly to a single argument (with no return result)
61 switch (hook)
63 case XACE_CORE_DISPATCH: {
64 XaceCoreDispatchRec rec = {
65 va_arg(ap, ClientPtr),
66 TRUE /* default allow */
68 calldata = &rec;
69 prv = &rec.rval;
70 break;
72 case XACE_RESOURCE_ACCESS: {
73 XaceResourceAccessRec rec = {
74 va_arg(ap, ClientPtr),
75 va_arg(ap, XID),
76 va_arg(ap, RESTYPE),
77 va_arg(ap, Mask),
78 va_arg(ap, pointer),
79 TRUE /* default allow */
81 calldata = &rec;
82 prv = &rec.rval;
83 break;
85 case XACE_DEVICE_ACCESS: {
86 XaceDeviceAccessRec rec = {
87 va_arg(ap, ClientPtr),
88 va_arg(ap, DeviceIntPtr),
89 va_arg(ap, Bool),
90 TRUE /* default allow */
92 calldata = &rec;
93 prv = &rec.rval;
94 break;
96 case XACE_PROPERTY_ACCESS: {
97 XacePropertyAccessRec rec = {
98 va_arg(ap, ClientPtr),
99 va_arg(ap, WindowPtr),
100 va_arg(ap, Atom),
101 va_arg(ap, Mask),
102 XaceAllowOperation /* default allow */
104 calldata = &rec;
105 prv = &rec.rval;
106 break;
108 case XACE_DRAWABLE_ACCESS: {
109 XaceDrawableAccessRec rec = {
110 va_arg(ap, ClientPtr),
111 va_arg(ap, DrawablePtr),
112 TRUE /* default allow */
114 calldata = &rec;
115 prv = &rec.rval;
116 break;
118 case XACE_MAP_ACCESS:
119 case XACE_BACKGRND_ACCESS: {
120 XaceMapAccessRec rec = {
121 va_arg(ap, ClientPtr),
122 va_arg(ap, WindowPtr),
123 TRUE /* default allow */
125 calldata = &rec;
126 prv = &rec.rval;
127 break;
129 case XACE_EXT_DISPATCH:
130 case XACE_EXT_ACCESS: {
131 XaceExtAccessRec rec = {
132 va_arg(ap, ClientPtr),
133 va_arg(ap, ExtensionEntry*),
134 TRUE /* default allow */
136 calldata = &rec;
137 prv = &rec.rval;
138 break;
140 case XACE_HOSTLIST_ACCESS: {
141 XaceHostlistAccessRec rec = {
142 va_arg(ap, ClientPtr),
143 va_arg(ap, Mask),
144 TRUE /* default allow */
146 calldata = &rec;
147 prv = &rec.rval;
148 break;
150 case XACE_SITE_POLICY: {
151 XaceSitePolicyRec rec = {
152 va_arg(ap, char*),
153 va_arg(ap, int),
154 FALSE /* default unrecognized */
156 calldata = &rec;
157 prv = &rec.rval;
158 break;
160 case XACE_DECLARE_EXT_SECURE: {
161 XaceDeclareExtSecureRec rec = {
162 va_arg(ap, ExtensionEntry*),
163 va_arg(ap, Bool)
165 calldata = &rec;
166 break;
168 case XACE_AUTH_AVAIL: {
169 XaceAuthAvailRec rec = {
170 va_arg(ap, ClientPtr),
171 va_arg(ap, XID)
173 calldata = &rec;
174 break;
176 case XACE_KEY_AVAIL: {
177 XaceKeyAvailRec rec = {
178 va_arg(ap, xEventPtr),
179 va_arg(ap, DeviceIntPtr),
180 va_arg(ap, int)
182 calldata = &rec;
183 break;
185 case XACE_WINDOW_INIT: {
186 XaceWindowRec rec = {
187 va_arg(ap, ClientPtr),
188 va_arg(ap, WindowPtr)
190 calldata = &rec;
191 break;
193 case XACE_AUDIT_BEGIN: {
194 XaceAuditRec rec = {
195 va_arg(ap, ClientPtr),
198 calldata = &rec;
199 break;
201 case XACE_AUDIT_END: {
202 XaceAuditRec rec = {
203 va_arg(ap, ClientPtr),
204 va_arg(ap, int)
206 calldata = &rec;
207 break;
209 default: {
210 va_end(ap);
211 return 0; /* unimplemented hook number */
214 va_end(ap);
216 /* call callbacks and return result, if any. */
217 CallCallbacks(&XaceHooks[hook], calldata);
218 return prv ? *prv : 0;
221 static int
222 ProcXaceDispatch(ClientPtr client)
224 REQUEST(xReq);
226 switch (stuff->data)
228 default:
229 return BadRequest;
231 } /* ProcXaceDispatch */
233 static int
234 SProcXaceDispatch(ClientPtr client)
236 REQUEST(xReq);
238 switch (stuff->data)
240 default:
241 return BadRequest;
243 } /* SProcXaceDispatch */
246 /* XaceResetProc
248 * Arguments:
249 * extEntry is the extension information for the XACE extension.
251 * Returns: nothing.
253 * Side Effects:
254 * Performs any cleanup needed by XACE at server shutdown time.
256 static void
257 XaceResetProc(ExtensionEntry *extEntry)
259 int i;
261 for (i=0; i<XACE_NUM_HOOKS; i++)
263 DeleteCallbackList(&XaceHooks[i]);
264 XaceHooks[i] = NULL;
266 } /* XaceResetProc */
269 static int
270 XaceCatchDispatchProc(ClientPtr client)
272 REQUEST(xReq);
273 int major = stuff->reqType;
275 if (!ProcVector[major])
276 return (BadRequest);
278 if (!XaceHook(XACE_CORE_DISPATCH, client))
279 return (BadAccess);
281 return client->swapped ?
282 (* SwappedProcVector[major])(client) :
283 (* ProcVector[major])(client);
286 static int
287 XaceCatchExtProc(ClientPtr client)
289 REQUEST(xReq);
290 int major = stuff->reqType;
291 ExtensionEntry *ext = GetExtensionEntry(major);
293 if (!ext || !ProcVector[major])
294 return (BadRequest);
296 if (!XaceHook(XACE_EXT_DISPATCH, client, ext))
297 return (BadRequest); /* pretend extension doesn't exist */
299 return client->swapped ?
300 (* SwappedProcVector[major])(client) :
301 (* ProcVector[major])(client);
305 /* SecurityClientStateCallback
307 * Arguments:
308 * pcbl is &ClientStateCallback.
309 * nullata is NULL.
310 * calldata is a pointer to a NewClientInfoRec (include/dixstruct.h)
311 * which contains information about client state changes.
313 * Returns: nothing.
315 * Side Effects:
317 * If a new client is connecting, its authorization ID is copied to
318 * client->authID. If this is a generated authorization, its reference
319 * count is bumped, its timer is cancelled if it was running, and its
320 * trustlevel is copied to TRUSTLEVEL(client).
322 * If a client is disconnecting and the client was using a generated
323 * authorization, the authorization's reference count is decremented, and
324 * if it is now zero, the timer for this authorization is started.
327 static void
328 XaceClientStateCallback(
329 CallbackListPtr *pcbl,
330 pointer nulldata,
331 pointer calldata)
333 NewClientInfoRec *pci = (NewClientInfoRec *)calldata;
334 ClientPtr client = pci->client;
336 switch (client->clientState)
338 case ClientStateRunning:
340 client->requestVector = client->swapped ?
341 SwappedUntrustedProcVector : UntrustedProcVector;
342 break;
344 default: break;
346 } /* XaceClientStateCallback */
348 /* XaceExtensionInit
350 * Initialize the XACE Extension
352 void XaceExtensionInit(INITARGS)
354 ExtensionEntry *extEntry;
355 int i;
357 if (!AddCallback(&ClientStateCallback, XaceClientStateCallback, NULL))
358 return;
360 extEntry = AddExtension(XACE_EXTENSION_NAME,
361 XaceNumberEvents, XaceNumberErrors,
362 ProcXaceDispatch, SProcXaceDispatch,
363 XaceResetProc, StandardMinorOpcode);
365 /* initialize dispatching intercept functions */
366 for (i = 0; i < 128; i++)
368 UntrustedProcVector[i] = XaceCatchDispatchProc;
369 SwappedUntrustedProcVector[i] = XaceCatchDispatchProc;
371 for (i = 128; i < 256; i++)
373 UntrustedProcVector[i] = XaceCatchExtProc;
374 SwappedUntrustedProcVector[i] = XaceCatchExtProc;
378 /* XaceCensorImage
380 * Called after pScreen->GetImage to prevent pieces or trusted windows from
381 * being returned in image data from an untrusted window.
383 * Arguments:
384 * client is the client doing the GetImage.
385 * pVisibleRegion is the visible region of the window.
386 * widthBytesLine is the width in bytes of one horizontal line in pBuf.
387 * pDraw is the source window.
388 * x, y, w, h is the rectangle of image data from pDraw in pBuf.
389 * format is the format of the image data in pBuf: ZPixmap or XYPixmap.
390 * pBuf is the image data.
392 * Returns: nothing.
394 * Side Effects:
395 * Any part of the rectangle (x, y, w, h) that is outside the visible
396 * region of the window will be destroyed (overwritten) in pBuf.
398 void
399 XaceCensorImage(client, pVisibleRegion, widthBytesLine, pDraw, x, y, w, h,
400 format, pBuf)
401 ClientPtr client;
402 RegionPtr pVisibleRegion;
403 long widthBytesLine;
404 DrawablePtr pDraw;
405 int x, y, w, h;
406 unsigned int format;
407 char * pBuf;
409 ScreenPtr pScreen;
410 RegionRec imageRegion; /* region representing x,y,w,h */
411 RegionRec censorRegion; /* region to obliterate */
412 BoxRec imageBox;
413 int nRects;
415 pScreen = pDraw->pScreen;
417 imageBox.x1 = x;
418 imageBox.y1 = y;
419 imageBox.x2 = x + w;
420 imageBox.y2 = y + h;
421 REGION_INIT(pScreen, &imageRegion, &imageBox, 1);
422 REGION_NULL(pScreen, &censorRegion);
424 /* censorRegion = imageRegion - visibleRegion */
425 REGION_SUBTRACT(pScreen, &censorRegion, &imageRegion, pVisibleRegion);
426 nRects = REGION_NUM_RECTS(&censorRegion);
427 if (nRects > 0)
428 { /* we have something to censor */
429 GCPtr pScratchGC = NULL;
430 PixmapPtr pPix = NULL;
431 xRectangle *pRects = NULL;
432 Bool failed = FALSE;
433 int depth = 1;
434 int bitsPerPixel = 1;
435 int i;
436 BoxPtr pBox;
438 /* convert region to list-of-rectangles for PolyFillRect */
440 pRects = (xRectangle *)ALLOCATE_LOCAL(nRects * sizeof(xRectangle *));
441 if (!pRects)
443 failed = TRUE;
444 goto failSafe;
446 for (pBox = REGION_RECTS(&censorRegion), i = 0;
447 i < nRects;
448 i++, pBox++)
450 pRects[i].x = pBox->x1;
451 pRects[i].y = pBox->y1 - imageBox.y1;
452 pRects[i].width = pBox->x2 - pBox->x1;
453 pRects[i].height = pBox->y2 - pBox->y1;
456 /* use pBuf as a fake pixmap */
458 if (format == ZPixmap)
460 depth = pDraw->depth;
461 bitsPerPixel = pDraw->bitsPerPixel;
464 pPix = GetScratchPixmapHeader(pDraw->pScreen, w, h,
465 depth, bitsPerPixel,
466 widthBytesLine, (pointer)pBuf);
467 if (!pPix)
469 failed = TRUE;
470 goto failSafe;
473 pScratchGC = GetScratchGC(depth, pPix->drawable.pScreen);
474 if (!pScratchGC)
476 failed = TRUE;
477 goto failSafe;
480 ValidateGC(&pPix->drawable, pScratchGC);
481 (* pScratchGC->ops->PolyFillRect)(&pPix->drawable,
482 pScratchGC, nRects, pRects);
484 failSafe:
485 if (failed)
487 /* Censoring was not completed above. To be safe, wipe out
488 * all the image data so that nothing trusted gets out.
490 bzero(pBuf, (int)(widthBytesLine * h));
492 if (pRects) DEALLOCATE_LOCAL(pRects);
493 if (pScratchGC) FreeScratchGC(pScratchGC);
494 if (pPix) FreeScratchPixmapHeader(pPix);
496 REGION_UNINIT(pScreen, &imageRegion);
497 REGION_UNINIT(pScreen, &censorRegion);
498 } /* XaceCensorImage */