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