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