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