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