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