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