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