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