"Fossies" - the Fresh Open Source Software Archive

Member "xorg-server-1.20.5/os/access.c" (30 May 2019, 61087 Bytes) of package /linux/misc/xorg-server-1.20.5.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "access.c" see the Fossies "Dox" file reference documentation.

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