xref: /OK3568_Linux_fs/external/xserver/Xext/xace.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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