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