access.c (61046B)
1 /*********************************************************** 2 3 Copyright 1987, 1998 The Open Group 4 5 All rights reserved. 6 7 Permission is hereby granted, free of charge, to any person obtaining a 8 copy of this software and associated documentation files (the 9 "Software"), to deal in the Software without restriction, including 10 without limitation the rights to use, copy, modify, merge, publish, 11 distribute, and/or sell copies of the Software, and to permit persons 12 to whom the Software is furnished to do so, provided that the above 13 copyright notice(s) and this permission notice appear in all copies of 14 the Software and that both the above copyright notice(s) and this 15 permission notice appear in supporting documentation. 16 17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 20 OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 21 HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL 22 INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING 23 FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 24 NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 25 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 26 27 Except as contained in this notice, the name of a copyright holder 28 shall not be used in advertising or otherwise to promote the sale, use 29 or other dealings in this Software without prior written authorization 30 of the copyright holder. 31 32 X Window System is a trademark of The Open Group. 33 34 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. 35 36 All Rights Reserved 37 38 Permission to use, copy, modify, and distribute this software and its 39 documentation for any purpose and without fee is hereby granted, 40 provided that the above copyright notice appear in all copies and that 41 both that copyright notice and this permission notice appear in 42 supporting documentation, and that the name of Digital not be 43 used in advertising or publicity pertaining to distribution of the 44 software without specific, written prior permission. 45 46 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 47 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 48 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 49 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 50 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 51 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 52 SOFTWARE. 53 54 ******************************************************************/ 55 56 /* 57 * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. 58 * 59 * Permission is hereby granted, free of charge, to any person obtaining a 60 * copy of this software and associated documentation files (the "Software"), 61 * to deal in the Software without restriction, including without limitation 62 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 63 * and/or sell copies of the Software, and to permit persons to whom the 64 * Software is furnished to do so, subject to the following conditions: 65 * 66 * The above copyright notice and this permission notice (including the next 67 * paragraph) shall be included in all copies or substantial portions of the 68 * Software. 69 * 70 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 71 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 72 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 73 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 74 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 75 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 76 * DEALINGS IN THE SOFTWARE. 77 */ 78 79 #ifdef HAVE_DIX_CONFIG_H 80 #include <dix-config.h> 81 #endif 82 83 #ifdef WIN32 84 #include <X11/Xwinsock.h> 85 #endif 86 87 #include <stdio.h> 88 #include <stdlib.h> 89 #define XSERV_t 90 #define TRANS_SERVER 91 #define TRANS_REOPEN 92 #include <X11/Xtrans/Xtrans.h> 93 #include <X11/Xauth.h> 94 #include <X11/X.h> 95 #include <X11/Xproto.h> 96 #include "misc.h" 97 #include <errno.h> 98 #include <sys/types.h> 99 #ifndef WIN32 100 #include <sys/socket.h> 101 #include <sys/ioctl.h> 102 #include <ctype.h> 103 104 #ifndef NO_LOCAL_CLIENT_CRED 105 #include <pwd.h> 106 #endif 107 108 #if defined(TCPCONN) 109 #include <netinet/in.h> 110 #endif /* TCPCONN || STREAMSCONN */ 111 112 #ifdef HAVE_GETPEERUCRED 113 #include <ucred.h> 114 #ifdef __sun 115 #include <zone.h> 116 #endif 117 #endif 118 119 #if defined(SVR4) || (defined(SYSV) && defined(__i386__)) || defined(__GNU__) 120 #include <sys/utsname.h> 121 #endif 122 #if defined(SYSV) && defined(__i386__) 123 #include <sys/stream.h> 124 #endif 125 #ifdef __GNU__ 126 #undef SIOCGIFCONF 127 #include <netdb.h> 128 #else /*!__GNU__ */ 129 #include <net/if.h> 130 #endif /*__GNU__ */ 131 132 #ifdef SVR4 133 #include <sys/sockio.h> 134 #include <sys/stropts.h> 135 #endif 136 137 #include <netdb.h> 138 139 #ifdef CSRG_BASED 140 #include <sys/param.h> 141 #if (BSD >= 199103) 142 #define VARIABLE_IFREQ 143 #endif 144 #endif 145 146 #ifdef BSD44SOCKETS 147 #ifndef VARIABLE_IFREQ 148 #define VARIABLE_IFREQ 149 #endif 150 #endif 151 152 #ifdef HAVE_GETIFADDRS 153 #include <ifaddrs.h> 154 #endif 155 156 /* Solaris provides an extended interface SIOCGLIFCONF. Other systems 157 * may have this as well, but the code has only been tested on Solaris 158 * so far, so we only enable it there. Other platforms may be added as 159 * needed. 160 * 161 * Test for Solaris commented out -- TSI @ UQV 2003.06.13 162 */ 163 #ifdef SIOCGLIFCONF 164 /* #if defined(__sun) */ 165 #define USE_SIOCGLIFCONF 166 /* #endif */ 167 #endif 168 169 #if defined(IPv6) && defined(AF_INET6) 170 #include <arpa/inet.h> 171 #endif 172 173 #endif /* WIN32 */ 174 175 #if !defined(WIN32) || defined(__CYGWIN__) 176 #include <libgen.h> 177 #endif 178 179 #define X_INCLUDE_NETDB_H 180 #include <X11/Xos_r.h> 181 182 #include "dixstruct.h" 183 #include "osdep.h" 184 185 #include "xace.h" 186 187 Bool defeatAccessControl = FALSE; 188 189 #define addrEqual(fam, address, length, host) \ 190 ((fam) == (host)->family &&\ 191 (length) == (host)->len &&\ 192 !memcmp (address, (host)->addr, length)) 193 194 static int ConvertAddr(struct sockaddr * /*saddr */ , 195 int * /*len */ , 196 void ** /*addr */ ); 197 198 static int CheckAddr(int /*family */ , 199 const void * /*pAddr */ , 200 unsigned /*length */ ); 201 202 static Bool NewHost(int /*family */ , 203 const void * /*addr */ , 204 int /*len */ , 205 int /* addingLocalHosts */ ); 206 207 /* XFree86 bug #156: To keep track of which hosts were explicitly requested in 208 /etc/X<display>.hosts, we've added a requested field to the HOST struct, 209 and a LocalHostRequested variable. These default to FALSE, but are set 210 to TRUE in ResetHosts when reading in /etc/X<display>.hosts. They are 211 checked in DisableLocalHost(), which is called to disable the default 212 local host entries when stronger authentication is turned on. */ 213 214 typedef struct _host { 215 short family; 216 short len; 217 unsigned char *addr; 218 struct _host *next; 219 int requested; 220 } HOST; 221 222 #define MakeHost(h,l) (h)=malloc(sizeof *(h)+(l));\ 223 if (h) { \ 224 (h)->addr=(unsigned char *) ((h) + 1);\ 225 (h)->requested = FALSE; \ 226 } 227 #define FreeHost(h) free(h) 228 static HOST *selfhosts = NULL; 229 static HOST *validhosts = NULL; 230 static int AccessEnabled = TRUE; 231 static int LocalHostEnabled = FALSE; 232 static int LocalHostRequested = FALSE; 233 static int UsingXdmcp = FALSE; 234 235 static enum { 236 LOCAL_ACCESS_SCOPE_HOST = 0, 237 #ifndef NO_LOCAL_CLIENT_CRED 238 LOCAL_ACCESS_SCOPE_USER, 239 #endif 240 } LocalAccessScope; 241 242 /* FamilyServerInterpreted implementation */ 243 static Bool siAddrMatch(int family, void *addr, int len, HOST * host, 244 ClientPtr client); 245 static int siCheckAddr(const char *addrString, int length); 246 static void siTypesInitialize(void); 247 248 /* 249 * called when authorization is not enabled to add the 250 * local host to the access list 251 */ 252 253 void 254 EnableLocalAccess(void) 255 { 256 switch (LocalAccessScope) { 257 case LOCAL_ACCESS_SCOPE_HOST: 258 EnableLocalHost(); 259 break; 260 #ifndef NO_LOCAL_CLIENT_CRED 261 case LOCAL_ACCESS_SCOPE_USER: 262 EnableLocalUser(); 263 break; 264 #endif 265 } 266 } 267 268 void 269 EnableLocalHost(void) 270 { 271 if (!UsingXdmcp) { 272 LocalHostEnabled = TRUE; 273 AddLocalHosts(); 274 } 275 } 276 277 /* 278 * called when authorization is enabled to keep us secure 279 */ 280 void 281 DisableLocalAccess(void) 282 { 283 switch (LocalAccessScope) { 284 case LOCAL_ACCESS_SCOPE_HOST: 285 DisableLocalHost(); 286 break; 287 #ifndef NO_LOCAL_CLIENT_CRED 288 case LOCAL_ACCESS_SCOPE_USER: 289 DisableLocalUser(); 290 break; 291 #endif 292 } 293 } 294 295 void 296 DisableLocalHost(void) 297 { 298 HOST *self; 299 300 if (!LocalHostRequested) /* Fix for XFree86 bug #156 */ 301 LocalHostEnabled = FALSE; 302 for (self = selfhosts; self; self = self->next) { 303 if (!self->requested) /* Fix for XFree86 bug #156 */ 304 (void) RemoveHost((ClientPtr) NULL, self->family, self->len, 305 (void *) self->addr); 306 } 307 } 308 309 #ifndef NO_LOCAL_CLIENT_CRED 310 static int GetLocalUserAddr(char **addr) 311 { 312 static const char *type = "localuser"; 313 static const char delimiter = '\0'; 314 static const char *value; 315 struct passwd *pw; 316 int length = -1; 317 318 pw = getpwuid(getuid()); 319 320 if (pw == NULL || pw->pw_name == NULL) 321 goto out; 322 323 value = pw->pw_name; 324 325 length = asprintf(addr, "%s%c%s", type, delimiter, value); 326 327 if (length == -1) { 328 goto out; 329 } 330 331 /* Trailing NUL */ 332 length++; 333 334 out: 335 return length; 336 } 337 338 void 339 EnableLocalUser(void) 340 { 341 char *addr = NULL; 342 int length = -1; 343 344 length = GetLocalUserAddr(&addr); 345 346 if (length == -1) 347 return; 348 349 NewHost(FamilyServerInterpreted, addr, length, TRUE); 350 351 free(addr); 352 } 353 354 void 355 DisableLocalUser(void) 356 { 357 char *addr = NULL; 358 int length = -1; 359 360 length = GetLocalUserAddr(&addr); 361 362 if (length == -1) 363 return; 364 365 RemoveHost(NULL, FamilyServerInterpreted, length, addr); 366 367 free(addr); 368 } 369 370 void 371 LocalAccessScopeUser(void) 372 { 373 LocalAccessScope = LOCAL_ACCESS_SCOPE_USER; 374 } 375 #endif 376 377 /* 378 * called at init time when XDMCP will be used; xdmcp always 379 * adds local hosts manually when needed 380 */ 381 382 void 383 AccessUsingXdmcp(void) 384 { 385 UsingXdmcp = TRUE; 386 LocalHostEnabled = FALSE; 387 } 388 389 #if defined(SVR4) && !defined(__sun) && defined(SIOCGIFCONF) && !defined(USE_SIOCGLIFCONF) 390 391 /* Deal with different SIOCGIFCONF ioctl semantics on these OSs */ 392 393 static int 394 ifioctl(int fd, int cmd, char *arg) 395 { 396 struct strioctl ioc; 397 int ret; 398 399 memset((char *) &ioc, 0, sizeof(ioc)); 400 ioc.ic_cmd = cmd; 401 ioc.ic_timout = 0; 402 if (cmd == SIOCGIFCONF) { 403 ioc.ic_len = ((struct ifconf *) arg)->ifc_len; 404 ioc.ic_dp = ((struct ifconf *) arg)->ifc_buf; 405 } 406 else { 407 ioc.ic_len = sizeof(struct ifreq); 408 ioc.ic_dp = arg; 409 } 410 ret = ioctl(fd, I_STR, (char *) &ioc); 411 if (ret >= 0 && cmd == SIOCGIFCONF) 412 #ifdef SVR4 413 ((struct ifconf *) arg)->ifc_len = ioc.ic_len; 414 #endif 415 return ret; 416 } 417 #else 418 #define ifioctl ioctl 419 #endif 420 421 /* 422 * DefineSelf (fd): 423 * 424 * Define this host for access control. Find all the hosts the OS knows about 425 * for this fd and add them to the selfhosts list. 426 */ 427 428 #if !defined(SIOCGIFCONF) 429 void 430 DefineSelf(int fd) 431 { 432 #if !defined(TCPCONN) && !defined(UNIXCONN) 433 return; 434 #else 435 register int n; 436 int len; 437 caddr_t addr; 438 int family; 439 register HOST *host; 440 441 #ifndef WIN32 442 struct utsname name; 443 #else 444 struct { 445 char nodename[512]; 446 } name; 447 #endif 448 449 register struct hostent *hp; 450 451 union { 452 struct sockaddr sa; 453 struct sockaddr_in in; 454 #if defined(IPv6) && defined(AF_INET6) 455 struct sockaddr_in6 in6; 456 #endif 457 } saddr; 458 459 struct sockaddr_in *inetaddr; 460 struct sockaddr_in6 *inet6addr; 461 struct sockaddr_in broad_addr; 462 463 #ifdef XTHREADS_NEEDS_BYNAMEPARAMS 464 _Xgethostbynameparams hparams; 465 #endif 466 467 /* Why not use gethostname()? Well, at least on my system, I've had to 468 * make an ugly kernel patch to get a name longer than 8 characters, and 469 * uname() lets me access to the whole string (it smashes release, you 470 * see), whereas gethostname() kindly truncates it for me. 471 */ 472 #ifndef WIN32 473 uname(&name); 474 #else 475 gethostname(name.nodename, sizeof(name.nodename)); 476 #endif 477 478 hp = _XGethostbyname(name.nodename, hparams); 479 if (hp != NULL) { 480 saddr.sa.sa_family = hp->h_addrtype; 481 switch (hp->h_addrtype) { 482 case AF_INET: 483 inetaddr = (struct sockaddr_in *) (&(saddr.sa)); 484 memcpy(&(inetaddr->sin_addr), hp->h_addr, hp->h_length); 485 len = sizeof(saddr.sa); 486 break; 487 #if defined(IPv6) && defined(AF_INET6) 488 case AF_INET6: 489 inet6addr = (struct sockaddr_in6 *) (&(saddr.sa)); 490 memcpy(&(inet6addr->sin6_addr), hp->h_addr, hp->h_length); 491 len = sizeof(saddr.in6); 492 break; 493 #endif 494 default: 495 goto DefineLocalHost; 496 } 497 family = ConvertAddr(&(saddr.sa), &len, (void **) &addr); 498 if (family != -1 && family != FamilyLocal) { 499 for (host = selfhosts; 500 host && !addrEqual(family, addr, len, host); 501 host = host->next); 502 if (!host) { 503 /* add this host to the host list. */ 504 MakeHost(host, len) 505 if (host) { 506 host->family = family; 507 host->len = len; 508 memcpy(host->addr, addr, len); 509 host->next = selfhosts; 510 selfhosts = host; 511 } 512 #ifdef XDMCP 513 /* 514 * If this is an Internet Address, but not the localhost 515 * address (127.0.0.1), nor the bogus address (0.0.0.0), 516 * register it. 517 */ 518 if (family == FamilyInternet && 519 !(len == 4 && 520 ((addr[0] == 127) || 521 (addr[0] == 0 && addr[1] == 0 && 522 addr[2] == 0 && addr[3] == 0))) 523 ) { 524 XdmcpRegisterConnection(family, (char *) addr, len); 525 broad_addr = *inetaddr; 526 ((struct sockaddr_in *) &broad_addr)->sin_addr.s_addr = 527 htonl(INADDR_BROADCAST); 528 XdmcpRegisterBroadcastAddress((struct sockaddr_in *) 529 &broad_addr); 530 } 531 #if defined(IPv6) && defined(AF_INET6) 532 else if (family == FamilyInternet6 && 533 !(IN6_IS_ADDR_LOOPBACK((struct in6_addr *) addr))) { 534 XdmcpRegisterConnection(family, (char *) addr, len); 535 } 536 #endif 537 538 #endif /* XDMCP */ 539 } 540 } 541 } 542 /* 543 * now add a host of family FamilyLocalHost... 544 */ 545 DefineLocalHost: 546 for (host = selfhosts; 547 host && !addrEqual(FamilyLocalHost, "", 0, host); host = host->next); 548 if (!host) { 549 MakeHost(host, 0); 550 if (host) { 551 host->family = FamilyLocalHost; 552 host->len = 0; 553 /* Nothing to store in host->addr */ 554 host->next = selfhosts; 555 selfhosts = host; 556 } 557 } 558 #endif /* !TCPCONN && !STREAMSCONN && !UNIXCONN */ 559 } 560 561 #else 562 563 #ifdef USE_SIOCGLIFCONF 564 #define ifr_type struct lifreq 565 #else 566 #define ifr_type struct ifreq 567 #endif 568 569 #ifdef VARIABLE_IFREQ 570 #define ifr_size(p) (sizeof (struct ifreq) + \ 571 (p->ifr_addr.sa_len > sizeof (p->ifr_addr) ? \ 572 p->ifr_addr.sa_len - sizeof (p->ifr_addr) : 0)) 573 #define ifraddr_size(a) (a.sa_len) 574 #else 575 #define ifr_size(p) (sizeof (ifr_type)) 576 #define ifraddr_size(a) (sizeof (a)) 577 #endif 578 579 #if defined(IPv6) && defined(AF_INET6) 580 static void 581 in6_fillscopeid(struct sockaddr_in6 *sin6) 582 { 583 #if defined(__KAME__) 584 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) && sin6->sin6_scope_id == 0) { 585 sin6->sin6_scope_id = 586 ntohs(*(u_int16_t *) &sin6->sin6_addr.s6_addr[2]); 587 sin6->sin6_addr.s6_addr[2] = sin6->sin6_addr.s6_addr[3] = 0; 588 } 589 #endif 590 } 591 #endif 592 593 void 594 DefineSelf(int fd) 595 { 596 #ifndef HAVE_GETIFADDRS 597 char *cp, *cplim; 598 599 #ifdef USE_SIOCGLIFCONF 600 struct sockaddr_storage buf[16]; 601 struct lifconf ifc; 602 register struct lifreq *ifr; 603 604 #ifdef SIOCGLIFNUM 605 struct lifnum ifn; 606 #endif 607 #else /* !USE_SIOCGLIFCONF */ 608 char buf[2048]; 609 struct ifconf ifc; 610 register struct ifreq *ifr; 611 #endif 612 void *bufptr = buf; 613 #else /* HAVE_GETIFADDRS */ 614 struct ifaddrs *ifap, *ifr; 615 #endif 616 int len; 617 unsigned char *addr; 618 int family; 619 register HOST *host; 620 621 #ifndef HAVE_GETIFADDRS 622 623 len = sizeof(buf); 624 625 #ifdef USE_SIOCGLIFCONF 626 627 #ifdef SIOCGLIFNUM 628 ifn.lifn_family = AF_UNSPEC; 629 ifn.lifn_flags = 0; 630 if (ioctl(fd, SIOCGLIFNUM, (char *) &ifn) < 0) 631 ErrorF("Getting interface count: %s\n", strerror(errno)); 632 if (len < (ifn.lifn_count * sizeof(struct lifreq))) { 633 len = ifn.lifn_count * sizeof(struct lifreq); 634 bufptr = malloc(len); 635 } 636 #endif 637 638 ifc.lifc_family = AF_UNSPEC; 639 ifc.lifc_flags = 0; 640 ifc.lifc_len = len; 641 ifc.lifc_buf = bufptr; 642 643 #define IFC_IOCTL_REQ SIOCGLIFCONF 644 #define IFC_IFC_REQ ifc.lifc_req 645 #define IFC_IFC_LEN ifc.lifc_len 646 #define IFR_IFR_ADDR ifr->lifr_addr 647 #define IFR_IFR_NAME ifr->lifr_name 648 649 #else /* Use SIOCGIFCONF */ 650 ifc.ifc_len = len; 651 ifc.ifc_buf = bufptr; 652 653 #define IFC_IOCTL_REQ SIOCGIFCONF 654 #define IFC_IFC_REQ ifc.ifc_req 655 #define IFC_IFC_LEN ifc.ifc_len 656 #define IFR_IFR_ADDR ifr->ifr_addr 657 #define IFR_IFR_NAME ifr->ifr_name 658 #endif 659 660 if (ifioctl(fd, IFC_IOCTL_REQ, (void *) &ifc) < 0) 661 ErrorF("Getting interface configuration (4): %s\n", strerror(errno)); 662 663 cplim = (char *) IFC_IFC_REQ + IFC_IFC_LEN; 664 665 for (cp = (char *) IFC_IFC_REQ; cp < cplim; cp += ifr_size(ifr)) { 666 ifr = (ifr_type *) cp; 667 len = ifraddr_size(IFR_IFR_ADDR); 668 family = ConvertAddr((struct sockaddr *) &IFR_IFR_ADDR, 669 &len, (void **) &addr); 670 if (family == -1 || family == FamilyLocal) 671 continue; 672 #if defined(IPv6) && defined(AF_INET6) 673 if (family == FamilyInternet6) 674 in6_fillscopeid((struct sockaddr_in6 *) &IFR_IFR_ADDR); 675 #endif 676 for (host = selfhosts; 677 host && !addrEqual(family, addr, len, host); host = host->next); 678 if (host) 679 continue; 680 MakeHost(host, len) 681 if (host) { 682 host->family = family; 683 host->len = len; 684 memcpy(host->addr, addr, len); 685 host->next = selfhosts; 686 selfhosts = host; 687 } 688 #ifdef XDMCP 689 { 690 #ifdef USE_SIOCGLIFCONF 691 struct sockaddr_storage broad_addr; 692 #else 693 struct sockaddr broad_addr; 694 #endif 695 696 /* 697 * If this isn't an Internet Address, don't register it. 698 */ 699 if (family != FamilyInternet 700 #if defined(IPv6) && defined(AF_INET6) 701 && family != FamilyInternet6 702 #endif 703 ) 704 continue; 705 706 /* 707 * ignore 'localhost' entries as they're not useful 708 * on the other end of the wire 709 */ 710 if (family == FamilyInternet && 711 addr[0] == 127 && addr[1] == 0 && addr[2] == 0 && addr[3] == 1) 712 continue; 713 #if defined(IPv6) && defined(AF_INET6) 714 else if (family == FamilyInternet6 && 715 IN6_IS_ADDR_LOOPBACK((struct in6_addr *) addr)) 716 continue; 717 #endif 718 719 /* 720 * Ignore '0.0.0.0' entries as they are 721 * returned by some OSes for unconfigured NICs but they are 722 * not useful on the other end of the wire. 723 */ 724 if (len == 4 && 725 addr[0] == 0 && addr[1] == 0 && addr[2] == 0 && addr[3] == 0) 726 continue; 727 728 XdmcpRegisterConnection(family, (char *) addr, len); 729 730 #if defined(IPv6) && defined(AF_INET6) 731 /* IPv6 doesn't support broadcasting, so we drop out here */ 732 if (family == FamilyInternet6) 733 continue; 734 #endif 735 736 broad_addr = IFR_IFR_ADDR; 737 738 ((struct sockaddr_in *) &broad_addr)->sin_addr.s_addr = 739 htonl(INADDR_BROADCAST); 740 #if defined(USE_SIOCGLIFCONF) && defined(SIOCGLIFBRDADDR) 741 { 742 struct lifreq broad_req; 743 744 broad_req = *ifr; 745 if (ioctl(fd, SIOCGLIFFLAGS, (char *) &broad_req) != -1 && 746 (broad_req.lifr_flags & IFF_BROADCAST) && 747 (broad_req.lifr_flags & IFF_UP) 748 ) { 749 broad_req = *ifr; 750 if (ioctl(fd, SIOCGLIFBRDADDR, &broad_req) != -1) 751 broad_addr = broad_req.lifr_broadaddr; 752 else 753 continue; 754 } 755 else 756 continue; 757 } 758 759 #elif defined(SIOCGIFBRDADDR) 760 { 761 struct ifreq broad_req; 762 763 broad_req = *ifr; 764 if (ifioctl(fd, SIOCGIFFLAGS, (void *) &broad_req) != -1 && 765 (broad_req.ifr_flags & IFF_BROADCAST) && 766 (broad_req.ifr_flags & IFF_UP) 767 ) { 768 broad_req = *ifr; 769 if (ifioctl(fd, SIOCGIFBRDADDR, (void *) &broad_req) != -1) 770 broad_addr = broad_req.ifr_addr; 771 else 772 continue; 773 } 774 else 775 continue; 776 } 777 #endif /* SIOCGIFBRDADDR */ 778 XdmcpRegisterBroadcastAddress((struct sockaddr_in *) &broad_addr); 779 } 780 #endif /* XDMCP */ 781 } 782 if (bufptr != buf) 783 free(bufptr); 784 #else /* HAVE_GETIFADDRS */ 785 if (getifaddrs(&ifap) < 0) { 786 ErrorF("Warning: getifaddrs returns %s\n", strerror(errno)); 787 return; 788 } 789 for (ifr = ifap; ifr != NULL; ifr = ifr->ifa_next) { 790 if (!ifr->ifa_addr) 791 continue; 792 len = sizeof(*(ifr->ifa_addr)); 793 family = ConvertAddr((struct sockaddr *) ifr->ifa_addr, &len, 794 (void **) &addr); 795 if (family == -1 || family == FamilyLocal) 796 continue; 797 #if defined(IPv6) && defined(AF_INET6) 798 if (family == FamilyInternet6) 799 in6_fillscopeid((struct sockaddr_in6 *) ifr->ifa_addr); 800 #endif 801 802 for (host = selfhosts; 803 host != NULL && !addrEqual(family, addr, len, host); 804 host = host->next); 805 if (host != NULL) 806 continue; 807 MakeHost(host, len); 808 if (host != NULL) { 809 host->family = family; 810 host->len = len; 811 memcpy(host->addr, addr, len); 812 host->next = selfhosts; 813 selfhosts = host; 814 } 815 #ifdef XDMCP 816 { 817 /* 818 * If this isn't an Internet Address, don't register it. 819 */ 820 if (family != FamilyInternet 821 #if defined(IPv6) && defined(AF_INET6) 822 && family != FamilyInternet6 823 #endif 824 ) 825 continue; 826 827 /* 828 * ignore 'localhost' entries as they're not useful 829 * on the other end of the wire 830 */ 831 if (ifr->ifa_flags & IFF_LOOPBACK) 832 continue; 833 834 if (family == FamilyInternet && 835 addr[0] == 127 && addr[1] == 0 && addr[2] == 0 && addr[3] == 1) 836 continue; 837 838 /* 839 * Ignore '0.0.0.0' entries as they are 840 * returned by some OSes for unconfigured NICs but they are 841 * not useful on the other end of the wire. 842 */ 843 if (len == 4 && 844 addr[0] == 0 && addr[1] == 0 && addr[2] == 0 && addr[3] == 0) 845 continue; 846 #if defined(IPv6) && defined(AF_INET6) 847 else if (family == FamilyInternet6 && 848 IN6_IS_ADDR_LOOPBACK((struct in6_addr *) addr)) 849 continue; 850 #endif 851 XdmcpRegisterConnection(family, (char *) addr, len); 852 #if defined(IPv6) && defined(AF_INET6) 853 if (family == FamilyInternet6) 854 /* IPv6 doesn't support broadcasting, so we drop out here */ 855 continue; 856 #endif 857 if ((ifr->ifa_flags & IFF_BROADCAST) && 858 (ifr->ifa_flags & IFF_UP) && ifr->ifa_broadaddr) 859 XdmcpRegisterBroadcastAddress((struct sockaddr_in *) ifr-> 860 ifa_broadaddr); 861 else 862 continue; 863 } 864 #endif /* XDMCP */ 865 866 } /* for */ 867 freeifaddrs(ifap); 868 #endif /* HAVE_GETIFADDRS */ 869 870 /* 871 * add something of FamilyLocalHost 872 */ 873 for (host = selfhosts; 874 host && !addrEqual(FamilyLocalHost, "", 0, host); host = host->next); 875 if (!host) { 876 MakeHost(host, 0); 877 if (host) { 878 host->family = FamilyLocalHost; 879 host->len = 0; 880 /* Nothing to store in host->addr */ 881 host->next = selfhosts; 882 selfhosts = host; 883 } 884 } 885 } 886 #endif /* hpux && !HAVE_IFREQ */ 887 888 #ifdef XDMCP 889 void 890 AugmentSelf(void *from, int len) 891 { 892 int family; 893 void *addr; 894 register HOST *host; 895 896 family = ConvertAddr(from, &len, (void **) &addr); 897 if (family == -1 || family == FamilyLocal) 898 return; 899 for (host = selfhosts; host; host = host->next) { 900 if (addrEqual(family, addr, len, host)) 901 return; 902 } 903 MakeHost(host, len) 904 if (!host) 905 return; 906 host->family = family; 907 host->len = len; 908 memcpy(host->addr, addr, len); 909 host->next = selfhosts; 910 selfhosts = host; 911 } 912 #endif 913 914 void 915 AddLocalHosts(void) 916 { 917 HOST *self; 918 919 for (self = selfhosts; self; self = self->next) 920 /* Fix for XFree86 bug #156: pass addingLocal = TRUE to 921 * NewHost to tell that we are adding the default local 922 * host entries and not to flag the entries as being 923 * explicitly requested */ 924 (void) NewHost(self->family, self->addr, self->len, TRUE); 925 } 926 927 /* Reset access control list to initial hosts */ 928 void 929 ResetHosts(const char *display) 930 { 931 register HOST *host; 932 char lhostname[120], ohostname[120]; 933 char *hostname = ohostname; 934 char fname[PATH_MAX + 1]; 935 int fnamelen; 936 FILE *fd; 937 char *ptr; 938 int i, hostlen; 939 940 #if defined(TCPCONN) && (!defined(IPv6) || !defined(AF_INET6)) 941 union { 942 struct sockaddr sa; 943 #if defined(TCPCONN) 944 struct sockaddr_in in; 945 #endif /* TCPCONN || STREAMSCONN */ 946 } saddr; 947 #endif 948 int family = 0; 949 void *addr = NULL; 950 int len; 951 952 siTypesInitialize(); 953 AccessEnabled = !defeatAccessControl; 954 LocalHostEnabled = FALSE; 955 while ((host = validhosts) != 0) { 956 validhosts = host->next; 957 FreeHost(host); 958 } 959 960 #if defined WIN32 && defined __MINGW32__ 961 #define ETC_HOST_PREFIX "X" 962 #else 963 #define ETC_HOST_PREFIX "/etc/X" 964 #endif 965 #define ETC_HOST_SUFFIX ".hosts" 966 fnamelen = strlen(ETC_HOST_PREFIX) + strlen(ETC_HOST_SUFFIX) + 967 strlen(display) + 1; 968 if (fnamelen > sizeof(fname)) 969 FatalError("Display name `%s' is too long\n", display); 970 snprintf(fname, sizeof(fname), ETC_HOST_PREFIX "%s" ETC_HOST_SUFFIX, 971 display); 972 973 if ((fd = fopen(fname, "r")) != 0) { 974 while (fgets(ohostname, sizeof(ohostname), fd)) { 975 family = FamilyWild; 976 if (*ohostname == '#') 977 continue; 978 if ((ptr = strchr(ohostname, '\n')) != 0) 979 *ptr = 0; 980 hostlen = strlen(ohostname) + 1; 981 for (i = 0; i < hostlen; i++) 982 lhostname[i] = tolower(ohostname[i]); 983 hostname = ohostname; 984 if (!strncmp("local:", lhostname, 6)) { 985 family = FamilyLocalHost; 986 NewHost(family, "", 0, FALSE); 987 LocalHostRequested = TRUE; /* Fix for XFree86 bug #156 */ 988 } 989 #if defined(TCPCONN) 990 else if (!strncmp("inet:", lhostname, 5)) { 991 family = FamilyInternet; 992 hostname = ohostname + 5; 993 } 994 #if defined(IPv6) && defined(AF_INET6) 995 else if (!strncmp("inet6:", lhostname, 6)) { 996 family = FamilyInternet6; 997 hostname = ohostname + 6; 998 } 999 #endif 1000 #endif 1001 #ifdef SECURE_RPC 1002 else if (!strncmp("nis:", lhostname, 4)) { 1003 family = FamilyNetname; 1004 hostname = ohostname + 4; 1005 } 1006 #endif 1007 else if (!strncmp("si:", lhostname, 3)) { 1008 family = FamilyServerInterpreted; 1009 hostname = ohostname + 3; 1010 hostlen -= 3; 1011 } 1012 1013 if (family == FamilyServerInterpreted) { 1014 len = siCheckAddr(hostname, hostlen); 1015 if (len >= 0) { 1016 NewHost(family, hostname, len, FALSE); 1017 } 1018 } 1019 else 1020 #ifdef SECURE_RPC 1021 if ((family == FamilyNetname) || (strchr(hostname, '@'))) { 1022 SecureRPCInit(); 1023 (void) NewHost(FamilyNetname, hostname, strlen(hostname), 1024 FALSE); 1025 } 1026 else 1027 #endif /* SECURE_RPC */ 1028 #if defined(TCPCONN) 1029 { 1030 #if defined(IPv6) && defined(AF_INET6) 1031 if ((family == FamilyInternet) || (family == FamilyInternet6) || 1032 (family == FamilyWild)) { 1033 struct addrinfo *addresses; 1034 struct addrinfo *a; 1035 int f; 1036 1037 if (getaddrinfo(hostname, NULL, NULL, &addresses) == 0) { 1038 for (a = addresses; a != NULL; a = a->ai_next) { 1039 len = a->ai_addrlen; 1040 f = ConvertAddr(a->ai_addr, &len, 1041 (void **) &addr); 1042 if (addr && ((family == f) || 1043 ((family == FamilyWild) && (f != -1)))) { 1044 NewHost(f, addr, len, FALSE); 1045 } 1046 } 1047 freeaddrinfo(addresses); 1048 } 1049 } 1050 #else 1051 #ifdef XTHREADS_NEEDS_BYNAMEPARAMS 1052 _Xgethostbynameparams hparams; 1053 #endif 1054 register struct hostent *hp; 1055 1056 /* host name */ 1057 if ((family == FamilyInternet && 1058 ((hp = _XGethostbyname(hostname, hparams)) != 0)) || 1059 ((hp = _XGethostbyname(hostname, hparams)) != 0)) { 1060 saddr.sa.sa_family = hp->h_addrtype; 1061 len = sizeof(saddr.sa); 1062 if ((family = 1063 ConvertAddr(&saddr.sa, &len, 1064 (void **) &addr)) != -1) { 1065 #ifdef h_addr /* new 4.3bsd version of gethostent */ 1066 char **list; 1067 1068 /* iterate over the addresses */ 1069 for (list = hp->h_addr_list; *list; list++) 1070 (void) NewHost(family, (void *) *list, len, FALSE); 1071 #else 1072 (void) NewHost(family, (void *) hp->h_addr, len, 1073 FALSE); 1074 #endif 1075 } 1076 } 1077 #endif /* IPv6 */ 1078 } 1079 #endif /* TCPCONN || STREAMSCONN */ 1080 family = FamilyWild; 1081 } 1082 fclose(fd); 1083 } 1084 } 1085 1086 static Bool 1087 xtransLocalClient(ClientPtr client) 1088 { 1089 int alen, family, notused; 1090 Xtransaddr *from = NULL; 1091 void *addr; 1092 register HOST *host; 1093 OsCommPtr oc = (OsCommPtr) client->osPrivate; 1094 1095 if (!oc->trans_conn) 1096 return FALSE; 1097 1098 if (!_XSERVTransGetPeerAddr(oc->trans_conn, ¬used, &alen, &from)) { 1099 family = ConvertAddr((struct sockaddr *) from, 1100 &alen, (void **) &addr); 1101 if (family == -1) { 1102 free(from); 1103 return FALSE; 1104 } 1105 if (family == FamilyLocal) { 1106 free(from); 1107 return TRUE; 1108 } 1109 for (host = selfhosts; host; host = host->next) { 1110 if (addrEqual(family, addr, alen, host)) { 1111 free(from); 1112 return TRUE; 1113 } 1114 } 1115 free(from); 1116 } 1117 return FALSE; 1118 } 1119 1120 /* Is client on the local host */ 1121 Bool 1122 ComputeLocalClient(ClientPtr client) 1123 { 1124 const char *cmdname = GetClientCmdName(client); 1125 1126 if (!xtransLocalClient(client)) 1127 return FALSE; 1128 1129 /* If the executable name is "ssh", assume that this client connection 1130 * is forwarded from another host via SSH 1131 */ 1132 if (cmdname) { 1133 char *cmd = strdup(cmdname); 1134 Bool ret; 1135 1136 /* Cut off any colon and whatever comes after it, see 1137 * https://lists.freedesktop.org/archives/xorg-devel/2015-December/048164.html 1138 */ 1139 char *tok = strtok(cmd, ":"); 1140 1141 #if !defined(WIN32) || defined(__CYGWIN__) 1142 ret = strcmp(basename(tok), "ssh") != 0; 1143 #else 1144 ret = strcmp(tok, "ssh") != 0; 1145 #endif 1146 1147 free(cmd); 1148 1149 return ret; 1150 } 1151 1152 return TRUE; 1153 } 1154 1155 /* 1156 * Return the uid and all gids of a connected local client 1157 * Allocates a LocalClientCredRec - caller must call FreeLocalClientCreds 1158 * 1159 * Used by localuser & localgroup ServerInterpreted access control forms below 1160 * Used by AuthAudit to log who local connections came from 1161 */ 1162 int 1163 GetLocalClientCreds(ClientPtr client, LocalClientCredRec ** lccp) 1164 { 1165 #if defined(HAVE_GETPEEREID) || defined(HAVE_GETPEERUCRED) || defined(SO_PEERCRED) 1166 int fd; 1167 XtransConnInfo ci; 1168 LocalClientCredRec *lcc; 1169 1170 #ifdef HAVE_GETPEEREID 1171 uid_t uid; 1172 gid_t gid; 1173 #elif defined(HAVE_GETPEERUCRED) 1174 ucred_t *peercred = NULL; 1175 const gid_t *gids; 1176 #elif defined(SO_PEERCRED) 1177 struct ucred peercred; 1178 socklen_t so_len = sizeof(peercred); 1179 #endif 1180 1181 if (client == NULL) 1182 return -1; 1183 ci = ((OsCommPtr) client->osPrivate)->trans_conn; 1184 #if !(defined(__sun) && defined(HAVE_GETPEERUCRED)) 1185 /* Most implementations can only determine peer credentials for Unix 1186 * domain sockets - Solaris getpeerucred can work with a bit more, so 1187 * we just let it tell us if the connection type is supported or not 1188 */ 1189 if (!_XSERVTransIsLocal(ci)) { 1190 return -1; 1191 } 1192 #endif 1193 1194 *lccp = calloc(1, sizeof(LocalClientCredRec)); 1195 if (*lccp == NULL) 1196 return -1; 1197 lcc = *lccp; 1198 1199 fd = _XSERVTransGetConnectionNumber(ci); 1200 #ifdef HAVE_GETPEEREID 1201 if (getpeereid(fd, &uid, &gid) == -1) { 1202 FreeLocalClientCreds(lcc); 1203 return -1; 1204 } 1205 lcc->euid = uid; 1206 lcc->egid = gid; 1207 lcc->fieldsSet = LCC_UID_SET | LCC_GID_SET; 1208 return 0; 1209 #elif defined(HAVE_GETPEERUCRED) 1210 if (getpeerucred(fd, &peercred) < 0) { 1211 FreeLocalClientCreds(lcc); 1212 return -1; 1213 } 1214 lcc->euid = ucred_geteuid(peercred); 1215 if (lcc->euid != -1) 1216 lcc->fieldsSet |= LCC_UID_SET; 1217 lcc->egid = ucred_getegid(peercred); 1218 if (lcc->egid != -1) 1219 lcc->fieldsSet |= LCC_GID_SET; 1220 lcc->pid = ucred_getpid(peercred); 1221 if (lcc->pid != -1) 1222 lcc->fieldsSet |= LCC_PID_SET; 1223 #ifdef HAVE_GETZONEID 1224 lcc->zoneid = ucred_getzoneid(peercred); 1225 if (lcc->zoneid != -1) 1226 lcc->fieldsSet |= LCC_ZID_SET; 1227 #endif 1228 lcc->nSuppGids = ucred_getgroups(peercred, &gids); 1229 if (lcc->nSuppGids > 0) { 1230 lcc->pSuppGids = calloc(lcc->nSuppGids, sizeof(int)); 1231 if (lcc->pSuppGids == NULL) { 1232 lcc->nSuppGids = 0; 1233 } 1234 else { 1235 int i; 1236 1237 for (i = 0; i < lcc->nSuppGids; i++) { 1238 (lcc->pSuppGids)[i] = (int) gids[i]; 1239 } 1240 } 1241 } 1242 else { 1243 lcc->nSuppGids = 0; 1244 } 1245 ucred_free(peercred); 1246 return 0; 1247 #elif defined(SO_PEERCRED) 1248 if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) == -1) { 1249 FreeLocalClientCreds(lcc); 1250 return -1; 1251 } 1252 lcc->euid = peercred.uid; 1253 lcc->egid = peercred.gid; 1254 lcc->pid = peercred.pid; 1255 lcc->fieldsSet = LCC_UID_SET | LCC_GID_SET | LCC_PID_SET; 1256 return 0; 1257 #endif 1258 #else 1259 /* No system call available to get the credentials of the peer */ 1260 return -1; 1261 #endif 1262 } 1263 1264 void 1265 FreeLocalClientCreds(LocalClientCredRec * lcc) 1266 { 1267 if (lcc != NULL) { 1268 if (lcc->nSuppGids > 0) { 1269 free(lcc->pSuppGids); 1270 } 1271 free(lcc); 1272 } 1273 } 1274 1275 static int 1276 AuthorizedClient(ClientPtr client) 1277 { 1278 int rc; 1279 1280 if (!client || defeatAccessControl) 1281 return Success; 1282 1283 /* untrusted clients can't change host access */ 1284 rc = XaceHook(XACE_SERVER_ACCESS, client, DixManageAccess); 1285 if (rc != Success) 1286 return rc; 1287 1288 return client->local ? Success : BadAccess; 1289 } 1290 1291 /* Add a host to the access control list. This is the external interface 1292 * called from the dispatcher */ 1293 1294 int 1295 AddHost(ClientPtr client, int family, unsigned length, /* of bytes in pAddr */ 1296 const void *pAddr) 1297 { 1298 int rc, len; 1299 1300 rc = AuthorizedClient(client); 1301 if (rc != Success) 1302 return rc; 1303 switch (family) { 1304 case FamilyLocalHost: 1305 len = length; 1306 LocalHostEnabled = TRUE; 1307 break; 1308 #ifdef SECURE_RPC 1309 case FamilyNetname: 1310 len = length; 1311 SecureRPCInit(); 1312 break; 1313 #endif 1314 case FamilyInternet: 1315 #if defined(IPv6) && defined(AF_INET6) 1316 case FamilyInternet6: 1317 #endif 1318 case FamilyDECnet: 1319 case FamilyChaos: 1320 case FamilyServerInterpreted: 1321 if ((len = CheckAddr(family, pAddr, length)) < 0) { 1322 client->errorValue = length; 1323 return BadValue; 1324 } 1325 break; 1326 case FamilyLocal: 1327 default: 1328 client->errorValue = family; 1329 return BadValue; 1330 } 1331 if (NewHost(family, pAddr, len, FALSE)) 1332 return Success; 1333 return BadAlloc; 1334 } 1335 1336 Bool 1337 ForEachHostInFamily(int family, Bool (*func) (unsigned char *addr, 1338 short len, 1339 void *closure), 1340 void *closure) 1341 { 1342 HOST *host; 1343 1344 for (host = validhosts; host; host = host->next) 1345 if (family == host->family && func(host->addr, host->len, closure)) 1346 return TRUE; 1347 return FALSE; 1348 } 1349 1350 /* Add a host to the access control list. This is the internal interface 1351 * called when starting or resetting the server */ 1352 static Bool 1353 NewHost(int family, const void *addr, int len, int addingLocalHosts) 1354 { 1355 register HOST *host; 1356 1357 for (host = validhosts; host; host = host->next) { 1358 if (addrEqual(family, addr, len, host)) 1359 return TRUE; 1360 } 1361 if (!addingLocalHosts) { /* Fix for XFree86 bug #156 */ 1362 for (host = selfhosts; host; host = host->next) { 1363 if (addrEqual(family, addr, len, host)) { 1364 host->requested = TRUE; 1365 break; 1366 } 1367 } 1368 } 1369 MakeHost(host, len) 1370 if (!host) 1371 return FALSE; 1372 host->family = family; 1373 host->len = len; 1374 memcpy(host->addr, addr, len); 1375 host->next = validhosts; 1376 validhosts = host; 1377 return TRUE; 1378 } 1379 1380 /* Remove a host from the access control list */ 1381 1382 int 1383 RemoveHost(ClientPtr client, int family, unsigned length, /* of bytes in pAddr */ 1384 void *pAddr) 1385 { 1386 int rc, len; 1387 register HOST *host, **prev; 1388 1389 rc = AuthorizedClient(client); 1390 if (rc != Success) 1391 return rc; 1392 switch (family) { 1393 case FamilyLocalHost: 1394 len = length; 1395 LocalHostEnabled = FALSE; 1396 break; 1397 #ifdef SECURE_RPC 1398 case FamilyNetname: 1399 len = length; 1400 break; 1401 #endif 1402 case FamilyInternet: 1403 #if defined(IPv6) && defined(AF_INET6) 1404 case FamilyInternet6: 1405 #endif 1406 case FamilyDECnet: 1407 case FamilyChaos: 1408 case FamilyServerInterpreted: 1409 if ((len = CheckAddr(family, pAddr, length)) < 0) { 1410 client->errorValue = length; 1411 return BadValue; 1412 } 1413 break; 1414 case FamilyLocal: 1415 default: 1416 client->errorValue = family; 1417 return BadValue; 1418 } 1419 for (prev = &validhosts; 1420 (host = *prev) && (!addrEqual(family, pAddr, len, host)); 1421 prev = &host->next); 1422 if (host) { 1423 *prev = host->next; 1424 FreeHost(host); 1425 } 1426 return Success; 1427 } 1428 1429 /* Get all hosts in the access control list */ 1430 int 1431 GetHosts(void **data, int *pnHosts, int *pLen, BOOL * pEnabled) 1432 { 1433 int len; 1434 register int n = 0; 1435 register unsigned char *ptr; 1436 register HOST *host; 1437 int nHosts = 0; 1438 1439 *pEnabled = AccessEnabled ? EnableAccess : DisableAccess; 1440 for (host = validhosts; host; host = host->next) { 1441 nHosts++; 1442 n += pad_to_int32(host->len) + sizeof(xHostEntry); 1443 /* Could check for INT_MAX, but in reality having more than 1mb of 1444 hostnames in the access list is ridiculous */ 1445 if (n >= 1048576) 1446 break; 1447 } 1448 if (n) { 1449 *data = ptr = malloc(n); 1450 if (!ptr) { 1451 return BadAlloc; 1452 } 1453 for (host = validhosts; host; host = host->next) { 1454 len = host->len; 1455 if ((ptr + sizeof(xHostEntry) + len) > ((unsigned char *) *data + n)) 1456 break; 1457 ((xHostEntry *) ptr)->family = host->family; 1458 ((xHostEntry *) ptr)->length = len; 1459 ptr += sizeof(xHostEntry); 1460 memcpy(ptr, host->addr, len); 1461 ptr += pad_to_int32(len); 1462 } 1463 } 1464 else { 1465 *data = NULL; 1466 } 1467 *pnHosts = nHosts; 1468 *pLen = n; 1469 return Success; 1470 } 1471 1472 /* Check for valid address family and length, and return address length. */ 1473 1474 /*ARGSUSED*/ static int 1475 CheckAddr(int family, const void *pAddr, unsigned length) 1476 { 1477 int len; 1478 1479 switch (family) { 1480 #if defined(TCPCONN) 1481 case FamilyInternet: 1482 if (length == sizeof(struct in_addr)) 1483 len = length; 1484 else 1485 len = -1; 1486 break; 1487 #if defined(IPv6) && defined(AF_INET6) 1488 case FamilyInternet6: 1489 if (length == sizeof(struct in6_addr)) 1490 len = length; 1491 else 1492 len = -1; 1493 break; 1494 #endif 1495 #endif 1496 case FamilyServerInterpreted: 1497 len = siCheckAddr(pAddr, length); 1498 break; 1499 default: 1500 len = -1; 1501 } 1502 return len; 1503 } 1504 1505 /* Check if a host is not in the access control list. 1506 * Returns 1 if host is invalid, 0 if we've found it. */ 1507 1508 int 1509 InvalidHost(register struct sockaddr *saddr, int len, ClientPtr client) 1510 { 1511 int family; 1512 void *addr = NULL; 1513 register HOST *selfhost, *host; 1514 1515 if (!AccessEnabled) /* just let them in */ 1516 return 0; 1517 family = ConvertAddr(saddr, &len, (void **) &addr); 1518 if (family == -1) 1519 return 1; 1520 if (family == FamilyLocal) { 1521 if (!LocalHostEnabled) { 1522 /* 1523 * check to see if any local address is enabled. This 1524 * implicitly enables local connections. 1525 */ 1526 for (selfhost = selfhosts; selfhost; selfhost = selfhost->next) { 1527 for (host = validhosts; host; host = host->next) { 1528 if (addrEqual(selfhost->family, selfhost->addr, 1529 selfhost->len, host)) 1530 return 0; 1531 } 1532 } 1533 } 1534 else 1535 return 0; 1536 } 1537 for (host = validhosts; host; host = host->next) { 1538 if (host->family == FamilyServerInterpreted) { 1539 if (siAddrMatch(family, addr, len, host, client)) { 1540 return 0; 1541 } 1542 } 1543 else { 1544 if (addr && addrEqual(family, addr, len, host)) 1545 return 0; 1546 } 1547 1548 } 1549 return 1; 1550 } 1551 1552 static int 1553 ConvertAddr(register struct sockaddr *saddr, int *len, void **addr) 1554 { 1555 if (*len == 0) 1556 return FamilyLocal; 1557 switch (saddr->sa_family) { 1558 case AF_UNSPEC: 1559 #if defined(UNIXCONN) || defined(LOCALCONN) 1560 case AF_UNIX: 1561 #endif 1562 return FamilyLocal; 1563 #if defined(TCPCONN) 1564 case AF_INET: 1565 #ifdef WIN32 1566 if (16777343 == *(long *) &((struct sockaddr_in *) saddr)->sin_addr) 1567 return FamilyLocal; 1568 #endif 1569 *len = sizeof(struct in_addr); 1570 *addr = (void *) &(((struct sockaddr_in *) saddr)->sin_addr); 1571 return FamilyInternet; 1572 #if defined(IPv6) && defined(AF_INET6) 1573 case AF_INET6: 1574 { 1575 struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *) saddr; 1576 1577 if (IN6_IS_ADDR_V4MAPPED(&(saddr6->sin6_addr))) { 1578 *len = sizeof(struct in_addr); 1579 *addr = (void *) &(saddr6->sin6_addr.s6_addr[12]); 1580 return FamilyInternet; 1581 } 1582 else { 1583 *len = sizeof(struct in6_addr); 1584 *addr = (void *) &(saddr6->sin6_addr); 1585 return FamilyInternet6; 1586 } 1587 } 1588 #endif 1589 #endif 1590 default: 1591 return -1; 1592 } 1593 } 1594 1595 int 1596 ChangeAccessControl(ClientPtr client, int fEnabled) 1597 { 1598 int rc = AuthorizedClient(client); 1599 1600 if (rc != Success) 1601 return rc; 1602 AccessEnabled = fEnabled; 1603 return Success; 1604 } 1605 1606 /* returns FALSE if xhost + in effect, else TRUE */ 1607 int 1608 GetAccessControl(void) 1609 { 1610 return AccessEnabled; 1611 } 1612 1613 int 1614 GetClientFd(ClientPtr client) 1615 { 1616 return ((OsCommPtr) client->osPrivate)->fd; 1617 } 1618 1619 Bool 1620 ClientIsLocal(ClientPtr client) 1621 { 1622 XtransConnInfo ci = ((OsCommPtr) client->osPrivate)->trans_conn; 1623 1624 return _XSERVTransIsLocal(ci); 1625 } 1626 1627 /***************************************************************************** 1628 * FamilyServerInterpreted host entry implementation 1629 * 1630 * Supports an extensible system of host types which the server can interpret 1631 * See the IPv6 extensions to the X11 protocol spec for the definition. 1632 * 1633 * Currently supported schemes: 1634 * 1635 * hostname - hostname as defined in IETF RFC 2396 1636 * ipv6 - IPv6 literal address as defined in IETF RFC's 3513 and <TBD> 1637 * 1638 * See xc/doc/specs/SIAddresses for formal definitions of each type. 1639 */ 1640 1641 /* These definitions and the siTypeAdd function could be exported in the 1642 * future to enable loading additional host types, but that was not done for 1643 * the initial implementation. 1644 */ 1645 typedef Bool (*siAddrMatchFunc) (int family, void *addr, int len, 1646 const char *siAddr, int siAddrlen, 1647 ClientPtr client, void *siTypePriv); 1648 typedef int (*siCheckAddrFunc) (const char *addrString, int length, 1649 void *siTypePriv); 1650 1651 struct siType { 1652 struct siType *next; 1653 const char *typeName; 1654 siAddrMatchFunc addrMatch; 1655 siCheckAddrFunc checkAddr; 1656 void *typePriv; /* Private data for type routines */ 1657 }; 1658 1659 static struct siType *siTypeList; 1660 1661 static int 1662 siTypeAdd(const char *typeName, siAddrMatchFunc addrMatch, 1663 siCheckAddrFunc checkAddr, void *typePriv) 1664 { 1665 struct siType *s, *p; 1666 1667 if ((typeName == NULL) || (addrMatch == NULL) || (checkAddr == NULL)) 1668 return BadValue; 1669 1670 for (s = siTypeList, p = NULL; s != NULL; p = s, s = s->next) { 1671 if (strcmp(typeName, s->typeName) == 0) { 1672 s->addrMatch = addrMatch; 1673 s->checkAddr = checkAddr; 1674 s->typePriv = typePriv; 1675 return Success; 1676 } 1677 } 1678 1679 s = malloc(sizeof(struct siType)); 1680 if (s == NULL) 1681 return BadAlloc; 1682 1683 if (p == NULL) 1684 siTypeList = s; 1685 else 1686 p->next = s; 1687 1688 s->next = NULL; 1689 s->typeName = typeName; 1690 s->addrMatch = addrMatch; 1691 s->checkAddr = checkAddr; 1692 s->typePriv = typePriv; 1693 return Success; 1694 } 1695 1696 /* Checks to see if a host matches a server-interpreted host entry */ 1697 static Bool 1698 siAddrMatch(int family, void *addr, int len, HOST * host, ClientPtr client) 1699 { 1700 Bool matches = FALSE; 1701 struct siType *s; 1702 const char *valueString; 1703 int addrlen; 1704 1705 valueString = (const char *) memchr(host->addr, '\0', host->len); 1706 if (valueString != NULL) { 1707 for (s = siTypeList; s != NULL; s = s->next) { 1708 if (strcmp((char *) host->addr, s->typeName) == 0) { 1709 addrlen = host->len - (strlen((char *) host->addr) + 1); 1710 matches = s->addrMatch(family, addr, len, 1711 valueString + 1, addrlen, client, 1712 s->typePriv); 1713 break; 1714 } 1715 } 1716 #ifdef FAMILY_SI_DEBUG 1717 ErrorF("Xserver: siAddrMatch(): type = %s, value = %*.*s -- %s\n", 1718 host->addr, addrlen, addrlen, valueString + 1, 1719 (matches) ? "accepted" : "rejected"); 1720 #endif 1721 } 1722 return matches; 1723 } 1724 1725 static int 1726 siCheckAddr(const char *addrString, int length) 1727 { 1728 const char *valueString; 1729 int addrlen, typelen; 1730 int len = -1; 1731 struct siType *s; 1732 1733 /* Make sure there is a \0 byte inside the specified length 1734 to separate the address type from the address value. */ 1735 valueString = (const char *) memchr(addrString, '\0', length); 1736 if (valueString != NULL) { 1737 /* Make sure the first string is a recognized address type, 1738 * and the second string is a valid address of that type. 1739 */ 1740 typelen = strlen(addrString) + 1; 1741 addrlen = length - typelen; 1742 1743 for (s = siTypeList; s != NULL; s = s->next) { 1744 if (strcmp(addrString, s->typeName) == 0) { 1745 len = s->checkAddr(valueString + 1, addrlen, s->typePriv); 1746 if (len >= 0) { 1747 len += typelen; 1748 } 1749 break; 1750 } 1751 } 1752 #ifdef FAMILY_SI_DEBUG 1753 { 1754 const char *resultMsg; 1755 1756 if (s == NULL) { 1757 resultMsg = "type not registered"; 1758 } 1759 else { 1760 if (len == -1) 1761 resultMsg = "rejected"; 1762 else 1763 resultMsg = "accepted"; 1764 } 1765 1766 ErrorF 1767 ("Xserver: siCheckAddr(): type = %s, value = %*.*s, len = %d -- %s\n", 1768 addrString, addrlen, addrlen, valueString + 1, len, resultMsg); 1769 } 1770 #endif 1771 } 1772 return len; 1773 } 1774 1775 /*** 1776 * Hostname server-interpreted host type 1777 * 1778 * Stored as hostname string, explicitly defined to be resolved ONLY 1779 * at access check time, to allow for hosts with dynamic addresses 1780 * but static hostnames, such as found in some DHCP & mobile setups. 1781 * 1782 * Hostname must conform to IETF RFC 2396 sec. 3.2.2, which defines it as: 1783 * hostname = *( domainlabel "." ) toplabel [ "." ] 1784 * domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum 1785 * toplabel = alpha | alpha *( alphanum | "-" ) alphanum 1786 */ 1787 1788 #ifdef NI_MAXHOST 1789 #define SI_HOSTNAME_MAXLEN NI_MAXHOST 1790 #else 1791 #ifdef MAXHOSTNAMELEN 1792 #define SI_HOSTNAME_MAXLEN MAXHOSTNAMELEN 1793 #else 1794 #define SI_HOSTNAME_MAXLEN 256 1795 #endif 1796 #endif 1797 1798 static Bool 1799 siHostnameAddrMatch(int family, void *addr, int len, 1800 const char *siAddr, int siAddrLen, ClientPtr client, 1801 void *typePriv) 1802 { 1803 Bool res = FALSE; 1804 1805 /* Currently only supports checking against IPv4 & IPv6 connections, but 1806 * support for other address families, such as DECnet, could be added if 1807 * desired. 1808 */ 1809 #if defined(IPv6) && defined(AF_INET6) 1810 if ((family == FamilyInternet) || (family == FamilyInternet6)) { 1811 char hostname[SI_HOSTNAME_MAXLEN]; 1812 struct addrinfo *addresses; 1813 struct addrinfo *a; 1814 int f, hostaddrlen; 1815 void *hostaddr = NULL; 1816 1817 if (siAddrLen >= sizeof(hostname)) 1818 return FALSE; 1819 1820 strlcpy(hostname, siAddr, siAddrLen + 1); 1821 1822 if (getaddrinfo(hostname, NULL, NULL, &addresses) == 0) { 1823 for (a = addresses; a != NULL; a = a->ai_next) { 1824 hostaddrlen = a->ai_addrlen; 1825 f = ConvertAddr(a->ai_addr, &hostaddrlen, &hostaddr); 1826 if ((f == family) && (len == hostaddrlen) && hostaddr && 1827 (memcmp(addr, hostaddr, len) == 0)) { 1828 res = TRUE; 1829 break; 1830 } 1831 } 1832 freeaddrinfo(addresses); 1833 } 1834 } 1835 #else /* IPv6 not supported, use gethostbyname instead for IPv4 */ 1836 if (family == FamilyInternet) { 1837 register struct hostent *hp; 1838 1839 #ifdef XTHREADS_NEEDS_BYNAMEPARAMS 1840 _Xgethostbynameparams hparams; 1841 #endif 1842 char hostname[SI_HOSTNAME_MAXLEN]; 1843 int f, hostaddrlen; 1844 void *hostaddr; 1845 const char **addrlist; 1846 1847 if (siAddrLen >= sizeof(hostname)) 1848 return FALSE; 1849 1850 strlcpy(hostname, siAddr, siAddrLen + 1); 1851 1852 if ((hp = _XGethostbyname(hostname, hparams)) != NULL) { 1853 #ifdef h_addr /* new 4.3bsd version of gethostent */ 1854 /* iterate over the addresses */ 1855 for (addrlist = hp->h_addr_list; *addrlist; addrlist++) 1856 #else 1857 addrlist = &hp->h_addr; 1858 #endif 1859 { 1860 struct sockaddr_in sin; 1861 1862 sin.sin_family = hp->h_addrtype; 1863 memcpy(&(sin.sin_addr), *addrlist, hp->h_length); 1864 hostaddrlen = sizeof(sin); 1865 f = ConvertAddr((struct sockaddr *) &sin, 1866 &hostaddrlen, &hostaddr); 1867 if ((f == family) && (len == hostaddrlen) && 1868 (memcmp(addr, hostaddr, len) == 0)) { 1869 res = TRUE; 1870 break; 1871 } 1872 } 1873 } 1874 } 1875 #endif 1876 return res; 1877 } 1878 1879 static int 1880 siHostnameCheckAddr(const char *valueString, int length, void *typePriv) 1881 { 1882 /* Check conformance of hostname to RFC 2396 sec. 3.2.2 definition. 1883 * We do not use ctype functions here to avoid locale-specific 1884 * character sets. Hostnames must be pure ASCII. 1885 */ 1886 int len = length; 1887 int i; 1888 Bool dotAllowed = FALSE; 1889 Bool dashAllowed = FALSE; 1890 1891 if ((length <= 0) || (length >= SI_HOSTNAME_MAXLEN)) { 1892 len = -1; 1893 } 1894 else { 1895 for (i = 0; i < length; i++) { 1896 char c = valueString[i]; 1897 1898 if (c == 0x2E) { /* '.' */ 1899 if (dotAllowed == FALSE) { 1900 len = -1; 1901 break; 1902 } 1903 else { 1904 dotAllowed = FALSE; 1905 dashAllowed = FALSE; 1906 } 1907 } 1908 else if (c == 0x2D) { /* '-' */ 1909 if (dashAllowed == FALSE) { 1910 len = -1; 1911 break; 1912 } 1913 else { 1914 dotAllowed = FALSE; 1915 } 1916 } 1917 else if (((c >= 0x30) && (c <= 0x3A)) /* 0-9 */ || 1918 ((c >= 0x61) && (c <= 0x7A)) /* a-z */ || 1919 ((c >= 0x41) && (c <= 0x5A)) /* A-Z */ ) { 1920 dotAllowed = TRUE; 1921 dashAllowed = TRUE; 1922 } 1923 else { /* Invalid character */ 1924 len = -1; 1925 break; 1926 } 1927 } 1928 } 1929 return len; 1930 } 1931 1932 #if defined(IPv6) && defined(AF_INET6) 1933 /*** 1934 * "ipv6" server interpreted type 1935 * 1936 * Currently supports only IPv6 literal address as specified in IETF RFC 3513 1937 * 1938 * Once draft-ietf-ipv6-scoping-arch-00.txt becomes an RFC, support will be 1939 * added for the scoped address format it specifies. 1940 */ 1941 1942 /* Maximum length of an IPv6 address string - increase when adding support 1943 * for scoped address qualifiers. Includes room for trailing NUL byte. 1944 */ 1945 #define SI_IPv6_MAXLEN INET6_ADDRSTRLEN 1946 1947 static Bool 1948 siIPv6AddrMatch(int family, void *addr, int len, 1949 const char *siAddr, int siAddrlen, ClientPtr client, 1950 void *typePriv) 1951 { 1952 struct in6_addr addr6; 1953 char addrbuf[SI_IPv6_MAXLEN]; 1954 1955 if ((family != FamilyInternet6) || (len != sizeof(addr6))) 1956 return FALSE; 1957 1958 memcpy(addrbuf, siAddr, siAddrlen); 1959 addrbuf[siAddrlen] = '\0'; 1960 1961 if (inet_pton(AF_INET6, addrbuf, &addr6) != 1) { 1962 perror("inet_pton"); 1963 return FALSE; 1964 } 1965 1966 if (memcmp(addr, &addr6, len) == 0) { 1967 return TRUE; 1968 } 1969 else { 1970 return FALSE; 1971 } 1972 } 1973 1974 static int 1975 siIPv6CheckAddr(const char *addrString, int length, void *typePriv) 1976 { 1977 int len; 1978 1979 /* Minimum length is 3 (smallest legal address is "::1") */ 1980 if (length < 3) { 1981 /* Address is too short! */ 1982 len = -1; 1983 } 1984 else if (length >= SI_IPv6_MAXLEN) { 1985 /* Address is too long! */ 1986 len = -1; 1987 } 1988 else { 1989 /* Assume inet_pton is sufficient validation */ 1990 struct in6_addr addr6; 1991 char addrbuf[SI_IPv6_MAXLEN]; 1992 1993 memcpy(addrbuf, addrString, length); 1994 addrbuf[length] = '\0'; 1995 1996 if (inet_pton(AF_INET6, addrbuf, &addr6) != 1) { 1997 perror("inet_pton"); 1998 len = -1; 1999 } 2000 else { 2001 len = length; 2002 } 2003 } 2004 return len; 2005 } 2006 #endif /* IPv6 */ 2007 2008 #if !defined(NO_LOCAL_CLIENT_CRED) 2009 /*** 2010 * "localuser" & "localgroup" server interpreted types 2011 * 2012 * Allows local connections from a given local user or group 2013 */ 2014 2015 #include <pwd.h> 2016 #include <grp.h> 2017 2018 #define LOCAL_USER 1 2019 #define LOCAL_GROUP 2 2020 2021 typedef struct { 2022 int credType; 2023 } siLocalCredPrivRec, *siLocalCredPrivPtr; 2024 2025 static siLocalCredPrivRec siLocalUserPriv = { LOCAL_USER }; 2026 static siLocalCredPrivRec siLocalGroupPriv = { LOCAL_GROUP }; 2027 2028 static Bool 2029 siLocalCredGetId(const char *addr, int len, siLocalCredPrivPtr lcPriv, int *id) 2030 { 2031 Bool parsedOK = FALSE; 2032 char *addrbuf = malloc(len + 1); 2033 2034 if (addrbuf == NULL) { 2035 return FALSE; 2036 } 2037 2038 memcpy(addrbuf, addr, len); 2039 addrbuf[len] = '\0'; 2040 2041 if (addr[0] == '#') { /* numeric id */ 2042 char *cp; 2043 2044 errno = 0; 2045 *id = strtol(addrbuf + 1, &cp, 0); 2046 if ((errno == 0) && (cp != (addrbuf + 1))) { 2047 parsedOK = TRUE; 2048 } 2049 } 2050 else { /* non-numeric name */ 2051 if (lcPriv->credType == LOCAL_USER) { 2052 struct passwd *pw = getpwnam(addrbuf); 2053 2054 if (pw != NULL) { 2055 *id = (int) pw->pw_uid; 2056 parsedOK = TRUE; 2057 } 2058 } 2059 else { /* group */ 2060 struct group *gr = getgrnam(addrbuf); 2061 2062 if (gr != NULL) { 2063 *id = (int) gr->gr_gid; 2064 parsedOK = TRUE; 2065 } 2066 } 2067 } 2068 2069 free(addrbuf); 2070 return parsedOK; 2071 } 2072 2073 static Bool 2074 siLocalCredAddrMatch(int family, void *addr, int len, 2075 const char *siAddr, int siAddrlen, ClientPtr client, 2076 void *typePriv) 2077 { 2078 int siAddrId; 2079 LocalClientCredRec *lcc; 2080 siLocalCredPrivPtr lcPriv = (siLocalCredPrivPtr) typePriv; 2081 2082 if (GetLocalClientCreds(client, &lcc) == -1) { 2083 return FALSE; 2084 } 2085 2086 #ifdef HAVE_GETZONEID /* Ensure process is in the same zone */ 2087 if ((lcc->fieldsSet & LCC_ZID_SET) && (lcc->zoneid != getzoneid())) { 2088 FreeLocalClientCreds(lcc); 2089 return FALSE; 2090 } 2091 #endif 2092 2093 if (siLocalCredGetId(siAddr, siAddrlen, lcPriv, &siAddrId) == FALSE) { 2094 FreeLocalClientCreds(lcc); 2095 return FALSE; 2096 } 2097 2098 if (lcPriv->credType == LOCAL_USER) { 2099 if ((lcc->fieldsSet & LCC_UID_SET) && (lcc->euid == siAddrId)) { 2100 FreeLocalClientCreds(lcc); 2101 return TRUE; 2102 } 2103 } 2104 else { 2105 if ((lcc->fieldsSet & LCC_GID_SET) && (lcc->egid == siAddrId)) { 2106 FreeLocalClientCreds(lcc); 2107 return TRUE; 2108 } 2109 if (lcc->pSuppGids != NULL) { 2110 int i; 2111 2112 for (i = 0; i < lcc->nSuppGids; i++) { 2113 if (lcc->pSuppGids[i] == siAddrId) { 2114 FreeLocalClientCreds(lcc); 2115 return TRUE; 2116 } 2117 } 2118 } 2119 } 2120 FreeLocalClientCreds(lcc); 2121 return FALSE; 2122 } 2123 2124 static int 2125 siLocalCredCheckAddr(const char *addrString, int length, void *typePriv) 2126 { 2127 int len = length; 2128 int id; 2129 2130 if (siLocalCredGetId(addrString, length, 2131 (siLocalCredPrivPtr) typePriv, &id) == FALSE) { 2132 len = -1; 2133 } 2134 return len; 2135 } 2136 #endif /* localuser */ 2137 2138 static void 2139 siTypesInitialize(void) 2140 { 2141 siTypeAdd("hostname", siHostnameAddrMatch, siHostnameCheckAddr, NULL); 2142 #if defined(IPv6) && defined(AF_INET6) 2143 siTypeAdd("ipv6", siIPv6AddrMatch, siIPv6CheckAddr, NULL); 2144 #endif 2145 #if !defined(NO_LOCAL_CLIENT_CRED) 2146 siTypeAdd("localuser", siLocalCredAddrMatch, siLocalCredCheckAddr, 2147 &siLocalUserPriv); 2148 siTypeAdd("localgroup", siLocalCredAddrMatch, siLocalCredCheckAddr, 2149 &siLocalGroupPriv); 2150 #endif 2151 }