aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/os/access.c
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/os/access.c')
-rw-r--r--xorg-server/os/access.c4200
1 files changed, 2098 insertions, 2102 deletions
diff --git a/xorg-server/os/access.c b/xorg-server/os/access.c
index bb857a0f3..4684b6466 100644
--- a/xorg-server/os/access.c
+++ b/xorg-server/os/access.c
@@ -1,2102 +1,2098 @@
-/***********************************************************
-
-Copyright 1987, 1998 The Open Group
-
-All rights reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, and/or sell copies of the Software, and to permit persons
-to whom the Software is furnished to do so, provided that the above
-copyright notice(s) and this permission notice appear in all copies of
-the Software and that both the above copyright notice(s) and this
-permission notice appear in supporting documentation.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
-OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
-HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
-INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
-FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
-NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
-WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-Except as contained in this notice, the name of a copyright holder
-shall not be used in advertising or otherwise to promote the sale, use
-or other dealings in this Software without prior written authorization
-of the copyright holder.
-
-X Window System is a trademark of The Open Group.
-
-Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
-
- All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-******************************************************************/
-
-/*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#ifdef WIN32
-#include <X11/Xwinsock.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#define XSERV_t
-#define TRANS_SERVER
-#define TRANS_REOPEN
-#include <X11/Xtrans/Xtrans.h>
-#include <X11/Xauth.h>
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include "misc.h"
-#include "site.h"
-#include <errno.h>
-#include <sys/types.h>
-#ifndef WIN32
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <ctype.h>
-
-#if defined(TCPCONN) || defined(STREAMSCONN) || defined(__SCO__)
-#include <netinet/in.h>
-#endif /* TCPCONN || STREAMSCONN || __SCO__ */
-
-#ifdef HAS_GETPEERUCRED
-# include <ucred.h>
-# ifdef sun
-# include <zone.h>
-# endif
-#endif
-
-#if defined(SVR4) || (defined(SYSV) && defined(__i386__)) || defined(__GNU__)
-# include <sys/utsname.h>
-#endif
-#if defined(SYSV) && defined(__i386__)
-# include <sys/stream.h>
-#endif
-#ifdef __GNU__
-#undef SIOCGIFCONF
-#include <netdb.h>
-#else /*!__GNU__*/
-# include <net/if.h>
-#endif /*__GNU__ */
-
-#ifdef SVR4
-#include <sys/sockio.h>
-#include <sys/stropts.h>
-#endif
-
-#include <netdb.h>
-
-#ifdef CSRG_BASED
-#include <sys/param.h>
-#if (BSD >= 199103)
-#define VARIABLE_IFREQ
-#endif
-#endif
-
-#ifdef BSD44SOCKETS
-#ifndef VARIABLE_IFREQ
-#define VARIABLE_IFREQ
-#endif
-#endif
-
-#ifdef HAS_GETIFADDRS
-#include <ifaddrs.h>
-#endif
-
-/* Solaris provides an extended interface SIOCGLIFCONF. Other systems
- * may have this as well, but the code has only been tested on Solaris
- * so far, so we only enable it there. Other platforms may be added as
- * needed.
- *
- * Test for Solaris commented out -- TSI @ UQV 2003.06.13
- */
-#ifdef SIOCGLIFCONF
-/* #if defined(sun) */
-#define USE_SIOCGLIFCONF
-/* #endif */
-#endif
-
-#endif /* WIN32 */
-
-#ifndef PATH_MAX
-#include <sys/param.h>
-#ifndef PATH_MAX
-#ifdef MAXPATHLEN
-#define PATH_MAX MAXPATHLEN
-#else
-#define PATH_MAX 1024
-#endif
-#endif
-#endif
-
-#ifdef __SCO__
-/* The system defined value is wrong. MAXPATHLEN is set in sco5.cf. */
-#undef PATH_MAX
-#endif
-
-#define X_INCLUDE_NETDB_H
-#include <X11/Xos_r.h>
-
-#include "dixstruct.h"
-#include "osdep.h"
-
-#include "xace.h"
-
-#ifndef PATH_MAX
-#ifdef MAXPATHLEN
-#define PATH_MAX MAXPATHLEN
-#else
-#define PATH_MAX 1024
-#endif
-#endif
-
-Bool defeatAccessControl = FALSE;
-
-#define acmp(a1, a2, len) memcmp((char *)(a1), (char *)(a2), len)
-#define acopy(a1, a2, len) memmove((char *)(a2), (char *)(a1), len)
-#define addrEqual(fam, address, length, host) \
- ((fam) == (host)->family &&\
- (length) == (host)->len &&\
- !acmp (address, (host)->addr, length))
-
-static int ConvertAddr(struct sockaddr * /*saddr*/,
- int * /*len*/,
- pointer * /*addr*/);
-
-static int CheckAddr(int /*family*/,
- const void * /*pAddr*/,
- unsigned /*length*/);
-
-static Bool NewHost(int /*family*/,
- const void * /*addr*/,
- int /*len*/,
- int /* addingLocalHosts */);
-
-/* XFree86 bug #156: To keep track of which hosts were explicitly requested in
- /etc/X<display>.hosts, we've added a requested field to the HOST struct,
- and a LocalHostRequested variable. These default to FALSE, but are set
- to TRUE in ResetHosts when reading in /etc/X<display>.hosts. They are
- checked in DisableLocalHost(), which is called to disable the default
- local host entries when stronger authentication is turned on. */
-
-typedef struct _host {
- short family;
- short len;
- unsigned char *addr;
- struct _host *next;
- int requested;
-} HOST;
-
-#define MakeHost(h,l) (h)=malloc(sizeof *(h)+(l));\
- if (h) { \
- (h)->addr=(unsigned char *) ((h) + 1);\
- (h)->requested = FALSE; \
- }
-#define FreeHost(h) free(h)
-static HOST *selfhosts = NULL;
-static HOST *validhosts = NULL;
-static int AccessEnabled = DEFAULT_ACCESS_CONTROL;
-static int LocalHostEnabled = FALSE;
-static int LocalHostRequested = FALSE;
-static int UsingXdmcp = FALSE;
-
-/* FamilyServerInterpreted implementation */
-static Bool siAddrMatch(int family, pointer addr, int len, HOST *host,
- ClientPtr client);
-static int siCheckAddr(const char *addrString, int length);
-static void siTypesInitialize(void);
-
-/*
- * called when authorization is not enabled to add the
- * local host to the access list
- */
-
-void
-EnableLocalHost (void)
-{
- if (!UsingXdmcp)
- {
- LocalHostEnabled = TRUE;
- AddLocalHosts ();
- }
-}
-
-/*
- * called when authorization is enabled to keep us secure
- */
-void
-DisableLocalHost (void)
-{
- HOST *self;
-
- if (!LocalHostRequested) /* Fix for XFree86 bug #156 */
- LocalHostEnabled = FALSE;
- for (self = selfhosts; self; self = self->next) {
- if (!self->requested) /* Fix for XFree86 bug #156 */
- (void) RemoveHost ((ClientPtr)NULL, self->family, self->len, (pointer)self->addr);
- }
-}
-
-/*
- * called at init time when XDMCP will be used; xdmcp always
- * adds local hosts manually when needed
- */
-
-void
-AccessUsingXdmcp (void)
-{
- UsingXdmcp = TRUE;
- LocalHostEnabled = FALSE;
-}
-
-
-#if defined(SVR4) && !defined(SCO325) && !defined(sun) && defined(SIOCGIFCONF) && !defined(USE_SIOCGLIFCONF)
-
-/* Deal with different SIOCGIFCONF ioctl semantics on these OSs */
-
-static int
-ifioctl (int fd, int cmd, char *arg)
-{
- struct strioctl ioc;
- int ret;
-
- memset((char *) &ioc, 0, sizeof(ioc));
- ioc.ic_cmd = cmd;
- ioc.ic_timout = 0;
- if (cmd == SIOCGIFCONF)
- {
- ioc.ic_len = ((struct ifconf *) arg)->ifc_len;
- ioc.ic_dp = ((struct ifconf *) arg)->ifc_buf;
- }
- else
- {
- ioc.ic_len = sizeof(struct ifreq);
- ioc.ic_dp = arg;
- }
- ret = ioctl(fd, I_STR, (char *) &ioc);
- if (ret >= 0 && cmd == SIOCGIFCONF)
-#ifdef SVR4
- ((struct ifconf *) arg)->ifc_len = ioc.ic_len;
-#endif
- return ret;
-}
-#else /* Case sun, SCO325 and others */
-#define ifioctl ioctl
-#endif
-
-/*
- * DefineSelf (fd):
- *
- * Define this host for access control. Find all the hosts the OS knows about
- * for this fd and add them to the selfhosts list.
- */
-
-#if !defined(SIOCGIFCONF)
-void
-DefineSelf (int fd)
-{
-#if !defined(TCPCONN) && !defined(STREAMSCONN) && !defined(UNIXCONN)
- return;
-#else
- register int n;
- int len;
- caddr_t addr;
- int family;
- register HOST *host;
-
-#ifndef WIN32
- struct utsname name;
-#else
- struct {
- char nodename[512];
- } name;
-#endif
-
- register struct hostent *hp;
-
- union {
- struct sockaddr sa;
- struct sockaddr_in in;
-#if defined(IPv6) && defined(AF_INET6)
- struct sockaddr_in6 in6;
-#endif
- } saddr;
-
- struct sockaddr_in *inetaddr;
- struct sockaddr_in6 *inet6addr;
- struct sockaddr_in broad_addr;
-#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
- _Xgethostbynameparams hparams;
-#endif
-
- /* Why not use gethostname()? Well, at least on my system, I've had to
- * make an ugly kernel patch to get a name longer than 8 characters, and
- * uname() lets me access to the whole string (it smashes release, you
- * see), whereas gethostname() kindly truncates it for me.
- */
-#ifndef WIN32
- uname(&name);
-#else
- gethostname(name.nodename, sizeof(name.nodename));
-#endif
-
- hp = _XGethostbyname(name.nodename, hparams);
- if (hp != NULL)
- {
- #ifdef h_addr
- #define hp_addr *list
- char **list;
-
- /* iterate over the addresses */
- for (list = hp->h_addr_list; *list; list++)
- #else
- #define hp_addr hp->h_addr
- #endif
- {
- saddr.sa.sa_family = hp->h_addrtype;
- switch (hp->h_addrtype) {
- case AF_INET:
- inetaddr = (struct sockaddr_in *) (&(saddr.sa));
- acopy ( hp_addr, &(inetaddr->sin_addr), hp->h_length);
- len = sizeof(saddr.sa);
- break;
-#if defined(IPv6) && defined(AF_INET6)
- case AF_INET6:
- inet6addr = (struct sockaddr_in6 *) (&(saddr.sa));
- acopy ( hp_addr, &(inet6addr->sin6_addr), hp->h_length);
- len = sizeof(saddr.in6);
- break;
-#endif
- default:
- goto DefineLocalHost;
- }
- family = ConvertAddr ( &(saddr.sa), &len, (pointer *)&addr);
- if ( family != -1 && family != FamilyLocal )
- {
- for (host = selfhosts;
- host && !addrEqual (family, addr, len, host);
- host = host->next) ;
- if (!host)
- {
- /* add this host to the host list. */
- MakeHost(host,len)
- if (host)
- {
- host->family = family;
- host->len = len;
- acopy ( addr, host->addr, len);
- host->next = selfhosts;
- selfhosts = host;
- }
- #ifdef XDMCP
- /*
- * If this is an Internet Address, but not the localhost
- * address (127.0.0.1), nor the bogus address (0.0.0.0),
- * register it.
- */
- if (family == FamilyInternet &&
- !(len == 4 &&
- ((addr[0] == 127) ||
- (addr[0] == 0 && addr[1] == 0 &&
- addr[2] == 0 && addr[3] == 0)))
- )
- {
- XdmcpRegisterConnection (family, (char *)addr, len);
- broad_addr = *inetaddr;
- ((struct sockaddr_in *) &broad_addr)->sin_addr.s_addr =
- htonl (INADDR_BROADCAST);
- XdmcpRegisterBroadcastAddress ((struct sockaddr_in *)
- &broad_addr);
- }
- #if defined(IPv6) && defined(AF_INET6)
- else if (family == FamilyInternet6 &&
- !(IN6_IS_ADDR_LOOPBACK((struct in6_addr *)addr)))
- {
- XdmcpRegisterConnection (family, (char *)addr, len);
- }
- #endif
-
- #endif /* XDMCP */
- }
- }
- }
- }
- /*
- * now add a host of family FamilyLocalHost...
- */
-DefineLocalHost:
- for (host = selfhosts;
- host && !addrEqual(FamilyLocalHost, "", 0, host);
- host = host->next);
- if (!host)
- {
- MakeHost(host, 0);
- if (host)
- {
- host->family = FamilyLocalHost;
- host->len = 0;
- acopy("", host->addr, 0);
- host->next = selfhosts;
- selfhosts = host;
- }
- }
-#endif /* !TCPCONN && !STREAMSCONN && !UNIXCONN */
-}
-
-#else
-
-#ifdef USE_SIOCGLIFCONF
-#define ifr_type struct lifreq
-#else
-#define ifr_type struct ifreq
-#endif
-
-#ifdef VARIABLE_IFREQ
-#define ifr_size(p) (sizeof (struct ifreq) + \
- (p->ifr_addr.sa_len > sizeof (p->ifr_addr) ? \
- p->ifr_addr.sa_len - sizeof (p->ifr_addr) : 0))
-#define ifraddr_size(a) (a.sa_len)
-#else
-#define ifr_size(p) (sizeof (ifr_type))
-#define ifraddr_size(a) (sizeof (a))
-#endif
-
-#if defined(IPv6) && defined(AF_INET6)
-#include <arpa/inet.h>
-#endif
-
-#if defined(IPv6) && defined(AF_INET6)
-static void
-in6_fillscopeid(struct sockaddr_in6 *sin6)
-{
-#if defined(__KAME__)
- if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
- sin6->sin6_scope_id =
- ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]);
- sin6->sin6_addr.s6_addr[2] = sin6->sin6_addr.s6_addr[3] = 0;
- }
-#endif
-}
-#endif
-
-void
-DefineSelf (int fd)
-{
-#ifndef HAS_GETIFADDRS
- char *cp, *cplim;
-# ifdef USE_SIOCGLIFCONF
- struct sockaddr_storage buf[16];
- struct lifconf ifc;
- register struct lifreq *ifr;
-# ifdef SIOCGLIFNUM
- struct lifnum ifn;
-# endif
-# else /* !USE_SIOCGLIFCONF */
- char buf[2048];
- struct ifconf ifc;
- register struct ifreq *ifr;
-# endif
- void * bufptr = buf;
-#else /* HAS_GETIFADDRS */
- struct ifaddrs * ifap, *ifr;
-#endif
- int len;
- unsigned char * addr;
- int family;
- register HOST *host;
-
-#ifndef HAS_GETIFADDRS
-
- len = sizeof(buf);
-
-#ifdef USE_SIOCGLIFCONF
-
-#ifdef SIOCGLIFNUM
- ifn.lifn_family = AF_UNSPEC;
- ifn.lifn_flags = 0;
- if (ioctl (fd, SIOCGLIFNUM, (char *) &ifn) < 0)
- Error ("Getting interface count");
- if (len < (ifn.lifn_count * sizeof(struct lifreq))) {
- len = ifn.lifn_count * sizeof(struct lifreq);
- bufptr = malloc(len);
- }
-#endif
-
- ifc.lifc_family = AF_UNSPEC;
- ifc.lifc_flags = 0;
- ifc.lifc_len = len;
- ifc.lifc_buf = bufptr;
-
-#define IFC_IOCTL_REQ SIOCGLIFCONF
-#define IFC_IFC_REQ ifc.lifc_req
-#define IFC_IFC_LEN ifc.lifc_len
-#define IFR_IFR_ADDR ifr->lifr_addr
-#define IFR_IFR_NAME ifr->lifr_name
-
-#else /* Use SIOCGIFCONF */
- ifc.ifc_len = len;
- ifc.ifc_buf = bufptr;
-
-#define IFC_IOCTL_REQ SIOCGIFCONF
-#define IFC_IFC_REQ ifc.ifc_req
-#define IFC_IFC_LEN ifc.ifc_len
-#define IFR_IFR_ADDR ifr->ifr_addr
-#define IFR_IFR_NAME ifr->ifr_name
-#endif
-
- if (ifioctl (fd, IFC_IOCTL_REQ, (pointer) &ifc) < 0)
- Error ("Getting interface configuration (4)");
-
- cplim = (char *) IFC_IFC_REQ + IFC_IFC_LEN;
-
- for (cp = (char *) IFC_IFC_REQ; cp < cplim; cp += ifr_size (ifr))
- {
- ifr = (ifr_type *) cp;
- len = ifraddr_size (IFR_IFR_ADDR);
- family = ConvertAddr ((struct sockaddr *) &IFR_IFR_ADDR,
- &len, (pointer *)&addr);
- if (family == -1 || family == FamilyLocal)
- continue;
-#if defined(IPv6) && defined(AF_INET6)
- if (family == FamilyInternet6)
- in6_fillscopeid((struct sockaddr_in6 *)&IFR_IFR_ADDR);
-#endif
- for (host = selfhosts;
- host && !addrEqual (family, addr, len, host);
- host = host->next)
- ;
- if (host)
- continue;
- MakeHost(host,len)
- if (host)
- {
- host->family = family;
- host->len = len;
- acopy(addr, host->addr, len);
- host->next = selfhosts;
- selfhosts = host;
- }
-#ifdef XDMCP
- {
-#ifdef USE_SIOCGLIFCONF
- struct sockaddr_storage broad_addr;
-#else
- struct sockaddr broad_addr;
-#endif
-
- /*
- * If this isn't an Internet Address, don't register it.
- */
- if (family != FamilyInternet
-#if defined(IPv6) && defined(AF_INET6)
- && family != FamilyInternet6
-#endif
- )
- continue;
-
- /*
- * ignore 'localhost' entries as they're not useful
- * on the other end of the wire
- */
- if (family == FamilyInternet &&
- addr[0] == 127 && addr[1] == 0 &&
- addr[2] == 0 && addr[3] == 1)
- continue;
-#if defined(IPv6) && defined(AF_INET6)
- else if (family == FamilyInternet6 &&
- IN6_IS_ADDR_LOOPBACK((struct in6_addr *)addr))
- continue;
-#endif
-
- /*
- * Ignore '0.0.0.0' entries as they are
- * returned by some OSes for unconfigured NICs but they are
- * not useful on the other end of the wire.
- */
- if (len == 4 &&
- addr[0] == 0 && addr[1] == 0 &&
- addr[2] == 0 && addr[3] == 0)
- continue;
-
- XdmcpRegisterConnection (family, (char *)addr, len);
-
-#if defined(IPv6) && defined(AF_INET6)
- /* IPv6 doesn't support broadcasting, so we drop out here */
- if (family == FamilyInternet6)
- continue;
-#endif
-
- broad_addr = IFR_IFR_ADDR;
-
- ((struct sockaddr_in *) &broad_addr)->sin_addr.s_addr =
- htonl (INADDR_BROADCAST);
-#if defined(USE_SIOCGLIFCONF) && defined(SIOCGLIFBRDADDR)
- {
- struct lifreq broad_req;
-
- broad_req = *ifr;
- if (ioctl (fd, SIOCGLIFFLAGS, (char *) &broad_req) != -1 &&
- (broad_req.lifr_flags & IFF_BROADCAST) &&
- (broad_req.lifr_flags & IFF_UP)
- )
- {
- broad_req = *ifr;
- if (ioctl (fd, SIOCGLIFBRDADDR, &broad_req) != -1)
- broad_addr = broad_req.lifr_broadaddr;
- else
- continue;
- }
- else
- continue;
- }
-
-#elif defined(SIOCGIFBRDADDR)
- {
- struct ifreq broad_req;
-
- broad_req = *ifr;
- if (ifioctl (fd, SIOCGIFFLAGS, (pointer) &broad_req) != -1 &&
- (broad_req.ifr_flags & IFF_BROADCAST) &&
- (broad_req.ifr_flags & IFF_UP)
- )
- {
- broad_req = *ifr;
- if (ifioctl (fd, SIOCGIFBRDADDR, (pointer) &broad_req) != -1)
- broad_addr = broad_req.ifr_addr;
- else
- continue;
- }
- else
- continue;
- }
-#endif /* SIOCGIFBRDADDR */
- XdmcpRegisterBroadcastAddress ((struct sockaddr_in *) &broad_addr);
- }
-#endif /* XDMCP */
- }
- if (bufptr != buf)
- free(bufptr);
-#else /* HAS_GETIFADDRS */
- if (getifaddrs(&ifap) < 0) {
- ErrorF("Warning: getifaddrs returns %s\n", strerror(errno));
- return;
- }
- for (ifr = ifap; ifr != NULL; ifr = ifr->ifa_next) {
- if (!ifr->ifa_addr)
- continue;
- len = sizeof(*(ifr->ifa_addr));
- family = ConvertAddr((struct sockaddr *) ifr->ifa_addr, &len,
- (pointer *)&addr);
- if (family == -1 || family == FamilyLocal)
- continue;
-#if defined(IPv6) && defined(AF_INET6)
- if (family == FamilyInternet6)
- in6_fillscopeid((struct sockaddr_in6 *)ifr->ifa_addr);
-#endif
-
- for (host = selfhosts;
- host != NULL && !addrEqual(family, addr, len, host);
- host = host->next)
- ;
- if (host != NULL)
- continue;
- MakeHost(host, len);
- if (host != NULL) {
- host->family = family;
- host->len = len;
- acopy(addr, host->addr, len);
- host->next = selfhosts;
- selfhosts = host;
- }
-#ifdef XDMCP
- {
- /*
- * If this isn't an Internet Address, don't register it.
- */
- if (family != FamilyInternet
-#if defined(IPv6) && defined(AF_INET6)
- && family != FamilyInternet6
-#endif
- )
- continue;
-
- /*
- * ignore 'localhost' entries as they're not useful
- * on the other end of the wire
- */
- if (ifr->ifa_flags & IFF_LOOPBACK)
- continue;
-
- if (family == FamilyInternet &&
- addr[0] == 127 && addr[1] == 0 &&
- addr[2] == 0 && addr[3] == 1)
- continue;
-
- /*
- * Ignore '0.0.0.0' entries as they are
- * returned by some OSes for unconfigured NICs but they are
- * not useful on the other end of the wire.
- */
- if (len == 4 &&
- addr[0] == 0 && addr[1] == 0 &&
- addr[2] == 0 && addr[3] == 0)
- continue;
-#if defined(IPv6) && defined(AF_INET6)
- else if (family == FamilyInternet6 &&
- IN6_IS_ADDR_LOOPBACK((struct in6_addr *)addr))
- continue;
-#endif
- XdmcpRegisterConnection(family, (char *)addr, len);
-#if defined(IPv6) && defined(AF_INET6)
- if (family == FamilyInternet6)
- /* IPv6 doesn't support broadcasting, so we drop out here */
- continue;
-#endif
- if ((ifr->ifa_flags & IFF_BROADCAST) &&
- (ifr->ifa_flags & IFF_UP) &&
- ifr->ifa_broadaddr)
- XdmcpRegisterBroadcastAddress(
- (struct sockaddr_in *) ifr->ifa_broadaddr);
- else
- continue;
- }
-#endif /* XDMCP */
-
- } /* for */
- freeifaddrs(ifap);
-#endif /* HAS_GETIFADDRS */
-
- /*
- * add something of FamilyLocalHost
- */
- for (host = selfhosts;
- host && !addrEqual(FamilyLocalHost, "", 0, host);
- host = host->next);
- if (!host)
- {
- MakeHost(host, 0);
- if (host)
- {
- host->family = FamilyLocalHost;
- host->len = 0;
- acopy("", host->addr, 0);
- host->next = selfhosts;
- selfhosts = host;
- }
- }
-}
-#endif /* hpux && !HAS_IFREQ */
-
-#ifdef XDMCP
-void
-AugmentSelf(pointer from, int len)
-{
- int family;
- pointer addr;
- register HOST *host;
-
- family = ConvertAddr(from, &len, (pointer *)&addr);
- if (family == -1 || family == FamilyLocal)
- return;
- for (host = selfhosts; host; host = host->next)
- {
- if (addrEqual(family, addr, len, host))
- return;
- }
- MakeHost(host,len)
- if (!host)
- return;
- host->family = family;
- host->len = len;
- acopy(addr, host->addr, len);
- host->next = selfhosts;
- selfhosts = host;
-}
-#endif
-
-void
-AddLocalHosts (void)
-{
- HOST *self;
-
- for (self = selfhosts; self; self = self->next)
- /* Fix for XFree86 bug #156: pass addingLocal = TRUE to
- * NewHost to tell that we are adding the default local
- * host entries and not to flag the entries as being
- * explicitely requested */
- (void) NewHost (self->family, self->addr, self->len, TRUE);
-}
-
-/* Reset access control list to initial hosts */
-void
-ResetHosts (char *display)
-{
- register HOST *host;
- char lhostname[120], ohostname[120];
- char *hostname = ohostname;
- char fname[PATH_MAX + 1];
- int fnamelen;
- FILE *fd;
- char *ptr;
- int i, hostlen;
-#if (defined(TCPCONN) || defined(STREAMSCONN) ) && \
- (!defined(IPv6) || !defined(AF_INET6))
- union {
- struct sockaddr sa;
-#if defined(TCPCONN) || defined(STREAMSCONN)
- struct sockaddr_in in;
-#endif /* TCPCONN || STREAMSCONN */
- } saddr;
-#endif
- int family = 0;
- pointer addr;
- int len;
-
- siTypesInitialize();
- AccessEnabled = defeatAccessControl ? FALSE : DEFAULT_ACCESS_CONTROL;
- LocalHostEnabled = FALSE;
- while ((host = validhosts) != 0)
- {
- validhosts = host->next;
- FreeHost (host);
- }
-
-#if defined WIN32 && defined __MINGW32__
-#define ETC_HOST_PREFIX "X"
-#else
-#define ETC_HOST_PREFIX "/etc/X"
-#endif
-#define ETC_HOST_SUFFIX ".hosts"
- fnamelen = strlen(ETC_HOST_PREFIX) + strlen(ETC_HOST_SUFFIX) +
- strlen(display) + 1;
- if (fnamelen > sizeof(fname))
- FatalError("Display name `%s' is too long\n", display);
- snprintf(fname, sizeof(fname), ETC_HOST_PREFIX "%s" ETC_HOST_SUFFIX,
- display);
-
- if ((fd = fopen (fname, "r")) != 0)
- {
- while (fgets (ohostname, sizeof (ohostname), fd))
- {
- family = FamilyWild;
- if (*ohostname == '#')
- continue;
- if ((ptr = strchr(ohostname, '\n')) != 0)
- *ptr = 0;
- hostlen = strlen(ohostname) + 1;
- for (i = 0; i < hostlen; i++)
- lhostname[i] = tolower(ohostname[i]);
- hostname = ohostname;
- if (!strncmp("local:", lhostname, 6))
- {
- family = FamilyLocalHost;
- NewHost(family, "", 0, FALSE);
- LocalHostRequested = TRUE; /* Fix for XFree86 bug #156 */
- }
-#if defined(TCPCONN) || defined(STREAMSCONN)
- else if (!strncmp("inet:", lhostname, 5))
- {
- family = FamilyInternet;
- hostname = ohostname + 5;
- }
-#if defined(IPv6) && defined(AF_INET6)
- else if (!strncmp("inet6:", lhostname, 6))
- {
- family = FamilyInternet6;
- hostname = ohostname + 6;
- }
-#endif
-#endif
-#ifdef SECURE_RPC
- else if (!strncmp("nis:", lhostname, 4))
- {
- family = FamilyNetname;
- hostname = ohostname + 4;
- }
-#endif
- else if (!strncmp("si:", lhostname, 3))
- {
- family = FamilyServerInterpreted;
- hostname = ohostname + 3;
- hostlen -= 3;
- }
-
-
- if (family == FamilyServerInterpreted)
- {
- len = siCheckAddr(hostname, hostlen);
- if (len >= 0) {
- NewHost(family, hostname, len, FALSE);
- }
- }
- else
-#ifdef SECURE_RPC
- if ((family == FamilyNetname) || (strchr(hostname, '@')))
- {
- SecureRPCInit ();
- (void) NewHost (FamilyNetname, hostname, strlen (hostname), FALSE);
- }
- else
-#endif /* SECURE_RPC */
-#if defined(TCPCONN) || defined(STREAMSCONN)
- {
-#if defined(IPv6) && defined(AF_INET6)
- if ( (family == FamilyInternet) || (family == FamilyInternet6) ||
- (family == FamilyWild) )
- {
- struct addrinfo *addresses;
- struct addrinfo *a;
- int f;
-
- if (getaddrinfo(hostname, NULL, NULL, &addresses) == 0) {
- for (a = addresses ; a != NULL ; a = a->ai_next) {
- len = a->ai_addrlen;
- f = ConvertAddr(a->ai_addr,&len,(pointer *)&addr);
- if ( (family == f) ||
- ((family == FamilyWild) && (f != -1)) ) {
- NewHost(f, addr, len, FALSE);
- }
- }
- freeaddrinfo(addresses);
- }
- }
-#else
-#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
- _Xgethostbynameparams hparams;
-#endif
- register struct hostent *hp;
-
- /* host name */
- if ((family == FamilyInternet &&
- ((hp = _XGethostbyname(hostname, hparams)) != 0)) ||
- ((hp = _XGethostbyname(hostname, hparams)) != 0))
- {
- saddr.sa.sa_family = hp->h_addrtype;
- len = sizeof(saddr.sa);
- if ((family = ConvertAddr (&saddr.sa, &len, (pointer *)&addr)) != -1)
- {
-#ifdef h_addr /* new 4.3bsd version of gethostent */
- char **list;
-
- /* iterate over the addresses */
- for (list = hp->h_addr_list; *list; list++)
- (void) NewHost (family, (pointer)*list, len, FALSE);
-#else
- (void) NewHost (family, (pointer)hp->h_addr, len, FALSE);
-#endif
- }
- }
-#endif /* IPv6 */
- }
-#endif /* TCPCONN || STREAMSCONN */
- family = FamilyWild;
- }
- fclose (fd);
- }
-}
-
-/* Is client on the local host */
-Bool LocalClient(ClientPtr client)
-{
- int alen, family, notused;
- Xtransaddr *from = NULL;
- pointer addr;
- register HOST *host;
-
- if (!client->osPrivate)
- return FALSE;
- if (!((OsCommPtr)client->osPrivate)->trans_conn)
- return FALSE;
-
- if (!_XSERVTransGetPeerAddr (((OsCommPtr)client->osPrivate)->trans_conn,
- &notused, &alen, &from))
- {
- family = ConvertAddr ((struct sockaddr *) from,
- &alen, (pointer *)&addr);
- if (family == -1)
- {
- free(from);
- return FALSE;
- }
- if (family == FamilyLocal)
- {
- free(from);
- return TRUE;
- }
- for (host = selfhosts; host; host = host->next)
- {
- if (addrEqual (family, addr, alen, host))
- return TRUE;
- }
- free(from);
- }
- return FALSE;
-}
-
-/*
- * Return the uid and gid of a connected local client
- *
- * Used by XShm to test access rights to shared memory segments
- */
-int
-LocalClientCred(ClientPtr client, int *pUid, int *pGid)
-{
- LocalClientCredRec *lcc;
- int ret = GetLocalClientCreds(client, &lcc);
-
- if (ret == 0) {
-#ifdef HAVE_GETZONEID /* only local if in the same zone */
- if ((lcc->fieldsSet & LCC_ZID_SET) && (lcc->zoneid != getzoneid())) {
- FreeLocalClientCreds(lcc);
- return -1;
- }
-#endif
- if ((lcc->fieldsSet & LCC_UID_SET) && (pUid != NULL))
- *pUid = lcc->euid;
- if ((lcc->fieldsSet & LCC_GID_SET) && (pGid != NULL))
- *pGid = lcc->egid;
- FreeLocalClientCreds(lcc);
- }
- return ret;
-}
-
-/*
- * Return the uid and all gids of a connected local client
- * Allocates a LocalClientCredRec - caller must call FreeLocalClientCreds
- *
- * Used by localuser & localgroup ServerInterpreted access control forms below
- * Used by AuthAudit to log who local connections came from
- */
-int
-GetLocalClientCreds(ClientPtr client, LocalClientCredRec **lccp)
-{
-#if defined(HAS_GETPEEREID) || defined(HAS_GETPEERUCRED) || defined(SO_PEERCRED)
- int fd;
- XtransConnInfo ci;
- LocalClientCredRec *lcc;
-#ifdef HAS_GETPEEREID
- uid_t uid;
- gid_t gid;
-#elif defined(HAS_GETPEERUCRED)
- ucred_t *peercred = NULL;
- const gid_t *gids;
-#elif defined(SO_PEERCRED)
- struct ucred peercred;
- socklen_t so_len = sizeof(peercred);
-#endif
-
- if (client == NULL)
- return -1;
- ci = ((OsCommPtr)client->osPrivate)->trans_conn;
-#if !(defined(sun) && defined(HAS_GETPEERUCRED))
- /* Most implementations can only determine peer credentials for Unix
- * domain sockets - Solaris getpeerucred can work with a bit more, so
- * we just let it tell us if the connection type is supported or not
- */
- if (!_XSERVTransIsLocal(ci)) {
- return -1;
- }
-#endif
-
- *lccp = calloc(1, sizeof(LocalClientCredRec));
- if (*lccp == NULL)
- return -1;
- lcc = *lccp;
-
- fd = _XSERVTransGetConnectionNumber(ci);
-#ifdef HAS_GETPEEREID
- if (getpeereid(fd, &uid, &gid) == -1) {
- FreeLocalClientCreds(lcc);
- return -1;
- }
- lcc->euid = uid;
- lcc->egid = gid;
- lcc->fieldsSet = LCC_UID_SET | LCC_GID_SET;
- return 0;
-#elif defined(HAS_GETPEERUCRED)
- if (getpeerucred(fd, &peercred) < 0) {
- FreeLocalClientCreds(lcc);
- return -1;
- }
- lcc->euid = ucred_geteuid(peercred);
- if (lcc->euid != -1)
- lcc->fieldsSet |= LCC_UID_SET;
- lcc->egid = ucred_getegid(peercred);
- if (lcc->egid != -1)
- lcc->fieldsSet |= LCC_GID_SET;
- lcc->pid = ucred_getpid(peercred);
- if (lcc->pid != -1)
- lcc->fieldsSet |= LCC_PID_SET;
-#ifdef HAVE_GETZONEID
- lcc->zoneid = ucred_getzoneid(peercred);
- if (lcc->zoneid != -1)
- lcc->fieldsSet |= LCC_ZID_SET;
-#endif
- lcc->nSuppGids = ucred_getgroups(peercred, &gids);
- if (lcc->nSuppGids > 0) {
- lcc->pSuppGids = calloc(lcc->nSuppGids, sizeof(int));
- if (lcc->pSuppGids == NULL) {
- lcc->nSuppGids = 0;
- } else {
- int i;
- for (i = 0 ; i < lcc->nSuppGids; i++) {
- (lcc->pSuppGids)[i] = (int) gids[i];
- }
- }
- } else {
- lcc->nSuppGids = 0;
- }
- ucred_free(peercred);
- return 0;
-#elif defined(SO_PEERCRED)
- if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) == -1) {
- FreeLocalClientCreds(lcc);
- return -1;
- }
- lcc->euid = peercred.uid;
- lcc->egid = peercred.gid;
- lcc->pid = peercred.pid;
- lcc->fieldsSet = LCC_UID_SET | LCC_GID_SET | LCC_PID_SET;
- return 0;
-#endif
-#else
- /* No system call available to get the credentials of the peer */
-#define NO_LOCAL_CLIENT_CRED
- return -1;
-#endif
-}
-
-void
-FreeLocalClientCreds(LocalClientCredRec *lcc)
-{
- if (lcc != NULL) {
- if (lcc->nSuppGids > 0) {
- free(lcc->pSuppGids);
- }
- free(lcc);
- }
-}
-
-static int
-AuthorizedClient(ClientPtr client)
-{
- int rc;
-
- if (!client || defeatAccessControl)
- return Success;
-
- /* untrusted clients can't change host access */
- rc = XaceHook(XACE_SERVER_ACCESS, client, DixManageAccess);
- if (rc != Success)
- return rc;
-
- return LocalClient(client) ? Success : BadAccess;
-}
-
-/* Add a host to the access control list. This is the external interface
- * called from the dispatcher */
-
-int
-AddHost (ClientPtr client,
- int family,
- unsigned length, /* of bytes in pAddr */
- const void * pAddr)
-{
- int rc, len;
-
- rc = AuthorizedClient(client);
- if (rc != Success)
- return rc;
- switch (family) {
- case FamilyLocalHost:
- len = length;
- LocalHostEnabled = TRUE;
- break;
-#ifdef SECURE_RPC
- case FamilyNetname:
- len = length;
- SecureRPCInit ();
- break;
-#endif
- case FamilyInternet:
-#if defined(IPv6) && defined(AF_INET6)
- case FamilyInternet6:
-#endif
- case FamilyDECnet:
- case FamilyChaos:
- case FamilyServerInterpreted:
- if ((len = CheckAddr (family, pAddr, length)) < 0)
- {
- client->errorValue = length;
- return BadValue;
- }
- break;
- case FamilyLocal:
- default:
- client->errorValue = family;
- return BadValue;
- }
- if (NewHost (family, pAddr, len, FALSE))
- return Success;
- return BadAlloc;
-}
-
-Bool
-ForEachHostInFamily (int family,
- Bool (*func)(
- unsigned char * /* addr */,
- short /* len */,
- pointer /* closure */),
- pointer closure)
-{
- HOST *host;
-
- for (host = validhosts; host; host = host->next)
- if (family == host->family && func (host->addr, host->len, closure))
- return TRUE;
- return FALSE;
-}
-
-/* Add a host to the access control list. This is the internal interface
- * called when starting or resetting the server */
-static Bool
-NewHost (int family,
- const void * addr,
- int len,
- int addingLocalHosts)
-{
- register HOST *host;
-
- for (host = validhosts; host; host = host->next)
- {
- if (addrEqual (family, addr, len, host))
- return TRUE;
- }
- if (!addingLocalHosts) { /* Fix for XFree86 bug #156 */
- for (host = selfhosts; host; host = host->next) {
- if (addrEqual (family, addr, len, host)) {
- host->requested = TRUE;
- break;
- }
- }
- }
- MakeHost(host,len)
- if (!host)
- return FALSE;
- host->family = family;
- host->len = len;
- acopy(addr, host->addr, len);
- host->next = validhosts;
- validhosts = host;
- return TRUE;
-}
-
-/* Remove a host from the access control list */
-
-int
-RemoveHost (
- ClientPtr client,
- int family,
- unsigned length, /* of bytes in pAddr */
- pointer pAddr)
-{
- int rc, len;
- register HOST *host, **prev;
-
- rc = AuthorizedClient(client);
- if (rc != Success)
- return rc;
- switch (family) {
- case FamilyLocalHost:
- len = length;
- LocalHostEnabled = FALSE;
- break;
-#ifdef SECURE_RPC
- case FamilyNetname:
- len = length;
- break;
-#endif
- case FamilyInternet:
-#if defined(IPv6) && defined(AF_INET6)
- case FamilyInternet6:
-#endif
- case FamilyDECnet:
- case FamilyChaos:
- case FamilyServerInterpreted:
- if ((len = CheckAddr (family, pAddr, length)) < 0)
- {
- client->errorValue = length;
- return BadValue;
- }
- break;
- case FamilyLocal:
- default:
- client->errorValue = family;
- return BadValue;
- }
- for (prev = &validhosts;
- (host = *prev) && (!addrEqual (family, pAddr, len, host));
- prev = &host->next)
- ;
- if (host)
- {
- *prev = host->next;
- FreeHost (host);
- }
- return Success;
-}
-
-/* Get all hosts in the access control list */
-int
-GetHosts (
- pointer *data,
- int *pnHosts,
- int *pLen,
- BOOL *pEnabled)
-{
- int len;
- register int n = 0;
- register unsigned char *ptr;
- register HOST *host;
- int nHosts = 0;
-
- *pEnabled = AccessEnabled ? EnableAccess : DisableAccess;
- for (host = validhosts; host; host = host->next)
- {
- nHosts++;
- n += pad_to_int32(host->len) + sizeof(xHostEntry);
- }
- if (n)
- {
- *data = ptr = malloc(n);
- if (!ptr)
- {
- return BadAlloc;
- }
- for (host = validhosts; host; host = host->next)
- {
- len = host->len;
- ((xHostEntry *)ptr)->family = host->family;
- ((xHostEntry *)ptr)->length = len;
- ptr += sizeof(xHostEntry);
- acopy (host->addr, ptr, len);
- ptr += pad_to_int32(len);
- }
- } else {
- *data = NULL;
- }
- *pnHosts = nHosts;
- *pLen = n;
- return Success;
-}
-
-/* Check for valid address family and length, and return address length. */
-
-/*ARGSUSED*/
-static int
-CheckAddr (
- int family,
- const void * pAddr,
- unsigned length)
-{
- int len;
-
- switch (family)
- {
-#if defined(TCPCONN) || defined(STREAMSCONN)
- case FamilyInternet:
- if (length == sizeof (struct in_addr))
- len = length;
- else
- len = -1;
- break;
-#if defined(IPv6) && defined(AF_INET6)
- case FamilyInternet6:
- if (length == sizeof (struct in6_addr))
- len = length;
- else
- len = -1;
- break;
-#endif
-#endif
- case FamilyServerInterpreted:
- len = siCheckAddr(pAddr, length);
- break;
- default:
- len = -1;
- }
- return len;
-}
-
-/* Check if a host is not in the access control list.
- * Returns 1 if host is invalid, 0 if we've found it. */
-
-int
-InvalidHost (
- register struct sockaddr *saddr,
- int len,
- ClientPtr client)
-{
- int family;
- pointer addr;
- register HOST *selfhost, *host;
-
- if (!AccessEnabled) /* just let them in */
- return 0;
- family = ConvertAddr (saddr, &len, (pointer *)&addr);
- if (family == -1)
- return 1;
- if (family == FamilyLocal)
- {
- if (!LocalHostEnabled)
- {
- /*
- * check to see if any local address is enabled. This
- * implicitly enables local connections.
- */
- for (selfhost = selfhosts; selfhost; selfhost=selfhost->next)
- {
- for (host = validhosts; host; host=host->next)
- {
- if (addrEqual (selfhost->family, selfhost->addr,
- selfhost->len, host))
- return 0;
- }
- }
- } else
- return 0;
- }
- for (host = validhosts; host; host = host->next)
- {
- if ((host->family == FamilyServerInterpreted)) {
- if (siAddrMatch (family, addr, len, host, client)) {
- return 0;
- }
- } else {
- if (addrEqual (family, addr, len, host))
- return 0;
- }
-
- }
- return 1;
-}
-
-static int
-ConvertAddr (
- register struct sockaddr *saddr,
- int *len,
- pointer *addr)
-{
- if (*len == 0)
- return FamilyLocal;
- switch (saddr->sa_family)
- {
- case AF_UNSPEC:
-#if defined(UNIXCONN) || defined(LOCALCONN)
- case AF_UNIX:
-#endif
- return FamilyLocal;
-#if defined(TCPCONN) || defined(STREAMSCONN)
- case AF_INET:
-#ifdef WIN32
- if (16777343 == *(long*)&((struct sockaddr_in *) saddr)->sin_addr)
- return FamilyLocal;
-#endif
- *len = sizeof (struct in_addr);
- *addr = (pointer) &(((struct sockaddr_in *) saddr)->sin_addr);
- return FamilyInternet;
-#if defined(IPv6) && defined(AF_INET6)
- case AF_INET6:
- {
- struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *) saddr;
- if (IN6_IS_ADDR_V4MAPPED(&(saddr6->sin6_addr))) {
- *len = sizeof (struct in_addr);
- *addr = (pointer) &(saddr6->sin6_addr.s6_addr[12]);
- return FamilyInternet;
- } else {
- *len = sizeof (struct in6_addr);
- *addr = (pointer) &(saddr6->sin6_addr);
- return FamilyInternet6;
- }
- }
-#endif
-#endif
- default:
- return -1;
- }
-}
-
-int
-ChangeAccessControl(
- ClientPtr client,
- int fEnabled)
-{
- int rc = AuthorizedClient(client);
- if (rc != Success)
- return rc;
- AccessEnabled = fEnabled;
- return Success;
-}
-
-/* returns FALSE if xhost + in effect, else TRUE */
-int
-GetAccessControl(void)
-{
- return AccessEnabled;
-}
-
-/*****************************************************************************
- * FamilyServerInterpreted host entry implementation
- *
- * Supports an extensible system of host types which the server can interpret
- * See the IPv6 extensions to the X11 protocol spec for the definition.
- *
- * Currently supported schemes:
- *
- * hostname - hostname as defined in IETF RFC 2396
- * ipv6 - IPv6 literal address as defined in IETF RFC's 3513 and <TBD>
- *
- * See xc/doc/specs/SIAddresses for formal definitions of each type.
- */
-
-/* These definitions and the siTypeAdd function could be exported in the
- * future to enable loading additional host types, but that was not done for
- * the initial implementation.
- */
-typedef Bool (*siAddrMatchFunc)(int family, pointer addr, int len,
- const char *siAddr, int siAddrlen, ClientPtr client, void *siTypePriv);
-typedef int (*siCheckAddrFunc)(const char *addrString, int length,
- void *siTypePriv);
-
-struct siType {
- struct siType * next;
- const char * typeName;
- siAddrMatchFunc addrMatch;
- siCheckAddrFunc checkAddr;
- void * typePriv; /* Private data for type routines */
-};
-
-static struct siType *siTypeList;
-
-static int
-siTypeAdd(const char *typeName, siAddrMatchFunc addrMatch,
- siCheckAddrFunc checkAddr, void *typePriv)
-{
- struct siType *s, *p;
-
- if ((typeName == NULL) || (addrMatch == NULL) || (checkAddr == NULL))
- return BadValue;
-
- for (s = siTypeList, p = NULL; s != NULL ; p = s, s = s->next) {
- if (strcmp(typeName, s->typeName) == 0) {
- s->addrMatch = addrMatch;
- s->checkAddr = checkAddr;
- s->typePriv = typePriv;
- return Success;
- }
- }
-
- s = malloc(sizeof(struct siType));
- if (s == NULL)
- return BadAlloc;
-
- if (p == NULL)
- siTypeList = s;
- else
- p->next = s;
-
- s->next = NULL;
- s->typeName = typeName;
- s->addrMatch = addrMatch;
- s->checkAddr = checkAddr;
- s->typePriv = typePriv;
- return Success;
-}
-
-/* Checks to see if a host matches a server-interpreted host entry */
-static Bool
-siAddrMatch(int family, pointer addr, int len, HOST *host, ClientPtr client)
-{
- Bool matches = FALSE;
- struct siType *s;
- const char *valueString;
- int addrlen;
-
- valueString = (const char *) memchr(host->addr, '\0', host->len);
- if (valueString != NULL) {
- for (s = siTypeList; s != NULL ; s = s->next) {
- if (strcmp((char *) host->addr, s->typeName) == 0) {
- addrlen = host->len - (strlen((char *)host->addr) + 1);
- matches = s->addrMatch(family, addr, len,
- valueString + 1, addrlen, client, s->typePriv);
- break;
- }
- }
-#ifdef FAMILY_SI_DEBUG
- ErrorF(
- "Xserver: siAddrMatch(): type = %s, value = %*.*s -- %s\n",
- host->addr, addrlen, addrlen, valueString + 1,
- (matches) ? "accepted" : "rejected");
-#endif
- }
- return matches;
-}
-
-static int
-siCheckAddr(const char *addrString, int length)
-{
- const char *valueString;
- int addrlen, typelen;
- int len = -1;
- struct siType *s;
-
- /* Make sure there is a \0 byte inside the specified length
- to separate the address type from the address value. */
- valueString = (const char *) memchr(addrString, '\0', length);
- if (valueString != NULL) {
- /* Make sure the first string is a recognized address type,
- * and the second string is a valid address of that type.
- */
- typelen = strlen(addrString) + 1;
- addrlen = length - typelen;
-
- for (s = siTypeList; s != NULL ; s = s->next) {
- if (strcmp(addrString, s->typeName) == 0) {
- len = s->checkAddr(valueString + 1, addrlen, s->typePriv);
- if (len >= 0) {
- len += typelen;
- }
- break;
- }
- }
-#ifdef FAMILY_SI_DEBUG
- {
- const char *resultMsg;
-
- if (s == NULL) {
- resultMsg = "type not registered";
- } else {
- if (len == -1)
- resultMsg = "rejected";
- else
- resultMsg = "accepted";
- }
-
- ErrorF("Xserver: siCheckAddr(): type = %s, value = %*.*s, len = %d -- %s\n",
- addrString, addrlen, addrlen, valueString + 1, len, resultMsg);
- }
-#endif
- }
- return len;
-}
-
-
-/***
- * Hostname server-interpreted host type
- *
- * Stored as hostname string, explicitly defined to be resolved ONLY
- * at access check time, to allow for hosts with dynamic addresses
- * but static hostnames, such as found in some DHCP & mobile setups.
- *
- * Hostname must conform to IETF RFC 2396 sec. 3.2.2, which defines it as:
- * hostname = *( domainlabel "." ) toplabel [ "." ]
- * domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
- * toplabel = alpha | alpha *( alphanum | "-" ) alphanum
- */
-
-#ifdef NI_MAXHOST
-# define SI_HOSTNAME_MAXLEN NI_MAXHOST
-#else
-# ifdef MAXHOSTNAMELEN
-# define SI_HOSTNAME_MAXLEN MAXHOSTNAMELEN
-# else
-# define SI_HOSTNAME_MAXLEN 256
-# endif
-#endif
-
-static Bool
-siHostnameAddrMatch(int family, pointer addr, int len,
- const char *siAddr, int siAddrLen, ClientPtr client, void *typePriv)
-{
- Bool res = FALSE;
-
-/* Currently only supports checking against IPv4 & IPv6 connections, but
- * support for other address families, such as DECnet, could be added if
- * desired.
- */
-#if defined(IPv6) && defined(AF_INET6)
- if ((family == FamilyInternet) || (family == FamilyInternet6)) {
- char hostname[SI_HOSTNAME_MAXLEN];
- struct addrinfo *addresses;
- struct addrinfo *a;
- int f, hostaddrlen;
- pointer hostaddr;
-
- if (siAddrLen >= sizeof(hostname))
- return FALSE;
-
- strncpy(hostname, siAddr, siAddrLen);
- hostname[siAddrLen] = '\0';
-
- if (getaddrinfo(hostname, NULL, NULL, &addresses) == 0) {
- for (a = addresses ; a != NULL ; a = a->ai_next) {
- hostaddrlen = a->ai_addrlen;
- f = ConvertAddr(a->ai_addr,&hostaddrlen,&hostaddr);
- if ((f == family) && (len == hostaddrlen) &&
- (acmp (addr, hostaddr, len) == 0) ) {
- res = TRUE;
- break;
- }
- }
- freeaddrinfo(addresses);
- }
- }
-#else /* IPv6 not supported, use gethostbyname instead for IPv4 */
- if (family == FamilyInternet) {
- register struct hostent *hp;
-#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
- _Xgethostbynameparams hparams;
-#endif
- char hostname[SI_HOSTNAME_MAXLEN];
- int f, hostaddrlen;
- pointer hostaddr;
- const char **addrlist;
-
- if (siAddrLen >= sizeof(hostname))
- return FALSE;
-
- strncpy(hostname, siAddr, siAddrLen);
- hostname[siAddrLen] = '\0';
-
- if ((hp = _XGethostbyname(hostname, hparams)) != NULL) {
-#ifdef h_addr /* new 4.3bsd version of gethostent */
- /* iterate over the addresses */
- for (addrlist = hp->h_addr_list; *addrlist; addrlist++)
-#else
- addrlist = &hp->h_addr;
-#endif
- {
- struct sockaddr_in sin;
-
- sin.sin_family = hp->h_addrtype;
- acopy ( *addrlist, &(sin.sin_addr), hp->h_length);
- hostaddrlen = sizeof(sin);
- f = ConvertAddr ((struct sockaddr *)&sin,
- &hostaddrlen, &hostaddr);
- if ((f == family) && (len == hostaddrlen) &&
- (acmp (addr, hostaddr, len) == 0) ) {
- res = TRUE;
- break;
- }
- }
- }
- }
-#endif
- return res;
-}
-
-
-static int
-siHostnameCheckAddr(const char *valueString, int length, void *typePriv)
-{
- /* Check conformance of hostname to RFC 2396 sec. 3.2.2 definition.
- * We do not use ctype functions here to avoid locale-specific
- * character sets. Hostnames must be pure ASCII.
- */
- int len = length;
- int i;
- Bool dotAllowed = FALSE;
- Bool dashAllowed = FALSE;
-
- if ((length <= 0) || (length >= SI_HOSTNAME_MAXLEN)) {
- len = -1;
- } else {
- for (i = 0; i < length; i++) {
- char c = valueString[i];
-
- if (c == 0x2E) { /* '.' */
- if (dotAllowed == FALSE) {
- len = -1;
- break;
- } else {
- dotAllowed = FALSE;
- dashAllowed = FALSE;
- }
- } else if (c == 0x2D) { /* '-' */
- if (dashAllowed == FALSE) {
- len = -1;
- break;
- } else {
- dotAllowed = FALSE;
- }
- } else if (((c >= 0x30) && (c <= 0x3A)) /* 0-9 */ ||
- ((c >= 0x61) && (c <= 0x7A)) /* a-z */ ||
- ((c >= 0x41) && (c <= 0x5A)) /* A-Z */) {
- dotAllowed = TRUE;
- dashAllowed = TRUE;
- } else { /* Invalid character */
- len = -1;
- break;
- }
- }
- }
- return len;
-}
-
-#if defined(IPv6) && defined(AF_INET6)
-/***
- * "ipv6" server interpreted type
- *
- * Currently supports only IPv6 literal address as specified in IETF RFC 3513
- *
- * Once draft-ietf-ipv6-scoping-arch-00.txt becomes an RFC, support will be
- * added for the scoped address format it specifies.
- */
-
-/* Maximum length of an IPv6 address string - increase when adding support
- * for scoped address qualifiers. Includes room for trailing NUL byte.
- */
-#define SI_IPv6_MAXLEN INET6_ADDRSTRLEN
-
-static Bool
-siIPv6AddrMatch(int family, pointer addr, int len,
- const char *siAddr, int siAddrlen, ClientPtr client, void *typePriv)
-{
- struct in6_addr addr6;
- char addrbuf[SI_IPv6_MAXLEN];
-
- if ((family != FamilyInternet6) || (len != sizeof(addr6)))
- return FALSE;
-
- memcpy(addrbuf, siAddr, siAddrlen);
- addrbuf[siAddrlen] = '\0';
-
- if (inet_pton(AF_INET6, addrbuf, &addr6) != 1) {
- perror("inet_pton");
- return FALSE;
- }
-
- if (memcmp(addr, &addr6, len) == 0) {
- return TRUE;
- } else {
- return FALSE;
- }
-}
-
-static int
-siIPv6CheckAddr(const char *addrString, int length, void *typePriv)
-{
- int len;
-
- /* Minimum length is 3 (smallest legal address is "::1") */
- if (length < 3) {
- /* Address is too short! */
- len = -1;
- } else if (length >= SI_IPv6_MAXLEN) {
- /* Address is too long! */
- len = -1;
- } else {
- /* Assume inet_pton is sufficient validation */
- struct in6_addr addr6;
- char addrbuf[SI_IPv6_MAXLEN];
-
- memcpy(addrbuf, addrString, length);
- addrbuf[length] = '\0';
-
- if (inet_pton(AF_INET6, addrbuf, &addr6) != 1) {
- perror("inet_pton");
- len = -1;
- } else {
- len = length;
- }
- }
- return len;
-}
-#endif /* IPv6 */
-
-#if !defined(NO_LOCAL_CLIENT_CRED)
-/***
- * "localuser" & "localgroup" server interpreted types
- *
- * Allows local connections from a given local user or group
- */
-
-#include <pwd.h>
-#include <grp.h>
-
-#define LOCAL_USER 1
-#define LOCAL_GROUP 2
-
-typedef struct {
- int credType;
-} siLocalCredPrivRec, *siLocalCredPrivPtr;
-
-static siLocalCredPrivRec siLocalUserPriv = { LOCAL_USER };
-static siLocalCredPrivRec siLocalGroupPriv = { LOCAL_GROUP };
-
-static Bool
-siLocalCredGetId(const char *addr, int len, siLocalCredPrivPtr lcPriv, int *id)
-{
- Bool parsedOK = FALSE;
- char *addrbuf = malloc(len + 1);
-
- if (addrbuf == NULL) {
- return FALSE;
- }
-
- memcpy(addrbuf, addr, len);
- addrbuf[len] = '\0';
-
- if (addr[0] == '#') { /* numeric id */
- char *cp;
- errno = 0;
- *id = strtol(addrbuf + 1, &cp, 0);
- if ((errno == 0) && (cp != (addrbuf+1))) {
- parsedOK = TRUE;
- }
- } else { /* non-numeric name */
- if (lcPriv->credType == LOCAL_USER) {
- struct passwd *pw = getpwnam(addrbuf);
-
- if (pw != NULL) {
- *id = (int) pw->pw_uid;
- parsedOK = TRUE;
- }
- } else { /* group */
- struct group *gr = getgrnam(addrbuf);
-
- if (gr != NULL) {
- *id = (int) gr->gr_gid;
- parsedOK = TRUE;
- }
- }
- }
-
- free(addrbuf);
- return parsedOK;
-}
-
-static Bool
-siLocalCredAddrMatch(int family, pointer addr, int len,
- const char *siAddr, int siAddrlen, ClientPtr client, void *typePriv)
-{
- int siAddrId;
- LocalClientCredRec *lcc;
- siLocalCredPrivPtr lcPriv = (siLocalCredPrivPtr) typePriv;
-
- if (GetLocalClientCreds(client, &lcc) == -1) {
- return FALSE;
- }
-
-#ifdef HAVE_GETZONEID /* Ensure process is in the same zone */
- if ((lcc->fieldsSet & LCC_ZID_SET) && (lcc->zoneid != getzoneid())) {
- FreeLocalClientCreds(lcc);
- return FALSE;
- }
-#endif
-
- if (siLocalCredGetId(siAddr, siAddrlen, lcPriv, &siAddrId) == FALSE) {
- FreeLocalClientCreds(lcc);
- return FALSE;
- }
-
- if (lcPriv->credType == LOCAL_USER) {
- if ((lcc->fieldsSet & LCC_UID_SET) && (lcc->euid == siAddrId)) {
- FreeLocalClientCreds(lcc);
- return TRUE;
- }
- } else {
- if ((lcc->fieldsSet & LCC_GID_SET) && (lcc->egid == siAddrId)) {
- FreeLocalClientCreds(lcc);
- return TRUE;
- }
- if (lcc->pSuppGids != NULL) {
- int i;
-
- for (i = 0 ; i < lcc->nSuppGids; i++) {
- if (lcc->pSuppGids[i] == siAddrId) {
- FreeLocalClientCreds(lcc);
- return TRUE;
- }
- }
- }
- }
- FreeLocalClientCreds(lcc);
- return FALSE;
-}
-
-static int
-siLocalCredCheckAddr(const char *addrString, int length, void *typePriv)
-{
- int len = length;
- int id;
-
- if (siLocalCredGetId(addrString, length,
- (siLocalCredPrivPtr)typePriv, &id) == FALSE) {
- len = -1;
- }
- return len;
-}
-#endif /* localuser */
-
-static void
-siTypesInitialize(void)
-{
- siTypeAdd("hostname", siHostnameAddrMatch, siHostnameCheckAddr, NULL);
-#if defined(IPv6) && defined(AF_INET6)
- siTypeAdd("ipv6", siIPv6AddrMatch, siIPv6CheckAddr, NULL);
-#endif
-#if !defined(NO_LOCAL_CLIENT_CRED)
- siTypeAdd("localuser", siLocalCredAddrMatch, siLocalCredCheckAddr,
- &siLocalUserPriv);
- siTypeAdd("localgroup", siLocalCredAddrMatch, siLocalCredCheckAddr,
- &siLocalGroupPriv);
-#endif
-}
+/***********************************************************
+
+Copyright 1987, 1998 The Open Group
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, and/or sell copies of the Software, and to permit persons
+to whom the Software is furnished to do so, provided that the above
+copyright notice(s) and this permission notice appear in all copies of
+the Software and that both the above copyright notice(s) and this
+permission notice appear in supporting documentation.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
+INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
+FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in this Software without prior written authorization
+of the copyright holder.
+
+X Window System is a trademark of The Open Group.
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+******************************************************************/
+
+/*
+ * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifdef WIN32
+#include <X11/Xwinsock.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#define XSERV_t
+#define TRANS_SERVER
+#define TRANS_REOPEN
+#include <X11/Xtrans/Xtrans.h>
+#include <X11/Xauth.h>
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include "misc.h"
+#include "site.h"
+#include <errno.h>
+#include <sys/types.h>
+#ifndef WIN32
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <ctype.h>
+
+#if defined(TCPCONN) || defined(STREAMSCONN)
+#include <netinet/in.h>
+#endif /* TCPCONN || STREAMSCONN */
+
+#ifdef HAS_GETPEERUCRED
+# include <ucred.h>
+# ifdef sun
+# include <zone.h>
+# endif
+#endif
+
+#if defined(SVR4) || (defined(SYSV) && defined(__i386__)) || defined(__GNU__)
+# include <sys/utsname.h>
+#endif
+#if defined(SYSV) && defined(__i386__)
+# include <sys/stream.h>
+#endif
+#ifdef __GNU__
+#undef SIOCGIFCONF
+#include <netdb.h>
+#else /*!__GNU__*/
+# include <net/if.h>
+#endif /*__GNU__ */
+
+#ifdef SVR4
+#include <sys/sockio.h>
+#include <sys/stropts.h>
+#endif
+
+#include <netdb.h>
+
+#ifdef CSRG_BASED
+#include <sys/param.h>
+#if (BSD >= 199103)
+#define VARIABLE_IFREQ
+#endif
+#endif
+
+#ifdef BSD44SOCKETS
+#ifndef VARIABLE_IFREQ
+#define VARIABLE_IFREQ
+#endif
+#endif
+
+#ifdef HAS_GETIFADDRS
+#include <ifaddrs.h>
+#endif
+
+/* Solaris provides an extended interface SIOCGLIFCONF. Other systems
+ * may have this as well, but the code has only been tested on Solaris
+ * so far, so we only enable it there. Other platforms may be added as
+ * needed.
+ *
+ * Test for Solaris commented out -- TSI @ UQV 2003.06.13
+ */
+#ifdef SIOCGLIFCONF
+/* #if defined(sun) */
+#define USE_SIOCGLIFCONF
+/* #endif */
+#endif
+
+#endif /* WIN32 */
+
+#ifndef PATH_MAX
+#include <sys/param.h>
+#ifndef PATH_MAX
+#ifdef MAXPATHLEN
+#define PATH_MAX MAXPATHLEN
+#else
+#define PATH_MAX 1024
+#endif
+#endif
+#endif
+
+
+#define X_INCLUDE_NETDB_H
+#include <X11/Xos_r.h>
+
+#include "dixstruct.h"
+#include "osdep.h"
+
+#include "xace.h"
+
+#ifndef PATH_MAX
+#ifdef MAXPATHLEN
+#define PATH_MAX MAXPATHLEN
+#else
+#define PATH_MAX 1024
+#endif
+#endif
+
+Bool defeatAccessControl = FALSE;
+
+#define acmp(a1, a2, len) memcmp((char *)(a1), (char *)(a2), len)
+#define acopy(a1, a2, len) memmove((char *)(a2), (char *)(a1), len)
+#define addrEqual(fam, address, length, host) \
+ ((fam) == (host)->family &&\
+ (length) == (host)->len &&\
+ !acmp (address, (host)->addr, length))
+
+static int ConvertAddr(struct sockaddr * /*saddr*/,
+ int * /*len*/,
+ pointer * /*addr*/);
+
+static int CheckAddr(int /*family*/,
+ const void * /*pAddr*/,
+ unsigned /*length*/);
+
+static Bool NewHost(int /*family*/,
+ const void * /*addr*/,
+ int /*len*/,
+ int /* addingLocalHosts */);
+
+/* XFree86 bug #156: To keep track of which hosts were explicitly requested in
+ /etc/X<display>.hosts, we've added a requested field to the HOST struct,
+ and a LocalHostRequested variable. These default to FALSE, but are set
+ to TRUE in ResetHosts when reading in /etc/X<display>.hosts. They are
+ checked in DisableLocalHost(), which is called to disable the default
+ local host entries when stronger authentication is turned on. */
+
+typedef struct _host {
+ short family;
+ short len;
+ unsigned char *addr;
+ struct _host *next;
+ int requested;
+} HOST;
+
+#define MakeHost(h,l) (h)=malloc(sizeof *(h)+(l));\
+ if (h) { \
+ (h)->addr=(unsigned char *) ((h) + 1);\
+ (h)->requested = FALSE; \
+ }
+#define FreeHost(h) free(h)
+static HOST *selfhosts = NULL;
+static HOST *validhosts = NULL;
+static int AccessEnabled = DEFAULT_ACCESS_CONTROL;
+static int LocalHostEnabled = FALSE;
+static int LocalHostRequested = FALSE;
+static int UsingXdmcp = FALSE;
+
+/* FamilyServerInterpreted implementation */
+static Bool siAddrMatch(int family, pointer addr, int len, HOST *host,
+ ClientPtr client);
+static int siCheckAddr(const char *addrString, int length);
+static void siTypesInitialize(void);
+
+/*
+ * called when authorization is not enabled to add the
+ * local host to the access list
+ */
+
+void
+EnableLocalHost (void)
+{
+ if (!UsingXdmcp)
+ {
+ LocalHostEnabled = TRUE;
+ AddLocalHosts ();
+ }
+}
+
+/*
+ * called when authorization is enabled to keep us secure
+ */
+void
+DisableLocalHost (void)
+{
+ HOST *self;
+
+ if (!LocalHostRequested) /* Fix for XFree86 bug #156 */
+ LocalHostEnabled = FALSE;
+ for (self = selfhosts; self; self = self->next) {
+ if (!self->requested) /* Fix for XFree86 bug #156 */
+ (void) RemoveHost ((ClientPtr)NULL, self->family, self->len, (pointer)self->addr);
+ }
+}
+
+/*
+ * called at init time when XDMCP will be used; xdmcp always
+ * adds local hosts manually when needed
+ */
+
+void
+AccessUsingXdmcp (void)
+{
+ UsingXdmcp = TRUE;
+ LocalHostEnabled = FALSE;
+}
+
+
+#if defined(SVR4) && !defined(sun) && defined(SIOCGIFCONF) && !defined(USE_SIOCGLIFCONF)
+
+/* Deal with different SIOCGIFCONF ioctl semantics on these OSs */
+
+static int
+ifioctl (int fd, int cmd, char *arg)
+{
+ struct strioctl ioc;
+ int ret;
+
+ memset((char *) &ioc, 0, sizeof(ioc));
+ ioc.ic_cmd = cmd;
+ ioc.ic_timout = 0;
+ if (cmd == SIOCGIFCONF)
+ {
+ ioc.ic_len = ((struct ifconf *) arg)->ifc_len;
+ ioc.ic_dp = ((struct ifconf *) arg)->ifc_buf;
+ }
+ else
+ {
+ ioc.ic_len = sizeof(struct ifreq);
+ ioc.ic_dp = arg;
+ }
+ ret = ioctl(fd, I_STR, (char *) &ioc);
+ if (ret >= 0 && cmd == SIOCGIFCONF)
+#ifdef SVR4
+ ((struct ifconf *) arg)->ifc_len = ioc.ic_len;
+#endif
+ return ret;
+}
+#else
+#define ifioctl ioctl
+#endif
+
+/*
+ * DefineSelf (fd):
+ *
+ * Define this host for access control. Find all the hosts the OS knows about
+ * for this fd and add them to the selfhosts list.
+ */
+
+#if !defined(SIOCGIFCONF)
+void
+DefineSelf (int fd)
+{
+#if !defined(TCPCONN) && !defined(STREAMSCONN) && !defined(UNIXCONN)
+ return;
+#else
+ register int n;
+ int len;
+ caddr_t addr;
+ int family;
+ register HOST *host;
+
+#ifndef WIN32
+ struct utsname name;
+#else
+ struct {
+ char nodename[512];
+ } name;
+#endif
+
+ register struct hostent *hp;
+
+ union {
+ struct sockaddr sa;
+ struct sockaddr_in in;
+#if defined(IPv6) && defined(AF_INET6)
+ struct sockaddr_in6 in6;
+#endif
+ } saddr;
+
+ struct sockaddr_in *inetaddr;
+ struct sockaddr_in6 *inet6addr;
+ struct sockaddr_in broad_addr;
+#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
+ _Xgethostbynameparams hparams;
+#endif
+
+ /* Why not use gethostname()? Well, at least on my system, I've had to
+ * make an ugly kernel patch to get a name longer than 8 characters, and
+ * uname() lets me access to the whole string (it smashes release, you
+ * see), whereas gethostname() kindly truncates it for me.
+ */
+#ifndef WIN32
+ uname(&name);
+#else
+ gethostname(name.nodename, sizeof(name.nodename));
+#endif
+
+ hp = _XGethostbyname(name.nodename, hparams);
+ if (hp != NULL)
+ {
+ #ifdef h_addr
+ #define hp_addr *list
+ char **list;
+
+ /* iterate over the addresses */
+ for (list = hp->h_addr_list; *list; list++)
+ #else
+ #define hp_addr hp->h_addr
+ #endif
+ {
+ saddr.sa.sa_family = hp->h_addrtype;
+ switch (hp->h_addrtype) {
+ case AF_INET:
+ inetaddr = (struct sockaddr_in *) (&(saddr.sa));
+ acopy ( hp_addr, &(inetaddr->sin_addr), hp->h_length);
+ len = sizeof(saddr.sa);
+ break;
+#if defined(IPv6) && defined(AF_INET6)
+ case AF_INET6:
+ inet6addr = (struct sockaddr_in6 *) (&(saddr.sa));
+ acopy ( hp_addr, &(inet6addr->sin6_addr), hp->h_length);
+ len = sizeof(saddr.in6);
+ break;
+#endif
+ default:
+ goto DefineLocalHost;
+ }
+ family = ConvertAddr ( &(saddr.sa), &len, (pointer *)&addr);
+ if ( family != -1 && family != FamilyLocal )
+ {
+ for (host = selfhosts;
+ host && !addrEqual (family, addr, len, host);
+ host = host->next) ;
+ if (!host)
+ {
+ /* add this host to the host list. */
+ MakeHost(host,len)
+ if (host)
+ {
+ host->family = family;
+ host->len = len;
+ acopy ( addr, host->addr, len);
+ host->next = selfhosts;
+ selfhosts = host;
+ }
+ #ifdef XDMCP
+ /*
+ * If this is an Internet Address, but not the localhost
+ * address (127.0.0.1), nor the bogus address (0.0.0.0),
+ * register it.
+ */
+ if (family == FamilyInternet &&
+ !(len == 4 &&
+ ((addr[0] == 127) ||
+ (addr[0] == 0 && addr[1] == 0 &&
+ addr[2] == 0 && addr[3] == 0)))
+ )
+ {
+ XdmcpRegisterConnection (family, (char *)addr, len);
+ broad_addr = *inetaddr;
+ ((struct sockaddr_in *) &broad_addr)->sin_addr.s_addr =
+ htonl (INADDR_BROADCAST);
+ XdmcpRegisterBroadcastAddress ((struct sockaddr_in *)
+ &broad_addr);
+ }
+ #if defined(IPv6) && defined(AF_INET6)
+ else if (family == FamilyInternet6 &&
+ !(IN6_IS_ADDR_LOOPBACK((struct in6_addr *)addr)))
+ {
+ XdmcpRegisterConnection (family, (char *)addr, len);
+ }
+ #endif
+
+ #endif /* XDMCP */
+ }
+ }
+ }
+ }
+ /*
+ * now add a host of family FamilyLocalHost...
+ */
+DefineLocalHost:
+ for (host = selfhosts;
+ host && !addrEqual(FamilyLocalHost, "", 0, host);
+ host = host->next);
+ if (!host)
+ {
+ MakeHost(host, 0);
+ if (host)
+ {
+ host->family = FamilyLocalHost;
+ host->len = 0;
+ acopy("", host->addr, 0);
+ host->next = selfhosts;
+ selfhosts = host;
+ }
+ }
+#endif /* !TCPCONN && !STREAMSCONN && !UNIXCONN */
+}
+
+#else
+
+#ifdef USE_SIOCGLIFCONF
+#define ifr_type struct lifreq
+#else
+#define ifr_type struct ifreq
+#endif
+
+#ifdef VARIABLE_IFREQ
+#define ifr_size(p) (sizeof (struct ifreq) + \
+ (p->ifr_addr.sa_len > sizeof (p->ifr_addr) ? \
+ p->ifr_addr.sa_len - sizeof (p->ifr_addr) : 0))
+#define ifraddr_size(a) (a.sa_len)
+#else
+#define ifr_size(p) (sizeof (ifr_type))
+#define ifraddr_size(a) (sizeof (a))
+#endif
+
+#if defined(IPv6) && defined(AF_INET6)
+#include <arpa/inet.h>
+#endif
+
+#if defined(IPv6) && defined(AF_INET6)
+static void
+in6_fillscopeid(struct sockaddr_in6 *sin6)
+{
+#if defined(__KAME__)
+ if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
+ sin6->sin6_scope_id =
+ ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]);
+ sin6->sin6_addr.s6_addr[2] = sin6->sin6_addr.s6_addr[3] = 0;
+ }
+#endif
+}
+#endif
+
+void
+DefineSelf (int fd)
+{
+#ifndef HAS_GETIFADDRS
+ char *cp, *cplim;
+# ifdef USE_SIOCGLIFCONF
+ struct sockaddr_storage buf[16];
+ struct lifconf ifc;
+ register struct lifreq *ifr;
+# ifdef SIOCGLIFNUM
+ struct lifnum ifn;
+# endif
+# else /* !USE_SIOCGLIFCONF */
+ char buf[2048];
+ struct ifconf ifc;
+ register struct ifreq *ifr;
+# endif
+ void * bufptr = buf;
+#else /* HAS_GETIFADDRS */
+ struct ifaddrs * ifap, *ifr;
+#endif
+ int len;
+ unsigned char * addr;
+ int family;
+ register HOST *host;
+
+#ifndef HAS_GETIFADDRS
+
+ len = sizeof(buf);
+
+#ifdef USE_SIOCGLIFCONF
+
+#ifdef SIOCGLIFNUM
+ ifn.lifn_family = AF_UNSPEC;
+ ifn.lifn_flags = 0;
+ if (ioctl (fd, SIOCGLIFNUM, (char *) &ifn) < 0)
+ Error ("Getting interface count");
+ if (len < (ifn.lifn_count * sizeof(struct lifreq))) {
+ len = ifn.lifn_count * sizeof(struct lifreq);
+ bufptr = malloc(len);
+ }
+#endif
+
+ ifc.lifc_family = AF_UNSPEC;
+ ifc.lifc_flags = 0;
+ ifc.lifc_len = len;
+ ifc.lifc_buf = bufptr;
+
+#define IFC_IOCTL_REQ SIOCGLIFCONF
+#define IFC_IFC_REQ ifc.lifc_req
+#define IFC_IFC_LEN ifc.lifc_len
+#define IFR_IFR_ADDR ifr->lifr_addr
+#define IFR_IFR_NAME ifr->lifr_name
+
+#else /* Use SIOCGIFCONF */
+ ifc.ifc_len = len;
+ ifc.ifc_buf = bufptr;
+
+#define IFC_IOCTL_REQ SIOCGIFCONF
+#define IFC_IFC_REQ ifc.ifc_req
+#define IFC_IFC_LEN ifc.ifc_len
+#define IFR_IFR_ADDR ifr->ifr_addr
+#define IFR_IFR_NAME ifr->ifr_name
+#endif
+
+ if (ifioctl (fd, IFC_IOCTL_REQ, (pointer) &ifc) < 0)
+ Error ("Getting interface configuration (4)");
+
+ cplim = (char *) IFC_IFC_REQ + IFC_IFC_LEN;
+
+ for (cp = (char *) IFC_IFC_REQ; cp < cplim; cp += ifr_size (ifr))
+ {
+ ifr = (ifr_type *) cp;
+ len = ifraddr_size (IFR_IFR_ADDR);
+ family = ConvertAddr ((struct sockaddr *) &IFR_IFR_ADDR,
+ &len, (pointer *)&addr);
+ if (family == -1 || family == FamilyLocal)
+ continue;
+#if defined(IPv6) && defined(AF_INET6)
+ if (family == FamilyInternet6)
+ in6_fillscopeid((struct sockaddr_in6 *)&IFR_IFR_ADDR);
+#endif
+ for (host = selfhosts;
+ host && !addrEqual (family, addr, len, host);
+ host = host->next)
+ ;
+ if (host)
+ continue;
+ MakeHost(host,len)
+ if (host)
+ {
+ host->family = family;
+ host->len = len;
+ acopy(addr, host->addr, len);
+ host->next = selfhosts;
+ selfhosts = host;
+ }
+#ifdef XDMCP
+ {
+#ifdef USE_SIOCGLIFCONF
+ struct sockaddr_storage broad_addr;
+#else
+ struct sockaddr broad_addr;
+#endif
+
+ /*
+ * If this isn't an Internet Address, don't register it.
+ */
+ if (family != FamilyInternet
+#if defined(IPv6) && defined(AF_INET6)
+ && family != FamilyInternet6
+#endif
+ )
+ continue;
+
+ /*
+ * ignore 'localhost' entries as they're not useful
+ * on the other end of the wire
+ */
+ if (family == FamilyInternet &&
+ addr[0] == 127 && addr[1] == 0 &&
+ addr[2] == 0 && addr[3] == 1)
+ continue;
+#if defined(IPv6) && defined(AF_INET6)
+ else if (family == FamilyInternet6 &&
+ IN6_IS_ADDR_LOOPBACK((struct in6_addr *)addr))
+ continue;
+#endif
+
+ /*
+ * Ignore '0.0.0.0' entries as they are
+ * returned by some OSes for unconfigured NICs but they are
+ * not useful on the other end of the wire.
+ */
+ if (len == 4 &&
+ addr[0] == 0 && addr[1] == 0 &&
+ addr[2] == 0 && addr[3] == 0)
+ continue;
+
+ XdmcpRegisterConnection (family, (char *)addr, len);
+
+#if defined(IPv6) && defined(AF_INET6)
+ /* IPv6 doesn't support broadcasting, so we drop out here */
+ if (family == FamilyInternet6)
+ continue;
+#endif
+
+ broad_addr = IFR_IFR_ADDR;
+
+ ((struct sockaddr_in *) &broad_addr)->sin_addr.s_addr =
+ htonl (INADDR_BROADCAST);
+#if defined(USE_SIOCGLIFCONF) && defined(SIOCGLIFBRDADDR)
+ {
+ struct lifreq broad_req;
+
+ broad_req = *ifr;
+ if (ioctl (fd, SIOCGLIFFLAGS, (char *) &broad_req) != -1 &&
+ (broad_req.lifr_flags & IFF_BROADCAST) &&
+ (broad_req.lifr_flags & IFF_UP)
+ )
+ {
+ broad_req = *ifr;
+ if (ioctl (fd, SIOCGLIFBRDADDR, &broad_req) != -1)
+ broad_addr = broad_req.lifr_broadaddr;
+ else
+ continue;
+ }
+ else
+ continue;
+ }
+
+#elif defined(SIOCGIFBRDADDR)
+ {
+ struct ifreq broad_req;
+
+ broad_req = *ifr;
+ if (ifioctl (fd, SIOCGIFFLAGS, (pointer) &broad_req) != -1 &&
+ (broad_req.ifr_flags & IFF_BROADCAST) &&
+ (broad_req.ifr_flags & IFF_UP)
+ )
+ {
+ broad_req = *ifr;
+ if (ifioctl (fd, SIOCGIFBRDADDR, (pointer) &broad_req) != -1)
+ broad_addr = broad_req.ifr_addr;
+ else
+ continue;
+ }
+ else
+ continue;
+ }
+#endif /* SIOCGIFBRDADDR */
+ XdmcpRegisterBroadcastAddress ((struct sockaddr_in *) &broad_addr);
+ }
+#endif /* XDMCP */
+ }
+ if (bufptr != buf)
+ free(bufptr);
+#else /* HAS_GETIFADDRS */
+ if (getifaddrs(&ifap) < 0) {
+ ErrorF("Warning: getifaddrs returns %s\n", strerror(errno));
+ return;
+ }
+ for (ifr = ifap; ifr != NULL; ifr = ifr->ifa_next) {
+ if (!ifr->ifa_addr)
+ continue;
+ len = sizeof(*(ifr->ifa_addr));
+ family = ConvertAddr((struct sockaddr *) ifr->ifa_addr, &len,
+ (pointer *)&addr);
+ if (family == -1 || family == FamilyLocal)
+ continue;
+#if defined(IPv6) && defined(AF_INET6)
+ if (family == FamilyInternet6)
+ in6_fillscopeid((struct sockaddr_in6 *)ifr->ifa_addr);
+#endif
+
+ for (host = selfhosts;
+ host != NULL && !addrEqual(family, addr, len, host);
+ host = host->next)
+ ;
+ if (host != NULL)
+ continue;
+ MakeHost(host, len);
+ if (host != NULL) {
+ host->family = family;
+ host->len = len;
+ acopy(addr, host->addr, len);
+ host->next = selfhosts;
+ selfhosts = host;
+ }
+#ifdef XDMCP
+ {
+ /*
+ * If this isn't an Internet Address, don't register it.
+ */
+ if (family != FamilyInternet
+#if defined(IPv6) && defined(AF_INET6)
+ && family != FamilyInternet6
+#endif
+ )
+ continue;
+
+ /*
+ * ignore 'localhost' entries as they're not useful
+ * on the other end of the wire
+ */
+ if (ifr->ifa_flags & IFF_LOOPBACK)
+ continue;
+
+ if (family == FamilyInternet &&
+ addr[0] == 127 && addr[1] == 0 &&
+ addr[2] == 0 && addr[3] == 1)
+ continue;
+
+ /*
+ * Ignore '0.0.0.0' entries as they are
+ * returned by some OSes for unconfigured NICs but they are
+ * not useful on the other end of the wire.
+ */
+ if (len == 4 &&
+ addr[0] == 0 && addr[1] == 0 &&
+ addr[2] == 0 && addr[3] == 0)
+ continue;
+#if defined(IPv6) && defined(AF_INET6)
+ else if (family == FamilyInternet6 &&
+ IN6_IS_ADDR_LOOPBACK((struct in6_addr *)addr))
+ continue;
+#endif
+ XdmcpRegisterConnection(family, (char *)addr, len);
+#if defined(IPv6) && defined(AF_INET6)
+ if (family == FamilyInternet6)
+ /* IPv6 doesn't support broadcasting, so we drop out here */
+ continue;
+#endif
+ if ((ifr->ifa_flags & IFF_BROADCAST) &&
+ (ifr->ifa_flags & IFF_UP) &&
+ ifr->ifa_broadaddr)
+ XdmcpRegisterBroadcastAddress(
+ (struct sockaddr_in *) ifr->ifa_broadaddr);
+ else
+ continue;
+ }
+#endif /* XDMCP */
+
+ } /* for */
+ freeifaddrs(ifap);
+#endif /* HAS_GETIFADDRS */
+
+ /*
+ * add something of FamilyLocalHost
+ */
+ for (host = selfhosts;
+ host && !addrEqual(FamilyLocalHost, "", 0, host);
+ host = host->next);
+ if (!host)
+ {
+ MakeHost(host, 0);
+ if (host)
+ {
+ host->family = FamilyLocalHost;
+ host->len = 0;
+ acopy("", host->addr, 0);
+ host->next = selfhosts;
+ selfhosts = host;
+ }
+ }
+}
+#endif /* hpux && !HAS_IFREQ */
+
+#ifdef XDMCP
+void
+AugmentSelf(pointer from, int len)
+{
+ int family;
+ pointer addr;
+ register HOST *host;
+
+ family = ConvertAddr(from, &len, (pointer *)&addr);
+ if (family == -1 || family == FamilyLocal)
+ return;
+ for (host = selfhosts; host; host = host->next)
+ {
+ if (addrEqual(family, addr, len, host))
+ return;
+ }
+ MakeHost(host,len)
+ if (!host)
+ return;
+ host->family = family;
+ host->len = len;
+ acopy(addr, host->addr, len);
+ host->next = selfhosts;
+ selfhosts = host;
+}
+#endif
+
+void
+AddLocalHosts (void)
+{
+ HOST *self;
+
+ for (self = selfhosts; self; self = self->next)
+ /* Fix for XFree86 bug #156: pass addingLocal = TRUE to
+ * NewHost to tell that we are adding the default local
+ * host entries and not to flag the entries as being
+ * explicitely requested */
+ (void) NewHost (self->family, self->addr, self->len, TRUE);
+}
+
+/* Reset access control list to initial hosts */
+void
+ResetHosts (char *display)
+{
+ register HOST *host;
+ char lhostname[120], ohostname[120];
+ char *hostname = ohostname;
+ char fname[PATH_MAX + 1];
+ int fnamelen;
+ FILE *fd;
+ char *ptr;
+ int i, hostlen;
+#if (defined(TCPCONN) || defined(STREAMSCONN) ) && \
+ (!defined(IPv6) || !defined(AF_INET6))
+ union {
+ struct sockaddr sa;
+#if defined(TCPCONN) || defined(STREAMSCONN)
+ struct sockaddr_in in;
+#endif /* TCPCONN || STREAMSCONN */
+ } saddr;
+#endif
+ int family = 0;
+ pointer addr;
+ int len;
+
+ siTypesInitialize();
+ AccessEnabled = defeatAccessControl ? FALSE : DEFAULT_ACCESS_CONTROL;
+ LocalHostEnabled = FALSE;
+ while ((host = validhosts) != 0)
+ {
+ validhosts = host->next;
+ FreeHost (host);
+ }
+
+#if defined WIN32 && defined __MINGW32__
+#define ETC_HOST_PREFIX "X"
+#else
+#define ETC_HOST_PREFIX "/etc/X"
+#endif
+#define ETC_HOST_SUFFIX ".hosts"
+ fnamelen = strlen(ETC_HOST_PREFIX) + strlen(ETC_HOST_SUFFIX) +
+ strlen(display) + 1;
+ if (fnamelen > sizeof(fname))
+ FatalError("Display name `%s' is too long\n", display);
+ snprintf(fname, sizeof(fname), ETC_HOST_PREFIX "%s" ETC_HOST_SUFFIX,
+ display);
+
+ if ((fd = fopen (fname, "r")) != 0)
+ {
+ while (fgets (ohostname, sizeof (ohostname), fd))
+ {
+ family = FamilyWild;
+ if (*ohostname == '#')
+ continue;
+ if ((ptr = strchr(ohostname, '\n')) != 0)
+ *ptr = 0;
+ hostlen = strlen(ohostname) + 1;
+ for (i = 0; i < hostlen; i++)
+ lhostname[i] = tolower(ohostname[i]);
+ hostname = ohostname;
+ if (!strncmp("local:", lhostname, 6))
+ {
+ family = FamilyLocalHost;
+ NewHost(family, "", 0, FALSE);
+ LocalHostRequested = TRUE; /* Fix for XFree86 bug #156 */
+ }
+#if defined(TCPCONN) || defined(STREAMSCONN)
+ else if (!strncmp("inet:", lhostname, 5))
+ {
+ family = FamilyInternet;
+ hostname = ohostname + 5;
+ }
+#if defined(IPv6) && defined(AF_INET6)
+ else if (!strncmp("inet6:", lhostname, 6))
+ {
+ family = FamilyInternet6;
+ hostname = ohostname + 6;
+ }
+#endif
+#endif
+#ifdef SECURE_RPC
+ else if (!strncmp("nis:", lhostname, 4))
+ {
+ family = FamilyNetname;
+ hostname = ohostname + 4;
+ }
+#endif
+ else if (!strncmp("si:", lhostname, 3))
+ {
+ family = FamilyServerInterpreted;
+ hostname = ohostname + 3;
+ hostlen -= 3;
+ }
+
+
+ if (family == FamilyServerInterpreted)
+ {
+ len = siCheckAddr(hostname, hostlen);
+ if (len >= 0) {
+ NewHost(family, hostname, len, FALSE);
+ }
+ }
+ else
+#ifdef SECURE_RPC
+ if ((family == FamilyNetname) || (strchr(hostname, '@')))
+ {
+ SecureRPCInit ();
+ (void) NewHost (FamilyNetname, hostname, strlen (hostname), FALSE);
+ }
+ else
+#endif /* SECURE_RPC */
+#if defined(TCPCONN) || defined(STREAMSCONN)
+ {
+#if defined(IPv6) && defined(AF_INET6)
+ if ( (family == FamilyInternet) || (family == FamilyInternet6) ||
+ (family == FamilyWild) )
+ {
+ struct addrinfo *addresses;
+ struct addrinfo *a;
+ int f;
+
+ if (getaddrinfo(hostname, NULL, NULL, &addresses) == 0) {
+ for (a = addresses ; a != NULL ; a = a->ai_next) {
+ len = a->ai_addrlen;
+ f = ConvertAddr(a->ai_addr,&len,(pointer *)&addr);
+ if ( (family == f) ||
+ ((family == FamilyWild) && (f != -1)) ) {
+ NewHost(f, addr, len, FALSE);
+ }
+ }
+ freeaddrinfo(addresses);
+ }
+ }
+#else
+#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
+ _Xgethostbynameparams hparams;
+#endif
+ register struct hostent *hp;
+
+ /* host name */
+ if ((family == FamilyInternet &&
+ ((hp = _XGethostbyname(hostname, hparams)) != 0)) ||
+ ((hp = _XGethostbyname(hostname, hparams)) != 0))
+ {
+ saddr.sa.sa_family = hp->h_addrtype;
+ len = sizeof(saddr.sa);
+ if ((family = ConvertAddr (&saddr.sa, &len, (pointer *)&addr)) != -1)
+ {
+#ifdef h_addr /* new 4.3bsd version of gethostent */
+ char **list;
+
+ /* iterate over the addresses */
+ for (list = hp->h_addr_list; *list; list++)
+ (void) NewHost (family, (pointer)*list, len, FALSE);
+#else
+ (void) NewHost (family, (pointer)hp->h_addr, len, FALSE);
+#endif
+ }
+ }
+#endif /* IPv6 */
+ }
+#endif /* TCPCONN || STREAMSCONN */
+ family = FamilyWild;
+ }
+ fclose (fd);
+ }
+}
+
+/* Is client on the local host */
+Bool LocalClient(ClientPtr client)
+{
+ int alen, family, notused;
+ Xtransaddr *from = NULL;
+ pointer addr;
+ register HOST *host;
+
+ if (!client->osPrivate)
+ return FALSE;
+ if (!((OsCommPtr)client->osPrivate)->trans_conn)
+ return FALSE;
+
+ if (!_XSERVTransGetPeerAddr (((OsCommPtr)client->osPrivate)->trans_conn,
+ &notused, &alen, &from))
+ {
+ family = ConvertAddr ((struct sockaddr *) from,
+ &alen, (pointer *)&addr);
+ if (family == -1)
+ {
+ free(from);
+ return FALSE;
+ }
+ if (family == FamilyLocal)
+ {
+ free(from);
+ return TRUE;
+ }
+ for (host = selfhosts; host; host = host->next)
+ {
+ if (addrEqual (family, addr, alen, host))
+ return TRUE;
+ }
+ free(from);
+ }
+ return FALSE;
+}
+
+/*
+ * Return the uid and gid of a connected local client
+ *
+ * Used by XShm to test access rights to shared memory segments
+ */
+int
+LocalClientCred(ClientPtr client, int *pUid, int *pGid)
+{
+ LocalClientCredRec *lcc;
+ int ret = GetLocalClientCreds(client, &lcc);
+
+ if (ret == 0) {
+#ifdef HAVE_GETZONEID /* only local if in the same zone */
+ if ((lcc->fieldsSet & LCC_ZID_SET) && (lcc->zoneid != getzoneid())) {
+ FreeLocalClientCreds(lcc);
+ return -1;
+ }
+#endif
+ if ((lcc->fieldsSet & LCC_UID_SET) && (pUid != NULL))
+ *pUid = lcc->euid;
+ if ((lcc->fieldsSet & LCC_GID_SET) && (pGid != NULL))
+ *pGid = lcc->egid;
+ FreeLocalClientCreds(lcc);
+ }
+ return ret;
+}
+
+/*
+ * Return the uid and all gids of a connected local client
+ * Allocates a LocalClientCredRec - caller must call FreeLocalClientCreds
+ *
+ * Used by localuser & localgroup ServerInterpreted access control forms below
+ * Used by AuthAudit to log who local connections came from
+ */
+int
+GetLocalClientCreds(ClientPtr client, LocalClientCredRec **lccp)
+{
+#if defined(HAS_GETPEEREID) || defined(HAS_GETPEERUCRED) || defined(SO_PEERCRED)
+ int fd;
+ XtransConnInfo ci;
+ LocalClientCredRec *lcc;
+#ifdef HAS_GETPEEREID
+ uid_t uid;
+ gid_t gid;
+#elif defined(HAS_GETPEERUCRED)
+ ucred_t *peercred = NULL;
+ const gid_t *gids;
+#elif defined(SO_PEERCRED)
+ struct ucred peercred;
+ socklen_t so_len = sizeof(peercred);
+#endif
+
+ if (client == NULL)
+ return -1;
+ ci = ((OsCommPtr)client->osPrivate)->trans_conn;
+#if !(defined(sun) && defined(HAS_GETPEERUCRED))
+ /* Most implementations can only determine peer credentials for Unix
+ * domain sockets - Solaris getpeerucred can work with a bit more, so
+ * we just let it tell us if the connection type is supported or not
+ */
+ if (!_XSERVTransIsLocal(ci)) {
+ return -1;
+ }
+#endif
+
+ *lccp = calloc(1, sizeof(LocalClientCredRec));
+ if (*lccp == NULL)
+ return -1;
+ lcc = *lccp;
+
+ fd = _XSERVTransGetConnectionNumber(ci);
+#ifdef HAS_GETPEEREID
+ if (getpeereid(fd, &uid, &gid) == -1) {
+ FreeLocalClientCreds(lcc);
+ return -1;
+ }
+ lcc->euid = uid;
+ lcc->egid = gid;
+ lcc->fieldsSet = LCC_UID_SET | LCC_GID_SET;
+ return 0;
+#elif defined(HAS_GETPEERUCRED)
+ if (getpeerucred(fd, &peercred) < 0) {
+ FreeLocalClientCreds(lcc);
+ return -1;
+ }
+ lcc->euid = ucred_geteuid(peercred);
+ if (lcc->euid != -1)
+ lcc->fieldsSet |= LCC_UID_SET;
+ lcc->egid = ucred_getegid(peercred);
+ if (lcc->egid != -1)
+ lcc->fieldsSet |= LCC_GID_SET;
+ lcc->pid = ucred_getpid(peercred);
+ if (lcc->pid != -1)
+ lcc->fieldsSet |= LCC_PID_SET;
+#ifdef HAVE_GETZONEID
+ lcc->zoneid = ucred_getzoneid(peercred);
+ if (lcc->zoneid != -1)
+ lcc->fieldsSet |= LCC_ZID_SET;
+#endif
+ lcc->nSuppGids = ucred_getgroups(peercred, &gids);
+ if (lcc->nSuppGids > 0) {
+ lcc->pSuppGids = calloc(lcc->nSuppGids, sizeof(int));
+ if (lcc->pSuppGids == NULL) {
+ lcc->nSuppGids = 0;
+ } else {
+ int i;
+ for (i = 0 ; i < lcc->nSuppGids; i++) {
+ (lcc->pSuppGids)[i] = (int) gids[i];
+ }
+ }
+ } else {
+ lcc->nSuppGids = 0;
+ }
+ ucred_free(peercred);
+ return 0;
+#elif defined(SO_PEERCRED)
+ if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) == -1) {
+ FreeLocalClientCreds(lcc);
+ return -1;
+ }
+ lcc->euid = peercred.uid;
+ lcc->egid = peercred.gid;
+ lcc->pid = peercred.pid;
+ lcc->fieldsSet = LCC_UID_SET | LCC_GID_SET | LCC_PID_SET;
+ return 0;
+#endif
+#else
+ /* No system call available to get the credentials of the peer */
+#define NO_LOCAL_CLIENT_CRED
+ return -1;
+#endif
+}
+
+void
+FreeLocalClientCreds(LocalClientCredRec *lcc)
+{
+ if (lcc != NULL) {
+ if (lcc->nSuppGids > 0) {
+ free(lcc->pSuppGids);
+ }
+ free(lcc);
+ }
+}
+
+static int
+AuthorizedClient(ClientPtr client)
+{
+ int rc;
+
+ if (!client || defeatAccessControl)
+ return Success;
+
+ /* untrusted clients can't change host access */
+ rc = XaceHook(XACE_SERVER_ACCESS, client, DixManageAccess);
+ if (rc != Success)
+ return rc;
+
+ return LocalClient(client) ? Success : BadAccess;
+}
+
+/* Add a host to the access control list. This is the external interface
+ * called from the dispatcher */
+
+int
+AddHost (ClientPtr client,
+ int family,
+ unsigned length, /* of bytes in pAddr */
+ const void * pAddr)
+{
+ int rc, len;
+
+ rc = AuthorizedClient(client);
+ if (rc != Success)
+ return rc;
+ switch (family) {
+ case FamilyLocalHost:
+ len = length;
+ LocalHostEnabled = TRUE;
+ break;
+#ifdef SECURE_RPC
+ case FamilyNetname:
+ len = length;
+ SecureRPCInit ();
+ break;
+#endif
+ case FamilyInternet:
+#if defined(IPv6) && defined(AF_INET6)
+ case FamilyInternet6:
+#endif
+ case FamilyDECnet:
+ case FamilyChaos:
+ case FamilyServerInterpreted:
+ if ((len = CheckAddr (family, pAddr, length)) < 0)
+ {
+ client->errorValue = length;
+ return BadValue;
+ }
+ break;
+ case FamilyLocal:
+ default:
+ client->errorValue = family;
+ return BadValue;
+ }
+ if (NewHost (family, pAddr, len, FALSE))
+ return Success;
+ return BadAlloc;
+}
+
+Bool
+ForEachHostInFamily (int family,
+ Bool (*func)(
+ unsigned char * /* addr */,
+ short /* len */,
+ pointer /* closure */),
+ pointer closure)
+{
+ HOST *host;
+
+ for (host = validhosts; host; host = host->next)
+ if (family == host->family && func (host->addr, host->len, closure))
+ return TRUE;
+ return FALSE;
+}
+
+/* Add a host to the access control list. This is the internal interface
+ * called when starting or resetting the server */
+static Bool
+NewHost (int family,
+ const void * addr,
+ int len,
+ int addingLocalHosts)
+{
+ register HOST *host;
+
+ for (host = validhosts; host; host = host->next)
+ {
+ if (addrEqual (family, addr, len, host))
+ return TRUE;
+ }
+ if (!addingLocalHosts) { /* Fix for XFree86 bug #156 */
+ for (host = selfhosts; host; host = host->next) {
+ if (addrEqual (family, addr, len, host)) {
+ host->requested = TRUE;
+ break;
+ }
+ }
+ }
+ MakeHost(host,len)
+ if (!host)
+ return FALSE;
+ host->family = family;
+ host->len = len;
+ acopy(addr, host->addr, len);
+ host->next = validhosts;
+ validhosts = host;
+ return TRUE;
+}
+
+/* Remove a host from the access control list */
+
+int
+RemoveHost (
+ ClientPtr client,
+ int family,
+ unsigned length, /* of bytes in pAddr */
+ pointer pAddr)
+{
+ int rc, len;
+ register HOST *host, **prev;
+
+ rc = AuthorizedClient(client);
+ if (rc != Success)
+ return rc;
+ switch (family) {
+ case FamilyLocalHost:
+ len = length;
+ LocalHostEnabled = FALSE;
+ break;
+#ifdef SECURE_RPC
+ case FamilyNetname:
+ len = length;
+ break;
+#endif
+ case FamilyInternet:
+#if defined(IPv6) && defined(AF_INET6)
+ case FamilyInternet6:
+#endif
+ case FamilyDECnet:
+ case FamilyChaos:
+ case FamilyServerInterpreted:
+ if ((len = CheckAddr (family, pAddr, length)) < 0)
+ {
+ client->errorValue = length;
+ return BadValue;
+ }
+ break;
+ case FamilyLocal:
+ default:
+ client->errorValue = family;
+ return BadValue;
+ }
+ for (prev = &validhosts;
+ (host = *prev) && (!addrEqual (family, pAddr, len, host));
+ prev = &host->next)
+ ;
+ if (host)
+ {
+ *prev = host->next;
+ FreeHost (host);
+ }
+ return Success;
+}
+
+/* Get all hosts in the access control list */
+int
+GetHosts (
+ pointer *data,
+ int *pnHosts,
+ int *pLen,
+ BOOL *pEnabled)
+{
+ int len;
+ register int n = 0;
+ register unsigned char *ptr;
+ register HOST *host;
+ int nHosts = 0;
+
+ *pEnabled = AccessEnabled ? EnableAccess : DisableAccess;
+ for (host = validhosts; host; host = host->next)
+ {
+ nHosts++;
+ n += pad_to_int32(host->len) + sizeof(xHostEntry);
+ }
+ if (n)
+ {
+ *data = ptr = malloc(n);
+ if (!ptr)
+ {
+ return BadAlloc;
+ }
+ for (host = validhosts; host; host = host->next)
+ {
+ len = host->len;
+ ((xHostEntry *)ptr)->family = host->family;
+ ((xHostEntry *)ptr)->length = len;
+ ptr += sizeof(xHostEntry);
+ acopy (host->addr, ptr, len);
+ ptr += pad_to_int32(len);
+ }
+ } else {
+ *data = NULL;
+ }
+ *pnHosts = nHosts;
+ *pLen = n;
+ return Success;
+}
+
+/* Check for valid address family and length, and return address length. */
+
+/*ARGSUSED*/
+static int
+CheckAddr (
+ int family,
+ const void * pAddr,
+ unsigned length)
+{
+ int len;
+
+ switch (family)
+ {
+#if defined(TCPCONN) || defined(STREAMSCONN)
+ case FamilyInternet:
+ if (length == sizeof (struct in_addr))
+ len = length;
+ else
+ len = -1;
+ break;
+#if defined(IPv6) && defined(AF_INET6)
+ case FamilyInternet6:
+ if (length == sizeof (struct in6_addr))
+ len = length;
+ else
+ len = -1;
+ break;
+#endif
+#endif
+ case FamilyServerInterpreted:
+ len = siCheckAddr(pAddr, length);
+ break;
+ default:
+ len = -1;
+ }
+ return len;
+}
+
+/* Check if a host is not in the access control list.
+ * Returns 1 if host is invalid, 0 if we've found it. */
+
+int
+InvalidHost (
+ register struct sockaddr *saddr,
+ int len,
+ ClientPtr client)
+{
+ int family;
+ pointer addr;
+ register HOST *selfhost, *host;
+
+ if (!AccessEnabled) /* just let them in */
+ return 0;
+ family = ConvertAddr (saddr, &len, (pointer *)&addr);
+ if (family == -1)
+ return 1;
+ if (family == FamilyLocal)
+ {
+ if (!LocalHostEnabled)
+ {
+ /*
+ * check to see if any local address is enabled. This
+ * implicitly enables local connections.
+ */
+ for (selfhost = selfhosts; selfhost; selfhost=selfhost->next)
+ {
+ for (host = validhosts; host; host=host->next)
+ {
+ if (addrEqual (selfhost->family, selfhost->addr,
+ selfhost->len, host))
+ return 0;
+ }
+ }
+ } else
+ return 0;
+ }
+ for (host = validhosts; host; host = host->next)
+ {
+ if ((host->family == FamilyServerInterpreted)) {
+ if (siAddrMatch (family, addr, len, host, client)) {
+ return 0;
+ }
+ } else {
+ if (addrEqual (family, addr, len, host))
+ return 0;
+ }
+
+ }
+ return 1;
+}
+
+static int
+ConvertAddr (
+ register struct sockaddr *saddr,
+ int *len,
+ pointer *addr)
+{
+ if (*len == 0)
+ return FamilyLocal;
+ switch (saddr->sa_family)
+ {
+ case AF_UNSPEC:
+#if defined(UNIXCONN) || defined(LOCALCONN)
+ case AF_UNIX:
+#endif
+ return FamilyLocal;
+#if defined(TCPCONN) || defined(STREAMSCONN)
+ case AF_INET:
+#ifdef WIN32
+ if (16777343 == *(long*)&((struct sockaddr_in *) saddr)->sin_addr)
+ return FamilyLocal;
+#endif
+ *len = sizeof (struct in_addr);
+ *addr = (pointer) &(((struct sockaddr_in *) saddr)->sin_addr);
+ return FamilyInternet;
+#if defined(IPv6) && defined(AF_INET6)
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *) saddr;
+ if (IN6_IS_ADDR_V4MAPPED(&(saddr6->sin6_addr))) {
+ *len = sizeof (struct in_addr);
+ *addr = (pointer) &(saddr6->sin6_addr.s6_addr[12]);
+ return FamilyInternet;
+ } else {
+ *len = sizeof (struct in6_addr);
+ *addr = (pointer) &(saddr6->sin6_addr);
+ return FamilyInternet6;
+ }
+ }
+#endif
+#endif
+ default:
+ return -1;
+ }
+}
+
+int
+ChangeAccessControl(
+ ClientPtr client,
+ int fEnabled)
+{
+ int rc = AuthorizedClient(client);
+ if (rc != Success)
+ return rc;
+ AccessEnabled = fEnabled;
+ return Success;
+}
+
+/* returns FALSE if xhost + in effect, else TRUE */
+int
+GetAccessControl(void)
+{
+ return AccessEnabled;
+}
+
+/*****************************************************************************
+ * FamilyServerInterpreted host entry implementation
+ *
+ * Supports an extensible system of host types which the server can interpret
+ * See the IPv6 extensions to the X11 protocol spec for the definition.
+ *
+ * Currently supported schemes:
+ *
+ * hostname - hostname as defined in IETF RFC 2396
+ * ipv6 - IPv6 literal address as defined in IETF RFC's 3513 and <TBD>
+ *
+ * See xc/doc/specs/SIAddresses for formal definitions of each type.
+ */
+
+/* These definitions and the siTypeAdd function could be exported in the
+ * future to enable loading additional host types, but that was not done for
+ * the initial implementation.
+ */
+typedef Bool (*siAddrMatchFunc)(int family, pointer addr, int len,
+ const char *siAddr, int siAddrlen, ClientPtr client, void *siTypePriv);
+typedef int (*siCheckAddrFunc)(const char *addrString, int length,
+ void *siTypePriv);
+
+struct siType {
+ struct siType * next;
+ const char * typeName;
+ siAddrMatchFunc addrMatch;
+ siCheckAddrFunc checkAddr;
+ void * typePriv; /* Private data for type routines */
+};
+
+static struct siType *siTypeList;
+
+static int
+siTypeAdd(const char *typeName, siAddrMatchFunc addrMatch,
+ siCheckAddrFunc checkAddr, void *typePriv)
+{
+ struct siType *s, *p;
+
+ if ((typeName == NULL) || (addrMatch == NULL) || (checkAddr == NULL))
+ return BadValue;
+
+ for (s = siTypeList, p = NULL; s != NULL ; p = s, s = s->next) {
+ if (strcmp(typeName, s->typeName) == 0) {
+ s->addrMatch = addrMatch;
+ s->checkAddr = checkAddr;
+ s->typePriv = typePriv;
+ return Success;
+ }
+ }
+
+ s = malloc(sizeof(struct siType));
+ if (s == NULL)
+ return BadAlloc;
+
+ if (p == NULL)
+ siTypeList = s;
+ else
+ p->next = s;
+
+ s->next = NULL;
+ s->typeName = typeName;
+ s->addrMatch = addrMatch;
+ s->checkAddr = checkAddr;
+ s->typePriv = typePriv;
+ return Success;
+}
+
+/* Checks to see if a host matches a server-interpreted host entry */
+static Bool
+siAddrMatch(int family, pointer addr, int len, HOST *host, ClientPtr client)
+{
+ Bool matches = FALSE;
+ struct siType *s;
+ const char *valueString;
+ int addrlen;
+
+ valueString = (const char *) memchr(host->addr, '\0', host->len);
+ if (valueString != NULL) {
+ for (s = siTypeList; s != NULL ; s = s->next) {
+ if (strcmp((char *) host->addr, s->typeName) == 0) {
+ addrlen = host->len - (strlen((char *)host->addr) + 1);
+ matches = s->addrMatch(family, addr, len,
+ valueString + 1, addrlen, client, s->typePriv);
+ break;
+ }
+ }
+#ifdef FAMILY_SI_DEBUG
+ ErrorF(
+ "Xserver: siAddrMatch(): type = %s, value = %*.*s -- %s\n",
+ host->addr, addrlen, addrlen, valueString + 1,
+ (matches) ? "accepted" : "rejected");
+#endif
+ }
+ return matches;
+}
+
+static int
+siCheckAddr(const char *addrString, int length)
+{
+ const char *valueString;
+ int addrlen, typelen;
+ int len = -1;
+ struct siType *s;
+
+ /* Make sure there is a \0 byte inside the specified length
+ to separate the address type from the address value. */
+ valueString = (const char *) memchr(addrString, '\0', length);
+ if (valueString != NULL) {
+ /* Make sure the first string is a recognized address type,
+ * and the second string is a valid address of that type.
+ */
+ typelen = strlen(addrString) + 1;
+ addrlen = length - typelen;
+
+ for (s = siTypeList; s != NULL ; s = s->next) {
+ if (strcmp(addrString, s->typeName) == 0) {
+ len = s->checkAddr(valueString + 1, addrlen, s->typePriv);
+ if (len >= 0) {
+ len += typelen;
+ }
+ break;
+ }
+ }
+#ifdef FAMILY_SI_DEBUG
+ {
+ const char *resultMsg;
+
+ if (s == NULL) {
+ resultMsg = "type not registered";
+ } else {
+ if (len == -1)
+ resultMsg = "rejected";
+ else
+ resultMsg = "accepted";
+ }
+
+ ErrorF("Xserver: siCheckAddr(): type = %s, value = %*.*s, len = %d -- %s\n",
+ addrString, addrlen, addrlen, valueString + 1, len, resultMsg);
+ }
+#endif
+ }
+ return len;
+}
+
+
+/***
+ * Hostname server-interpreted host type
+ *
+ * Stored as hostname string, explicitly defined to be resolved ONLY
+ * at access check time, to allow for hosts with dynamic addresses
+ * but static hostnames, such as found in some DHCP & mobile setups.
+ *
+ * Hostname must conform to IETF RFC 2396 sec. 3.2.2, which defines it as:
+ * hostname = *( domainlabel "." ) toplabel [ "." ]
+ * domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
+ * toplabel = alpha | alpha *( alphanum | "-" ) alphanum
+ */
+
+#ifdef NI_MAXHOST
+# define SI_HOSTNAME_MAXLEN NI_MAXHOST
+#else
+# ifdef MAXHOSTNAMELEN
+# define SI_HOSTNAME_MAXLEN MAXHOSTNAMELEN
+# else
+# define SI_HOSTNAME_MAXLEN 256
+# endif
+#endif
+
+static Bool
+siHostnameAddrMatch(int family, pointer addr, int len,
+ const char *siAddr, int siAddrLen, ClientPtr client, void *typePriv)
+{
+ Bool res = FALSE;
+
+/* Currently only supports checking against IPv4 & IPv6 connections, but
+ * support for other address families, such as DECnet, could be added if
+ * desired.
+ */
+#if defined(IPv6) && defined(AF_INET6)
+ if ((family == FamilyInternet) || (family == FamilyInternet6)) {
+ char hostname[SI_HOSTNAME_MAXLEN];
+ struct addrinfo *addresses;
+ struct addrinfo *a;
+ int f, hostaddrlen;
+ pointer hostaddr;
+
+ if (siAddrLen >= sizeof(hostname))
+ return FALSE;
+
+ strncpy(hostname, siAddr, siAddrLen);
+ hostname[siAddrLen] = '\0';
+
+ if (getaddrinfo(hostname, NULL, NULL, &addresses) == 0) {
+ for (a = addresses ; a != NULL ; a = a->ai_next) {
+ hostaddrlen = a->ai_addrlen;
+ f = ConvertAddr(a->ai_addr,&hostaddrlen,&hostaddr);
+ if ((f == family) && (len == hostaddrlen) &&
+ (acmp (addr, hostaddr, len) == 0) ) {
+ res = TRUE;
+ break;
+ }
+ }
+ freeaddrinfo(addresses);
+ }
+ }
+#else /* IPv6 not supported, use gethostbyname instead for IPv4 */
+ if (family == FamilyInternet) {
+ register struct hostent *hp;
+#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
+ _Xgethostbynameparams hparams;
+#endif
+ char hostname[SI_HOSTNAME_MAXLEN];
+ int f, hostaddrlen;
+ pointer hostaddr;
+ const char **addrlist;
+
+ if (siAddrLen >= sizeof(hostname))
+ return FALSE;
+
+ strncpy(hostname, siAddr, siAddrLen);
+ hostname[siAddrLen] = '\0';
+
+ if ((hp = _XGethostbyname(hostname, hparams)) != NULL) {
+#ifdef h_addr /* new 4.3bsd version of gethostent */
+ /* iterate over the addresses */
+ for (addrlist = hp->h_addr_list; *addrlist; addrlist++)
+#else
+ addrlist = &hp->h_addr;
+#endif
+ {
+ struct sockaddr_in sin;
+
+ sin.sin_family = hp->h_addrtype;
+ acopy ( *addrlist, &(sin.sin_addr), hp->h_length);
+ hostaddrlen = sizeof(sin);
+ f = ConvertAddr ((struct sockaddr *)&sin,
+ &hostaddrlen, &hostaddr);
+ if ((f == family) && (len == hostaddrlen) &&
+ (acmp (addr, hostaddr, len) == 0) ) {
+ res = TRUE;
+ break;
+ }
+ }
+ }
+ }
+#endif
+ return res;
+}
+
+
+static int
+siHostnameCheckAddr(const char *valueString, int length, void *typePriv)
+{
+ /* Check conformance of hostname to RFC 2396 sec. 3.2.2 definition.
+ * We do not use ctype functions here to avoid locale-specific
+ * character sets. Hostnames must be pure ASCII.
+ */
+ int len = length;
+ int i;
+ Bool dotAllowed = FALSE;
+ Bool dashAllowed = FALSE;
+
+ if ((length <= 0) || (length >= SI_HOSTNAME_MAXLEN)) {
+ len = -1;
+ } else {
+ for (i = 0; i < length; i++) {
+ char c = valueString[i];
+
+ if (c == 0x2E) { /* '.' */
+ if (dotAllowed == FALSE) {
+ len = -1;
+ break;
+ } else {
+ dotAllowed = FALSE;
+ dashAllowed = FALSE;
+ }
+ } else if (c == 0x2D) { /* '-' */
+ if (dashAllowed == FALSE) {
+ len = -1;
+ break;
+ } else {
+ dotAllowed = FALSE;
+ }
+ } else if (((c >= 0x30) && (c <= 0x3A)) /* 0-9 */ ||
+ ((c >= 0x61) && (c <= 0x7A)) /* a-z */ ||
+ ((c >= 0x41) && (c <= 0x5A)) /* A-Z */) {
+ dotAllowed = TRUE;
+ dashAllowed = TRUE;
+ } else { /* Invalid character */
+ len = -1;
+ break;
+ }
+ }
+ }
+ return len;
+}
+
+#if defined(IPv6) && defined(AF_INET6)
+/***
+ * "ipv6" server interpreted type
+ *
+ * Currently supports only IPv6 literal address as specified in IETF RFC 3513
+ *
+ * Once draft-ietf-ipv6-scoping-arch-00.txt becomes an RFC, support will be
+ * added for the scoped address format it specifies.
+ */
+
+/* Maximum length of an IPv6 address string - increase when adding support
+ * for scoped address qualifiers. Includes room for trailing NUL byte.
+ */
+#define SI_IPv6_MAXLEN INET6_ADDRSTRLEN
+
+static Bool
+siIPv6AddrMatch(int family, pointer addr, int len,
+ const char *siAddr, int siAddrlen, ClientPtr client, void *typePriv)
+{
+ struct in6_addr addr6;
+ char addrbuf[SI_IPv6_MAXLEN];
+
+ if ((family != FamilyInternet6) || (len != sizeof(addr6)))
+ return FALSE;
+
+ memcpy(addrbuf, siAddr, siAddrlen);
+ addrbuf[siAddrlen] = '\0';
+
+ if (inet_pton(AF_INET6, addrbuf, &addr6) != 1) {
+ perror("inet_pton");
+ return FALSE;
+ }
+
+ if (memcmp(addr, &addr6, len) == 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+static int
+siIPv6CheckAddr(const char *addrString, int length, void *typePriv)
+{
+ int len;
+
+ /* Minimum length is 3 (smallest legal address is "::1") */
+ if (length < 3) {
+ /* Address is too short! */
+ len = -1;
+ } else if (length >= SI_IPv6_MAXLEN) {
+ /* Address is too long! */
+ len = -1;
+ } else {
+ /* Assume inet_pton is sufficient validation */
+ struct in6_addr addr6;
+ char addrbuf[SI_IPv6_MAXLEN];
+
+ memcpy(addrbuf, addrString, length);
+ addrbuf[length] = '\0';
+
+ if (inet_pton(AF_INET6, addrbuf, &addr6) != 1) {
+ perror("inet_pton");
+ len = -1;
+ } else {
+ len = length;
+ }
+ }
+ return len;
+}
+#endif /* IPv6 */
+
+#if !defined(NO_LOCAL_CLIENT_CRED)
+/***
+ * "localuser" & "localgroup" server interpreted types
+ *
+ * Allows local connections from a given local user or group
+ */
+
+#include <pwd.h>
+#include <grp.h>
+
+#define LOCAL_USER 1
+#define LOCAL_GROUP 2
+
+typedef struct {
+ int credType;
+} siLocalCredPrivRec, *siLocalCredPrivPtr;
+
+static siLocalCredPrivRec siLocalUserPriv = { LOCAL_USER };
+static siLocalCredPrivRec siLocalGroupPriv = { LOCAL_GROUP };
+
+static Bool
+siLocalCredGetId(const char *addr, int len, siLocalCredPrivPtr lcPriv, int *id)
+{
+ Bool parsedOK = FALSE;
+ char *addrbuf = malloc(len + 1);
+
+ if (addrbuf == NULL) {
+ return FALSE;
+ }
+
+ memcpy(addrbuf, addr, len);
+ addrbuf[len] = '\0';
+
+ if (addr[0] == '#') { /* numeric id */
+ char *cp;
+ errno = 0;
+ *id = strtol(addrbuf + 1, &cp, 0);
+ if ((errno == 0) && (cp != (addrbuf+1))) {
+ parsedOK = TRUE;
+ }
+ } else { /* non-numeric name */
+ if (lcPriv->credType == LOCAL_USER) {
+ struct passwd *pw = getpwnam(addrbuf);
+
+ if (pw != NULL) {
+ *id = (int) pw->pw_uid;
+ parsedOK = TRUE;
+ }
+ } else { /* group */
+ struct group *gr = getgrnam(addrbuf);
+
+ if (gr != NULL) {
+ *id = (int) gr->gr_gid;
+ parsedOK = TRUE;
+ }
+ }
+ }
+
+ free(addrbuf);
+ return parsedOK;
+}
+
+static Bool
+siLocalCredAddrMatch(int family, pointer addr, int len,
+ const char *siAddr, int siAddrlen, ClientPtr client, void *typePriv)
+{
+ int siAddrId;
+ LocalClientCredRec *lcc;
+ siLocalCredPrivPtr lcPriv = (siLocalCredPrivPtr) typePriv;
+
+ if (GetLocalClientCreds(client, &lcc) == -1) {
+ return FALSE;
+ }
+
+#ifdef HAVE_GETZONEID /* Ensure process is in the same zone */
+ if ((lcc->fieldsSet & LCC_ZID_SET) && (lcc->zoneid != getzoneid())) {
+ FreeLocalClientCreds(lcc);
+ return FALSE;
+ }
+#endif
+
+ if (siLocalCredGetId(siAddr, siAddrlen, lcPriv, &siAddrId) == FALSE) {
+ FreeLocalClientCreds(lcc);
+ return FALSE;
+ }
+
+ if (lcPriv->credType == LOCAL_USER) {
+ if ((lcc->fieldsSet & LCC_UID_SET) && (lcc->euid == siAddrId)) {
+ FreeLocalClientCreds(lcc);
+ return TRUE;
+ }
+ } else {
+ if ((lcc->fieldsSet & LCC_GID_SET) && (lcc->egid == siAddrId)) {
+ FreeLocalClientCreds(lcc);
+ return TRUE;
+ }
+ if (lcc->pSuppGids != NULL) {
+ int i;
+
+ for (i = 0 ; i < lcc->nSuppGids; i++) {
+ if (lcc->pSuppGids[i] == siAddrId) {
+ FreeLocalClientCreds(lcc);
+ return TRUE;
+ }
+ }
+ }
+ }
+ FreeLocalClientCreds(lcc);
+ return FALSE;
+}
+
+static int
+siLocalCredCheckAddr(const char *addrString, int length, void *typePriv)
+{
+ int len = length;
+ int id;
+
+ if (siLocalCredGetId(addrString, length,
+ (siLocalCredPrivPtr)typePriv, &id) == FALSE) {
+ len = -1;
+ }
+ return len;
+}
+#endif /* localuser */
+
+static void
+siTypesInitialize(void)
+{
+ siTypeAdd("hostname", siHostnameAddrMatch, siHostnameCheckAddr, NULL);
+#if defined(IPv6) && defined(AF_INET6)
+ siTypeAdd("ipv6", siIPv6AddrMatch, siIPv6CheckAddr, NULL);
+#endif
+#if !defined(NO_LOCAL_CLIENT_CRED)
+ siTypeAdd("localuser", siLocalCredAddrMatch, siLocalCredCheckAddr,
+ &siLocalUserPriv);
+ siTypeAdd("localgroup", siLocalCredAddrMatch, siLocalCredCheckAddr,
+ &siLocalGroupPriv);
+#endif
+}