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