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