]> git.sesse.net Git - rdpsrv/blob - Xserver/programs/Xserver/os/access.c
Support RDP5 logon packets.
[rdpsrv] / Xserver / programs / Xserver / os / access.c
1 /* $XConsortium: access.c /main/68 1996/12/15 22:57:09 rws $ */
2 /* $XFree86: xc/programs/Xserver/os/access.c,v 3.18.2.4 1998/02/21 06:07:16 robin Exp $ */
3 /***********************************************************
4
5 Copyright (c) 1987  X Consortium
6
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
13
14 The above copyright notice and this permission notice shall be included in
15 all copies or substantial portions of the Software.
16
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
20 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
24 Except as contained in this notice, the name of the X Consortium shall not be
25 used in advertising or otherwise to promote the sale, use or other dealings
26 in this Software without prior written authorization from the X Consortium.
27
28
29 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
30
31                         All Rights Reserved
32
33 Permission to use, copy, modify, and distribute this software and its 
34 documentation for any purpose and without fee is hereby granted, 
35 provided that the above copyright notice appear in all copies and that
36 both that copyright notice and this permission notice appear in 
37 supporting documentation, and that the name of Digital not be
38 used in advertising or publicity pertaining to distribution of the
39 software without specific, written prior permission.  
40
41 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
42 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
43 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
44 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
45 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
46 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
47 SOFTWARE.
48
49 ******************************************************************/
50
51 #ifdef WIN32
52 #include <X11/Xwinsock.h>
53 #endif
54
55 #include <stdio.h>
56 #include <X11/Xtrans.h>
57 #include <X11/Xauth.h>
58 #include "X.h"
59 #include "Xproto.h"
60 #include "misc.h"
61 #include "site.h"
62 #include <errno.h>
63 #include <sys/types.h>
64 #ifndef WIN32
65 #if !defined(AMOEBA) && !defined(MINIX)
66 #ifdef ESIX
67 #include <lan/socket.h>
68 #else
69 #ifndef Lynx
70 #include <sys/socket.h>
71 #else
72 #include <socket.h>
73 #endif
74 #endif
75 #include <sys/ioctl.h>
76 #else
77 #ifdef AMOEBA
78 #define port am_port_t
79 #include <amoeba.h>
80 #include <cmdreg.h>
81 #include <stdcom.h>
82 #include <stderr.h>
83 #include <ampolicy.h>
84 #include <server/ip/hton.h>
85 #include <server/ip/types.h>
86 #include <server/ip/tcpip.h>
87 #include <server/ip/tcp_io.h>
88 #include <server/ip/gen/in.h>
89 #include <server/ip/gen/tcp.h>
90 #include <server/ip/gen/tcp_io.h>
91 #include <server/ip/gen/socket.h>
92 #undef port
93 #endif
94 #endif /* AMOEBA || MINIX */
95 #include <ctype.h>
96
97 #if defined(TCPCONN) || defined(STREAMSCONN) || defined(ISC) || defined(SCO)
98 #include <netinet/in.h>
99 #endif /* TCPCONN || STREAMSCONN || ISC || SCO */
100 #ifdef DNETCONN
101 #include <netdnet/dn.h>
102 #include <netdnet/dnetdb.h>
103 #endif
104
105 #if !defined(AMOEBA)
106 #ifdef hpux
107 # include <sys/utsname.h>
108 # ifdef HAS_IFREQ
109 #  include <net/if.h>
110 # endif
111 #else
112 #if defined(SVR4) ||  (defined(SYSV) && defined(i386)) || defined(MINIX)
113 # include <sys/utsname.h>
114 #endif
115 #if defined(SYSV) &&  defined(i386)
116 # include <sys/stream.h>
117 # ifdef ISC
118 #  include <sys/stropts.h>
119 #  include <sys/sioctl.h>
120 # endif /* ISC */
121 #endif
122 #ifdef ESIX
123 # include <lan/if.h>
124 #else
125 #ifndef MINIX
126 # include <net/if.h>
127 #endif
128 #endif
129 #endif /* hpux */
130 #endif /* !AMOEBA */
131
132 #ifdef SVR4
133 #ifndef SCO
134 #include <sys/sockio.h>
135 #endif
136 #include <sys/stropts.h>
137 #endif
138
139 #ifdef ESIX
140 #include <lan/netdb.h>
141 #else
142 #if !defined(AMOEBA) && !defined(MINIX)
143 #include <netdb.h>
144 #else
145 #ifdef AMOEBA
146 #include <server/ip/gen/netdb.h>
147 #endif
148 #ifdef MINIX
149 #include <net/hton.h>
150 #include <net/gen/netdb.h>
151 #define INADDR_BROADCAST 0xFFFFFFFF
152 #endif
153 #endif /* AMOEBA || MINIX */
154 #endif /* ESIX */
155
156 #ifdef CSRG_BASED
157 #include <sys/param.h>
158 #if (BSD >= 199103)
159 #define VARIABLE_IFREQ
160 #endif
161 #endif
162
163 #if defined(Lynx) && defined(BSD44SOCKETS)
164 #define VARIABLE_IFREQ
165 #endif
166
167 #endif /* WIN32 */
168
169 #ifndef PATH_MAX
170 #ifndef Lynx
171 #include <sys/param.h>
172 #else
173 #include <param.h>
174 #endif 
175 #ifndef PATH_MAX
176 #ifdef MAXPATHLEN
177 #define PATH_MAX MAXPATHLEN
178 #else
179 #define PATH_MAX 1024
180 #endif
181 #endif
182 #endif 
183
184 #include "dixstruct.h"
185 #include "osdep.h"
186
187 #ifdef XCSECURITY
188 #define _SECURITY_SERVER
189 #include "extensions/security.h"
190 #endif
191
192 Bool defeatAccessControl = FALSE;
193
194 #define acmp(a1, a2, len) memcmp((char *)(a1), (char *)(a2), len)
195 #define acopy(a1, a2, len) memmove((char *)(a2), (char *)(a1), len)
196 #define addrEqual(fam, address, length, host) \
197                          ((fam) == (host)->family &&\
198                           (length) == (host)->len &&\
199                           !acmp (address, (host)->addr, length))
200
201 static int ConvertAddr(
202 #if NeedFunctionPrototypes
203     struct sockaddr */*saddr*/,
204     int */*len*/,
205     pointer */*addr*/
206 #endif
207 );
208
209 static int CheckAddr(
210 #if NeedFunctionPrototypes
211     int /*family*/,
212     pointer /*pAddr*/,
213     unsigned /*length*/
214 #endif
215 );
216
217 static Bool NewHost(
218 #if NeedFunctionPrototypes
219     int /*family*/,
220     pointer /*addr*/,
221     int /*len*/
222 #endif
223 );
224
225 typedef struct _host {
226         short           family;
227         short           len;
228         unsigned char   *addr;
229         struct _host *next;
230 } HOST;
231
232 #define MakeHost(h,l)   (h)=(HOST *) xalloc(sizeof *(h)+(l));\
233                         (h)->addr=(unsigned char *) ((h) + 1);
234 #define FreeHost(h)     xfree(h)
235 static HOST *selfhosts = NULL;
236 static HOST *validhosts = NULL;
237 static int AccessEnabled = DEFAULT_ACCESS_CONTROL;
238 static int LocalHostEnabled = FALSE;
239 static int UsingXdmcp = FALSE;
240
241
242 /*
243  * called when authorization is not enabled to add the
244  * local host to the access list
245  */
246
247 void
248 EnableLocalHost ()
249 {
250     if (!UsingXdmcp)
251     {
252         LocalHostEnabled = TRUE;
253         AddLocalHosts ();
254     }
255 }
256
257 /*
258  * called when authorization is enabled to keep us secure
259  */
260 void
261 DisableLocalHost ()
262 {
263     HOST *self;
264
265     LocalHostEnabled = FALSE;
266     for (self = selfhosts; self; self = self->next)
267         (void) RemoveHost ((ClientPtr)NULL, self->family, self->len, (pointer)self->addr);
268 }
269
270 /*
271  * called at init time when XDMCP will be used; xdmcp always
272  * adds local hosts manually when needed
273  */
274
275 void
276 AccessUsingXdmcp ()
277 {
278     UsingXdmcp = TRUE;
279     LocalHostEnabled = FALSE;
280 }
281
282
283 #if ((defined(SVR4) && !defined(SCO325) && !defined(sun) && !defined(NCR)) || defined(ISC)) && defined(SIOCGIFCONF)
284
285 /* Deal with different SIOCGIFCONF ioctl semantics on these OSs */
286
287 static int
288 ifioctl (fd, cmd, arg)
289     int fd;
290     int cmd;
291     char *arg;
292 {
293     struct strioctl ioc;
294     int ret;
295
296     bzero((char *) &ioc, sizeof(ioc));
297     ioc.ic_cmd = cmd;
298     ioc.ic_timout = 0;
299     if (cmd == SIOCGIFCONF)
300     {
301         ioc.ic_len = ((struct ifconf *) arg)->ifc_len;
302         ioc.ic_dp = ((struct ifconf *) arg)->ifc_buf;
303 #ifdef ISC
304         /* SIOCGIFCONF is somewhat brain damaged on ISC. The argument
305          * buffer must contain the ifconf structure as header. Ifc_req
306          * is also not a pointer but a one element array of ifreq
307          * structures. On return this array is extended by enough
308          * ifreq fields to hold all interfaces. The return buffer length
309          * is placed in the buffer header.
310          */
311         ((struct ifconf *) ioc.ic_dp)->ifc_len =
312                                          ioc.ic_len - sizeof(struct ifconf);
313 #endif
314     }
315     else
316     {
317         ioc.ic_len = sizeof(struct ifreq);
318         ioc.ic_dp = arg;
319     }
320     ret = ioctl(fd, I_STR, (char *) &ioc);
321     if (ret >= 0 && cmd == SIOCGIFCONF)
322 #ifdef SVR4
323         ((struct ifconf *) arg)->ifc_len = ioc.ic_len;
324 #endif
325 #ifdef ISC
326     {
327         ((struct ifconf *) arg)->ifc_len =
328                                  ((struct ifconf *)ioc.ic_dp)->ifc_len;
329         ((struct ifconf *) arg)->ifc_buf = 
330                         (caddr_t)((struct ifconf *)ioc.ic_dp)->ifc_req;
331     }
332 #endif
333     return(ret);
334 }
335 #else /* ((SVR4 && !sun) || ISC) && SIOCGIFCONF */
336 #define ifioctl ioctl
337 #endif /* ((SVR4 && !sun) || ISC) && SIOCGIFCONF */
338
339 /*
340  * DefineSelf (fd):
341  *
342  * Define this host for access control.  Find all the hosts the OS knows about 
343  * for this fd and add them to the selfhosts list.
344  */
345
346 #ifdef WINTCP /* NCR Wollongong based TCP */
347
348 #include <sys/un.h>
349 #include <stropts.h>
350 #include <tiuser.h>
351
352 #include <sys/stream.h>
353 #include <net/if.h>
354 #include <netinet/ip.h>
355 #include <netinet/ip_var.h>
356 #include <netinet/in.h>
357 #include <netinet/in_var.h>
358
359 void
360 DefineSelf (fd)
361     int fd;
362 {
363     /*
364      * The Wolongong drivers used by NCR SVR4/MP-RAS don't understand the
365      * socket IO calls that most other drivers seem to like. Because of
366      * this, this routine must be special cased for NCR. Eventually,
367      * this will be cleared up.
368      */
369
370     struct ipb ifnet;
371     struct in_ifaddr ifaddr;
372     struct strioctl str;
373     unsigned char *addr;
374     register HOST *host;
375     int family, len;
376
377     if ((fd = open ("/dev/ip", O_RDWR, 0 )) < 0)
378         Error ("Getting interface configuration (1)");
379
380     /* Indicate that we want to start at the begining */
381     ifnet.ib_next = (struct ipb *) 1;
382
383     while (ifnet.ib_next)
384     {
385         str.ic_cmd = IPIOC_GETIPB;
386         str.ic_timout = 0;
387         str.ic_len = sizeof (struct ipb);
388         str.ic_dp = (char *) &ifnet;
389
390         if (ioctl (fd, (int) I_STR, (char *) &str) < 0)
391         {
392             close (fd);
393             Error ("Getting interface configuration (2)");
394         }
395
396         ifaddr.ia_next = (struct in_ifaddr *) ifnet.if_addrlist;
397         str.ic_cmd = IPIOC_GETINADDR;
398         str.ic_timout = 0;
399         str.ic_len = sizeof (struct in_ifaddr);
400         str.ic_dp = (char *) &ifaddr;
401
402         if (ioctl (fd, (int) I_STR, (char *) &str) < 0)
403         {
404             close (fd);
405             Error ("Getting interface configuration (3)");
406         }
407
408         len = sizeof(struct sockaddr_in);
409         family = ConvertAddr (IA_SIN(&ifaddr), &len, (pointer *)&addr);
410         if (family == -1 || family == FamilyLocal)
411             continue;
412         for (host = selfhosts;
413              host && !addrEqual (family, addr, len, host);
414              host = host->next)
415             ;
416         if (host)
417             continue;
418         MakeHost(host,len)
419         if (host)
420         {
421             host->family = family;
422             host->len = len;
423             acopy(addr, host->addr, len);
424             host->next = selfhosts;
425             selfhosts = host;
426         }
427 #ifdef XDMCP
428         {
429             struct sockaddr broad_addr;
430
431             /*
432              * If this isn't an Internet Address, don't register it.
433              */
434             if (family != FamilyInternet)
435                 continue;
436
437             /*
438              * ignore 'localhost' entries as they're not useful
439              * on the other end of the wire
440              */
441             if (len == 4 &&
442                 addr[0] == 127 && addr[1] == 0 &&
443                 addr[2] == 0 && addr[3] == 1)
444                 continue;
445
446             XdmcpRegisterConnection (family, (char *)addr, len);
447
448
449 #define IA_BROADADDR(ia) ((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_broadaddr))
450
451             XdmcpRegisterBroadcastAddress (
452                 (struct sockaddr_in *) IA_BROADADDR(&ifaddr));
453
454 #undef IA_BROADADDR
455         }
456 #endif /* XDMCP */
457     }
458
459     close(fd);
460
461     /*
462      * add something of FamilyLocalHost
463      */
464     for (host = selfhosts;
465          host && !addrEqual(FamilyLocalHost, "", 0, host);
466          host = host->next);
467     if (!host)
468     {
469         MakeHost(host, 0);
470         if (host)
471         {
472             host->family = FamilyLocalHost;
473             host->len = 0;
474             acopy("", host->addr, 0);
475             host->next = selfhosts;
476             selfhosts = host;
477         }
478     }
479 }
480
481 #else /* WINTCP */
482
483 #if !defined(SIOCGIFCONF) || (defined (hpux) && ! defined (HAS_IFREQ))
484 void
485 DefineSelf (fd)
486     int fd;
487 {
488 #if !defined(TCPCONN) && !defined(STREAMSCONN) && !defined(UNIXCONN) && !defined(MNX_TCPCONN)
489     return;
490 #else
491     register int n;
492     int len;
493     caddr_t     addr;
494     int         family;
495     register HOST       *host;
496
497     struct utsname name;
498     register struct hostent  *hp;
499
500     union {
501         struct  sockaddr   sa;
502         struct  sockaddr_in  in;
503     } saddr;
504         
505     struct      sockaddr_in     *inetaddr;
506     struct sockaddr_in broad_addr;
507
508     /* Why not use gethostname()?  Well, at least on my system, I've had to
509      * make an ugly kernel patch to get a name longer than 8 characters, and
510      * uname() lets me access to the whole string (it smashes release, you
511      * see), whereas gethostname() kindly truncates it for me.
512      */
513     uname(&name);
514     hp = gethostbyname (name.nodename);
515     if (hp != NULL)
516     {
517         saddr.sa.sa_family = hp->h_addrtype;
518         inetaddr = (struct sockaddr_in *) (&(saddr.sa));
519         acopy ( hp->h_addr, &(inetaddr->sin_addr), hp->h_length);
520         len = sizeof(saddr.sa);
521         family = ConvertAddr ( &(saddr.sa), &len, (pointer *)&addr);
522         if ( family != -1 && family != FamilyLocal )
523         {
524             for (host = selfhosts;
525                  host && !addrEqual (family, addr, len, host);
526                  host = host->next) ;
527             if (!host)
528             {
529                 /* add this host to the host list.      */
530                 MakeHost(host,len)
531                 if (host)
532                 {
533                     host->family = family;
534                     host->len = len;
535                     acopy ( addr, host->addr, len);
536                     host->next = selfhosts;
537                     selfhosts = host;
538                 }
539 #ifdef XDMCP
540                 /*
541                  *  If this is an Internet Address, but not the localhost
542                  *  address (127.0.0.1), register it.
543                  */
544                 if (family == FamilyInternet &&
545                     !(len == 4 && addr[0] == 127 && addr[1] == 0 &&
546                       addr[2] == 0 && addr[3] == 1)
547                    )
548                 {
549                     XdmcpRegisterConnection (family, (char *)addr, len);
550                     broad_addr = *inetaddr;
551                     ((struct sockaddr_in *) &broad_addr)->sin_addr.s_addr =
552                         htonl (INADDR_BROADCAST);
553                     XdmcpRegisterBroadcastAddress ((struct sockaddr_in *)
554                                                    &broad_addr);
555                 }
556 #endif /* XDMCP */
557             }
558         }
559     }
560     /*
561      * now add a host of family FamilyLocalHost...
562      */
563     for (host = selfhosts;
564          host && !addrEqual(FamilyLocalHost, "", 0, host);
565          host = host->next);
566     if (!host)
567     {
568         MakeHost(host, 0);
569         if (host)
570         {
571             host->family = FamilyLocalHost;
572             host->len = 0;
573             acopy("", host->addr, 0);
574             host->next = selfhosts;
575             selfhosts = host;
576         }
577     }
578 #endif /* !TCPCONN && !STREAMSCONN && !UNIXCONN && !MNX_TCPCONN */
579 }
580
581 #else
582
583 #ifdef VARIABLE_IFREQ
584 #define ifr_size(p) (sizeof (struct ifreq) + \
585                      (p->ifr_addr.sa_len > sizeof (p->ifr_addr) ? \
586                       p->ifr_addr.sa_len - sizeof (p->ifr_addr) : 0))
587 #define ifraddr_size(a) (a.sa_len)
588 #else
589 #define ifr_size(p) (sizeof (struct ifreq))
590 #define ifraddr_size(a) (sizeof (a))
591 #endif
592
593 void
594 DefineSelf (fd)
595     int fd;
596 {
597     char                buf[2048], *cp, *cplim;
598     struct ifconf       ifc;
599     register int        n;
600     int                 len;
601     unsigned char *     addr;
602     int                 family;
603     register HOST       *host;
604     register struct ifreq *ifr;
605     
606 #ifdef DNETCONN
607     struct dn_naddr *dnaddr = getnodeadd();
608     /*
609      * AF_DECnet may not be listed in the interface list.  Instead use
610      * the supported library call to find out the local address (if any).
611      */
612     if (dnaddr)
613     {    
614         addr = (unsigned char *) dnaddr;
615         len = dnaddr->a_len + sizeof(dnaddr->a_len);
616         family = FamilyDECnet;
617         for (host = selfhosts;
618              host && !addrEqual (family, addr, len, host);
619              host = host->next)
620             ;
621         if (!host)
622         {
623             MakeHost(host,len)
624             if (host)
625             {
626                 host->family = family;
627                 host->len = len;
628                 acopy(addr, host->addr, len);
629                 host->next = selfhosts;
630                 selfhosts = host;
631             }
632         }
633     }
634 #endif
635     ifc.ifc_len = sizeof (buf);
636     ifc.ifc_buf = buf;
637     if (ifioctl (fd, (int) SIOCGIFCONF, (pointer) &ifc) < 0)
638         Error ("Getting interface configuration (4)");
639
640 #ifdef ISC
641 #define IFC_IFC_REQ (struct ifreq *) ifc.ifc_buf
642 #else
643 #define IFC_IFC_REQ ifc.ifc_req
644 #endif
645
646     cplim = (char *) IFC_IFC_REQ + ifc.ifc_len;
647     
648     for (cp = (char *) IFC_IFC_REQ; cp < cplim; cp += ifr_size (ifr))
649     {
650         ifr = (struct ifreq *) cp;
651         len = ifraddr_size (ifr->ifr_addr);
652 #ifdef DNETCONN
653         /*
654          * DECnet was handled up above.
655          */
656         if (ifr->ifr_addr.sa_family == AF_DECnet)
657             continue;
658 #endif /* DNETCONN */
659         family = ConvertAddr (&ifr->ifr_addr, &len, (pointer *)&addr);
660         if (family == -1 || family == FamilyLocal)
661             continue;
662 #ifdef DEF_SELF_DEBUG
663         if (family == FamilyInternet) 
664             ErrorF("Xserver: DefineSelf(): ifname = %s, addr = %d.%d.%d.%d\n",
665                    ifr->ifr_name, addr[0], addr[1], addr[2], addr[3]);
666 #endif
667         for (host = selfhosts;
668              host && !addrEqual (family, addr, len, host);
669              host = host->next)
670             ;
671         if (host)
672             continue;
673         MakeHost(host,len)
674         if (host)
675         {
676             host->family = family;
677             host->len = len;
678             acopy(addr, host->addr, len);
679             host->next = selfhosts;
680             selfhosts = host;
681         }
682 #ifdef XDMCP
683         {
684             struct sockaddr broad_addr;
685
686             /*
687              * If this isn't an Internet Address, don't register it.
688              */
689             if (family != FamilyInternet)
690                 continue;
691
692             /*
693              * ignore 'localhost' entries as they're not useful
694              * on the other end of the wire
695              */
696             if (len == 4 &&
697                 addr[0] == 127 && addr[1] == 0 &&
698                 addr[2] == 0 && addr[3] == 1)
699                 continue;
700
701             XdmcpRegisterConnection (family, (char *)addr, len);
702             broad_addr = ifr->ifr_addr;
703             ((struct sockaddr_in *) &broad_addr)->sin_addr.s_addr =
704                 htonl (INADDR_BROADCAST);
705 #ifdef SIOCGIFBRDADDR
706             {
707                 struct ifreq    broad_req;
708     
709                 broad_req = *ifr;
710                 if (ifioctl (fd, SIOCGIFFLAGS, (char *) &broad_req) != -1 &&
711                     (broad_req.ifr_flags & IFF_BROADCAST) &&
712                     (broad_req.ifr_flags & IFF_UP)
713                     )
714                 {
715                     broad_req = *ifr;
716                     if (ifioctl (fd, SIOCGIFBRDADDR, &broad_req) != -1)
717                         broad_addr = broad_req.ifr_addr;
718                     else
719                         continue;
720                 }
721                 else
722                     continue;
723             }
724 #endif
725 #ifdef DEF_SELF_DEBUG
726             ErrorF("Xserver: DefineSelf(): ifname = %s, baddr = %s\n",
727                    ifr->ifr_name,
728                    inet_ntoa(((struct sockaddr_in *) &broad_addr)->sin_addr));
729 #endif
730             XdmcpRegisterBroadcastAddress ((struct sockaddr_in *) &broad_addr);
731         }
732 #endif
733     }
734     /*
735      * add something of FamilyLocalHost
736      */
737     for (host = selfhosts;
738          host && !addrEqual(FamilyLocalHost, "", 0, host);
739          host = host->next);
740     if (!host)
741     {
742         MakeHost(host, 0);
743         if (host)
744         {
745             host->family = FamilyLocalHost;
746             host->len = 0;
747             acopy("", host->addr, 0);
748             host->next = selfhosts;
749             selfhosts = host;
750         }
751     }
752 }
753 #endif /* hpux && !HAS_IFREQ */
754 #endif /* WINTCP */
755
756 #ifdef XDMCP
757 void
758 AugmentSelf(from, len)
759     pointer from;
760     int     len;
761 {
762     int family;
763     pointer addr;
764     register HOST *host;
765
766     family = ConvertAddr(from, &len, (pointer *)&addr);
767     if (family == -1 || family == FamilyLocal)
768         return;
769     for (host = selfhosts; host; host = host->next)
770     {
771         if (addrEqual(family, addr, len, host))
772             return;
773     }
774     MakeHost(host,len)
775     if (!host)
776         return;
777     host->family = family;
778     host->len = len;
779     acopy(addr, host->addr, len);
780     host->next = selfhosts;
781     selfhosts = host;
782 }
783 #endif
784
785 void
786 AddLocalHosts ()
787 {
788     HOST    *self;
789
790     for (self = selfhosts; self; self = self->next)
791         (void) NewHost (self->family, self->addr, self->len);
792 }
793
794 /* Reset access control list to initial hosts */
795 void
796 ResetHosts (display)
797     char *display;
798 {
799     register HOST       *host;
800     char                lhostname[120], ohostname[120];
801     char                *hostname = ohostname;
802     char                fname[PATH_MAX + 1];
803     int                 fnamelen;
804     FILE                *fd;
805     char                *ptr;
806     int                 i, hostlen;
807 #ifndef AMOEBA
808     union {
809         struct sockaddr sa;
810 #if defined(TCPCONN) || defined(STREAMSCONN) || defined(MNX_TCPCONN)
811         struct sockaddr_in in;
812 #endif /* TCPCONN || STREAMSCONN */
813 #ifdef DNETCONN
814         struct sockaddr_dn dn;
815 #endif
816     }                   saddr;
817 #endif /* AMOEBA */
818 #ifdef DNETCONN
819     struct nodeent      *np;
820     struct dn_naddr     dnaddr, *dnaddrp, *dnet_addr();
821 #endif
822 #ifdef K5AUTH
823     krb5_principal      princ;
824     krb5_data           kbuf;
825 #endif
826     int                 family;
827     pointer             addr;
828     int                 len;
829     register struct hostent *hp;
830
831     AccessEnabled = defeatAccessControl ? FALSE : DEFAULT_ACCESS_CONTROL;
832     LocalHostEnabled = FALSE;
833     while (host = validhosts)
834     {
835         validhosts = host->next;
836         FreeHost (host);
837     }
838 #ifndef __EMX__
839 #define ETC_HOST_PREFIX "/etc/X"
840 #define ETC_HOST_SUFFIX ".hosts"
841 #else
842 #define ETC_HOST_PREFIX "/XFree86/lib/X11/X"
843 #define ETC_HOST_SUFFIX ".hosts"
844 #endif /* __EMX__ */
845     fnamelen = strlen(ETC_HOST_PREFIX) + strlen(ETC_HOST_SUFFIX) +
846                 strlen(display) + 1;
847     if (fnamelen > sizeof(fname))
848         FatalError("Display name `%s' is too long\n");
849     sprintf(fname, ETC_HOST_PREFIX "%s" ETC_HOST_SUFFIX, display);
850 #ifdef __EMX__
851     strcpy(fname, (char*)__XOS2RedirRoot(fname));
852 #endif /* __EMX__ */
853
854     if (fd = fopen (fname, "r")) 
855     {
856         while (fgets (ohostname, sizeof (ohostname), fd))
857         {
858         if (*ohostname == '#')
859             continue;
860         if (ptr = strchr(ohostname, '\n'))
861             *ptr = 0;
862 #ifdef __EMX__
863         if (ptr = strchr(ohostname, '\r'))
864             *ptr = 0;
865 #endif
866         hostlen = strlen(ohostname) + 1;
867         for (i = 0; i < hostlen; i++)
868             lhostname[i] = tolower(ohostname[i]);
869         hostname = ohostname;
870         if (!strncmp("local:", lhostname, 6))
871         {
872             family = FamilyLocalHost;
873             NewHost(family, "", 0);
874         }
875 #if defined(TCPCONN) || defined(STREAMSCONN) || defined(MNX_TCPCONN)
876         else if (!strncmp("inet:", lhostname, 5))
877         {
878             family = FamilyInternet;
879             hostname = ohostname + 5;
880         }
881 #endif
882 #ifdef DNETCONN
883         else if (!strncmp("dnet:", lhostname, 5))
884         {
885             family = FamilyDECnet;
886             hostname = ohostname + 5;
887         }
888 #endif
889 #ifdef SECURE_RPC
890         else if (!strncmp("nis:", lhostname, 4))
891         {
892             family = FamilyNetname;
893             hostname = ohostname + 4;
894         }
895 #endif
896 #ifdef K5AUTH
897         else if (!strncmp("krb:", lhostname, 4))
898         {
899             family = FamilyKrb5Principal;
900             hostname = ohostname + 4;
901         }
902 #endif
903 #ifdef DNETCONN
904         if ((family == FamilyDECnet) ||
905             (ptr = strchr(hostname, ':')) && (*(ptr + 1) == ':') &&
906             !(*ptr = '\0'))     /* bash trailing colons if necessary */
907         {
908             /* node name (DECnet names end in "::") */
909             dnaddrp = dnet_addr(hostname);
910             if (!dnaddrp && (np = getnodebyname (hostname)))
911             {
912                 /* node was specified by name */
913                 saddr.sa.sa_family = np->n_addrtype;
914                 len = sizeof(saddr.sa);
915                 if (ConvertAddr (&saddr.sa, &len, (pointer *)&addr) == FamilyDECnet)
916                 {
917                     bzero ((char *) &dnaddr, sizeof (dnaddr));
918                     dnaddr.a_len = np->n_length;
919                     acopy (np->n_addr, dnaddr.a_addr, np->n_length);
920                     dnaddrp = &dnaddr;
921                 }
922             }
923             if (dnaddrp)
924                 (void) NewHost(FamilyDECnet, (pointer)dnaddrp,
925                         (int)(dnaddrp->a_len + sizeof(dnaddrp->a_len)));
926         }
927         else
928 #endif /* DNETCONN */
929 #ifdef K5AUTH
930         if (family == FamilyKrb5Principal)
931         {
932             krb5_parse_name(hostname, &princ);
933             XauKrb5Encode(princ, &kbuf);
934             (void) NewHost(FamilyKrb5Principal, kbuf.data, kbuf.length);
935             krb5_free_principal(princ);
936         }
937         else
938 #endif
939 #ifdef SECURE_RPC
940         if ((family == FamilyNetname) || (strchr(hostname, '@')))
941         {
942             SecureRPCInit ();
943             (void) NewHost (FamilyNetname, hostname, strlen (hostname));
944         }
945         else
946 #endif /* SECURE_RPC */
947 #if defined(TCPCONN) || defined(STREAMSCONN) || defined(MNX_TCPCONN)
948         {
949             /* host name */
950             if (family == FamilyInternet && (hp = gethostbyname (hostname)) ||
951                  (hp = gethostbyname (hostname)))
952             {
953                 saddr.sa.sa_family = hp->h_addrtype;
954                 len = sizeof(saddr.sa);
955                 if ((family = ConvertAddr (&saddr.sa, &len, (pointer *)&addr)) != -1)
956                 {
957 #ifdef h_addr                           /* new 4.3bsd version of gethostent */
958                     char **list;
959
960                     /* iterate over the addresses */
961                     for (list = hp->h_addr_list; *list; list++)
962                         (void) NewHost (family, (pointer)*list, len);
963 #else
964                     (void) NewHost (family, (pointer)hp->h_addr, len);
965 #endif
966                 }
967             }
968         }
969 #endif /* TCPCONN || STREAMSCONN */
970         family = FamilyWild;
971         }
972         fclose (fd);
973     }
974 }
975
976 /* Is client on the local host */
977 Bool LocalClient(client)
978     ClientPtr client;
979 {
980     int                 alen, family, notused;
981     Xtransaddr          *from = NULL;
982     pointer             addr;
983     register HOST       *host;
984
985 #ifdef XCSECURITY
986     /* untrusted clients can't change host access */
987     if (client->trustLevel != XSecurityClientTrusted)
988     {
989         SecurityAudit("client %d attempted to change host access\n",
990                       client->index);
991         return FALSE;
992     }
993 #endif
994 #ifdef LBX
995     if (!((OsCommPtr)client->osPrivate)->trans_conn)
996         return FALSE;
997 #endif
998     if (!_XSERVTransGetPeerAddr (((OsCommPtr)client->osPrivate)->trans_conn,
999         &notused, &alen, &from))
1000     {
1001         family = ConvertAddr ((struct sockaddr *) from,
1002             &alen, (pointer *)&addr);
1003         if (family == -1)
1004         {
1005             xfree ((char *) from);
1006             return FALSE;
1007         }
1008         if (family == FamilyLocal)
1009         {
1010             xfree ((char *) from);
1011             return TRUE;
1012         }
1013         for (host = selfhosts; host; host = host->next)
1014         {
1015             if (addrEqual (family, addr, alen, host))
1016                 return TRUE;
1017         }
1018         xfree ((char *) from);
1019     }
1020     return FALSE;
1021 }
1022
1023 static Bool
1024 AuthorizedClient(client)
1025     ClientPtr client;
1026 {
1027     if (!client || defeatAccessControl)
1028         return TRUE;
1029     return LocalClient(client);
1030 }
1031
1032 /* Add a host to the access control list.  This is the external interface
1033  * called from the dispatcher */
1034
1035 int
1036 AddHost (client, family, length, pAddr)
1037     ClientPtr           client;
1038     int                 family;
1039     unsigned            length;        /* of bytes in pAddr */
1040     pointer             pAddr;
1041 {
1042     int                 len;
1043
1044     if (!AuthorizedClient(client))
1045         return(BadAccess);
1046     switch (family) {
1047     case FamilyLocalHost:
1048         len = length;
1049         LocalHostEnabled = TRUE;
1050         break;
1051 #ifdef K5AUTH
1052     case FamilyKrb5Principal:
1053         len = length;
1054         break;
1055 #endif
1056 #ifdef SECURE_RPC
1057     case FamilyNetname:
1058         len = length;
1059         SecureRPCInit ();
1060         break;
1061 #endif
1062     case FamilyInternet:
1063     case FamilyDECnet:
1064     case FamilyChaos:
1065         if ((len = CheckAddr (family, pAddr, length)) < 0)
1066         {
1067             client->errorValue = length;
1068             return (BadValue);
1069         }
1070         break;
1071     case FamilyLocal:
1072     default:
1073         client->errorValue = family;
1074         return (BadValue);
1075     }
1076     if (NewHost (family, pAddr, len))
1077         return Success;
1078     return BadAlloc;
1079 }
1080
1081 Bool
1082 #if NeedFunctionPrototypes
1083 ForEachHostInFamily (
1084     int     family,
1085     Bool    (*func)(
1086 #if NeedNestedPrototypes
1087             unsigned char * /* addr */,
1088             short           /* len */,
1089             pointer         /* closure */
1090 #endif
1091             ),
1092     pointer closure)
1093 #else
1094 ForEachHostInFamily (family, func, closure)
1095     int     family;
1096     Bool    (*func)();
1097     pointer closure;
1098 #endif
1099 {
1100     HOST    *host;
1101
1102     for (host = validhosts; host; host = host->next)
1103         if (family == host->family && func (host->addr, host->len, closure))
1104             return TRUE;
1105     return FALSE;
1106 }
1107
1108 /* Add a host to the access control list. This is the internal interface 
1109  * called when starting or resetting the server */
1110 static Bool
1111 NewHost (family, addr, len)
1112     int         family;
1113     pointer     addr;
1114     int         len;
1115 {
1116     register HOST *host;
1117
1118     for (host = validhosts; host; host = host->next)
1119     {
1120         if (addrEqual (family, addr, len, host))
1121             return TRUE;
1122     }
1123     MakeHost(host,len)
1124     if (!host)
1125         return FALSE;
1126     host->family = family;
1127     host->len = len;
1128     acopy(addr, host->addr, len);
1129     host->next = validhosts;
1130     validhosts = host;
1131     return TRUE;
1132 }
1133
1134 /* Remove a host from the access control list */
1135
1136 int
1137 RemoveHost (client, family, length, pAddr)
1138     ClientPtr           client;
1139     int                 family;
1140     unsigned            length;        /* of bytes in pAddr */
1141     pointer             pAddr;
1142 {
1143     int                 len;
1144     register HOST       *host, **prev;
1145
1146     if (!AuthorizedClient(client))
1147         return(BadAccess);
1148     switch (family) {
1149     case FamilyLocalHost:
1150         len = length;
1151         LocalHostEnabled = FALSE;
1152         break;
1153 #ifdef K5AUTH
1154     case FamilyKrb5Principal:
1155         len = length;
1156         break;
1157 #endif
1158 #ifdef SECURE_RPC
1159     case FamilyNetname:
1160         len = length;
1161         break;
1162 #endif
1163     case FamilyInternet:
1164     case FamilyDECnet:
1165     case FamilyChaos:
1166         if ((len = CheckAddr (family, pAddr, length)) < 0)
1167         {
1168             client->errorValue = length;
1169             return(BadValue);
1170         }
1171         break;
1172     case FamilyLocal:
1173     default:
1174         client->errorValue = family;
1175         return(BadValue);
1176     }
1177     for (prev = &validhosts;
1178          (host = *prev) && (!addrEqual (family, pAddr, len, host));
1179          prev = &host->next)
1180         ;
1181     if (host)
1182     {
1183         *prev = host->next;
1184         FreeHost (host);
1185     }
1186     return (Success);
1187 }
1188
1189 /* Get all hosts in the access control list */
1190 int
1191 GetHosts (data, pnHosts, pLen, pEnabled)
1192     pointer             *data;
1193     int                 *pnHosts;
1194     int                 *pLen;
1195     BOOL                *pEnabled;
1196 {
1197     int                 len;
1198     register int        n = 0;
1199     register unsigned char *ptr;
1200     register HOST       *host;
1201     int                 nHosts = 0;
1202
1203     *pEnabled = AccessEnabled ? EnableAccess : DisableAccess;
1204     for (host = validhosts; host; host = host->next)
1205     {
1206         nHosts++;
1207         n += (((host->len + 3) >> 2) << 2) + sizeof(xHostEntry);
1208     }
1209     if (n)
1210     {
1211         *data = ptr = (pointer) xalloc (n);
1212         if (!ptr)
1213         {
1214             return(BadAlloc);
1215         }
1216         for (host = validhosts; host; host = host->next)
1217         {
1218             len = host->len;
1219             ((xHostEntry *)ptr)->family = host->family;
1220             ((xHostEntry *)ptr)->length = len;
1221             ptr += sizeof(xHostEntry);
1222             acopy (host->addr, ptr, len);
1223             ptr += ((len + 3) >> 2) << 2;
1224         }
1225     } else {
1226         *data = NULL;
1227     }
1228     *pnHosts = nHosts;
1229     *pLen = n;
1230     return(Success);
1231 }
1232
1233 /* Check for valid address family and length, and return address length. */
1234
1235 /*ARGSUSED*/
1236 static int
1237 CheckAddr (family, pAddr, length)
1238     int                 family;
1239     pointer             pAddr;
1240     unsigned            length;
1241 {
1242     int len;
1243
1244     switch (family)
1245     {
1246 #if defined(TCPCONN) || defined(STREAMSCONN) || defined(AMTCPCONN) || defined(MNX_TCPCONN)
1247       case FamilyInternet:
1248 #if !defined(AMOEBA)
1249         if (length == sizeof (struct in_addr))
1250 #else
1251         if (length == sizeof(ipaddr_t))
1252 #endif
1253             len = length;
1254         else
1255             len = -1;
1256         break;
1257 #endif 
1258 #ifdef DNETCONN
1259       case FamilyDECnet:
1260         {
1261             struct dn_naddr *dnaddr = (struct dn_naddr *) pAddr;
1262
1263             if ((length < sizeof(dnaddr->a_len)) ||
1264                 (length < dnaddr->a_len + sizeof(dnaddr->a_len)))
1265                 len = -1;
1266             else
1267                 len = dnaddr->a_len + sizeof(dnaddr->a_len);
1268             if (len > sizeof(struct dn_naddr))
1269                 len = -1;
1270         }
1271         break;
1272 #endif
1273       default:
1274         len = -1;
1275     }
1276     return (len);
1277 }
1278
1279 /* Check if a host is not in the access control list. 
1280  * Returns 1 if host is invalid, 0 if we've found it. */
1281
1282 InvalidHost (saddr, len)
1283 #ifndef AMOEBA_ORIG
1284     register struct sockaddr    *saddr;
1285 #else
1286     register ipaddr_t           *saddr;
1287 #endif
1288     int                         len;
1289 {
1290     int                         family;
1291     pointer                     addr;
1292     register HOST               *selfhost, *host;
1293
1294     if (!AccessEnabled)   /* just let them in */
1295         return(0);    
1296     family = ConvertAddr (saddr, &len, (pointer *)&addr);
1297     if (family == -1)
1298         return 1;
1299     if (family == FamilyLocal)
1300     {
1301         if (!LocalHostEnabled)
1302         {
1303             /*
1304              * check to see if any local address is enabled.  This 
1305              * implicitly enables local connections.
1306              */
1307             for (selfhost = selfhosts; selfhost; selfhost=selfhost->next)
1308             {
1309                 for (host = validhosts; host; host=host->next)
1310                 {
1311                     if (addrEqual (selfhost->family, selfhost->addr,
1312                                    selfhost->len, host))
1313                         return 0;
1314                 }
1315             }
1316             return 1;
1317         } else
1318             return 0;
1319     }
1320     for (host = validhosts; host; host = host->next)
1321     {
1322         if (addrEqual (family, addr, len, host))
1323             return (0);
1324     }
1325     return (1);
1326 }
1327
1328 static int
1329 ConvertAddr (saddr, len, addr)
1330 #ifndef AMOEBA_ORIG
1331     register struct sockaddr    *saddr;
1332 #else
1333     register ipaddr_t           *saddr;
1334 #endif
1335     int                         *len;
1336     pointer                     *addr;
1337 {
1338 #ifndef AMOEBA
1339     if (*len == 0)
1340         return (FamilyLocal);
1341     switch (saddr->sa_family)
1342     {
1343     case AF_UNSPEC:
1344 #if defined(UNIXCONN) || defined(LOCALCONN) || defined(OS2PIPECONN)
1345     case AF_UNIX:
1346 #endif
1347         return FamilyLocal;
1348 #if defined(TCPCONN) || defined(STREAMSCONN) || defined(MNX_TCPCONN)
1349     case AF_INET:
1350         *len = sizeof (struct in_addr);
1351         *addr = (pointer) &(((struct sockaddr_in *) saddr)->sin_addr);
1352         return FamilyInternet;
1353 #endif
1354 #ifdef DNETCONN
1355     case AF_DECnet:
1356         {
1357             struct sockaddr_dn *sdn = (struct sockaddr_dn *) saddr;
1358             *len = sdn->sdn_nodeaddrl + sizeof(sdn->sdn_nodeaddrl);
1359             *addr = (pointer) &(sdn->sdn_add);
1360         }
1361         return FamilyDECnet;
1362 #endif
1363 #ifdef CHAOSCONN
1364     case AF_CHAOS:
1365         {
1366             not implemented
1367         }
1368         return FamilyChaos;
1369 #endif
1370     default:
1371         return -1;
1372     }
1373 #else /* AMOEBA */
1374     if (*len == 0) return -1;
1375     *len = sizeof (ipaddr_t);
1376     *addr = (pointer) saddr;
1377     return FamilyInternet;
1378 #endif /* AMOEBA */
1379 }
1380
1381 int
1382 ChangeAccessControl(client, fEnabled)
1383     ClientPtr client;
1384     int fEnabled;
1385 {
1386     if (!AuthorizedClient(client))
1387         return BadAccess;
1388     AccessEnabled = fEnabled;
1389     return Success;
1390 }
1391
1392 /* returns FALSE if xhost + in effect, else TRUE */
1393 int
1394 GetAccessControl()
1395 {
1396     return AccessEnabled;
1397 }
1398