1 /***********************************************************
3 Copyright 1987, 1998 The Open Group
7 Permission is hereby granted, free of charge, to any person obtaining a
8 copy of this software and associated documentation files (the
9 "Software"), to deal in the Software without restriction, including
10 without limitation the rights to use, copy, modify, merge, publish,
11 distribute, and/or sell copies of the Software, and to permit persons
12 to whom the Software is furnished to do so, provided that the above
13 copyright notice(s) and this permission notice appear in all copies of
14 the Software and that both the above copyright notice(s) and this
15 permission notice appear in supporting documentation.
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
20 OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
21 HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
22 INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
23 FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
24 NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
25 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
27 Except as contained in this notice, the name of a copyright holder
28 shall not be used in advertising or otherwise to promote the sale, use
29 or other dealings in this Software without prior written authorization
30 of the copyright holder.
32 X Window System is a trademark of The Open Group.
34 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
38 Permission to use, copy, modify, and distribute this software and its
39 documentation for any purpose and without fee is hereby granted,
40 provided that the above copyright notice appear in all copies and that
41 both that copyright notice and this permission notice appear in
42 supporting documentation, and that the name of Digital not be
43 used in advertising or publicity pertaining to distribution of the
44 software without specific, written prior permission.
46 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
47 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
48 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
49 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
50 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
51 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
54 ******************************************************************/
57 * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
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:
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
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.
79 #ifdef HAVE_DIX_CONFIG_H
80 #include <dix-config.h>
84 #include <X11/Xwinsock.h>
92 #include <X11/Xtrans/Xtrans.h>
93 #include <X11/Xauth.h>
95 #include <X11/Xproto.h>
99 #include <sys/types.h>
101 #include <sys/socket.h>
102 #include <sys/ioctl.h>
105 #if defined(TCPCONN) || defined(STREAMSCONN)
106 #include <netinet/in.h>
107 #endif /* TCPCONN || STREAMSCONN */
109 #ifdef HAVE_GETPEERUCRED
116 #if defined(SVR4) || (defined(SYSV) && defined(__i386__)) || defined(__GNU__)
117 #include <sys/utsname.h>
119 #if defined(SYSV) && defined(__i386__)
120 #include <sys/stream.h>
130 #include <sys/sockio.h>
131 #include <sys/stropts.h>
137 #include <sys/param.h>
139 #define VARIABLE_IFREQ
144 #ifndef VARIABLE_IFREQ
145 #define VARIABLE_IFREQ
149 #ifdef HAVE_GETIFADDRS
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
158 * Test for Solaris commented out -- TSI @ UQV 2003.06.13
161 /* #if defined(sun) */
162 #define USE_SIOCGLIFCONF
166 #if defined(IPv6) && defined(AF_INET6)
167 #include <arpa/inet.h>
172 #define X_INCLUDE_NETDB_H
173 #include <X11/Xos_r.h>
175 #include "dixstruct.h"
180 Bool defeatAccessControl
= FALSE
;
182 #define addrEqual(fam, address, length, host) \
183 ((fam) == (host)->family &&\
184 (length) == (host)->len &&\
185 !memcmp (address, (host)->addr, length))
187 static int ConvertAddr(struct sockaddr
* /*saddr */ ,
189 pointer
* /*addr */ );
191 static int CheckAddr(int /*family */ ,
192 const void * /*pAddr */ ,
193 unsigned /*length */ );
195 static Bool
NewHost(int /*family */ ,
196 const void * /*addr */ ,
198 int /* addingLocalHosts */ );
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. */
207 typedef struct _host
{
215 #define MakeHost(h,l) (h)=malloc(sizeof *(h)+(l));\
217 (h)->addr=(unsigned char *) ((h) + 1);\
218 (h)->requested = FALSE; \
220 #define FreeHost(h) free(h)
221 static HOST
*selfhosts
= NULL
;
222 static HOST
*validhosts
= NULL
;
223 static int AccessEnabled
= DEFAULT_ACCESS_CONTROL
;
224 static int LocalHostEnabled
= FALSE
;
225 static int LocalHostRequested
= FALSE
;
226 static int UsingXdmcp
= FALSE
;
228 /* FamilyServerInterpreted implementation */
229 static Bool
siAddrMatch(int family
, pointer addr
, int len
, HOST
* host
,
231 static int siCheckAddr(const char *addrString
, int length
);
232 static void siTypesInitialize(void);
235 * called when authorization is not enabled to add the
236 * local host to the access list
240 EnableLocalHost(void)
243 LocalHostEnabled
= TRUE
;
249 * called when authorization is enabled to keep us secure
252 DisableLocalHost(void)
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
);
266 * called at init time when XDMCP will be used; xdmcp always
267 * adds local hosts manually when needed
271 AccessUsingXdmcp(void)
274 LocalHostEnabled
= FALSE
;
277 #if defined(SVR4) && !defined(sun) && defined(SIOCGIFCONF) && !defined(USE_SIOCGLIFCONF)
279 /* Deal with different SIOCGIFCONF ioctl semantics on these OSs */
282 ifioctl(int fd
, int cmd
, char *arg
)
287 memset((char *) &ioc
, 0, sizeof(ioc
));
290 if (cmd
== SIOCGIFCONF
) {
291 ioc
.ic_len
= ((struct ifconf
*) arg
)->ifc_len
;
292 ioc
.ic_dp
= ((struct ifconf
*) arg
)->ifc_buf
;
295 ioc
.ic_len
= sizeof(struct ifreq
);
298 ret
= ioctl(fd
, I_STR
, (char *) &ioc
);
299 if (ret
>= 0 && cmd
== SIOCGIFCONF
)
301 ((struct ifconf
*) arg
)->ifc_len
= ioc
.ic_len
;
306 #define ifioctl ioctl
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.
316 #if !defined(SIOCGIFCONF)
320 #if !defined(TCPCONN) && !defined(STREAMSCONN) && !defined(UNIXCONN)
337 register struct hostent
*hp
;
341 struct sockaddr_in in
;
342 #if defined(IPv6) && defined(AF_INET6)
343 struct sockaddr_in6 in6
;
347 struct sockaddr_in
*inetaddr
;
348 struct sockaddr_in6
*inet6addr
;
349 struct sockaddr_in broad_addr
;
351 #ifdef XTHREADS_NEEDS_BYNAMEPARAMS
352 _Xgethostbynameparams hparams
;
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.
363 gethostname(name
.nodename
, sizeof(name
.nodename
));
366 hp
= _XGethostbyname(name
.nodename
, hparams
);
368 saddr
.sa
.sa_family
= hp
->h_addrtype
;
369 switch (hp
->h_addrtype
) {
371 inetaddr
= (struct sockaddr_in
*) (&(saddr
.sa
));
372 memcpy(&(inetaddr
->sin_addr
), hp
->h_addr
, hp
->h_length
);
373 len
= sizeof(saddr
.sa
);
375 #if defined(IPv6) && defined(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
);
383 goto DefineLocalHost
;
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
);
391 /* add this host to the host list. */
394 host
->family
= family
;
396 memcpy(host
->addr
, addr
, len
);
397 host
->next
= selfhosts
;
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),
406 if (family
== FamilyInternet
&&
409 (addr
[0] == 0 && addr
[1] == 0 &&
410 addr
[2] == 0 && addr
[3] == 0)))
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
*)
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
);
431 * now add a host of family FamilyLocalHost...
434 for (host
= selfhosts
;
435 host
&& !addrEqual(FamilyLocalHost
, "", 0, host
); host
= host
->next
);
439 host
->family
= FamilyLocalHost
;
441 /* Nothing to store in host->addr */
442 host
->next
= selfhosts
;
446 #endif /* !TCPCONN && !STREAMSCONN && !UNIXCONN */
451 #ifdef USE_SIOCGLIFCONF
452 #define ifr_type struct lifreq
454 #define ifr_type struct ifreq
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)
463 #define ifr_size(p) (sizeof (ifr_type))
464 #define ifraddr_size(a) (sizeof (a))
467 #if defined(IPv6) && defined(AF_INET6)
469 in6_fillscopeid(struct sockaddr_in6
*sin6
)
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;
484 #ifndef HAVE_GETIFADDRS
487 #ifdef USE_SIOCGLIFCONF
488 struct sockaddr_storage buf
[16];
490 register struct lifreq
*ifr
;
495 #else /* !USE_SIOCGLIFCONF */
498 register struct ifreq
*ifr
;
501 #else /* HAVE_GETIFADDRS */
502 struct ifaddrs
*ifap
, *ifr
;
509 #ifndef HAVE_GETIFADDRS
513 #ifdef USE_SIOCGLIFCONF
516 ifn
.lifn_family
= AF_UNSPEC
;
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
);
526 ifc
.lifc_family
= AF_UNSPEC
;
529 ifc
.lifc_buf
= bufptr
;
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
537 #else /* Use SIOCGIFCONF */
539 ifc
.ifc_buf
= bufptr
;
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
548 if (ifioctl(fd
, IFC_IOCTL_REQ
, (pointer
) &ifc
) < 0)
549 ErrorF("Getting interface configuration (4): %s\n", strerror(errno
));
551 cplim
= (char *) IFC_IFC_REQ
+ IFC_IFC_LEN
;
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
)
560 #if defined(IPv6) && defined(AF_INET6)
561 if (family
== FamilyInternet6
)
562 in6_fillscopeid((struct sockaddr_in6
*) &IFR_IFR_ADDR
);
564 for (host
= selfhosts
;
565 host
&& !addrEqual(family
, addr
, len
, host
); host
= host
->next
);
570 host
->family
= family
;
572 memcpy(host
->addr
, addr
, len
);
573 host
->next
= selfhosts
;
578 #ifdef USE_SIOCGLIFCONF
579 struct sockaddr_storage broad_addr
;
581 struct sockaddr broad_addr
;
585 * If this isn't an Internet Address, don't register it.
587 if (family
!= FamilyInternet
588 #if defined(IPv6) && defined(AF_INET6)
589 && family
!= FamilyInternet6
595 * ignore 'localhost' entries as they're not useful
596 * on the other end of the wire
598 if (family
== FamilyInternet
&&
599 addr
[0] == 127 && addr
[1] == 0 && addr
[2] == 0 && addr
[3] == 1)
601 #if defined(IPv6) && defined(AF_INET6)
602 else if (family
== FamilyInternet6
&&
603 IN6_IS_ADDR_LOOPBACK((struct in6_addr
*) addr
))
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.
613 addr
[0] == 0 && addr
[1] == 0 && addr
[2] == 0 && addr
[3] == 0)
616 XdmcpRegisterConnection(family
, (char *) addr
, len
);
618 #if defined(IPv6) && defined(AF_INET6)
619 /* IPv6 doesn't support broadcasting, so we drop out here */
620 if (family
== FamilyInternet6
)
624 broad_addr
= IFR_IFR_ADDR
;
626 ((struct sockaddr_in
*) &broad_addr
)->sin_addr
.s_addr
=
627 htonl(INADDR_BROADCAST
);
628 #if defined(USE_SIOCGLIFCONF) && defined(SIOCGLIFBRDADDR)
630 struct lifreq broad_req
;
633 if (ioctl(fd
, SIOCGLIFFLAGS
, (char *) &broad_req
) != -1 &&
634 (broad_req
.lifr_flags
& IFF_BROADCAST
) &&
635 (broad_req
.lifr_flags
& IFF_UP
)
638 if (ioctl(fd
, SIOCGLIFBRDADDR
, &broad_req
) != -1)
639 broad_addr
= broad_req
.lifr_broadaddr
;
647 #elif defined(SIOCGIFBRDADDR)
649 struct ifreq broad_req
;
652 if (ifioctl(fd
, SIOCGIFFLAGS
, (pointer
) &broad_req
) != -1 &&
653 (broad_req
.ifr_flags
& IFF_BROADCAST
) &&
654 (broad_req
.ifr_flags
& IFF_UP
)
657 if (ifioctl(fd
, SIOCGIFBRDADDR
, (pointer
) &broad_req
) != -1)
658 broad_addr
= broad_req
.ifr_addr
;
665 #endif /* SIOCGIFBRDADDR */
666 XdmcpRegisterBroadcastAddress((struct sockaddr_in
*) &broad_addr
);
672 #else /* HAVE_GETIFADDRS */
673 if (getifaddrs(&ifap
) < 0) {
674 ErrorF("Warning: getifaddrs returns %s\n", strerror(errno
));
677 for (ifr
= ifap
; ifr
!= NULL
; ifr
= ifr
->ifa_next
) {
680 len
= sizeof(*(ifr
->ifa_addr
));
681 family
= ConvertAddr((struct sockaddr
*) ifr
->ifa_addr
, &len
,
683 if (family
== -1 || family
== FamilyLocal
)
685 #if defined(IPv6) && defined(AF_INET6)
686 if (family
== FamilyInternet6
)
687 in6_fillscopeid((struct sockaddr_in6
*) ifr
->ifa_addr
);
690 for (host
= selfhosts
;
691 host
!= NULL
&& !addrEqual(family
, addr
, len
, host
);
697 host
->family
= family
;
699 memcpy(host
->addr
, addr
, len
);
700 host
->next
= selfhosts
;
706 * If this isn't an Internet Address, don't register it.
708 if (family
!= FamilyInternet
709 #if defined(IPv6) && defined(AF_INET6)
710 && family
!= FamilyInternet6
716 * ignore 'localhost' entries as they're not useful
717 * on the other end of the wire
719 if (ifr
->ifa_flags
& IFF_LOOPBACK
)
722 if (family
== FamilyInternet
&&
723 addr
[0] == 127 && addr
[1] == 0 && addr
[2] == 0 && addr
[3] == 1)
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.
732 addr
[0] == 0 && addr
[1] == 0 && addr
[2] == 0 && addr
[3] == 0)
734 #if defined(IPv6) && defined(AF_INET6)
735 else if (family
== FamilyInternet6
&&
736 IN6_IS_ADDR_LOOPBACK((struct in6_addr
*) addr
))
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 */
745 if ((ifr
->ifa_flags
& IFF_BROADCAST
) &&
746 (ifr
->ifa_flags
& IFF_UP
) && ifr
->ifa_broadaddr
)
747 XdmcpRegisterBroadcastAddress((struct sockaddr_in
*) ifr
->
756 #endif /* HAVE_GETIFADDRS */
759 * add something of FamilyLocalHost
761 for (host
= selfhosts
;
762 host
&& !addrEqual(FamilyLocalHost
, "", 0, host
); host
= host
->next
);
766 host
->family
= FamilyLocalHost
;
768 /* Nothing to store in host->addr */
769 host
->next
= selfhosts
;
774 #endif /* hpux && !HAVE_IFREQ */
778 AugmentSelf(pointer from
, int len
)
784 family
= ConvertAddr(from
, &len
, (pointer
*) &addr
);
785 if (family
== -1 || family
== FamilyLocal
)
787 for (host
= selfhosts
; host
; host
= host
->next
) {
788 if (addrEqual(family
, addr
, len
, host
))
794 host
->family
= family
;
796 memcpy(host
->addr
, addr
, len
);
797 host
->next
= selfhosts
;
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
);
815 /* Reset access control list to initial hosts */
817 ResetHosts(char *display
)
820 char lhostname
[120], ohostname
[120];
821 char *hostname
= ohostname
;
822 char fname
[PATH_MAX
+ 1];
828 #if (defined(TCPCONN) || defined(STREAMSCONN) ) && \
829 (!defined(IPv6) || !defined(AF_INET6))
832 #if defined(TCPCONN) || defined(STREAMSCONN)
833 struct sockaddr_in in
;
834 #endif /* TCPCONN || STREAMSCONN */
842 AccessEnabled
= defeatAccessControl
? FALSE
: DEFAULT_ACCESS_CONTROL
;
843 LocalHostEnabled
= FALSE
;
844 while ((host
= validhosts
) != 0) {
845 validhosts
= host
->next
;
849 #if defined WIN32 && defined __MINGW32__
850 #define ETC_HOST_PREFIX "X"
852 #define ETC_HOST_PREFIX "/etc/X"
854 #define ETC_HOST_SUFFIX ".hosts"
855 fnamelen
= strlen(ETC_HOST_PREFIX
) + strlen(ETC_HOST_SUFFIX
) +
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
,
862 if ((fd
= fopen(fname
, "r")) != 0) {
863 while (fgets(ohostname
, sizeof(ohostname
), fd
)) {
865 if (*ohostname
== '#')
867 if ((ptr
= strchr(ohostname
, '\n')) != 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 */
878 #if defined(TCPCONN) || defined(STREAMSCONN)
879 else if (!strncmp("inet:", lhostname
, 5)) {
880 family
= FamilyInternet
;
881 hostname
= ohostname
+ 5;
883 #if defined(IPv6) && defined(AF_INET6)
884 else if (!strncmp("inet6:", lhostname
, 6)) {
885 family
= FamilyInternet6
;
886 hostname
= ohostname
+ 6;
891 else if (!strncmp("nis:", lhostname
, 4)) {
892 family
= FamilyNetname
;
893 hostname
= ohostname
+ 4;
896 else if (!strncmp("si:", lhostname
, 3)) {
897 family
= FamilyServerInterpreted
;
898 hostname
= ohostname
+ 3;
902 if (family
== FamilyServerInterpreted
) {
903 len
= siCheckAddr(hostname
, hostlen
);
905 NewHost(family
, hostname
, len
, FALSE
);
910 if ((family
== FamilyNetname
) || (strchr(hostname
, '@'))) {
912 (void) NewHost(FamilyNetname
, hostname
, strlen(hostname
),
916 #endif /* SECURE_RPC */
917 #if defined(TCPCONN) || defined(STREAMSCONN)
919 #if defined(IPv6) && defined(AF_INET6)
920 if ((family
== FamilyInternet
) || (family
== FamilyInternet6
) ||
921 (family
== FamilyWild
)) {
922 struct addrinfo
*addresses
;
926 if (getaddrinfo(hostname
, NULL
, NULL
, &addresses
) == 0) {
927 for (a
= addresses
; a
!= NULL
; a
= a
->ai_next
) {
929 f
= ConvertAddr(a
->ai_addr
, &len
,
932 ((family
== FamilyWild
) && (f
!= -1))) {
933 NewHost(f
, addr
, len
, FALSE
);
936 freeaddrinfo(addresses
);
940 #ifdef XTHREADS_NEEDS_BYNAMEPARAMS
941 _Xgethostbynameparams hparams
;
943 register struct hostent
*hp
;
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
);
952 ConvertAddr(&saddr
.sa
, &len
,
953 (pointer
*) &addr
)) != -1) {
954 #ifdef h_addr /* new 4.3bsd version of gethostent */
957 /* iterate over the addresses */
958 for (list
= hp
->h_addr_list
; *list
; list
++)
959 (void) NewHost(family
, (pointer
) *list
, len
, FALSE
);
961 (void) NewHost(family
, (pointer
) hp
->h_addr
, len
,
968 #endif /* TCPCONN || STREAMSCONN */
975 /* Is client on the local host */
977 ComputeLocalClient(ClientPtr client
)
979 int alen
, family
, notused
;
980 Xtransaddr
*from
= NULL
;
983 OsCommPtr oc
= (OsCommPtr
) client
->osPrivate
;
988 if (!_XSERVTransGetPeerAddr(oc
->trans_conn
, ¬used
, &alen
, &from
)) {
989 family
= ConvertAddr((struct sockaddr
*) from
,
990 &alen
, (pointer
*) &addr
);
995 if (family
== FamilyLocal
) {
999 for (host
= selfhosts
; host
; host
= host
->next
) {
1000 if (addrEqual(family
, addr
, alen
, host
)) {
1011 * Return the uid and gid of a connected local client
1013 * Used by XShm to test access rights to shared memory segments
1016 LocalClientCred(ClientPtr client
, int *pUid
, int *pGid
)
1018 LocalClientCredRec
*lcc
;
1019 int ret
= GetLocalClientCreds(client
, &lcc
);
1022 #ifdef HAVE_GETZONEID /* only local if in the same zone */
1023 if ((lcc
->fieldsSet
& LCC_ZID_SET
) && (lcc
->zoneid
!= getzoneid())) {
1024 FreeLocalClientCreds(lcc
);
1028 if ((lcc
->fieldsSet
& LCC_UID_SET
) && (pUid
!= NULL
))
1030 if ((lcc
->fieldsSet
& LCC_GID_SET
) && (pGid
!= NULL
))
1032 FreeLocalClientCreds(lcc
);
1038 * Return the uid and all gids of a connected local client
1039 * Allocates a LocalClientCredRec - caller must call FreeLocalClientCreds
1041 * Used by localuser & localgroup ServerInterpreted access control forms below
1042 * Used by AuthAudit to log who local connections came from
1045 GetLocalClientCreds(ClientPtr client
, LocalClientCredRec
** lccp
)
1047 #if defined(HAVE_GETPEEREID) || defined(HAVE_GETPEERUCRED) || defined(SO_PEERCRED)
1050 LocalClientCredRec
*lcc
;
1052 #ifdef HAVE_GETPEEREID
1055 #elif defined(HAVE_GETPEERUCRED)
1056 ucred_t
*peercred
= NULL
;
1058 #elif defined(SO_PEERCRED)
1059 struct ucred peercred
;
1060 socklen_t so_len
= sizeof(peercred
);
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
1071 if (!_XSERVTransIsLocal(ci
)) {
1076 *lccp
= calloc(1, sizeof(LocalClientCredRec
));
1081 fd
= _XSERVTransGetConnectionNumber(ci
);
1082 #ifdef HAVE_GETPEEREID
1083 if (getpeereid(fd
, &uid
, &gid
) == -1) {
1084 FreeLocalClientCreds(lcc
);
1089 lcc
->fieldsSet
= LCC_UID_SET
| LCC_GID_SET
;
1091 #elif defined(HAVE_GETPEERUCRED)
1092 if (getpeerucred(fd
, &peercred
) < 0) {
1093 FreeLocalClientCreds(lcc
);
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
);
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
;
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
) {
1119 for (i
= 0; i
< lcc
->nSuppGids
; i
++) {
1120 (lcc
->pSuppGids
)[i
] = (int) gids
[i
];
1127 ucred_free(peercred
);
1129 #elif defined(SO_PEERCRED)
1130 if (getsockopt(fd
, SOL_SOCKET
, SO_PEERCRED
, &peercred
, &so_len
) == -1) {
1131 FreeLocalClientCreds(lcc
);
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
;
1141 /* No system call available to get the credentials of the peer */
1142 #define NO_LOCAL_CLIENT_CRED
1148 FreeLocalClientCreds(LocalClientCredRec
* lcc
)
1151 if (lcc
->nSuppGids
> 0) {
1152 free(lcc
->pSuppGids
);
1159 AuthorizedClient(ClientPtr client
)
1163 if (!client
|| defeatAccessControl
)
1166 /* untrusted clients can't change host access */
1167 rc
= XaceHook(XACE_SERVER_ACCESS
, client
, DixManageAccess
);
1171 return client
->local
? Success
: BadAccess
;
1174 /* Add a host to the access control list. This is the external interface
1175 * called from the dispatcher */
1178 AddHost(ClientPtr client
, int family
, unsigned length
, /* of bytes in pAddr */
1183 rc
= AuthorizedClient(client
);
1187 case FamilyLocalHost
:
1189 LocalHostEnabled
= TRUE
;
1197 case FamilyInternet
:
1198 #if defined(IPv6) && defined(AF_INET6)
1199 case FamilyInternet6
:
1203 case FamilyServerInterpreted
:
1204 if ((len
= CheckAddr(family
, pAddr
, length
)) < 0) {
1205 client
->errorValue
= length
;
1211 client
->errorValue
= family
;
1214 if (NewHost(family
, pAddr
, len
, FALSE
))
1220 ForEachHostInFamily(int family
, Bool (*func
) (unsigned char * /* addr */ ,
1222 pointer
/* closure */ ),
1227 for (host
= validhosts
; host
; host
= host
->next
)
1228 if (family
== host
->family
&& func(host
->addr
, host
->len
, closure
))
1233 /* Add a host to the access control list. This is the internal interface
1234 * called when starting or resetting the server */
1236 NewHost(int family
, const void *addr
, int len
, int addingLocalHosts
)
1238 register HOST
*host
;
1240 for (host
= validhosts
; host
; host
= host
->next
) {
1241 if (addrEqual(family
, addr
, len
, host
))
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
;
1255 host
->family
= family
;
1257 memcpy(host
->addr
, addr
, len
);
1258 host
->next
= validhosts
;
1263 /* Remove a host from the access control list */
1266 RemoveHost(ClientPtr client
, int family
, unsigned length
, /* of bytes in pAddr */
1270 register HOST
*host
, **prev
;
1272 rc
= AuthorizedClient(client
);
1276 case FamilyLocalHost
:
1278 LocalHostEnabled
= FALSE
;
1285 case FamilyInternet
:
1286 #if defined(IPv6) && defined(AF_INET6)
1287 case FamilyInternet6
:
1291 case FamilyServerInterpreted
:
1292 if ((len
= CheckAddr(family
, pAddr
, length
)) < 0) {
1293 client
->errorValue
= length
;
1299 client
->errorValue
= family
;
1302 for (prev
= &validhosts
;
1303 (host
= *prev
) && (!addrEqual(family
, pAddr
, len
, host
));
1304 prev
= &host
->next
);
1312 /* Get all hosts in the access control list */
1314 GetHosts(pointer
*data
, int *pnHosts
, int *pLen
, BOOL
* pEnabled
)
1318 register unsigned char *ptr
;
1319 register HOST
*host
;
1322 *pEnabled
= AccessEnabled
? EnableAccess
: DisableAccess
;
1323 for (host
= validhosts
; host
; host
= host
->next
) {
1325 n
+= pad_to_int32(host
->len
) + sizeof(xHostEntry
);
1328 *data
= ptr
= malloc(n
);
1332 for (host
= validhosts
; host
; host
= host
->next
) {
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
);
1349 /* Check for valid address family and length, and return address length. */
1351 /*ARGSUSED*/ static int
1352 CheckAddr(int family
, const void *pAddr
, unsigned length
)
1357 #if defined(TCPCONN) || defined(STREAMSCONN)
1358 case FamilyInternet
:
1359 if (length
== sizeof(struct in_addr
))
1364 #if defined(IPv6) && defined(AF_INET6)
1365 case FamilyInternet6
:
1366 if (length
== sizeof(struct in6_addr
))
1373 case FamilyServerInterpreted
:
1374 len
= siCheckAddr(pAddr
, length
);
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. */
1386 InvalidHost(register struct sockaddr
*saddr
, int len
, ClientPtr client
)
1390 register HOST
*selfhost
, *host
;
1392 if (!AccessEnabled
) /* just let them in */
1394 family
= ConvertAddr(saddr
, &len
, (pointer
*) &addr
);
1397 if (family
== FamilyLocal
) {
1398 if (!LocalHostEnabled
) {
1400 * check to see if any local address is enabled. This
1401 * implicitly enables local connections.
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
))
1414 for (host
= validhosts
; host
; host
= host
->next
) {
1415 if (host
->family
== FamilyServerInterpreted
) {
1416 if (siAddrMatch(family
, addr
, len
, host
, client
)) {
1421 if (addrEqual(family
, addr
, len
, host
))
1430 ConvertAddr(register struct sockaddr
*saddr
, int *len
, pointer
*addr
)
1434 switch (saddr
->sa_family
) {
1436 #if defined(UNIXCONN) || defined(LOCALCONN)
1440 #if defined(TCPCONN) || defined(STREAMSCONN)
1443 if (16777343 == *(long *) &((struct sockaddr_in
*) saddr
)->sin_addr
)
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)
1452 struct sockaddr_in6
*saddr6
= (struct sockaddr_in6
*) saddr
;
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
;
1460 *len
= sizeof(struct in6_addr
);
1461 *addr
= (pointer
) &(saddr6
->sin6_addr
);
1462 return FamilyInternet6
;
1473 ChangeAccessControl(ClientPtr client
, int fEnabled
)
1475 int rc
= AuthorizedClient(client
);
1479 AccessEnabled
= fEnabled
;
1483 /* returns FALSE if xhost + in effect, else TRUE */
1485 GetAccessControl(void)
1487 return AccessEnabled
;
1490 /*****************************************************************************
1491 * FamilyServerInterpreted host entry implementation
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.
1496 * Currently supported schemes:
1498 * hostname - hostname as defined in IETF RFC 2396
1499 * ipv6 - IPv6 literal address as defined in IETF RFC's 3513 and <TBD>
1501 * See xc/doc/specs/SIAddresses for formal definitions of each type.
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.
1508 typedef Bool (*siAddrMatchFunc
) (int family
, pointer addr
, int len
,
1509 const char *siAddr
, int siAddrlen
,
1510 ClientPtr client
, void *siTypePriv
);
1511 typedef int (*siCheckAddrFunc
) (const char *addrString
, int length
,
1515 struct siType
*next
;
1516 const char *typeName
;
1517 siAddrMatchFunc addrMatch
;
1518 siCheckAddrFunc checkAddr
;
1519 void *typePriv
; /* Private data for type routines */
1522 static struct siType
*siTypeList
;
1525 siTypeAdd(const char *typeName
, siAddrMatchFunc addrMatch
,
1526 siCheckAddrFunc checkAddr
, void *typePriv
)
1528 struct siType
*s
, *p
;
1530 if ((typeName
== NULL
) || (addrMatch
== NULL
) || (checkAddr
== NULL
))
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
;
1542 s
= malloc(sizeof(struct siType
));
1552 s
->typeName
= typeName
;
1553 s
->addrMatch
= addrMatch
;
1554 s
->checkAddr
= checkAddr
;
1555 s
->typePriv
= typePriv
;
1559 /* Checks to see if a host matches a server-interpreted host entry */
1561 siAddrMatch(int family
, pointer addr
, int len
, HOST
* host
, ClientPtr client
)
1563 Bool matches
= FALSE
;
1565 const char *valueString
;
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
,
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");
1589 siCheckAddr(const char *addrString
, int length
)
1591 const char *valueString
;
1592 int addrlen
, typelen
;
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.
1603 typelen
= strlen(addrString
) + 1;
1604 addrlen
= length
- typelen
;
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
);
1615 #ifdef FAMILY_SI_DEBUG
1617 const char *resultMsg
;
1620 resultMsg
= "type not registered";
1624 resultMsg
= "rejected";
1626 resultMsg
= "accepted";
1630 ("Xserver: siCheckAddr(): type = %s, value = %*.*s, len = %d -- %s\n",
1631 addrString
, addrlen
, addrlen
, valueString
+ 1, len
, resultMsg
);
1639 * Hostname server-interpreted host type
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.
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
1652 #define SI_HOSTNAME_MAXLEN NI_MAXHOST
1654 #ifdef MAXHOSTNAMELEN
1655 #define SI_HOSTNAME_MAXLEN MAXHOSTNAMELEN
1657 #define SI_HOSTNAME_MAXLEN 256
1662 siHostnameAddrMatch(int family
, pointer addr
, int len
,
1663 const char *siAddr
, int siAddrLen
, ClientPtr client
,
1668 /* Currently only supports checking against IPv4 & IPv6 connections, but
1669 * support for other address families, such as DECnet, could be added if
1672 #if defined(IPv6) && defined(AF_INET6)
1673 if ((family
== FamilyInternet
) || (family
== FamilyInternet6
)) {
1674 char hostname
[SI_HOSTNAME_MAXLEN
];
1675 struct addrinfo
*addresses
;
1680 if (siAddrLen
>= sizeof(hostname
))
1683 strlcpy(hostname
, siAddr
, siAddrLen
+ 1);
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)) {
1695 freeaddrinfo(addresses
);
1698 #else /* IPv6 not supported, use gethostbyname instead for IPv4 */
1699 if (family
== FamilyInternet
) {
1700 register struct hostent
*hp
;
1702 #ifdef XTHREADS_NEEDS_BYNAMEPARAMS
1703 _Xgethostbynameparams hparams
;
1705 char hostname
[SI_HOSTNAME_MAXLEN
];
1708 const char **addrlist
;
1710 if (siAddrLen
>= sizeof(hostname
))
1713 strlcpy(hostname
, siAddr
, siAddrLen
+ 1);
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
++)
1720 addrlist
= &hp
->h_addr
;
1723 struct sockaddr_in sin
;
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)) {
1743 siHostnameCheckAddr(const char *valueString
, int length
, void *typePriv
)
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.
1751 Bool dotAllowed
= FALSE
;
1752 Bool dashAllowed
= FALSE
;
1754 if ((length
<= 0) || (length
>= SI_HOSTNAME_MAXLEN
)) {
1758 for (i
= 0; i
< length
; i
++) {
1759 char c
= valueString
[i
];
1761 if (c
== 0x2E) { /* '.' */
1762 if (dotAllowed
== FALSE
) {
1768 dashAllowed
= FALSE
;
1771 else if (c
== 0x2D) { /* '-' */
1772 if (dashAllowed
== FALSE
) {
1780 else if (((c
>= 0x30) && (c
<= 0x3A)) /* 0-9 */ ||
1781 ((c
>= 0x61) && (c
<= 0x7A)) /* a-z */ ||
1782 ((c
>= 0x41) && (c
<= 0x5A)) /* A-Z */ ) {
1786 else { /* Invalid character */
1795 #if defined(IPv6) && defined(AF_INET6)
1797 * "ipv6" server interpreted type
1799 * Currently supports only IPv6 literal address as specified in IETF RFC 3513
1801 * Once draft-ietf-ipv6-scoping-arch-00.txt becomes an RFC, support will be
1802 * added for the scoped address format it specifies.
1805 /* Maximum length of an IPv6 address string - increase when adding support
1806 * for scoped address qualifiers. Includes room for trailing NUL byte.
1808 #define SI_IPv6_MAXLEN INET6_ADDRSTRLEN
1811 siIPv6AddrMatch(int family
, pointer addr
, int len
,
1812 const char *siAddr
, int siAddrlen
, ClientPtr client
,
1815 struct in6_addr addr6
;
1816 char addrbuf
[SI_IPv6_MAXLEN
];
1818 if ((family
!= FamilyInternet6
) || (len
!= sizeof(addr6
)))
1821 memcpy(addrbuf
, siAddr
, siAddrlen
);
1822 addrbuf
[siAddrlen
] = '\0';
1824 if (inet_pton(AF_INET6
, addrbuf
, &addr6
) != 1) {
1825 perror("inet_pton");
1829 if (memcmp(addr
, &addr6
, len
) == 0) {
1838 siIPv6CheckAddr(const char *addrString
, int length
, void *typePriv
)
1842 /* Minimum length is 3 (smallest legal address is "::1") */
1844 /* Address is too short! */
1847 else if (length
>= SI_IPv6_MAXLEN
) {
1848 /* Address is too long! */
1852 /* Assume inet_pton is sufficient validation */
1853 struct in6_addr addr6
;
1854 char addrbuf
[SI_IPv6_MAXLEN
];
1856 memcpy(addrbuf
, addrString
, length
);
1857 addrbuf
[length
] = '\0';
1859 if (inet_pton(AF_INET6
, addrbuf
, &addr6
) != 1) {
1860 perror("inet_pton");
1871 #if !defined(NO_LOCAL_CLIENT_CRED)
1873 * "localuser" & "localgroup" server interpreted types
1875 * Allows local connections from a given local user or group
1881 #define LOCAL_USER 1
1882 #define LOCAL_GROUP 2
1886 } siLocalCredPrivRec
, *siLocalCredPrivPtr
;
1888 static siLocalCredPrivRec siLocalUserPriv
= { LOCAL_USER
};
1889 static siLocalCredPrivRec siLocalGroupPriv
= { LOCAL_GROUP
};
1892 siLocalCredGetId(const char *addr
, int len
, siLocalCredPrivPtr lcPriv
, int *id
)
1894 Bool parsedOK
= FALSE
;
1895 char *addrbuf
= malloc(len
+ 1);
1897 if (addrbuf
== NULL
) {
1901 memcpy(addrbuf
, addr
, len
);
1902 addrbuf
[len
] = '\0';
1904 if (addr
[0] == '#') { /* numeric id */
1908 *id
= strtol(addrbuf
+ 1, &cp
, 0);
1909 if ((errno
== 0) && (cp
!= (addrbuf
+ 1))) {
1913 else { /* non-numeric name */
1914 if (lcPriv
->credType
== LOCAL_USER
) {
1915 struct passwd
*pw
= getpwnam(addrbuf
);
1918 *id
= (int) pw
->pw_uid
;
1923 struct group
*gr
= getgrnam(addrbuf
);
1926 *id
= (int) gr
->gr_gid
;
1937 siLocalCredAddrMatch(int family
, pointer addr
, int len
,
1938 const char *siAddr
, int siAddrlen
, ClientPtr client
,
1942 LocalClientCredRec
*lcc
;
1943 siLocalCredPrivPtr lcPriv
= (siLocalCredPrivPtr
) typePriv
;
1945 if (GetLocalClientCreds(client
, &lcc
) == -1) {
1949 #ifdef HAVE_GETZONEID /* Ensure process is in the same zone */
1950 if ((lcc
->fieldsSet
& LCC_ZID_SET
) && (lcc
->zoneid
!= getzoneid())) {
1951 FreeLocalClientCreds(lcc
);
1956 if (siLocalCredGetId(siAddr
, siAddrlen
, lcPriv
, &siAddrId
) == FALSE
) {
1957 FreeLocalClientCreds(lcc
);
1961 if (lcPriv
->credType
== LOCAL_USER
) {
1962 if ((lcc
->fieldsSet
& LCC_UID_SET
) && (lcc
->euid
== siAddrId
)) {
1963 FreeLocalClientCreds(lcc
);
1968 if ((lcc
->fieldsSet
& LCC_GID_SET
) && (lcc
->egid
== siAddrId
)) {
1969 FreeLocalClientCreds(lcc
);
1972 if (lcc
->pSuppGids
!= NULL
) {
1975 for (i
= 0; i
< lcc
->nSuppGids
; i
++) {
1976 if (lcc
->pSuppGids
[i
] == siAddrId
) {
1977 FreeLocalClientCreds(lcc
);
1983 FreeLocalClientCreds(lcc
);
1988 siLocalCredCheckAddr(const char *addrString
, int length
, void *typePriv
)
1993 if (siLocalCredGetId(addrString
, length
,
1994 (siLocalCredPrivPtr
) typePriv
, &id
) == FALSE
) {
1999 #endif /* localuser */
2002 siTypesInitialize(void)
2004 siTypeAdd("hostname", siHostnameAddrMatch
, siHostnameCheckAddr
, NULL
);
2005 #if defined(IPv6) && defined(AF_INET6)
2006 siTypeAdd("ipv6", siIPv6AddrMatch
, siIPv6CheckAddr
, NULL
);
2008 #if !defined(NO_LOCAL_CLIENT_CRED)
2009 siTypeAdd("localuser", siLocalCredAddrMatch
, siLocalCredCheckAddr
,
2011 siTypeAdd("localgroup", siLocalCredAddrMatch
, siLocalCredCheckAddr
,