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