3 Copyright 1996, 1998 The Open Group
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
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
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.
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.
27 #ifdef HAVE_DIX_CONFIG_H
28 #include <dix-config.h>
31 #include "scrnintstr.h"
33 #include "windowstr.h"
34 #include "propertyst.h"
35 #include "colormapst.h"
39 #include "securitysrv.h"
40 #include <X11/extensions/securproto.h>
42 #include "protocol-versions.h"
45 static int SecurityErrorBase
; /* first Security error number */
46 static int SecurityEventBase
; /* first Security event number */
48 RESTYPE SecurityAuthorizationResType
; /* resource type for authorizations */
49 static RESTYPE RTEventClient
;
51 static CallbackListPtr SecurityValidateGroupCallback
= NULL
;
53 /* Private state record */
54 static DevPrivateKeyRec stateKeyRec
;
56 #define stateKey (&stateKeyRec)
58 /* This is what we store as client security state */
60 unsigned int haveState
:1;
62 unsigned int trustLevel
:2;
66 /* Extensions that untrusted clients shouldn't have access to */
67 static const char *SecurityTrustedExtensions
[] = {
75 * Access modes that untrusted clients are allowed on trusted objects.
77 static const Mask SecurityResourceMask
=
78 DixGetAttrAccess
| DixReceiveAccess
| DixListPropAccess
|
79 DixGetPropAccess
| DixListAccess
;
80 static const Mask SecurityWindowExtraMask
= DixRemoveAccess
;
81 static const Mask SecurityRootWindowExtraMask
=
82 DixReceiveAccess
| DixSendAccess
| DixAddAccess
| DixRemoveAccess
;
83 static const Mask SecurityDeviceMask
=
84 DixGetAttrAccess
| DixReceiveAccess
| DixGetFocusAccess
|
85 DixGrabAccess
| DixSetAttrAccess
| DixUseAccess
;
86 static const Mask SecurityServerMask
= DixGetAttrAccess
| DixGrabAccess
;
87 static const Mask SecurityClientMask
= DixGetAttrAccess
;
92 * format is the formatting string to be used to interpret the
93 * remaining arguments.
98 * Writes the message to the log file if security logging is on.
102 _X_ATTRIBUTE_PRINTF(1, 2)
103 SecurityAudit(const char *format
, ...)
107 if (auditTrailLevel
< SECURITY_AUDIT_LEVEL
)
109 va_start(args
, format
);
110 VAuditF(format
, args
);
112 } /* SecurityAudit */
115 * Performs a Security permission check.
118 SecurityDoCheck(SecurityStateRec
* subj
, SecurityStateRec
* obj
,
119 Mask requested
, Mask allowed
)
121 if (!subj
->haveState
|| !obj
->haveState
)
123 if (subj
->trustLevel
== XSecurityClientTrusted
)
125 if (obj
->trustLevel
!= XSecurityClientTrusted
)
127 if ((requested
| allowed
) == allowed
)
134 * Labels initial server objects.
137 SecurityLabelInitial(void)
139 SecurityStateRec
*state
;
141 /* Do the serverClient */
142 state
= dixLookupPrivate(&serverClient
->devPrivates
, stateKey
);
143 state
->trustLevel
= XSecurityClientTrusted
;
144 state
->haveState
= TRUE
;
149 * Looks up a request name
151 static _X_INLINE
const char *
152 SecurityLookupRequestName(ClientPtr client
)
154 return LookupRequestName(client
->majorOp
, client
->minorOp
);
157 /* SecurityDeleteAuthorization
160 * value is the authorization to delete.
161 * id is its resource ID.
166 * Frees everything associated with the authorization.
170 SecurityDeleteAuthorization(pointer value
, XID id
)
172 SecurityAuthorizationPtr pAuth
= (SecurityAuthorizationPtr
) value
;
173 unsigned short name_len
, data_len
;
178 OtherClientsPtr pEventClient
;
180 /* Remove the auth using the os layer auth manager */
182 status
= AuthorizationFromID(pAuth
->id
, &name_len
, &name
, &data_len
, &data
);
184 status
= RemoveAuthorization(name_len
, name
, data_len
, data
);
188 /* free the auth timer if there is one */
191 TimerFree(pAuth
->timer
);
193 /* send revoke events */
195 while ((pEventClient
= pAuth
->eventClients
)) {
196 /* send revocation event event */
197 xSecurityAuthorizationRevokedEvent are
= {
198 .type
= SecurityEventBase
+ XSecurityAuthorizationRevoked
,
201 WriteEventsToClient(rClient(pEventClient
), 1, (xEvent
*) &are
);
202 FreeResource(pEventClient
->resource
, RT_NONE
);
205 /* kill all clients using this auth */
207 for (i
= 1; i
< currentMaxClients
; i
++)
209 SecurityStateRec
*state
;
211 state
= dixLookupPrivate(&clients
[i
]->devPrivates
, stateKey
);
212 if (state
->haveState
&& state
->authId
== pAuth
->id
)
213 CloseDownClient(clients
[i
]);
216 SecurityAudit("revoked authorization ID %d\n", pAuth
->id
);
220 } /* SecurityDeleteAuthorization */
222 /* resource delete function for RTEventClient */
224 SecurityDeleteAuthorizationEventClient(pointer value
, XID id
)
226 OtherClientsPtr pEventClient
, prev
= NULL
;
227 SecurityAuthorizationPtr pAuth
= (SecurityAuthorizationPtr
) value
;
229 for (pEventClient
= pAuth
->eventClients
;
230 pEventClient
; pEventClient
= pEventClient
->next
) {
231 if (pEventClient
->resource
== id
) {
233 prev
->next
= pEventClient
->next
;
235 pAuth
->eventClients
= pEventClient
->next
;
241 /*NOTREACHED*/ return -1; /* make compiler happy */
242 } /* SecurityDeleteAuthorizationEventClient */
244 /* SecurityComputeAuthorizationTimeout
247 * pAuth is the authorization for which we are computing the timeout
248 * seconds is the number of seconds we want to wait
251 * the number of milliseconds that the auth timer should be set to
254 * Sets pAuth->secondsRemaining to any "overflow" amount of time
255 * that didn't fit in 32 bits worth of milliseconds
259 SecurityComputeAuthorizationTimeout(SecurityAuthorizationPtr pAuth
,
260 unsigned int seconds
)
262 /* maxSecs is the number of full seconds that can be expressed in
263 * 32 bits worth of milliseconds
265 CARD32 maxSecs
= (CARD32
) (~0) / (CARD32
) MILLI_PER_SECOND
;
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
;
271 else { /* by far the common case */
272 pAuth
->secondsRemaining
= 0;
273 return seconds
* MILLI_PER_SECOND
;
275 } /* SecurityStartAuthorizationTimer */
277 /* SecurityAuthorizationExpired
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.
283 * timer is the timer for this authorization.
284 * time is the current time.
285 * pval is the authorization whose time is up.
288 * A new time delay in milliseconds if the timer should wait some
292 * Frees the authorization resource if the timeout period is really
293 * over, otherwise recomputes pAuth->secondsRemaining.
297 SecurityAuthorizationExpired(OsTimerPtr timer
, CARD32 time
, pointer pval
)
299 SecurityAuthorizationPtr pAuth
= (SecurityAuthorizationPtr
) pval
;
301 assert(pAuth
->timer
== timer
);
303 if (pAuth
->secondsRemaining
) {
304 return SecurityComputeAuthorizationTimeout(pAuth
,
305 pAuth
->secondsRemaining
);
308 FreeResource(pAuth
->id
, RT_NONE
);
311 } /* SecurityAuthorizationExpired */
313 /* SecurityStartAuthorizationTimer
316 * pAuth is the authorization whose timer should be started.
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.
327 SecurityStartAuthorizationTimer(SecurityAuthorizationPtr pAuth
)
329 pAuth
->timer
= TimerSet(pAuth
->timer
, 0,
330 SecurityComputeAuthorizationTimeout(pAuth
,
332 SecurityAuthorizationExpired
, pAuth
);
333 } /* SecurityStartAuthorizationTimer */
335 /* Proc functions all take a client argument, execute the request in
336 * client->requestBuffer, and return a protocol error status.
340 ProcSecurityQueryVersion(ClientPtr client
)
342 /* REQUEST(xSecurityQueryVersionReq); */
343 xSecurityQueryVersionReply rep
= {
345 .sequenceNumber
= client
->sequence
,
347 .majorVersion
= SERVER_SECURITY_MAJOR_VERSION
,
348 .minorVersion
= SERVER_SECURITY_MINOR_VERSION
351 REQUEST_SIZE_MATCH(xSecurityQueryVersionReq
);
353 if (client
->swapped
) {
354 swaps(&rep
.sequenceNumber
);
355 swaps(&rep
.majorVersion
);
356 swaps(&rep
.minorVersion
);
358 WriteToClient(client
, SIZEOF(xSecurityQueryVersionReply
), &rep
);
360 } /* ProcSecurityQueryVersion */
363 SecurityEventSelectForAuthorization(SecurityAuthorizationPtr pAuth
,
364 ClientPtr client
, Mask mask
)
366 OtherClients
*pEventClient
;
368 for (pEventClient
= pAuth
->eventClients
;
369 pEventClient
; pEventClient
= pEventClient
->next
) {
370 if (SameClient(pEventClient
, client
)) {
372 FreeResource(pEventClient
->resource
, RT_NONE
);
374 pEventClient
->mask
= mask
;
379 pEventClient
= malloc(sizeof(OtherClients
));
382 pEventClient
->mask
= mask
;
383 pEventClient
->resource
= FakeClientID(client
->index
);
384 pEventClient
->next
= pAuth
->eventClients
;
385 if (!AddResource(pEventClient
->resource
, RTEventClient
, (pointer
) pAuth
)) {
389 pAuth
->eventClients
= pEventClient
;
392 } /* SecurityEventSelectForAuthorization */
395 ProcSecurityGenerateAuthorization(ClientPtr client
)
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 */
414 /* check request length */
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
)
425 /* check valuemask */
426 if (stuff
->valueMask
& ~XSecurityAllAuthorizationAttributes
) {
427 client
->errorValue
= stuff
->valueMask
;
433 if (stuff
->valueMask
& XSecurityTimeout
) {
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
;
450 if (stuff
->valueMask
& XSecurityGroup
) {
452 if (SecurityValidateGroupCallback
) {
453 SecurityValidateGroupInfoRec vgi
;
457 CallCallbacks(&SecurityValidateGroupCallback
, (pointer
) &vgi
);
459 /* if nobody said they recognized it, it's an error */
462 client
->errorValue
= group
;
468 /* check event mask */
470 if (stuff
->valueMask
& XSecurityEventMask
) {
471 eventMask
= *values
++;
472 if (eventMask
& ~XSecurityAllEventMasks
) {
473 client
->errorValue
= eventMask
;
478 protoname
= (char *) &stuff
[1];
479 protodata
= protoname
+ bytes_to_int32(stuff
->nbytesAuthProto
);
481 /* call os layer to generate the authorization */
483 authId
= GenerateAuthorization(stuff
->nbytesAuthProto
, protoname
,
484 stuff
->nbytesAuthData
, protodata
,
485 &authdata_len
, &pAuthdata
);
486 if ((XID
) ~0L == authId
) {
487 err
= SecurityErrorBase
+ XSecurityBadAuthorizationProtocol
;
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)
496 /* associate additional information with this auth ID */
498 pAuth
= malloc(sizeof(SecurityAuthorizationRec
));
504 /* fill in the auth fields */
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;
513 pAuth
->eventClients
= NULL
;
515 /* handle event selection */
517 err
= SecurityEventSelectForAuthorization(pAuth
, client
, eventMask
);
522 if (!AddResource(authId
, SecurityAuthorizationResType
, pAuth
)) {
527 /* start the timer ticking */
529 if (pAuth
->timeout
!= 0)
530 SecurityStartAuthorizationTimer(pAuth
);
532 /* tell client the auth id and data */
534 rep
= (xSecurityGenerateAuthorizationReply
) {
536 .sequenceNumber
= client
->sequence
,
537 .length
= bytes_to_int32(authdata_len
),
539 .dataLength
= authdata_len
542 if (client
->swapped
) {
544 swaps(&rep
.sequenceNumber
);
546 swaps(&rep
.dataLength
);
549 WriteToClient(client
, SIZEOF(xSecurityGenerateAuthorizationReply
), &rep
);
550 WriteToClient(client
, authdata_len
, pAuthdata
);
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
);
557 /* the request succeeded; don't call RemoveAuthorization or free pAuth */
562 RemoveAuthorization(stuff
->nbytesAuthProto
, protoname
,
563 authdata_len
, pAuthdata
);
567 } /* ProcSecurityGenerateAuthorization */
570 ProcSecurityRevokeAuthorization(ClientPtr client
)
572 REQUEST(xSecurityRevokeAuthorizationReq
);
573 SecurityAuthorizationPtr pAuth
;
576 REQUEST_SIZE_MATCH(xSecurityRevokeAuthorizationReq
);
578 rc
= dixLookupResourceByType((pointer
*) &pAuth
, stuff
->authId
,
579 SecurityAuthorizationResType
, client
,
584 FreeResource(stuff
->authId
, RT_NONE
);
586 } /* ProcSecurityRevokeAuthorization */
589 ProcSecurityDispatch(ClientPtr client
)
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
);
603 } /* ProcSecurityDispatch */
606 SProcSecurityQueryVersion(ClientPtr client
)
608 REQUEST(xSecurityQueryVersionReq
);
610 swaps(&stuff
->length
);
611 REQUEST_SIZE_MATCH(xSecurityQueryVersionReq
);
612 swaps(&stuff
->majorVersion
);
613 swaps(&stuff
->minorVersion
);
614 return ProcSecurityQueryVersion(client
);
615 } /* SProcSecurityQueryVersion */
618 SProcSecurityGenerateAuthorization(ClientPtr client
)
620 REQUEST(xSecurityGenerateAuthorizationReq
);
622 unsigned long nvalues
;
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
);
633 stuff
->length
- bytes_to_int32(sz_xSecurityGenerateAuthorizationReq
))
635 values
= (CARD32
*) (&stuff
[1]) + values_offset
;
636 nvalues
= (((CARD32
*) stuff
) + stuff
->length
) - values
;
637 SwapLongs(values
, nvalues
);
638 return ProcSecurityGenerateAuthorization(client
);
639 } /* SProcSecurityGenerateAuthorization */
642 SProcSecurityRevokeAuthorization(ClientPtr client
)
644 REQUEST(xSecurityRevokeAuthorizationReq
);
646 swaps(&stuff
->length
);
647 REQUEST_SIZE_MATCH(xSecurityRevokeAuthorizationReq
);
648 swapl(&stuff
->authId
);
649 return ProcSecurityRevokeAuthorization(client
);
650 } /* SProcSecurityRevokeAuthorization */
653 SProcSecurityDispatch(ClientPtr client
)
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
);
667 } /* SProcSecurityDispatch */
670 SwapSecurityAuthorizationRevokedEvent(xSecurityAuthorizationRevokedEvent
* from
,
671 xSecurityAuthorizationRevokedEvent
* to
)
673 to
->type
= from
->type
;
674 to
->detail
= from
->detail
;
675 cpswaps(from
->sequenceNumber
, to
->sequenceNumber
);
676 cpswapl(from
->authId
, to
->authId
);
679 /* SecurityCheckDeviceAccess
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)
689 * TRUE if the device access should be allowed, else FALSE.
692 * An audit message is generated if access is denied.
696 SecurityDevice(CallbackListPtr
*pcbl
, pointer unused
, pointer calldata
)
698 XaceDeviceAccessRec
*rec
= calldata
;
699 SecurityStateRec
*subj
, *obj
;
700 Mask requested
= rec
->access_mode
;
701 Mask allowed
= SecurityDeviceMask
;
703 subj
= dixLookupPrivate(&rec
->client
->devPrivates
, stateKey
);
704 obj
= dixLookupPrivate(&serverClient
->devPrivates
, stateKey
);
706 if (rec
->dev
!= inputInfo
.keyboard
)
707 /* this extension only supports the core keyboard */
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
;
720 * This function gets plugged into client->CheckAccess and is called from
721 * SecurityLookupIDByType/Class to determine if the client can access the
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
730 * res is a pointer to the resource structure for this resource.
733 * If access is granted, the value of rval that was passed in, else FALSE.
736 * Disallowed resource accesses are audited.
740 SecurityResource(CallbackListPtr
*pcbl
, pointer unused
, pointer calldata
)
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
;
748 subj
= dixLookupPrivate(&rec
->client
->devPrivates
, stateKey
);
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
;
755 /* additional permissions for specific resource types */
756 if (rec
->rtype
== RT_WINDOW
)
757 allowed
|= SecurityWindowExtraMask
;
759 /* special checks for server-owned resources */
761 if (rec
->rtype
& RC_DRAWABLE
)
762 /* additional operations allowed on root windows */
763 allowed
|= SecurityRootWindowExtraMask
;
765 else if (rec
->rtype
== RT_COLORMAP
)
766 /* allow access to default colormaps */
770 /* allow read access to other server-owned resources */
771 allowed
|= DixReadAccess
;
774 if (clients
[cid
] != NULL
) {
775 obj
= dixLookupPrivate(&clients
[cid
]->devPrivates
, stateKey
);
776 if (SecurityDoCheck(subj
, obj
, requested
, allowed
) == Success
)
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 */
788 SecurityExtension(CallbackListPtr
*pcbl
, pointer unused
, pointer calldata
)
790 XaceExtAccessRec
*rec
= calldata
;
791 SecurityStateRec
*subj
;
794 subj
= dixLookupPrivate(&rec
->client
->devPrivates
, stateKey
);
796 if (subj
->haveState
&& subj
->trustLevel
== XSecurityClientTrusted
)
799 while (SecurityTrustedExtensions
[i
])
800 if (!strcmp(SecurityTrustedExtensions
[i
++], rec
->ext
->name
))
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
;
811 SecurityServer(CallbackListPtr
*pcbl
, pointer unused
, pointer calldata
)
813 XaceServerAccessRec
*rec
= calldata
;
814 SecurityStateRec
*subj
, *obj
;
815 Mask requested
= rec
->access_mode
;
816 Mask allowed
= SecurityServerMask
;
818 subj
= dixLookupPrivate(&rec
->client
->devPrivates
, stateKey
);
819 obj
= dixLookupPrivate(&serverClient
->devPrivates
, stateKey
);
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
;
830 SecurityClient(CallbackListPtr
*pcbl
, pointer unused
, pointer calldata
)
832 XaceClientAccessRec
*rec
= calldata
;
833 SecurityStateRec
*subj
, *obj
;
834 Mask requested
= rec
->access_mode
;
835 Mask allowed
= SecurityClientMask
;
837 subj
= dixLookupPrivate(&rec
->client
->devPrivates
, stateKey
);
838 obj
= dixLookupPrivate(&rec
->target
->devPrivates
, stateKey
);
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
;
849 SecurityProperty(CallbackListPtr
*pcbl
, pointer unused
, pointer calldata
)
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
;
857 subj
= dixLookupPrivate(&rec
->client
->devPrivates
, stateKey
);
858 obj
= dixLookupPrivate(&wClient(rec
->pWin
)->devPrivates
, stateKey
);
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
;
871 SecuritySend(CallbackListPtr
*pcbl
, pointer unused
, pointer calldata
)
873 XaceSendAccessRec
*rec
= calldata
;
874 SecurityStateRec
*subj
, *obj
;
879 subj
= dixLookupPrivate(&rec
->client
->devPrivates
, stateKey
);
880 obj
= dixLookupPrivate(&wClient(rec
->pWin
)->devPrivates
, stateKey
);
882 if (SecurityDoCheck(subj
, obj
, DixSendAccess
, 0) == Success
)
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
) {
890 SecurityAudit("Security: denied client %d from sending event "
891 "of type %s to window 0x%x of client %d\n",
893 LookupEventName(rec
->events
[i
].u
.u
.type
),
894 rec
->pWin
->drawable
.id
,
895 wClient(rec
->pWin
)->index
);
896 rec
->status
= BadAccess
;
903 SecurityReceive(CallbackListPtr
*pcbl
, pointer unused
, pointer calldata
)
905 XaceReceiveAccessRec
*rec
= calldata
;
906 SecurityStateRec
*subj
, *obj
;
908 subj
= dixLookupPrivate(&rec
->client
->devPrivates
, stateKey
);
909 obj
= dixLookupPrivate(&wClient(rec
->pWin
)->devPrivates
, stateKey
);
911 if (SecurityDoCheck(subj
, obj
, DixReceiveAccess
, 0) == Success
)
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
;
921 /* SecurityClientStateCallback
924 * pcbl is &ClientStateCallback.
926 * calldata is a pointer to a NewClientInfoRec (include/dixstruct.h)
927 * which contains information about client state changes.
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).
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.
944 SecurityClientState(CallbackListPtr
*pcbl
, pointer unused
, pointer calldata
)
946 NewClientInfoRec
*pci
= calldata
;
947 SecurityStateRec
*state
;
948 SecurityAuthorizationPtr pAuth
;
951 state
= dixLookupPrivate(&pci
->client
->devPrivates
, stateKey
);
953 switch (pci
->client
->clientState
) {
954 case ClientStateInitial
:
955 state
->trustLevel
= XSecurityClientTrusted
;
956 state
->authId
= None
;
957 state
->haveState
= TRUE
;
961 case ClientStateRunning
:
962 state
->authId
= AuthorizationIDOfClient(pci
->client
);
963 rc
= dixLookupResourceByType((pointer
*) &pAuth
, state
->authId
,
964 SecurityAuthorizationResType
, serverClient
,
967 /* it is a generated authorization */
970 if (pAuth
->refcnt
== 1 && pAuth
->timer
)
971 TimerCancel(pAuth
->timer
);
973 state
->trustLevel
= pAuth
->trustLevel
;
977 case ClientStateGone
:
978 case ClientStateRetained
:
979 rc
= dixLookupResourceByType((pointer
*) &pAuth
, state
->authId
,
980 SecurityAuthorizationResType
, serverClient
,
982 if (rc
== Success
&& state
->live
) {
983 /* it is a generated authorization */
986 if (pAuth
->refcnt
== 0)
987 SecurityStartAuthorizationTimer(pAuth
);
999 * extEntry is the extension information for the security extension.
1004 * Performs any cleanup needed by Security at server shutdown time.
1008 SecurityResetProc(ExtensionEntry
* extEntry
)
1010 /* Unregister callbacks */
1011 DeleteCallback(&ClientStateCallback
, SecurityClientState
, NULL
);
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
);
1024 /* SecurityExtensionInit
1031 * Enables the Security extension if possible.
1035 SecurityExtensionInit(void)
1037 ExtensionEntry
*extEntry
;
1040 SecurityAuthorizationResType
=
1041 CreateNewResourceType(SecurityDeleteAuthorization
,
1042 "SecurityAuthorization");
1045 CreateNewResourceType(SecurityDeleteAuthorizationEventClient
,
1046 "SecurityEventClient");
1048 if (!SecurityAuthorizationResType
|| !RTEventClient
)
1051 RTEventClient
|= RC_NEVERRETAIN
;
1053 /* Allocate the private storage */
1054 if (!dixRegisterPrivateKey
1055 (stateKey
, PRIVATE_CLIENT
, sizeof(SecurityStateRec
)))
1056 FatalError("SecurityExtensionSetup: Can't allocate client private.\n");
1058 /* Register callbacks */
1059 ret
&= AddCallback(&ClientStateCallback
, SecurityClientState
, NULL
);
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
);
1072 FatalError("SecurityExtensionSetup: Failed to register callbacks\n");
1074 /* Add extension to server */
1075 extEntry
= AddExtension(SECURITY_EXTENSION_NAME
,
1076 XSecurityNumberEvents
, XSecurityNumberErrors
,
1077 ProcSecurityDispatch
, SProcSecurityDispatch
,
1078 SecurityResetProc
, StandardMinorOpcode
);
1080 SecurityErrorBase
= extEntry
->errorBase
;
1081 SecurityEventBase
= extEntry
->eventBase
;
1083 EventSwapVector
[SecurityEventBase
+ XSecurityAuthorizationRevoked
] =
1084 (EventSwapPtr
) SwapSecurityAuthorizationRevokedEvent
;
1086 SetResourceTypeErrorValue(SecurityAuthorizationResType
,
1087 SecurityErrorBase
+ XSecurityBadAuthorization
);
1089 /* Label objects that were created before we could register ourself */
1090 SecurityLabelInitial();