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