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 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; /* 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 */ 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]) { 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; } /* SecurityDeleteAuthorization */
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); /* disable background None for untrusted windows */ if ((requested & DixCreateAccess) && (rec->rtype == RT_WINDOW)) if (subj->haveState && subj->trustLevel != XSecurityClientTrusted) ((WindowPtr)rec->res)->forcedBG = TRUE; /* additional permissions for specific resource types */ if (rec->rtype == RT_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 == RT_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 %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 */ }
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 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 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 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) /* 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; } }
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, RT_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 */
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, (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 + 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.type = X_Reply; rep.length = bytes_to_int32(authdata_len); 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); /* 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 */