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 "dixstruct.h"
32 #include "extnsionst.h"
33 #include "windowstr.h"
35 #include "scrnintstr.h"
37 #include "colormapst.h"
38 #include "propertyst.h"
40 #include "securitysrv.h"
41 #include <X11/extensions/securstr.h>
47 #include <stdio.h> /* for file reading operations */
48 #include <X11/Xatom.h> /* for XA_STRING */
50 #ifndef DEFAULTPOLICYFILE
51 # define DEFAULTPOLICYFILE NULL
53 #if defined(WIN32) || defined(__CYGWIN__)
60 static int SecurityErrorBase
; /* first Security error number */
61 static int SecurityEventBase
; /* first Security event number */
62 static int securityClientPrivateIndex
;
63 static int securityExtnsnPrivateIndex
;
65 /* this is what we store as client security state */
67 unsigned int trustLevel
;
69 } SecurityClientStateRec
;
71 #define STATEVAL(extnsn) \
72 ((extnsn)->devPrivates[securityExtnsnPrivateIndex].val)
73 #define STATEPTR(client) \
74 ((client)->devPrivates[securityClientPrivateIndex].ptr)
75 #define TRUSTLEVEL(client) \
76 (((SecurityClientStateRec*)STATEPTR(client))->trustLevel)
77 #define AUTHID(client) \
78 (((SecurityClientStateRec*)STATEPTR(client))->authId)
80 static CallbackListPtr SecurityValidateGroupCallback
= NULL
;
82 RESTYPE SecurityAuthorizationResType
; /* resource type for authorizations */
84 static RESTYPE RTEventClient
;
86 #define CALLBACK(name) static void \
87 name(CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
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 SecurityAudit(char *format
, ...)
106 if (auditTrailLevel
< SECURITY_AUDIT_LEVEL
)
108 va_start(args
, format
);
109 VAuditF(format
, args
);
111 } /* SecurityAudit */
113 #define rClient(obj) (clients[CLIENT_ID((obj)->resource)])
115 /* SecurityDeleteAuthorization
118 * value is the authorization to delete.
119 * id is its resource ID.
124 * Frees everything associated with the authorization.
128 SecurityDeleteAuthorization(
132 SecurityAuthorizationPtr pAuth
= (SecurityAuthorizationPtr
)value
;
133 unsigned short name_len
, data_len
;
137 OtherClientsPtr pEventClient
;
139 /* Remove the auth using the os layer auth manager */
141 status
= AuthorizationFromID(pAuth
->id
, &name_len
, &name
,
144 status
= RemoveAuthorization(name_len
, name
, data_len
, data
);
148 /* free the auth timer if there is one */
150 if (pAuth
->timer
) TimerFree(pAuth
->timer
);
152 /* send revoke events */
154 while ((pEventClient
= pAuth
->eventClients
))
156 /* send revocation event event */
157 ClientPtr client
= rClient(pEventClient
);
159 if (!client
->clientGone
)
161 xSecurityAuthorizationRevokedEvent are
;
162 are
.type
= SecurityEventBase
+ XSecurityAuthorizationRevoked
;
163 are
.sequenceNumber
= client
->sequence
;
164 are
.authId
= pAuth
->id
;
165 WriteEventsToClient(client
, 1, (xEvent
*)&are
);
167 FreeResource(pEventClient
->resource
, RT_NONE
);
170 /* kill all clients using this auth */
172 for (i
= 1; i
<currentMaxClients
; i
++)
174 if (clients
[i
] && (AUTHID(clients
[i
]) == pAuth
->id
))
175 CloseDownClient(clients
[i
]);
178 SecurityAudit("revoked authorization ID %d\n", pAuth
->id
);
182 } /* SecurityDeleteAuthorization */
185 /* resource delete function for RTEventClient */
187 SecurityDeleteAuthorizationEventClient(
191 OtherClientsPtr pEventClient
, prev
= NULL
;
192 SecurityAuthorizationPtr pAuth
= (SecurityAuthorizationPtr
)value
;
194 for (pEventClient
= pAuth
->eventClients
;
196 pEventClient
= pEventClient
->next
)
198 if (pEventClient
->resource
== id
)
201 prev
->next
= pEventClient
->next
;
203 pAuth
->eventClients
= pEventClient
->next
;
210 return -1; /* make compiler happy */
211 } /* SecurityDeleteAuthorizationEventClient */
214 /* SecurityComputeAuthorizationTimeout
217 * pAuth is the authorization for which we are computing the timeout
218 * seconds is the number of seconds we want to wait
221 * the number of milliseconds that the auth timer should be set to
224 * Sets pAuth->secondsRemaining to any "overflow" amount of time
225 * that didn't fit in 32 bits worth of milliseconds
229 SecurityComputeAuthorizationTimeout(
230 SecurityAuthorizationPtr pAuth
,
231 unsigned int seconds
)
233 /* maxSecs is the number of full seconds that can be expressed in
234 * 32 bits worth of milliseconds
236 CARD32 maxSecs
= (CARD32
)(~0) / (CARD32
)MILLI_PER_SECOND
;
238 if (seconds
> maxSecs
)
239 { /* only come here if we want to wait more than 49 days */
240 pAuth
->secondsRemaining
= seconds
- maxSecs
;
241 return maxSecs
* MILLI_PER_SECOND
;
244 { /* by far the common case */
245 pAuth
->secondsRemaining
= 0;
246 return seconds
* MILLI_PER_SECOND
;
248 } /* SecurityStartAuthorizationTimer */
250 /* SecurityAuthorizationExpired
252 * This function is passed as an argument to TimerSet and gets called from
253 * the timer manager in the os layer when its time is up.
256 * timer is the timer for this authorization.
257 * time is the current time.
258 * pval is the authorization whose time is up.
261 * A new time delay in milliseconds if the timer should wait some
265 * Frees the authorization resource if the timeout period is really
266 * over, otherwise recomputes pAuth->secondsRemaining.
270 SecurityAuthorizationExpired(
275 SecurityAuthorizationPtr pAuth
= (SecurityAuthorizationPtr
)pval
;
277 assert(pAuth
->timer
== timer
);
279 if (pAuth
->secondsRemaining
)
281 return SecurityComputeAuthorizationTimeout(pAuth
,
282 pAuth
->secondsRemaining
);
286 FreeResource(pAuth
->id
, RT_NONE
);
289 } /* SecurityAuthorizationExpired */
291 /* SecurityStartAuthorizationTimer
294 * pAuth is the authorization whose timer should be started.
299 * A timer is started, set to expire after the timeout period for
300 * this authorization. When it expires, the function
301 * SecurityAuthorizationExpired will be called.
305 SecurityStartAuthorizationTimer(
306 SecurityAuthorizationPtr pAuth
)
308 pAuth
->timer
= TimerSet(pAuth
->timer
, 0,
309 SecurityComputeAuthorizationTimeout(pAuth
, pAuth
->timeout
),
310 SecurityAuthorizationExpired
, pAuth
);
311 } /* SecurityStartAuthorizationTimer */
314 /* Proc functions all take a client argument, execute the request in
315 * client->requestBuffer, and return a protocol error status.
319 ProcSecurityQueryVersion(
322 /* REQUEST(xSecurityQueryVersionReq); */
323 xSecurityQueryVersionReply rep
;
325 /* paranoia: this "can't happen" because this extension is hidden
326 * from untrusted clients, but just in case...
328 if (TRUSTLEVEL(client
) != XSecurityClientTrusted
)
331 REQUEST_SIZE_MATCH(xSecurityQueryVersionReq
);
333 rep
.sequenceNumber
= client
->sequence
;
335 rep
.majorVersion
= SECURITY_MAJOR_VERSION
;
336 rep
.minorVersion
= SECURITY_MINOR_VERSION
;
340 swaps(&rep
.sequenceNumber
, n
);
341 swaps(&rep
.majorVersion
, n
);
342 swaps(&rep
.minorVersion
, n
);
344 (void)WriteToClient(client
, SIZEOF(xSecurityQueryVersionReply
),
346 return (client
->noClientException
);
347 } /* ProcSecurityQueryVersion */
351 SecurityEventSelectForAuthorization(
352 SecurityAuthorizationPtr pAuth
,
356 OtherClients
*pEventClient
;
358 for (pEventClient
= pAuth
->eventClients
;
360 pEventClient
= pEventClient
->next
)
362 if (SameClient(pEventClient
, client
))
365 FreeResource(pEventClient
->resource
, RT_NONE
);
367 pEventClient
->mask
= mask
;
372 pEventClient
= (OtherClients
*) xalloc(sizeof(OtherClients
));
375 pEventClient
->mask
= mask
;
376 pEventClient
->resource
= FakeClientID(client
->index
);
377 pEventClient
->next
= pAuth
->eventClients
;
378 if (!AddResource(pEventClient
->resource
, RTEventClient
,
384 pAuth
->eventClients
= pEventClient
;
387 } /* SecurityEventSelectForAuthorization */
391 ProcSecurityGenerateAuthorization(
394 REQUEST(xSecurityGenerateAuthorizationReq
);
395 int len
; /* request length in CARD32s*/
396 Bool removeAuth
= FALSE
; /* if bailout, call RemoveAuthorization? */
397 SecurityAuthorizationPtr pAuth
= NULL
; /* auth we are creating */
398 int err
; /* error to return from this function */
399 XID authId
; /* authorization ID assigned by os layer */
400 xSecurityGenerateAuthorizationReply rep
; /* reply struct */
401 unsigned int trustLevel
; /* trust level of new auth */
402 XID group
; /* group of new auth */
403 CARD32 timeout
; /* timeout of new auth */
404 CARD32
*values
; /* list of supplied attributes */
405 char *protoname
; /* auth proto name sent in request */
406 char *protodata
; /* auth proto data sent in request */
407 unsigned int authdata_len
; /* # bytes of generated auth data */
408 char *pAuthdata
; /* generated auth data */
409 Mask eventMask
; /* what events on this auth does client want */
411 /* paranoia: this "can't happen" because this extension is hidden
412 * from untrusted clients, but just in case...
414 if (TRUSTLEVEL(client
) != XSecurityClientTrusted
)
417 /* check request length */
419 REQUEST_AT_LEAST_SIZE(xSecurityGenerateAuthorizationReq
);
420 len
= SIZEOF(xSecurityGenerateAuthorizationReq
) >> 2;
421 len
+= (stuff
->nbytesAuthProto
+ (unsigned)3) >> 2;
422 len
+= (stuff
->nbytesAuthData
+ (unsigned)3) >> 2;
423 values
= ((CARD32
*)stuff
) + len
;
424 len
+= Ones(stuff
->valueMask
);
425 if (client
->req_len
!= len
)
428 /* check valuemask */
429 if (stuff
->valueMask
& ~XSecurityAllAuthorizationAttributes
)
431 client
->errorValue
= stuff
->valueMask
;
437 if (stuff
->valueMask
& XSecurityTimeout
)
442 /* check trustLevel */
443 trustLevel
= XSecurityClientUntrusted
;
444 if (stuff
->valueMask
& XSecurityTrustLevel
)
446 trustLevel
= *values
++;
447 if (trustLevel
!= XSecurityClientTrusted
&&
448 trustLevel
!= XSecurityClientUntrusted
)
450 client
->errorValue
= trustLevel
;
457 if (stuff
->valueMask
& XSecurityGroup
)
460 if (SecurityValidateGroupCallback
)
462 SecurityValidateGroupInfoRec vgi
;
465 CallCallbacks(&SecurityValidateGroupCallback
, (pointer
)&vgi
);
467 /* if nobody said they recognized it, it's an error */
471 client
->errorValue
= group
;
477 /* check event mask */
479 if (stuff
->valueMask
& XSecurityEventMask
)
481 eventMask
= *values
++;
482 if (eventMask
& ~XSecurityAllEventMasks
)
484 client
->errorValue
= eventMask
;
489 protoname
= (char *)&stuff
[1];
490 protodata
= protoname
+ ((stuff
->nbytesAuthProto
+ (unsigned)3) >> 2);
492 /* call os layer to generate the authorization */
494 authId
= GenerateAuthorization(stuff
->nbytesAuthProto
, protoname
,
495 stuff
->nbytesAuthData
, protodata
,
496 &authdata_len
, &pAuthdata
);
497 if ((XID
) ~0L == authId
)
499 err
= SecurityErrorBase
+ XSecurityBadAuthorizationProtocol
;
503 /* now that we've added the auth, remember to remove it if we have to
504 * abort the request for some reason (like allocation failure)
508 /* associate additional information with this auth ID */
510 pAuth
= (SecurityAuthorizationPtr
)xalloc(sizeof(SecurityAuthorizationRec
));
517 /* fill in the auth fields */
520 pAuth
->timeout
= timeout
;
521 pAuth
->group
= group
;
522 pAuth
->trustLevel
= trustLevel
;
523 pAuth
->refcnt
= 0; /* the auth was just created; nobody's using it yet */
524 pAuth
->secondsRemaining
= 0;
526 pAuth
->eventClients
= NULL
;
528 /* handle event selection */
531 err
= SecurityEventSelectForAuthorization(pAuth
, client
, eventMask
);
536 if (!AddResource(authId
, SecurityAuthorizationResType
, pAuth
))
542 /* start the timer ticking */
544 if (pAuth
->timeout
!= 0)
545 SecurityStartAuthorizationTimer(pAuth
);
547 /* tell client the auth id and data */
550 rep
.length
= (authdata_len
+ 3) >> 2;
551 rep
.sequenceNumber
= client
->sequence
;
553 rep
.dataLength
= authdata_len
;
558 swapl(&rep
.length
, n
);
559 swaps(&rep
.sequenceNumber
, n
);
560 swapl(&rep
.authId
, n
);
561 swaps(&rep
.dataLength
, n
);
564 WriteToClient(client
, SIZEOF(xSecurityGenerateAuthorizationReply
),
566 WriteToClient(client
, authdata_len
, pAuthdata
);
568 SecurityAudit("client %d generated authorization %d trust %d timeout %d group %d events %d\n",
569 client
->index
, pAuth
->id
, pAuth
->trustLevel
, pAuth
->timeout
,
570 pAuth
->group
, eventMask
);
572 /* the request succeeded; don't call RemoveAuthorization or free pAuth */
576 err
= client
->noClientException
;
580 RemoveAuthorization(stuff
->nbytesAuthProto
, protoname
,
581 authdata_len
, pAuthdata
);
582 if (pAuth
) xfree(pAuth
);
585 } /* ProcSecurityGenerateAuthorization */
588 ProcSecurityRevokeAuthorization(
591 REQUEST(xSecurityRevokeAuthorizationReq
);
592 SecurityAuthorizationPtr pAuth
;
594 /* paranoia: this "can't happen" because this extension is hidden
595 * from untrusted clients, but just in case...
597 if (TRUSTLEVEL(client
) != XSecurityClientTrusted
)
600 REQUEST_SIZE_MATCH(xSecurityRevokeAuthorizationReq
);
602 pAuth
= (SecurityAuthorizationPtr
)SecurityLookupIDByType(client
,
603 stuff
->authId
, SecurityAuthorizationResType
, DixDestroyAccess
);
605 return SecurityErrorBase
+ XSecurityBadAuthorization
;
607 FreeResource(stuff
->authId
, RT_NONE
);
609 } /* ProcSecurityRevokeAuthorization */
613 ProcSecurityDispatch(
620 case X_SecurityQueryVersion
:
621 return ProcSecurityQueryVersion(client
);
622 case X_SecurityGenerateAuthorization
:
623 return ProcSecurityGenerateAuthorization(client
);
624 case X_SecurityRevokeAuthorization
:
625 return ProcSecurityRevokeAuthorization(client
);
629 } /* ProcSecurityDispatch */
632 SProcSecurityQueryVersion(
635 REQUEST(xSecurityQueryVersionReq
);
638 swaps(&stuff
->length
, n
);
639 REQUEST_SIZE_MATCH(xSecurityQueryVersionReq
);
640 swaps(&stuff
->majorVersion
, n
);
641 swaps(&stuff
->minorVersion
,n
);
642 return ProcSecurityQueryVersion(client
);
643 } /* SProcSecurityQueryVersion */
647 SProcSecurityGenerateAuthorization(
650 REQUEST(xSecurityGenerateAuthorizationReq
);
653 unsigned long nvalues
;
655 swaps(&stuff
->length
, n
);
656 REQUEST_AT_LEAST_SIZE(xSecurityGenerateAuthorizationReq
);
657 swaps(&stuff
->nbytesAuthProto
, n
);
658 swaps(&stuff
->nbytesAuthData
, n
);
659 swapl(&stuff
->valueMask
, n
);
660 values
= (CARD32
*)(&stuff
[1]) +
661 ((stuff
->nbytesAuthProto
+ (unsigned)3) >> 2) +
662 ((stuff
->nbytesAuthData
+ (unsigned)3) >> 2);
663 nvalues
= (((CARD32
*)stuff
) + stuff
->length
) - values
;
664 SwapLongs(values
, nvalues
);
665 return ProcSecurityGenerateAuthorization(client
);
666 } /* SProcSecurityGenerateAuthorization */
670 SProcSecurityRevokeAuthorization(
673 REQUEST(xSecurityRevokeAuthorizationReq
);
676 swaps(&stuff
->length
, n
);
677 REQUEST_SIZE_MATCH(xSecurityRevokeAuthorizationReq
);
678 swapl(&stuff
->authId
, n
);
679 return ProcSecurityRevokeAuthorization(client
);
680 } /* SProcSecurityRevokeAuthorization */
684 SProcSecurityDispatch(
691 case X_SecurityQueryVersion
:
692 return SProcSecurityQueryVersion(client
);
693 case X_SecurityGenerateAuthorization
:
694 return SProcSecurityGenerateAuthorization(client
);
695 case X_SecurityRevokeAuthorization
:
696 return SProcSecurityRevokeAuthorization(client
);
700 } /* SProcSecurityDispatch */
703 SwapSecurityAuthorizationRevokedEvent(
704 xSecurityAuthorizationRevokedEvent
*from
,
705 xSecurityAuthorizationRevokedEvent
*to
)
707 to
->type
= from
->type
;
708 to
->detail
= from
->detail
;
709 cpswaps(from
->sequenceNumber
, to
->sequenceNumber
);
710 cpswapl(from
->authId
, to
->authId
);
713 /* SecurityDetermineEventPropogationLimits
715 * This is a helper function for SecurityCheckDeviceAccess.
718 * dev is the device for which the starting and stopping windows for
719 * event propogation should be determined.
720 * The values pointed to by ppWin and ppStopWin are not used.
723 * ppWin is filled in with a pointer to the window at which event
724 * propogation for the given device should start given the current
725 * state of the server (pointer position, window layout, etc.)
726 * ppStopWin is filled in with the window at which event propogation
727 * should stop; events should not go to ppStopWin.
729 * Side Effects: none.
733 SecurityDetermineEventPropogationLimits(
736 WindowPtr
*ppStopWin
)
738 WindowPtr pFocusWin
= dev
->focus
? dev
->focus
->win
: NoneWin
;
740 if (pFocusWin
== NoneWin
)
741 { /* no focus -- events don't go anywhere */
742 *ppWin
= *ppStopWin
= NULL
;
746 if (pFocusWin
== PointerRootWin
)
747 { /* focus follows the pointer */
748 *ppWin
= GetSpriteWindow();
749 *ppStopWin
= NULL
; /* propogate all the way to the root */
752 { /* a real window is set for the focus */
753 WindowPtr pSpriteWin
= GetSpriteWindow();
754 *ppStopWin
= pFocusWin
->parent
; /* don't go past the focus window */
756 /* if the pointer is in a subwindow of the focus window, start
757 * at that subwindow, else start at the focus window itself
759 if (IsParent(pFocusWin
, pSpriteWin
))
761 else *ppWin
= pFocusWin
;
763 } /* SecurityDetermineEventPropogationLimits */
766 /* SecurityCheckDeviceAccess
769 * client is the client attempting to access a device.
770 * dev is the device being accessed.
771 * fromRequest is TRUE if the device access is a direct result of
772 * the client executing some request and FALSE if it is a
773 * result of the server trying to send an event (e.g. KeymapNotify)
776 * TRUE if the device access should be allowed, else FALSE.
779 * An audit message is generated if access is denied.
782 CALLBACK(SecurityCheckDeviceAccess
)
784 XaceDeviceAccessRec
*rec
= (XaceDeviceAccessRec
*)calldata
;
785 ClientPtr client
= rec
->client
;
786 DeviceIntPtr dev
= rec
->dev
;
787 Bool fromRequest
= rec
->fromRequest
;
788 WindowPtr pWin
, pStopWin
;
789 Bool untrusted_got_event
;
790 Bool found_event_window
;
794 /* trusted clients always allowed to do anything */
795 if (TRUSTLEVEL(client
) == XSecurityClientTrusted
)
798 /* device security other than keyboard is not implemented yet */
799 if (dev
!= inputInfo
.keyboard
)
802 /* some untrusted client wants access */
806 reqtype
= ((xReq
*)client
->requestBuffer
)->reqType
;
809 /* never allow these */
810 case X_ChangeKeyboardMapping
:
811 case X_ChangeKeyboardControl
:
812 case X_SetModifierMapping
:
813 SecurityAudit("client %d attempted request %d\n",
814 client
->index
, reqtype
);
822 untrusted_got_event
= FALSE
;
823 found_event_window
= FALSE
;
827 untrusted_got_event
=
828 (TRUSTLEVEL(rClient(dev
->grab
)) != XSecurityClientTrusted
);
832 SecurityDetermineEventPropogationLimits(dev
, &pWin
, &pStopWin
);
834 eventmask
= KeyPressMask
| KeyReleaseMask
;
835 while ( (pWin
!= pStopWin
) && !found_event_window
)
839 if (pWin
->eventMask
& eventmask
)
841 found_event_window
= TRUE
;
842 client
= wClient(pWin
);
843 if (TRUSTLEVEL(client
) != XSecurityClientTrusted
)
845 untrusted_got_event
= TRUE
;
848 if (wOtherEventMasks(pWin
) & eventmask
)
850 found_event_window
= TRUE
;
851 for (other
= wOtherClients(pWin
); other
; other
= other
->next
)
853 if (other
->mask
& eventmask
)
855 client
= rClient(other
);
856 if (TRUSTLEVEL(client
) != XSecurityClientTrusted
)
858 untrusted_got_event
= TRUE
;
864 if (wDontPropagateMask(pWin
) & eventmask
)
867 } /* while propogating the event */
870 /* allow access by untrusted clients only if an event would have gone
871 * to an untrusted client
874 if (!untrusted_got_event
)
876 char *devname
= dev
->name
;
877 if (!devname
) devname
= "unnamed";
879 SecurityAudit("client %d attempted request %d device %d (%s)\n",
880 client
->index
, reqtype
, dev
->id
, devname
);
882 SecurityAudit("client %d attempted to access device %d (%s)\n",
883 client
->index
, dev
->id
, devname
);
887 } /* SecurityCheckDeviceAccess */
891 /* SecurityAuditResourceIDAccess
894 * client is the client doing the resource access.
895 * id is the resource id.
900 * An audit message is generated with details of the denied
905 SecurityAuditResourceIDAccess(
909 int cid
= CLIENT_ID(id
);
910 int reqtype
= ((xReq
*)client
->requestBuffer
)->reqType
;
913 case X_ChangeProperty
:
914 case X_DeleteProperty
:
917 xChangePropertyReq
*req
=
918 (xChangePropertyReq
*)client
->requestBuffer
;
919 int propertyatom
= req
->property
;
920 char *propertyname
= NameForAtom(propertyatom
);
922 SecurityAudit("client %d attempted request %d with window 0x%x property %s of client %d\n",
923 client
->index
, reqtype
, id
, propertyname
, cid
);
928 SecurityAudit("client %d attempted request %d with resource 0x%x of client %d\n",
929 client
->index
, reqtype
, id
, cid
);
934 } /* SecurityAuditResourceIDAccess */
937 /* SecurityCheckResourceIDAccess
939 * This function gets plugged into client->CheckAccess and is called from
940 * SecurityLookupIDByType/Class to determine if the client can access the
944 * client is the client doing the resource access.
945 * id is the resource id.
946 * rtype is its type or class.
947 * access_mode represents the intended use of the resource; see
949 * res is a pointer to the resource structure for this resource.
952 * If access is granted, the value of rval that was passed in, else FALSE.
955 * Disallowed resource accesses are audited.
958 CALLBACK(SecurityCheckResourceIDAccess
)
960 XaceResourceAccessRec
*rec
= (XaceResourceAccessRec
*)calldata
;
961 ClientPtr client
= rec
->client
;
963 RESTYPE rtype
= rec
->rtype
;
964 Mask access_mode
= rec
->access_mode
;
965 pointer rval
= rec
->res
;
968 if (TRUSTLEVEL(client
) == XSecurityClientTrusted
||
969 DixUnknownAccess
== access_mode
)
970 return; /* for compatibility, we have to allow access */
973 reqtype
= ((xReq
*)client
->requestBuffer
)->reqType
;
975 { /* these are always allowed */
977 case X_TranslateCoords
:
979 /* property access is controlled in SecurityCheckPropertyAccess */
981 case X_ChangeProperty
:
982 case X_DeleteProperty
:
983 case X_RotateProperties
:
984 case X_ListProperties
:
991 { /* not a server-owned resource */
993 * The following 'if' restricts clients to only access resources at
994 * the same trustLevel. Since there are currently only two trust levels,
995 * and trusted clients never call this function, this degenerates into
996 * saying that untrusted clients can only access resources of other
997 * untrusted clients. One way to add the notion of groups would be to
998 * allow values other than Trusted (0) and Untrusted (1) for this field.
999 * Clients at the same trust level would be able to use each other's
1000 * resources, but not those of clients at other trust levels. I haven't
1001 * tried it, but this probably mostly works already. The obvious
1002 * competing alternative for grouping clients for security purposes is to
1003 * use app groups. dpw
1005 if (TRUSTLEVEL(client
) == TRUSTLEVEL(clients
[cid
])
1007 || (RT_COLORMAP
== rtype
&&
1008 XagDefaultColormap (client
) == (Colormap
) id
)
1015 else /* server-owned resource - probably a default colormap or root window */
1017 if (RT_WINDOW
== rtype
|| RC_DRAWABLE
== rtype
)
1020 { /* the following operations are allowed on root windows */
1021 case X_CreatePixmap
:
1023 case X_CreateWindow
:
1024 case X_CreateColormap
:
1025 case X_ListProperties
:
1027 case X_UngrabButton
:
1028 case X_QueryBestSize
:
1029 case X_GetWindowAttributes
:
1032 { /* see if it is an event specified by the ICCCM */
1033 xSendEventReq
*req
= (xSendEventReq
*)
1034 (client
->requestBuffer
);
1035 if (req
->propagate
== xTrue
1037 (req
->eventMask
!= ColormapChangeMask
&&
1038 req
->eventMask
!= StructureNotifyMask
&&
1040 (SubstructureRedirectMask
|SubstructureNotifyMask
)
1043 (req
->event
.u
.u
.type
!= UnmapNotify
&&
1044 req
->event
.u
.u
.type
!= ConfigureRequest
&&
1045 req
->event
.u
.u
.type
!= ClientMessage
1048 { /* not an ICCCM event */
1052 } /* case X_SendEvent on root */
1054 case X_ChangeWindowAttributes
:
1055 { /* Allow selection of PropertyNotify and StructureNotify
1056 * events on the root.
1058 xChangeWindowAttributesReq
*req
=
1059 (xChangeWindowAttributesReq
*)(client
->requestBuffer
);
1060 if (req
->valueMask
== CWEventMask
)
1062 CARD32 value
= *((CARD32
*)(req
+ 1));
1064 ~(PropertyChangeMask
|StructureNotifyMask
)) == 0)
1068 } /* case X_ChangeWindowAttributes on root */
1072 /* others not allowed */
1076 } /* end server-owned window or drawable */
1077 else if (SecurityAuthorizationResType
== rtype
)
1079 SecurityAuthorizationPtr pAuth
= (SecurityAuthorizationPtr
)rval
;
1080 if (pAuth
->trustLevel
!= TRUSTLEVEL(client
))
1083 else if (RT_COLORMAP
!= rtype
)
1084 { /* don't allow anything else besides colormaps */
1090 SecurityAuditResourceIDAccess(client
, id
);
1091 rec
->rval
= FALSE
; /* deny access */
1092 } /* SecurityCheckResourceIDAccess */
1095 /* SecurityClientStateCallback
1098 * pcbl is &ClientStateCallback.
1100 * calldata is a pointer to a NewClientInfoRec (include/dixstruct.h)
1101 * which contains information about client state changes.
1107 * If a new client is connecting, its authorization ID is copied to
1108 * client->authID. If this is a generated authorization, its reference
1109 * count is bumped, its timer is cancelled if it was running, and its
1110 * trustlevel is copied to TRUSTLEVEL(client).
1112 * If a client is disconnecting and the client was using a generated
1113 * authorization, the authorization's reference count is decremented, and
1114 * if it is now zero, the timer for this authorization is started.
1117 CALLBACK(SecurityClientStateCallback
)
1119 NewClientInfoRec
*pci
= (NewClientInfoRec
*)calldata
;
1120 ClientPtr client
= pci
->client
;
1122 switch (client
->clientState
)
1124 case ClientStateInitial
:
1125 TRUSTLEVEL(client
) = XSecurityClientTrusted
;
1126 AUTHID(client
) = None
;
1129 case ClientStateRunning
:
1131 XID authId
= AuthorizationIDOfClient(client
);
1132 SecurityAuthorizationPtr pAuth
;
1134 TRUSTLEVEL(client
) = XSecurityClientTrusted
;
1135 AUTHID(client
) = authId
;
1136 pAuth
= (SecurityAuthorizationPtr
)LookupIDByType(authId
,
1137 SecurityAuthorizationResType
);
1139 { /* it is a generated authorization */
1141 if (pAuth
->refcnt
== 1)
1143 if (pAuth
->timer
) TimerCancel(pAuth
->timer
);
1145 TRUSTLEVEL(client
) = pAuth
->trustLevel
;
1149 case ClientStateGone
:
1150 case ClientStateRetained
: /* client disconnected */
1152 SecurityAuthorizationPtr pAuth
;
1154 /* client may not have any state (bad authorization) */
1155 if (!STATEPTR(client
))
1158 pAuth
= (SecurityAuthorizationPtr
)LookupIDByType(AUTHID(client
),
1159 SecurityAuthorizationResType
);
1161 { /* it is a generated authorization */
1163 if (pAuth
->refcnt
== 0)
1165 SecurityStartAuthorizationTimer(pAuth
);
1172 } /* SecurityClientStateCallback */
1174 CALLBACK(SecurityCheckDrawableAccess
)
1176 XaceDrawableAccessRec
*rec
= (XaceDrawableAccessRec
*)calldata
;
1178 if (TRUSTLEVEL(rec
->client
) != XSecurityClientTrusted
)
1182 CALLBACK(SecurityCheckMapAccess
)
1184 XaceMapAccessRec
*rec
= (XaceMapAccessRec
*)calldata
;
1185 WindowPtr pWin
= rec
->pWin
;
1187 if (STATEPTR(rec
->client
) &&
1188 (TRUSTLEVEL(rec
->client
) != XSecurityClientTrusted
) &&
1189 (pWin
->drawable
.class == InputOnly
) &&
1190 pWin
->parent
&& pWin
->parent
->parent
&&
1191 (TRUSTLEVEL(wClient(pWin
->parent
)) == XSecurityClientTrusted
))
1196 CALLBACK(SecurityCheckBackgrndAccess
)
1198 XaceMapAccessRec
*rec
= (XaceMapAccessRec
*)calldata
;
1200 if (TRUSTLEVEL(rec
->client
) != XSecurityClientTrusted
)
1204 CALLBACK(SecurityCheckExtAccess
)
1206 XaceExtAccessRec
*rec
= (XaceExtAccessRec
*)calldata
;
1208 if ((TRUSTLEVEL(rec
->client
) != XSecurityClientTrusted
) &&
1209 !STATEVAL(rec
->ext
))
1214 CALLBACK(SecurityCheckHostlistAccess
)
1216 XaceHostlistAccessRec
*rec
= (XaceHostlistAccessRec
*)calldata
;
1218 if (TRUSTLEVEL(rec
->client
) != XSecurityClientTrusted
)
1221 if (rec
->access_mode
== DixWriteAccess
)
1222 SecurityAudit("client %d attempted to change host access\n",
1223 rec
->client
->index
);
1225 SecurityAudit("client %d attempted to list hosts\n",
1226 rec
->client
->index
);
1230 CALLBACK(SecurityDeclareExtSecure
)
1232 XaceDeclareExtSecureRec
*rec
= (XaceDeclareExtSecureRec
*)calldata
;
1234 /* security state for extensions is simply a boolean trust value */
1235 STATEVAL(rec
->ext
) = rec
->secure
;
1238 /**********************************************************************/
1240 typedef struct _PropertyAccessRec
{
1242 ATOM mustHaveProperty
;
1243 char *mustHaveValue
;
1244 char windowRestriction
;
1245 #define SecurityAnyWindow 0
1246 #define SecurityRootWindow 1
1247 #define SecurityWindowWithProperty 2
1251 struct _PropertyAccessRec
*next
;
1252 } PropertyAccessRec
, *PropertyAccessPtr
;
1254 static PropertyAccessPtr PropertyAccessList
= NULL
;
1255 static char SecurityDefaultAction
= XaceErrorOperation
;
1256 static char *SecurityPolicyFile
= DEFAULTPOLICYFILE
;
1257 static ATOM SecurityMaxPropertyName
= 0;
1259 static char *SecurityKeywords
[] = {
1260 #define SecurityKeywordComment 0
1262 #define SecurityKeywordProperty 1
1264 #define SecurityKeywordSitePolicy 2
1266 #define SecurityKeywordRoot 3
1268 #define SecurityKeywordAny 4
1272 #define NUMKEYWORDS (sizeof(SecurityKeywords) / sizeof(char *))
1275 /*#define PROPDEBUG 1*/
1278 SecurityFreePropertyAccessList(void)
1280 while (PropertyAccessList
)
1282 PropertyAccessPtr freeit
= PropertyAccessList
;
1283 PropertyAccessList
= PropertyAccessList
->next
;
1286 } /* SecurityFreePropertyAccessList */
1288 #define SecurityIsWhitespace(c) ( (c == ' ') || (c == '\t') || (c == '\n') )
1291 SecuritySkipWhitespace(
1294 while (SecurityIsWhitespace(*p
))
1297 } /* SecuritySkipWhitespace */
1301 SecurityParseString(
1304 char *startOfString
;
1308 s
= SecuritySkipWhitespace(s
);
1310 if (*s
== '"' || *s
== '\'')
1314 while (*s
&& (*s
!= endChar
))
1320 while (*s
&& !SecurityIsWhitespace(*s
))
1327 return startOfString
;
1332 return (endChar
) ? NULL
: startOfString
;
1334 } /* SecurityParseString */
1338 SecurityParseKeyword(
1343 s
= SecuritySkipWhitespace(s
);
1344 for (i
= 0; i
< NUMKEYWORDS
; i
++)
1346 int len
= strlen(SecurityKeywords
[i
]);
1347 if (strncmp(s
, SecurityKeywords
[i
], len
) == 0)
1355 } /* SecurityParseKeyword */
1359 SecurityParsePropertyAccessRule(
1364 char action
= SecurityDefaultAction
;
1365 char readAction
, writeAction
, destroyAction
;
1366 PropertyAccessPtr pacl
, prev
, cur
;
1367 char *mustHaveProperty
= NULL
;
1368 char *mustHaveValue
= NULL
;
1370 char windowRestriction
;
1374 /* get property name */
1375 propname
= SecurityParseString(&p
);
1376 if (!propname
|| (strlen(propname
) == 0))
1379 /* get window on which property must reside for rule to apply */
1381 keyword
= SecurityParseKeyword(&p
);
1382 if (keyword
== SecurityKeywordRoot
)
1383 windowRestriction
= SecurityRootWindow
;
1384 else if (keyword
== SecurityKeywordAny
)
1385 windowRestriction
= SecurityAnyWindow
;
1386 else /* not root or any, must be a property name */
1388 mustHaveProperty
= SecurityParseString(&p
);
1389 if (!mustHaveProperty
|| (strlen(mustHaveProperty
) == 0))
1391 windowRestriction
= SecurityWindowWithProperty
;
1392 p
= SecuritySkipWhitespace(p
);
1394 { /* property value is specified too */
1395 p
++; /* skip over '=' */
1396 mustHaveValue
= SecurityParseString(&p
);
1402 /* get operations and actions */
1405 readAction
= writeAction
= destroyAction
= SecurityDefaultAction
;
1406 while ( (c
= *p
++) && !invalid
)
1410 case 'i': action
= XaceIgnoreOperation
; break;
1411 case 'a': action
= XaceAllowOperation
; break;
1412 case 'e': action
= XaceErrorOperation
; break;
1414 case 'r': readAction
= action
; break;
1415 case 'w': writeAction
= action
; break;
1416 case 'd': destroyAction
= action
; break;
1419 if (!SecurityIsWhitespace(c
))
1427 /* We've successfully collected all the information needed for this
1428 * property access rule. Now record it in a PropertyAccessRec.
1430 size
= sizeof(PropertyAccessRec
);
1432 /* If there is a property value string, allocate space for it
1433 * right after the PropertyAccessRec.
1436 size
+= strlen(mustHaveValue
) + 1;
1437 pacl
= (PropertyAccessPtr
)Xalloc(size
);
1441 pacl
->name
= MakeAtom(propname
, strlen(propname
), TRUE
);
1442 if (pacl
->name
== BAD_RESOURCE
)
1447 if (mustHaveProperty
)
1449 pacl
->mustHaveProperty
= MakeAtom(mustHaveProperty
,
1450 strlen(mustHaveProperty
), TRUE
);
1451 if (pacl
->mustHaveProperty
== BAD_RESOURCE
)
1458 pacl
->mustHaveProperty
= 0;
1462 pacl
->mustHaveValue
= (char *)(pacl
+ 1);
1463 strcpy(pacl
->mustHaveValue
, mustHaveValue
);
1466 pacl
->mustHaveValue
= NULL
;
1468 SecurityMaxPropertyName
= max(SecurityMaxPropertyName
, pacl
->name
);
1470 pacl
->windowRestriction
= windowRestriction
;
1471 pacl
->readAction
= readAction
;
1472 pacl
->writeAction
= writeAction
;
1473 pacl
->destroyAction
= destroyAction
;
1475 /* link the new rule into the list of rules in order of increasing
1476 * property name (atom) value to make searching easier
1479 for (prev
= NULL
, cur
= PropertyAccessList
;
1480 cur
&& cur
->name
<= pacl
->name
;
1481 prev
= cur
, cur
= cur
->next
)
1486 PropertyAccessList
= pacl
;
1494 } /* SecurityParsePropertyAccessRule */
1496 static char **SecurityPolicyStrings
= NULL
;
1497 static int nSecurityPolicyStrings
= 0;
1500 SecurityParseSitePolicy(
1503 char *policyStr
= SecurityParseString(&p
);
1504 char *copyPolicyStr
;
1510 copyPolicyStr
= (char *)Xalloc(strlen(policyStr
) + 1);
1513 strcpy(copyPolicyStr
, policyStr
);
1514 newStrings
= (char **)Xrealloc(SecurityPolicyStrings
,
1515 sizeof (char *) * (nSecurityPolicyStrings
+ 1));
1518 Xfree(copyPolicyStr
);
1522 SecurityPolicyStrings
= newStrings
;
1523 SecurityPolicyStrings
[nSecurityPolicyStrings
++] = copyPolicyStr
;
1527 } /* SecurityParseSitePolicy */
1531 SecurityGetSitePolicyStrings(n
)
1534 *n
= nSecurityPolicyStrings
;
1535 return SecurityPolicyStrings
;
1536 } /* SecurityGetSitePolicyStrings */
1539 SecurityFreeSitePolicyStrings(void)
1541 if (SecurityPolicyStrings
)
1543 assert(nSecurityPolicyStrings
);
1544 while (nSecurityPolicyStrings
--)
1546 Xfree(SecurityPolicyStrings
[nSecurityPolicyStrings
]);
1548 Xfree(SecurityPolicyStrings
);
1549 SecurityPolicyStrings
= NULL
;
1550 nSecurityPolicyStrings
= 0;
1552 } /* SecurityFreeSitePolicyStrings */
1556 SecurityLoadPropertyAccessList(void)
1561 SecurityMaxPropertyName
= 0;
1563 if (!SecurityPolicyFile
)
1566 f
= fopen(SecurityPolicyFile
, "r");
1569 ErrorF("error opening security policy file %s\n",
1570 SecurityPolicyFile
);
1580 if (!(p
= fgets(buf
, sizeof(buf
), f
)))
1584 /* if first line, check version number */
1585 if (lineNumber
== 1)
1587 char *v
= SecurityParseString(&p
);
1588 if (strcmp(v
, SECURITY_POLICY_FILE_VERSION
) != 0)
1590 ErrorF("%s: invalid security policy file version, ignoring file\n",
1591 SecurityPolicyFile
);
1598 switch (SecurityParseKeyword(&p
))
1600 case SecurityKeywordComment
:
1604 case SecurityKeywordProperty
:
1605 validLine
= SecurityParsePropertyAccessRule(p
);
1608 case SecurityKeywordSitePolicy
:
1609 validLine
= SecurityParseSitePolicy(p
);
1613 validLine
= (*p
== '\0'); /* blank lines OK, others not */
1619 ErrorF("Line %d of %s invalid, ignoring\n",
1620 lineNumber
, SecurityPolicyFile
);
1621 } /* end while more input */
1625 PropertyAccessPtr pacl
;
1627 for (pacl
= PropertyAccessList
; pacl
; pacl
= pacl
->next
)
1629 ErrorF("property %s ", NameForAtom(pacl
->name
));
1630 switch (pacl
->windowRestriction
)
1632 case SecurityAnyWindow
: ErrorF("any "); break;
1633 case SecurityRootWindow
: ErrorF("root "); break;
1634 case SecurityWindowWithProperty
:
1636 ErrorF("%s ", NameForAtom(pacl
->mustHaveProperty
));
1637 if (pacl
->mustHaveValue
)
1638 ErrorF(" = \"%s\" ", pacl
->mustHaveValue
);
1643 ErrorF("%cr %cw %cd\n", op
[pacl
->readAction
],
1644 op
[pacl
->writeAction
], op
[pacl
->destroyAction
]);
1647 #endif /* PROPDEBUG */
1650 } /* SecurityLoadPropertyAccessList */
1654 SecurityMatchString(
1664 while (!(match
= SecurityMatchString(ws
, cs
)) && *cs
)
1670 else if (*ws
== *cs
)
1677 return ( ( (*ws
== '\0') || ((*ws
== '*') && *(ws
+1) == '\0') )
1679 } /* SecurityMatchString */
1682 #include <sys/types.h>
1683 #include <sys/stat.h>
1687 CALLBACK(SecurityCheckPropertyAccess
)
1689 XacePropertyAccessRec
*rec
= (XacePropertyAccessRec
*)calldata
;
1690 ClientPtr client
= rec
->client
;
1691 WindowPtr pWin
= rec
->pWin
;
1692 ATOM propertyName
= rec
->propertyName
;
1693 Mask access_mode
= rec
->access_mode
;
1694 PropertyAccessPtr pacl
;
1695 char action
= SecurityDefaultAction
;
1697 /* if client trusted or window untrusted, allow operation */
1699 if ( (TRUSTLEVEL(client
) == XSecurityClientTrusted
) ||
1700 (TRUSTLEVEL(wClient(pWin
)) != XSecurityClientTrusted
) )
1704 /* For testing, it's more convenient if the property rules file gets
1705 * reloaded whenever it changes, so we can rapidly try things without
1706 * having to reset the server.
1710 static time_t lastmod
= 0;
1711 int ret
= stat(SecurityPolicyFile
, &buf
);
1712 if ( (ret
== 0) && (buf
.st_mtime
> lastmod
) )
1714 ErrorF("reloading property rules\n");
1715 SecurityFreePropertyAccessList();
1716 SecurityLoadPropertyAccessList();
1717 lastmod
= buf
.st_mtime
;
1722 /* If the property atom is bigger than any atoms on the list,
1723 * we know we won't find it, so don't even bother looking.
1725 if (propertyName
<= SecurityMaxPropertyName
)
1727 /* untrusted client operating on trusted window; see if it's allowed */
1729 for (pacl
= PropertyAccessList
; pacl
; pacl
= pacl
->next
)
1731 if (pacl
->name
< propertyName
)
1733 if (pacl
->name
> propertyName
)
1736 /* pacl->name == propertyName, so see if it applies to this window */
1738 switch (pacl
->windowRestriction
)
1740 case SecurityAnyWindow
: /* always applies */
1743 case SecurityRootWindow
:
1745 /* if not a root window, this rule doesn't apply */
1751 case SecurityWindowWithProperty
:
1753 PropertyPtr pProp
= wUserProps (pWin
);
1760 if (pProp
->propertyName
== pacl
->mustHaveProperty
)
1762 pProp
= pProp
->next
;
1766 if (!pacl
->mustHaveValue
)
1768 if (pProp
->type
!= XA_STRING
|| pProp
->format
!= 8)
1772 pEndData
= ((char *)pProp
->data
) + pProp
->size
;
1773 while (!match
&& p
< pEndData
)
1775 if (SecurityMatchString(pacl
->mustHaveValue
, p
))
1778 { /* skip to the next string */
1779 while (*p
++ && p
< pEndData
)
1786 break; /* end case SecurityWindowWithProperty */
1787 } /* end switch on windowRestriction */
1789 /* If we get here, the property access rule pacl applies.
1790 * If pacl doesn't apply, something above should have
1791 * executed a continue, which will skip the follwing code.
1793 action
= XaceAllowOperation
;
1794 if (access_mode
& DixReadAccess
)
1795 action
= max(action
, pacl
->readAction
);
1796 if (access_mode
& DixWriteAccess
)
1797 action
= max(action
, pacl
->writeAction
);
1798 if (access_mode
& DixDestroyAccess
)
1799 action
= max(action
, pacl
->destroyAction
);
1801 } /* end for each pacl */
1802 } /* end if propertyName <= SecurityMaxPropertyName */
1804 if (XaceAllowOperation
!= action
)
1805 { /* audit the access violation */
1806 int cid
= CLIENT_ID(pWin
->drawable
.id
);
1807 int reqtype
= ((xReq
*)client
->requestBuffer
)->reqType
;
1808 char *actionstr
= (XaceIgnoreOperation
== action
) ?
1809 "ignored" : "error";
1810 SecurityAudit("client %d attempted request %d with window 0x%x property %s (atom 0x%x) of client %d, %s\n",
1811 client
->index
, reqtype
, pWin
->drawable
.id
,
1812 NameForAtom(propertyName
), propertyName
, cid
, actionstr
);
1814 /* return codes increase with strictness */
1815 if (action
> rec
->rval
)
1817 } /* SecurityCheckPropertyAccess */
1820 /* SecurityResetProc
1823 * extEntry is the extension information for the security extension.
1828 * Performs any cleanup needed by Security at server shutdown time.
1833 ExtensionEntry
*extEntry
)
1835 SecurityFreePropertyAccessList();
1836 SecurityFreeSitePolicyStrings();
1837 } /* SecurityResetProc */
1841 XSecurityOptions(argc
, argv
, i
)
1846 if (strcmp(argv
[i
], "-sp") == 0)
1849 SecurityPolicyFile
= argv
[++i
];
1853 } /* XSecurityOptions */
1856 /* SecurityExtensionSetup
1863 * Sets up the Security extension if possible.
1864 * This function contains things that need to be done
1865 * before any other extension init functions get called.
1869 SecurityExtensionSetup(INITARGS
)
1871 /* Allocate the client private index */
1872 securityClientPrivateIndex
= AllocateClientPrivateIndex();
1873 if (!AllocateClientPrivate(securityClientPrivateIndex
,
1874 sizeof (SecurityClientStateRec
)))
1875 FatalError("SecurityExtensionSetup: Can't allocate client private.\n");
1877 /* Allocate the extension private index */
1878 securityExtnsnPrivateIndex
= AllocateExtensionPrivateIndex();
1879 if (!AllocateExtensionPrivate(securityExtnsnPrivateIndex
, 0))
1880 FatalError("SecurityExtensionSetup: Can't allocate extnsn private.\n");
1882 /* register callbacks */
1883 #define XaceRC XaceRegisterCallback
1884 XaceRC(XACE_RESOURCE_ACCESS
, SecurityCheckResourceIDAccess
, NULL
);
1885 XaceRC(XACE_DEVICE_ACCESS
, SecurityCheckDeviceAccess
, NULL
);
1886 XaceRC(XACE_PROPERTY_ACCESS
, SecurityCheckPropertyAccess
, NULL
);
1887 XaceRC(XACE_DRAWABLE_ACCESS
, SecurityCheckDrawableAccess
, NULL
);
1888 XaceRC(XACE_MAP_ACCESS
, SecurityCheckMapAccess
, NULL
);
1889 XaceRC(XACE_BACKGRND_ACCESS
, SecurityCheckBackgrndAccess
, NULL
);
1890 XaceRC(XACE_EXT_DISPATCH
, SecurityCheckExtAccess
, NULL
);
1891 XaceRC(XACE_EXT_ACCESS
, SecurityCheckExtAccess
, NULL
);
1892 XaceRC(XACE_HOSTLIST_ACCESS
, SecurityCheckHostlistAccess
, NULL
);
1893 XaceRC(XACE_DECLARE_EXT_SECURE
, SecurityDeclareExtSecure
, NULL
);
1894 } /* SecurityExtensionSetup */
1897 /* SecurityExtensionInit
1904 * Enables the Security extension if possible.
1908 SecurityExtensionInit(INITARGS
)
1910 ExtensionEntry
*extEntry
;
1912 SecurityAuthorizationResType
=
1913 CreateNewResourceType(SecurityDeleteAuthorization
);
1915 RTEventClient
= CreateNewResourceType(
1916 SecurityDeleteAuthorizationEventClient
);
1918 if (!SecurityAuthorizationResType
|| !RTEventClient
)
1921 RTEventClient
|= RC_NEVERRETAIN
;
1923 if (!AddCallback(&ClientStateCallback
, SecurityClientStateCallback
, NULL
))
1926 extEntry
= AddExtension(SECURITY_EXTENSION_NAME
,
1927 XSecurityNumberEvents
, XSecurityNumberErrors
,
1928 ProcSecurityDispatch
, SProcSecurityDispatch
,
1929 SecurityResetProc
, StandardMinorOpcode
);
1931 SecurityErrorBase
= extEntry
->errorBase
;
1932 SecurityEventBase
= extEntry
->eventBase
;
1934 EventSwapVector
[SecurityEventBase
+ XSecurityAuthorizationRevoked
] =
1935 (EventSwapPtr
)SwapSecurityAuthorizationRevokedEvent
;
1937 SecurityLoadPropertyAccessList();
1939 } /* SecurityExtensionInit */