329 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			329 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C
		
	
	
	
| /************************************************************
 | |
| 
 | |
| Author: Eamon Walsh <ewalsh@tycho.nsa.gov>
 | |
| 
 | |
| Permission to use, copy, modify, distribute, and sell this software and its
 | |
| documentation for any purpose is hereby granted without fee, provided that
 | |
| this permission notice appear in supporting documentation.  This permission
 | |
| notice shall be included in all copies or substantial portions of the
 | |
| Software.
 | |
| 
 | |
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | |
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | |
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 | |
| AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 | |
| AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | |
| CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | |
| 
 | |
| ********************************************************/
 | |
| 
 | |
| #ifdef HAVE_DIX_CONFIG_H
 | |
| #include <dix-config.h>
 | |
| #endif
 | |
| 
 | |
| #include <stdarg.h>
 | |
| #include "scrnintstr.h"
 | |
| #include "extnsionst.h"
 | |
| #include "pixmapstr.h"
 | |
| #include "regionstr.h"
 | |
| #include "gcstruct.h"
 | |
| #include "xacestr.h"
 | |
| 
 | |
| CallbackListPtr XaceHooks[XACE_NUM_HOOKS] = { 0 };
 | |
| 
 | |
| /* Special-cased hook functions.  Called by Xserver.
 | |
|  */
 | |
| #undef XaceHookDispatch
 | |
| int
 | |
| XaceHookDispatch(ClientPtr client, int major)
 | |
| {
 | |
|     /* Call the extension dispatch hook */
 | |
|     ExtensionEntry *ext = GetExtensionEntry(major);
 | |
|     XaceExtAccessRec erec = { client, ext, DixUseAccess, Success };
 | |
|     if (ext)
 | |
|         CallCallbacks(&XaceHooks[XACE_EXT_DISPATCH], &erec);
 | |
|     /* On error, pretend extension doesn't exist */
 | |
|     return (erec.status == Success) ? Success : BadRequest;
 | |
| }
 | |
| 
 | |
| int
 | |
| XaceHookPropertyAccess(ClientPtr client, WindowPtr pWin,
 | |
|                        PropertyPtr *ppProp, Mask access_mode)
 | |
| {
 | |
|     XacePropertyAccessRec rec = { client, pWin, ppProp, access_mode, Success };
 | |
|     CallCallbacks(&XaceHooks[XACE_PROPERTY_ACCESS], &rec);
 | |
|     return rec.status;
 | |
| }
 | |
| 
 | |
| int
 | |
| XaceHookSelectionAccess(ClientPtr client, Selection ** ppSel, Mask access_mode)
 | |
| {
 | |
|     XaceSelectionAccessRec rec = { client, ppSel, access_mode, Success };
 | |
|     CallCallbacks(&XaceHooks[XACE_SELECTION_ACCESS], &rec);
 | |
|     return rec.status;
 | |
| }
 | |
| 
 | |
| /* Entry point for hook functions.  Called by Xserver.
 | |
|  */
 | |
| int
 | |
| XaceHook(int hook, ...)
 | |
| {
 | |
|     union {
 | |
|         XaceResourceAccessRec res;
 | |
|         XaceDeviceAccessRec dev;
 | |
|         XaceSendAccessRec send;
 | |
|         XaceReceiveAccessRec recv;
 | |
|         XaceClientAccessRec client;
 | |
|         XaceExtAccessRec ext;
 | |
|         XaceServerAccessRec server;
 | |
|         XaceScreenAccessRec screen;
 | |
|         XaceAuthAvailRec auth;
 | |
|         XaceKeyAvailRec key;
 | |
|     } u;
 | |
|     int *prv = NULL;            /* points to return value from callback */
 | |
|     va_list ap;                 /* argument list */
 | |
| 
 | |
|     if (!XaceHooks[hook])
 | |
|         return Success;
 | |
| 
 | |
|     va_start(ap, hook);
 | |
| 
 | |
|     /* Marshal arguments for passing to callback.
 | |
|      * Each callback has its own case, which sets up a structure to hold
 | |
|      * the arguments and integer return parameter, or in some cases just
 | |
|      * sets calldata directly to a single argument (with no return result)
 | |
|      */
 | |
|     switch (hook) {
 | |
|     case XACE_RESOURCE_ACCESS:
 | |
|         u.res.client = va_arg(ap, ClientPtr);
 | |
|         u.res.id = va_arg(ap, XID);
 | |
|         u.res.rtype = va_arg(ap, RESTYPE);
 | |
|         u.res.res = va_arg(ap, void *);
 | |
|         u.res.ptype = va_arg(ap, RESTYPE);
 | |
|         u.res.parent = va_arg(ap, void *);
 | |
|         u.res.access_mode = va_arg(ap, Mask);
 | |
| 
 | |
|         u.res.status = Success; /* default allow */
 | |
|         prv = &u.res.status;
 | |
|         break;
 | |
|     case XACE_DEVICE_ACCESS:
 | |
|         u.dev.client = va_arg(ap, ClientPtr);
 | |
|         u.dev.dev = va_arg(ap, DeviceIntPtr);
 | |
|         u.dev.access_mode = va_arg(ap, Mask);
 | |
| 
 | |
|         u.dev.status = Success; /* default allow */
 | |
|         prv = &u.dev.status;
 | |
|         break;
 | |
|     case XACE_SEND_ACCESS:
 | |
|         u.send.client = va_arg(ap, ClientPtr);
 | |
|         u.send.dev = va_arg(ap, DeviceIntPtr);
 | |
|         u.send.pWin = va_arg(ap, WindowPtr);
 | |
| 
 | |
|         u.send.events = va_arg(ap, xEventPtr);
 | |
|         u.send.count = va_arg(ap, int);
 | |
| 
 | |
|         u.send.status = Success;        /* default allow */
 | |
|         prv = &u.send.status;
 | |
|         break;
 | |
|     case XACE_RECEIVE_ACCESS:
 | |
|         u.recv.client = va_arg(ap, ClientPtr);
 | |
|         u.recv.pWin = va_arg(ap, WindowPtr);
 | |
| 
 | |
|         u.recv.events = va_arg(ap, xEventPtr);
 | |
|         u.recv.count = va_arg(ap, int);
 | |
| 
 | |
|         u.recv.status = Success;        /* default allow */
 | |
|         prv = &u.recv.status;
 | |
|         break;
 | |
|     case XACE_CLIENT_ACCESS:
 | |
|         u.client.client = va_arg(ap, ClientPtr);
 | |
|         u.client.target = va_arg(ap, ClientPtr);
 | |
|         u.client.access_mode = va_arg(ap, Mask);
 | |
| 
 | |
|         u.client.status = Success;      /* default allow */
 | |
|         prv = &u.client.status;
 | |
|         break;
 | |
|     case XACE_EXT_ACCESS:
 | |
|         u.ext.client = va_arg(ap, ClientPtr);
 | |
| 
 | |
|         u.ext.ext = va_arg(ap, ExtensionEntry *);
 | |
|         u.ext.access_mode = DixGetAttrAccess;
 | |
|         u.ext.status = Success; /* default allow */
 | |
|         prv = &u.ext.status;
 | |
|         break;
 | |
|     case XACE_SERVER_ACCESS:
 | |
|         u.server.client = va_arg(ap, ClientPtr);
 | |
|         u.server.access_mode = va_arg(ap, Mask);
 | |
| 
 | |
|         u.server.status = Success;      /* default allow */
 | |
|         prv = &u.server.status;
 | |
|         break;
 | |
|     case XACE_SCREEN_ACCESS:
 | |
|     case XACE_SCREENSAVER_ACCESS:
 | |
|         u.screen.client = va_arg(ap, ClientPtr);
 | |
|         u.screen.screen = va_arg(ap, ScreenPtr);
 | |
|         u.screen.access_mode = va_arg(ap, Mask);
 | |
| 
 | |
|         u.screen.status = Success;      /* default allow */
 | |
|         prv = &u.screen.status;
 | |
|         break;
 | |
|     case XACE_AUTH_AVAIL:
 | |
|         u.auth.client = va_arg(ap, ClientPtr);
 | |
|         u.auth.authId = va_arg(ap, XID);
 | |
| 
 | |
|         break;
 | |
|     case XACE_KEY_AVAIL:
 | |
|         u.key.event = va_arg(ap, xEventPtr);
 | |
|         u.key.keybd = va_arg(ap, DeviceIntPtr);
 | |
|         u.key.count = va_arg(ap, int);
 | |
| 
 | |
|         break;
 | |
|     default:
 | |
|         va_end(ap);
 | |
|         return 0;               /* unimplemented hook number */
 | |
|     }
 | |
|     va_end(ap);
 | |
| 
 | |
|     /* call callbacks and return result, if any. */
 | |
|     CallCallbacks(&XaceHooks[hook], &u);
 | |
|     return prv ? *prv : Success;
 | |
| }
 | |
| 
 | |
| /* XaceHookIsSet
 | |
|  *
 | |
|  * Utility function to determine whether there are any callbacks listening on a
 | |
|  * particular XACE hook.
 | |
|  *
 | |
|  * Returns non-zero if there is a callback, zero otherwise.
 | |
|  */
 | |
| int
 | |
| XaceHookIsSet(int hook)
 | |
| {
 | |
|     if (hook < 0 || hook >= XACE_NUM_HOOKS)
 | |
|         return 0;
 | |
|     return XaceHooks[hook] != NULL;
 | |
| }
 | |
| 
 | |
| /* XaceCensorImage
 | |
|  *
 | |
|  * Called after pScreen->GetImage to prevent pieces or trusted windows from
 | |
|  * being returned in image data from an untrusted window.
 | |
|  *
 | |
|  * Arguments:
 | |
|  *	client is the client doing the GetImage.
 | |
|  *      pVisibleRegion is the visible region of the window.
 | |
|  *	widthBytesLine is the width in bytes of one horizontal line in pBuf.
 | |
|  *	pDraw is the source window.
 | |
|  *	x, y, w, h is the rectangle of image data from pDraw in pBuf.
 | |
|  *	format is the format of the image data in pBuf: ZPixmap or XYPixmap.
 | |
|  *	pBuf is the image data.
 | |
|  *
 | |
|  * Returns: nothing.
 | |
|  *
 | |
|  * Side Effects:
 | |
|  *	Any part of the rectangle (x, y, w, h) that is outside the visible
 | |
|  *	region of the window will be destroyed (overwritten) in pBuf.
 | |
|  */
 | |
| void
 | |
| XaceCensorImage(ClientPtr client,
 | |
|                 RegionPtr pVisibleRegion,
 | |
|                 long widthBytesLine,
 | |
|                 DrawablePtr pDraw,
 | |
|                 int x, int y, int w, int h, unsigned int format, char *pBuf)
 | |
| {
 | |
|     RegionRec imageRegion;      /* region representing x,y,w,h */
 | |
|     RegionRec censorRegion;     /* region to obliterate */
 | |
|     BoxRec imageBox;
 | |
|     int nRects;
 | |
| 
 | |
|     imageBox.x1 = pDraw->x + x;
 | |
|     imageBox.y1 = pDraw->y + y;
 | |
|     imageBox.x2 = pDraw->x + x + w;
 | |
|     imageBox.y2 = pDraw->y + y + h;
 | |
|     RegionInit(&imageRegion, &imageBox, 1);
 | |
|     RegionNull(&censorRegion);
 | |
| 
 | |
|     /* censorRegion = imageRegion - visibleRegion */
 | |
|     RegionSubtract(&censorRegion, &imageRegion, pVisibleRegion);
 | |
|     nRects = RegionNumRects(&censorRegion);
 | |
|     if (nRects > 0) {           /* we have something to censor */
 | |
|         GCPtr pScratchGC = NULL;
 | |
|         PixmapPtr pPix = NULL;
 | |
|         xRectangle *pRects = NULL;
 | |
|         Bool failed = FALSE;
 | |
|         int depth = 1;
 | |
|         int bitsPerPixel = 1;
 | |
|         int i;
 | |
|         BoxPtr pBox;
 | |
| 
 | |
|         /* convert region to list-of-rectangles for PolyFillRect */
 | |
| 
 | |
|         pRects = malloc(nRects * sizeof(xRectangle));
 | |
|         if (!pRects) {
 | |
|             failed = TRUE;
 | |
|             goto failSafe;
 | |
|         }
 | |
|         for (pBox = RegionRects(&censorRegion), i = 0; i < nRects; i++, pBox++) {
 | |
|             pRects[i].x = pBox->x1 - imageBox.x1;
 | |
|             pRects[i].y = pBox->y1 - imageBox.y1;
 | |
|             pRects[i].width = pBox->x2 - pBox->x1;
 | |
|             pRects[i].height = pBox->y2 - pBox->y1;
 | |
|         }
 | |
| 
 | |
|         /* use pBuf as a fake pixmap */
 | |
| 
 | |
|         if (format == ZPixmap) {
 | |
|             depth = pDraw->depth;
 | |
|             bitsPerPixel = pDraw->bitsPerPixel;
 | |
|         }
 | |
| 
 | |
|         pPix = GetScratchPixmapHeader(pDraw->pScreen, w, h,
 | |
|                                       depth, bitsPerPixel,
 | |
|                                       widthBytesLine, (void *) pBuf);
 | |
|         if (!pPix) {
 | |
|             failed = TRUE;
 | |
|             goto failSafe;
 | |
|         }
 | |
| 
 | |
|         pScratchGC = GetScratchGC(depth, pPix->drawable.pScreen);
 | |
|         if (!pScratchGC) {
 | |
|             failed = TRUE;
 | |
|             goto failSafe;
 | |
|         }
 | |
| 
 | |
|         ValidateGC(&pPix->drawable, pScratchGC);
 | |
|         (*pScratchGC->ops->PolyFillRect) (&pPix->drawable,
 | |
|                                           pScratchGC, nRects, pRects);
 | |
| 
 | |
|  failSafe:
 | |
|         if (failed) {
 | |
|             /* Censoring was not completed above.  To be safe, wipe out
 | |
|              * all the image data so that nothing trusted gets out.
 | |
|              */
 | |
|             memset(pBuf, 0, (int) (widthBytesLine * h));
 | |
|         }
 | |
|         free(pRects);
 | |
|         if (pScratchGC)
 | |
|             FreeScratchGC(pScratchGC);
 | |
|         if (pPix)
 | |
|             FreeScratchPixmapHeader(pPix);
 | |
|     }
 | |
|     RegionUninit(&imageRegion);
 | |
|     RegionUninit(&censorRegion);
 | |
| }                               /* XaceCensorImage */
 | |
| 
 | |
| /*
 | |
|  * Xtrans wrappers for use by modules
 | |
|  */
 | |
| int
 | |
| XaceGetConnectionNumber(ClientPtr client)
 | |
| {
 | |
|     return GetClientFd(client);
 | |
| }
 | |
| 
 | |
| int
 | |
| XaceIsLocal(ClientPtr client)
 | |
| {
 | |
|     return ClientIsLocal(client);
 | |
| }
 |