summaryrefslogtreecommitdiff
path: root/xserver/Xext/security.c
diff options
context:
space:
mode:
authorMatthieu Herrb <matthieu@cvs.openbsd.org>2008-11-02 15:26:35 +0000
committerMatthieu Herrb <matthieu@cvs.openbsd.org>2008-11-02 15:26:35 +0000
commitdbca69c8a4f3e2d1ccb4f89152213b2861b33af6 (patch)
treef8963ef73903a7b4374adc2354dffbaa905112ac /xserver/Xext/security.c
parent33b2029f322f3c238b7ba528083195ad8dde33e1 (diff)
xserver 1.5.2. tested by ckuethe@, oga@, and others.
Diffstat (limited to 'xserver/Xext/security.c')
-rw-r--r--xserver/Xext/security.c1496
1 files changed, 351 insertions, 1145 deletions
diff --git a/xserver/Xext/security.c b/xserver/Xext/security.c
index a8a75ea6c..ad30e06b8 100644
--- a/xserver/Xext/security.c
+++ b/xserver/Xext/security.c
@@ -28,63 +28,62 @@ in this Software without prior written authorization from The Open Group.
#include <dix-config.h>
#endif
-#include "dixstruct.h"
-#include "extnsionst.h"
-#include "windowstr.h"
-#include "inputstr.h"
#include "scrnintstr.h"
-#include "gcstruct.h"
-#include "colormapst.h"
+#include "inputstr.h"
+#include "windowstr.h"
#include "propertyst.h"
+#include "colormapst.h"
+#include "privates.h"
+#include "registry.h"
#include "xacestr.h"
#include "securitysrv.h"
#include <X11/extensions/securstr.h>
-#include <assert.h>
-#include <stdarg.h>
#ifdef XAPPGROUP
#include "appgroup.h"
#endif
-#include <stdio.h> /* for file reading operations */
-#include <X11/Xatom.h> /* for XA_STRING */
-
-#ifndef DEFAULTPOLICYFILE
-# define DEFAULTPOLICYFILE NULL
-#endif
-#if defined(WIN32) || defined(__CYGWIN__)
-#include <X11/Xos.h>
-#undef index
-#endif
-
#include "modinit.h"
+/* Extension stuff */
static int SecurityErrorBase; /* first Security error number */
static int SecurityEventBase; /* first Security event number */
-static int securityClientPrivateIndex;
-static int securityExtnsnPrivateIndex;
-/* this is what we store as client security state */
-typedef struct {
- unsigned int trustLevel;
- XID authId;
-} SecurityClientStateRec;
-
-#define STATEVAL(extnsn) \
- ((extnsn)->devPrivates[securityExtnsnPrivateIndex].val)
-#define STATEPTR(client) \
- ((client)->devPrivates[securityClientPrivateIndex].ptr)
-#define TRUSTLEVEL(client) \
- (((SecurityClientStateRec*)STATEPTR(client))->trustLevel)
-#define AUTHID(client) \
- (((SecurityClientStateRec*)STATEPTR(client))->authId)
+RESTYPE SecurityAuthorizationResType; /* resource type for authorizations */
+static RESTYPE RTEventClient;
static CallbackListPtr SecurityValidateGroupCallback = NULL;
-RESTYPE SecurityAuthorizationResType; /* resource type for authorizations */
+/* Private state record */
+static DevPrivateKey stateKey = &stateKey;
-static RESTYPE RTEventClient;
+/* This is what we store as client security state */
+typedef struct {
+ int haveState;
+ unsigned int trustLevel;
+ XID authId;
+} SecurityStateRec;
+
+/* Extensions that untrusted clients shouldn't have access to */
+static char *SecurityUntrustedExtensions[] = {
+ "RandR",
+ "SECURITY",
+ "XFree86-DGA",
+ NULL
+};
+
+/*
+ * Access modes that untrusted clients are allowed on trusted objects.
+ */
+static const Mask SecurityResourceMask =
+ DixGetAttrAccess | DixReceiveAccess | DixListPropAccess |
+ DixGetPropAccess | DixListAccess;
+static const Mask SecurityRootWindowExtraMask =
+ DixReceiveAccess | DixSendAccess | DixAddAccess | DixRemoveAccess;
+static const Mask SecurityDeviceMask =
+ DixGetAttrAccess | DixReceiveAccess | DixGetFocusAccess |
+ DixGrabAccess | DixSetAttrAccess | DixUseAccess;
+static const Mask SecurityServerMask = DixGetAttrAccess | DixGrabAccess;
+static const Mask SecurityClientMask = DixGetAttrAccess;
-#define CALLBACK(name) static void \
-name(CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
/* SecurityAudit
*
@@ -110,6 +109,51 @@ SecurityAudit(char *format, ...)
va_end(args);
} /* SecurityAudit */
+/*
+ * Performs a Security permission check.
+ */
+static int
+SecurityDoCheck(SecurityStateRec *subj, SecurityStateRec *obj,
+ Mask requested, Mask allowed)
+{
+ if (!subj->haveState || !obj->haveState)
+ return Success;
+ if (subj->trustLevel == XSecurityClientTrusted)
+ return Success;
+ if (obj->trustLevel != XSecurityClientTrusted)
+ return Success;
+ if ((requested | allowed) == allowed)
+ return Success;
+
+ return BadAccess;
+}
+
+/*
+ * Labels initial server objects.
+ */
+static void
+SecurityLabelInitial(void)
+{
+ SecurityStateRec *state;
+
+ /* Do the serverClient */
+ state = dixLookupPrivate(&serverClient->devPrivates, stateKey);
+ state->trustLevel = XSecurityClientTrusted;
+ state->haveState = TRUE;
+}
+
+/*
+ * Looks up a request name
+ */
+static _X_INLINE const char *
+SecurityLookupRequestName(ClientPtr client)
+{
+ int major = ((xReq *)client->requestBuffer)->reqType;
+ int minor = MinorOpcodeOfRequest(client);
+ return LookupRequestName(major, minor);
+}
+
+
#define rClient(obj) (clients[CLIENT_ID((obj)->resource)])
/* SecurityDeleteAuthorization
@@ -170,10 +214,12 @@ SecurityDeleteAuthorization(
/* kill all clients using this auth */
for (i = 1; i<currentMaxClients; i++)
- {
- if (clients[i] && (AUTHID(clients[i]) == pAuth->id))
- CloseDownClient(clients[i]);
- }
+ if (clients[i]) {
+ SecurityStateRec *state;
+ state = dixLookupPrivate(&clients[i]->devPrivates, stateKey);
+ if (state->haveState && state->authId == pAuth->id)
+ CloseDownClient(clients[i]);
+ }
SecurityAudit("revoked authorization ID %d\n", pAuth->id);
xfree(pAuth);
@@ -322,12 +368,6 @@ ProcSecurityQueryVersion(
/* REQUEST(xSecurityQueryVersionReq); */
xSecurityQueryVersionReply rep;
- /* paranoia: this "can't happen" because this extension is hidden
- * from untrusted clients, but just in case...
- */
- if (TRUSTLEVEL(client) != XSecurityClientTrusted)
- return BadRequest;
-
REQUEST_SIZE_MATCH(xSecurityQueryVersionReq);
rep.type = X_Reply;
rep.sequenceNumber = client->sequence;
@@ -408,12 +448,6 @@ ProcSecurityGenerateAuthorization(
char *pAuthdata; /* generated auth data */
Mask eventMask; /* what events on this auth does client want */
- /* paranoia: this "can't happen" because this extension is hidden
- * from untrusted clients, but just in case...
- */
- if (TRUSTLEVEL(client) != XSecurityClientTrusted)
- return BadRequest;
-
/* check request length */
REQUEST_AT_LEAST_SIZE(xSecurityGenerateAuthorizationReq);
@@ -591,12 +625,6 @@ ProcSecurityRevokeAuthorization(
REQUEST(xSecurityRevokeAuthorizationReq);
SecurityAuthorizationPtr pAuth;
- /* paranoia: this "can't happen" because this extension is hidden
- * from untrusted clients, but just in case...
- */
- if (TRUSTLEVEL(client) != XSecurityClientTrusted)
- return BadRequest;
-
REQUEST_SIZE_MATCH(xSecurityRevokeAuthorizationReq);
pAuth = (SecurityAuthorizationPtr)SecurityLookupIDByType(client,
@@ -714,59 +742,6 @@ SwapSecurityAuthorizationRevokedEvent(
cpswapl(from->authId, to->authId);
}
-/* SecurityDetermineEventPropogationLimits
- *
- * This is a helper function for SecurityCheckDeviceAccess.
- *
- * Arguments:
- * dev is the device for which the starting and stopping windows for
- * event propogation should be determined.
- * The values pointed to by ppWin and ppStopWin are not used.
- *
- * Returns:
- * ppWin is filled in with a pointer to the window at which event
- * propogation for the given device should start given the current
- * state of the server (pointer position, window layout, etc.)
- * ppStopWin is filled in with the window at which event propogation
- * should stop; events should not go to ppStopWin.
- *
- * Side Effects: none.
- */
-
-static void
-SecurityDetermineEventPropogationLimits(
- DeviceIntPtr dev,
- WindowPtr *ppWin,
- WindowPtr *ppStopWin)
-{
- WindowPtr pFocusWin = dev->focus ? dev->focus->win : NoneWin;
-
- if (pFocusWin == NoneWin)
- { /* no focus -- events don't go anywhere */
- *ppWin = *ppStopWin = NULL;
- return;
- }
-
- if (pFocusWin == PointerRootWin)
- { /* focus follows the pointer */
- *ppWin = GetSpriteWindow();
- *ppStopWin = NULL; /* propogate all the way to the root */
- }
- else
- { /* a real window is set for the focus */
- WindowPtr pSpriteWin = GetSpriteWindow();
- *ppStopWin = pFocusWin->parent; /* don't go past the focus window */
-
- /* if the pointer is in a subwindow of the focus window, start
- * at that subwindow, else start at the focus window itself
- */
- if (IsParent(pFocusWin, pSpriteWin))
- *ppWin = pSpriteWin;
- else *ppWin = pFocusWin;
- }
-} /* SecurityDetermineEventPropogationLimits */
-
-
/* SecurityCheckDeviceAccess
*
* Arguments:
@@ -783,162 +758,30 @@ SecurityDetermineEventPropogationLimits(
* An audit message is generated if access is denied.
*/
-CALLBACK(SecurityCheckDeviceAccess)
-{
- XaceDeviceAccessRec *rec = (XaceDeviceAccessRec*)calldata;
- ClientPtr client = rec->client;
- DeviceIntPtr dev = rec->dev;
- Bool fromRequest = rec->fromRequest;
- WindowPtr pWin, pStopWin;
- Bool untrusted_got_event;
- Bool found_event_window;
- Mask eventmask;
- int reqtype = 0;
-
- /* trusted clients always allowed to do anything */
- if (TRUSTLEVEL(client) == XSecurityClientTrusted)
- return;
-
- /* device security other than keyboard is not implemented yet */
- if (dev != inputInfo.keyboard)
- return;
-
- /* some untrusted client wants access */
-
- if (fromRequest)
- {
- reqtype = ((xReq *)client->requestBuffer)->reqType;
- switch (reqtype)
- {
- /* never allow these */
- case X_ChangeKeyboardMapping:
- case X_ChangeKeyboardControl:
- case X_SetModifierMapping:
- SecurityAudit("client %d attempted request %d\n",
- client->index, reqtype);
- rec->rval = FALSE;
- return;
- default:
- break;
- }
- }
-
- untrusted_got_event = FALSE;
- found_event_window = FALSE;
-
- if (dev->grab)
- {
- untrusted_got_event =
- (TRUSTLEVEL(rClient(dev->grab)) != XSecurityClientTrusted);
- }
- else
- {
- SecurityDetermineEventPropogationLimits(dev, &pWin, &pStopWin);
-
- eventmask = KeyPressMask | KeyReleaseMask;
- while ( (pWin != pStopWin) && !found_event_window)
- {
- OtherClients *other;
-
- if (pWin->eventMask & eventmask)
- {
- found_event_window = TRUE;
- client = wClient(pWin);
- if (TRUSTLEVEL(client) != XSecurityClientTrusted)
- {
- untrusted_got_event = TRUE;
- }
- }
- if (wOtherEventMasks(pWin) & eventmask)
- {
- found_event_window = TRUE;
- for (other = wOtherClients(pWin); other; other = other->next)
- {
- if (other->mask & eventmask)
- {
- client = rClient(other);
- if (TRUSTLEVEL(client) != XSecurityClientTrusted)
- {
- untrusted_got_event = TRUE;
- break;
- }
- }
- }
- }
- if (wDontPropagateMask(pWin) & eventmask)
- break;
- pWin = pWin->parent;
- } /* while propogating the event */
- }
-
- /* allow access by untrusted clients only if an event would have gone
- * to an untrusted client
- */
-
- if (!untrusted_got_event)
- {
- char *devname = dev->name;
- if (!devname) devname = "unnamed";
- if (fromRequest)
- SecurityAudit("client %d attempted request %d device %d (%s)\n",
- client->index, reqtype, dev->id, devname);
- else
- SecurityAudit("client %d attempted to access device %d (%s)\n",
- client->index, dev->id, devname);
- rec->rval = FALSE;
- }
- return;
-} /* SecurityCheckDeviceAccess */
-
-
-
-/* SecurityAuditResourceIDAccess
- *
- * Arguments:
- * client is the client doing the resource access.
- * id is the resource id.
- *
- * Returns: NULL
- *
- * Side Effects:
- * An audit message is generated with details of the denied
- * resource access.
- */
-
-static pointer
-SecurityAuditResourceIDAccess(
- ClientPtr client,
- XID id)
+static void
+SecurityDevice(CallbackListPtr *pcbl, pointer unused, pointer calldata)
{
- int cid = CLIENT_ID(id);
- int reqtype = ((xReq *)client->requestBuffer)->reqType;
- switch (reqtype)
- {
- case X_ChangeProperty:
- case X_DeleteProperty:
- case X_GetProperty:
- {
- xChangePropertyReq *req =
- (xChangePropertyReq *)client->requestBuffer;
- int propertyatom = req->property;
- char *propertyname = NameForAtom(propertyatom);
-
- SecurityAudit("client %d attempted request %d with window 0x%x property %s of client %d\n",
- client->index, reqtype, id, propertyname, cid);
- break;
- }
- default:
- {
- SecurityAudit("client %d attempted request %d with resource 0x%x of client %d\n",
- client->index, reqtype, id, cid);
- break;
- }
+ XaceDeviceAccessRec *rec = calldata;
+ SecurityStateRec *subj, *obj;
+ Mask requested = rec->access_mode;
+ Mask allowed = SecurityDeviceMask;
+
+ subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
+ obj = dixLookupPrivate(&serverClient->devPrivates, stateKey);
+
+ if (rec->dev != inputInfo.keyboard)
+ /* this extension only supports the core keyboard */
+ allowed = requested;
+
+ if (SecurityDoCheck(subj, obj, requested, allowed) != Success) {
+ SecurityAudit("Security denied client %d keyboard access on request "
+ "%s\n", rec->client->index,
+ SecurityLookupRequestName(rec->client));
+ rec->status = BadAccess;
}
- return NULL;
-} /* SecurityAuditResourceIDAccess */
-
+}
-/* SecurityCheckResourceIDAccess
+/* SecurityResource
*
* This function gets plugged into client->CheckAccess and is called from
* SecurityLookupIDByType/Class to determine if the client can access the
@@ -959,867 +802,256 @@ SecurityAuditResourceIDAccess(
* Disallowed resource accesses are audited.
*/
-CALLBACK(SecurityCheckResourceIDAccess)
+static void
+SecurityResource(CallbackListPtr *pcbl, pointer unused, pointer calldata)
{
- XaceResourceAccessRec *rec = (XaceResourceAccessRec*)calldata;
- 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 (TRUSTLEVEL(client) == XSecurityClientTrusted ||
- DixUnknownAccess == access_mode)
- return; /* for compatibility, we have to allow access */
-
- cid = CLIENT_ID(id);
- reqtype = ((xReq *)client->requestBuffer)->reqType;
- switch (reqtype)
- { /* these are always allowed */
- case X_QueryTree:
- case X_TranslateCoords:
- case X_GetGeometry:
- /* property access is controlled in SecurityCheckPropertyAccess */
- case X_GetProperty:
- case X_ChangeProperty:
- case X_DeleteProperty:
- case X_RotateProperties:
- case X_ListProperties:
- return;
- default:
- break;
- }
+ XaceResourceAccessRec *rec = calldata;
+ SecurityStateRec *subj, *obj;
+ int cid = CLIENT_ID(rec->id);
+ Mask requested = rec->access_mode;
+ Mask allowed = SecurityResourceMask;
+
+ subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
+ obj = dixLookupPrivate(&clients[cid]->devPrivates, stateKey);
+
+ /* disable background None for untrusted windows */
+ if ((requested & DixCreateAccess) && (rec->rtype == RT_WINDOW))
+ if (subj->haveState && subj->trustLevel != XSecurityClientTrusted)
+ ((WindowPtr)rec->res)->forcedBG = TRUE;
+
+ /* special checks for server-owned resources */
+ if (cid == 0) {
+ if (rec->rtype & RC_DRAWABLE)
+ /* additional operations allowed on root windows */
+ allowed |= SecurityRootWindowExtraMask;
+
+ else if (rec->rtype == RT_COLORMAP)
+ /* allow access to default colormaps */
+ allowed = requested;
- if (cid != 0)
- { /* not a server-owned resource */
- /*
- * The following 'if' restricts clients to only access resources at
- * the same trustLevel. Since there are currently only two trust levels,
- * and trusted clients never call this function, this degenerates into
- * saying that untrusted clients can only access resources of other
- * untrusted clients. One way to add the notion of groups would be to
- * allow values other than Trusted (0) and Untrusted (1) for this field.
- * Clients at the same trust level would be able to use each other's
- * resources, but not those of clients at other trust levels. I haven't
- * tried it, but this probably mostly works already. The obvious
- * competing alternative for grouping clients for security purposes is to
- * use app groups. dpw
- */
- if (TRUSTLEVEL(client) == TRUSTLEVEL(clients[cid])
-#ifdef XAPPGROUP
- || (RT_COLORMAP == rtype &&
- XagDefaultColormap (client) == (Colormap) id)
-#endif
- )
- return;
else
- goto deny;
+ /* allow read access to other server-owned resources */
+ allowed |= DixReadAccess;
}
- else /* server-owned resource - probably a default colormap or root window */
- {
- if (RC_DRAWABLE & rtype)
- {
- switch (reqtype)
- { /* the following operations are allowed on root windows */
- case X_CreatePixmap:
- case X_CreateGC:
- case X_CreateWindow:
- case X_CreateColormap:
- case X_ListProperties:
- case X_GrabPointer:
- case X_UngrabButton:
- case X_QueryBestSize:
- case X_GetWindowAttributes:
- break;
- case X_SendEvent:
- { /* see if it is an event specified by the ICCCM */
- xSendEventReq *req = (xSendEventReq *)
- (client->requestBuffer);
- if (req->propagate == xTrue
- ||
- (req->eventMask != ColormapChangeMask &&
- req->eventMask != StructureNotifyMask &&
- req->eventMask !=
- (SubstructureRedirectMask|SubstructureNotifyMask)
- )
- ||
- (req->event.u.u.type != UnmapNotify &&
- req->event.u.u.type != ConfigureRequest &&
- req->event.u.u.type != ClientMessage
- )
- )
- { /* not an ICCCM event */
- goto deny;
- }
- break;
- } /* case X_SendEvent on root */
-
- case X_ChangeWindowAttributes:
- { /* Allow selection of PropertyNotify and StructureNotify
- * events on the root.
- */
- xChangeWindowAttributesReq *req =
- (xChangeWindowAttributesReq *)(client->requestBuffer);
- if (req->valueMask == CWEventMask)
- {
- CARD32 value = *((CARD32 *)(req + 1));
- if ( (value &
- ~(PropertyChangeMask|StructureNotifyMask)) == 0)
- break;
- }
- goto deny;
- } /* case X_ChangeWindowAttributes on root */
-
- default:
- {
- /* others not allowed */
- goto deny;
- }
- }
- } /* end server-owned window or drawable */
- else if (SecurityAuthorizationResType == rtype)
- {
- SecurityAuthorizationPtr pAuth = (SecurityAuthorizationPtr)rval;
- if (pAuth->trustLevel != TRUSTLEVEL(client))
- goto deny;
- }
- else if (RT_COLORMAP != rtype)
- { /* don't allow anything else besides colormaps */
- goto deny;
- }
- }
- return;
- deny:
- SecurityAuditResourceIDAccess(client, id);
- rec->rval = FALSE; /* deny access */
-} /* SecurityCheckResourceIDAccess */
-
-
-/* SecurityClientStateCallback
- *
- * Arguments:
- * pcbl is &ClientStateCallback.
- * nullata is NULL.
- * calldata is a pointer to a NewClientInfoRec (include/dixstruct.h)
- * which contains information about client state changes.
- *
- * Returns: nothing.
- *
- * Side Effects:
- *
- * If a new client is connecting, its authorization ID is copied to
- * client->authID. If this is a generated authorization, its reference
- * count is bumped, its timer is cancelled if it was running, and its
- * trustlevel is copied to TRUSTLEVEL(client).
- *
- * If a client is disconnecting and the client was using a generated
- * authorization, the authorization's reference count is decremented, and
- * if it is now zero, the timer for this authorization is started.
- */
-CALLBACK(SecurityClientStateCallback)
-{
- NewClientInfoRec *pci = (NewClientInfoRec *)calldata;
- ClientPtr client = pci->client;
-
- switch (client->clientState)
- {
- case ClientStateInitial:
- TRUSTLEVEL(client) = XSecurityClientTrusted;
- AUTHID(client) = None;
- break;
-
- case ClientStateRunning:
- {
- XID authId = AuthorizationIDOfClient(client);
- SecurityAuthorizationPtr pAuth;
-
- TRUSTLEVEL(client) = XSecurityClientTrusted;
- AUTHID(client) = authId;
- pAuth = (SecurityAuthorizationPtr)LookupIDByType(authId,
- SecurityAuthorizationResType);
- if (pAuth)
- { /* it is a generated authorization */
- pAuth->refcnt++;
- if (pAuth->refcnt == 1)
- {
- if (pAuth->timer) TimerCancel(pAuth->timer);
- }
- TRUSTLEVEL(client) = pAuth->trustLevel;
- }
- break;
- }
- case ClientStateGone:
- case ClientStateRetained: /* client disconnected */
- {
- SecurityAuthorizationPtr pAuth;
-
- /* client may not have any state (bad authorization) */
- if (!STATEPTR(client))
- break;
-
- pAuth = (SecurityAuthorizationPtr)LookupIDByType(AUTHID(client),
- SecurityAuthorizationResType);
- if (pAuth)
- { /* it is a generated authorization */
- pAuth->refcnt--;
- if (pAuth->refcnt == 0)
- {
- SecurityStartAuthorizationTimer(pAuth);
- }
- }
- break;
- }
- default: break;
- }
-} /* SecurityClientStateCallback */
+ if (SecurityDoCheck(subj, obj, requested, allowed) == Success)
+ return;
-CALLBACK(SecurityCheckDrawableAccess)
-{
- XaceDrawableAccessRec *rec = (XaceDrawableAccessRec*)calldata;
+#ifdef XAPPGROUP
+ if (rec->id == XagDefaultColormap(rec->client))
+ return;
+#endif
- if (TRUSTLEVEL(rec->client) != XSecurityClientTrusted)
- rec->rval = FALSE;
+ SecurityAudit("Security: denied client %d access %x to resource 0x%x "
+ "of client %d on request %s\n", rec->client->index,
+ requested, rec->id, cid,
+ SecurityLookupRequestName(rec->client));
+ rec->status = BadAccess; /* deny access */
}
-CALLBACK(SecurityCheckMapAccess)
-{
- XaceMapAccessRec *rec = (XaceMapAccessRec*)calldata;
- WindowPtr pWin = rec->pWin;
-
- if (STATEPTR(rec->client) &&
- (TRUSTLEVEL(rec->client) != XSecurityClientTrusted) &&
- (pWin->drawable.class == InputOnly) &&
- pWin->parent && pWin->parent->parent &&
- (TRUSTLEVEL(wClient(pWin->parent)) == XSecurityClientTrusted))
- rec->rval = FALSE;
-}
-
-CALLBACK(SecurityCheckBackgrndAccess)
+static void
+SecurityExtension(CallbackListPtr *pcbl, pointer unused, pointer calldata)
{
- XaceMapAccessRec *rec = (XaceMapAccessRec*)calldata;
-
- if (TRUSTLEVEL(rec->client) != XSecurityClientTrusted)
- rec->rval = FALSE;
+ XaceExtAccessRec *rec = calldata;
+ SecurityStateRec *subj;
+ int i = 0;
+
+ subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
+
+ if (subj->haveState && subj->trustLevel != XSecurityClientTrusted)
+ while (SecurityUntrustedExtensions[i])
+ if (!strcmp(SecurityUntrustedExtensions[i++], rec->ext->name)) {
+ SecurityAudit("Security: denied client %d access to extension "
+ "%s on request %s\n",
+ rec->client->index, rec->ext->name,
+ SecurityLookupRequestName(rec->client));
+ rec->status = BadAccess;
+ return;
+ }
}
-CALLBACK(SecurityCheckExtAccess)
+static void
+SecurityServer(CallbackListPtr *pcbl, pointer unused, pointer calldata)
{
- XaceExtAccessRec *rec = (XaceExtAccessRec*)calldata;
-
- if ((TRUSTLEVEL(rec->client) != XSecurityClientTrusted) &&
- !STATEVAL(rec->ext))
-
- rec->rval = FALSE;
-}
+ XaceServerAccessRec *rec = calldata;
+ SecurityStateRec *subj, *obj;
+ Mask requested = rec->access_mode;
+ Mask allowed = SecurityServerMask;
-CALLBACK(SecurityCheckHostlistAccess)
-{
- XaceHostlistAccessRec *rec = (XaceHostlistAccessRec*)calldata;
+ subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
+ obj = dixLookupPrivate(&serverClient->devPrivates, stateKey);
- if (TRUSTLEVEL(rec->client) != XSecurityClientTrusted)
- {
- rec->rval = FALSE;
- if (rec->access_mode == DixWriteAccess)
- SecurityAudit("client %d attempted to change host access\n",
- rec->client->index);
- else
- SecurityAudit("client %d attempted to list hosts\n",
- rec->client->index);
+ if (SecurityDoCheck(subj, obj, requested, allowed) != Success) {
+ SecurityAudit("Security: denied client %d access to server "
+ "configuration request %s\n", rec->client->index,
+ SecurityLookupRequestName(rec->client));
+ rec->status = BadAccess;
}
}
-CALLBACK(SecurityDeclareExtSecure)
-{
- XaceDeclareExtSecureRec *rec = (XaceDeclareExtSecureRec*)calldata;
-
- /* security state for extensions is simply a boolean trust value */
- STATEVAL(rec->ext) = rec->secure;
-}
-
-/**********************************************************************/
-
-typedef struct _PropertyAccessRec {
- ATOM name;
- ATOM mustHaveProperty;
- char *mustHaveValue;
- char windowRestriction;
-#define SecurityAnyWindow 0
-#define SecurityRootWindow 1
-#define SecurityWindowWithProperty 2
- char readAction;
- char writeAction;
- char destroyAction;
- struct _PropertyAccessRec *next;
-} PropertyAccessRec, *PropertyAccessPtr;
-
-static PropertyAccessPtr PropertyAccessList = NULL;
-static char SecurityDefaultAction = XaceErrorOperation;
-static char *SecurityPolicyFile = DEFAULTPOLICYFILE;
-static ATOM SecurityMaxPropertyName = 0;
-
-static char *SecurityKeywords[] = {
-#define SecurityKeywordComment 0
- "#",
-#define SecurityKeywordProperty 1
- "property",
-#define SecurityKeywordSitePolicy 2
- "sitepolicy",
-#define SecurityKeywordRoot 3
- "root",
-#define SecurityKeywordAny 4
- "any"
-};
-
-#define NUMKEYWORDS (sizeof(SecurityKeywords) / sizeof(char *))
-
-#undef PROPDEBUG
-/*#define PROPDEBUG 1*/
-
static void
-SecurityFreePropertyAccessList(void)
-{
- while (PropertyAccessList)
- {
- PropertyAccessPtr freeit = PropertyAccessList;
- PropertyAccessList = PropertyAccessList->next;
- xfree(freeit);
- }
-} /* SecurityFreePropertyAccessList */
-
-#define SecurityIsWhitespace(c) ( (c == ' ') || (c == '\t') || (c == '\n') )
-
-static char *
-SecuritySkipWhitespace(
- char *p)
-{
- while (SecurityIsWhitespace(*p))
- p++;
- return p;
-} /* SecuritySkipWhitespace */
-
-
-static char *
-SecurityParseString(
- char **rest)
-{
- char *startOfString;
- char *s = *rest;
- char endChar = 0;
-
- s = SecuritySkipWhitespace(s);
-
- if (*s == '"' || *s == '\'')
- {
- endChar = *s++;
- startOfString = s;
- while (*s && (*s != endChar))
- s++;
- }
- else
- {
- startOfString = s;
- while (*s && !SecurityIsWhitespace(*s))
- s++;
- }
- if (*s)
- {
- *s = '\0';
- *rest = s + 1;
- return startOfString;
- }
- else
- {
- *rest = s;
- return (endChar) ? NULL : startOfString;
- }
-} /* SecurityParseString */
-
-
-static int
-SecurityParseKeyword(
- char **p)
+SecurityClient(CallbackListPtr *pcbl, pointer unused, pointer calldata)
{
- int i;
- char *s = *p;
- s = SecuritySkipWhitespace(s);
- for (i = 0; i < NUMKEYWORDS; i++)
- {
- int len = strlen(SecurityKeywords[i]);
- if (strncmp(s, SecurityKeywords[i], len) == 0)
- {
- *p = s + len;
- return (i);
- }
- }
- *p = s;
- return -1;
-} /* SecurityParseKeyword */
-
-
-static Bool
-SecurityParsePropertyAccessRule(
- char *p)
-{
- char *propname;
- char c;
- char action = SecurityDefaultAction;
- char readAction, writeAction, destroyAction;
- PropertyAccessPtr pacl, prev, cur;
- char *mustHaveProperty = NULL;
- char *mustHaveValue = NULL;
- Bool invalid;
- char windowRestriction;
- int size;
- int keyword;
-
- /* get property name */
- propname = SecurityParseString(&p);
- if (!propname || (strlen(propname) == 0))
- return FALSE;
-
- /* get window on which property must reside for rule to apply */
-
- keyword = SecurityParseKeyword(&p);
- if (keyword == SecurityKeywordRoot)
- windowRestriction = SecurityRootWindow;
- else if (keyword == SecurityKeywordAny)
- windowRestriction = SecurityAnyWindow;
- else /* not root or any, must be a property name */
- {
- mustHaveProperty = SecurityParseString(&p);
- if (!mustHaveProperty || (strlen(mustHaveProperty) == 0))
- return FALSE;
- windowRestriction = SecurityWindowWithProperty;
- p = SecuritySkipWhitespace(p);
- if (*p == '=')
- { /* property value is specified too */
- p++; /* skip over '=' */
- mustHaveValue = SecurityParseString(&p);
- if (!mustHaveValue)
- return FALSE;
- }
- }
-
- /* get operations and actions */
-
- invalid = FALSE;
- readAction = writeAction = destroyAction = SecurityDefaultAction;
- while ( (c = *p++) && !invalid)
- {
- switch (c)
- {
- case 'i': action = XaceIgnoreOperation; break;
- case 'a': action = XaceAllowOperation; break;
- case 'e': action = XaceErrorOperation; break;
-
- case 'r': readAction = action; break;
- case 'w': writeAction = action; break;
- case 'd': destroyAction = action; break;
-
- default :
- if (!SecurityIsWhitespace(c))
- invalid = TRUE;
- break;
- }
- }
- if (invalid)
- return FALSE;
-
- /* We've successfully collected all the information needed for this
- * property access rule. Now record it in a PropertyAccessRec.
- */
- size = sizeof(PropertyAccessRec);
-
- /* If there is a property value string, allocate space for it
- * right after the PropertyAccessRec.
- */
- if (mustHaveValue)
- size += strlen(mustHaveValue) + 1;
- pacl = (PropertyAccessPtr)Xalloc(size);
- if (!pacl)
- return FALSE;
-
- pacl->name = MakeAtom(propname, strlen(propname), TRUE);
- if (pacl->name == BAD_RESOURCE)
- {
- Xfree(pacl);
- return FALSE;
- }
- if (mustHaveProperty)
- {
- pacl->mustHaveProperty = MakeAtom(mustHaveProperty,
- strlen(mustHaveProperty), TRUE);
- if (pacl->mustHaveProperty == BAD_RESOURCE)
- {
- Xfree(pacl);
- return FALSE;
- }
- }
- else
- pacl->mustHaveProperty = 0;
-
- if (mustHaveValue)
- {
- pacl->mustHaveValue = (char *)(pacl + 1);
- strcpy(pacl->mustHaveValue, mustHaveValue);
+ XaceClientAccessRec *rec = calldata;
+ SecurityStateRec *subj, *obj;
+ Mask requested = rec->access_mode;
+ Mask allowed = SecurityClientMask;
+
+ subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
+ obj = dixLookupPrivate(&rec->target->devPrivates, stateKey);
+
+ if (SecurityDoCheck(subj, obj, requested, allowed) != Success) {
+ SecurityAudit("Security: denied client %d access to client %d on "
+ "request %s\n", rec->client->index, rec->target->index,
+ SecurityLookupRequestName(rec->client));
+ rec->status = BadAccess;
}
- else
- pacl->mustHaveValue = NULL;
-
- SecurityMaxPropertyName = max(SecurityMaxPropertyName, pacl->name);
-
- pacl->windowRestriction = windowRestriction;
- pacl->readAction = readAction;
- pacl->writeAction = writeAction;
- pacl->destroyAction = destroyAction;
-
- /* link the new rule into the list of rules in order of increasing
- * property name (atom) value to make searching easier
- */
+}
- for (prev = NULL, cur = PropertyAccessList;
- cur && cur->name <= pacl->name;
- prev = cur, cur = cur->next)
- ;
- if (!prev)
- {
- pacl->next = cur;
- PropertyAccessList = pacl;
- }
- else
- {
- prev->next = pacl;
- pacl->next = cur;
+static void
+SecurityProperty(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+ XacePropertyAccessRec *rec = calldata;
+ SecurityStateRec *subj, *obj;
+ ATOM name = (*rec->ppProp)->propertyName;
+ Mask requested = rec->access_mode;
+ Mask allowed = SecurityResourceMask | DixReadAccess;
+
+ subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
+ obj = dixLookupPrivate(&wClient(rec->pWin)->devPrivates, stateKey);
+
+ if (SecurityDoCheck(subj, obj, requested, allowed) != Success) {
+ SecurityAudit("Security: denied client %d access to property %s "
+ "(atom 0x%x) window 0x%x of client %d on request %s\n",
+ rec->client->index, NameForAtom(name), name,
+ rec->pWin->drawable.id, wClient(rec->pWin)->index,
+ SecurityLookupRequestName(rec->client));
+ rec->status = BadAccess;
}
- return TRUE;
-} /* SecurityParsePropertyAccessRule */
-
-static char **SecurityPolicyStrings = NULL;
-static int nSecurityPolicyStrings = 0;
+}
-static Bool
-SecurityParseSitePolicy(
- char *p)
+static void
+SecuritySend(CallbackListPtr *pcbl, pointer unused, pointer calldata)
{
- char *policyStr = SecurityParseString(&p);
- char *copyPolicyStr;
- char **newStrings;
-
- if (!policyStr)
- return FALSE;
-
- copyPolicyStr = (char *)Xalloc(strlen(policyStr) + 1);
- if (!copyPolicyStr)
- return TRUE;
- strcpy(copyPolicyStr, policyStr);
- newStrings = (char **)Xrealloc(SecurityPolicyStrings,
- sizeof (char *) * (nSecurityPolicyStrings + 1));
- if (!newStrings)
- {
- Xfree(copyPolicyStr);
- return TRUE;
- }
-
- SecurityPolicyStrings = newStrings;
- SecurityPolicyStrings[nSecurityPolicyStrings++] = copyPolicyStr;
+ XaceSendAccessRec *rec = calldata;
+ SecurityStateRec *subj, *obj;
- return TRUE;
+ if (rec->client) {
+ int i;
-} /* SecurityParseSitePolicy */
+ subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
+ obj = dixLookupPrivate(&wClient(rec->pWin)->devPrivates, stateKey);
+ if (SecurityDoCheck(subj, obj, DixSendAccess, 0) == Success)
+ return;
-char **
-SecurityGetSitePolicyStrings(n)
- int *n;
-{
- *n = nSecurityPolicyStrings;
- return SecurityPolicyStrings;
-} /* SecurityGetSitePolicyStrings */
-
-static void
-SecurityFreeSitePolicyStrings(void)
-{
- if (SecurityPolicyStrings)
- {
- assert(nSecurityPolicyStrings);
- while (nSecurityPolicyStrings--)
- {
- Xfree(SecurityPolicyStrings[nSecurityPolicyStrings]);
- }
- Xfree(SecurityPolicyStrings);
- SecurityPolicyStrings = NULL;
- nSecurityPolicyStrings = 0;
+ for (i = 0; i < rec->count; i++)
+ if (rec->events[i].u.u.type != UnmapNotify &&
+ rec->events[i].u.u.type != ConfigureRequest &&
+ rec->events[i].u.u.type != ClientMessage) {
+
+ SecurityAudit("Security: denied client %d from sending event "
+ "of type %s to window 0x%x of client %d\n",
+ rec->client->index, rec->pWin->drawable.id,
+ wClient(rec->pWin)->index,
+ LookupEventName(rec->events[i].u.u.type));
+ rec->status = BadAccess;
+ return;
+ }
}
-} /* SecurityFreeSitePolicyStrings */
-
+}
static void
-SecurityLoadPropertyAccessList(void)
+SecurityReceive(CallbackListPtr *pcbl, pointer unused, pointer calldata)
{
- FILE *f;
- int lineNumber = 0;
+ XaceReceiveAccessRec *rec = calldata;
+ SecurityStateRec *subj, *obj;
- SecurityMaxPropertyName = 0;
+ subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
+ obj = dixLookupPrivate(&wClient(rec->pWin)->devPrivates, stateKey);
- if (!SecurityPolicyFile)
+ if (SecurityDoCheck(subj, obj, DixReceiveAccess, 0) == Success)
return;
- f = Fopen(SecurityPolicyFile, "r");
- if (!f)
- {
- ErrorF("error opening security policy file %s\n",
- SecurityPolicyFile);
- return;
- }
-
- while (!feof(f))
- {
- char buf[200];
- Bool validLine;
- char *p;
-
- if (!(p = fgets(buf, sizeof(buf), f)))
- break;
- lineNumber++;
-
- /* if first line, check version number */
- if (lineNumber == 1)
- {
- char *v = SecurityParseString(&p);
- if (strcmp(v, SECURITY_POLICY_FILE_VERSION) != 0)
- {
- ErrorF("%s: invalid security policy file version, ignoring file\n",
- SecurityPolicyFile);
- break;
- }
- validLine = TRUE;
- }
- else
- {
- switch (SecurityParseKeyword(&p))
- {
- case SecurityKeywordComment:
- validLine = TRUE;
- break;
-
- case SecurityKeywordProperty:
- validLine = SecurityParsePropertyAccessRule(p);
- break;
-
- case SecurityKeywordSitePolicy:
- validLine = SecurityParseSitePolicy(p);
- break;
-
- default:
- validLine = (*p == '\0'); /* blank lines OK, others not */
- break;
- }
- }
-
- if (!validLine)
- ErrorF("Line %d of %s invalid, ignoring\n",
- lineNumber, SecurityPolicyFile);
- } /* end while more input */
-
-#ifdef PROPDEBUG
- {
- PropertyAccessPtr pacl;
- char *op = "aie";
- for (pacl = PropertyAccessList; pacl; pacl = pacl->next)
- {
- ErrorF("property %s ", NameForAtom(pacl->name));
- switch (pacl->windowRestriction)
- {
- case SecurityAnyWindow: ErrorF("any "); break;
- case SecurityRootWindow: ErrorF("root "); break;
- case SecurityWindowWithProperty:
- {
- ErrorF("%s ", NameForAtom(pacl->mustHaveProperty));
- if (pacl->mustHaveValue)
- ErrorF(" = \"%s\" ", pacl->mustHaveValue);
-
- }
- break;
- }
- ErrorF("%cr %cw %cd\n", op[pacl->readAction],
- op[pacl->writeAction], op[pacl->destroyAction]);
- }
- }
-#endif /* PROPDEBUG */
-
- Fclose(f);
-} /* SecurityLoadPropertyAccessList */
+ SecurityAudit("Security: denied client %d from receiving an event "
+ "sent to window 0x%x of client %d\n",
+ rec->client->index, rec->pWin->drawable.id,
+ wClient(rec->pWin)->index);
+ rec->status = BadAccess;
+}
+/* SecurityClientStateCallback
+ *
+ * Arguments:
+ * pcbl is &ClientStateCallback.
+ * nullata is NULL.
+ * calldata is a pointer to a NewClientInfoRec (include/dixstruct.h)
+ * which contains information about client state changes.
+ *
+ * Returns: nothing.
+ *
+ * Side Effects:
+ *
+ * If a new client is connecting, its authorization ID is copied to
+ * client->authID. If this is a generated authorization, its reference
+ * count is bumped, its timer is cancelled if it was running, and its
+ * trustlevel is copied to TRUSTLEVEL(client).
+ *
+ * If a client is disconnecting and the client was using a generated
+ * authorization, the authorization's reference count is decremented, and
+ * if it is now zero, the timer for this authorization is started.
+ */
-static Bool
-SecurityMatchString(
- char *ws,
- char *cs)
+static void
+SecurityClientState(CallbackListPtr *pcbl, pointer unused, pointer calldata)
{
- while (*ws && *cs)
- {
- if (*ws == '*')
- {
- Bool match = FALSE;
- ws++;
- while (!(match = SecurityMatchString(ws, cs)) && *cs)
- {
- cs++;
- }
- return match;
- }
- else if (*ws == *cs)
- {
- ws++;
- cs++;
- }
- else break;
- }
- return ( ( (*ws == '\0') || ((*ws == '*') && *(ws+1) == '\0') )
- && (*cs == '\0') );
-} /* SecurityMatchString */
-
-#ifdef PROPDEBUG
-#include <sys/types.h>
-#include <sys/stat.h>
-#endif
+ NewClientInfoRec *pci = calldata;
+ SecurityStateRec *state;
+ SecurityAuthorizationPtr pAuth;
+ int rc;
+ state = dixLookupPrivate(&pci->client->devPrivates, stateKey);
-CALLBACK(SecurityCheckPropertyAccess)
-{
- XacePropertyAccessRec *rec = (XacePropertyAccessRec*)calldata;
- ClientPtr client = rec->client;
- WindowPtr pWin = rec->pWin;
- ATOM propertyName = rec->propertyName;
- Mask access_mode = rec->access_mode;
- PropertyAccessPtr pacl;
- char action = SecurityDefaultAction;
-
- /* if client trusted or window untrusted, allow operation */
-
- if ( (TRUSTLEVEL(client) == XSecurityClientTrusted) ||
- (TRUSTLEVEL(wClient(pWin)) != XSecurityClientTrusted) )
- return;
+ switch (pci->client->clientState) {
+ case ClientStateInitial:
+ state->trustLevel = XSecurityClientTrusted;
+ state->authId = None;
+ state->haveState = TRUE;
+ break;
-#ifdef PROPDEBUG
- /* For testing, it's more convenient if the property rules file gets
- * reloaded whenever it changes, so we can rapidly try things without
- * having to reset the server.
- */
- {
- struct stat buf;
- static time_t lastmod = 0;
- int ret = stat(SecurityPolicyFile , &buf);
- if ( (ret == 0) && (buf.st_mtime > lastmod) )
- {
- ErrorF("reloading property rules\n");
- SecurityFreePropertyAccessList();
- SecurityLoadPropertyAccessList();
- lastmod = buf.st_mtime;
+ case ClientStateRunning:
+ state->authId = AuthorizationIDOfClient(pci->client);
+ rc = dixLookupResource((pointer *)&pAuth, state->authId,
+ SecurityAuthorizationResType, serverClient,
+ DixGetAttrAccess);
+ if (rc == Success) {
+ /* it is a generated authorization */
+ pAuth->refcnt++;
+ if (pAuth->refcnt == 1 && pAuth->timer)
+ TimerCancel(pAuth->timer);
+
+ state->trustLevel = pAuth->trustLevel;
}
- }
-#endif
-
- /* If the property atom is bigger than any atoms on the list,
- * we know we won't find it, so don't even bother looking.
- */
- if (propertyName <= SecurityMaxPropertyName)
- {
- /* untrusted client operating on trusted window; see if it's allowed */
-
- for (pacl = PropertyAccessList; pacl; pacl = pacl->next)
- {
- if (pacl->name < propertyName)
- continue;
- if (pacl->name > propertyName)
- break;
+ break;
- /* pacl->name == propertyName, so see if it applies to this window */
+ case ClientStateGone:
+ case ClientStateRetained:
+ rc = dixLookupResource((pointer *)&pAuth, state->authId,
+ SecurityAuthorizationResType, serverClient,
+ DixGetAttrAccess);
+ if (rc == Success) {
+ /* it is a generated authorization */
+ pAuth->refcnt--;
+ if (pAuth->refcnt == 0)
+ SecurityStartAuthorizationTimer(pAuth);
+ }
+ break;
- switch (pacl->windowRestriction)
- {
- case SecurityAnyWindow: /* always applies */
- break;
-
- case SecurityRootWindow:
- {
- /* if not a root window, this rule doesn't apply */
- if (pWin->parent)
- continue;
- }
- break;
-
- case SecurityWindowWithProperty:
- {
- PropertyPtr pProp = wUserProps (pWin);
- Bool match = FALSE;
- char *p;
- char *pEndData;
-
- while (pProp)
- {
- if (pProp->propertyName == pacl->mustHaveProperty)
- break;
- pProp = pProp->next;
- }
- if (!pProp)
- continue;
- if (!pacl->mustHaveValue)
- break;
- if (pProp->type != XA_STRING || pProp->format != 8)
- continue;
-
- p = pProp->data;
- pEndData = ((char *)pProp->data) + pProp->size;
- while (!match && p < pEndData)
- {
- if (SecurityMatchString(pacl->mustHaveValue, p))
- match = TRUE;
- else
- { /* skip to the next string */
- while (*p++ && p < pEndData)
- ;
- }
- }
- if (!match)
- continue;
- }
- break; /* end case SecurityWindowWithProperty */
- } /* end switch on windowRestriction */
-
- /* If we get here, the property access rule pacl applies.
- * If pacl doesn't apply, something above should have
- * executed a continue, which will skip the follwing code.
- */
- action = XaceAllowOperation;
- if (access_mode & DixReadAccess)
- action = max(action, pacl->readAction);
- if (access_mode & DixWriteAccess)
- action = max(action, pacl->writeAction);
- if (access_mode & DixDestroyAccess)
- action = max(action, pacl->destroyAction);
- break;
- } /* end for each pacl */
- } /* end if propertyName <= SecurityMaxPropertyName */
-
- if (XaceAllowOperation != action)
- { /* audit the access violation */
- int cid = CLIENT_ID(pWin->drawable.id);
- int reqtype = ((xReq *)client->requestBuffer)->reqType;
- char *actionstr = (XaceIgnoreOperation == action) ?
- "ignored" : "error";
- SecurityAudit("client %d attempted request %d with window 0x%x property %s (atom 0x%x) of client %d, %s\n",
- client->index, reqtype, pWin->drawable.id,
- NameForAtom(propertyName), propertyName, cid, actionstr);
+ default:
+ break;
}
- /* return codes increase with strictness */
- if (action > rec->rval)
- rec->rval = action;
-} /* SecurityCheckPropertyAccess */
-
+}
/* SecurityResetProc
*
@@ -1836,66 +1068,19 @@ static void
SecurityResetProc(
ExtensionEntry *extEntry)
{
- SecurityFreePropertyAccessList();
- SecurityFreeSitePolicyStrings();
-} /* SecurityResetProc */
-
-
-int
-XSecurityOptions(argc, argv, i)
- int argc;
- char **argv;
- int i;
-{
- if (strcmp(argv[i], "-sp") == 0)
- {
- if (i < argc)
- SecurityPolicyFile = argv[++i];
- return (i + 1);
- }
- return (i);
-} /* 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 the client private index */
- securityClientPrivateIndex = AllocateClientPrivateIndex();
- if (!AllocateClientPrivate(securityClientPrivateIndex,
- sizeof (SecurityClientStateRec)))
- FatalError("SecurityExtensionSetup: Can't allocate client private.\n");
-
- /* Allocate the extension private index */
- securityExtnsnPrivateIndex = AllocateExtensionPrivateIndex();
- if (!AllocateExtensionPrivate(securityExtnsnPrivateIndex, 0))
- FatalError("SecurityExtensionSetup: Can't allocate extnsn private.\n");
-
- /* 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);
-} /* SecurityExtensionSetup */
+ /* Unregister callbacks */
+ DeleteCallback(&ClientStateCallback, SecurityClientState, NULL);
+
+ XaceDeleteCallback(XACE_EXT_DISPATCH, SecurityExtension, NULL);
+ XaceDeleteCallback(XACE_RESOURCE_ACCESS, SecurityResource, NULL);
+ XaceDeleteCallback(XACE_DEVICE_ACCESS, SecurityDevice, NULL);
+ XaceDeleteCallback(XACE_PROPERTY_ACCESS, SecurityProperty, NULL);
+ XaceDeleteCallback(XACE_SEND_ACCESS, SecuritySend, NULL);
+ XaceDeleteCallback(XACE_RECEIVE_ACCESS, SecurityReceive, NULL);
+ XaceDeleteCallback(XACE_CLIENT_ACCESS, SecurityClient, NULL);
+ XaceDeleteCallback(XACE_EXT_ACCESS, SecurityExtension, NULL);
+ XaceDeleteCallback(XACE_SERVER_ACCESS, SecurityServer, NULL);
+}
/* SecurityExtensionInit
@@ -1912,6 +1097,7 @@ void
SecurityExtensionInit(INITARGS)
{
ExtensionEntry *extEntry;
+ int ret = TRUE;
SecurityAuthorizationResType =
CreateNewResourceType(SecurityDeleteAuthorization);
@@ -1923,10 +1109,30 @@ SecurityExtensionInit(INITARGS)
return;
RTEventClient |= RC_NEVERRETAIN;
+ RegisterResourceName(SecurityAuthorizationResType, "SecurityAuthorization");
+ RegisterResourceName(RTEventClient, "SecurityEventClient");
- if (!AddCallback(&ClientStateCallback, SecurityClientStateCallback, NULL))
- return;
+ /* Allocate the private storage */
+ if (!dixRequestPrivate(stateKey, sizeof(SecurityStateRec)))
+ FatalError("SecurityExtensionSetup: Can't allocate client private.\n");
+
+ /* Register callbacks */
+ ret &= AddCallback(&ClientStateCallback, SecurityClientState, NULL);
+
+ ret &= XaceRegisterCallback(XACE_EXT_DISPATCH, SecurityExtension, NULL);
+ ret &= XaceRegisterCallback(XACE_RESOURCE_ACCESS, SecurityResource, NULL);
+ ret &= XaceRegisterCallback(XACE_DEVICE_ACCESS, SecurityDevice, NULL);
+ ret &= XaceRegisterCallback(XACE_PROPERTY_ACCESS, SecurityProperty, NULL);
+ ret &= XaceRegisterCallback(XACE_SEND_ACCESS, SecuritySend, NULL);
+ ret &= XaceRegisterCallback(XACE_RECEIVE_ACCESS, SecurityReceive, NULL);
+ ret &= XaceRegisterCallback(XACE_CLIENT_ACCESS, SecurityClient, NULL);
+ ret &= XaceRegisterCallback(XACE_EXT_ACCESS, SecurityExtension, NULL);
+ ret &= XaceRegisterCallback(XACE_SERVER_ACCESS, SecurityServer, NULL);
+ if (!ret)
+ FatalError("SecurityExtensionSetup: Failed to register callbacks\n");
+
+ /* Add extension to server */
extEntry = AddExtension(SECURITY_EXTENSION_NAME,
XSecurityNumberEvents, XSecurityNumberErrors,
ProcSecurityDispatch, SProcSecurityDispatch,
@@ -1938,6 +1144,6 @@ SecurityExtensionInit(INITARGS)
EventSwapVector[SecurityEventBase + XSecurityAuthorizationRevoked] =
(EventSwapPtr)SwapSecurityAuthorizationRevokedEvent;
- SecurityLoadPropertyAccessList();
-
-} /* SecurityExtensionInit */
+ /* Label objects that were created before we could register ourself */
+ SecurityLabelInitial();
+}