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.
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 #include <dix-config.h>
82 #include <X11/Xwinsock.h>
90 #include <X11/Xtrans/Xtrans.h>
91 #include <X11/Xauth.h>
93 #include <X11/Xproto.h>
96 #include <sys/types.h>
98 #include <sys/socket.h>
99 #include <sys/ioctl.h>
102 #ifndef NO_LOCAL_CLIENT_CRED
107 #include <netinet/in.h>
110 #ifdef HAVE_GETPEERUCRED
117 #ifdef HAVE_SYS_UCRED_H
118 #include <sys/ucred.h>
125 #if defined(SVR4) || defined(__GNU__)
126 #include <sys/utsname.h>
136 #include <sys/sockio.h>
137 #include <sys/stropts.h>
143 #include <sys/param.h>
145 #define VARIABLE_IFREQ
150 #ifndef VARIABLE_IFREQ
151 #define VARIABLE_IFREQ
155 #ifdef HAVE_GETIFADDRS
159 /* Solaris provides an extended interface SIOCGLIFCONF. */
161 #define USE_SIOCGLIFCONF
163 #endif /* HAVE_GETIFADDRS */
165 #include <arpa/inet.h>
169 #if !defined(WIN32) || defined(__CYGWIN__)
173 #define X_INCLUDE_NETDB_H
174 #include <X11/Xos_r.h>
177 #include "os/client_priv.h"
179 #include "dixstruct.h"
185 Bool defeatAccessControl
= FALSE
;
187 #define addrEqual(fam, address, length, host) \
188 ((fam) == (host)->family &&\
189 (length) == (host)->len &&\
190 !memcmp (address, (host)->addr, length))
192 static int ConvertAddr(struct sockaddr
* /*saddr */ ,
196 static int CheckAddr(int /*family */ ,
197 const void * /*pAddr */ ,
198 unsigned /*length */ );
200 static Bool
NewHost(int /*family */ ,
201 const void * /*addr */ ,
203 int /* addingLocalHosts */ );
205 /* XFree86 bug #156: To keep track of which hosts were explicitly requested in
206 /etc/X<display>.hosts, we've added a requested field to the HOST struct,
207 and a LocalHostRequested variable. These default to FALSE, but are set
208 to TRUE in ResetHosts when reading in /etc/X<display>.hosts. They are
209 checked in DisableLocalHost(), which is called to disable the default
210 local host entries when stronger authentication is turned on. */
212 typedef struct _host
{
220 #define MakeHost(h,l) (h)=malloc(sizeof *(h)+(l));\
222 (h)->addr=(unsigned char *) ((h) + 1);\
223 (h)->requested = FALSE; \
225 #define FreeHost(h) free(h)
226 static HOST
*selfhosts
= NULL
;
227 static HOST
*validhosts
= NULL
;
228 static int AccessEnabled
= TRUE
;
229 static int LocalHostEnabled
= FALSE
;
230 static int LocalHostRequested
= FALSE
;
231 static int UsingXdmcp
= FALSE
;
234 LOCAL_ACCESS_SCOPE_HOST
= 0,
235 #ifndef NO_LOCAL_CLIENT_CRED
236 LOCAL_ACCESS_SCOPE_USER
,
240 /* FamilyServerInterpreted implementation */
241 static Bool
siAddrMatch(int family
, void *addr
, int len
, HOST
* host
,
243 static int siCheckAddr(const char *addrString
, int length
);
244 static void siTypesInitialize(void);
246 static void EnableLocalHost(void);
247 static void DisableLocalHost(void);
249 #ifndef NO_LOCAL_CLIENT_CRED
250 static void EnableLocalUser(void);
251 static void DisableLocalUser(void);
255 * called when authorization is not enabled to add the
256 * local host to the access list
260 EnableLocalAccess(void)
262 switch (LocalAccessScope
) {
263 case LOCAL_ACCESS_SCOPE_HOST
:
266 #ifndef NO_LOCAL_CLIENT_CRED
267 case LOCAL_ACCESS_SCOPE_USER
:
274 static void EnableLocalHost(void)
277 LocalHostEnabled
= TRUE
;
283 * called when authorization is enabled to keep us secure
286 DisableLocalAccess(void)
288 switch (LocalAccessScope
) {
289 case LOCAL_ACCESS_SCOPE_HOST
:
292 #ifndef NO_LOCAL_CLIENT_CRED
293 case LOCAL_ACCESS_SCOPE_USER
:
300 static void DisableLocalHost(void)
304 if (!LocalHostRequested
) /* Fix for XFree86 bug #156 */
305 LocalHostEnabled
= FALSE
;
306 for (self
= selfhosts
; self
; self
= self
->next
) {
307 if (!self
->requested
) /* Fix for XFree86 bug #156 */
308 (void) RemoveHost((ClientPtr
) NULL
, self
->family
, self
->len
,
309 (void *) self
->addr
);
313 #ifndef NO_LOCAL_CLIENT_CRED
314 static int GetLocalUserAddr(char **addr
)
316 static const char *type
= "localuser";
317 static const char delimiter
= '\0';
318 static const char *value
;
322 pw
= getpwuid(getuid());
324 if (pw
== NULL
|| pw
->pw_name
== NULL
)
329 length
= asprintf(addr
, "%s%c%s", type
, delimiter
, value
);
342 static void EnableLocalUser(void)
347 length
= GetLocalUserAddr(&addr
);
352 NewHost(FamilyServerInterpreted
, addr
, length
, TRUE
);
357 static void DisableLocalUser(void)
362 length
= GetLocalUserAddr(&addr
);
367 RemoveHost(NULL
, FamilyServerInterpreted
, length
, addr
);
373 LocalAccessScopeUser(void)
375 LocalAccessScope
= LOCAL_ACCESS_SCOPE_USER
;
380 * called at init time when XDMCP will be used; xdmcp always
381 * adds local hosts manually when needed
385 AccessUsingXdmcp(void)
388 LocalHostEnabled
= FALSE
;
394 * Define this host for access control. Find all the hosts the OS knows about
395 * for this fd and add them to the selfhosts list.
398 #if !defined(SIOCGIFCONF)
402 #if !defined(TCPCONN) && !defined(UNIXCONN)
410 register struct hostent
*hp
;
414 struct sockaddr_in in
;
416 struct sockaddr_in6 in6
;
420 struct sockaddr_in
*inetaddr
;
422 struct sockaddr_in6
*inet6addr
;
424 struct sockaddr_in broad_addr
;
426 #ifdef XTHREADS_NEEDS_BYNAMEPARAMS
427 _Xgethostbynameparams hparams
;
430 /* Why not use gethostname()? Well, at least on my system, I've had to
431 * make an ugly kernel patch to get a name longer than 8 characters, and
432 * uname() lets me access to the whole string (it smashes release, you
433 * see), whereas gethostname() kindly truncates it for me.
437 hp
= _XGethostbyname(name
.nodename
, hparams
);
439 saddr
.sa
.sa_family
= hp
->h_addrtype
;
440 switch (hp
->h_addrtype
) {
442 inetaddr
= (struct sockaddr_in
*) (&(saddr
.sa
));
443 memcpy(&(inetaddr
->sin_addr
), hp
->h_addr
, hp
->h_length
);
444 len
= sizeof(saddr
.sa
);
448 inet6addr
= (struct sockaddr_in6
*) (&(saddr
.sa
));
449 memcpy(&(inet6addr
->sin6_addr
), hp
->h_addr
, hp
->h_length
);
450 len
= sizeof(saddr
.in6
);
454 goto DefineLocalHost
;
456 family
= ConvertAddr(&(saddr
.sa
), &len
, (void **) &addr
);
457 if (family
!= -1 && family
!= FamilyLocal
) {
458 for (host
= selfhosts
;
459 host
&& !addrEqual(family
, addr
, len
, host
);
462 /* add this host to the host list. */
465 host
->family
= family
;
467 memcpy(host
->addr
, addr
, len
);
468 host
->next
= selfhosts
;
473 * If this is an Internet Address, but not the localhost
474 * address (127.0.0.1), nor the bogus address (0.0.0.0),
477 if (family
== FamilyInternet
&&
480 (addr
[0] == 0 && addr
[1] == 0 &&
481 addr
[2] == 0 && addr
[3] == 0)))
483 XdmcpRegisterConnection(family
, (char *) addr
, len
);
484 broad_addr
= *inetaddr
;
485 ((struct sockaddr_in
*) &broad_addr
)->sin_addr
.s_addr
=
486 htonl(INADDR_BROADCAST
);
487 XdmcpRegisterBroadcastAddress((struct sockaddr_in
*)
491 else if (family
== FamilyInternet6
&&
492 !(IN6_IS_ADDR_LOOPBACK((struct in6_addr
*) addr
))) {
493 XdmcpRegisterConnection(family
, (char *) addr
, len
);
502 * now add a host of family FamilyLocalHost...
505 for (host
= selfhosts
;
506 host
&& !addrEqual(FamilyLocalHost
, "", 0, host
); host
= host
->next
);
510 host
->family
= FamilyLocalHost
;
512 /* Nothing to store in host->addr */
513 host
->next
= selfhosts
;
517 #endif /* !TCPCONN && !UNIXCONN */
522 #ifdef USE_SIOCGLIFCONF
523 #define ifr_type struct lifreq
525 #define ifr_type struct ifreq
528 #ifdef VARIABLE_IFREQ
529 #define ifr_size(p) (sizeof (struct ifreq) + \
530 (p->ifr_addr.sa_len > sizeof (p->ifr_addr) ? \
531 p->ifr_addr.sa_len - sizeof (p->ifr_addr) : 0))
532 #define ifraddr_size(a) (a.sa_len)
534 #define ifr_size(p) (sizeof (ifr_type))
535 #define ifraddr_size(a) (sizeof (a))
540 in6_fillscopeid(struct sockaddr_in6
*sin6
)
542 #if defined(__KAME__)
543 if (IN6_IS_ADDR_LINKLOCAL(&sin6
->sin6_addr
) && sin6
->sin6_scope_id
== 0) {
544 sin6
->sin6_scope_id
=
545 ntohs(*(u_int16_t
*) &sin6
->sin6_addr
.s6_addr
[2]);
546 sin6
->sin6_addr
.s6_addr
[2] = sin6
->sin6_addr
.s6_addr
[3] = 0;
555 #ifndef HAVE_GETIFADDRS
558 #ifdef USE_SIOCGLIFCONF
559 struct sockaddr_storage buf
[16];
561 register struct lifreq
*ifr
;
566 #else /* !USE_SIOCGLIFCONF */
569 register struct ifreq
*ifr
;
572 #else /* HAVE_GETIFADDRS */
573 struct ifaddrs
*ifap
, *ifr
;
580 #ifndef HAVE_GETIFADDRS
584 #ifdef USE_SIOCGLIFCONF
587 ifn
.lifn_family
= AF_UNSPEC
;
589 if (ioctl(fd
, SIOCGLIFNUM
, (char *) &ifn
) < 0)
590 ErrorF("Getting interface count: %s\n", strerror(errno
));
591 if (len
< (ifn
.lifn_count
* sizeof(struct lifreq
))) {
592 len
= ifn
.lifn_count
* sizeof(struct lifreq
);
593 bufptr
= malloc(len
);
597 ifc
.lifc_family
= AF_UNSPEC
;
600 ifc
.lifc_buf
= bufptr
;
602 #define IFC_IOCTL_REQ SIOCGLIFCONF
603 #define IFC_IFC_REQ ifc.lifc_req
604 #define IFC_IFC_LEN ifc.lifc_len
605 #define IFR_IFR_ADDR ifr->lifr_addr
606 #define IFR_IFR_NAME ifr->lifr_name
608 #else /* Use SIOCGIFCONF */
610 ifc
.ifc_buf
= bufptr
;
612 #define IFC_IOCTL_REQ SIOCGIFCONF
613 #define IFC_IFC_REQ ifc.ifc_req
614 #define IFC_IFC_LEN ifc.ifc_len
615 #define IFR_IFR_ADDR ifr->ifr_addr
616 #define IFR_IFR_NAME ifr->ifr_name
619 if (ioctl(fd
, IFC_IOCTL_REQ
, (void *) &ifc
) < 0)
620 ErrorF("Getting interface configuration (4): %s\n", strerror(errno
));
622 cplim
= (char *) IFC_IFC_REQ
+ IFC_IFC_LEN
;
624 for (cp
= (char *) IFC_IFC_REQ
; cp
< cplim
; cp
+= ifr_size(ifr
)) {
625 ifr
= (ifr_type
*) cp
;
626 len
= ifraddr_size(IFR_IFR_ADDR
);
627 family
= ConvertAddr((struct sockaddr
*) &IFR_IFR_ADDR
,
628 &len
, (void **) &addr
);
629 if (family
== -1 || family
== FamilyLocal
)
632 if (family
== FamilyInternet6
)
633 in6_fillscopeid((struct sockaddr_in6
*) &IFR_IFR_ADDR
);
635 for (host
= selfhosts
;
636 host
&& !addrEqual(family
, addr
, len
, host
); host
= host
->next
);
641 host
->family
= family
;
643 memcpy(host
->addr
, addr
, len
);
644 host
->next
= selfhosts
;
649 #ifdef USE_SIOCGLIFCONF
650 struct sockaddr_storage broad_addr
;
652 struct sockaddr broad_addr
;
656 * If this isn't an Internet Address, don't register it.
658 if (family
!= FamilyInternet
660 && family
!= FamilyInternet6
666 * ignore 'localhost' entries as they're not useful
667 * on the other end of the wire
669 if (family
== FamilyInternet
&&
670 addr
[0] == 127 && addr
[1] == 0 && addr
[2] == 0 && addr
[3] == 1)
673 else if (family
== FamilyInternet6
&&
674 IN6_IS_ADDR_LOOPBACK((struct in6_addr
*) addr
))
679 * Ignore '0.0.0.0' entries as they are
680 * returned by some OSes for unconfigured NICs but they are
681 * not useful on the other end of the wire.
684 addr
[0] == 0 && addr
[1] == 0 && addr
[2] == 0 && addr
[3] == 0)
687 XdmcpRegisterConnection(family
, (char *) addr
, len
);
690 /* IPv6 doesn't support broadcasting, so we drop out here */
691 if (family
== FamilyInternet6
)
695 broad_addr
= IFR_IFR_ADDR
;
697 ((struct sockaddr_in
*) &broad_addr
)->sin_addr
.s_addr
=
698 htonl(INADDR_BROADCAST
);
699 #if defined(USE_SIOCGLIFCONF) && defined(SIOCGLIFBRDADDR)
701 struct lifreq broad_req
;
704 if (ioctl(fd
, SIOCGLIFFLAGS
, (char *) &broad_req
) != -1 &&
705 (broad_req
.lifr_flags
& IFF_BROADCAST
) &&
706 (broad_req
.lifr_flags
& IFF_UP
)
709 if (ioctl(fd
, SIOCGLIFBRDADDR
, &broad_req
) != -1)
710 broad_addr
= broad_req
.lifr_broadaddr
;
718 #elif defined(SIOCGIFBRDADDR)
720 struct ifreq broad_req
;
723 if (ioctl(fd
, SIOCGIFFLAGS
, (void *) &broad_req
) != -1 &&
724 (broad_req
.ifr_flags
& IFF_BROADCAST
) &&
725 (broad_req
.ifr_flags
& IFF_UP
)
728 if (ioctl(fd
, SIOCGIFBRDADDR
, (void *) &broad_req
) != -1)
729 broad_addr
= broad_req
.ifr_addr
;
736 #endif /* SIOCGIFBRDADDR */
737 XdmcpRegisterBroadcastAddress((struct sockaddr_in
*) &broad_addr
);
743 #else /* HAVE_GETIFADDRS */
744 if (getifaddrs(&ifap
) < 0) {
745 ErrorF("Warning: getifaddrs returns %s\n", strerror(errno
));
748 for (ifr
= ifap
; ifr
!= NULL
; ifr
= ifr
->ifa_next
) {
751 len
= sizeof(*(ifr
->ifa_addr
));
752 family
= ConvertAddr((struct sockaddr
*) ifr
->ifa_addr
, &len
,
754 if (family
== -1 || family
== FamilyLocal
)
757 if (family
== FamilyInternet6
)
758 in6_fillscopeid((struct sockaddr_in6
*) ifr
->ifa_addr
);
761 for (host
= selfhosts
;
762 host
!= NULL
&& !addrEqual(family
, addr
, len
, host
);
768 host
->family
= family
;
770 memcpy(host
->addr
, addr
, len
);
771 host
->next
= selfhosts
;
777 * If this isn't an Internet Address, don't register it.
779 if (family
!= FamilyInternet
781 && family
!= FamilyInternet6
787 * ignore 'localhost' entries as they're not useful
788 * on the other end of the wire
790 if (ifr
->ifa_flags
& IFF_LOOPBACK
)
793 if (family
== FamilyInternet
&&
794 addr
[0] == 127 && addr
[1] == 0 && addr
[2] == 0 && addr
[3] == 1)
798 * Ignore '0.0.0.0' entries as they are
799 * returned by some OSes for unconfigured NICs but they are
800 * not useful on the other end of the wire.
803 addr
[0] == 0 && addr
[1] == 0 && addr
[2] == 0 && addr
[3] == 0)
806 else if (family
== FamilyInternet6
&&
807 IN6_IS_ADDR_LOOPBACK((struct in6_addr
*) addr
))
810 XdmcpRegisterConnection(family
, (char *) addr
, len
);
812 if (family
== FamilyInternet6
)
813 /* IPv6 doesn't support broadcasting, so we drop out here */
816 if ((ifr
->ifa_flags
& IFF_BROADCAST
) &&
817 (ifr
->ifa_flags
& IFF_UP
) && ifr
->ifa_broadaddr
)
818 XdmcpRegisterBroadcastAddress((struct sockaddr_in
*) ifr
->
827 #endif /* HAVE_GETIFADDRS */
830 * add something of FamilyLocalHost
832 for (host
= selfhosts
;
833 host
&& !addrEqual(FamilyLocalHost
, "", 0, host
); host
= host
->next
);
837 host
->family
= FamilyLocalHost
;
839 /* Nothing to store in host->addr */
840 host
->next
= selfhosts
;
845 #endif /* hpux && !HAVE_IFREQ */
849 AugmentSelf(void *from
, int len
)
855 family
= ConvertAddr(from
, &len
, (void **) &addr
);
856 if (family
== -1 || family
== FamilyLocal
)
858 for (host
= selfhosts
; host
; host
= host
->next
) {
859 if (addrEqual(family
, addr
, len
, host
))
865 host
->family
= family
;
867 memcpy(host
->addr
, addr
, len
);
868 host
->next
= selfhosts
;
878 for (self
= selfhosts
; self
; self
= self
->next
)
879 /* Fix for XFree86 bug #156: pass addingLocal = TRUE to
880 * NewHost to tell that we are adding the default local
881 * host entries and not to flag the entries as being
882 * explicitly requested */
883 (void) NewHost(self
->family
, self
->addr
, self
->len
, TRUE
);
886 /* Reset access control list to initial hosts */
888 ResetHosts(const char *display
)
891 char lhostname
[120], ohostname
[120];
892 char *hostname
= ohostname
;
893 char fname
[PATH_MAX
+ 1];
899 #if defined(TCPCONN) && (!defined(IPv6))
902 struct sockaddr_in in
;
910 AccessEnabled
= !defeatAccessControl
;
911 LocalHostEnabled
= FALSE
;
912 while ((host
= validhosts
) != 0) {
913 validhosts
= host
->next
;
917 #if defined WIN32 && defined __MINGW32__
918 #define ETC_HOST_PREFIX "X"
920 #define ETC_HOST_PREFIX "/etc/X"
922 #define ETC_HOST_SUFFIX ".hosts"
923 fnamelen
= strlen(ETC_HOST_PREFIX
) + strlen(ETC_HOST_SUFFIX
) +
925 if (fnamelen
> sizeof(fname
))
926 FatalError("Display name `%s' is too long\n", display
);
927 snprintf(fname
, sizeof(fname
), ETC_HOST_PREFIX
"%s" ETC_HOST_SUFFIX
,
930 if ((fd
= fopen(fname
, "r")) != 0) {
931 while (fgets(ohostname
, sizeof(ohostname
), fd
)) {
933 if (*ohostname
== '#')
935 if ((ptr
= strchr(ohostname
, '\n')) != 0)
937 hostlen
= strlen(ohostname
) + 1;
938 for (i
= 0; i
< hostlen
; i
++)
939 lhostname
[i
] = tolower((unsigned char)ohostname
[i
]);
940 hostname
= ohostname
;
941 if (!strncmp("local:", lhostname
, 6)) {
942 family
= FamilyLocalHost
;
943 NewHost(family
, "", 0, FALSE
);
944 LocalHostRequested
= TRUE
; /* Fix for XFree86 bug #156 */
947 else if (!strncmp("inet:", lhostname
, 5)) {
948 family
= FamilyInternet
;
949 hostname
= ohostname
+ 5;
952 else if (!strncmp("inet6:", lhostname
, 6)) {
953 family
= FamilyInternet6
;
954 hostname
= ohostname
+ 6;
958 else if (!strncmp("si:", lhostname
, 3)) {
959 family
= FamilyServerInterpreted
;
960 hostname
= ohostname
+ 3;
964 if (family
== FamilyServerInterpreted
) {
965 len
= siCheckAddr(hostname
, hostlen
);
967 NewHost(family
, hostname
, len
, FALSE
);
973 #if defined(HAVE_GETADDRINFO)
974 if ((family
== FamilyInternet
) ||
976 (family
== FamilyInternet6
) ||
978 (family
== FamilyWild
)) {
979 struct addrinfo
*addresses
;
983 if (getaddrinfo(hostname
, NULL
, NULL
, &addresses
) == 0) {
984 for (a
= addresses
; a
!= NULL
; a
= a
->ai_next
) {
986 f
= ConvertAddr(a
->ai_addr
, &len
,
988 if (addr
&& ((family
== f
) ||
989 ((family
== FamilyWild
) && (f
!= -1)))) {
990 NewHost(f
, addr
, len
, FALSE
);
993 freeaddrinfo(addresses
);
996 #else /* HAVE_GETADDRINFO */
997 #ifdef XTHREADS_NEEDS_BYNAMEPARAMS
998 _Xgethostbynameparams hparams
;
1000 register struct hostent
*hp
;
1003 if ((family
== FamilyInternet
&&
1004 ((hp
= _XGethostbyname(hostname
, hparams
)) != 0)) ||
1005 ((hp
= _XGethostbyname(hostname
, hparams
)) != 0)) {
1006 saddr
.sa
.sa_family
= hp
->h_addrtype
;
1007 len
= sizeof(saddr
.sa
);
1009 ConvertAddr(&saddr
.sa
, &len
,
1010 (void **) &addr
)) != -1) {
1011 #ifdef h_addr /* new 4.3bsd version of gethostent */
1014 /* iterate over the addresses */
1015 for (list
= hp
->h_addr_list
; *list
; list
++)
1016 (void) NewHost(family
, (void *) *list
, len
, FALSE
);
1018 (void) NewHost(family
, (void *) hp
->h_addr
, len
,
1023 #endif /* HAVE_GETADDRINFO */
1025 #endif /* TCPCONN */
1026 family
= FamilyWild
;
1033 xtransLocalClient(ClientPtr client
)
1035 int alen
, family
, notused
;
1036 Xtransaddr
*from
= NULL
;
1038 register HOST
*host
;
1039 OsCommPtr oc
= (OsCommPtr
) client
->osPrivate
;
1041 if (!oc
->trans_conn
)
1044 if (!_XSERVTransGetPeerAddr(oc
->trans_conn
, ¬used
, &alen
, &from
)) {
1045 family
= ConvertAddr((struct sockaddr
*) from
,
1046 &alen
, (void **) &addr
);
1051 if (family
== FamilyLocal
) {
1055 for (host
= selfhosts
; host
; host
= host
->next
) {
1056 if (addrEqual(family
, addr
, alen
, host
)) {
1066 /* Is client on the local host */
1068 ComputeLocalClient(ClientPtr client
)
1070 const char *cmdname
= GetClientCmdName(client
);
1072 if (!xtransLocalClient(client
))
1075 /* If the executable name is "ssh", assume that this client connection
1076 * is forwarded from another host via SSH
1079 char *cmd
= strdup(cmdname
);
1082 /* Cut off any colon and whatever comes after it, see
1083 * https://lists.freedesktop.org/archives/xorg-devel/2015-December/048164.html
1085 char *tok
= strtok(cmd
, ":");
1087 #if !defined(WIN32) || defined(__CYGWIN__)
1088 ret
= strcmp(basename(tok
), "ssh") != 0;
1090 ret
= strcmp(tok
, "ssh") != 0;
1102 * Return the uid and all gids of a connected local client
1103 * Allocates a LocalClientCredRec - caller must call FreeLocalClientCreds
1105 * Used by localuser & localgroup ServerInterpreted access control forms below
1106 * Used by AuthAudit to log who local connections came from
1109 GetLocalClientCreds(ClientPtr client
, LocalClientCredRec
** lccp
)
1111 #if defined(HAVE_GETPEEREID) || defined(HAVE_GETPEERUCRED) || defined(SO_PEERCRED) || defined(LOCAL_PEERCRED)
1114 LocalClientCredRec
*lcc
;
1116 #if defined(HAVE_GETPEERUCRED)
1117 ucred_t
*peercred
= NULL
;
1119 #elif defined(SO_PEERCRED)
1121 struct ucred peercred
;
1123 struct sockpeercred peercred
;
1125 socklen_t so_len
= sizeof(peercred
);
1126 #elif defined(LOCAL_PEERCRED) && defined(HAVE_XUCRED_CR_PID)
1127 struct xucred peercred
;
1128 socklen_t so_len
= sizeof(peercred
);
1129 #elif defined(HAVE_GETPEEREID)
1132 #if defined(LOCAL_PEERPID)
1134 socklen_t so_len
= sizeof(pid
);
1140 ci
= ((OsCommPtr
) client
->osPrivate
)->trans_conn
;
1141 #if !(defined(__sun) && defined(HAVE_GETPEERUCRED))
1142 /* Most implementations can only determine peer credentials for Unix
1143 * domain sockets - Solaris getpeerucred can work with a bit more, so
1144 * we just let it tell us if the connection type is supported or not
1146 if (!_XSERVTransIsLocal(ci
)) {
1151 *lccp
= calloc(1, sizeof(LocalClientCredRec
));
1156 fd
= _XSERVTransGetConnectionNumber(ci
);
1157 #if defined(HAVE_GETPEERUCRED)
1158 if (getpeerucred(fd
, &peercred
) < 0) {
1159 FreeLocalClientCreds(lcc
);
1162 lcc
->euid
= ucred_geteuid(peercred
);
1163 if (lcc
->euid
!= -1)
1164 lcc
->fieldsSet
|= LCC_UID_SET
;
1165 lcc
->egid
= ucred_getegid(peercred
);
1166 if (lcc
->egid
!= -1)
1167 lcc
->fieldsSet
|= LCC_GID_SET
;
1168 lcc
->pid
= ucred_getpid(peercred
);
1170 lcc
->fieldsSet
|= LCC_PID_SET
;
1171 #ifdef HAVE_GETZONEID
1172 lcc
->zoneid
= ucred_getzoneid(peercred
);
1173 if (lcc
->zoneid
!= -1)
1174 lcc
->fieldsSet
|= LCC_ZID_SET
;
1176 lcc
->nSuppGids
= ucred_getgroups(peercred
, &gids
);
1177 if (lcc
->nSuppGids
> 0) {
1178 lcc
->pSuppGids
= calloc(lcc
->nSuppGids
, sizeof(int));
1179 if (lcc
->pSuppGids
== NULL
) {
1185 for (i
= 0; i
< lcc
->nSuppGids
; i
++) {
1186 (lcc
->pSuppGids
)[i
] = (int) gids
[i
];
1193 ucred_free(peercred
);
1195 #elif defined(SO_PEERCRED)
1196 if (getsockopt(fd
, SOL_SOCKET
, SO_PEERCRED
, &peercred
, &so_len
) == -1) {
1197 FreeLocalClientCreds(lcc
);
1200 lcc
->euid
= peercred
.uid
;
1201 lcc
->egid
= peercred
.gid
;
1202 lcc
->pid
= peercred
.pid
;
1203 lcc
->fieldsSet
= LCC_UID_SET
| LCC_GID_SET
| LCC_PID_SET
;
1205 #elif defined(LOCAL_PEERCRED) && defined(HAVE_XUCRED_CR_PID)
1206 if (getsockopt(fd
, SOL_LOCAL
, LOCAL_PEERCRED
, &peercred
, &so_len
) != 0 ||
1207 peercred
.cr_version
!= XUCRED_VERSION
) {
1208 FreeLocalClientCreds(lcc
);
1211 lcc
->euid
= peercred
.cr_uid
;
1212 lcc
->egid
= peercred
.cr_gid
;
1213 lcc
->pid
= peercred
.cr_pid
;
1214 lcc
->fieldsSet
= LCC_UID_SET
| LCC_GID_SET
| LCC_PID_SET
;
1216 #elif defined(HAVE_GETPEEREID)
1217 if (getpeereid(fd
, &uid
, &gid
) == -1) {
1218 FreeLocalClientCreds(lcc
);
1223 lcc
->fieldsSet
= LCC_UID_SET
| LCC_GID_SET
;
1225 #if defined(LOCAL_PEERPID)
1226 if (getsockopt(fd
, SOL_LOCAL
, LOCAL_PEERPID
, &pid
, &so_len
) != 0) {
1227 ErrorF("getsockopt failed to determine pid of socket %d: %s\n", fd
, strerror(errno
));
1230 lcc
->fieldsSet
|= LCC_PID_SET
;
1237 /* No system call available to get the credentials of the peer */
1243 FreeLocalClientCreds(LocalClientCredRec
* lcc
)
1246 if (lcc
->nSuppGids
> 0) {
1247 free(lcc
->pSuppGids
);
1254 AuthorizedClient(ClientPtr client
)
1258 if (!client
|| defeatAccessControl
)
1261 /* untrusted clients can't change host access */
1262 rc
= XaceHookServerAccess(client
, DixManageAccess
);
1266 return client
->local
? Success
: BadAccess
;
1269 /* Add a host to the access control list. This is the external interface
1270 * called from the dispatcher */
1273 AddHost(ClientPtr client
, int family
, unsigned length
, /* of bytes in pAddr */
1278 rc
= AuthorizedClient(client
);
1282 case FamilyLocalHost
:
1284 LocalHostEnabled
= TRUE
;
1286 case FamilyInternet
:
1288 case FamilyInternet6
:
1292 case FamilyServerInterpreted
:
1293 if ((len
= CheckAddr(family
, pAddr
, length
)) < 0) {
1294 client
->errorValue
= length
;
1300 client
->errorValue
= family
;
1303 if (NewHost(family
, pAddr
, len
, FALSE
))
1309 ForEachHostInFamily(int family
, Bool (*func
) (unsigned char *addr
,
1316 for (host
= validhosts
; host
; host
= host
->next
)
1317 if (family
== host
->family
&& func(host
->addr
, host
->len
, closure
))
1322 /* Add a host to the access control list. This is the internal interface
1323 * called when starting or resetting the server */
1325 NewHost(int family
, const void *addr
, int len
, int addingLocalHosts
)
1327 register HOST
*host
;
1329 for (host
= validhosts
; host
; host
= host
->next
) {
1330 if (addrEqual(family
, addr
, len
, host
))
1333 if (!addingLocalHosts
) { /* Fix for XFree86 bug #156 */
1334 for (host
= selfhosts
; host
; host
= host
->next
) {
1335 if (addrEqual(family
, addr
, len
, host
)) {
1336 host
->requested
= TRUE
;
1344 host
->family
= family
;
1346 memcpy(host
->addr
, addr
, len
);
1347 host
->next
= validhosts
;
1352 /* Remove a host from the access control list */
1355 RemoveHost(ClientPtr client
, int family
, unsigned length
, /* of bytes in pAddr */
1359 register HOST
*host
, **prev
;
1361 rc
= AuthorizedClient(client
);
1365 case FamilyLocalHost
:
1367 LocalHostEnabled
= FALSE
;
1369 case FamilyInternet
:
1371 case FamilyInternet6
:
1375 case FamilyServerInterpreted
:
1376 if ((len
= CheckAddr(family
, pAddr
, length
)) < 0) {
1378 client
->errorValue
= length
;
1385 client
->errorValue
= family
;
1388 for (prev
= &validhosts
;
1389 (host
= *prev
) && (!addrEqual(family
, pAddr
, len
, host
));
1390 prev
= &host
->next
);
1398 /* Get all hosts in the access control list */
1400 GetHosts(void **data
, int *pnHosts
, int *pLen
, BOOL
* pEnabled
)
1404 register unsigned char *ptr
;
1405 register HOST
*host
;
1408 *pEnabled
= AccessEnabled
? EnableAccess
: DisableAccess
;
1409 for (host
= validhosts
; host
; host
= host
->next
) {
1411 n
+= pad_to_int32(host
->len
) + sizeof(xHostEntry
);
1412 /* Could check for INT_MAX, but in reality having more than 1mb of
1413 hostnames in the access list is ridiculous */
1418 *data
= ptr
= malloc(n
);
1422 for (host
= validhosts
; host
; host
= host
->next
) {
1424 if ((ptr
+ sizeof(xHostEntry
) + len
) > ((unsigned char *) *data
+ n
))
1426 ((xHostEntry
*) ptr
)->family
= host
->family
;
1427 ((xHostEntry
*) ptr
)->length
= len
;
1428 ptr
+= sizeof(xHostEntry
);
1429 memcpy(ptr
, host
->addr
, len
);
1430 ptr
+= pad_to_int32(len
);
1441 /* Check for valid address family and length, and return address length. */
1443 /*ARGSUSED*/ static int
1444 CheckAddr(int family
, const void *pAddr
, unsigned length
)
1449 #if defined(TCPCONN)
1450 case FamilyInternet
:
1451 if (length
== sizeof(struct in_addr
))
1457 case FamilyInternet6
:
1458 if (length
== sizeof(struct in6_addr
))
1465 case FamilyServerInterpreted
:
1466 len
= siCheckAddr(pAddr
, length
);
1474 /* Check if a host is not in the access control list.
1475 * Returns 1 if host is invalid, 0 if we've found it. */
1478 InvalidHost(register struct sockaddr
*saddr
, int len
, ClientPtr client
)
1482 register HOST
*selfhost
, *host
;
1484 if (!AccessEnabled
) /* just let them in */
1486 family
= ConvertAddr(saddr
, &len
, (void **) &addr
);
1489 if (family
== FamilyLocal
) {
1490 if (!LocalHostEnabled
) {
1492 * check to see if any local address is enabled. This
1493 * implicitly enables local connections.
1495 for (selfhost
= selfhosts
; selfhost
; selfhost
= selfhost
->next
) {
1496 for (host
= validhosts
; host
; host
= host
->next
) {
1497 if (addrEqual(selfhost
->family
, selfhost
->addr
,
1498 selfhost
->len
, host
))
1506 for (host
= validhosts
; host
; host
= host
->next
) {
1507 if (host
->family
== FamilyServerInterpreted
) {
1508 if (siAddrMatch(family
, addr
, len
, host
, client
)) {
1513 if (addr
&& addrEqual(family
, addr
, len
, host
))
1522 ConvertAddr(register struct sockaddr
*saddr
, int *len
, void **addr
)
1526 switch (saddr
->sa_family
) {
1528 #if defined(UNIXCONN) || defined(LOCALCONN)
1532 #if defined(TCPCONN)
1535 if (16777343 == *(long *) &((struct sockaddr_in
*) saddr
)->sin_addr
)
1538 *len
= sizeof(struct in_addr
);
1539 *addr
= (void *) &(((struct sockaddr_in
*) saddr
)->sin_addr
);
1540 return FamilyInternet
;
1544 struct sockaddr_in6
*saddr6
= (struct sockaddr_in6
*) saddr
;
1546 if (IN6_IS_ADDR_V4MAPPED(&(saddr6
->sin6_addr
))) {
1547 *len
= sizeof(struct in_addr
);
1548 *addr
= (void *) &(saddr6
->sin6_addr
.s6_addr
[12]);
1549 return FamilyInternet
;
1552 *len
= sizeof(struct in6_addr
);
1553 *addr
= (void *) &(saddr6
->sin6_addr
);
1554 return FamilyInternet6
;
1565 ChangeAccessControl(ClientPtr client
, int fEnabled
)
1567 int rc
= AuthorizedClient(client
);
1571 AccessEnabled
= fEnabled
;
1576 GetClientFd(ClientPtr client
)
1578 return ((OsCommPtr
) client
->osPrivate
)->fd
;
1582 ClientIsLocal(ClientPtr client
)
1584 XtransConnInfo ci
= ((OsCommPtr
) client
->osPrivate
)->trans_conn
;
1586 return _XSERVTransIsLocal(ci
);
1589 /*****************************************************************************
1590 * FamilyServerInterpreted host entry implementation
1592 * Supports an extensible system of host types which the server can interpret
1593 * See the IPv6 extensions to the X11 protocol spec for the definition.
1595 * Currently supported schemes:
1597 * hostname - hostname as defined in IETF RFC 2396
1598 * ipv6 - IPv6 literal address as defined in IETF RFC's 3513 and <TBD>
1600 * See xc/doc/specs/SIAddresses for formal definitions of each type.
1603 /* These definitions and the siTypeAdd function could be exported in the
1604 * future to enable loading additional host types, but that was not done for
1605 * the initial implementation.
1607 typedef Bool (*siAddrMatchFunc
) (int family
, void *addr
, int len
,
1608 const char *siAddr
, int siAddrlen
,
1609 ClientPtr client
, void *siTypePriv
);
1610 typedef int (*siCheckAddrFunc
) (const char *addrString
, int length
,
1614 struct siType
*next
;
1615 const char *typeName
;
1616 siAddrMatchFunc addrMatch
;
1617 siCheckAddrFunc checkAddr
;
1618 void *typePriv
; /* Private data for type routines */
1621 static struct siType
*siTypeList
;
1624 siTypeAdd(const char *typeName
, siAddrMatchFunc addrMatch
,
1625 siCheckAddrFunc checkAddr
, void *typePriv
)
1627 struct siType
*s
, *p
;
1629 if ((typeName
== NULL
) || (addrMatch
== NULL
) || (checkAddr
== NULL
))
1632 for (s
= siTypeList
, p
= NULL
; s
!= NULL
; p
= s
, s
= s
->next
) {
1633 if (strcmp(typeName
, s
->typeName
) == 0) {
1634 s
->addrMatch
= addrMatch
;
1635 s
->checkAddr
= checkAddr
;
1636 s
->typePriv
= typePriv
;
1641 s
= malloc(sizeof(struct siType
));
1651 s
->typeName
= typeName
;
1652 s
->addrMatch
= addrMatch
;
1653 s
->checkAddr
= checkAddr
;
1654 s
->typePriv
= typePriv
;
1658 /* Checks to see if a host matches a server-interpreted host entry */
1660 siAddrMatch(int family
, void *addr
, int len
, HOST
* host
, ClientPtr client
)
1662 Bool matches
= FALSE
;
1664 const char *valueString
;
1667 valueString
= (const char *) memchr(host
->addr
, '\0', host
->len
);
1668 if (valueString
!= NULL
) {
1669 for (s
= siTypeList
; s
!= NULL
; s
= s
->next
) {
1670 if (strcmp((char *) host
->addr
, s
->typeName
) == 0) {
1671 addrlen
= host
->len
- (strlen((char *) host
->addr
) + 1);
1672 matches
= s
->addrMatch(family
, addr
, len
,
1673 valueString
+ 1, addrlen
, client
,
1678 #ifdef FAMILY_SI_DEBUG
1679 ErrorF("Xserver: siAddrMatch(): type = %s, value = %*.*s -- %s\n",
1680 host
->addr
, addrlen
, addrlen
, valueString
+ 1,
1681 (matches
) ? "accepted" : "rejected");
1688 siCheckAddr(const char *addrString
, int length
)
1690 const char *valueString
;
1691 int addrlen
, typelen
;
1695 /* Make sure there is a \0 byte inside the specified length
1696 to separate the address type from the address value. */
1697 valueString
= (const char *) memchr(addrString
, '\0', length
);
1698 if (valueString
!= NULL
) {
1699 /* Make sure the first string is a recognized address type,
1700 * and the second string is a valid address of that type.
1702 typelen
= strlen(addrString
) + 1;
1703 addrlen
= length
- typelen
;
1705 for (s
= siTypeList
; s
!= NULL
; s
= s
->next
) {
1706 if (strcmp(addrString
, s
->typeName
) == 0) {
1707 len
= s
->checkAddr(valueString
+ 1, addrlen
, s
->typePriv
);
1714 #ifdef FAMILY_SI_DEBUG
1716 const char *resultMsg
;
1719 resultMsg
= "type not registered";
1723 resultMsg
= "rejected";
1725 resultMsg
= "accepted";
1729 ("Xserver: siCheckAddr(): type = %s, value = %*.*s, len = %d -- %s\n",
1730 addrString
, addrlen
, addrlen
, valueString
+ 1, len
, resultMsg
);
1738 * Hostname server-interpreted host type
1740 * Stored as hostname string, explicitly defined to be resolved ONLY
1741 * at access check time, to allow for hosts with dynamic addresses
1742 * but static hostnames, such as found in some DHCP & mobile setups.
1744 * Hostname must conform to IETF RFC 2396 sec. 3.2.2, which defines it as:
1745 * hostname = *( domainlabel "." ) toplabel [ "." ]
1746 * domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
1747 * toplabel = alpha | alpha *( alphanum | "-" ) alphanum
1751 #define SI_HOSTNAME_MAXLEN NI_MAXHOST
1753 #ifdef MAXHOSTNAMELEN
1754 #define SI_HOSTNAME_MAXLEN MAXHOSTNAMELEN
1756 #define SI_HOSTNAME_MAXLEN 256
1761 siHostnameAddrMatch(int family
, void *addr
, int len
,
1762 const char *siAddr
, int siAddrLen
, ClientPtr client
,
1767 /* Currently only supports checking against IPv4 & IPv6 connections, but
1768 * support for other address families, such as DECnet, could be added if
1771 #if defined(HAVE_GETADDRINFO)
1772 if ((family
== FamilyInternet
)
1774 || (family
== FamilyInternet6
)
1777 char hostname
[SI_HOSTNAME_MAXLEN
];
1778 struct addrinfo
*addresses
;
1781 void *hostaddr
= NULL
;
1783 if (siAddrLen
>= sizeof(hostname
))
1786 strlcpy(hostname
, siAddr
, siAddrLen
+ 1);
1788 if (getaddrinfo(hostname
, NULL
, NULL
, &addresses
) == 0) {
1789 for (a
= addresses
; a
!= NULL
; a
= a
->ai_next
) {
1790 hostaddrlen
= a
->ai_addrlen
;
1791 f
= ConvertAddr(a
->ai_addr
, &hostaddrlen
, &hostaddr
);
1792 if ((f
== family
) && (len
== hostaddrlen
) && hostaddr
&&
1793 (memcmp(addr
, hostaddr
, len
) == 0)) {
1798 freeaddrinfo(addresses
);
1801 #else /* getaddrinfo not supported, use gethostbyname instead for IPv4 */
1802 if (family
== FamilyInternet
) {
1803 register struct hostent
*hp
;
1805 #ifdef XTHREADS_NEEDS_BYNAMEPARAMS
1806 _Xgethostbynameparams hparams
;
1808 char hostname
[SI_HOSTNAME_MAXLEN
];
1813 if (siAddrLen
>= sizeof(hostname
))
1816 strlcpy(hostname
, siAddr
, siAddrLen
+ 1);
1818 if ((hp
= _XGethostbyname(hostname
, hparams
)) != NULL
) {
1819 #ifdef h_addr /* new 4.3bsd version of gethostent */
1820 /* iterate over the addresses */
1821 for (addrlist
= hp
->h_addr_list
; *addrlist
; addrlist
++)
1823 addrlist
= &hp
->h_addr
;
1826 struct sockaddr_in sin
;
1828 sin
.sin_family
= hp
->h_addrtype
;
1829 memcpy(&(sin
.sin_addr
), *addrlist
, hp
->h_length
);
1830 hostaddrlen
= sizeof(sin
);
1831 f
= ConvertAddr((struct sockaddr
*) &sin
,
1832 &hostaddrlen
, &hostaddr
);
1833 if ((f
== family
) && (len
== hostaddrlen
) &&
1834 (memcmp(addr
, hostaddr
, len
) == 0)) {
1848 siHostnameCheckAddr(const char *valueString
, int length
, void *typePriv
)
1850 /* Check conformance of hostname to RFC 2396 sec. 3.2.2 definition.
1851 * We do not use ctype functions here to avoid locale-specific
1852 * character sets. Hostnames must be pure ASCII.
1856 Bool dotAllowed
= FALSE
;
1857 Bool dashAllowed
= FALSE
;
1859 if ((length
<= 0) || (length
>= SI_HOSTNAME_MAXLEN
)) {
1863 for (i
= 0; i
< length
; i
++) {
1864 char c
= valueString
[i
];
1866 if (c
== 0x2E) { /* '.' */
1867 if (dotAllowed
== FALSE
) {
1873 dashAllowed
= FALSE
;
1876 else if (c
== 0x2D) { /* '-' */
1877 if (dashAllowed
== FALSE
) {
1885 else if (((c
>= 0x30) && (c
<= 0x3A)) /* 0-9 */ ||
1886 ((c
>= 0x61) && (c
<= 0x7A)) /* a-z */ ||
1887 ((c
>= 0x41) && (c
<= 0x5A)) /* A-Z */ ) {
1891 else { /* Invalid character */
1902 * "ipv6" server interpreted type
1904 * Currently supports only IPv6 literal address as specified in IETF RFC 3513
1906 * Once draft-ietf-ipv6-scoping-arch-00.txt becomes an RFC, support will be
1907 * added for the scoped address format it specifies.
1910 /* Maximum length of an IPv6 address string - increase when adding support
1911 * for scoped address qualifiers. Includes room for trailing NUL byte.
1913 #define SI_IPv6_MAXLEN INET6_ADDRSTRLEN
1916 siIPv6AddrMatch(int family
, void *addr
, int len
,
1917 const char *siAddr
, int siAddrlen
, ClientPtr client
,
1920 struct in6_addr addr6
;
1921 char addrbuf
[SI_IPv6_MAXLEN
];
1923 if ((family
!= FamilyInternet6
) || (len
!= sizeof(addr6
)))
1926 memcpy(addrbuf
, siAddr
, siAddrlen
);
1927 addrbuf
[siAddrlen
] = '\0';
1929 if (inet_pton(AF_INET6
, addrbuf
, &addr6
) != 1) {
1930 perror("inet_pton");
1934 if (memcmp(addr
, &addr6
, len
) == 0) {
1943 siIPv6CheckAddr(const char *addrString
, int length
, void *typePriv
)
1947 /* Minimum length is 3 (smallest legal address is "::1") */
1949 /* Address is too short! */
1952 else if (length
>= SI_IPv6_MAXLEN
) {
1953 /* Address is too long! */
1957 /* Assume inet_pton is sufficient validation */
1958 struct in6_addr addr6
;
1959 char addrbuf
[SI_IPv6_MAXLEN
];
1961 memcpy(addrbuf
, addrString
, length
);
1962 addrbuf
[length
] = '\0';
1964 if (inet_pton(AF_INET6
, addrbuf
, &addr6
) != 1) {
1965 perror("inet_pton");
1976 #if !defined(NO_LOCAL_CLIENT_CRED)
1978 * "localuser" & "localgroup" server interpreted types
1980 * Allows local connections from a given local user or group
1986 #define LOCAL_USER 1
1987 #define LOCAL_GROUP 2
1991 } siLocalCredPrivRec
, *siLocalCredPrivPtr
;
1993 static siLocalCredPrivRec siLocalUserPriv
= { LOCAL_USER
};
1994 static siLocalCredPrivRec siLocalGroupPriv
= { LOCAL_GROUP
};
1997 siLocalCredGetId(const char *addr
, int len
, siLocalCredPrivPtr lcPriv
, int *id
)
1999 Bool parsedOK
= FALSE
;
2000 char *addrbuf
= malloc(len
+ 1);
2002 if (addrbuf
== NULL
) {
2006 memcpy(addrbuf
, addr
, len
);
2007 addrbuf
[len
] = '\0';
2009 if (addr
[0] == '#') { /* numeric id */
2013 *id
= strtol(addrbuf
+ 1, &cp
, 0);
2014 if ((errno
== 0) && (cp
!= (addrbuf
+ 1))) {
2018 else { /* non-numeric name */
2019 if (lcPriv
->credType
== LOCAL_USER
) {
2020 struct passwd
*pw
= getpwnam(addrbuf
);
2023 *id
= (int) pw
->pw_uid
;
2028 struct group
*gr
= getgrnam(addrbuf
);
2031 *id
= (int) gr
->gr_gid
;
2042 siLocalCredAddrMatch(int family
, void *addr
, int len
,
2043 const char *siAddr
, int siAddrlen
, ClientPtr client
,
2047 LocalClientCredRec
*lcc
;
2048 siLocalCredPrivPtr lcPriv
= (siLocalCredPrivPtr
) typePriv
;
2050 if (GetLocalClientCreds(client
, &lcc
) == -1) {
2054 #ifdef HAVE_GETZONEID /* Ensure process is in the same zone */
2055 if ((lcc
->fieldsSet
& LCC_ZID_SET
) && (lcc
->zoneid
!= getzoneid())) {
2056 FreeLocalClientCreds(lcc
);
2061 if (siLocalCredGetId(siAddr
, siAddrlen
, lcPriv
, &siAddrId
) == FALSE
) {
2062 FreeLocalClientCreds(lcc
);
2066 if (lcPriv
->credType
== LOCAL_USER
) {
2067 if ((lcc
->fieldsSet
& LCC_UID_SET
) && (lcc
->euid
== siAddrId
)) {
2068 FreeLocalClientCreds(lcc
);
2073 if ((lcc
->fieldsSet
& LCC_GID_SET
) && (lcc
->egid
== siAddrId
)) {
2074 FreeLocalClientCreds(lcc
);
2077 if (lcc
->pSuppGids
!= NULL
) {
2080 for (i
= 0; i
< lcc
->nSuppGids
; i
++) {
2081 if (lcc
->pSuppGids
[i
] == siAddrId
) {
2082 FreeLocalClientCreds(lcc
);
2088 FreeLocalClientCreds(lcc
);
2093 siLocalCredCheckAddr(const char *addrString
, int length
, void *typePriv
)
2098 if (siLocalCredGetId(addrString
, length
,
2099 (siLocalCredPrivPtr
) typePriv
, &id
) == FALSE
) {
2104 #endif /* localuser */
2107 siTypesInitialize(void)
2109 siTypeAdd("hostname", siHostnameAddrMatch
, siHostnameCheckAddr
, NULL
);
2111 siTypeAdd("ipv6", siIPv6AddrMatch
, siIPv6CheckAddr
, NULL
);
2113 #if !defined(NO_LOCAL_CLIENT_CRED)
2114 siTypeAdd("localuser", siLocalCredAddrMatch
, siLocalCredCheckAddr
,
2116 siTypeAdd("localgroup", siLocalCredAddrMatch
, siLocalCredCheckAddr
,