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 ¬used, &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