1099 lines
		
	
	
		
			35 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1099 lines
		
	
	
		
			35 KiB
		
	
	
	
		
			C
		
	
	
	
/*
 | 
						|
 | 
						|
Copyright 1996, 1998  The Open Group
 | 
						|
 | 
						|
Permission to use, copy, modify, distribute, and sell this software and its
 | 
						|
documentation for any purpose is hereby granted without fee, provided that
 | 
						|
the above copyright notice appear in all copies and that both that
 | 
						|
copyright notice and this permission notice appear in supporting
 | 
						|
documentation.
 | 
						|
 | 
						|
The above copyright notice and this permission notice shall be included in
 | 
						|
all copies or substantial portions of the Software.
 | 
						|
 | 
						|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
						|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
						|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 | 
						|
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 | 
						|
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
						|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
						|
 | 
						|
Except as contained in this notice, the name of The Open Group shall not be
 | 
						|
used in advertising or otherwise to promote the sale, use or other dealings
 | 
						|
in this Software without prior written authorization from The Open Group.
 | 
						|
 | 
						|
*/
 | 
						|
 | 
						|
#ifdef HAVE_DIX_CONFIG_H
 | 
						|
#include <dix-config.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#include <X11/extensions/securproto.h>
 | 
						|
#include <X11/Xfuncproto.h>
 | 
						|
 | 
						|
#include "dix/dix_priv.h"
 | 
						|
#include "dix/registry_priv.h"
 | 
						|
#include "miext/extinit_priv.h"
 | 
						|
#include "os/audit.h"
 | 
						|
#include "os/auth.h"
 | 
						|
 | 
						|
#include "scrnintstr.h"
 | 
						|
#include "inputstr.h"
 | 
						|
#include "windowstr.h"
 | 
						|
#include "propertyst.h"
 | 
						|
#include "colormapst.h"
 | 
						|
#include "privates.h"
 | 
						|
#include "xacestr.h"
 | 
						|
#include "securitysrv.h"
 | 
						|
#include "protocol-versions.h"
 | 
						|
 | 
						|
Bool noSecurityExtension = FALSE;
 | 
						|
 | 
						|
/* Extension stuff */
 | 
						|
static int SecurityErrorBase;   /* first Security error number */
 | 
						|
static int SecurityEventBase;   /* first Security event number */
 | 
						|
 | 
						|
RESTYPE SecurityAuthorizationResType;   /* resource type for authorizations */
 | 
						|
static RESTYPE RTEventClient;
 | 
						|
 | 
						|
static CallbackListPtr SecurityValidateGroupCallback = NULL;
 | 
						|
 | 
						|
/* Private state record */
 | 
						|
static DevPrivateKeyRec stateKeyRec;
 | 
						|
 | 
						|
#define stateKey (&stateKeyRec)
 | 
						|
 | 
						|
/* This is what we store as client security state */
 | 
						|
typedef struct {
 | 
						|
    unsigned int haveState  :1;
 | 
						|
    unsigned int live       :1;
 | 
						|
    unsigned int trustLevel :2;
 | 
						|
    XID authId;
 | 
						|
} SecurityStateRec;
 | 
						|
 | 
						|
/* The only extensions that untrusted clients have access to */
 | 
						|
static const char *SecurityTrustedExtensions[] = {
 | 
						|
    "XC-MISC",
 | 
						|
    "BIG-REQUESTS",
 | 
						|
    NULL
 | 
						|
};
 | 
						|
 | 
						|
/*
 | 
						|
 * Access modes that untrusted clients are allowed on trusted objects.
 | 
						|
 */
 | 
						|
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;
 | 
						|
 | 
						|
/* SecurityAudit
 | 
						|
 *
 | 
						|
 * Arguments:
 | 
						|
 *	format is the formatting string to be used to interpret the
 | 
						|
 *	  remaining arguments.
 | 
						|
 *
 | 
						|
 * Returns: nothing.
 | 
						|
 *
 | 
						|
 * Side Effects:
 | 
						|
 *	Writes the message to the log file if security logging is on.
 | 
						|
 */
 | 
						|
 | 
						|
static void
 | 
						|
_X_ATTRIBUTE_PRINTF(1, 2)
 | 
						|
SecurityAudit(const char *format, ...)
 | 
						|
{
 | 
						|
    va_list args;
 | 
						|
 | 
						|
    if (auditTrailLevel < SECURITY_AUDIT_LEVEL)
 | 
						|
        return;
 | 
						|
    va_start(args, format);
 | 
						|
    VAuditF(format, args);
 | 
						|
    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;
 | 
						|
    state->live = FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Looks up a request name
 | 
						|
 */
 | 
						|
static inline const char *
 | 
						|
SecurityLookupRequestName(ClientPtr client)
 | 
						|
{
 | 
						|
    return LookupRequestName(client->majorOp, client->minorOp);
 | 
						|
}
 | 
						|
 | 
						|
/* SecurityDeleteAuthorization
 | 
						|
 *
 | 
						|
 * Arguments:
 | 
						|
 *	value is the authorization to delete.
 | 
						|
 *	id is its resource ID.
 | 
						|
 *
 | 
						|
 * Returns: Success.
 | 
						|
 *
 | 
						|
 * Side Effects:
 | 
						|
 *	Frees everything associated with the authorization.
 | 
						|
 */
 | 
						|
 | 
						|
static int
 | 
						|
SecurityDeleteAuthorization(void *value, XID id)
 | 
						|
{
 | 
						|
    SecurityAuthorizationPtr pAuth = (SecurityAuthorizationPtr) value;
 | 
						|
    unsigned short name_len, data_len;
 | 
						|
    const char *name;
 | 
						|
    char *data;
 | 
						|
    int status;
 | 
						|
    int i;
 | 
						|
    OtherClientsPtr pEventClient;
 | 
						|
 | 
						|
    /* Remove the auth using the os layer auth manager */
 | 
						|
 | 
						|
    status = AuthorizationFromID(pAuth->id, &name_len, &name, &data_len, &data);
 | 
						|
    assert(status);
 | 
						|
    status = RemoveAuthorization(name_len, name, data_len, data);
 | 
						|
    assert(status);
 | 
						|
    (void) status;
 | 
						|
 | 
						|
    /* free the auth timer if there is one */
 | 
						|
 | 
						|
    if (pAuth->timer)
 | 
						|
        TimerFree(pAuth->timer);
 | 
						|
 | 
						|
    /* send revoke events */
 | 
						|
 | 
						|
    while ((pEventClient = pAuth->eventClients)) {
 | 
						|
        /* send revocation event event */
 | 
						|
        xSecurityAuthorizationRevokedEvent are = {
 | 
						|
            .type = SecurityEventBase + XSecurityAuthorizationRevoked,
 | 
						|
            .authId = pAuth->id
 | 
						|
        };
 | 
						|
        WriteEventsToClient(rClient(pEventClient), 1, (xEvent *) &are);
 | 
						|
        FreeResource(pEventClient->resource, X11_RESTYPE_NONE);
 | 
						|
    }
 | 
						|
 | 
						|
    /* kill all clients using this auth */
 | 
						|
 | 
						|
    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 %lu\n", (unsigned long)pAuth->id);
 | 
						|
    free(pAuth);
 | 
						|
    return Success;
 | 
						|
 | 
						|
}                               /* SecurityDeleteAuthorization */
 | 
						|
 | 
						|
/* resource delete function for RTEventClient */
 | 
						|
static int
 | 
						|
SecurityDeleteAuthorizationEventClient(void *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;
 | 
						|
            free(pEventClient);
 | 
						|
            return Success;
 | 
						|
        }
 | 
						|
        prev = pEventClient;
 | 
						|
    }
 | 
						|
     /*NOTREACHED*/ return -1;  /* make compiler happy */
 | 
						|
}                               /* SecurityDeleteAuthorizationEventClient */
 | 
						|
 | 
						|
/* SecurityComputeAuthorizationTimeout
 | 
						|
 *
 | 
						|
 * Arguments:
 | 
						|
 *	pAuth is the authorization for which we are computing the timeout
 | 
						|
 *	seconds is the number of seconds we want to wait
 | 
						|
 *
 | 
						|
 * Returns:
 | 
						|
 *	the number of milliseconds that the auth timer should be set to
 | 
						|
 *
 | 
						|
 * Side Effects:
 | 
						|
 *	Sets pAuth->secondsRemaining to any "overflow" amount of time
 | 
						|
 *	that didn't fit in 32 bits worth of milliseconds
 | 
						|
 */
 | 
						|
 | 
						|
static CARD32
 | 
						|
SecurityComputeAuthorizationTimeout(SecurityAuthorizationPtr pAuth,
 | 
						|
                                    unsigned int seconds)
 | 
						|
{
 | 
						|
    /* maxSecs is the number of full seconds that can be expressed in
 | 
						|
     * 32 bits worth of milliseconds
 | 
						|
     */
 | 
						|
    CARD32 maxSecs = (CARD32) (~0) / (CARD32) MILLI_PER_SECOND;
 | 
						|
 | 
						|
    if (seconds > maxSecs) {    /* only come here if we want to wait more than 49 days */
 | 
						|
        pAuth->secondsRemaining = seconds - maxSecs;
 | 
						|
        return maxSecs * MILLI_PER_SECOND;
 | 
						|
    }
 | 
						|
    else {                      /* by far the common case */
 | 
						|
        pAuth->secondsRemaining = 0;
 | 
						|
        return seconds * MILLI_PER_SECOND;
 | 
						|
    }
 | 
						|
}                               /* SecurityStartAuthorizationTimer */
 | 
						|
 | 
						|
/* SecurityAuthorizationExpired
 | 
						|
 *
 | 
						|
 * This function is passed as an argument to TimerSet and gets called from
 | 
						|
 * the timer manager in the os layer when its time is up.
 | 
						|
 *
 | 
						|
 * Arguments:
 | 
						|
 *	timer is the timer for this authorization.
 | 
						|
 *	time is the current time.
 | 
						|
 *	pval is the authorization whose time is up.
 | 
						|
 *
 | 
						|
 * Returns:
 | 
						|
 *	A new time delay in milliseconds if the timer should wait some
 | 
						|
 *	more, else zero.
 | 
						|
 *
 | 
						|
 * Side Effects:
 | 
						|
 *	Frees the authorization resource if the timeout period is really
 | 
						|
 *	over, otherwise recomputes pAuth->secondsRemaining.
 | 
						|
 */
 | 
						|
 | 
						|
static CARD32
 | 
						|
SecurityAuthorizationExpired(OsTimerPtr timer, CARD32 time, void *pval)
 | 
						|
{
 | 
						|
    SecurityAuthorizationPtr pAuth = (SecurityAuthorizationPtr) pval;
 | 
						|
 | 
						|
    assert(pAuth->timer == timer);
 | 
						|
 | 
						|
    if (pAuth->secondsRemaining) {
 | 
						|
        return SecurityComputeAuthorizationTimeout(pAuth,
 | 
						|
                                                   pAuth->secondsRemaining);
 | 
						|
    }
 | 
						|
    else {
 | 
						|
        FreeResource(pAuth->id, X11_RESTYPE_NONE);
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
}                               /* SecurityAuthorizationExpired */
 | 
						|
 | 
						|
/* SecurityStartAuthorizationTimer
 | 
						|
 *
 | 
						|
 * Arguments:
 | 
						|
 *	pAuth is the authorization whose timer should be started.
 | 
						|
 *
 | 
						|
 * Returns: nothing.
 | 
						|
 *
 | 
						|
 * Side Effects:
 | 
						|
 *	A timer is started, set to expire after the timeout period for
 | 
						|
 *	this authorization.  When it expires, the function
 | 
						|
 *	SecurityAuthorizationExpired will be called.
 | 
						|
 */
 | 
						|
 | 
						|
static void
 | 
						|
SecurityStartAuthorizationTimer(SecurityAuthorizationPtr pAuth)
 | 
						|
{
 | 
						|
    pAuth->timer = TimerSet(pAuth->timer, 0,
 | 
						|
                            SecurityComputeAuthorizationTimeout(pAuth,
 | 
						|
                                                                pAuth->timeout),
 | 
						|
                            SecurityAuthorizationExpired, pAuth);
 | 
						|
}                               /* SecurityStartAuthorizationTimer */
 | 
						|
 | 
						|
/* Proc functions all take a client argument, execute the request in
 | 
						|
 * client->requestBuffer, and return a protocol error status.
 | 
						|
 */
 | 
						|
 | 
						|
static int
 | 
						|
ProcSecurityQueryVersion(ClientPtr client)
 | 
						|
{
 | 
						|
    /* REQUEST(xSecurityQueryVersionReq); */
 | 
						|
    xSecurityQueryVersionReply rep = {
 | 
						|
        .type = X_Reply,
 | 
						|
        .sequenceNumber = client->sequence,
 | 
						|
        .length = 0,
 | 
						|
        .majorVersion = SERVER_SECURITY_MAJOR_VERSION,
 | 
						|
        .minorVersion = SERVER_SECURITY_MINOR_VERSION
 | 
						|
    };
 | 
						|
 | 
						|
    REQUEST_SIZE_MATCH(xSecurityQueryVersionReq);
 | 
						|
 | 
						|
    if (client->swapped) {
 | 
						|
        swaps(&rep.sequenceNumber);
 | 
						|
        swaps(&rep.majorVersion);
 | 
						|
        swaps(&rep.minorVersion);
 | 
						|
    }
 | 
						|
    WriteToClient(client, SIZEOF(xSecurityQueryVersionReply), &rep);
 | 
						|
    return Success;
 | 
						|
}                               /* ProcSecurityQueryVersion */
 | 
						|
 | 
						|
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, X11_RESTYPE_NONE);
 | 
						|
            else
 | 
						|
                pEventClient->mask = mask;
 | 
						|
            return Success;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    pEventClient = malloc(sizeof(OtherClients));
 | 
						|
    if (!pEventClient)
 | 
						|
        return BadAlloc;
 | 
						|
    pEventClient->mask = mask;
 | 
						|
    pEventClient->resource = FakeClientID(client->index);
 | 
						|
    pEventClient->next = pAuth->eventClients;
 | 
						|
    if (!AddResource(pEventClient->resource, RTEventClient, (void *) pAuth)) {
 | 
						|
        free(pEventClient);
 | 
						|
        return BadAlloc;
 | 
						|
    }
 | 
						|
    pAuth->eventClients = pEventClient;
 | 
						|
 | 
						|
    return Success;
 | 
						|
}                               /* SecurityEventSelectForAuthorization */
 | 
						|
 | 
						|
static int
 | 
						|
ProcSecurityGenerateAuthorization(ClientPtr client)
 | 
						|
{
 | 
						|
    REQUEST(xSecurityGenerateAuthorizationReq);
 | 
						|
    int len;                    /* request length in CARD32s */
 | 
						|
    Bool removeAuth = FALSE;    /* if bailout, call RemoveAuthorization? */
 | 
						|
    SecurityAuthorizationPtr pAuth = NULL;      /* auth we are creating */
 | 
						|
    int err;                    /* error to return from this function */
 | 
						|
    XID authId;                 /* authorization ID assigned by os layer */
 | 
						|
    xSecurityGenerateAuthorizationReply rep;    /* reply struct */
 | 
						|
    unsigned int trustLevel;    /* trust level of new auth */
 | 
						|
    XID group;                  /* group of new auth */
 | 
						|
    CARD32 timeout;             /* timeout of new auth */
 | 
						|
    CARD32 *values;             /* list of supplied attributes */
 | 
						|
    char *protoname;            /* auth proto name sent in request */
 | 
						|
    char *protodata;            /* auth proto data sent in request */
 | 
						|
    unsigned int authdata_len;  /* # bytes of generated auth data */
 | 
						|
    char *pAuthdata;            /* generated auth data */
 | 
						|
    Mask eventMask;             /* what events on this auth does client want */
 | 
						|
 | 
						|
    /* check request length */
 | 
						|
 | 
						|
    REQUEST_AT_LEAST_SIZE(xSecurityGenerateAuthorizationReq);
 | 
						|
    len = bytes_to_int32(SIZEOF(xSecurityGenerateAuthorizationReq));
 | 
						|
    len += bytes_to_int32(stuff->nbytesAuthProto);
 | 
						|
    len += bytes_to_int32(stuff->nbytesAuthData);
 | 
						|
    values = ((CARD32 *) stuff) + len;
 | 
						|
    len += Ones(stuff->valueMask);
 | 
						|
    if (client->req_len != len)
 | 
						|
        return BadLength;
 | 
						|
 | 
						|
    /* check valuemask */
 | 
						|
    if (stuff->valueMask & ~XSecurityAllAuthorizationAttributes) {
 | 
						|
        client->errorValue = stuff->valueMask;
 | 
						|
        return BadValue;
 | 
						|
    }
 | 
						|
 | 
						|
    /* check timeout */
 | 
						|
    timeout = 60;
 | 
						|
    if (stuff->valueMask & XSecurityTimeout) {
 | 
						|
        timeout = *values++;
 | 
						|
    }
 | 
						|
 | 
						|
    /* check trustLevel */
 | 
						|
    trustLevel = XSecurityClientUntrusted;
 | 
						|
    if (stuff->valueMask & XSecurityTrustLevel) {
 | 
						|
        trustLevel = *values++;
 | 
						|
        if (trustLevel != XSecurityClientTrusted &&
 | 
						|
            trustLevel != XSecurityClientUntrusted) {
 | 
						|
            client->errorValue = trustLevel;
 | 
						|
            return BadValue;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /* check group */
 | 
						|
    group = None;
 | 
						|
    if (stuff->valueMask & XSecurityGroup) {
 | 
						|
        group = *values++;
 | 
						|
        if (SecurityValidateGroupCallback) {
 | 
						|
            SecurityValidateGroupInfoRec vgi;
 | 
						|
 | 
						|
            vgi.group = group;
 | 
						|
            vgi.valid = FALSE;
 | 
						|
            CallCallbacks(&SecurityValidateGroupCallback, (void *) &vgi);
 | 
						|
 | 
						|
            /* if nobody said they recognized it, it's an error */
 | 
						|
 | 
						|
            if (!vgi.valid) {
 | 
						|
                client->errorValue = group;
 | 
						|
                return BadValue;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /* check event mask */
 | 
						|
    eventMask = 0;
 | 
						|
    if (stuff->valueMask & XSecurityEventMask) {
 | 
						|
        eventMask = *values++;
 | 
						|
        if (eventMask & ~XSecurityAllEventMasks) {
 | 
						|
            client->errorValue = eventMask;
 | 
						|
            return BadValue;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    protoname = (char *) &stuff[1];
 | 
						|
    protodata = protoname + bytes_to_int32(stuff->nbytesAuthProto);
 | 
						|
 | 
						|
    /* call os layer to generate the authorization */
 | 
						|
 | 
						|
    authId = GenerateAuthorization(stuff->nbytesAuthProto, protoname,
 | 
						|
                                   stuff->nbytesAuthData, protodata,
 | 
						|
                                   &authdata_len, &pAuthdata);
 | 
						|
    if ((XID) ~0L == authId) {
 | 
						|
        err = SecurityErrorBase + XSecurityBadAuthorizationProtocol;
 | 
						|
        goto bailout;
 | 
						|
    }
 | 
						|
 | 
						|
    /* now that we've added the auth, remember to remove it if we have to
 | 
						|
     * abort the request for some reason (like allocation failure)
 | 
						|
     */
 | 
						|
    removeAuth = TRUE;
 | 
						|
 | 
						|
    /* associate additional information with this auth ID */
 | 
						|
 | 
						|
    pAuth = malloc(sizeof(SecurityAuthorizationRec));
 | 
						|
    if (!pAuth) {
 | 
						|
        err = BadAlloc;
 | 
						|
        goto bailout;
 | 
						|
    }
 | 
						|
 | 
						|
    /* fill in the auth fields */
 | 
						|
 | 
						|
    pAuth->id = authId;
 | 
						|
    pAuth->timeout = timeout;
 | 
						|
    pAuth->group = group;
 | 
						|
    pAuth->trustLevel = trustLevel;
 | 
						|
    pAuth->refcnt = 0;          /* the auth was just created; nobody's using it yet */
 | 
						|
    pAuth->secondsRemaining = 0;
 | 
						|
    pAuth->timer = NULL;
 | 
						|
    pAuth->eventClients = NULL;
 | 
						|
 | 
						|
    /* handle event selection */
 | 
						|
    if (eventMask) {
 | 
						|
        err = SecurityEventSelectForAuthorization(pAuth, client, eventMask);
 | 
						|
        if (err != Success)
 | 
						|
            goto bailout;
 | 
						|
    }
 | 
						|
 | 
						|
    if (!AddResource(authId, SecurityAuthorizationResType, pAuth)) {
 | 
						|
        err = BadAlloc;
 | 
						|
        goto bailout;
 | 
						|
    }
 | 
						|
 | 
						|
    /* start the timer ticking */
 | 
						|
 | 
						|
    if (pAuth->timeout != 0)
 | 
						|
        SecurityStartAuthorizationTimer(pAuth);
 | 
						|
 | 
						|
    /* tell client the auth id and data */
 | 
						|
 | 
						|
    rep = (xSecurityGenerateAuthorizationReply) {
 | 
						|
        .type = X_Reply,
 | 
						|
        .sequenceNumber = client->sequence,
 | 
						|
        .length = bytes_to_int32(authdata_len),
 | 
						|
        .authId = authId,
 | 
						|
        .dataLength = authdata_len
 | 
						|
    };
 | 
						|
 | 
						|
    if (client->swapped) {
 | 
						|
        swapl(&rep.length);
 | 
						|
        swaps(&rep.sequenceNumber);
 | 
						|
        swapl(&rep.authId);
 | 
						|
        swaps(&rep.dataLength);
 | 
						|
    }
 | 
						|
 | 
						|
    WriteToClient(client, SIZEOF(xSecurityGenerateAuthorizationReply), &rep);
 | 
						|
    WriteToClient(client, authdata_len, pAuthdata);
 | 
						|
 | 
						|
    SecurityAudit
 | 
						|
        ("client %d generated authorization %lu trust %d timeout %lu group %lu events %lu\n",
 | 
						|
         client->index, (unsigned long)pAuth->id, pAuth->trustLevel, (unsigned long)pAuth->timeout,
 | 
						|
         (unsigned long)pAuth->group, (unsigned long)eventMask);
 | 
						|
 | 
						|
    /* the request succeeded; don't call RemoveAuthorization or free pAuth */
 | 
						|
    return Success;
 | 
						|
 | 
						|
 bailout:
 | 
						|
    if (removeAuth)
 | 
						|
        RemoveAuthorization(stuff->nbytesAuthProto, protoname,
 | 
						|
                            authdata_len, pAuthdata);
 | 
						|
    free(pAuth);
 | 
						|
    return err;
 | 
						|
 | 
						|
}                               /* ProcSecurityGenerateAuthorization */
 | 
						|
 | 
						|
static int
 | 
						|
ProcSecurityRevokeAuthorization(ClientPtr client)
 | 
						|
{
 | 
						|
    REQUEST(xSecurityRevokeAuthorizationReq);
 | 
						|
    SecurityAuthorizationPtr pAuth;
 | 
						|
    int rc;
 | 
						|
 | 
						|
    REQUEST_SIZE_MATCH(xSecurityRevokeAuthorizationReq);
 | 
						|
 | 
						|
    rc = dixLookupResourceByType((void **) &pAuth, stuff->authId,
 | 
						|
                                 SecurityAuthorizationResType, client,
 | 
						|
                                 DixDestroyAccess);
 | 
						|
    if (rc != Success)
 | 
						|
        return rc;
 | 
						|
 | 
						|
    FreeResource(stuff->authId, X11_RESTYPE_NONE);
 | 
						|
    return Success;
 | 
						|
}                               /* ProcSecurityRevokeAuthorization */
 | 
						|
 | 
						|
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;
 | 
						|
    }
 | 
						|
}                               /* ProcSecurityDispatch */
 | 
						|
 | 
						|
static int _X_COLD
 | 
						|
SProcSecurityQueryVersion(ClientPtr client)
 | 
						|
{
 | 
						|
    REQUEST(xSecurityQueryVersionReq);
 | 
						|
 | 
						|
    swaps(&stuff->length);
 | 
						|
    REQUEST_SIZE_MATCH(xSecurityQueryVersionReq);
 | 
						|
    swaps(&stuff->majorVersion);
 | 
						|
    swaps(&stuff->minorVersion);
 | 
						|
    return ProcSecurityQueryVersion(client);
 | 
						|
}                               /* SProcSecurityQueryVersion */
 | 
						|
 | 
						|
static int _X_COLD
 | 
						|
SProcSecurityGenerateAuthorization(ClientPtr client)
 | 
						|
{
 | 
						|
    REQUEST(xSecurityGenerateAuthorizationReq);
 | 
						|
    CARD32 *values;
 | 
						|
    unsigned long nvalues;
 | 
						|
    int values_offset;
 | 
						|
 | 
						|
    swaps(&stuff->length);
 | 
						|
    REQUEST_AT_LEAST_SIZE(xSecurityGenerateAuthorizationReq);
 | 
						|
    swaps(&stuff->nbytesAuthProto);
 | 
						|
    swaps(&stuff->nbytesAuthData);
 | 
						|
    swapl(&stuff->valueMask);
 | 
						|
    values_offset = bytes_to_int32(stuff->nbytesAuthProto) +
 | 
						|
        bytes_to_int32(stuff->nbytesAuthData);
 | 
						|
    if (values_offset >
 | 
						|
        stuff->length - bytes_to_int32(sz_xSecurityGenerateAuthorizationReq))
 | 
						|
        return BadLength;
 | 
						|
    values = (CARD32 *) (&stuff[1]) + values_offset;
 | 
						|
    nvalues = (((CARD32 *) stuff) + stuff->length) - values;
 | 
						|
    SwapLongs(values, nvalues);
 | 
						|
    return ProcSecurityGenerateAuthorization(client);
 | 
						|
}                               /* SProcSecurityGenerateAuthorization */
 | 
						|
 | 
						|
static int _X_COLD
 | 
						|
SProcSecurityRevokeAuthorization(ClientPtr client)
 | 
						|
{
 | 
						|
    REQUEST(xSecurityRevokeAuthorizationReq);
 | 
						|
 | 
						|
    swaps(&stuff->length);
 | 
						|
    REQUEST_SIZE_MATCH(xSecurityRevokeAuthorizationReq);
 | 
						|
    swapl(&stuff->authId);
 | 
						|
    return ProcSecurityRevokeAuthorization(client);
 | 
						|
}                               /* SProcSecurityRevokeAuthorization */
 | 
						|
 | 
						|
static int _X_COLD
 | 
						|
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;
 | 
						|
    }
 | 
						|
}                               /* SProcSecurityDispatch */
 | 
						|
 | 
						|
static void _X_COLD
 | 
						|
SwapSecurityAuthorizationRevokedEvent(xSecurityAuthorizationRevokedEvent * from,
 | 
						|
                                      xSecurityAuthorizationRevokedEvent * to)
 | 
						|
{
 | 
						|
    to->type = from->type;
 | 
						|
    to->detail = from->detail;
 | 
						|
    cpswaps(from->sequenceNumber, to->sequenceNumber);
 | 
						|
    cpswapl(from->authId, to->authId);
 | 
						|
}
 | 
						|
 | 
						|
/* SecurityCheckDeviceAccess
 | 
						|
 *
 | 
						|
 * Arguments:
 | 
						|
 *	client is the client attempting to access a device.
 | 
						|
 *	dev is the device being accessed.
 | 
						|
 *	fromRequest is TRUE if the device access is a direct result of
 | 
						|
 *	  the client executing some request and FALSE if it is a
 | 
						|
 *	  result of the server trying to send an event (e.g. KeymapNotify)
 | 
						|
 *	  to the client.
 | 
						|
 * Returns:
 | 
						|
 *	TRUE if the device access should be allowed, else FALSE.
 | 
						|
 *
 | 
						|
 * Side Effects:
 | 
						|
 *	An audit message is generated if access is denied.
 | 
						|
 */
 | 
						|
 | 
						|
static void
 | 
						|
SecurityDevice(CallbackListPtr *pcbl, void *unused, void *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)
 | 
						|
        /* 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;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/* SecurityResource
 | 
						|
 *
 | 
						|
 * This function gets plugged into client->CheckAccess and is called from
 | 
						|
 * SecurityLookupIDByType/Class to determine if the client can access the
 | 
						|
 * resource.
 | 
						|
 *
 | 
						|
 * Arguments:
 | 
						|
 *	client is the client doing the resource access.
 | 
						|
 *	id is the resource id.
 | 
						|
 *	rtype is its type or class.
 | 
						|
 *	access_mode represents the intended use of the resource; see
 | 
						|
 *	  resource.h.
 | 
						|
 *	res is a pointer to the resource structure for this resource.
 | 
						|
 *
 | 
						|
 * Returns:
 | 
						|
 *	If access is granted, the value of rval that was passed in, else FALSE.
 | 
						|
 *
 | 
						|
 * Side Effects:
 | 
						|
 *	Disallowed resource accesses are audited.
 | 
						|
 */
 | 
						|
 | 
						|
static void
 | 
						|
SecurityResource(CallbackListPtr *pcbl, void *unused, void *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);
 | 
						|
 | 
						|
    /* disable background None for untrusted windows */
 | 
						|
    if ((requested & DixCreateAccess) && (rec->rtype == X11_RESTYPE_WINDOW))
 | 
						|
        if (subj->haveState && subj->trustLevel != XSecurityClientTrusted)
 | 
						|
            ((WindowPtr) rec->res)->forcedBG = TRUE;
 | 
						|
 | 
						|
    /* additional permissions for specific resource types */
 | 
						|
    if (rec->rtype == X11_RESTYPE_WINDOW)
 | 
						|
        allowed |= SecurityWindowExtraMask;
 | 
						|
 | 
						|
    /* 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 == X11_RESTYPE_COLORMAP)
 | 
						|
            /* allow access to default colormaps */
 | 
						|
            allowed = requested;
 | 
						|
 | 
						|
        else
 | 
						|
            /* allow read access to other server-owned resources */
 | 
						|
            allowed |= DixReadAccess;
 | 
						|
    }
 | 
						|
 | 
						|
    if (clients[cid] != NULL) {
 | 
						|
        obj = dixLookupPrivate(&clients[cid]->devPrivates, stateKey);
 | 
						|
        if (SecurityDoCheck(subj, obj, requested, allowed) == Success)
 | 
						|
            return;
 | 
						|
    }
 | 
						|
 | 
						|
    SecurityAudit("Security: denied client %d access %lx to resource 0x%lx "
 | 
						|
                  "of client %d on request %s\n", rec->client->index,
 | 
						|
                  (unsigned long)requested, (unsigned long)rec->id, cid,
 | 
						|
                  SecurityLookupRequestName(rec->client));
 | 
						|
    rec->status = BadAccess;    /* deny access */
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
SecurityExtension(CallbackListPtr *pcbl, void *unused, void *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, void *unused, void *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, void *unused, void *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, void *unused, void *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%lx of client %d on request %s\n",
 | 
						|
                      rec->client->index, NameForAtom(name), name,
 | 
						|
                      (unsigned long)rec->pWin->drawable.id, wClient(rec->pWin)->index,
 | 
						|
                      SecurityLookupRequestName(rec->client));
 | 
						|
        rec->status = BadAccess;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
SecuritySend(CallbackListPtr *pcbl, void *unused, void *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%lx of client %d\n",
 | 
						|
                              rec->client->index,
 | 
						|
                              LookupEventName(rec->events[i].u.u.type),
 | 
						|
                              (unsigned long)rec->pWin->drawable.id,
 | 
						|
                              wClient(rec->pWin)->index);
 | 
						|
                rec->status = BadAccess;
 | 
						|
                return;
 | 
						|
            }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
SecurityReceive(CallbackListPtr *pcbl, void *unused, void *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%lx of client %d\n",
 | 
						|
                  rec->client->index, (unsigned long)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 void
 | 
						|
SecurityClientState(CallbackListPtr *pcbl, void *unused, void *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;
 | 
						|
        state->live = FALSE;
 | 
						|
        break;
 | 
						|
 | 
						|
    case ClientStateRunning:
 | 
						|
        state->authId = AuthorizationIDOfClient(pci->client);
 | 
						|
        rc = dixLookupResourceByType((void **) &pAuth, state->authId,
 | 
						|
                                     SecurityAuthorizationResType, serverClient,
 | 
						|
                                     DixGetAttrAccess);
 | 
						|
        if (rc == Success) {
 | 
						|
            /* it is a generated authorization */
 | 
						|
            pAuth->refcnt++;
 | 
						|
            state->live = TRUE;
 | 
						|
            if (pAuth->refcnt == 1 && pAuth->timer)
 | 
						|
                TimerCancel(pAuth->timer);
 | 
						|
 | 
						|
            state->trustLevel = pAuth->trustLevel;
 | 
						|
        }
 | 
						|
        break;
 | 
						|
 | 
						|
    case ClientStateGone:
 | 
						|
    case ClientStateRetained:
 | 
						|
        rc = dixLookupResourceByType((void **) &pAuth, state->authId,
 | 
						|
                                     SecurityAuthorizationResType, serverClient,
 | 
						|
                                     DixGetAttrAccess);
 | 
						|
        if (rc == Success && state->live) {
 | 
						|
            /* it is a generated authorization */
 | 
						|
            pAuth->refcnt--;
 | 
						|
            state->live = FALSE;
 | 
						|
            if (pAuth->refcnt == 0)
 | 
						|
                SecurityStartAuthorizationTimer(pAuth);
 | 
						|
        }
 | 
						|
        break;
 | 
						|
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/* SecurityResetProc
 | 
						|
 *
 | 
						|
 * Arguments:
 | 
						|
 *	extEntry is the extension information for the security extension.
 | 
						|
 *
 | 
						|
 * Returns: nothing.
 | 
						|
 *
 | 
						|
 * Side Effects:
 | 
						|
 *	Performs any cleanup needed by Security at server shutdown time.
 | 
						|
 */
 | 
						|
 | 
						|
static void
 | 
						|
SecurityResetProc(ExtensionEntry * extEntry)
 | 
						|
{
 | 
						|
    /* 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
 | 
						|
 *
 | 
						|
 * Arguments: none.
 | 
						|
 *
 | 
						|
 * Returns: nothing.
 | 
						|
 *
 | 
						|
 * Side Effects:
 | 
						|
 *	Enables the Security extension if possible.
 | 
						|
 */
 | 
						|
 | 
						|
void
 | 
						|
SecurityExtensionInit(void)
 | 
						|
{
 | 
						|
    ExtensionEntry *extEntry;
 | 
						|
    int ret = TRUE;
 | 
						|
 | 
						|
    SecurityAuthorizationResType =
 | 
						|
        CreateNewResourceType(SecurityDeleteAuthorization,
 | 
						|
                              "SecurityAuthorization");
 | 
						|
 | 
						|
    RTEventClient =
 | 
						|
        CreateNewResourceType(SecurityDeleteAuthorizationEventClient,
 | 
						|
                              "SecurityEventClient");
 | 
						|
 | 
						|
    if (!SecurityAuthorizationResType || !RTEventClient)
 | 
						|
        return;
 | 
						|
 | 
						|
    RTEventClient |= RC_NEVERRETAIN;
 | 
						|
 | 
						|
    /* Allocate the private storage */
 | 
						|
    if (!dixRegisterPrivateKey
 | 
						|
        (stateKey, PRIVATE_CLIENT, 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,
 | 
						|
                            SecurityResetProc, StandardMinorOpcode);
 | 
						|
 | 
						|
    SecurityErrorBase = extEntry->errorBase;
 | 
						|
    SecurityEventBase = extEntry->eventBase;
 | 
						|
 | 
						|
    EventSwapVector[SecurityEventBase + XSecurityAuthorizationRevoked] =
 | 
						|
        (EventSwapPtr) SwapSecurityAuthorizationRevokedEvent;
 | 
						|
 | 
						|
    SetResourceTypeErrorValue(SecurityAuthorizationResType,
 | 
						|
                              SecurityErrorBase + XSecurityBadAuthorization);
 | 
						|
 | 
						|
    /* Label objects that were created before we could register ourself */
 | 
						|
    SecurityLabelInitial();
 | 
						|
}
 |