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