📄 security.c
字号:
/* $XConsortium: security.c /main/13 1996/12/15 21:24:27 rws $ *//*Copyright (c) 1996 X Consortium, Inc.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OFMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OROTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OFOR OTHER DEALINGS IN THE SOFTWARE.Except as contained in this notice, the name of the X Consortium shallnot be used in advertising or otherwise to promote the sale, use orother dealings in this Software without prior written authorizationfrom the X Consortium.*//* $XFree86: xc/programs/Xserver/Xext/security.c,v 1.2 1997/01/27 06:57:17 dawes Exp $ */#include "dixstruct.h"#include "extnsionst.h"#include "windowstr.h"#include "inputstr.h"#include "gcstruct.h"#include "colormapst.h"#include "propertyst.h"#define _SECURITY_SERVER#include "securstr.h"#include <assert.h>#include <stdarg.h>#ifdef LBX#define _XLBX_SERVER_#include "XLbx.h"extern unsigned char LbxReqCode;#endif#ifdef XAPPGROUP#include "Xagsrv.h"#endif#include <stdio.h> /* for file reading operations */#include "Xatom.h" /* for XA_STRING */#ifndef DEFAULTPOLICYFILE# define DEFAULTPOLICYFILE NULL#endif#ifdef WIN32#include <X11/Xos.h>#undef index#endifstatic int SecurityErrorBase; /* first Security error number */static int SecurityEventBase; /* first Security event number */CallbackListPtr SecurityValidateGroupCallback = NULL; /* see security.h */RESTYPE SecurityAuthorizationResType; /* resource type for authorizations */static RESTYPE RTEventClient;/* Proc vectors for untrusted clients, swapped and unswapped versions. * These are the same as the normal proc vectors except that extensions * that haven't declared themselves secure will have ProcBadRequest plugged * in for their major opcode dispatcher. This prevents untrusted clients * from guessing extension major opcodes and using the extension even though * the extension can't be listed or queried. */int (*UntrustedProcVector[256])(#if NeedNestedPrototypes ClientPtr /*client*/#endif);int (*SwappedUntrustedProcVector[256])(#if NeedNestedPrototypes ClientPtr /*client*/#endif);extern int ProcBadRequest();/* 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. */voidSecurityAudit(char *format, ...){ va_list args; if (auditTrailLevel < SECURITY_AUDIT_LEVEL) return; AuditPrefix(format); va_start(args, format); VErrorF(format, args); va_end(args);} /* SecurityAudit */#define rClient(obj) (clients[CLIENT_ID((obj)->resource)])/* SecurityDeleteAuthorization * * Arguments: * value is the authorization to delete. * id is its resource ID. * * Returns: Success. * * Side Effects: * Frees everything associated with the authorization. */static intSecurityDeleteAuthorization(value, id) pointer value; XID id;{ SecurityAuthorizationPtr pAuth = (SecurityAuthorizationPtr)value; unsigned short name_len, data_len; char *name, *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); /* 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 */ 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); } /* kill all clients using this auth */ for (i = 1; i<currentMaxClients; i++) { if (clients[i] && (clients[i]->authId == pAuth->id)) CloseDownClient(clients[i]); } SecurityAudit("revoked authorization ID %d\n", pAuth->id); xfree(pAuth); return Success;} /* SecurityDeleteAuthorization *//* resource delete function for RTEventClient */static intSecurityDeleteAuthorizationEventClient(value, id) 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; } /*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 CARD32SecurityComputeAuthorizationTimeout(pAuth, seconds) 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 CARD32SecurityAuthorizationExpired(timer, time, pval) 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; }} /* 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 voidSecurityStartAuthorizationTimer(pAuth) 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 intProcSecurityQueryVersion(client) ClientPtr client;{ REQUEST(xSecurityQueryVersionReq); xSecurityQueryVersionReply rep; /* paranoia: this "can't happen" because this extension is hidden * from untrusted clients, but just in case... */ if (client->trustLevel != XSecurityClientTrusted) return BadRequest; 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) { register char n; swaps(&rep.sequenceNumber, n); swaps(&rep.majorVersion, n); swaps(&rep.minorVersion, n); } (void)WriteToClient(client, SIZEOF(xSecurityQueryVersionReply), (char *)&rep); return (client->noClientException);} /* ProcSecurityQueryVersion */static intSecurityEventSelectForAuthorization(pAuth, client, mask) 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;} /* SecurityEventSelectForAuthorization */static intProcSecurityGenerateAuthorization(client) 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 */ int status; /* return value from os functions */ 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 */ /* paranoia: this "can't happen" because this extension is hidden * from untrusted clients, but just in case... */ if (client->trustLevel != XSecurityClientTrusted) return BadRequest; /* check request length */ 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; /* 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, (pointer)&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 + ((stuff->nbytesAuthProto + (unsigned)3) >> 2); /* 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -