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
EnableLocalHost()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
DisableLocalHost()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
AccessUsingXdmcp()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
ifioctl(fd,cmd,arg)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
DefineSelf(fd)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
DefineSelf(fd)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
DefineSelf(fd)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, 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
AugmentSelf(from,len)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
AddLocalHosts()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
ResetHosts(display)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 */
LocalClient(client)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
AuthorizedClient(client)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
AddHost(client,family,length,pAddr)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
ForEachHostInFamily(int family,Bool (* func)(unsigned char *,short,pointer),pointer closure)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
NewHost(family,addr,len)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
RemoveHost(client,family,length,pAddr)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
GetHosts(data,pnHosts,pLen,pEnabled)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
CheckAddr(family,pAddr,length)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 
InvalidHost(saddr,len)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
ConvertAddr(saddr,len,addr)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
ChangeAccessControl(client,fEnabled)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
GetAccessControl()1394 GetAccessControl()
1395 {
1396     return AccessEnabled;
1397 }
1398 
1399