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