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
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>
25 #include "windowstr.h"
26 #include "scrnintstr.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])(
43 static int (*SwappedUntrustedProcVector
[256])(
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 */
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)
63 case XACE_CORE_DISPATCH
: {
64 XaceCoreDispatchRec rec
= {
65 va_arg(ap
, ClientPtr
),
66 TRUE
/* default allow */
72 case XACE_RESOURCE_ACCESS
: {
73 XaceResourceAccessRec rec
= {
74 va_arg(ap
, ClientPtr
),
79 TRUE
/* default allow */
85 case XACE_DEVICE_ACCESS
: {
86 XaceDeviceAccessRec rec
= {
87 va_arg(ap
, ClientPtr
),
88 va_arg(ap
, DeviceIntPtr
),
90 TRUE
/* default allow */
96 case XACE_PROPERTY_ACCESS
: {
97 XacePropertyAccessRec rec
= {
98 va_arg(ap
, ClientPtr
),
99 va_arg(ap
, WindowPtr
),
102 XaceAllowOperation
/* default allow */
108 case XACE_DRAWABLE_ACCESS
: {
109 XaceDrawableAccessRec rec
= {
110 va_arg(ap
, ClientPtr
),
111 va_arg(ap
, DrawablePtr
),
112 TRUE
/* default allow */
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 */
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 */
140 case XACE_HOSTLIST_ACCESS
: {
141 XaceHostlistAccessRec rec
= {
142 va_arg(ap
, ClientPtr
),
144 TRUE
/* default allow */
150 case XACE_SITE_POLICY
: {
151 XaceSitePolicyRec rec
= {
154 FALSE
/* default unrecognized */
160 case XACE_DECLARE_EXT_SECURE
: {
161 XaceDeclareExtSecureRec rec
= {
162 va_arg(ap
, ExtensionEntry
*),
168 case XACE_AUTH_AVAIL
: {
169 XaceAuthAvailRec rec
= {
170 va_arg(ap
, ClientPtr
),
176 case XACE_KEY_AVAIL
: {
177 XaceKeyAvailRec rec
= {
178 va_arg(ap
, xEventPtr
),
179 va_arg(ap
, DeviceIntPtr
),
185 case XACE_WINDOW_INIT
: {
186 XaceWindowRec rec
= {
187 va_arg(ap
, ClientPtr
),
188 va_arg(ap
, WindowPtr
)
193 case XACE_AUDIT_BEGIN
: {
195 va_arg(ap
, ClientPtr
),
201 case XACE_AUDIT_END
: {
203 va_arg(ap
, ClientPtr
),
211 return 0; /* unimplemented hook number */
216 /* call callbacks and return result, if any. */
217 CallCallbacks(&XaceHooks
[hook
], calldata
);
218 return prv
? *prv
: 0;
222 ProcXaceDispatch(ClientPtr client
)
231 } /* ProcXaceDispatch */
234 SProcXaceDispatch(ClientPtr client
)
243 } /* SProcXaceDispatch */
249 * extEntry is the extension information for the XACE extension.
254 * Performs any cleanup needed by XACE at server shutdown time.
257 XaceResetProc(ExtensionEntry
*extEntry
)
261 for (i
=0; i
<XACE_NUM_HOOKS
; i
++)
263 DeleteCallbackList(&XaceHooks
[i
]);
266 } /* XaceResetProc */
270 XaceCatchDispatchProc(ClientPtr client
)
273 int major
= stuff
->reqType
;
275 if (!ProcVector
[major
])
278 if (!XaceHook(XACE_CORE_DISPATCH
, client
))
281 return client
->swapped
?
282 (* SwappedProcVector
[major
])(client
) :
283 (* ProcVector
[major
])(client
);
287 XaceCatchExtProc(ClientPtr client
)
290 int major
= stuff
->reqType
;
291 ExtensionEntry
*ext
= GetExtensionEntry(major
);
293 if (!ext
|| !ProcVector
[major
])
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
308 * pcbl is &ClientStateCallback.
310 * calldata is a pointer to a NewClientInfoRec (include/dixstruct.h)
311 * which contains information about client state changes.
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.
328 XaceClientStateCallback(
329 CallbackListPtr
*pcbl
,
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
;
346 } /* XaceClientStateCallback */
350 * Initialize the XACE Extension
352 void XaceExtensionInit(INITARGS
)
354 ExtensionEntry
*extEntry
;
357 if (!AddCallback(&ClientStateCallback
, XaceClientStateCallback
, NULL
))
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
;
380 * Called after pScreen->GetImage to prevent pieces or trusted windows from
381 * being returned in image data from an untrusted window.
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.
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.
399 XaceCensorImage(client
, pVisibleRegion
, widthBytesLine
, pDraw
, x
, y
, w
, h
,
402 RegionPtr pVisibleRegion
;
410 RegionRec imageRegion
; /* region representing x,y,w,h */
411 RegionRec censorRegion
; /* region to obliterate */
415 pScreen
= pDraw
->pScreen
;
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
);
428 { /* we have something to censor */
429 GCPtr pScratchGC
= NULL
;
430 PixmapPtr pPix
= NULL
;
431 xRectangle
*pRects
= NULL
;
434 int bitsPerPixel
= 1;
438 /* convert region to list-of-rectangles for PolyFillRect */
440 pRects
= (xRectangle
*)ALLOCATE_LOCAL(nRects
* sizeof(xRectangle
*));
446 for (pBox
= REGION_RECTS(&censorRegion
), i
= 0;
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
,
466 widthBytesLine
, (pointer
)pBuf
);
473 pScratchGC
= GetScratchGC(depth
, pPix
->drawable
.pScreen
);
480 ValidateGC(&pPix
->drawable
, pScratchGC
);
481 (* pScratchGC
->ops
->PolyFillRect
)(&pPix
->drawable
,
482 pScratchGC
, nRects
, pRects
);
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 */