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