Modify XC-SECURITY and XC-APPGROUP extensions to work with XACE

This commit is contained in:
Eamon Walsh 2004-05-05 20:07:37 +00:00
parent 8526cd6395
commit 0106715000
2 changed files with 265 additions and 287 deletions

View File

@ -40,6 +40,7 @@ from The Open Group.
#define _XAG_SERVER_ #define _XAG_SERVER_
#include "Xagstr.h" #include "Xagstr.h"
#include "Xagsrv.h" #include "Xagsrv.h"
#include "xacestr.h"
#define _SECURITY_SERVER #define _SECURITY_SERVER
#include "security.h" #include "security.h"
#include "Xfuncproto.h" #include "Xfuncproto.h"
@ -125,60 +126,9 @@ void XagClientStateChange(
pointer nulldata, pointer nulldata,
pointer calldata) pointer calldata)
{ {
SecurityAuthorizationPtr pAuth;
NewClientInfoRec* pci = (NewClientInfoRec*) calldata; NewClientInfoRec* pci = (NewClientInfoRec*) calldata;
ClientPtr pClient = pci->client; ClientPtr pClient = pci->client;
AppGroupPtr pAppGrp; AppGroupPtr pAppGrp = pClient->appgroup;
XID authId = 0;
if (!pClient->appgroup) {
switch (pClient->clientState) {
case ClientStateAuthenticating:
case ClientStateRunning:
case ClientStateCheckingSecurity:
return;
case ClientStateInitial:
case ClientStateCheckedSecurity:
/*
* If the client is connecting via a firewall proxy (which
* uses XC-QUERY-SECURITY-1, then the authId is available
* during ClientStateCheckedSecurity, otherwise it's
* available during ClientStateInitial.
*
* Don't get it from pClient because can't guarantee the order
* of the callbacks and the security extension might not have
* plugged it in yet.
*/
authId = AuthorizationIDOfClient(pClient);
break;
case ClientStateGone:
case ClientStateRetained:
/*
* Don't get if from AuthorizationIDOfClient because can't
* guarantee the order of the callbacks and the security
* extension may have torn down the client's private data
*/
authId = pClient->authId;
break;
}
if (authId == None)
return;
pAuth = (SecurityAuthorizationPtr)SecurityLookupIDByType(pClient,
authId, SecurityAuthorizationResType, SecurityReadAccess);
if (pAuth == NULL)
return;
for (pAppGrp = appGrpList; pAppGrp != NULL; pAppGrp = pAppGrp->next)
if (pAppGrp->appgroupId == pAuth->group) break;
} else {
pAppGrp = pClient->appgroup;
}
if (!pAppGrp) if (!pAppGrp)
return; return;
@ -248,6 +198,7 @@ XagExtensionInit(INITARGS)
StandardMinorOpcode)) { StandardMinorOpcode)) {
#endif #endif
RT_APPGROUP = CreateNewResourceType (XagAppGroupFree); RT_APPGROUP = CreateNewResourceType (XagAppGroupFree);
XaceRegisterCallback(XACE_AUTH_AVAIL, XagCallClientStateChange, NULL);
} }
} }
@ -814,12 +765,33 @@ void XagGetDeltaInfo(
} }
void XagCallClientStateChange( void XagCallClientStateChange(
ClientPtr client) CallbackListPtr *pcbl,
pointer nulldata,
pointer calldata)
{ {
if (appGrpList) { XaceAuthAvailRec* rec = (XaceAuthAvailRec*) calldata;
ClientPtr pClient = rec->client;
if (!pClient->appgroup) {
SecurityAuthorizationPtr pAuth;
XID authId = rec->authId;
/* can't use SecurityLookupIDByType here -- client
* security state hasn't been setup yet.
*/
pAuth = (SecurityAuthorizationPtr)LookupIDByType(authId,
SecurityAuthorizationResType);
if (!pAuth)
return;
pClient->appgroup = (AppGroupPtr)LookupIDByType(pAuth->group,
RT_APPGROUP);
}
if (pClient->appgroup) {
NewClientInfoRec clientinfo; NewClientInfoRec clientinfo;
clientinfo.client = client; clientinfo.client = pClient;
XagClientStateChange (NULL, NULL, (pointer)&clientinfo); XagClientStateChange (NULL, NULL, (pointer)&clientinfo);
} }
} }

View File

@ -1,4 +1,4 @@
/* $XdotOrg: xc/programs/Xserver/Xext/security.c,v 1.2 2004/04/23 18:44:41 eich Exp $ */ /* $XdotOrg: xc/programs/Xserver/Xext/security.c,v 1.1.4.4.4.1 2004/05/04 19:43:00 ewalsh Exp $ */
/* $Xorg: security.c,v 1.4 2001/02/09 02:04:32 xorgcvs Exp $ */ /* $Xorg: security.c,v 1.4 2001/02/09 02:04:32 xorgcvs Exp $ */
/* /*
@ -35,13 +35,13 @@ in this Software without prior written authorization from The Open Group.
#include "gcstruct.h" #include "gcstruct.h"
#include "colormapst.h" #include "colormapst.h"
#include "propertyst.h" #include "propertyst.h"
#include "xacestr.h"
#define _SECURITY_SERVER #define _SECURITY_SERVER
#include "securstr.h" #include "securstr.h"
#include <assert.h> #include <assert.h>
#include <stdarg.h> #include <stdarg.h>
#ifdef LBX #ifdef LBX
#define _XLBX_SERVER_ #include "lbxserve.h"
#include "XLbx.h"
extern unsigned char LbxReqCode; extern unsigned char LbxReqCode;
#endif #endif
#ifdef XAPPGROUP #ifdef XAPPGROUP
@ -62,6 +62,17 @@ extern unsigned char LbxReqCode;
static int SecurityErrorBase; /* first Security error number */ static int SecurityErrorBase; /* first Security error number */
static int SecurityEventBase; /* first Security event number */ static int SecurityEventBase; /* first Security event number */
static int slot; /* Xace security state number */
/* this is what we store as client security state */
typedef struct {
unsigned int trustLevel;
XID authId;
} SecurityClientStateRec;
#define STATEPTR(obj) ((obj)->securityState[slot])
#define TRUSTLEVEL(obj) (((SecurityClientStateRec*)STATEPTR(obj))->trustLevel)
#define AUTHID(obj) (((SecurityClientStateRec*)STATEPTR(obj))->authId)
CallbackListPtr SecurityValidateGroupCallback = NULL; /* see security.h */ CallbackListPtr SecurityValidateGroupCallback = NULL; /* see security.h */
@ -69,19 +80,8 @@ RESTYPE SecurityAuthorizationResType; /* resource type for authorizations */
static RESTYPE RTEventClient; static RESTYPE RTEventClient;
/* Proc vectors for untrusted clients, swapped and unswapped versions. #define CALLBACK(name) static void \
* These are the same as the normal proc vectors except that extensions name(CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
* that haven't declared themselves secure will have ProcBadRequest plugged
* in for their major opcode dispatcher. This prevents untrusted clients
* from guessing extension major opcodes and using the extension even though
* the extension can't be listed or queried.
*/
int (*UntrustedProcVector[256])(
ClientPtr /*client*/
);
int (*SwappedUntrustedProcVector[256])(
ClientPtr /*client*/
);
/* SecurityAudit /* SecurityAudit
* *
@ -95,7 +95,7 @@ int (*SwappedUntrustedProcVector[256])(
* Writes the message to the log file if security logging is on. * Writes the message to the log file if security logging is on.
*/ */
void static void
SecurityAudit(char *format, ...) SecurityAudit(char *format, ...)
{ {
va_list args; va_list args;
@ -168,7 +168,7 @@ SecurityDeleteAuthorization(
for (i = 1; i<currentMaxClients; i++) for (i = 1; i<currentMaxClients; i++)
{ {
if (clients[i] && (clients[i]->authId == pAuth->id)) if (clients[i] && (AUTHID(clients[i]) == pAuth->id))
CloseDownClient(clients[i]); CloseDownClient(clients[i]);
} }
@ -322,7 +322,7 @@ ProcSecurityQueryVersion(
/* paranoia: this "can't happen" because this extension is hidden /* paranoia: this "can't happen" because this extension is hidden
* from untrusted clients, but just in case... * from untrusted clients, but just in case...
*/ */
if (client->trustLevel != XSecurityClientTrusted) if (TRUSTLEVEL(client) != XSecurityClientTrusted)
return BadRequest; return BadRequest;
REQUEST_SIZE_MATCH(xSecurityQueryVersionReq); REQUEST_SIZE_MATCH(xSecurityQueryVersionReq);
@ -408,7 +408,7 @@ ProcSecurityGenerateAuthorization(
/* paranoia: this "can't happen" because this extension is hidden /* paranoia: this "can't happen" because this extension is hidden
* from untrusted clients, but just in case... * from untrusted clients, but just in case...
*/ */
if (client->trustLevel != XSecurityClientTrusted) if (TRUSTLEVEL(client) != XSecurityClientTrusted)
return BadRequest; return BadRequest;
/* check request length */ /* check request length */
@ -591,7 +591,7 @@ ProcSecurityRevokeAuthorization(
/* paranoia: this "can't happen" because this extension is hidden /* paranoia: this "can't happen" because this extension is hidden
* from untrusted clients, but just in case... * from untrusted clients, but just in case...
*/ */
if (client->trustLevel != XSecurityClientTrusted) if (TRUSTLEVEL(client) != XSecurityClientTrusted)
return BadRequest; return BadRequest;
REQUEST_SIZE_MATCH(xSecurityRevokeAuthorizationReq); REQUEST_SIZE_MATCH(xSecurityRevokeAuthorizationReq);
@ -776,12 +776,12 @@ SecurityDetermineEventPropogationLimits(
* An audit message is generated if access is denied. * An audit message is generated if access is denied.
*/ */
Bool CALLBACK(SecurityCheckDeviceAccess)
SecurityCheckDeviceAccess(client, dev, fromRequest)
ClientPtr client;
DeviceIntPtr dev;
Bool fromRequest;
{ {
XaceDeviceAccessRec *rec = (XaceDeviceAccessRec*)calldata;
ClientPtr client = rec->client;
DeviceIntPtr dev = rec->dev;
Bool fromRequest = rec->fromRequest;
WindowPtr pWin, pStopWin; WindowPtr pWin, pStopWin;
Bool untrusted_got_event; Bool untrusted_got_event;
Bool found_event_window; Bool found_event_window;
@ -789,12 +789,12 @@ SecurityCheckDeviceAccess(client, dev, fromRequest)
int reqtype = 0; int reqtype = 0;
/* trusted clients always allowed to do anything */ /* trusted clients always allowed to do anything */
if (client->trustLevel == XSecurityClientTrusted) if (TRUSTLEVEL(client) == XSecurityClientTrusted)
return TRUE; return;
/* device security other than keyboard is not implemented yet */ /* device security other than keyboard is not implemented yet */
if (dev != inputInfo.keyboard) if (dev != inputInfo.keyboard)
return TRUE; return;
/* some untrusted client wants access */ /* some untrusted client wants access */
@ -809,7 +809,8 @@ SecurityCheckDeviceAccess(client, dev, fromRequest)
case X_SetModifierMapping: case X_SetModifierMapping:
SecurityAudit("client %d attempted request %d\n", SecurityAudit("client %d attempted request %d\n",
client->index, reqtype); client->index, reqtype);
return FALSE; rec->rval = FALSE;
return;
default: default:
break; break;
} }
@ -821,7 +822,7 @@ SecurityCheckDeviceAccess(client, dev, fromRequest)
if (dev->grab) if (dev->grab)
{ {
untrusted_got_event = untrusted_got_event =
((rClient(dev->grab))->trustLevel != XSecurityClientTrusted); (TRUSTLEVEL(rClient(dev->grab)) != XSecurityClientTrusted);
} }
else else
{ {
@ -836,7 +837,7 @@ SecurityCheckDeviceAccess(client, dev, fromRequest)
{ {
found_event_window = TRUE; found_event_window = TRUE;
client = wClient(pWin); client = wClient(pWin);
if (client->trustLevel != XSecurityClientTrusted) if (TRUSTLEVEL(client) != XSecurityClientTrusted)
{ {
untrusted_got_event = TRUE; untrusted_got_event = TRUE;
} }
@ -849,7 +850,7 @@ SecurityCheckDeviceAccess(client, dev, fromRequest)
if (other->mask & eventmask) if (other->mask & eventmask)
{ {
client = rClient(other); client = rClient(other);
if (client->trustLevel != XSecurityClientTrusted) if (TRUSTLEVEL(client) != XSecurityClientTrusted)
{ {
untrusted_got_event = TRUE; untrusted_got_event = TRUE;
break; break;
@ -877,8 +878,9 @@ SecurityCheckDeviceAccess(client, dev, fromRequest)
else else
SecurityAudit("client %d attempted to access device %d (%s)\n", SecurityAudit("client %d attempted to access device %d (%s)\n",
client->index, dev->id, devname); client->index, dev->id, devname);
rec->rval = FALSE;
} }
return untrusted_got_event; return;
} /* SecurityCheckDeviceAccess */ } /* SecurityCheckDeviceAccess */
@ -950,20 +952,22 @@ SecurityAuditResourceIDAccess(
* Disallowed resource accesses are audited. * Disallowed resource accesses are audited.
*/ */
static pointer CALLBACK(SecurityCheckResourceIDAccess)
SecurityCheckResourceIDAccess(
ClientPtr client,
XID id,
RESTYPE rtype,
Mask access_mode,
pointer rval)
{ {
int cid = CLIENT_ID(id); XaceResourceAccessRec *rec = (XaceResourceAccessRec*)calldata;
int reqtype = ((xReq *)client->requestBuffer)->reqType; ClientPtr client = rec->client;
XID id = rec->id;
RESTYPE rtype = rec->rtype;
Mask access_mode = rec->access_mode;
pointer rval = rec->res;
int cid, reqtype;
if (SecurityUnknownAccess == access_mode) if (TRUSTLEVEL(client) == XSecurityClientTrusted ||
return rval; /* for compatibility, we have to allow access */ SecurityUnknownAccess == access_mode)
return; /* for compatibility, we have to allow access */
cid = CLIENT_ID(id);
reqtype = ((xReq *)client->requestBuffer)->reqType;
switch (reqtype) switch (reqtype)
{ /* these are always allowed */ { /* these are always allowed */
case X_QueryTree: case X_QueryTree:
@ -975,7 +979,7 @@ SecurityCheckResourceIDAccess(
case X_DeleteProperty: case X_DeleteProperty:
case X_RotateProperties: case X_RotateProperties:
case X_ListProperties: case X_ListProperties:
return rval; return;
default: default:
break; break;
} }
@ -995,15 +999,15 @@ SecurityCheckResourceIDAccess(
* competing alternative for grouping clients for security purposes is to * competing alternative for grouping clients for security purposes is to
* use app groups. dpw * use app groups. dpw
*/ */
if (client->trustLevel == clients[cid]->trustLevel if (TRUSTLEVEL(client) == TRUSTLEVEL(clients[cid])
#ifdef XAPPGROUP #ifdef XAPPGROUP
|| (RT_COLORMAP == rtype && || (RT_COLORMAP == rtype &&
XagDefaultColormap (client) == (Colormap) id) XagDefaultColormap (client) == (Colormap) id)
#endif #endif
) )
return rval; return;
else else
return SecurityAuditResourceIDAccess(client, id); goto deny;
} }
else /* server-owned resource - probably a default colormap or root window */ else /* server-owned resource - probably a default colormap or root window */
{ {
@ -1039,7 +1043,7 @@ SecurityCheckResourceIDAccess(
) )
) )
{ /* not an ICCCM event */ { /* not an ICCCM event */
return SecurityAuditResourceIDAccess(client, id); goto deny;
} }
break; break;
} /* case X_SendEvent on root */ } /* case X_SendEvent on root */
@ -1057,7 +1061,7 @@ SecurityCheckResourceIDAccess(
~(PropertyChangeMask|StructureNotifyMask)) == 0) ~(PropertyChangeMask|StructureNotifyMask)) == 0)
break; break;
} }
return SecurityAuditResourceIDAccess(client, id); goto deny;
} /* case X_ChangeWindowAttributes on root */ } /* case X_ChangeWindowAttributes on root */
default: default:
@ -1068,29 +1072,32 @@ SecurityCheckResourceIDAccess(
switch (((xReq *)client->requestBuffer)->data) { switch (((xReq *)client->requestBuffer)->data) {
case X_LbxGetProperty: case X_LbxGetProperty:
case X_LbxChangeProperty: case X_LbxChangeProperty:
return rval; return;
default: default:
break; break;
} }
} }
#endif #endif
/* others not allowed */ /* others not allowed */
return SecurityAuditResourceIDAccess(client, id); goto deny;
} }
} }
} /* end server-owned window or drawable */ } /* end server-owned window or drawable */
else if (SecurityAuthorizationResType == rtype) else if (SecurityAuthorizationResType == rtype)
{ {
SecurityAuthorizationPtr pAuth = (SecurityAuthorizationPtr)rval; SecurityAuthorizationPtr pAuth = (SecurityAuthorizationPtr)rval;
if (pAuth->trustLevel != client->trustLevel) if (pAuth->trustLevel != TRUSTLEVEL(client))
return SecurityAuditResourceIDAccess(client, id); goto deny;
} }
else if (RT_COLORMAP != rtype) else if (RT_COLORMAP != rtype)
{ /* don't allow anything else besides colormaps */ { /* don't allow anything else besides colormaps */
return SecurityAuditResourceIDAccess(client, id); goto deny;
} }
} }
return rval; return;
deny:
SecurityAuditResourceIDAccess(client, id);
rec->rval = FALSE; /* deny access */
} /* SecurityCheckResourceIDAccess */ } /* SecurityCheckResourceIDAccess */
@ -1109,18 +1116,14 @@ SecurityCheckResourceIDAccess(
* If a new client is connecting, its authorization ID is copied to * If a new client is connecting, its authorization ID is copied to
* client->authID. If this is a generated authorization, its reference * client->authID. If this is a generated authorization, its reference
* count is bumped, its timer is cancelled if it was running, and its * count is bumped, its timer is cancelled if it was running, and its
* trustlevel is copied to client->trustLevel. * trustlevel is copied to TRUSTLEVEL(client).
* *
* If a client is disconnecting and the client was using a generated * If a client is disconnecting and the client was using a generated
* authorization, the authorization's reference count is decremented, and * authorization, the authorization's reference count is decremented, and
* if it is now zero, the timer for this authorization is started. * if it is now zero, the timer for this authorization is started.
*/ */
static void CALLBACK(SecurityClientStateCallback)
SecurityClientStateCallback(
CallbackListPtr *pcbl,
pointer nulldata,
pointer calldata)
{ {
NewClientInfoRec *pci = (NewClientInfoRec *)calldata; NewClientInfoRec *pci = (NewClientInfoRec *)calldata;
ClientPtr client = pci->client; ClientPtr client = pci->client;
@ -1132,7 +1135,14 @@ SecurityClientStateCallback(
XID authId = AuthorizationIDOfClient(client); XID authId = AuthorizationIDOfClient(client);
SecurityAuthorizationPtr pAuth; SecurityAuthorizationPtr pAuth;
client->authId = authId; /* allocate space for security state */
STATEPTR(client) = xalloc(sizeof(SecurityClientStateRec));
if (!STATEPTR(client))
FatalError("Client %d: couldn't allocate security state\n",
client->index);
TRUSTLEVEL(client) = XSecurityClientTrusted;
AUTHID(client) = authId;
pAuth = (SecurityAuthorizationPtr)LookupIDByType(authId, pAuth = (SecurityAuthorizationPtr)LookupIDByType(authId,
SecurityAuthorizationResType); SecurityAuthorizationResType);
if (pAuth) if (pAuth)
@ -1142,23 +1152,21 @@ SecurityClientStateCallback(
{ {
if (pAuth->timer) TimerCancel(pAuth->timer); if (pAuth->timer) TimerCancel(pAuth->timer);
} }
client->trustLevel = pAuth->trustLevel; TRUSTLEVEL(client) = pAuth->trustLevel;
if (client->trustLevel != XSecurityClientTrusted)
{
client->CheckAccess = SecurityCheckResourceIDAccess;
client->requestVector = client->swapped ?
SwappedUntrustedProcVector : UntrustedProcVector;
}
} }
break; break;
} }
case ClientStateGone: case ClientStateGone:
case ClientStateRetained: /* client disconnected */ case ClientStateRetained: /* client disconnected */
{ {
XID authId = client->authId;
SecurityAuthorizationPtr pAuth; SecurityAuthorizationPtr pAuth;
pointer freeit;
pAuth = (SecurityAuthorizationPtr)LookupIDByType(authId, /* client may not have any state (bad authorization) */
if (!STATEPTR(client))
break;
pAuth = (SecurityAuthorizationPtr)LookupIDByType(AUTHID(client),
SecurityAuthorizationResType); SecurityAuthorizationResType);
if (pAuth) if (pAuth)
{ /* it is a generated authorization */ { /* it is a generated authorization */
@ -1168,148 +1176,114 @@ SecurityClientStateCallback(
SecurityStartAuthorizationTimer(pAuth); SecurityStartAuthorizationTimer(pAuth);
} }
} }
/* free security state */
freeit = STATEPTR(client);
STATEPTR(client) = NULL;
xfree(freeit);
break; break;
} }
default: break; default: break;
} }
} /* SecurityClientStateCallback */ } /* SecurityClientStateCallback */
#ifdef LBX CALLBACK(SecurityCheckDrawableAccess)
Bool
SecuritySameLevel(client, authId)
ClientPtr client;
XID authId;
{ {
XaceDrawableAccessRec *rec = (XaceDrawableAccessRec*)calldata;
if (TRUSTLEVEL(rec->client) != XSecurityClientTrusted)
rec->rval = FALSE;
}
CALLBACK(SecurityCheckMapAccess)
{
XaceMapAccessRec *rec = (XaceMapAccessRec*)calldata;
WindowPtr pWin = rec->pWin;
if (STATEPTR(rec->client) &&
(TRUSTLEVEL(rec->client) != XSecurityClientTrusted) &&
(pWin->drawable.class == InputOnly) &&
(TRUSTLEVEL(wClient(pWin->parent)) == XSecurityClientTrusted))
rec->rval = FALSE;
}
CALLBACK(SecurityCheckBackgrndAccess)
{
XaceMapAccessRec *rec = (XaceMapAccessRec*)calldata;
if (TRUSTLEVEL(rec->client) != XSecurityClientTrusted)
rec->rval = FALSE;
}
CALLBACK(SecurityCheckExtAccess)
{
XaceExtAccessRec *rec = (XaceExtAccessRec*)calldata;
if ((TRUSTLEVEL(rec->client) != XSecurityClientTrusted) &&
!STATEPTR(rec->ext))
rec->rval = FALSE;
}
CALLBACK(SecurityCheckHostlistAccess)
{
XaceHostlistAccessRec *rec = (XaceHostlistAccessRec*)calldata;
if (TRUSTLEVEL(rec->client) != XSecurityClientTrusted)
{
rec->rval = FALSE;
if (rec->access_mode == SecurityWriteAccess)
SecurityAudit("client %d attempted to change host access\n",
rec->client->index);
else
SecurityAudit("client %d attempted to list hosts\n",
rec->client->index);
}
}
CALLBACK(SecurityDeclareExtSecure)
{
XaceDeclareExtSecureRec *rec = (XaceDeclareExtSecureRec*)calldata;
/* security state for extensions is simply a boolean trust value */
STATEPTR(rec->ext) = (pointer)rec->secure;
}
#ifdef LBX
CALLBACK(SecuritySameLevel)
{
XaceLbxProxyAccessRec *rec = (XaceLbxProxyAccessRec*)calldata;
ClientPtr client = rec->client;
XID authId = rec->authId;
SecurityAuthorizationPtr pAuth; SecurityAuthorizationPtr pAuth;
pAuth = (SecurityAuthorizationPtr)LookupIDByType(authId, pAuth = (SecurityAuthorizationPtr)LookupIDByType(authId,
SecurityAuthorizationResType); SecurityAuthorizationResType);
if (pAuth) if ((pAuth && TRUSTLEVEL(client) != pAuth->trustLevel) ||
return client->trustLevel == pAuth->trustLevel; (TRUSTLEVEL(client) != XSecurityClientTrusted))
return client->trustLevel == XSecurityClientTrusted; rec->rval = FALSE;
}
CALLBACK(SecurityCheckLbxExtAccess)
{
XaceLbxExtAccessRec *rec = (XaceLbxExtAccessRec*)calldata;
if ((TRUSTLEVEL(rec->client) != XSecurityClientTrusted) &&
!STATEPTR(rec->ext))
rec->rval = FALSE;
}
CALLBACK(SecurityDeclareLbxExtSecure)
{
XaceDeclareLbxExtSecureRec *rec =
(XaceDeclareLbxExtSecureRec*)calldata;
/* security state for extensions is simply a boolean trust value */
STATEPTR(rec->ext) = (pointer)rec->secure;
} }
#endif #endif
/* SecurityCensorImage
*
* 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
SecurityCensorImage(client, pVisibleRegion, widthBytesLine, pDraw, x, y, w, h,
format, pBuf)
ClientPtr client;
RegionPtr pVisibleRegion;
long widthBytesLine;
DrawablePtr pDraw;
int x, y, w, h;
unsigned int format;
char * pBuf;
{
ScreenPtr pScreen = pDraw->pScreen;
RegionRec imageRegion; /* region representing x,y,w,h */
RegionRec censorRegion; /* region to obliterate */
BoxRec imageBox;
int nRects;
imageBox.x1 = x;
imageBox.y1 = y;
imageBox.x2 = x + w;
imageBox.y2 = y + h;
REGION_INIT(pScreen, &imageRegion, &imageBox, 1);
REGION_NULL(pScreen, &censorRegion);
/* censorRegion = imageRegion - visibleRegion */
REGION_SUBTRACT(pScreen, &censorRegion, &imageRegion, pVisibleRegion);
nRects = REGION_NUM_RECTS(&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 = (xRectangle *)ALLOCATE_LOCAL(nRects * sizeof(xRectangle *));
if (!pRects)
{
failed = TRUE;
goto failSafe;
}
for (pBox = REGION_RECTS(&censorRegion), i = 0;
i < nRects;
i++, pBox++)
{
pRects[i].x = pBox->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, (pointer)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.
*/
bzero(pBuf, (int)(widthBytesLine * h));
}
if (pRects) DEALLOCATE_LOCAL(pRects);
if (pScratchGC) FreeScratchGC(pScratchGC);
if (pPix) FreeScratchPixmapHeader(pPix);
}
REGION_UNINIT(pScreen, &imageRegion);
REGION_UNINIT(pScreen, &censorRegion);
} /* SecurityCensorImage */
/**********************************************************************/ /**********************************************************************/
typedef struct _PropertyAccessRec { typedef struct _PropertyAccessRec {
@ -1767,21 +1741,21 @@ SecurityMatchString(
#endif #endif
char CALLBACK(SecurityCheckPropertyAccess)
SecurityCheckPropertyAccess(client, pWin, propertyName, access_mode)
ClientPtr client;
WindowPtr pWin;
ATOM propertyName;
Mask access_mode;
{ {
XacePropertyAccessRec *rec = (XacePropertyAccessRec*)calldata;
ClientPtr client = rec->client;
WindowPtr pWin = rec->pWin;
ATOM propertyName = rec->propertyName;
Mask access_mode = rec->access_mode;
PropertyAccessPtr pacl; PropertyAccessPtr pacl;
char action = SecurityDefaultAction; char action = SecurityDefaultAction;
/* if client trusted or window untrusted, allow operation */ /* if client trusted or window untrusted, allow operation */
if ( (client->trustLevel == XSecurityClientTrusted) || if ( (TRUSTLEVEL(client) == XSecurityClientTrusted) ||
(wClient(pWin)->trustLevel != XSecurityClientTrusted) ) (TRUSTLEVEL(wClient(pWin)) != XSecurityClientTrusted) )
return SecurityAllowOperation; return;
#ifdef PROPDEBUG #ifdef PROPDEBUG
/* For testing, it's more convenient if the property rules file gets /* For testing, it's more convenient if the property rules file gets
@ -1894,7 +1868,9 @@ SecurityCheckPropertyAccess(client, pWin, propertyName, access_mode)
client->index, reqtype, pWin->drawable.id, client->index, reqtype, pWin->drawable.id,
NameForAtom(propertyName), propertyName, cid, actionstr); NameForAtom(propertyName), propertyName, cid, actionstr);
} }
return action; /* return codes increase with strictness */
if (action > rec->rval)
rec->rval = action;
} /* SecurityCheckPropertyAccess */ } /* SecurityCheckPropertyAccess */
@ -1913,6 +1889,10 @@ static void
SecurityResetProc( SecurityResetProc(
ExtensionEntry *extEntry) ExtensionEntry *extEntry)
{ {
pointer freeit = STATEPTR(serverClient);
STATEPTR(serverClient) = NULL;
xfree(freeit);
XaceUnregisterExtension(slot);
SecurityFreePropertyAccessList(); SecurityFreePropertyAccessList();
SecurityFreeSitePolicyStrings(); SecurityFreeSitePolicyStrings();
} /* SecurityResetProc */ } /* SecurityResetProc */
@ -1934,6 +1914,48 @@ XSecurityOptions(argc, argv, i)
} /* XSecurityOptions */ } /* XSecurityOptions */
/* SecurityExtensionSetup
*
* Arguments: none.
*
* Returns: nothing.
*
* Side Effects:
* Sets up the Security extension if possible.
* This function contains things that need to be done
* before any other extension init functions get called.
*/
void
SecurityExtensionSetup(INITARGS)
{
/* allocate space for security state (freed in SecurityResetProc) */
STATEPTR(serverClient) = xalloc(sizeof(SecurityClientStateRec));
if (!STATEPTR(serverClient))
FatalError("serverClient: couldn't allocate security state\n");
TRUSTLEVEL(serverClient) = XSecurityClientTrusted;
AUTHID(serverClient) = None;
/* register callbacks */
#define XaceRC XaceRegisterCallback
XaceRC(XACE_RESOURCE_ACCESS, SecurityCheckResourceIDAccess, NULL);
XaceRC(XACE_DEVICE_ACCESS, SecurityCheckDeviceAccess, NULL);
XaceRC(XACE_PROPERTY_ACCESS, SecurityCheckPropertyAccess, NULL);
XaceRC(XACE_DRAWABLE_ACCESS, SecurityCheckDrawableAccess, NULL);
XaceRC(XACE_MAP_ACCESS, SecurityCheckMapAccess, NULL);
XaceRC(XACE_BACKGRND_ACCESS, SecurityCheckBackgrndAccess, NULL);
XaceRC(XACE_EXT_DISPATCH, SecurityCheckExtAccess, NULL);
XaceRC(XACE_EXT_ACCESS, SecurityCheckExtAccess, NULL);
XaceRC(XACE_HOSTLIST_ACCESS, SecurityCheckHostlistAccess, NULL);
XaceRC(XACE_DECLARE_EXT_SECURE, SecurityDeclareExtSecure, NULL);
#ifdef LBX
XaceRC(XACE_LBX_EXT_ACCESS, SecurityCheckLbxExtAccess, NULL);
XaceRC(XACE_DECLARE_LBX_EXT_SECURE, SecurityDeclareLbxExtSecure, NULL);
XaceRC(XACE_LBX_PROXY_ACCESS, SecuritySameLevel, NULL);
#endif
} /* SecurityExtensionSetup */
/* SecurityExtensionInit /* SecurityExtensionInit
* *
@ -1949,7 +1971,6 @@ void
SecurityExtensionInit(INITARGS) SecurityExtensionInit(INITARGS)
{ {
ExtensionEntry *extEntry; ExtensionEntry *extEntry;
int i;
SecurityAuthorizationResType = SecurityAuthorizationResType =
CreateNewResourceType(SecurityDeleteAuthorization); CreateNewResourceType(SecurityDeleteAuthorization);
@ -1965,6 +1986,10 @@ SecurityExtensionInit(INITARGS)
if (!AddCallback(&ClientStateCallback, SecurityClientStateCallback, NULL)) if (!AddCallback(&ClientStateCallback, SecurityClientStateCallback, NULL))
return; return;
slot = XaceRegisterExtension(SECURITY_EXTENSION_NAME);
if (slot < 0)
return;
extEntry = AddExtension(SECURITY_EXTENSION_NAME, extEntry = AddExtension(SECURITY_EXTENSION_NAME,
XSecurityNumberEvents, XSecurityNumberErrors, XSecurityNumberEvents, XSecurityNumberErrors,
ProcSecurityDispatch, SProcSecurityDispatch, ProcSecurityDispatch, SProcSecurityDispatch,
@ -1976,25 +2001,6 @@ SecurityExtensionInit(INITARGS)
EventSwapVector[SecurityEventBase + XSecurityAuthorizationRevoked] = EventSwapVector[SecurityEventBase + XSecurityAuthorizationRevoked] =
(EventSwapPtr)SwapSecurityAuthorizationRevokedEvent; (EventSwapPtr)SwapSecurityAuthorizationRevokedEvent;
/* initialize untrusted proc vectors */
for (i = 0; i < 128; i++)
{
UntrustedProcVector[i] = ProcVector[i];
SwappedUntrustedProcVector[i] = SwappedProcVector[i];
}
/* make sure insecure extensions are not allowed */
for (i = 128; i < 256; i++)
{
if (!UntrustedProcVector[i])
{
UntrustedProcVector[i] = ProcBadRequest;
SwappedUntrustedProcVector[i] = ProcBadRequest;
}
}
SecurityLoadPropertyAccessList(); SecurityLoadPropertyAccessList();
} /* SecurityExtensionInit */ } /* SecurityExtensionInit */