tizen 2.4 release
[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 #if defined(IPv6) && defined(AF_INET6)
167 #include <arpa/inet.h>
168 #endif
169
170 #endif                          /* WIN32 */
171
172 #define X_INCLUDE_NETDB_H
173 #include <X11/Xos_r.h>
174
175 #include "dixstruct.h"
176 #include "osdep.h"
177
178 #include "xace.h"
179
180 Bool defeatAccessControl = FALSE;
181
182 #define addrEqual(fam, address, length, host) \
183                          ((fam) == (host)->family &&\
184                           (length) == (host)->len &&\
185                           !memcmp (address, (host)->addr, length))
186
187 static int ConvertAddr(struct sockaddr * /*saddr */ ,
188                        int * /*len */ ,
189                        void ** /*addr */ );
190
191 static int CheckAddr(int /*family */ ,
192                      const void * /*pAddr */ ,
193                      unsigned /*length */ );
194
195 static Bool NewHost(int /*family */ ,
196                     const void * /*addr */ ,
197                     int /*len */ ,
198                     int /* addingLocalHosts */ );
199
200 /* XFree86 bug #156: To keep track of which hosts were explicitly requested in
201    /etc/X<display>.hosts, we've added a requested field to the HOST struct,
202    and a LocalHostRequested variable.  These default to FALSE, but are set
203    to TRUE in ResetHosts when reading in /etc/X<display>.hosts.  They are
204    checked in DisableLocalHost(), which is called to disable the default 
205    local host entries when stronger authentication is turned on. */
206
207 typedef struct _host {
208     short family;
209     short len;
210     unsigned char *addr;
211     struct _host *next;
212     int requested;
213 } HOST;
214
215 #define MakeHost(h,l)   (h)=malloc(sizeof *(h)+(l));\
216                         if (h) { \
217                            (h)->addr=(unsigned char *) ((h) + 1);\
218                            (h)->requested = FALSE; \
219                         }
220 #define FreeHost(h)     free(h)
221 static HOST *selfhosts = NULL;
222 static HOST *validhosts = NULL;
223 static int AccessEnabled = DEFAULT_ACCESS_CONTROL;
224 static int LocalHostEnabled = FALSE;
225 static int LocalHostRequested = FALSE;
226 static int UsingXdmcp = FALSE;
227
228 /* FamilyServerInterpreted implementation */
229 static Bool siAddrMatch(int family, void *addr, int len, HOST * host,
230                         ClientPtr client);
231 static int siCheckAddr(const char *addrString, int length);
232 static void siTypesInitialize(void);
233
234 /*
235  * called when authorization is not enabled to add the
236  * local host to the access list
237  */
238
239 void
240 EnableLocalHost(void)
241 {
242     if (!UsingXdmcp) {
243         LocalHostEnabled = TRUE;
244         AddLocalHosts();
245     }
246 }
247
248 /*
249  * called when authorization is enabled to keep us secure
250  */
251 void
252 DisableLocalHost(void)
253 {
254     HOST *self;
255
256     if (!LocalHostRequested)    /* Fix for XFree86 bug #156 */
257         LocalHostEnabled = FALSE;
258     for (self = selfhosts; self; self = self->next) {
259         if (!self->requested)   /* Fix for XFree86 bug #156 */
260             (void) RemoveHost((ClientPtr) NULL, self->family, self->len,
261                               (void *) self->addr);
262     }
263 }
264
265 /*
266  * called at init time when XDMCP will be used; xdmcp always
267  * adds local hosts manually when needed
268  */
269
270 void
271 AccessUsingXdmcp(void)
272 {
273     UsingXdmcp = TRUE;
274     LocalHostEnabled = FALSE;
275 }
276
277 #if  defined(SVR4) && !defined(sun)  && defined(SIOCGIFCONF) && !defined(USE_SIOCGLIFCONF)
278
279 /* Deal with different SIOCGIFCONF ioctl semantics on these OSs */
280
281 static int
282 ifioctl(int fd, int cmd, char *arg)
283 {
284     struct strioctl ioc;
285     int ret;
286
287     memset((char *) &ioc, 0, sizeof(ioc));
288     ioc.ic_cmd = cmd;
289     ioc.ic_timout = 0;
290     if (cmd == SIOCGIFCONF) {
291         ioc.ic_len = ((struct ifconf *) arg)->ifc_len;
292         ioc.ic_dp = ((struct ifconf *) arg)->ifc_buf;
293     }
294     else {
295         ioc.ic_len = sizeof(struct ifreq);
296         ioc.ic_dp = arg;
297     }
298     ret = ioctl(fd, I_STR, (char *) &ioc);
299     if (ret >= 0 && cmd == SIOCGIFCONF)
300 #ifdef SVR4
301         ((struct ifconf *) arg)->ifc_len = ioc.ic_len;
302 #endif
303     return ret;
304 }
305 #else
306 #define ifioctl ioctl
307 #endif
308
309 /*
310  * DefineSelf (fd):
311  *
312  * Define this host for access control.  Find all the hosts the OS knows about 
313  * for this fd and add them to the selfhosts list.
314  */
315
316 #if !defined(SIOCGIFCONF)
317 void
318 DefineSelf(int fd)
319 {
320 #if !defined(TCPCONN) && !defined(STREAMSCONN) && !defined(UNIXCONN)
321     return;
322 #else
323     register int n;
324     int len;
325     caddr_t addr;
326     int family;
327     register HOST *host;
328
329 #ifndef WIN32
330     struct utsname name;
331 #else
332     struct {
333         char nodename[512];
334     } name;
335 #endif
336
337     register struct hostent *hp;
338
339     union {
340         struct sockaddr sa;
341         struct sockaddr_in in;
342 #if defined(IPv6) && defined(AF_INET6)
343         struct sockaddr_in6 in6;
344 #endif
345     } saddr;
346
347     struct sockaddr_in *inetaddr;
348     struct sockaddr_in6 *inet6addr;
349     struct sockaddr_in broad_addr;
350
351 #ifdef XTHREADS_NEEDS_BYNAMEPARAMS
352     _Xgethostbynameparams hparams;
353 #endif
354
355     /* Why not use gethostname()?  Well, at least on my system, I've had to
356      * make an ugly kernel patch to get a name longer than 8 characters, and
357      * uname() lets me access to the whole string (it smashes release, you
358      * see), whereas gethostname() kindly truncates it for me.
359      */
360 #ifndef WIN32
361     uname(&name);
362 #else
363     gethostname(name.nodename, sizeof(name.nodename));
364 #endif
365
366     hp = _XGethostbyname(name.nodename, hparams);
367     if (hp != NULL) {
368         saddr.sa.sa_family = hp->h_addrtype;
369         switch (hp->h_addrtype) {
370         case AF_INET:
371             inetaddr = (struct sockaddr_in *) (&(saddr.sa));
372             memcpy(&(inetaddr->sin_addr), hp->h_addr, hp->h_length);
373             len = sizeof(saddr.sa);
374             break;
375 #if defined(IPv6) && defined(AF_INET6)
376         case AF_INET6:
377             inet6addr = (struct sockaddr_in6 *) (&(saddr.sa));
378             memcpy(&(inet6addr->sin6_addr), hp->h_addr, hp->h_length);
379             len = sizeof(saddr.in6);
380             break;
381 #endif
382         default:
383             goto DefineLocalHost;
384         }
385         family = ConvertAddr(&(saddr.sa), &len, (void **) &addr);
386         if (family != -1 && family != FamilyLocal) {
387             for (host = selfhosts;
388                  host && !addrEqual(family, addr, len, host);
389                  host = host->next);
390             if (!host) {
391                 /* add this host to the host list.      */
392                 MakeHost(host, len)
393                     if (host) {
394                     host->family = family;
395                     host->len = len;
396                     memcpy(host->addr, addr, len);
397                     host->next = selfhosts;
398                     selfhosts = host;
399                 }
400 #ifdef XDMCP
401                 /*
402                  *  If this is an Internet Address, but not the localhost
403                  *  address (127.0.0.1), nor the bogus address (0.0.0.0),
404                  *  register it.
405                  */
406                 if (family == FamilyInternet &&
407                     !(len == 4 &&
408                       ((addr[0] == 127) ||
409                        (addr[0] == 0 && addr[1] == 0 &&
410                         addr[2] == 0 && addr[3] == 0)))
411                     ) {
412                     XdmcpRegisterConnection(family, (char *) addr, len);
413                     broad_addr = *inetaddr;
414                     ((struct sockaddr_in *) &broad_addr)->sin_addr.s_addr =
415                         htonl(INADDR_BROADCAST);
416                     XdmcpRegisterBroadcastAddress((struct sockaddr_in *)
417                                                   &broad_addr);
418                 }
419 #if defined(IPv6) && defined(AF_INET6)
420                 else if (family == FamilyInternet6 &&
421                          !(IN6_IS_ADDR_LOOPBACK((struct in6_addr *) addr))) {
422                     XdmcpRegisterConnection(family, (char *) addr, len);
423                 }
424 #endif
425
426 #endif                          /* XDMCP */
427             }
428         }
429     }
430     /*
431      * now add a host of family FamilyLocalHost...
432      */
433  DefineLocalHost:
434     for (host = selfhosts;
435          host && !addrEqual(FamilyLocalHost, "", 0, host); host = host->next);
436     if (!host) {
437         MakeHost(host, 0);
438         if (host) {
439             host->family = FamilyLocalHost;
440             host->len = 0;
441             /* Nothing to store in host->addr */
442             host->next = selfhosts;
443             selfhosts = host;
444         }
445     }
446 #endif                          /* !TCPCONN && !STREAMSCONN && !UNIXCONN */
447 }
448
449 #else
450
451 #ifdef USE_SIOCGLIFCONF
452 #define ifr_type    struct lifreq
453 #else
454 #define ifr_type    struct ifreq
455 #endif
456
457 #ifdef VARIABLE_IFREQ
458 #define ifr_size(p) (sizeof (struct ifreq) + \
459                      (p->ifr_addr.sa_len > sizeof (p->ifr_addr) ? \
460                       p->ifr_addr.sa_len - sizeof (p->ifr_addr) : 0))
461 #define ifraddr_size(a) (a.sa_len)
462 #else
463 #define ifr_size(p) (sizeof (ifr_type))
464 #define ifraddr_size(a) (sizeof (a))
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, (void *) &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, (void **) &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, (void *) &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, (void *) &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                              (void **) &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(void *from, int len)
779 {
780     int family;
781     void *addr;
782     register HOST *host;
783
784     family = ConvertAddr(from, &len, (void **) &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(const 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     void *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                                             (void **) &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                                      (void **) &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, (void *) *list, len, FALSE);
960 #else
961                         (void) NewHost(family, (void *) 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     void *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, (void **) &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 /*
1011  * Return the uid and gid of a connected local client
1012  * 
1013  * Used by XShm to test access rights to shared memory segments
1014  */
1015 int
1016 LocalClientCred(ClientPtr client, int *pUid, int *pGid)
1017 {
1018     LocalClientCredRec *lcc;
1019     int ret = GetLocalClientCreds(client, &lcc);
1020
1021     if (ret == 0) {
1022 #ifdef HAVE_GETZONEID           /* only local if in the same zone */
1023         if ((lcc->fieldsSet & LCC_ZID_SET) && (lcc->zoneid != getzoneid())) {
1024             FreeLocalClientCreds(lcc);
1025             return -1;
1026         }
1027 #endif
1028         if ((lcc->fieldsSet & LCC_UID_SET) && (pUid != NULL))
1029             *pUid = lcc->euid;
1030         if ((lcc->fieldsSet & LCC_GID_SET) && (pGid != NULL))
1031             *pGid = lcc->egid;
1032         FreeLocalClientCreds(lcc);
1033     }
1034     return ret;
1035 }
1036
1037 /*
1038  * Return the uid and all gids of a connected local client
1039  * Allocates a LocalClientCredRec - caller must call FreeLocalClientCreds
1040  * 
1041  * Used by localuser & localgroup ServerInterpreted access control forms below
1042  * Used by AuthAudit to log who local connections came from
1043  */
1044 int
1045 GetLocalClientCreds(ClientPtr client, LocalClientCredRec ** lccp)
1046 {
1047 #if defined(HAVE_GETPEEREID) || defined(HAVE_GETPEERUCRED) || defined(SO_PEERCRED)
1048     int fd;
1049     XtransConnInfo ci;
1050     LocalClientCredRec *lcc;
1051
1052 #ifdef HAVE_GETPEEREID
1053     uid_t uid;
1054     gid_t gid;
1055 #elif defined(HAVE_GETPEERUCRED)
1056     ucred_t *peercred = NULL;
1057     const gid_t *gids;
1058 #elif defined(SO_PEERCRED)
1059     struct ucred peercred;
1060     socklen_t so_len = sizeof(peercred);
1061 #endif
1062
1063     if (client == NULL)
1064         return -1;
1065     ci = ((OsCommPtr) client->osPrivate)->trans_conn;
1066 #if !(defined(sun) && defined(HAVE_GETPEERUCRED))
1067     /* Most implementations can only determine peer credentials for Unix 
1068      * domain sockets - Solaris getpeerucred can work with a bit more, so 
1069      * we just let it tell us if the connection type is supported or not
1070      */
1071     if (!_XSERVTransIsLocal(ci)) {
1072         return -1;
1073     }
1074 #endif
1075
1076     *lccp = calloc(1, sizeof(LocalClientCredRec));
1077     if (*lccp == NULL)
1078         return -1;
1079     lcc = *lccp;
1080
1081     fd = _XSERVTransGetConnectionNumber(ci);
1082 #ifdef HAVE_GETPEEREID
1083     if (getpeereid(fd, &uid, &gid) == -1) {
1084         FreeLocalClientCreds(lcc);
1085         return -1;
1086     }
1087     lcc->euid = uid;
1088     lcc->egid = gid;
1089     lcc->fieldsSet = LCC_UID_SET | LCC_GID_SET;
1090     return 0;
1091 #elif defined(HAVE_GETPEERUCRED)
1092     if (getpeerucred(fd, &peercred) < 0) {
1093         FreeLocalClientCreds(lcc);
1094         return -1;
1095     }
1096     lcc->euid = ucred_geteuid(peercred);
1097     if (lcc->euid != -1)
1098         lcc->fieldsSet |= LCC_UID_SET;
1099     lcc->egid = ucred_getegid(peercred);
1100     if (lcc->egid != -1)
1101         lcc->fieldsSet |= LCC_GID_SET;
1102     lcc->pid = ucred_getpid(peercred);
1103     if (lcc->pid != -1)
1104         lcc->fieldsSet |= LCC_PID_SET;
1105 #ifdef HAVE_GETZONEID
1106     lcc->zoneid = ucred_getzoneid(peercred);
1107     if (lcc->zoneid != -1)
1108         lcc->fieldsSet |= LCC_ZID_SET;
1109 #endif
1110     lcc->nSuppGids = ucred_getgroups(peercred, &gids);
1111     if (lcc->nSuppGids > 0) {
1112         lcc->pSuppGids = calloc(lcc->nSuppGids, sizeof(int));
1113         if (lcc->pSuppGids == NULL) {
1114             lcc->nSuppGids = 0;
1115         }
1116         else {
1117             int i;
1118
1119             for (i = 0; i < lcc->nSuppGids; i++) {
1120                 (lcc->pSuppGids)[i] = (int) gids[i];
1121             }
1122         }
1123     }
1124     else {
1125         lcc->nSuppGids = 0;
1126     }
1127     ucred_free(peercred);
1128     return 0;
1129 #elif defined(SO_PEERCRED)
1130     if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) == -1) {
1131         FreeLocalClientCreds(lcc);
1132         return -1;
1133     }
1134     lcc->euid = peercred.uid;
1135     lcc->egid = peercred.gid;
1136     lcc->pid = peercred.pid;
1137     lcc->fieldsSet = LCC_UID_SET | LCC_GID_SET | LCC_PID_SET;
1138     return 0;
1139 #endif
1140 #else
1141     /* No system call available to get the credentials of the peer */
1142 #define NO_LOCAL_CLIENT_CRED
1143     return -1;
1144 #endif
1145 }
1146
1147 void
1148 FreeLocalClientCreds(LocalClientCredRec * lcc)
1149 {
1150     if (lcc != NULL) {
1151         if (lcc->nSuppGids > 0) {
1152             free(lcc->pSuppGids);
1153         }
1154         free(lcc);
1155     }
1156 }
1157
1158 static int
1159 AuthorizedClient(ClientPtr client)
1160 {
1161     int rc;
1162
1163     if (!client || defeatAccessControl)
1164         return Success;
1165
1166     /* untrusted clients can't change host access */
1167     rc = XaceHook(XACE_SERVER_ACCESS, client, DixManageAccess);
1168     if (rc != Success)
1169         return rc;
1170
1171     return client->local ? Success : BadAccess;
1172 }
1173
1174 /* Add a host to the access control list.  This is the external interface
1175  * called from the dispatcher */
1176
1177 int
1178 AddHost(ClientPtr client, int family, unsigned length,  /* of bytes in pAddr */
1179         const void *pAddr)
1180 {
1181     int rc, len;
1182
1183     rc = AuthorizedClient(client);
1184     if (rc != Success)
1185         return rc;
1186     switch (family) {
1187     case FamilyLocalHost:
1188         len = length;
1189         LocalHostEnabled = TRUE;
1190         break;
1191 #ifdef SECURE_RPC
1192     case FamilyNetname:
1193         len = length;
1194         SecureRPCInit();
1195         break;
1196 #endif
1197     case FamilyInternet:
1198 #if defined(IPv6) && defined(AF_INET6)
1199     case FamilyInternet6:
1200 #endif
1201     case FamilyDECnet:
1202     case FamilyChaos:
1203     case FamilyServerInterpreted:
1204         if ((len = CheckAddr(family, pAddr, length)) < 0) {
1205             client->errorValue = length;
1206             return BadValue;
1207         }
1208         break;
1209     case FamilyLocal:
1210     default:
1211         client->errorValue = family;
1212         return BadValue;
1213     }
1214     if (NewHost(family, pAddr, len, FALSE))
1215         return Success;
1216     return BadAlloc;
1217 }
1218
1219 Bool
1220 ForEachHostInFamily(int family, Bool (*func) (unsigned char * /* addr */ ,
1221                                               short /* len */ ,
1222                                               void */* closure */ ),
1223                     void *closure)
1224 {
1225     HOST *host;
1226
1227     for (host = validhosts; host; host = host->next)
1228         if (family == host->family && func(host->addr, host->len, closure))
1229             return TRUE;
1230     return FALSE;
1231 }
1232
1233 /* Add a host to the access control list. This is the internal interface 
1234  * called when starting or resetting the server */
1235 static Bool
1236 NewHost(int family, const void *addr, int len, int addingLocalHosts)
1237 {
1238     register HOST *host;
1239
1240     for (host = validhosts; host; host = host->next) {
1241         if (addrEqual(family, addr, len, host))
1242             return TRUE;
1243     }
1244     if (!addingLocalHosts) {    /* Fix for XFree86 bug #156 */
1245         for (host = selfhosts; host; host = host->next) {
1246             if (addrEqual(family, addr, len, host)) {
1247                 host->requested = TRUE;
1248                 break;
1249             }
1250         }
1251     }
1252     MakeHost(host, len)
1253         if (!host)
1254         return FALSE;
1255     host->family = family;
1256     host->len = len;
1257     memcpy(host->addr, addr, len);
1258     host->next = validhosts;
1259     validhosts = host;
1260     return TRUE;
1261 }
1262
1263 /* Remove a host from the access control list */
1264
1265 int
1266 RemoveHost(ClientPtr client, int family, unsigned length,       /* of bytes in pAddr */
1267            void *pAddr)
1268 {
1269     int rc, len;
1270     register HOST *host, **prev;
1271
1272     rc = AuthorizedClient(client);
1273     if (rc != Success)
1274         return rc;
1275     switch (family) {
1276     case FamilyLocalHost:
1277         len = length;
1278         LocalHostEnabled = FALSE;
1279         break;
1280 #ifdef SECURE_RPC
1281     case FamilyNetname:
1282         len = length;
1283         break;
1284 #endif
1285     case FamilyInternet:
1286 #if defined(IPv6) && defined(AF_INET6)
1287     case FamilyInternet6:
1288 #endif
1289     case FamilyDECnet:
1290     case FamilyChaos:
1291     case FamilyServerInterpreted:
1292         if ((len = CheckAddr(family, pAddr, length)) < 0) {
1293             client->errorValue = length;
1294             return BadValue;
1295         }
1296         break;
1297     case FamilyLocal:
1298     default:
1299         client->errorValue = family;
1300         return BadValue;
1301     }
1302     for (prev = &validhosts;
1303          (host = *prev) && (!addrEqual(family, pAddr, len, host));
1304          prev = &host->next);
1305     if (host) {
1306         *prev = host->next;
1307         FreeHost(host);
1308     }
1309     return Success;
1310 }
1311
1312 /* Get all hosts in the access control list */
1313 int
1314 GetHosts(void **data, int *pnHosts, int *pLen, BOOL * pEnabled)
1315 {
1316     int len;
1317     register int n = 0;
1318     register unsigned char *ptr;
1319     register HOST *host;
1320     int nHosts = 0;
1321
1322     *pEnabled = AccessEnabled ? EnableAccess : DisableAccess;
1323     for (host = validhosts; host; host = host->next) {
1324         nHosts++;
1325         n += pad_to_int32(host->len) + sizeof(xHostEntry);
1326     }
1327     if (n) {
1328         *data = ptr = malloc(n);
1329         if (!ptr) {
1330             return BadAlloc;
1331         }
1332         for (host = validhosts; host; host = host->next) {
1333             len = host->len;
1334             ((xHostEntry *) ptr)->family = host->family;
1335             ((xHostEntry *) ptr)->length = len;
1336             ptr += sizeof(xHostEntry);
1337             memcpy(ptr, host->addr, len);
1338             ptr += pad_to_int32(len);
1339         }
1340     }
1341     else {
1342         *data = NULL;
1343     }
1344     *pnHosts = nHosts;
1345     *pLen = n;
1346     return Success;
1347 }
1348
1349 /* Check for valid address family and length, and return address length. */
1350
1351  /*ARGSUSED*/ static int
1352 CheckAddr(int family, const void *pAddr, unsigned length)
1353 {
1354     int len;
1355
1356     switch (family) {
1357 #if defined(TCPCONN) || defined(STREAMSCONN)
1358     case FamilyInternet:
1359         if (length == sizeof(struct in_addr))
1360             len = length;
1361         else
1362             len = -1;
1363         break;
1364 #if defined(IPv6) && defined(AF_INET6)
1365     case FamilyInternet6:
1366         if (length == sizeof(struct in6_addr))
1367             len = length;
1368         else
1369             len = -1;
1370         break;
1371 #endif
1372 #endif
1373     case FamilyServerInterpreted:
1374         len = siCheckAddr(pAddr, length);
1375         break;
1376     default:
1377         len = -1;
1378     }
1379     return len;
1380 }
1381
1382 /* Check if a host is not in the access control list. 
1383  * Returns 1 if host is invalid, 0 if we've found it. */
1384
1385 int
1386 InvalidHost(register struct sockaddr *saddr, int len, ClientPtr client)
1387 {
1388     int family;
1389     void *addr;
1390     register HOST *selfhost, *host;
1391
1392     if (!AccessEnabled)         /* just let them in */
1393         return 0;
1394     family = ConvertAddr(saddr, &len, (void **) &addr);
1395     if (family == -1)
1396         return 1;
1397     if (family == FamilyLocal) {
1398         if (!LocalHostEnabled) {
1399             /*
1400              * check to see if any local address is enabled.  This 
1401              * implicitly enables local connections.
1402              */
1403             for (selfhost = selfhosts; selfhost; selfhost = selfhost->next) {
1404                 for (host = validhosts; host; host = host->next) {
1405                     if (addrEqual(selfhost->family, selfhost->addr,
1406                                   selfhost->len, host))
1407                         return 0;
1408                 }
1409             }
1410         }
1411         else
1412             return 0;
1413     }
1414     for (host = validhosts; host; host = host->next) {
1415         if (host->family == FamilyServerInterpreted) {
1416             if (siAddrMatch(family, addr, len, host, client)) {
1417                 return 0;
1418             }
1419         }
1420         else {
1421             if (addrEqual(family, addr, len, host))
1422                 return 0;
1423         }
1424
1425     }
1426     return 1;
1427 }
1428
1429 static int
1430 ConvertAddr(register struct sockaddr *saddr, int *len, void **addr)
1431 {
1432     if (*len == 0)
1433         return FamilyLocal;
1434     switch (saddr->sa_family) {
1435     case AF_UNSPEC:
1436 #if defined(UNIXCONN) || defined(LOCALCONN)
1437     case AF_UNIX:
1438 #endif
1439         return FamilyLocal;
1440 #if defined(TCPCONN) || defined(STREAMSCONN)
1441     case AF_INET:
1442 #ifdef WIN32
1443         if (16777343 == *(long *) &((struct sockaddr_in *) saddr)->sin_addr)
1444             return FamilyLocal;
1445 #endif
1446         *len = sizeof(struct in_addr);
1447         *addr = (void *) &(((struct sockaddr_in *) saddr)->sin_addr);
1448         return FamilyInternet;
1449 #if defined(IPv6) && defined(AF_INET6)
1450     case AF_INET6:
1451     {
1452         struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *) saddr;
1453
1454         if (IN6_IS_ADDR_V4MAPPED(&(saddr6->sin6_addr))) {
1455             *len = sizeof(struct in_addr);
1456             *addr = (void *) &(saddr6->sin6_addr.s6_addr[12]);
1457             return FamilyInternet;
1458         }
1459         else {
1460             *len = sizeof(struct in6_addr);
1461             *addr = (void *) &(saddr6->sin6_addr);
1462             return FamilyInternet6;
1463         }
1464     }
1465 #endif
1466 #endif
1467     default:
1468         return -1;
1469     }
1470 }
1471
1472 int
1473 ChangeAccessControl(ClientPtr client, int fEnabled)
1474 {
1475     int rc = AuthorizedClient(client);
1476
1477     if (rc != Success)
1478         return rc;
1479     AccessEnabled = fEnabled;
1480     return Success;
1481 }
1482
1483 /* returns FALSE if xhost + in effect, else TRUE */
1484 int
1485 GetAccessControl(void)
1486 {
1487     return AccessEnabled;
1488 }
1489
1490 /*****************************************************************************
1491  * FamilyServerInterpreted host entry implementation
1492  *
1493  * Supports an extensible system of host types which the server can interpret
1494  * See the IPv6 extensions to the X11 protocol spec for the definition.
1495  *
1496  * Currently supported schemes:
1497  *
1498  * hostname     - hostname as defined in IETF RFC 2396
1499  * ipv6         - IPv6 literal address as defined in IETF RFC's 3513 and <TBD>
1500  *
1501  * See xc/doc/specs/SIAddresses for formal definitions of each type.
1502  */
1503
1504 /* These definitions and the siTypeAdd function could be exported in the 
1505  * future to enable loading additional host types, but that was not done for
1506  * the initial implementation.
1507  */
1508 typedef Bool (*siAddrMatchFunc) (int family, void *addr, int len,
1509                                  const char *siAddr, int siAddrlen,
1510                                  ClientPtr client, void *siTypePriv);
1511 typedef int (*siCheckAddrFunc) (const char *addrString, int length,
1512                                 void *siTypePriv);
1513
1514 struct siType {
1515     struct siType *next;
1516     const char *typeName;
1517     siAddrMatchFunc addrMatch;
1518     siCheckAddrFunc checkAddr;
1519     void *typePriv;             /* Private data for type routines */
1520 };
1521
1522 static struct siType *siTypeList;
1523
1524 static int
1525 siTypeAdd(const char *typeName, siAddrMatchFunc addrMatch,
1526           siCheckAddrFunc checkAddr, void *typePriv)
1527 {
1528     struct siType *s, *p;
1529
1530     if ((typeName == NULL) || (addrMatch == NULL) || (checkAddr == NULL))
1531         return BadValue;
1532
1533     for (s = siTypeList, p = NULL; s != NULL; p = s, s = s->next) {
1534         if (strcmp(typeName, s->typeName) == 0) {
1535             s->addrMatch = addrMatch;
1536             s->checkAddr = checkAddr;
1537             s->typePriv = typePriv;
1538             return Success;
1539         }
1540     }
1541
1542     s = malloc(sizeof(struct siType));
1543     if (s == NULL)
1544         return BadAlloc;
1545
1546     if (p == NULL)
1547         siTypeList = s;
1548     else
1549         p->next = s;
1550
1551     s->next = NULL;
1552     s->typeName = typeName;
1553     s->addrMatch = addrMatch;
1554     s->checkAddr = checkAddr;
1555     s->typePriv = typePriv;
1556     return Success;
1557 }
1558
1559 /* Checks to see if a host matches a server-interpreted host entry */
1560 static Bool
1561 siAddrMatch(int family, void *addr, int len, HOST * host, ClientPtr client)
1562 {
1563     Bool matches = FALSE;
1564     struct siType *s;
1565     const char *valueString;
1566     int addrlen;
1567
1568     valueString = (const char *) memchr(host->addr, '\0', host->len);
1569     if (valueString != NULL) {
1570         for (s = siTypeList; s != NULL; s = s->next) {
1571             if (strcmp((char *) host->addr, s->typeName) == 0) {
1572                 addrlen = host->len - (strlen((char *) host->addr) + 1);
1573                 matches = s->addrMatch(family, addr, len,
1574                                        valueString + 1, addrlen, client,
1575                                        s->typePriv);
1576                 break;
1577             }
1578         }
1579 #ifdef FAMILY_SI_DEBUG
1580         ErrorF("Xserver: siAddrMatch(): type = %s, value = %*.*s -- %s\n",
1581                host->addr, addrlen, addrlen, valueString + 1,
1582                (matches) ? "accepted" : "rejected");
1583 #endif
1584     }
1585     return matches;
1586 }
1587
1588 static int
1589 siCheckAddr(const char *addrString, int length)
1590 {
1591     const char *valueString;
1592     int addrlen, typelen;
1593     int len = -1;
1594     struct siType *s;
1595
1596     /* Make sure there is a \0 byte inside the specified length
1597        to separate the address type from the address value. */
1598     valueString = (const char *) memchr(addrString, '\0', length);
1599     if (valueString != NULL) {
1600         /* Make sure the first string is a recognized address type,
1601          * and the second string is a valid address of that type. 
1602          */
1603         typelen = strlen(addrString) + 1;
1604         addrlen = length - typelen;
1605
1606         for (s = siTypeList; s != NULL; s = s->next) {
1607             if (strcmp(addrString, s->typeName) == 0) {
1608                 len = s->checkAddr(valueString + 1, addrlen, s->typePriv);
1609                 if (len >= 0) {
1610                     len += typelen;
1611                 }
1612                 break;
1613             }
1614         }
1615 #ifdef FAMILY_SI_DEBUG
1616         {
1617             const char *resultMsg;
1618
1619             if (s == NULL) {
1620                 resultMsg = "type not registered";
1621             }
1622             else {
1623                 if (len == -1)
1624                     resultMsg = "rejected";
1625                 else
1626                     resultMsg = "accepted";
1627             }
1628
1629             ErrorF
1630                 ("Xserver: siCheckAddr(): type = %s, value = %*.*s, len = %d -- %s\n",
1631                  addrString, addrlen, addrlen, valueString + 1, len, resultMsg);
1632         }
1633 #endif
1634     }
1635     return len;
1636 }
1637
1638 /***
1639  * Hostname server-interpreted host type
1640  *
1641  * Stored as hostname string, explicitly defined to be resolved ONLY
1642  * at access check time, to allow for hosts with dynamic addresses
1643  * but static hostnames, such as found in some DHCP & mobile setups.
1644  *
1645  * Hostname must conform to IETF RFC 2396 sec. 3.2.2, which defines it as:
1646  *      hostname     = *( domainlabel "." ) toplabel [ "." ]
1647  *      domainlabel  = alphanum | alphanum *( alphanum | "-" ) alphanum
1648  *      toplabel     = alpha | alpha *( alphanum | "-" ) alphanum
1649  */
1650
1651 #ifdef NI_MAXHOST
1652 #define SI_HOSTNAME_MAXLEN NI_MAXHOST
1653 #else
1654 #ifdef MAXHOSTNAMELEN
1655 #define SI_HOSTNAME_MAXLEN MAXHOSTNAMELEN
1656 #else
1657 #define SI_HOSTNAME_MAXLEN 256
1658 #endif
1659 #endif
1660
1661 static Bool
1662 siHostnameAddrMatch(int family, void *addr, int len,
1663                     const char *siAddr, int siAddrLen, ClientPtr client,
1664                     void *typePriv)
1665 {
1666     Bool res = FALSE;
1667
1668 /* Currently only supports checking against IPv4 & IPv6 connections, but 
1669  * support for other address families, such as DECnet, could be added if 
1670  * desired.
1671  */
1672 #if defined(IPv6) && defined(AF_INET6)
1673     if ((family == FamilyInternet) || (family == FamilyInternet6)) {
1674         char hostname[SI_HOSTNAME_MAXLEN];
1675         struct addrinfo *addresses;
1676         struct addrinfo *a;
1677         int f, hostaddrlen;
1678         void *hostaddr;
1679
1680         if (siAddrLen >= sizeof(hostname))
1681             return FALSE;
1682
1683         strlcpy(hostname, siAddr, siAddrLen + 1);
1684
1685         if (getaddrinfo(hostname, NULL, NULL, &addresses) == 0) {
1686             for (a = addresses; a != NULL; a = a->ai_next) {
1687                 hostaddrlen = a->ai_addrlen;
1688                 f = ConvertAddr(a->ai_addr, &hostaddrlen, &hostaddr);
1689                 if ((f == family) && (len == hostaddrlen) &&
1690                     (memcmp(addr, hostaddr, len) == 0)) {
1691                     res = TRUE;
1692                     break;
1693                 }
1694             }
1695             freeaddrinfo(addresses);
1696         }
1697     }
1698 #else                           /* IPv6 not supported, use gethostbyname instead for IPv4 */
1699     if (family == FamilyInternet) {
1700         register struct hostent *hp;
1701
1702 #ifdef XTHREADS_NEEDS_BYNAMEPARAMS
1703         _Xgethostbynameparams hparams;
1704 #endif
1705         char hostname[SI_HOSTNAME_MAXLEN];
1706         int f, hostaddrlen;
1707         void *hostaddr;
1708         const char **addrlist;
1709
1710         if (siAddrLen >= sizeof(hostname))
1711             return FALSE;
1712
1713         strlcpy(hostname, siAddr, siAddrLen + 1);
1714
1715         if ((hp = _XGethostbyname(hostname, hparams)) != NULL) {
1716 #ifdef h_addr                   /* new 4.3bsd version of gethostent */
1717             /* iterate over the addresses */
1718             for (addrlist = hp->h_addr_list; *addrlist; addrlist++)
1719 #else
1720             addrlist = &hp->h_addr;
1721 #endif
1722             {
1723                 struct sockaddr_in sin;
1724
1725                 sin.sin_family = hp->h_addrtype;
1726                 memcpy(&(sin.sin_addr), *addrlist, hp->h_length);
1727                 hostaddrlen = sizeof(sin);
1728                 f = ConvertAddr((struct sockaddr *) &sin,
1729                                 &hostaddrlen, &hostaddr);
1730                 if ((f == family) && (len == hostaddrlen) &&
1731                     (memcmp(addr, hostaddr, len) == 0)) {
1732                     res = TRUE;
1733                     break;
1734                 }
1735             }
1736         }
1737     }
1738 #endif
1739     return res;
1740 }
1741
1742 static int
1743 siHostnameCheckAddr(const char *valueString, int length, void *typePriv)
1744 {
1745     /* Check conformance of hostname to RFC 2396 sec. 3.2.2 definition.
1746      * We do not use ctype functions here to avoid locale-specific
1747      * character sets.  Hostnames must be pure ASCII.  
1748      */
1749     int len = length;
1750     int i;
1751     Bool dotAllowed = FALSE;
1752     Bool dashAllowed = FALSE;
1753
1754     if ((length <= 0) || (length >= SI_HOSTNAME_MAXLEN)) {
1755         len = -1;
1756     }
1757     else {
1758         for (i = 0; i < length; i++) {
1759             char c = valueString[i];
1760
1761             if (c == 0x2E) {    /* '.' */
1762                 if (dotAllowed == FALSE) {
1763                     len = -1;
1764                     break;
1765                 }
1766                 else {
1767                     dotAllowed = FALSE;
1768                     dashAllowed = FALSE;
1769                 }
1770             }
1771             else if (c == 0x2D) {       /* '-' */
1772                 if (dashAllowed == FALSE) {
1773                     len = -1;
1774                     break;
1775                 }
1776                 else {
1777                     dotAllowed = FALSE;
1778                 }
1779             }
1780             else if (((c >= 0x30) && (c <= 0x3A)) /* 0-9 */ ||
1781                      ((c >= 0x61) && (c <= 0x7A)) /* a-z */ ||
1782                      ((c >= 0x41) && (c <= 0x5A)) /* A-Z */ ) {
1783                 dotAllowed = TRUE;
1784                 dashAllowed = TRUE;
1785             }
1786             else {              /* Invalid character */
1787                 len = -1;
1788                 break;
1789             }
1790         }
1791     }
1792     return len;
1793 }
1794
1795 #if defined(IPv6) && defined(AF_INET6)
1796 /***
1797  * "ipv6" server interpreted type
1798  *
1799  * Currently supports only IPv6 literal address as specified in IETF RFC 3513
1800  *
1801  * Once draft-ietf-ipv6-scoping-arch-00.txt becomes an RFC, support will be 
1802  * added for the scoped address format it specifies.
1803  */
1804
1805 /* Maximum length of an IPv6 address string - increase when adding support 
1806  * for scoped address qualifiers.  Includes room for trailing NUL byte. 
1807  */
1808 #define SI_IPv6_MAXLEN INET6_ADDRSTRLEN
1809
1810 static Bool
1811 siIPv6AddrMatch(int family, void *addr, int len,
1812                 const char *siAddr, int siAddrlen, ClientPtr client,
1813                 void *typePriv)
1814 {
1815     struct in6_addr addr6;
1816     char addrbuf[SI_IPv6_MAXLEN];
1817
1818     if ((family != FamilyInternet6) || (len != sizeof(addr6)))
1819         return FALSE;
1820
1821     memcpy(addrbuf, siAddr, siAddrlen);
1822     addrbuf[siAddrlen] = '\0';
1823
1824     if (inet_pton(AF_INET6, addrbuf, &addr6) != 1) {
1825         perror("inet_pton");
1826         return FALSE;
1827     }
1828
1829     if (memcmp(addr, &addr6, len) == 0) {
1830         return TRUE;
1831     }
1832     else {
1833         return FALSE;
1834     }
1835 }
1836
1837 static int
1838 siIPv6CheckAddr(const char *addrString, int length, void *typePriv)
1839 {
1840     int len;
1841
1842     /* Minimum length is 3 (smallest legal address is "::1") */
1843     if (length < 3) {
1844         /* Address is too short! */
1845         len = -1;
1846     }
1847     else if (length >= SI_IPv6_MAXLEN) {
1848         /* Address is too long! */
1849         len = -1;
1850     }
1851     else {
1852         /* Assume inet_pton is sufficient validation */
1853         struct in6_addr addr6;
1854         char addrbuf[SI_IPv6_MAXLEN];
1855
1856         memcpy(addrbuf, addrString, length);
1857         addrbuf[length] = '\0';
1858
1859         if (inet_pton(AF_INET6, addrbuf, &addr6) != 1) {
1860             perror("inet_pton");
1861             len = -1;
1862         }
1863         else {
1864             len = length;
1865         }
1866     }
1867     return len;
1868 }
1869 #endif                          /* IPv6 */
1870
1871 #if !defined(NO_LOCAL_CLIENT_CRED)
1872 /***
1873  * "localuser" & "localgroup" server interpreted types
1874  *
1875  * Allows local connections from a given local user or group
1876  */
1877
1878 #include <pwd.h>
1879 #include <grp.h>
1880
1881 #define LOCAL_USER 1
1882 #define LOCAL_GROUP 2
1883
1884 typedef struct {
1885     int credType;
1886 } siLocalCredPrivRec, *siLocalCredPrivPtr;
1887
1888 static siLocalCredPrivRec siLocalUserPriv = { LOCAL_USER };
1889 static siLocalCredPrivRec siLocalGroupPriv = { LOCAL_GROUP };
1890
1891 static Bool
1892 siLocalCredGetId(const char *addr, int len, siLocalCredPrivPtr lcPriv, int *id)
1893 {
1894     Bool parsedOK = FALSE;
1895     char *addrbuf = malloc(len + 1);
1896
1897     if (addrbuf == NULL) {
1898         return FALSE;
1899     }
1900
1901     memcpy(addrbuf, addr, len);
1902     addrbuf[len] = '\0';
1903
1904     if (addr[0] == '#') {       /* numeric id */
1905         char *cp;
1906
1907         errno = 0;
1908         *id = strtol(addrbuf + 1, &cp, 0);
1909         if ((errno == 0) && (cp != (addrbuf + 1))) {
1910             parsedOK = TRUE;
1911         }
1912     }
1913     else {                      /* non-numeric name */
1914         if (lcPriv->credType == LOCAL_USER) {
1915             struct passwd *pw;
1916             struct passwd pwd;
1917             char *buf;
1918             size_t bufsize=0;
1919             int s;
1920
1921             bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
1922             if (bufsize == -1) /* Value was indeterminate */
1923                 bufsize = 16384; /* Should be more than enough */
1924
1925             buf = malloc(bufsize);
1926             if (!buf)
1927                 goto out;
1928             s = getpwnam_r(addrbuf, &pwd, buf, bufsize, &pw);
1929
1930             if (pw != NULL) {
1931                 *id = (int) pw->pw_uid;
1932                 parsedOK = TRUE;
1933             }
1934
1935             free(buf);
1936         }
1937         else {                  /* group */
1938             struct group *gr;
1939             struct group grp;
1940             char *buf;
1941             size_t bufsize=0;
1942             int s;
1943
1944             bufsize = sysconf(_SC_GETGR_R_SIZE_MAX);
1945             if (bufsize == -1) /* Value was indeterminate */
1946                 bufsize = 16384; /* Should be more than enough */
1947
1948            buf = malloc(bufsize);
1949             if (!buf)
1950                 goto out;
1951             s = getgrnam_r(addrbuf, &grp, buf, bufsize, &gr);
1952
1953             if (gr != NULL) {
1954                 *id = (int) gr->gr_gid;
1955                 parsedOK = TRUE;
1956             }
1957
1958             free(buf);
1959         }
1960     }
1961
1962 out:
1963     free(addrbuf);
1964     return parsedOK;
1965 }
1966
1967 static Bool
1968 siLocalCredAddrMatch(int family, void *addr, int len,
1969                      const char *siAddr, int siAddrlen, ClientPtr client,
1970                      void *typePriv)
1971 {
1972     int siAddrId;
1973     LocalClientCredRec *lcc;
1974     siLocalCredPrivPtr lcPriv = (siLocalCredPrivPtr) typePriv;
1975
1976     if (GetLocalClientCreds(client, &lcc) == -1) {
1977         return FALSE;
1978     }
1979
1980 #ifdef HAVE_GETZONEID           /* Ensure process is in the same zone */
1981     if ((lcc->fieldsSet & LCC_ZID_SET) && (lcc->zoneid != getzoneid())) {
1982         FreeLocalClientCreds(lcc);
1983         return FALSE;
1984     }
1985 #endif
1986
1987     if (siLocalCredGetId(siAddr, siAddrlen, lcPriv, &siAddrId) == FALSE) {
1988         FreeLocalClientCreds(lcc);
1989         return FALSE;
1990     }
1991
1992     if (lcPriv->credType == LOCAL_USER) {
1993         if ((lcc->fieldsSet & LCC_UID_SET) && (lcc->euid == siAddrId)) {
1994             FreeLocalClientCreds(lcc);
1995             return TRUE;
1996         }
1997     }
1998     else {
1999         if ((lcc->fieldsSet & LCC_GID_SET) && (lcc->egid == siAddrId)) {
2000             FreeLocalClientCreds(lcc);
2001             return TRUE;
2002         }
2003         if (lcc->pSuppGids != NULL) {
2004             int i;
2005
2006             for (i = 0; i < lcc->nSuppGids; i++) {
2007                 if (lcc->pSuppGids[i] == siAddrId) {
2008                     FreeLocalClientCreds(lcc);
2009                     return TRUE;
2010                 }
2011             }
2012         }
2013     }
2014     FreeLocalClientCreds(lcc);
2015     return FALSE;
2016 }
2017
2018 static int
2019 siLocalCredCheckAddr(const char *addrString, int length, void *typePriv)
2020 {
2021     int len = length;
2022     int id;
2023
2024     if (siLocalCredGetId(addrString, length,
2025                          (siLocalCredPrivPtr) typePriv, &id) == FALSE) {
2026         len = -1;
2027     }
2028     return len;
2029 }
2030 #endif                          /* localuser */
2031
2032 static void
2033 siTypesInitialize(void)
2034 {
2035     siTypeAdd("hostname", siHostnameAddrMatch, siHostnameCheckAddr, NULL);
2036 #if defined(IPv6) && defined(AF_INET6)
2037     siTypeAdd("ipv6", siIPv6AddrMatch, siIPv6CheckAddr, NULL);
2038 #endif
2039 #if !defined(NO_LOCAL_CLIENT_CRED)
2040     siTypeAdd("localuser", siLocalCredAddrMatch, siLocalCredCheckAddr,
2041               &siLocalUserPriv);
2042     siTypeAdd("localgroup", siLocalCredAddrMatch, siLocalCredCheckAddr,
2043               &siLocalGroupPriv);
2044 #endif
2045 }