284 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			284 lines
		
	
	
		
			8.7 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.
 | |
| 
 | |
| ********************************************************/
 | |
| 
 | |
| #include <dix-config.h>
 | |
| 
 | |
| #include <stdarg.h>
 | |
| 
 | |
| #include "os/client_priv.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.
 | |
|  */
 | |
| int
 | |
| XaceHookDispatch0(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;
 | |
| }
 | |
| 
 | |
| int XaceHookResourceAccess(ClientPtr client, XID id, RESTYPE rtype, void *res,
 | |
|                            RESTYPE ptype, void *parent, Mask access_mode)
 | |
| {
 | |
|     XaceResourceAccessRec rec = { client, id, rtype, res, ptype, parent,
 | |
|                                   access_mode, Success };
 | |
|     CallCallbacks(&XaceHooks[XACE_RESOURCE_ACCESS], &rec);
 | |
|     return rec.status;
 | |
| }
 | |
| 
 | |
| int XaceHookDeviceAccess(ClientPtr client, DeviceIntPtr dev, Mask access_mode)
 | |
| {
 | |
|     XaceDeviceAccessRec rec = { client, dev, access_mode, Success };
 | |
|     CallCallbacks(&XaceHooks[XACE_DEVICE_ACCESS], &rec);
 | |
|     return rec.status;
 | |
| }
 | |
| 
 | |
| int XaceHookSendAccess(ClientPtr client, DeviceIntPtr dev, WindowPtr win,
 | |
|                        xEventPtr ev, int count)
 | |
| {
 | |
|     XaceSendAccessRec rec = { client, dev, win, ev, count, Success };
 | |
|     CallCallbacks(&XaceHooks[XACE_SEND_ACCESS], &rec);
 | |
|     return rec.status;
 | |
| }
 | |
| 
 | |
| int XaceHookReceiveAccess(ClientPtr client, WindowPtr win,
 | |
|                           xEventPtr ev, int count)
 | |
| {
 | |
|     XaceReceiveAccessRec rec = { client, win, ev, count, Success };
 | |
|     CallCallbacks(&XaceHooks[XACE_RECEIVE_ACCESS], &rec);
 | |
|     return rec.status;
 | |
| }
 | |
| 
 | |
| int XaceHookClientAccess(ClientPtr client, ClientPtr target, Mask access_mode)
 | |
| {
 | |
|     XaceClientAccessRec rec = { client, target, access_mode, Success };
 | |
|     CallCallbacks(&XaceHooks[XACE_CLIENT_ACCESS], &rec);
 | |
|     return rec.status;
 | |
| }
 | |
| 
 | |
| int XaceHookExtAccess(ClientPtr client, ExtensionEntry *ext)
 | |
| {
 | |
|     XaceExtAccessRec rec = { client, ext, DixGetAttrAccess, Success };
 | |
|     CallCallbacks(&XaceHooks[XACE_EXT_ACCESS], &rec);
 | |
|     return rec.status;
 | |
| }
 | |
| 
 | |
| int XaceHookServerAccess(ClientPtr client, Mask access_mode)
 | |
| {
 | |
|     XaceServerAccessRec rec = { client, access_mode, Success };
 | |
|     CallCallbacks(&XaceHooks[XACE_SERVER_ACCESS], &rec);
 | |
|     return rec.status;
 | |
| }
 | |
| 
 | |
| int XaceHookScreenAccess(ClientPtr client, ScreenPtr screen, Mask access_mode)
 | |
| {
 | |
|     XaceScreenAccessRec rec = { client, screen, access_mode, Success };
 | |
|     CallCallbacks(&XaceHooks[XACE_SCREEN_ACCESS], &rec);
 | |
|     return rec.status;
 | |
| }
 | |
| 
 | |
| int XaceHookScreensaverAccess(ClientPtr client, ScreenPtr screen, Mask access_mode)
 | |
| {
 | |
|     XaceScreenAccessRec rec = { client, screen, access_mode, Success };
 | |
|     CallCallbacks(&XaceHooks[XACE_SCREENSAVER_ACCESS], &rec);
 | |
|     return rec.status;
 | |
| }
 | |
| 
 | |
| int XaceHookAuthAvail(ClientPtr client, XID authId)
 | |
| {
 | |
|     XaceAuthAvailRec rec = { client, authId };
 | |
|     CallCallbacks(&XaceHooks[XACE_AUTH_AVAIL], &rec);
 | |
|     return Success;
 | |
| }
 | |
| 
 | |
| int XaceHookKeyAvail(xEventPtr ev, DeviceIntPtr dev, int count)
 | |
| {
 | |
|     XaceKeyAvailRec rec = { ev, dev, count };
 | |
|     CallCallbacks(&XaceHooks[XACE_KEY_AVAIL], &rec);
 | |
|     return 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);
 | |
| }
 |