xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

access.c (61046B)


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