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