#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include "scrnintstr.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/securproto.h>
#include "modinit.h"
static int SecurityErrorBase;
static int SecurityEventBase;
RESTYPE SecurityAuthorizationResType;
static RESTYPE RTEventClient;
static CallbackListPtr SecurityValidateGroupCallback = NULL;
static int stateKeyIndex;
static DevPrivateKey stateKey = &stateKeyIndex;
typedef struct {
int haveState;
unsigned int trustLevel;
XID authId;
} SecurityStateRec;
static char *SecurityTrustedExtensions[] = {
"XC-MISC",
"BIG-REQUESTS",
"XpExtension",
NULL
};
static const Mask SecurityResourceMask =
DixGetAttrAccess | DixReceiveAccess | DixListPropAccess |
DixGetPropAccess | DixListAccess;
static const Mask SecurityWindowExtraMask = DixRemoveAccess;
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;
static void
SecurityAudit(char *format, ...)
{
va_list args;
if (auditTrailLevel < SECURITY_AUDIT_LEVEL)
return;
va_start(args, format);
VAuditF(format, args);
va_end(args);
}
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;
}
static void
SecurityLabelInitial(void)
{
SecurityStateRec *state;
state = dixLookupPrivate(&serverClient->devPrivates, stateKey);
state->trustLevel = XSecurityClientTrusted;
state->haveState = TRUE;
}
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)])
static int
SecurityDeleteAuthorization(
pointer value,
XID id)
{
SecurityAuthorizationPtr pAuth = (SecurityAuthorizationPtr)value;
unsigned short name_len, data_len;
char *name, *data;
int status;
int i;
OtherClientsPtr pEventClient;
status = AuthorizationFromID(pAuth->id, &name_len, &name,
&data_len, &data);
assert(status);
status = RemoveAuthorization(name_len, name, data_len, data);
assert(status);
(void)status;
if (pAuth->timer) TimerFree(pAuth->timer);
while ((pEventClient = pAuth->eventClients))
{
ClientPtr client = rClient(pEventClient);
if (!client->clientGone)
{
xSecurityAuthorizationRevokedEvent are;
are.type = SecurityEventBase + XSecurityAuthorizationRevoked;
are.sequenceNumber = client->sequence;
are.authId = pAuth->id;
WriteEventsToClient(client, 1, (xEvent *)&are);
}
FreeResource(pEventClient->resource, RT_NONE);
}
for (i = 1; i<currentMaxClients; 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);
return Success;
}
static int
SecurityDeleteAuthorizationEventClient(
pointer value,
XID id)
{
OtherClientsPtr pEventClient, prev = NULL;
SecurityAuthorizationPtr pAuth = (SecurityAuthorizationPtr)value;
for (pEventClient = pAuth->eventClients;
pEventClient;
pEventClient = pEventClient->next)
{
if (pEventClient->resource == id)
{
if (prev)
prev->next = pEventClient->next;
else
pAuth->eventClients = pEventClient->next;
xfree(pEventClient);
return(Success);
}
prev = pEventClient;
}
return -1;
}
static CARD32
SecurityComputeAuthorizationTimeout(
SecurityAuthorizationPtr pAuth,
unsigned int seconds)
{
CARD32 maxSecs = (CARD32)(~0) / (CARD32)MILLI_PER_SECOND;
if (seconds > maxSecs)
{
pAuth->secondsRemaining = seconds - maxSecs;
return maxSecs * MILLI_PER_SECOND;
}
else
{
pAuth->secondsRemaining = 0;
return seconds * MILLI_PER_SECOND;
}
}
static CARD32
SecurityAuthorizationExpired(
OsTimerPtr timer,
CARD32 time,
pointer pval)
{
SecurityAuthorizationPtr pAuth = (SecurityAuthorizationPtr)pval;
assert(pAuth->timer == timer);
if (pAuth->secondsRemaining)
{
return SecurityComputeAuthorizationTimeout(pAuth,
pAuth->secondsRemaining);
}
else
{
FreeResource(pAuth->id, RT_NONE);
return 0;
}
}
static void
SecurityStartAuthorizationTimer(
SecurityAuthorizationPtr pAuth)
{
pAuth->timer = TimerSet(pAuth->timer, 0,
SecurityComputeAuthorizationTimeout(pAuth, pAuth->timeout),
SecurityAuthorizationExpired, pAuth);
}
static int
ProcSecurityQueryVersion(
ClientPtr client)
{
xSecurityQueryVersionReply rep;
REQUEST_SIZE_MATCH(xSecurityQueryVersionReq);
rep.type = X_Reply;
rep.sequenceNumber = client->sequence;
rep.length = 0;
rep.majorVersion = SECURITY_MAJOR_VERSION;
rep.minorVersion = SECURITY_MINOR_VERSION;
if(client->swapped)
{
char n;
swaps(&rep.sequenceNumber, n);
swaps(&rep.majorVersion, n);
swaps(&rep.minorVersion, n);
}
(void)WriteToClient(client, SIZEOF(xSecurityQueryVersionReply),
(char *)&rep);
return (client->noClientException);
}
static int
SecurityEventSelectForAuthorization(
SecurityAuthorizationPtr pAuth,
ClientPtr client,
Mask mask)
{
OtherClients *pEventClient;
for (pEventClient = pAuth->eventClients;
pEventClient;
pEventClient = pEventClient->next)
{
if (SameClient(pEventClient, client))
{
if (mask == 0)
FreeResource(pEventClient->resource, RT_NONE);
else
pEventClient->mask = mask;
return Success;
}
}
pEventClient = (OtherClients *) xalloc(sizeof(OtherClients));
if (!pEventClient)
return BadAlloc;
pEventClient->mask = mask;
pEventClient->resource = FakeClientID(client->index);
pEventClient->next = pAuth->eventClients;
if (!AddResource(pEventClient->resource, RTEventClient,
(pointer)pAuth))
{
xfree(pEventClient);
return BadAlloc;
}
pAuth->eventClients = pEventClient;
return Success;
}
static int
ProcSecurityGenerateAuthorization(
ClientPtr client)
{
REQUEST(xSecurityGenerateAuthorizationReq);
int len;
Bool removeAuth = FALSE;
SecurityAuthorizationPtr pAuth = NULL;
int err;
XID authId;
xSecurityGenerateAuthorizationReply rep;
unsigned int trustLevel;
XID group;
CARD32 timeout;
CARD32 *values;
char *protoname;
char *protodata;
unsigned int authdata_len;
char *pAuthdata;
Mask eventMask;
REQUEST_AT_LEAST_SIZE(xSecurityGenerateAuthorizationReq);
len = SIZEOF(xSecurityGenerateAuthorizationReq) >> 2;
len += (stuff->nbytesAuthProto + (unsigned)3) >> 2;
len += (stuff->nbytesAuthData + (unsigned)3) >> 2;
values = ((CARD32 *)stuff) + len;
len += Ones(stuff->valueMask);
if (client->req_len != len)
return BadLength;
if (stuff->valueMask & ~XSecurityAllAuthorizationAttributes)
{
client->errorValue = stuff->valueMask;
return BadValue;
}
timeout = 60;
if (stuff->valueMask & XSecurityTimeout)
{
timeout = *values++;
}
trustLevel = XSecurityClientUntrusted;
if (stuff->valueMask & XSecurityTrustLevel)
{
trustLevel = *values++;
if (trustLevel != XSecurityClientTrusted &&
trustLevel != XSecurityClientUntrusted)
{
client->errorValue = trustLevel;
return BadValue;
}
}
group = None;
if (stuff->valueMask & XSecurityGroup)
{
group = *values++;
if (SecurityValidateGroupCallback)
{
SecurityValidateGroupInfoRec vgi;
vgi.group = group;
vgi.valid = FALSE;
CallCallbacks(&SecurityValidateGroupCallback, (pointer)&vgi);
if (!vgi.valid)
{
client->errorValue = group;
return BadValue;
}
}
}
eventMask = 0;
if (stuff->valueMask & XSecurityEventMask)
{
eventMask = *values++;
if (eventMask & ~XSecurityAllEventMasks)
{
client->errorValue = eventMask;
return BadValue;
}
}
protoname = (char *)&stuff[1];
protodata = protoname + ((stuff->nbytesAuthProto + (unsigned)3) >> 2);
authId = GenerateAuthorization(stuff->nbytesAuthProto, protoname,
stuff->nbytesAuthData, protodata,
&authdata_len, &pAuthdata);
if ((XID) ~0L == authId)
{
err = SecurityErrorBase + XSecurityBadAuthorizationProtocol;
goto bailout;
}
removeAuth = TRUE;
pAuth = (SecurityAuthorizationPtr)xalloc(sizeof(SecurityAuthorizationRec));
if (!pAuth)
{
err = BadAlloc;
goto bailout;
}
pAuth->id = authId;
pAuth->timeout = timeout;
pAuth->group = group;
pAuth->trustLevel = trustLevel;
pAuth->refcnt = 0;
pAuth->secondsRemaining = 0;
pAuth->timer = NULL;
pAuth->eventClients = NULL;
if (eventMask)
{
err = SecurityEventSelectForAuthorization(pAuth, client, eventMask);
if (err != Success)
goto bailout;
}
if (!AddResource(authId, SecurityAuthorizationResType, pAuth))
{
err = BadAlloc;
goto bailout;
}
if (pAuth->timeout != 0)
SecurityStartAuthorizationTimer(pAuth);
rep.type = X_Reply;
rep.length = (authdata_len + 3) >> 2;
rep.sequenceNumber = client->sequence;
rep.authId = authId;
rep.dataLength = authdata_len;
if (client->swapped)
{
char n;
swapl(&rep.length, n);
swaps(&rep.sequenceNumber, n);
swapl(&rep.authId, n);
swaps(&rep.dataLength, n);
}
WriteToClient(client, SIZEOF(xSecurityGenerateAuthorizationReply),
(char *)&rep);
WriteToClient(client, authdata_len, pAuthdata);
SecurityAudit("client %d generated authorization %d trust %d timeout %d group %d events %d\n",
client->index, pAuth->id, pAuth->trustLevel, pAuth->timeout,
pAuth->group, eventMask);
removeAuth = FALSE;
pAuth = NULL;
err = client->noClientException;
bailout:
if (removeAuth)
RemoveAuthorization(stuff->nbytesAuthProto, protoname,
authdata_len, pAuthdata);
if (pAuth) xfree(pAuth);
return err;
}
static int
ProcSecurityRevokeAuthorization(
ClientPtr client)
{
REQUEST(xSecurityRevokeAuthorizationReq);
SecurityAuthorizationPtr pAuth;
REQUEST_SIZE_MATCH(xSecurityRevokeAuthorizationReq);
pAuth = (SecurityAuthorizationPtr)SecurityLookupIDByType(client,
stuff->authId, SecurityAuthorizationResType, DixDestroyAccess);
if (!pAuth)
return SecurityErrorBase + XSecurityBadAuthorization;
FreeResource(stuff->authId, RT_NONE);
return Success;
}
static int
ProcSecurityDispatch(
ClientPtr client)
{
REQUEST(xReq);
switch (stuff->data)
{
case X_SecurityQueryVersion:
return ProcSecurityQueryVersion(client);
case X_SecurityGenerateAuthorization:
return ProcSecurityGenerateAuthorization(client);
case X_SecurityRevokeAuthorization:
return ProcSecurityRevokeAuthorization(client);
default:
return BadRequest;
}
}
static int
SProcSecurityQueryVersion(
ClientPtr client)
{
REQUEST(xSecurityQueryVersionReq);
char n;
swaps(&stuff->length, n);
REQUEST_SIZE_MATCH(xSecurityQueryVersionReq);
swaps(&stuff->majorVersion, n);
swaps(&stuff->minorVersion,n);
return ProcSecurityQueryVersion(client);
}
static int
SProcSecurityGenerateAuthorization(
ClientPtr client)
{
REQUEST(xSecurityGenerateAuthorizationReq);
char n;
CARD32 *values;
unsigned long nvalues;
int values_offset;
swaps(&stuff->length, n);
REQUEST_AT_LEAST_SIZE(xSecurityGenerateAuthorizationReq);
swaps(&stuff->nbytesAuthProto, n);
swaps(&stuff->nbytesAuthData, n);
swapl(&stuff->valueMask, n);
values_offset = ((stuff->nbytesAuthProto + (unsigned)3) >> 2) +
((stuff->nbytesAuthData + (unsigned)3) >> 2);
if (values_offset >
stuff->length - (sz_xSecurityGenerateAuthorizationReq >> 2))
return BadLength;
values = (CARD32 *)(&stuff[1]) + values_offset;
nvalues = (((CARD32 *)stuff) + stuff->length) - values;
SwapLongs(values, nvalues);
return ProcSecurityGenerateAuthorization(client);
}
static int
SProcSecurityRevokeAuthorization(
ClientPtr client)
{
REQUEST(xSecurityRevokeAuthorizationReq);
char n;
swaps(&stuff->length, n);
REQUEST_SIZE_MATCH(xSecurityRevokeAuthorizationReq);
swapl(&stuff->authId, n);
return ProcSecurityRevokeAuthorization(client);
}
static int
SProcSecurityDispatch(
ClientPtr client)
{
REQUEST(xReq);
switch (stuff->data)
{
case X_SecurityQueryVersion:
return SProcSecurityQueryVersion(client);
case X_SecurityGenerateAuthorization:
return SProcSecurityGenerateAuthorization(client);
case X_SecurityRevokeAuthorization:
return SProcSecurityRevokeAuthorization(client);
default:
return BadRequest;
}
}
static void
SwapSecurityAuthorizationRevokedEvent(
xSecurityAuthorizationRevokedEvent *from,
xSecurityAuthorizationRevokedEvent *to)
{
to->type = from->type;
to->detail = from->detail;
cpswaps(from->sequenceNumber, to->sequenceNumber);
cpswapl(from->authId, to->authId);
}
static void
SecurityDevice(CallbackListPtr *pcbl, pointer unused, pointer calldata)
{
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)
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;
}
}
static void
SecurityResource(CallbackListPtr *pcbl, pointer unused, pointer calldata)
{
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);
if ((requested & DixCreateAccess) && (rec->rtype == RT_WINDOW))
if (subj->haveState && subj->trustLevel != XSecurityClientTrusted)
((WindowPtr)rec->res)->forcedBG = TRUE;
if (rec->rtype == RT_WINDOW)
allowed |= SecurityWindowExtraMask;
if (cid == 0) {
if (rec->rtype & RC_DRAWABLE)
allowed |= SecurityRootWindowExtraMask;
else if (rec->rtype == RT_COLORMAP)
allowed = requested;
else
allowed |= DixReadAccess;
}
if (SecurityDoCheck(subj, obj, requested, allowed) == Success)
return;
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;
}
static void
SecurityExtension(CallbackListPtr *pcbl, pointer unused, pointer calldata)
{
XaceExtAccessRec *rec = calldata;
SecurityStateRec *subj;
int i = 0;
subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
if (subj->haveState && subj->trustLevel == XSecurityClientTrusted)
return;
while (SecurityTrustedExtensions[i])
if (!strcmp(SecurityTrustedExtensions[i++], rec->ext->name))
return;
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;
}
static void
SecurityServer(CallbackListPtr *pcbl, pointer unused, pointer calldata)
{
XaceServerAccessRec *rec = calldata;
SecurityStateRec *subj, *obj;
Mask requested = rec->access_mode;
Mask allowed = SecurityServerMask;
subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
obj = dixLookupPrivate(&serverClient->devPrivates, stateKey);
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;
}
}
static void
SecurityClient(CallbackListPtr *pcbl, pointer unused, pointer calldata)
{
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;
}
}
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;
}
}
static void
SecuritySend(CallbackListPtr *pcbl, pointer unused, pointer calldata)
{
XaceSendAccessRec *rec = calldata;
SecurityStateRec *subj, *obj;
if (rec->client) {
int i;
subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
obj = dixLookupPrivate(&wClient(rec->pWin)->devPrivates, stateKey);
if (SecurityDoCheck(subj, obj, DixSendAccess, 0) == Success)
return;
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,
LookupEventName(rec->events[i].u.u.type),
rec->pWin->drawable.id,
wClient(rec->pWin)->index);
rec->status = BadAccess;
return;
}
}
}
static void
SecurityReceive(CallbackListPtr *pcbl, pointer unused, pointer calldata)
{
XaceReceiveAccessRec *rec = calldata;
SecurityStateRec *subj, *obj;
subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
obj = dixLookupPrivate(&wClient(rec->pWin)->devPrivates, stateKey);
if (SecurityDoCheck(subj, obj, DixReceiveAccess, 0) == Success)
return;
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;
}
static void
SecurityClientState(CallbackListPtr *pcbl, pointer unused, pointer calldata)
{
NewClientInfoRec *pci = calldata;
SecurityStateRec *state;
SecurityAuthorizationPtr pAuth;
int rc;
state = dixLookupPrivate(&pci->client->devPrivates, stateKey);
switch (pci->client->clientState) {
case ClientStateInitial:
state->trustLevel = XSecurityClientTrusted;
state->authId = None;
state->haveState = TRUE;
break;
case ClientStateRunning:
state->authId = AuthorizationIDOfClient(pci->client);
rc = dixLookupResourceByType((pointer *)&pAuth, state->authId,
SecurityAuthorizationResType, serverClient,
DixGetAttrAccess);
if (rc == Success) {
pAuth->refcnt++;
if (pAuth->refcnt == 1 && pAuth->timer)
TimerCancel(pAuth->timer);
state->trustLevel = pAuth->trustLevel;
}
break;
case ClientStateGone:
case ClientStateRetained:
rc = dixLookupResourceByType((pointer *)&pAuth, state->authId,
SecurityAuthorizationResType, serverClient,
DixGetAttrAccess);
if (rc == Success) {
pAuth->refcnt--;
if (pAuth->refcnt == 0)
SecurityStartAuthorizationTimer(pAuth);
}
break;
default:
break;
}
}
static void
SecurityResetProc(
ExtensionEntry *extEntry)
{
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);
}
void
SecurityExtensionInit(INITARGS)
{
ExtensionEntry *extEntry;
int ret = TRUE;
SecurityAuthorizationResType =
CreateNewResourceType(SecurityDeleteAuthorization);
RTEventClient = CreateNewResourceType(
SecurityDeleteAuthorizationEventClient);
if (!SecurityAuthorizationResType || !RTEventClient)
return;
RTEventClient |= RC_NEVERRETAIN;
RegisterResourceName(SecurityAuthorizationResType, "SecurityAuthorization");
RegisterResourceName(RTEventClient, "SecurityEventClient");
if (!dixRequestPrivate(stateKey, sizeof(SecurityStateRec)))
FatalError("SecurityExtensionSetup: Can't allocate client private.\n");
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");
extEntry = AddExtension(SECURITY_EXTENSION_NAME,
XSecurityNumberEvents, XSecurityNumberErrors,
ProcSecurityDispatch, SProcSecurityDispatch,
SecurityResetProc, StandardMinorOpcode);
SecurityErrorBase = extEntry->errorBase;
SecurityEventBase = extEntry->eventBase;
EventSwapVector[SecurityEventBase + XSecurityAuthorizationRevoked] =
(EventSwapPtr)SwapSecurityAuthorizationRevokedEvent;
SecurityLabelInitial();
}