Imported Upstream version 1.15.1
[deb_xorg-server.git] / Xext / security.c
CommitLineData
a09e091a
JB
1/*
2
3Copyright 1996, 1998 The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21Except as contained in this notice, the name of The Open Group shall not be
22used in advertising or otherwise to promote the sale, use or other dealings
23in this Software without prior written authorization from The Open Group.
24
25*/
26
27#ifdef HAVE_DIX_CONFIG_H
28#include <dix-config.h>
29#endif
30
31#include "scrnintstr.h"
32#include "inputstr.h"
33#include "windowstr.h"
34#include "propertyst.h"
35#include "colormapst.h"
36#include "privates.h"
37#include "registry.h"
38#include "xacestr.h"
39#include "securitysrv.h"
40#include <X11/extensions/securproto.h>
41#include "extinit.h"
42#include "protocol-versions.h"
43
44/* Extension stuff */
45static int SecurityErrorBase; /* first Security error number */
46static int SecurityEventBase; /* first Security event number */
47
48RESTYPE SecurityAuthorizationResType; /* resource type for authorizations */
49static RESTYPE RTEventClient;
50
51static CallbackListPtr SecurityValidateGroupCallback = NULL;
52
53/* Private state record */
54static DevPrivateKeyRec stateKeyRec;
55
56#define stateKey (&stateKeyRec)
57
58/* This is what we store as client security state */
59typedef struct {
60 unsigned int haveState :1;
61 unsigned int live :1;
62 unsigned int trustLevel :2;
63 XID authId;
64} SecurityStateRec;
65
66/* Extensions that untrusted clients shouldn't have access to */
67static const char *SecurityTrustedExtensions[] = {
68 "XC-MISC",
69 "BIG-REQUESTS",
70 "XpExtension",
71 NULL
72};
73
74/*
75 * Access modes that untrusted clients are allowed on trusted objects.
76 */
77static const Mask SecurityResourceMask =
78 DixGetAttrAccess | DixReceiveAccess | DixListPropAccess |
79 DixGetPropAccess | DixListAccess;
80static const Mask SecurityWindowExtraMask = DixRemoveAccess;
81static const Mask SecurityRootWindowExtraMask =
82 DixReceiveAccess | DixSendAccess | DixAddAccess | DixRemoveAccess;
83static const Mask SecurityDeviceMask =
84 DixGetAttrAccess | DixReceiveAccess | DixGetFocusAccess |
85 DixGrabAccess | DixSetAttrAccess | DixUseAccess;
86static const Mask SecurityServerMask = DixGetAttrAccess | DixGrabAccess;
87static const Mask SecurityClientMask = DixGetAttrAccess;
88
89/* SecurityAudit
90 *
91 * Arguments:
92 * format is the formatting string to be used to interpret the
93 * remaining arguments.
94 *
95 * Returns: nothing.
96 *
97 * Side Effects:
98 * Writes the message to the log file if security logging is on.
99 */
100
101static void
102_X_ATTRIBUTE_PRINTF(1, 2)
103SecurityAudit(const char *format, ...)
104{
105 va_list args;
106
107 if (auditTrailLevel < SECURITY_AUDIT_LEVEL)
108 return;
109 va_start(args, format);
110 VAuditF(format, args);
111 va_end(args);
112} /* SecurityAudit */
113
114/*
115 * Performs a Security permission check.
116 */
117static int
118SecurityDoCheck(SecurityStateRec * subj, SecurityStateRec * obj,
119 Mask requested, Mask allowed)
120{
121 if (!subj->haveState || !obj->haveState)
122 return Success;
123 if (subj->trustLevel == XSecurityClientTrusted)
124 return Success;
125 if (obj->trustLevel != XSecurityClientTrusted)
126 return Success;
127 if ((requested | allowed) == allowed)
128 return Success;
129
130 return BadAccess;
131}
132
133/*
134 * Labels initial server objects.
135 */
136static void
137SecurityLabelInitial(void)
138{
139 SecurityStateRec *state;
140
141 /* Do the serverClient */
142 state = dixLookupPrivate(&serverClient->devPrivates, stateKey);
143 state->trustLevel = XSecurityClientTrusted;
144 state->haveState = TRUE;
145 state->live = FALSE;
146}
147
148/*
149 * Looks up a request name
150 */
151static _X_INLINE const char *
152SecurityLookupRequestName(ClientPtr client)
153{
154 return LookupRequestName(client->majorOp, client->minorOp);
155}
156
157/* SecurityDeleteAuthorization
158 *
159 * Arguments:
160 * value is the authorization to delete.
161 * id is its resource ID.
162 *
163 * Returns: Success.
164 *
165 * Side Effects:
166 * Frees everything associated with the authorization.
167 */
168
169static int
170SecurityDeleteAuthorization(pointer value, XID id)
171{
172 SecurityAuthorizationPtr pAuth = (SecurityAuthorizationPtr) value;
173 unsigned short name_len, data_len;
174 const char *name;
175 char *data;
176 int status;
177 int i;
178 OtherClientsPtr pEventClient;
179
180 /* Remove the auth using the os layer auth manager */
181
182 status = AuthorizationFromID(pAuth->id, &name_len, &name, &data_len, &data);
183 assert(status);
184 status = RemoveAuthorization(name_len, name, data_len, data);
185 assert(status);
186 (void) status;
187
188 /* free the auth timer if there is one */
189
190 if (pAuth->timer)
191 TimerFree(pAuth->timer);
192
193 /* send revoke events */
194
195 while ((pEventClient = pAuth->eventClients)) {
196 /* send revocation event event */
197 xSecurityAuthorizationRevokedEvent are = {
198 .type = SecurityEventBase + XSecurityAuthorizationRevoked,
199 .authId = pAuth->id
200 };
201 WriteEventsToClient(rClient(pEventClient), 1, (xEvent *) &are);
202 FreeResource(pEventClient->resource, RT_NONE);
203 }
204
205 /* kill all clients using this auth */
206
207 for (i = 1; i < currentMaxClients; i++)
208 if (clients[i]) {
209 SecurityStateRec *state;
210
211 state = dixLookupPrivate(&clients[i]->devPrivates, stateKey);
212 if (state->haveState && state->authId == pAuth->id)
213 CloseDownClient(clients[i]);
214 }
215
216 SecurityAudit("revoked authorization ID %d\n", pAuth->id);
217 free(pAuth);
218 return Success;
219
220} /* SecurityDeleteAuthorization */
221
222/* resource delete function for RTEventClient */
223static int
224SecurityDeleteAuthorizationEventClient(pointer value, XID id)
225{
226 OtherClientsPtr pEventClient, prev = NULL;
227 SecurityAuthorizationPtr pAuth = (SecurityAuthorizationPtr) value;
228
229 for (pEventClient = pAuth->eventClients;
230 pEventClient; pEventClient = pEventClient->next) {
231 if (pEventClient->resource == id) {
232 if (prev)
233 prev->next = pEventClient->next;
234 else
235 pAuth->eventClients = pEventClient->next;
236 free(pEventClient);
237 return Success;
238 }
239 prev = pEventClient;
240 }
241 /*NOTREACHED*/ return -1; /* make compiler happy */
242} /* SecurityDeleteAuthorizationEventClient */
243
244/* SecurityComputeAuthorizationTimeout
245 *
246 * Arguments:
247 * pAuth is the authorization for which we are computing the timeout
248 * seconds is the number of seconds we want to wait
249 *
250 * Returns:
251 * the number of milliseconds that the auth timer should be set to
252 *
253 * Side Effects:
254 * Sets pAuth->secondsRemaining to any "overflow" amount of time
255 * that didn't fit in 32 bits worth of milliseconds
256 */
257
258static CARD32
259SecurityComputeAuthorizationTimeout(SecurityAuthorizationPtr pAuth,
260 unsigned int seconds)
261{
262 /* maxSecs is the number of full seconds that can be expressed in
263 * 32 bits worth of milliseconds
264 */
265 CARD32 maxSecs = (CARD32) (~0) / (CARD32) MILLI_PER_SECOND;
266
267 if (seconds > maxSecs) { /* only come here if we want to wait more than 49 days */
268 pAuth->secondsRemaining = seconds - maxSecs;
269 return maxSecs * MILLI_PER_SECOND;
270 }
271 else { /* by far the common case */
272 pAuth->secondsRemaining = 0;
273 return seconds * MILLI_PER_SECOND;
274 }
275} /* SecurityStartAuthorizationTimer */
276
277/* SecurityAuthorizationExpired
278 *
279 * This function is passed as an argument to TimerSet and gets called from
280 * the timer manager in the os layer when its time is up.
281 *
282 * Arguments:
283 * timer is the timer for this authorization.
284 * time is the current time.
285 * pval is the authorization whose time is up.
286 *
287 * Returns:
288 * A new time delay in milliseconds if the timer should wait some
289 * more, else zero.
290 *
291 * Side Effects:
292 * Frees the authorization resource if the timeout period is really
293 * over, otherwise recomputes pAuth->secondsRemaining.
294 */
295
296static CARD32
297SecurityAuthorizationExpired(OsTimerPtr timer, CARD32 time, pointer pval)
298{
299 SecurityAuthorizationPtr pAuth = (SecurityAuthorizationPtr) pval;
300
301 assert(pAuth->timer == timer);
302
303 if (pAuth->secondsRemaining) {
304 return SecurityComputeAuthorizationTimeout(pAuth,
305 pAuth->secondsRemaining);
306 }
307 else {
308 FreeResource(pAuth->id, RT_NONE);
309 return 0;
310 }
311} /* SecurityAuthorizationExpired */
312
313/* SecurityStartAuthorizationTimer
314 *
315 * Arguments:
316 * pAuth is the authorization whose timer should be started.
317 *
318 * Returns: nothing.
319 *
320 * Side Effects:
321 * A timer is started, set to expire after the timeout period for
322 * this authorization. When it expires, the function
323 * SecurityAuthorizationExpired will be called.
324 */
325
326static void
327SecurityStartAuthorizationTimer(SecurityAuthorizationPtr pAuth)
328{
329 pAuth->timer = TimerSet(pAuth->timer, 0,
330 SecurityComputeAuthorizationTimeout(pAuth,
331 pAuth->timeout),
332 SecurityAuthorizationExpired, pAuth);
333} /* SecurityStartAuthorizationTimer */
334
335/* Proc functions all take a client argument, execute the request in
336 * client->requestBuffer, and return a protocol error status.
337 */
338
339static int
340ProcSecurityQueryVersion(ClientPtr client)
341{
342 /* REQUEST(xSecurityQueryVersionReq); */
343 xSecurityQueryVersionReply rep = {
344 .type = X_Reply,
345 .sequenceNumber = client->sequence,
346 .length = 0,
347 .majorVersion = SERVER_SECURITY_MAJOR_VERSION,
348 .minorVersion = SERVER_SECURITY_MINOR_VERSION
349 };
350
351 REQUEST_SIZE_MATCH(xSecurityQueryVersionReq);
352
353 if (client->swapped) {
354 swaps(&rep.sequenceNumber);
355 swaps(&rep.majorVersion);
356 swaps(&rep.minorVersion);
357 }
358 WriteToClient(client, SIZEOF(xSecurityQueryVersionReply), &rep);
359 return Success;
360} /* ProcSecurityQueryVersion */
361
362static int
363SecurityEventSelectForAuthorization(SecurityAuthorizationPtr pAuth,
364 ClientPtr client, Mask mask)
365{
366 OtherClients *pEventClient;
367
368 for (pEventClient = pAuth->eventClients;
369 pEventClient; pEventClient = pEventClient->next) {
370 if (SameClient(pEventClient, client)) {
371 if (mask == 0)
372 FreeResource(pEventClient->resource, RT_NONE);
373 else
374 pEventClient->mask = mask;
375 return Success;
376 }
377 }
378
379 pEventClient = malloc(sizeof(OtherClients));
380 if (!pEventClient)
381 return BadAlloc;
382 pEventClient->mask = mask;
383 pEventClient->resource = FakeClientID(client->index);
384 pEventClient->next = pAuth->eventClients;
385 if (!AddResource(pEventClient->resource, RTEventClient, (pointer) pAuth)) {
386 free(pEventClient);
387 return BadAlloc;
388 }
389 pAuth->eventClients = pEventClient;
390
391 return Success;
392} /* SecurityEventSelectForAuthorization */
393
394static int
395ProcSecurityGenerateAuthorization(ClientPtr client)
396{
397 REQUEST(xSecurityGenerateAuthorizationReq);
398 int len; /* request length in CARD32s */
399 Bool removeAuth = FALSE; /* if bailout, call RemoveAuthorization? */
400 SecurityAuthorizationPtr pAuth = NULL; /* auth we are creating */
401 int err; /* error to return from this function */
402 XID authId; /* authorization ID assigned by os layer */
403 xSecurityGenerateAuthorizationReply rep; /* reply struct */
404 unsigned int trustLevel; /* trust level of new auth */
405 XID group; /* group of new auth */
406 CARD32 timeout; /* timeout of new auth */
407 CARD32 *values; /* list of supplied attributes */
408 char *protoname; /* auth proto name sent in request */
409 char *protodata; /* auth proto data sent in request */
410 unsigned int authdata_len; /* # bytes of generated auth data */
411 char *pAuthdata; /* generated auth data */
412 Mask eventMask; /* what events on this auth does client want */
413
414 /* check request length */
415
416 REQUEST_AT_LEAST_SIZE(xSecurityGenerateAuthorizationReq);
417 len = bytes_to_int32(SIZEOF(xSecurityGenerateAuthorizationReq));
418 len += bytes_to_int32(stuff->nbytesAuthProto);
419 len += bytes_to_int32(stuff->nbytesAuthData);
420 values = ((CARD32 *) stuff) + len;
421 len += Ones(stuff->valueMask);
422 if (client->req_len != len)
423 return BadLength;
424
425 /* check valuemask */
426 if (stuff->valueMask & ~XSecurityAllAuthorizationAttributes) {
427 client->errorValue = stuff->valueMask;
428 return BadValue;
429 }
430
431 /* check timeout */
432 timeout = 60;
433 if (stuff->valueMask & XSecurityTimeout) {
434 timeout = *values++;
435 }
436
437 /* check trustLevel */
438 trustLevel = XSecurityClientUntrusted;
439 if (stuff->valueMask & XSecurityTrustLevel) {
440 trustLevel = *values++;
441 if (trustLevel != XSecurityClientTrusted &&
442 trustLevel != XSecurityClientUntrusted) {
443 client->errorValue = trustLevel;
444 return BadValue;
445 }
446 }
447
448 /* check group */
449 group = None;
450 if (stuff->valueMask & XSecurityGroup) {
451 group = *values++;
452 if (SecurityValidateGroupCallback) {
453 SecurityValidateGroupInfoRec vgi;
454
455 vgi.group = group;
456 vgi.valid = FALSE;
457 CallCallbacks(&SecurityValidateGroupCallback, (pointer) &vgi);
458
459 /* if nobody said they recognized it, it's an error */
460
461 if (!vgi.valid) {
462 client->errorValue = group;
463 return BadValue;
464 }
465 }
466 }
467
468 /* check event mask */
469 eventMask = 0;
470 if (stuff->valueMask & XSecurityEventMask) {
471 eventMask = *values++;
472 if (eventMask & ~XSecurityAllEventMasks) {
473 client->errorValue = eventMask;
474 return BadValue;
475 }
476 }
477
478 protoname = (char *) &stuff[1];
479 protodata = protoname + bytes_to_int32(stuff->nbytesAuthProto);
480
481 /* call os layer to generate the authorization */
482
483 authId = GenerateAuthorization(stuff->nbytesAuthProto, protoname,
484 stuff->nbytesAuthData, protodata,
485 &authdata_len, &pAuthdata);
486 if ((XID) ~0L == authId) {
487 err = SecurityErrorBase + XSecurityBadAuthorizationProtocol;
488 goto bailout;
489 }
490
491 /* now that we've added the auth, remember to remove it if we have to
492 * abort the request for some reason (like allocation failure)
493 */
494 removeAuth = TRUE;
495
496 /* associate additional information with this auth ID */
497
498 pAuth = malloc(sizeof(SecurityAuthorizationRec));
499 if (!pAuth) {
500 err = BadAlloc;
501 goto bailout;
502 }
503
504 /* fill in the auth fields */
505
506 pAuth->id = authId;
507 pAuth->timeout = timeout;
508 pAuth->group = group;
509 pAuth->trustLevel = trustLevel;
510 pAuth->refcnt = 0; /* the auth was just created; nobody's using it yet */
511 pAuth->secondsRemaining = 0;
512 pAuth->timer = NULL;
513 pAuth->eventClients = NULL;
514
515 /* handle event selection */
516 if (eventMask) {
517 err = SecurityEventSelectForAuthorization(pAuth, client, eventMask);
518 if (err != Success)
519 goto bailout;
520 }
521
522 if (!AddResource(authId, SecurityAuthorizationResType, pAuth)) {
523 err = BadAlloc;
524 goto bailout;
525 }
526
527 /* start the timer ticking */
528
529 if (pAuth->timeout != 0)
530 SecurityStartAuthorizationTimer(pAuth);
531
532 /* tell client the auth id and data */
533
534 rep = (xSecurityGenerateAuthorizationReply) {
535 .type = X_Reply,
536 .sequenceNumber = client->sequence,
537 .length = bytes_to_int32(authdata_len),
538 .authId = authId,
539 .dataLength = authdata_len
540 };
541
542 if (client->swapped) {
543 swapl(&rep.length);
544 swaps(&rep.sequenceNumber);
545 swapl(&rep.authId);
546 swaps(&rep.dataLength);
547 }
548
549 WriteToClient(client, SIZEOF(xSecurityGenerateAuthorizationReply), &rep);
550 WriteToClient(client, authdata_len, pAuthdata);
551
552 SecurityAudit
553 ("client %d generated authorization %d trust %d timeout %d group %d events %d\n",
554 client->index, pAuth->id, pAuth->trustLevel, pAuth->timeout,
555 pAuth->group, eventMask);
556
557 /* the request succeeded; don't call RemoveAuthorization or free pAuth */
558 return Success;
559
560 bailout:
561 if (removeAuth)
562 RemoveAuthorization(stuff->nbytesAuthProto, protoname,
563 authdata_len, pAuthdata);
564 free(pAuth);
565 return err;
566
567} /* ProcSecurityGenerateAuthorization */
568
569static int
570ProcSecurityRevokeAuthorization(ClientPtr client)
571{
572 REQUEST(xSecurityRevokeAuthorizationReq);
573 SecurityAuthorizationPtr pAuth;
574 int rc;
575
576 REQUEST_SIZE_MATCH(xSecurityRevokeAuthorizationReq);
577
578 rc = dixLookupResourceByType((pointer *) &pAuth, stuff->authId,
579 SecurityAuthorizationResType, client,
580 DixDestroyAccess);
581 if (rc != Success)
582 return rc;
583
584 FreeResource(stuff->authId, RT_NONE);
585 return Success;
586} /* ProcSecurityRevokeAuthorization */
587
588static int
589ProcSecurityDispatch(ClientPtr client)
590{
591 REQUEST(xReq);
592
593 switch (stuff->data) {
594 case X_SecurityQueryVersion:
595 return ProcSecurityQueryVersion(client);
596 case X_SecurityGenerateAuthorization:
597 return ProcSecurityGenerateAuthorization(client);
598 case X_SecurityRevokeAuthorization:
599 return ProcSecurityRevokeAuthorization(client);
600 default:
601 return BadRequest;
602 }
603} /* ProcSecurityDispatch */
604
605static int
606SProcSecurityQueryVersion(ClientPtr client)
607{
608 REQUEST(xSecurityQueryVersionReq);
609
610 swaps(&stuff->length);
611 REQUEST_SIZE_MATCH(xSecurityQueryVersionReq);
612 swaps(&stuff->majorVersion);
613 swaps(&stuff->minorVersion);
614 return ProcSecurityQueryVersion(client);
615} /* SProcSecurityQueryVersion */
616
617static int
618SProcSecurityGenerateAuthorization(ClientPtr client)
619{
620 REQUEST(xSecurityGenerateAuthorizationReq);
621 CARD32 *values;
622 unsigned long nvalues;
623 int values_offset;
624
625 swaps(&stuff->length);
626 REQUEST_AT_LEAST_SIZE(xSecurityGenerateAuthorizationReq);
627 swaps(&stuff->nbytesAuthProto);
628 swaps(&stuff->nbytesAuthData);
629 swapl(&stuff->valueMask);
630 values_offset = bytes_to_int32(stuff->nbytesAuthProto) +
631 bytes_to_int32(stuff->nbytesAuthData);
632 if (values_offset >
633 stuff->length - bytes_to_int32(sz_xSecurityGenerateAuthorizationReq))
634 return BadLength;
635 values = (CARD32 *) (&stuff[1]) + values_offset;
636 nvalues = (((CARD32 *) stuff) + stuff->length) - values;
637 SwapLongs(values, nvalues);
638 return ProcSecurityGenerateAuthorization(client);
639} /* SProcSecurityGenerateAuthorization */
640
641static int
642SProcSecurityRevokeAuthorization(ClientPtr client)
643{
644 REQUEST(xSecurityRevokeAuthorizationReq);
645
646 swaps(&stuff->length);
647 REQUEST_SIZE_MATCH(xSecurityRevokeAuthorizationReq);
648 swapl(&stuff->authId);
649 return ProcSecurityRevokeAuthorization(client);
650} /* SProcSecurityRevokeAuthorization */
651
652static int
653SProcSecurityDispatch(ClientPtr client)
654{
655 REQUEST(xReq);
656
657 switch (stuff->data) {
658 case X_SecurityQueryVersion:
659 return SProcSecurityQueryVersion(client);
660 case X_SecurityGenerateAuthorization:
661 return SProcSecurityGenerateAuthorization(client);
662 case X_SecurityRevokeAuthorization:
663 return SProcSecurityRevokeAuthorization(client);
664 default:
665 return BadRequest;
666 }
667} /* SProcSecurityDispatch */
668
669static void
670SwapSecurityAuthorizationRevokedEvent(xSecurityAuthorizationRevokedEvent * from,
671 xSecurityAuthorizationRevokedEvent * to)
672{
673 to->type = from->type;
674 to->detail = from->detail;
675 cpswaps(from->sequenceNumber, to->sequenceNumber);
676 cpswapl(from->authId, to->authId);
677}
678
679/* SecurityCheckDeviceAccess
680 *
681 * Arguments:
682 * client is the client attempting to access a device.
683 * dev is the device being accessed.
684 * fromRequest is TRUE if the device access is a direct result of
685 * the client executing some request and FALSE if it is a
686 * result of the server trying to send an event (e.g. KeymapNotify)
687 * to the client.
688 * Returns:
689 * TRUE if the device access should be allowed, else FALSE.
690 *
691 * Side Effects:
692 * An audit message is generated if access is denied.
693 */
694
695static void
696SecurityDevice(CallbackListPtr *pcbl, pointer unused, pointer calldata)
697{
698 XaceDeviceAccessRec *rec = calldata;
699 SecurityStateRec *subj, *obj;
700 Mask requested = rec->access_mode;
701 Mask allowed = SecurityDeviceMask;
702
703 subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
704 obj = dixLookupPrivate(&serverClient->devPrivates, stateKey);
705
706 if (rec->dev != inputInfo.keyboard)
707 /* this extension only supports the core keyboard */
708 allowed = requested;
709
710 if (SecurityDoCheck(subj, obj, requested, allowed) != Success) {
711 SecurityAudit("Security denied client %d keyboard access on request "
712 "%s\n", rec->client->index,
713 SecurityLookupRequestName(rec->client));
714 rec->status = BadAccess;
715 }
716}
717
718/* SecurityResource
719 *
720 * This function gets plugged into client->CheckAccess and is called from
721 * SecurityLookupIDByType/Class to determine if the client can access the
722 * resource.
723 *
724 * Arguments:
725 * client is the client doing the resource access.
726 * id is the resource id.
727 * rtype is its type or class.
728 * access_mode represents the intended use of the resource; see
729 * resource.h.
730 * res is a pointer to the resource structure for this resource.
731 *
732 * Returns:
733 * If access is granted, the value of rval that was passed in, else FALSE.
734 *
735 * Side Effects:
736 * Disallowed resource accesses are audited.
737 */
738
739static void
740SecurityResource(CallbackListPtr *pcbl, pointer unused, pointer calldata)
741{
742 XaceResourceAccessRec *rec = calldata;
743 SecurityStateRec *subj, *obj;
744 int cid = CLIENT_ID(rec->id);
745 Mask requested = rec->access_mode;
746 Mask allowed = SecurityResourceMask;
747
748 subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
749
750 /* disable background None for untrusted windows */
751 if ((requested & DixCreateAccess) && (rec->rtype == RT_WINDOW))
752 if (subj->haveState && subj->trustLevel != XSecurityClientTrusted)
753 ((WindowPtr) rec->res)->forcedBG = TRUE;
754
755 /* additional permissions for specific resource types */
756 if (rec->rtype == RT_WINDOW)
757 allowed |= SecurityWindowExtraMask;
758
759 /* special checks for server-owned resources */
760 if (cid == 0) {
761 if (rec->rtype & RC_DRAWABLE)
762 /* additional operations allowed on root windows */
763 allowed |= SecurityRootWindowExtraMask;
764
765 else if (rec->rtype == RT_COLORMAP)
766 /* allow access to default colormaps */
767 allowed = requested;
768
769 else
770 /* allow read access to other server-owned resources */
771 allowed |= DixReadAccess;
772 }
773
774 if (clients[cid] != NULL) {
775 obj = dixLookupPrivate(&clients[cid]->devPrivates, stateKey);
776 if (SecurityDoCheck(subj, obj, requested, allowed) == Success)
777 return;
778 }
779
780 SecurityAudit("Security: denied client %d access %x to resource 0x%x "
781 "of client %d on request %s\n", rec->client->index,
782 requested, rec->id, cid,
783 SecurityLookupRequestName(rec->client));
784 rec->status = BadAccess; /* deny access */
785}
786
787static void
788SecurityExtension(CallbackListPtr *pcbl, pointer unused, pointer calldata)
789{
790 XaceExtAccessRec *rec = calldata;
791 SecurityStateRec *subj;
792 int i = 0;
793
794 subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
795
796 if (subj->haveState && subj->trustLevel == XSecurityClientTrusted)
797 return;
798
799 while (SecurityTrustedExtensions[i])
800 if (!strcmp(SecurityTrustedExtensions[i++], rec->ext->name))
801 return;
802
803 SecurityAudit("Security: denied client %d access to extension "
804 "%s on request %s\n",
805 rec->client->index, rec->ext->name,
806 SecurityLookupRequestName(rec->client));
807 rec->status = BadAccess;
808}
809
810static void
811SecurityServer(CallbackListPtr *pcbl, pointer unused, pointer calldata)
812{
813 XaceServerAccessRec *rec = calldata;
814 SecurityStateRec *subj, *obj;
815 Mask requested = rec->access_mode;
816 Mask allowed = SecurityServerMask;
817
818 subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
819 obj = dixLookupPrivate(&serverClient->devPrivates, stateKey);
820
821 if (SecurityDoCheck(subj, obj, requested, allowed) != Success) {
822 SecurityAudit("Security: denied client %d access to server "
823 "configuration request %s\n", rec->client->index,
824 SecurityLookupRequestName(rec->client));
825 rec->status = BadAccess;
826 }
827}
828
829static void
830SecurityClient(CallbackListPtr *pcbl, pointer unused, pointer calldata)
831{
832 XaceClientAccessRec *rec = calldata;
833 SecurityStateRec *subj, *obj;
834 Mask requested = rec->access_mode;
835 Mask allowed = SecurityClientMask;
836
837 subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
838 obj = dixLookupPrivate(&rec->target->devPrivates, stateKey);
839
840 if (SecurityDoCheck(subj, obj, requested, allowed) != Success) {
841 SecurityAudit("Security: denied client %d access to client %d on "
842 "request %s\n", rec->client->index, rec->target->index,
843 SecurityLookupRequestName(rec->client));
844 rec->status = BadAccess;
845 }
846}
847
848static void
849SecurityProperty(CallbackListPtr *pcbl, pointer unused, pointer calldata)
850{
851 XacePropertyAccessRec *rec = calldata;
852 SecurityStateRec *subj, *obj;
853 ATOM name = (*rec->ppProp)->propertyName;
854 Mask requested = rec->access_mode;
855 Mask allowed = SecurityResourceMask | DixReadAccess;
856
857 subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
858 obj = dixLookupPrivate(&wClient(rec->pWin)->devPrivates, stateKey);
859
860 if (SecurityDoCheck(subj, obj, requested, allowed) != Success) {
861 SecurityAudit("Security: denied client %d access to property %s "
862 "(atom 0x%x) window 0x%x of client %d on request %s\n",
863 rec->client->index, NameForAtom(name), name,
864 rec->pWin->drawable.id, wClient(rec->pWin)->index,
865 SecurityLookupRequestName(rec->client));
866 rec->status = BadAccess;
867 }
868}
869
870static void
871SecuritySend(CallbackListPtr *pcbl, pointer unused, pointer calldata)
872{
873 XaceSendAccessRec *rec = calldata;
874 SecurityStateRec *subj, *obj;
875
876 if (rec->client) {
877 int i;
878
879 subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
880 obj = dixLookupPrivate(&wClient(rec->pWin)->devPrivates, stateKey);
881
882 if (SecurityDoCheck(subj, obj, DixSendAccess, 0) == Success)
883 return;
884
885 for (i = 0; i < rec->count; i++)
886 if (rec->events[i].u.u.type != UnmapNotify &&
887 rec->events[i].u.u.type != ConfigureRequest &&
888 rec->events[i].u.u.type != ClientMessage) {
889
890 SecurityAudit("Security: denied client %d from sending event "
891 "of type %s to window 0x%x of client %d\n",
892 rec->client->index,
893 LookupEventName(rec->events[i].u.u.type),
894 rec->pWin->drawable.id,
895 wClient(rec->pWin)->index);
896 rec->status = BadAccess;
897 return;
898 }
899 }
900}
901
902static void
903SecurityReceive(CallbackListPtr *pcbl, pointer unused, pointer calldata)
904{
905 XaceReceiveAccessRec *rec = calldata;
906 SecurityStateRec *subj, *obj;
907
908 subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
909 obj = dixLookupPrivate(&wClient(rec->pWin)->devPrivates, stateKey);
910
911 if (SecurityDoCheck(subj, obj, DixReceiveAccess, 0) == Success)
912 return;
913
914 SecurityAudit("Security: denied client %d from receiving an event "
915 "sent to window 0x%x of client %d\n",
916 rec->client->index, rec->pWin->drawable.id,
917 wClient(rec->pWin)->index);
918 rec->status = BadAccess;
919}
920
921/* SecurityClientStateCallback
922 *
923 * Arguments:
924 * pcbl is &ClientStateCallback.
925 * nullata is NULL.
926 * calldata is a pointer to a NewClientInfoRec (include/dixstruct.h)
927 * which contains information about client state changes.
928 *
929 * Returns: nothing.
930 *
931 * Side Effects:
932 *
933 * If a new client is connecting, its authorization ID is copied to
934 * client->authID. If this is a generated authorization, its reference
935 * count is bumped, its timer is cancelled if it was running, and its
936 * trustlevel is copied to TRUSTLEVEL(client).
937 *
938 * If a client is disconnecting and the client was using a generated
939 * authorization, the authorization's reference count is decremented, and
940 * if it is now zero, the timer for this authorization is started.
941 */
942
943static void
944SecurityClientState(CallbackListPtr *pcbl, pointer unused, pointer calldata)
945{
946 NewClientInfoRec *pci = calldata;
947 SecurityStateRec *state;
948 SecurityAuthorizationPtr pAuth;
949 int rc;
950
951 state = dixLookupPrivate(&pci->client->devPrivates, stateKey);
952
953 switch (pci->client->clientState) {
954 case ClientStateInitial:
955 state->trustLevel = XSecurityClientTrusted;
956 state->authId = None;
957 state->haveState = TRUE;
958 state->live = FALSE;
959 break;
960
961 case ClientStateRunning:
962 state->authId = AuthorizationIDOfClient(pci->client);
963 rc = dixLookupResourceByType((pointer *) &pAuth, state->authId,
964 SecurityAuthorizationResType, serverClient,
965 DixGetAttrAccess);
966 if (rc == Success) {
967 /* it is a generated authorization */
968 pAuth->refcnt++;
969 state->live = TRUE;
970 if (pAuth->refcnt == 1 && pAuth->timer)
971 TimerCancel(pAuth->timer);
972
973 state->trustLevel = pAuth->trustLevel;
974 }
975 break;
976
977 case ClientStateGone:
978 case ClientStateRetained:
979 rc = dixLookupResourceByType((pointer *) &pAuth, state->authId,
980 SecurityAuthorizationResType, serverClient,
981 DixGetAttrAccess);
982 if (rc == Success && state->live) {
983 /* it is a generated authorization */
984 pAuth->refcnt--;
985 state->live = FALSE;
986 if (pAuth->refcnt == 0)
987 SecurityStartAuthorizationTimer(pAuth);
988 }
989 break;
990
991 default:
992 break;
993 }
994}
995
996/* SecurityResetProc
997 *
998 * Arguments:
999 * extEntry is the extension information for the security extension.
1000 *
1001 * Returns: nothing.
1002 *
1003 * Side Effects:
1004 * Performs any cleanup needed by Security at server shutdown time.
1005 */
1006
1007static void
1008SecurityResetProc(ExtensionEntry * extEntry)
1009{
1010 /* Unregister callbacks */
1011 DeleteCallback(&ClientStateCallback, SecurityClientState, NULL);
1012
1013 XaceDeleteCallback(XACE_EXT_DISPATCH, SecurityExtension, NULL);
1014 XaceDeleteCallback(XACE_RESOURCE_ACCESS, SecurityResource, NULL);
1015 XaceDeleteCallback(XACE_DEVICE_ACCESS, SecurityDevice, NULL);
1016 XaceDeleteCallback(XACE_PROPERTY_ACCESS, SecurityProperty, NULL);
1017 XaceDeleteCallback(XACE_SEND_ACCESS, SecuritySend, NULL);
1018 XaceDeleteCallback(XACE_RECEIVE_ACCESS, SecurityReceive, NULL);
1019 XaceDeleteCallback(XACE_CLIENT_ACCESS, SecurityClient, NULL);
1020 XaceDeleteCallback(XACE_EXT_ACCESS, SecurityExtension, NULL);
1021 XaceDeleteCallback(XACE_SERVER_ACCESS, SecurityServer, NULL);
1022}
1023
1024/* SecurityExtensionInit
1025 *
1026 * Arguments: none.
1027 *
1028 * Returns: nothing.
1029 *
1030 * Side Effects:
1031 * Enables the Security extension if possible.
1032 */
1033
1034void
1035SecurityExtensionInit(void)
1036{
1037 ExtensionEntry *extEntry;
1038 int ret = TRUE;
1039
1040 SecurityAuthorizationResType =
1041 CreateNewResourceType(SecurityDeleteAuthorization,
1042 "SecurityAuthorization");
1043
1044 RTEventClient =
1045 CreateNewResourceType(SecurityDeleteAuthorizationEventClient,
1046 "SecurityEventClient");
1047
1048 if (!SecurityAuthorizationResType || !RTEventClient)
1049 return;
1050
1051 RTEventClient |= RC_NEVERRETAIN;
1052
1053 /* Allocate the private storage */
1054 if (!dixRegisterPrivateKey
1055 (stateKey, PRIVATE_CLIENT, sizeof(SecurityStateRec)))
1056 FatalError("SecurityExtensionSetup: Can't allocate client private.\n");
1057
1058 /* Register callbacks */
1059 ret &= AddCallback(&ClientStateCallback, SecurityClientState, NULL);
1060
1061 ret &= XaceRegisterCallback(XACE_EXT_DISPATCH, SecurityExtension, NULL);
1062 ret &= XaceRegisterCallback(XACE_RESOURCE_ACCESS, SecurityResource, NULL);
1063 ret &= XaceRegisterCallback(XACE_DEVICE_ACCESS, SecurityDevice, NULL);
1064 ret &= XaceRegisterCallback(XACE_PROPERTY_ACCESS, SecurityProperty, NULL);
1065 ret &= XaceRegisterCallback(XACE_SEND_ACCESS, SecuritySend, NULL);
1066 ret &= XaceRegisterCallback(XACE_RECEIVE_ACCESS, SecurityReceive, NULL);
1067 ret &= XaceRegisterCallback(XACE_CLIENT_ACCESS, SecurityClient, NULL);
1068 ret &= XaceRegisterCallback(XACE_EXT_ACCESS, SecurityExtension, NULL);
1069 ret &= XaceRegisterCallback(XACE_SERVER_ACCESS, SecurityServer, NULL);
1070
1071 if (!ret)
1072 FatalError("SecurityExtensionSetup: Failed to register callbacks\n");
1073
1074 /* Add extension to server */
1075 extEntry = AddExtension(SECURITY_EXTENSION_NAME,
1076 XSecurityNumberEvents, XSecurityNumberErrors,
1077 ProcSecurityDispatch, SProcSecurityDispatch,
1078 SecurityResetProc, StandardMinorOpcode);
1079
1080 SecurityErrorBase = extEntry->errorBase;
1081 SecurityEventBase = extEntry->eventBase;
1082
1083 EventSwapVector[SecurityEventBase + XSecurityAuthorizationRevoked] =
1084 (EventSwapPtr) SwapSecurityAuthorizationRevokedEvent;
1085
1086 SetResourceTypeErrorValue(SecurityAuthorizationResType,
1087 SecurityErrorBase + XSecurityBadAuthorization);
1088
1089 /* Label objects that were created before we could register ourself */
1090 SecurityLabelInitial();
1091}