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