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