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