access.c revision 706f2543
1706f2543Smrg/*********************************************************** 2706f2543Smrg 3706f2543SmrgCopyright 1987, 1998 The Open Group 4706f2543Smrg 5706f2543SmrgAll rights reserved. 6706f2543Smrg 7706f2543SmrgPermission is hereby granted, free of charge, to any person obtaining a 8706f2543Smrgcopy of this software and associated documentation files (the 9706f2543Smrg"Software"), to deal in the Software without restriction, including 10706f2543Smrgwithout limitation the rights to use, copy, modify, merge, publish, 11706f2543Smrgdistribute, and/or sell copies of the Software, and to permit persons 12706f2543Smrgto whom the Software is furnished to do so, provided that the above 13706f2543Smrgcopyright notice(s) and this permission notice appear in all copies of 14706f2543Smrgthe Software and that both the above copyright notice(s) and this 15706f2543Smrgpermission notice appear in supporting documentation. 16706f2543Smrg 17706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18706f2543SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19706f2543SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 20706f2543SmrgOF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 21706f2543SmrgHOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL 22706f2543SmrgINDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING 23706f2543SmrgFROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 24706f2543SmrgNEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 25706f2543SmrgWITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 26706f2543Smrg 27706f2543SmrgExcept as contained in this notice, the name of a copyright holder 28706f2543Smrgshall not be used in advertising or otherwise to promote the sale, use 29706f2543Smrgor other dealings in this Software without prior written authorization 30706f2543Smrgof the copyright holder. 31706f2543Smrg 32706f2543SmrgX Window System is a trademark of The Open Group. 33706f2543Smrg 34706f2543SmrgCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. 35706f2543Smrg 36706f2543Smrg All Rights Reserved 37706f2543Smrg 38706f2543SmrgPermission to use, copy, modify, and distribute this software and its 39706f2543Smrgdocumentation for any purpose and without fee is hereby granted, 40706f2543Smrgprovided that the above copyright notice appear in all copies and that 41706f2543Smrgboth that copyright notice and this permission notice appear in 42706f2543Smrgsupporting documentation, and that the name of Digital not be 43706f2543Smrgused in advertising or publicity pertaining to distribution of the 44706f2543Smrgsoftware without specific, written prior permission. 45706f2543Smrg 46706f2543SmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 47706f2543SmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 48706f2543SmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 49706f2543SmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 50706f2543SmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 51706f2543SmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 52706f2543SmrgSOFTWARE. 53706f2543Smrg 54706f2543Smrg******************************************************************/ 55706f2543Smrg 56706f2543Smrg/* 57706f2543Smrg * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. 58706f2543Smrg * 59706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining a 60706f2543Smrg * copy of this software and associated documentation files (the "Software"), 61706f2543Smrg * to deal in the Software without restriction, including without limitation 62706f2543Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 63706f2543Smrg * and/or sell copies of the Software, and to permit persons to whom the 64706f2543Smrg * Software is furnished to do so, subject to the following conditions: 65706f2543Smrg * 66706f2543Smrg * The above copyright notice and this permission notice (including the next 67706f2543Smrg * paragraph) shall be included in all copies or substantial portions of the 68706f2543Smrg * Software. 69706f2543Smrg * 70706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 71706f2543Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 72706f2543Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 73706f2543Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 74706f2543Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 75706f2543Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 76706f2543Smrg * DEALINGS IN THE SOFTWARE. 77706f2543Smrg */ 78706f2543Smrg 79706f2543Smrg#ifdef HAVE_DIX_CONFIG_H 80706f2543Smrg#include <dix-config.h> 81706f2543Smrg#endif 82706f2543Smrg 83706f2543Smrg#ifdef WIN32 84706f2543Smrg#include <X11/Xwinsock.h> 85706f2543Smrg#endif 86706f2543Smrg 87706f2543Smrg#include <stdio.h> 88706f2543Smrg#include <stdlib.h> 89706f2543Smrg#define XSERV_t 90706f2543Smrg#define TRANS_SERVER 91706f2543Smrg#define TRANS_REOPEN 92706f2543Smrg#include <X11/Xtrans/Xtrans.h> 93706f2543Smrg#include <X11/Xauth.h> 94706f2543Smrg#include <X11/X.h> 95706f2543Smrg#include <X11/Xproto.h> 96706f2543Smrg#include "misc.h" 97706f2543Smrg#include "site.h" 98706f2543Smrg#include <errno.h> 99706f2543Smrg#include <sys/types.h> 100706f2543Smrg#ifndef WIN32 101706f2543Smrg#include <sys/socket.h> 102706f2543Smrg#include <sys/ioctl.h> 103706f2543Smrg#include <ctype.h> 104706f2543Smrg 105706f2543Smrg#if defined(TCPCONN) || defined(STREAMSCONN) 106706f2543Smrg#include <netinet/in.h> 107706f2543Smrg#endif /* TCPCONN || STREAMSCONN */ 108706f2543Smrg 109706f2543Smrg#ifdef HAS_GETPEERUCRED 110706f2543Smrg# include <ucred.h> 111706f2543Smrg# ifdef sun 112706f2543Smrg# include <zone.h> 113706f2543Smrg# endif 114706f2543Smrg#endif 115706f2543Smrg 116706f2543Smrg#if defined(SVR4) || (defined(SYSV) && defined(__i386__)) || defined(__GNU__) 117706f2543Smrg# include <sys/utsname.h> 118706f2543Smrg#endif 119706f2543Smrg#if defined(SYSV) && defined(__i386__) 120706f2543Smrg# include <sys/stream.h> 121706f2543Smrg#endif 122706f2543Smrg#ifdef __GNU__ 123706f2543Smrg#undef SIOCGIFCONF 124706f2543Smrg#include <netdb.h> 125706f2543Smrg#else /*!__GNU__*/ 126706f2543Smrg# include <net/if.h> 127706f2543Smrg#endif /*__GNU__ */ 128706f2543Smrg 129706f2543Smrg#ifdef SVR4 130706f2543Smrg#include <sys/sockio.h> 131706f2543Smrg#include <sys/stropts.h> 132706f2543Smrg#endif 133706f2543Smrg 134706f2543Smrg#include <netdb.h> 135706f2543Smrg 136706f2543Smrg#ifdef CSRG_BASED 137706f2543Smrg#include <sys/param.h> 138706f2543Smrg#if (BSD >= 199103) 139706f2543Smrg#define VARIABLE_IFREQ 140706f2543Smrg#endif 141706f2543Smrg#endif 142706f2543Smrg 143706f2543Smrg#ifdef BSD44SOCKETS 144706f2543Smrg#ifndef VARIABLE_IFREQ 145706f2543Smrg#define VARIABLE_IFREQ 146706f2543Smrg#endif 147706f2543Smrg#endif 148706f2543Smrg 149706f2543Smrg#ifdef HAS_GETIFADDRS 150706f2543Smrg#include <ifaddrs.h> 151706f2543Smrg#endif 152706f2543Smrg 153706f2543Smrg/* Solaris provides an extended interface SIOCGLIFCONF. Other systems 154706f2543Smrg * may have this as well, but the code has only been tested on Solaris 155706f2543Smrg * so far, so we only enable it there. Other platforms may be added as 156706f2543Smrg * needed. 157706f2543Smrg * 158706f2543Smrg * Test for Solaris commented out -- TSI @ UQV 2003.06.13 159706f2543Smrg */ 160706f2543Smrg#ifdef SIOCGLIFCONF 161706f2543Smrg/* #if defined(sun) */ 162706f2543Smrg#define USE_SIOCGLIFCONF 163706f2543Smrg/* #endif */ 164706f2543Smrg#endif 165706f2543Smrg 166706f2543Smrg#endif /* WIN32 */ 167706f2543Smrg 168706f2543Smrg#ifndef PATH_MAX 169706f2543Smrg#include <sys/param.h> 170706f2543Smrg#ifndef PATH_MAX 171706f2543Smrg#ifdef MAXPATHLEN 172706f2543Smrg#define PATH_MAX MAXPATHLEN 173706f2543Smrg#else 174706f2543Smrg#define PATH_MAX 1024 175706f2543Smrg#endif 176706f2543Smrg#endif 177706f2543Smrg#endif 178706f2543Smrg 179706f2543Smrg 180706f2543Smrg#define X_INCLUDE_NETDB_H 181706f2543Smrg#include <X11/Xos_r.h> 182706f2543Smrg 183706f2543Smrg#include "dixstruct.h" 184706f2543Smrg#include "osdep.h" 185706f2543Smrg 186706f2543Smrg#include "xace.h" 187706f2543Smrg 188706f2543Smrg#ifndef PATH_MAX 189706f2543Smrg#ifdef MAXPATHLEN 190706f2543Smrg#define PATH_MAX MAXPATHLEN 191706f2543Smrg#else 192706f2543Smrg#define PATH_MAX 1024 193706f2543Smrg#endif 194706f2543Smrg#endif 195706f2543Smrg 196706f2543SmrgBool defeatAccessControl = FALSE; 197706f2543Smrg 198706f2543Smrg#define acmp(a1, a2, len) memcmp((char *)(a1), (char *)(a2), len) 199706f2543Smrg#define acopy(a1, a2, len) memmove((char *)(a2), (char *)(a1), len) 200706f2543Smrg#define addrEqual(fam, address, length, host) \ 201706f2543Smrg ((fam) == (host)->family &&\ 202706f2543Smrg (length) == (host)->len &&\ 203706f2543Smrg !acmp (address, (host)->addr, length)) 204706f2543Smrg 205706f2543Smrgstatic int ConvertAddr(struct sockaddr * /*saddr*/, 206706f2543Smrg int * /*len*/, 207706f2543Smrg pointer * /*addr*/); 208706f2543Smrg 209706f2543Smrgstatic int CheckAddr(int /*family*/, 210706f2543Smrg const void * /*pAddr*/, 211706f2543Smrg unsigned /*length*/); 212706f2543Smrg 213706f2543Smrgstatic Bool NewHost(int /*family*/, 214706f2543Smrg const void * /*addr*/, 215706f2543Smrg int /*len*/, 216706f2543Smrg int /* addingLocalHosts */); 217706f2543Smrg 218706f2543Smrg/* XFree86 bug #156: To keep track of which hosts were explicitly requested in 219706f2543Smrg /etc/X<display>.hosts, we've added a requested field to the HOST struct, 220706f2543Smrg and a LocalHostRequested variable. These default to FALSE, but are set 221706f2543Smrg to TRUE in ResetHosts when reading in /etc/X<display>.hosts. They are 222706f2543Smrg checked in DisableLocalHost(), which is called to disable the default 223706f2543Smrg local host entries when stronger authentication is turned on. */ 224706f2543Smrg 225706f2543Smrgtypedef struct _host { 226706f2543Smrg short family; 227706f2543Smrg short len; 228706f2543Smrg unsigned char *addr; 229706f2543Smrg struct _host *next; 230706f2543Smrg int requested; 231706f2543Smrg} HOST; 232706f2543Smrg 233706f2543Smrg#define MakeHost(h,l) (h)=malloc(sizeof *(h)+(l));\ 234706f2543Smrg if (h) { \ 235706f2543Smrg (h)->addr=(unsigned char *) ((h) + 1);\ 236706f2543Smrg (h)->requested = FALSE; \ 237706f2543Smrg } 238706f2543Smrg#define FreeHost(h) free(h) 239706f2543Smrgstatic HOST *selfhosts = NULL; 240706f2543Smrgstatic HOST *validhosts = NULL; 241706f2543Smrgstatic int AccessEnabled = DEFAULT_ACCESS_CONTROL; 242706f2543Smrgstatic int LocalHostEnabled = FALSE; 243706f2543Smrgstatic int LocalHostRequested = FALSE; 244706f2543Smrgstatic int UsingXdmcp = FALSE; 245706f2543Smrg 246706f2543Smrg/* FamilyServerInterpreted implementation */ 247706f2543Smrgstatic Bool siAddrMatch(int family, pointer addr, int len, HOST *host, 248706f2543Smrg ClientPtr client); 249706f2543Smrgstatic int siCheckAddr(const char *addrString, int length); 250706f2543Smrgstatic void siTypesInitialize(void); 251706f2543Smrg 252706f2543Smrg/* 253706f2543Smrg * called when authorization is not enabled to add the 254706f2543Smrg * local host to the access list 255706f2543Smrg */ 256706f2543Smrg 257706f2543Smrgvoid 258706f2543SmrgEnableLocalHost (void) 259706f2543Smrg{ 260706f2543Smrg if (!UsingXdmcp) 261706f2543Smrg { 262706f2543Smrg LocalHostEnabled = TRUE; 263706f2543Smrg AddLocalHosts (); 264706f2543Smrg } 265706f2543Smrg} 266706f2543Smrg 267706f2543Smrg/* 268706f2543Smrg * called when authorization is enabled to keep us secure 269706f2543Smrg */ 270706f2543Smrgvoid 271706f2543SmrgDisableLocalHost (void) 272706f2543Smrg{ 273706f2543Smrg HOST *self; 274706f2543Smrg 275706f2543Smrg if (!LocalHostRequested) /* Fix for XFree86 bug #156 */ 276706f2543Smrg LocalHostEnabled = FALSE; 277706f2543Smrg for (self = selfhosts; self; self = self->next) { 278706f2543Smrg if (!self->requested) /* Fix for XFree86 bug #156 */ 279706f2543Smrg (void) RemoveHost ((ClientPtr)NULL, self->family, self->len, (pointer)self->addr); 280706f2543Smrg } 281706f2543Smrg} 282706f2543Smrg 283706f2543Smrg/* 284706f2543Smrg * called at init time when XDMCP will be used; xdmcp always 285706f2543Smrg * adds local hosts manually when needed 286706f2543Smrg */ 287706f2543Smrg 288706f2543Smrgvoid 289706f2543SmrgAccessUsingXdmcp (void) 290706f2543Smrg{ 291706f2543Smrg UsingXdmcp = TRUE; 292706f2543Smrg LocalHostEnabled = FALSE; 293706f2543Smrg} 294706f2543Smrg 295706f2543Smrg 296706f2543Smrg#if defined(SVR4) && !defined(sun) && defined(SIOCGIFCONF) && !defined(USE_SIOCGLIFCONF) 297706f2543Smrg 298706f2543Smrg/* Deal with different SIOCGIFCONF ioctl semantics on these OSs */ 299706f2543Smrg 300706f2543Smrgstatic int 301706f2543Smrgifioctl (int fd, int cmd, char *arg) 302706f2543Smrg{ 303706f2543Smrg struct strioctl ioc; 304706f2543Smrg int ret; 305706f2543Smrg 306706f2543Smrg memset((char *) &ioc, 0, sizeof(ioc)); 307706f2543Smrg ioc.ic_cmd = cmd; 308706f2543Smrg ioc.ic_timout = 0; 309706f2543Smrg if (cmd == SIOCGIFCONF) 310706f2543Smrg { 311706f2543Smrg ioc.ic_len = ((struct ifconf *) arg)->ifc_len; 312706f2543Smrg ioc.ic_dp = ((struct ifconf *) arg)->ifc_buf; 313706f2543Smrg } 314706f2543Smrg else 315706f2543Smrg { 316706f2543Smrg ioc.ic_len = sizeof(struct ifreq); 317706f2543Smrg ioc.ic_dp = arg; 318706f2543Smrg } 319706f2543Smrg ret = ioctl(fd, I_STR, (char *) &ioc); 320706f2543Smrg if (ret >= 0 && cmd == SIOCGIFCONF) 321706f2543Smrg#ifdef SVR4 322706f2543Smrg ((struct ifconf *) arg)->ifc_len = ioc.ic_len; 323706f2543Smrg#endif 324706f2543Smrg return ret; 325706f2543Smrg} 326706f2543Smrg#else 327706f2543Smrg#define ifioctl ioctl 328706f2543Smrg#endif 329706f2543Smrg 330706f2543Smrg/* 331706f2543Smrg * DefineSelf (fd): 332706f2543Smrg * 333706f2543Smrg * Define this host for access control. Find all the hosts the OS knows about 334706f2543Smrg * for this fd and add them to the selfhosts list. 335706f2543Smrg */ 336706f2543Smrg 337706f2543Smrg#if !defined(SIOCGIFCONF) 338706f2543Smrgvoid 339706f2543SmrgDefineSelf (int fd) 340706f2543Smrg{ 341706f2543Smrg#if !defined(TCPCONN) && !defined(STREAMSCONN) && !defined(UNIXCONN) 342706f2543Smrg return; 343706f2543Smrg#else 344706f2543Smrg register int n; 345706f2543Smrg int len; 346706f2543Smrg caddr_t addr; 347706f2543Smrg int family; 348706f2543Smrg register HOST *host; 349706f2543Smrg 350706f2543Smrg#ifndef WIN32 351706f2543Smrg struct utsname name; 352706f2543Smrg#else 353706f2543Smrg struct { 354706f2543Smrg char nodename[512]; 355706f2543Smrg } name; 356706f2543Smrg#endif 357706f2543Smrg 358706f2543Smrg register struct hostent *hp; 359706f2543Smrg 360706f2543Smrg union { 361706f2543Smrg struct sockaddr sa; 362706f2543Smrg struct sockaddr_in in; 363706f2543Smrg#if defined(IPv6) && defined(AF_INET6) 364706f2543Smrg struct sockaddr_in6 in6; 365706f2543Smrg#endif 366706f2543Smrg } saddr; 367706f2543Smrg 368706f2543Smrg struct sockaddr_in *inetaddr; 369706f2543Smrg struct sockaddr_in6 *inet6addr; 370706f2543Smrg struct sockaddr_in broad_addr; 371706f2543Smrg#ifdef XTHREADS_NEEDS_BYNAMEPARAMS 372706f2543Smrg _Xgethostbynameparams hparams; 373706f2543Smrg#endif 374706f2543Smrg 375706f2543Smrg /* Why not use gethostname()? Well, at least on my system, I've had to 376706f2543Smrg * make an ugly kernel patch to get a name longer than 8 characters, and 377706f2543Smrg * uname() lets me access to the whole string (it smashes release, you 378706f2543Smrg * see), whereas gethostname() kindly truncates it for me. 379706f2543Smrg */ 380706f2543Smrg#ifndef WIN32 381706f2543Smrg uname(&name); 382706f2543Smrg#else 383706f2543Smrg gethostname(name.nodename, sizeof(name.nodename)); 384706f2543Smrg#endif 385706f2543Smrg 386706f2543Smrg hp = _XGethostbyname(name.nodename, hparams); 387706f2543Smrg if (hp != NULL) 388706f2543Smrg { 389706f2543Smrg saddr.sa.sa_family = hp->h_addrtype; 390706f2543Smrg switch (hp->h_addrtype) { 391706f2543Smrg case AF_INET: 392706f2543Smrg inetaddr = (struct sockaddr_in *) (&(saddr.sa)); 393706f2543Smrg acopy ( hp->h_addr, &(inetaddr->sin_addr), hp->h_length); 394706f2543Smrg len = sizeof(saddr.sa); 395706f2543Smrg break; 396706f2543Smrg#if defined(IPv6) && defined(AF_INET6) 397706f2543Smrg case AF_INET6: 398706f2543Smrg inet6addr = (struct sockaddr_in6 *) (&(saddr.sa)); 399706f2543Smrg acopy ( hp->h_addr, &(inet6addr->sin6_addr), hp->h_length); 400706f2543Smrg len = sizeof(saddr.in6); 401706f2543Smrg break; 402706f2543Smrg#endif 403706f2543Smrg default: 404706f2543Smrg goto DefineLocalHost; 405706f2543Smrg } 406706f2543Smrg family = ConvertAddr ( &(saddr.sa), &len, (pointer *)&addr); 407706f2543Smrg if ( family != -1 && family != FamilyLocal ) 408706f2543Smrg { 409706f2543Smrg for (host = selfhosts; 410706f2543Smrg host && !addrEqual (family, addr, len, host); 411706f2543Smrg host = host->next) ; 412706f2543Smrg if (!host) 413706f2543Smrg { 414706f2543Smrg /* add this host to the host list. */ 415706f2543Smrg MakeHost(host,len) 416706f2543Smrg if (host) 417706f2543Smrg { 418706f2543Smrg host->family = family; 419706f2543Smrg host->len = len; 420706f2543Smrg acopy ( addr, host->addr, len); 421706f2543Smrg host->next = selfhosts; 422706f2543Smrg selfhosts = host; 423706f2543Smrg } 424706f2543Smrg#ifdef XDMCP 425706f2543Smrg /* 426706f2543Smrg * If this is an Internet Address, but not the localhost 427706f2543Smrg * address (127.0.0.1), nor the bogus address (0.0.0.0), 428706f2543Smrg * register it. 429706f2543Smrg */ 430706f2543Smrg if (family == FamilyInternet && 431706f2543Smrg !(len == 4 && 432706f2543Smrg ((addr[0] == 127) || 433706f2543Smrg (addr[0] == 0 && addr[1] == 0 && 434706f2543Smrg addr[2] == 0 && addr[3] == 0))) 435706f2543Smrg ) 436706f2543Smrg { 437706f2543Smrg XdmcpRegisterConnection (family, (char *)addr, len); 438706f2543Smrg broad_addr = *inetaddr; 439706f2543Smrg ((struct sockaddr_in *) &broad_addr)->sin_addr.s_addr = 440706f2543Smrg htonl (INADDR_BROADCAST); 441706f2543Smrg XdmcpRegisterBroadcastAddress ((struct sockaddr_in *) 442706f2543Smrg &broad_addr); 443706f2543Smrg } 444706f2543Smrg#if defined(IPv6) && defined(AF_INET6) 445706f2543Smrg else if (family == FamilyInternet6 && 446706f2543Smrg !(IN6_IS_ADDR_LOOPBACK((struct in6_addr *)addr))) 447706f2543Smrg { 448706f2543Smrg XdmcpRegisterConnection (family, (char *)addr, len); 449706f2543Smrg } 450706f2543Smrg#endif 451706f2543Smrg 452706f2543Smrg#endif /* XDMCP */ 453706f2543Smrg } 454706f2543Smrg } 455706f2543Smrg } 456706f2543Smrg /* 457706f2543Smrg * now add a host of family FamilyLocalHost... 458706f2543Smrg */ 459706f2543SmrgDefineLocalHost: 460706f2543Smrg for (host = selfhosts; 461706f2543Smrg host && !addrEqual(FamilyLocalHost, "", 0, host); 462706f2543Smrg host = host->next); 463706f2543Smrg if (!host) 464706f2543Smrg { 465706f2543Smrg MakeHost(host, 0); 466706f2543Smrg if (host) 467706f2543Smrg { 468706f2543Smrg host->family = FamilyLocalHost; 469706f2543Smrg host->len = 0; 470706f2543Smrg acopy("", host->addr, 0); 471706f2543Smrg host->next = selfhosts; 472706f2543Smrg selfhosts = host; 473706f2543Smrg } 474706f2543Smrg } 475706f2543Smrg#endif /* !TCPCONN && !STREAMSCONN && !UNIXCONN */ 476706f2543Smrg} 477706f2543Smrg 478706f2543Smrg#else 479706f2543Smrg 480706f2543Smrg#ifdef USE_SIOCGLIFCONF 481706f2543Smrg#define ifr_type struct lifreq 482706f2543Smrg#else 483706f2543Smrg#define ifr_type struct ifreq 484706f2543Smrg#endif 485706f2543Smrg 486706f2543Smrg#ifdef VARIABLE_IFREQ 487706f2543Smrg#define ifr_size(p) (sizeof (struct ifreq) + \ 488706f2543Smrg (p->ifr_addr.sa_len > sizeof (p->ifr_addr) ? \ 489706f2543Smrg p->ifr_addr.sa_len - sizeof (p->ifr_addr) : 0)) 490706f2543Smrg#define ifraddr_size(a) (a.sa_len) 491706f2543Smrg#else 492706f2543Smrg#define ifr_size(p) (sizeof (ifr_type)) 493706f2543Smrg#define ifraddr_size(a) (sizeof (a)) 494706f2543Smrg#endif 495706f2543Smrg 496706f2543Smrg#if defined(IPv6) && defined(AF_INET6) 497706f2543Smrg#include <arpa/inet.h> 498706f2543Smrg#endif 499706f2543Smrg 500706f2543Smrg#if defined(IPv6) && defined(AF_INET6) 501706f2543Smrgstatic void 502706f2543Smrgin6_fillscopeid(struct sockaddr_in6 *sin6) 503706f2543Smrg{ 504706f2543Smrg#if defined(__KAME__) 505706f2543Smrg if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 506706f2543Smrg sin6->sin6_scope_id = 507706f2543Smrg ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]); 508706f2543Smrg sin6->sin6_addr.s6_addr[2] = sin6->sin6_addr.s6_addr[3] = 0; 509706f2543Smrg } 510706f2543Smrg#endif 511706f2543Smrg} 512706f2543Smrg#endif 513706f2543Smrg 514706f2543Smrgvoid 515706f2543SmrgDefineSelf (int fd) 516706f2543Smrg{ 517706f2543Smrg#ifndef HAS_GETIFADDRS 518706f2543Smrg char *cp, *cplim; 519706f2543Smrg# ifdef USE_SIOCGLIFCONF 520706f2543Smrg struct sockaddr_storage buf[16]; 521706f2543Smrg struct lifconf ifc; 522706f2543Smrg register struct lifreq *ifr; 523706f2543Smrg# ifdef SIOCGLIFNUM 524706f2543Smrg struct lifnum ifn; 525706f2543Smrg# endif 526706f2543Smrg# else /* !USE_SIOCGLIFCONF */ 527706f2543Smrg char buf[2048]; 528706f2543Smrg struct ifconf ifc; 529706f2543Smrg register struct ifreq *ifr; 530706f2543Smrg# endif 531706f2543Smrg void * bufptr = buf; 532706f2543Smrg#else /* HAS_GETIFADDRS */ 533706f2543Smrg struct ifaddrs * ifap, *ifr; 534706f2543Smrg#endif 535706f2543Smrg int len; 536706f2543Smrg unsigned char * addr; 537706f2543Smrg int family; 538706f2543Smrg register HOST *host; 539706f2543Smrg 540706f2543Smrg#ifndef HAS_GETIFADDRS 541706f2543Smrg 542706f2543Smrg len = sizeof(buf); 543706f2543Smrg 544706f2543Smrg#ifdef USE_SIOCGLIFCONF 545706f2543Smrg 546706f2543Smrg#ifdef SIOCGLIFNUM 547706f2543Smrg ifn.lifn_family = AF_UNSPEC; 548706f2543Smrg ifn.lifn_flags = 0; 549706f2543Smrg if (ioctl (fd, SIOCGLIFNUM, (char *) &ifn) < 0) 550706f2543Smrg Error ("Getting interface count"); 551706f2543Smrg if (len < (ifn.lifn_count * sizeof(struct lifreq))) { 552706f2543Smrg len = ifn.lifn_count * sizeof(struct lifreq); 553706f2543Smrg bufptr = malloc(len); 554706f2543Smrg } 555706f2543Smrg#endif 556706f2543Smrg 557706f2543Smrg ifc.lifc_family = AF_UNSPEC; 558706f2543Smrg ifc.lifc_flags = 0; 559706f2543Smrg ifc.lifc_len = len; 560706f2543Smrg ifc.lifc_buf = bufptr; 561706f2543Smrg 562706f2543Smrg#define IFC_IOCTL_REQ SIOCGLIFCONF 563706f2543Smrg#define IFC_IFC_REQ ifc.lifc_req 564706f2543Smrg#define IFC_IFC_LEN ifc.lifc_len 565706f2543Smrg#define IFR_IFR_ADDR ifr->lifr_addr 566706f2543Smrg#define IFR_IFR_NAME ifr->lifr_name 567706f2543Smrg 568706f2543Smrg#else /* Use SIOCGIFCONF */ 569706f2543Smrg ifc.ifc_len = len; 570706f2543Smrg ifc.ifc_buf = bufptr; 571706f2543Smrg 572706f2543Smrg#define IFC_IOCTL_REQ SIOCGIFCONF 573706f2543Smrg#define IFC_IFC_REQ ifc.ifc_req 574706f2543Smrg#define IFC_IFC_LEN ifc.ifc_len 575706f2543Smrg#define IFR_IFR_ADDR ifr->ifr_addr 576706f2543Smrg#define IFR_IFR_NAME ifr->ifr_name 577706f2543Smrg#endif 578706f2543Smrg 579706f2543Smrg if (ifioctl (fd, IFC_IOCTL_REQ, (pointer) &ifc) < 0) 580706f2543Smrg Error ("Getting interface configuration (4)"); 581706f2543Smrg 582706f2543Smrg cplim = (char *) IFC_IFC_REQ + IFC_IFC_LEN; 583706f2543Smrg 584706f2543Smrg for (cp = (char *) IFC_IFC_REQ; cp < cplim; cp += ifr_size (ifr)) 585706f2543Smrg { 586706f2543Smrg ifr = (ifr_type *) cp; 587706f2543Smrg len = ifraddr_size (IFR_IFR_ADDR); 588706f2543Smrg family = ConvertAddr ((struct sockaddr *) &IFR_IFR_ADDR, 589706f2543Smrg &len, (pointer *)&addr); 590706f2543Smrg if (family == -1 || family == FamilyLocal) 591706f2543Smrg continue; 592706f2543Smrg#if defined(IPv6) && defined(AF_INET6) 593706f2543Smrg if (family == FamilyInternet6) 594706f2543Smrg in6_fillscopeid((struct sockaddr_in6 *)&IFR_IFR_ADDR); 595706f2543Smrg#endif 596706f2543Smrg for (host = selfhosts; 597706f2543Smrg host && !addrEqual (family, addr, len, host); 598706f2543Smrg host = host->next) 599706f2543Smrg ; 600706f2543Smrg if (host) 601706f2543Smrg continue; 602706f2543Smrg MakeHost(host,len) 603706f2543Smrg if (host) 604706f2543Smrg { 605706f2543Smrg host->family = family; 606706f2543Smrg host->len = len; 607706f2543Smrg acopy(addr, host->addr, len); 608706f2543Smrg host->next = selfhosts; 609706f2543Smrg selfhosts = host; 610706f2543Smrg } 611706f2543Smrg#ifdef XDMCP 612706f2543Smrg { 613706f2543Smrg#ifdef USE_SIOCGLIFCONF 614706f2543Smrg struct sockaddr_storage broad_addr; 615706f2543Smrg#else 616706f2543Smrg struct sockaddr broad_addr; 617706f2543Smrg#endif 618706f2543Smrg 619706f2543Smrg /* 620706f2543Smrg * If this isn't an Internet Address, don't register it. 621706f2543Smrg */ 622706f2543Smrg if (family != FamilyInternet 623706f2543Smrg#if defined(IPv6) && defined(AF_INET6) 624706f2543Smrg && family != FamilyInternet6 625706f2543Smrg#endif 626706f2543Smrg ) 627706f2543Smrg continue; 628706f2543Smrg 629706f2543Smrg /* 630706f2543Smrg * ignore 'localhost' entries as they're not useful 631706f2543Smrg * on the other end of the wire 632706f2543Smrg */ 633706f2543Smrg if (family == FamilyInternet && 634706f2543Smrg addr[0] == 127 && addr[1] == 0 && 635706f2543Smrg addr[2] == 0 && addr[3] == 1) 636706f2543Smrg continue; 637706f2543Smrg#if defined(IPv6) && defined(AF_INET6) 638706f2543Smrg else if (family == FamilyInternet6 && 639706f2543Smrg IN6_IS_ADDR_LOOPBACK((struct in6_addr *)addr)) 640706f2543Smrg continue; 641706f2543Smrg#endif 642706f2543Smrg 643706f2543Smrg /* 644706f2543Smrg * Ignore '0.0.0.0' entries as they are 645706f2543Smrg * returned by some OSes for unconfigured NICs but they are 646706f2543Smrg * not useful on the other end of the wire. 647706f2543Smrg */ 648706f2543Smrg if (len == 4 && 649706f2543Smrg addr[0] == 0 && addr[1] == 0 && 650706f2543Smrg addr[2] == 0 && addr[3] == 0) 651706f2543Smrg continue; 652706f2543Smrg 653706f2543Smrg XdmcpRegisterConnection (family, (char *)addr, len); 654706f2543Smrg 655706f2543Smrg#if defined(IPv6) && defined(AF_INET6) 656706f2543Smrg /* IPv6 doesn't support broadcasting, so we drop out here */ 657706f2543Smrg if (family == FamilyInternet6) 658706f2543Smrg continue; 659706f2543Smrg#endif 660706f2543Smrg 661706f2543Smrg broad_addr = IFR_IFR_ADDR; 662706f2543Smrg 663706f2543Smrg ((struct sockaddr_in *) &broad_addr)->sin_addr.s_addr = 664706f2543Smrg htonl (INADDR_BROADCAST); 665706f2543Smrg#if defined(USE_SIOCGLIFCONF) && defined(SIOCGLIFBRDADDR) 666706f2543Smrg { 667706f2543Smrg struct lifreq broad_req; 668706f2543Smrg 669706f2543Smrg broad_req = *ifr; 670706f2543Smrg if (ioctl (fd, SIOCGLIFFLAGS, (char *) &broad_req) != -1 && 671706f2543Smrg (broad_req.lifr_flags & IFF_BROADCAST) && 672706f2543Smrg (broad_req.lifr_flags & IFF_UP) 673706f2543Smrg ) 674706f2543Smrg { 675706f2543Smrg broad_req = *ifr; 676706f2543Smrg if (ioctl (fd, SIOCGLIFBRDADDR, &broad_req) != -1) 677706f2543Smrg broad_addr = broad_req.lifr_broadaddr; 678706f2543Smrg else 679706f2543Smrg continue; 680706f2543Smrg } 681706f2543Smrg else 682706f2543Smrg continue; 683706f2543Smrg } 684706f2543Smrg 685706f2543Smrg#elif defined(SIOCGIFBRDADDR) 686706f2543Smrg { 687706f2543Smrg struct ifreq broad_req; 688706f2543Smrg 689706f2543Smrg broad_req = *ifr; 690706f2543Smrg if (ifioctl (fd, SIOCGIFFLAGS, (pointer) &broad_req) != -1 && 691706f2543Smrg (broad_req.ifr_flags & IFF_BROADCAST) && 692706f2543Smrg (broad_req.ifr_flags & IFF_UP) 693706f2543Smrg ) 694706f2543Smrg { 695706f2543Smrg broad_req = *ifr; 696706f2543Smrg if (ifioctl (fd, SIOCGIFBRDADDR, (pointer) &broad_req) != -1) 697706f2543Smrg broad_addr = broad_req.ifr_addr; 698706f2543Smrg else 699706f2543Smrg continue; 700706f2543Smrg } 701706f2543Smrg else 702706f2543Smrg continue; 703706f2543Smrg } 704706f2543Smrg#endif /* SIOCGIFBRDADDR */ 705706f2543Smrg XdmcpRegisterBroadcastAddress ((struct sockaddr_in *) &broad_addr); 706706f2543Smrg } 707706f2543Smrg#endif /* XDMCP */ 708706f2543Smrg } 709706f2543Smrg if (bufptr != buf) 710706f2543Smrg free(bufptr); 711706f2543Smrg#else /* HAS_GETIFADDRS */ 712706f2543Smrg if (getifaddrs(&ifap) < 0) { 713706f2543Smrg ErrorF("Warning: getifaddrs returns %s\n", strerror(errno)); 714706f2543Smrg return; 715706f2543Smrg } 716706f2543Smrg for (ifr = ifap; ifr != NULL; ifr = ifr->ifa_next) { 717706f2543Smrg if (!ifr->ifa_addr) 718706f2543Smrg continue; 719706f2543Smrg len = sizeof(*(ifr->ifa_addr)); 720706f2543Smrg family = ConvertAddr((struct sockaddr *) ifr->ifa_addr, &len, 721706f2543Smrg (pointer *)&addr); 722706f2543Smrg if (family == -1 || family == FamilyLocal) 723706f2543Smrg continue; 724706f2543Smrg#if defined(IPv6) && defined(AF_INET6) 725706f2543Smrg if (family == FamilyInternet6) 726706f2543Smrg in6_fillscopeid((struct sockaddr_in6 *)ifr->ifa_addr); 727706f2543Smrg#endif 728706f2543Smrg 729706f2543Smrg for (host = selfhosts; 730706f2543Smrg host != NULL && !addrEqual(family, addr, len, host); 731706f2543Smrg host = host->next) 732706f2543Smrg ; 733706f2543Smrg if (host != NULL) 734706f2543Smrg continue; 735706f2543Smrg MakeHost(host, len); 736706f2543Smrg if (host != NULL) { 737706f2543Smrg host->family = family; 738706f2543Smrg host->len = len; 739706f2543Smrg acopy(addr, host->addr, len); 740706f2543Smrg host->next = selfhosts; 741706f2543Smrg selfhosts = host; 742706f2543Smrg } 743706f2543Smrg#ifdef XDMCP 744706f2543Smrg { 745706f2543Smrg /* 746706f2543Smrg * If this isn't an Internet Address, don't register it. 747706f2543Smrg */ 748706f2543Smrg if (family != FamilyInternet 749706f2543Smrg#if defined(IPv6) && defined(AF_INET6) 750706f2543Smrg && family != FamilyInternet6 751706f2543Smrg#endif 752706f2543Smrg ) 753706f2543Smrg continue; 754706f2543Smrg 755706f2543Smrg /* 756706f2543Smrg * ignore 'localhost' entries as they're not useful 757706f2543Smrg * on the other end of the wire 758706f2543Smrg */ 759706f2543Smrg if (ifr->ifa_flags & IFF_LOOPBACK) 760706f2543Smrg continue; 761706f2543Smrg 762706f2543Smrg if (family == FamilyInternet && 763706f2543Smrg addr[0] == 127 && addr[1] == 0 && 764706f2543Smrg addr[2] == 0 && addr[3] == 1) 765706f2543Smrg continue; 766706f2543Smrg 767706f2543Smrg /* 768706f2543Smrg * Ignore '0.0.0.0' entries as they are 769706f2543Smrg * returned by some OSes for unconfigured NICs but they are 770706f2543Smrg * not useful on the other end of the wire. 771706f2543Smrg */ 772706f2543Smrg if (len == 4 && 773706f2543Smrg addr[0] == 0 && addr[1] == 0 && 774706f2543Smrg addr[2] == 0 && addr[3] == 0) 775706f2543Smrg continue; 776706f2543Smrg#if defined(IPv6) && defined(AF_INET6) 777706f2543Smrg else if (family == FamilyInternet6 && 778706f2543Smrg IN6_IS_ADDR_LOOPBACK((struct in6_addr *)addr)) 779706f2543Smrg continue; 780706f2543Smrg#endif 781706f2543Smrg XdmcpRegisterConnection(family, (char *)addr, len); 782706f2543Smrg#if defined(IPv6) && defined(AF_INET6) 783706f2543Smrg if (family == FamilyInternet6) 784706f2543Smrg /* IPv6 doesn't support broadcasting, so we drop out here */ 785706f2543Smrg continue; 786706f2543Smrg#endif 787706f2543Smrg if ((ifr->ifa_flags & IFF_BROADCAST) && 788706f2543Smrg (ifr->ifa_flags & IFF_UP) && 789706f2543Smrg ifr->ifa_broadaddr) 790706f2543Smrg XdmcpRegisterBroadcastAddress( 791706f2543Smrg (struct sockaddr_in *) ifr->ifa_broadaddr); 792706f2543Smrg else 793706f2543Smrg continue; 794706f2543Smrg } 795706f2543Smrg#endif /* XDMCP */ 796706f2543Smrg 797706f2543Smrg } /* for */ 798706f2543Smrg freeifaddrs(ifap); 799706f2543Smrg#endif /* HAS_GETIFADDRS */ 800706f2543Smrg 801706f2543Smrg /* 802706f2543Smrg * add something of FamilyLocalHost 803706f2543Smrg */ 804706f2543Smrg for (host = selfhosts; 805706f2543Smrg host && !addrEqual(FamilyLocalHost, "", 0, host); 806706f2543Smrg host = host->next); 807706f2543Smrg if (!host) 808706f2543Smrg { 809706f2543Smrg MakeHost(host, 0); 810706f2543Smrg if (host) 811706f2543Smrg { 812706f2543Smrg host->family = FamilyLocalHost; 813706f2543Smrg host->len = 0; 814706f2543Smrg acopy("", host->addr, 0); 815706f2543Smrg host->next = selfhosts; 816706f2543Smrg selfhosts = host; 817706f2543Smrg } 818706f2543Smrg } 819706f2543Smrg} 820706f2543Smrg#endif /* hpux && !HAS_IFREQ */ 821706f2543Smrg 822706f2543Smrg#ifdef XDMCP 823706f2543Smrgvoid 824706f2543SmrgAugmentSelf(pointer from, int len) 825706f2543Smrg{ 826706f2543Smrg int family; 827706f2543Smrg pointer addr; 828706f2543Smrg register HOST *host; 829706f2543Smrg 830706f2543Smrg family = ConvertAddr(from, &len, (pointer *)&addr); 831706f2543Smrg if (family == -1 || family == FamilyLocal) 832706f2543Smrg return; 833706f2543Smrg for (host = selfhosts; host; host = host->next) 834706f2543Smrg { 835706f2543Smrg if (addrEqual(family, addr, len, host)) 836706f2543Smrg return; 837706f2543Smrg } 838706f2543Smrg MakeHost(host,len) 839706f2543Smrg if (!host) 840706f2543Smrg return; 841706f2543Smrg host->family = family; 842706f2543Smrg host->len = len; 843706f2543Smrg acopy(addr, host->addr, len); 844706f2543Smrg host->next = selfhosts; 845706f2543Smrg selfhosts = host; 846706f2543Smrg} 847706f2543Smrg#endif 848706f2543Smrg 849706f2543Smrgvoid 850706f2543SmrgAddLocalHosts (void) 851706f2543Smrg{ 852706f2543Smrg HOST *self; 853706f2543Smrg 854706f2543Smrg for (self = selfhosts; self; self = self->next) 855706f2543Smrg /* Fix for XFree86 bug #156: pass addingLocal = TRUE to 856706f2543Smrg * NewHost to tell that we are adding the default local 857706f2543Smrg * host entries and not to flag the entries as being 858706f2543Smrg * explicitely requested */ 859706f2543Smrg (void) NewHost (self->family, self->addr, self->len, TRUE); 860706f2543Smrg} 861706f2543Smrg 862706f2543Smrg/* Reset access control list to initial hosts */ 863706f2543Smrgvoid 864706f2543SmrgResetHosts (char *display) 865706f2543Smrg{ 866706f2543Smrg register HOST *host; 867706f2543Smrg char lhostname[120], ohostname[120]; 868706f2543Smrg char *hostname = ohostname; 869706f2543Smrg char fname[PATH_MAX + 1]; 870706f2543Smrg int fnamelen; 871706f2543Smrg FILE *fd; 872706f2543Smrg char *ptr; 873706f2543Smrg int i, hostlen; 874706f2543Smrg#if (defined(TCPCONN) || defined(STREAMSCONN) ) && \ 875706f2543Smrg (!defined(IPv6) || !defined(AF_INET6)) 876706f2543Smrg union { 877706f2543Smrg struct sockaddr sa; 878706f2543Smrg#if defined(TCPCONN) || defined(STREAMSCONN) 879706f2543Smrg struct sockaddr_in in; 880706f2543Smrg#endif /* TCPCONN || STREAMSCONN */ 881706f2543Smrg } saddr; 882706f2543Smrg#endif 883706f2543Smrg int family = 0; 884706f2543Smrg pointer addr; 885706f2543Smrg int len; 886706f2543Smrg 887706f2543Smrg siTypesInitialize(); 888706f2543Smrg AccessEnabled = defeatAccessControl ? FALSE : DEFAULT_ACCESS_CONTROL; 889706f2543Smrg LocalHostEnabled = FALSE; 890706f2543Smrg while ((host = validhosts) != 0) 891706f2543Smrg { 892706f2543Smrg validhosts = host->next; 893706f2543Smrg FreeHost (host); 894706f2543Smrg } 895706f2543Smrg 896706f2543Smrg#if defined WIN32 && defined __MINGW32__ 897706f2543Smrg#define ETC_HOST_PREFIX "X" 898706f2543Smrg#else 899706f2543Smrg#define ETC_HOST_PREFIX "/etc/X" 900706f2543Smrg#endif 901706f2543Smrg#define ETC_HOST_SUFFIX ".hosts" 902706f2543Smrg fnamelen = strlen(ETC_HOST_PREFIX) + strlen(ETC_HOST_SUFFIX) + 903706f2543Smrg strlen(display) + 1; 904706f2543Smrg if (fnamelen > sizeof(fname)) 905706f2543Smrg FatalError("Display name `%s' is too long\n", display); 906706f2543Smrg snprintf(fname, sizeof(fname), ETC_HOST_PREFIX "%s" ETC_HOST_SUFFIX, 907706f2543Smrg display); 908706f2543Smrg 909706f2543Smrg if ((fd = fopen (fname, "r")) != 0) 910706f2543Smrg { 911706f2543Smrg while (fgets (ohostname, sizeof (ohostname), fd)) 912706f2543Smrg { 913706f2543Smrg family = FamilyWild; 914706f2543Smrg if (*ohostname == '#') 915706f2543Smrg continue; 916706f2543Smrg if ((ptr = strchr(ohostname, '\n')) != 0) 917706f2543Smrg *ptr = 0; 918706f2543Smrg hostlen = strlen(ohostname) + 1; 919706f2543Smrg for (i = 0; i < hostlen; i++) 920706f2543Smrg lhostname[i] = tolower(ohostname[i]); 921706f2543Smrg hostname = ohostname; 922706f2543Smrg if (!strncmp("local:", lhostname, 6)) 923706f2543Smrg { 924706f2543Smrg family = FamilyLocalHost; 925706f2543Smrg NewHost(family, "", 0, FALSE); 926706f2543Smrg LocalHostRequested = TRUE; /* Fix for XFree86 bug #156 */ 927706f2543Smrg } 928706f2543Smrg#if defined(TCPCONN) || defined(STREAMSCONN) 929706f2543Smrg else if (!strncmp("inet:", lhostname, 5)) 930706f2543Smrg { 931706f2543Smrg family = FamilyInternet; 932706f2543Smrg hostname = ohostname + 5; 933706f2543Smrg } 934706f2543Smrg#if defined(IPv6) && defined(AF_INET6) 935706f2543Smrg else if (!strncmp("inet6:", lhostname, 6)) 936706f2543Smrg { 937706f2543Smrg family = FamilyInternet6; 938706f2543Smrg hostname = ohostname + 6; 939706f2543Smrg } 940706f2543Smrg#endif 941706f2543Smrg#endif 942706f2543Smrg#ifdef SECURE_RPC 943706f2543Smrg else if (!strncmp("nis:", lhostname, 4)) 944706f2543Smrg { 945706f2543Smrg family = FamilyNetname; 946706f2543Smrg hostname = ohostname + 4; 947706f2543Smrg } 948706f2543Smrg#endif 949706f2543Smrg else if (!strncmp("si:", lhostname, 3)) 950706f2543Smrg { 951706f2543Smrg family = FamilyServerInterpreted; 952706f2543Smrg hostname = ohostname + 3; 953706f2543Smrg hostlen -= 3; 954706f2543Smrg } 955706f2543Smrg 956706f2543Smrg 957706f2543Smrg if (family == FamilyServerInterpreted) 958706f2543Smrg { 959706f2543Smrg len = siCheckAddr(hostname, hostlen); 960706f2543Smrg if (len >= 0) { 961706f2543Smrg NewHost(family, hostname, len, FALSE); 962706f2543Smrg } 963706f2543Smrg } 964706f2543Smrg else 965706f2543Smrg#ifdef SECURE_RPC 966706f2543Smrg if ((family == FamilyNetname) || (strchr(hostname, '@'))) 967706f2543Smrg { 968706f2543Smrg SecureRPCInit (); 969706f2543Smrg (void) NewHost (FamilyNetname, hostname, strlen (hostname), FALSE); 970706f2543Smrg } 971706f2543Smrg else 972706f2543Smrg#endif /* SECURE_RPC */ 973706f2543Smrg#if defined(TCPCONN) || defined(STREAMSCONN) 974706f2543Smrg { 975706f2543Smrg#if defined(IPv6) && defined(AF_INET6) 976706f2543Smrg if ( (family == FamilyInternet) || (family == FamilyInternet6) || 977706f2543Smrg (family == FamilyWild) ) 978706f2543Smrg { 979706f2543Smrg struct addrinfo *addresses; 980706f2543Smrg struct addrinfo *a; 981706f2543Smrg int f; 982706f2543Smrg 983706f2543Smrg if (getaddrinfo(hostname, NULL, NULL, &addresses) == 0) { 984706f2543Smrg for (a = addresses ; a != NULL ; a = a->ai_next) { 985706f2543Smrg len = a->ai_addrlen; 986706f2543Smrg f = ConvertAddr(a->ai_addr,&len,(pointer *)&addr); 987706f2543Smrg if ( (family == f) || 988706f2543Smrg ((family == FamilyWild) && (f != -1)) ) { 989706f2543Smrg NewHost(f, addr, len, FALSE); 990706f2543Smrg } 991706f2543Smrg } 992706f2543Smrg freeaddrinfo(addresses); 993706f2543Smrg } 994706f2543Smrg } 995706f2543Smrg#else 996706f2543Smrg#ifdef XTHREADS_NEEDS_BYNAMEPARAMS 997706f2543Smrg _Xgethostbynameparams hparams; 998706f2543Smrg#endif 999706f2543Smrg register struct hostent *hp; 1000706f2543Smrg 1001706f2543Smrg /* host name */ 1002706f2543Smrg if ((family == FamilyInternet && 1003706f2543Smrg ((hp = _XGethostbyname(hostname, hparams)) != 0)) || 1004706f2543Smrg ((hp = _XGethostbyname(hostname, hparams)) != 0)) 1005706f2543Smrg { 1006706f2543Smrg saddr.sa.sa_family = hp->h_addrtype; 1007706f2543Smrg len = sizeof(saddr.sa); 1008706f2543Smrg if ((family = ConvertAddr (&saddr.sa, &len, (pointer *)&addr)) != -1) 1009706f2543Smrg { 1010706f2543Smrg#ifdef h_addr /* new 4.3bsd version of gethostent */ 1011706f2543Smrg char **list; 1012706f2543Smrg 1013706f2543Smrg /* iterate over the addresses */ 1014706f2543Smrg for (list = hp->h_addr_list; *list; list++) 1015706f2543Smrg (void) NewHost (family, (pointer)*list, len, FALSE); 1016706f2543Smrg#else 1017706f2543Smrg (void) NewHost (family, (pointer)hp->h_addr, len, FALSE); 1018706f2543Smrg#endif 1019706f2543Smrg } 1020706f2543Smrg } 1021706f2543Smrg#endif /* IPv6 */ 1022706f2543Smrg } 1023706f2543Smrg#endif /* TCPCONN || STREAMSCONN */ 1024706f2543Smrg family = FamilyWild; 1025706f2543Smrg } 1026706f2543Smrg fclose (fd); 1027706f2543Smrg } 1028706f2543Smrg} 1029706f2543Smrg 1030706f2543Smrg/* Is client on the local host */ 1031706f2543SmrgBool 1032706f2543SmrgComputeLocalClient(ClientPtr client) 1033706f2543Smrg{ 1034706f2543Smrg int alen, family, notused; 1035706f2543Smrg Xtransaddr *from = NULL; 1036706f2543Smrg pointer addr; 1037706f2543Smrg register HOST *host; 1038706f2543Smrg OsCommPtr oc = (OsCommPtr) client->osPrivate; 1039706f2543Smrg 1040706f2543Smrg if (!oc->trans_conn) 1041706f2543Smrg return FALSE; 1042706f2543Smrg 1043706f2543Smrg if (!_XSERVTransGetPeerAddr (oc->trans_conn, ¬used, &alen, &from)) 1044706f2543Smrg { 1045706f2543Smrg family = ConvertAddr ((struct sockaddr *) from, 1046706f2543Smrg &alen, (pointer *)&addr); 1047706f2543Smrg if (family == -1) 1048706f2543Smrg { 1049706f2543Smrg free(from); 1050706f2543Smrg return FALSE; 1051706f2543Smrg } 1052706f2543Smrg if (family == FamilyLocal) 1053706f2543Smrg { 1054706f2543Smrg free(from); 1055706f2543Smrg return TRUE; 1056706f2543Smrg } 1057706f2543Smrg for (host = selfhosts; host; host = host->next) 1058706f2543Smrg { 1059706f2543Smrg if (addrEqual (family, addr, alen, host)) { 1060706f2543Smrg free(from); 1061706f2543Smrg return TRUE; 1062706f2543Smrg } 1063706f2543Smrg } 1064706f2543Smrg free(from); 1065706f2543Smrg } 1066706f2543Smrg return FALSE; 1067706f2543Smrg} 1068706f2543Smrg 1069706f2543SmrgBool LocalClient(ClientPtr client) 1070706f2543Smrg{ 1071706f2543Smrg if (!client->osPrivate) 1072706f2543Smrg return FALSE; 1073706f2543Smrg return ((OsCommPtr)client->osPrivate)->local_client; 1074706f2543Smrg} 1075706f2543Smrg 1076706f2543Smrg/* 1077706f2543Smrg * Return the uid and gid of a connected local client 1078706f2543Smrg * 1079706f2543Smrg * Used by XShm to test access rights to shared memory segments 1080706f2543Smrg */ 1081706f2543Smrgint 1082706f2543SmrgLocalClientCred(ClientPtr client, int *pUid, int *pGid) 1083706f2543Smrg{ 1084706f2543Smrg LocalClientCredRec *lcc; 1085706f2543Smrg int ret = GetLocalClientCreds(client, &lcc); 1086706f2543Smrg 1087706f2543Smrg if (ret == 0) { 1088706f2543Smrg#ifdef HAVE_GETZONEID /* only local if in the same zone */ 1089706f2543Smrg if ((lcc->fieldsSet & LCC_ZID_SET) && (lcc->zoneid != getzoneid())) { 1090706f2543Smrg FreeLocalClientCreds(lcc); 1091706f2543Smrg return -1; 1092706f2543Smrg } 1093706f2543Smrg#endif 1094706f2543Smrg if ((lcc->fieldsSet & LCC_UID_SET) && (pUid != NULL)) 1095706f2543Smrg *pUid = lcc->euid; 1096706f2543Smrg if ((lcc->fieldsSet & LCC_GID_SET) && (pGid != NULL)) 1097706f2543Smrg *pGid = lcc->egid; 1098706f2543Smrg FreeLocalClientCreds(lcc); 1099706f2543Smrg } 1100706f2543Smrg return ret; 1101706f2543Smrg} 1102706f2543Smrg 1103706f2543Smrg/* 1104706f2543Smrg * Return the uid and all gids of a connected local client 1105706f2543Smrg * Allocates a LocalClientCredRec - caller must call FreeLocalClientCreds 1106706f2543Smrg * 1107706f2543Smrg * Used by localuser & localgroup ServerInterpreted access control forms below 1108706f2543Smrg * Used by AuthAudit to log who local connections came from 1109706f2543Smrg */ 1110706f2543Smrgint 1111706f2543SmrgGetLocalClientCreds(ClientPtr client, LocalClientCredRec **lccp) 1112706f2543Smrg{ 1113706f2543Smrg#if defined(HAS_GETPEEREID) || defined(HAS_GETPEERUCRED) || defined(SO_PEERCRED) 1114706f2543Smrg int fd; 1115706f2543Smrg XtransConnInfo ci; 1116706f2543Smrg LocalClientCredRec *lcc; 1117706f2543Smrg#ifdef HAS_GETPEEREID 1118706f2543Smrg uid_t uid; 1119706f2543Smrg gid_t gid; 1120706f2543Smrg#elif defined(HAS_GETPEERUCRED) 1121706f2543Smrg ucred_t *peercred = NULL; 1122706f2543Smrg const gid_t *gids; 1123706f2543Smrg#elif defined(SO_PEERCRED) 1124706f2543Smrg struct ucred peercred; 1125706f2543Smrg socklen_t so_len = sizeof(peercred); 1126706f2543Smrg#endif 1127706f2543Smrg 1128706f2543Smrg if (client == NULL) 1129706f2543Smrg return -1; 1130706f2543Smrg ci = ((OsCommPtr)client->osPrivate)->trans_conn; 1131706f2543Smrg#if !(defined(sun) && defined(HAS_GETPEERUCRED)) 1132706f2543Smrg /* Most implementations can only determine peer credentials for Unix 1133706f2543Smrg * domain sockets - Solaris getpeerucred can work with a bit more, so 1134706f2543Smrg * we just let it tell us if the connection type is supported or not 1135706f2543Smrg */ 1136706f2543Smrg if (!_XSERVTransIsLocal(ci)) { 1137706f2543Smrg return -1; 1138706f2543Smrg } 1139706f2543Smrg#endif 1140706f2543Smrg 1141706f2543Smrg *lccp = calloc(1, sizeof(LocalClientCredRec)); 1142706f2543Smrg if (*lccp == NULL) 1143706f2543Smrg return -1; 1144706f2543Smrg lcc = *lccp; 1145706f2543Smrg 1146706f2543Smrg fd = _XSERVTransGetConnectionNumber(ci); 1147706f2543Smrg#ifdef HAS_GETPEEREID 1148706f2543Smrg if (getpeereid(fd, &uid, &gid) == -1) { 1149706f2543Smrg FreeLocalClientCreds(lcc); 1150706f2543Smrg return -1; 1151706f2543Smrg } 1152706f2543Smrg lcc->euid = uid; 1153706f2543Smrg lcc->egid = gid; 1154706f2543Smrg lcc->fieldsSet = LCC_UID_SET | LCC_GID_SET; 1155706f2543Smrg return 0; 1156706f2543Smrg#elif defined(HAS_GETPEERUCRED) 1157706f2543Smrg if (getpeerucred(fd, &peercred) < 0) { 1158706f2543Smrg FreeLocalClientCreds(lcc); 1159706f2543Smrg return -1; 1160706f2543Smrg } 1161706f2543Smrg lcc->euid = ucred_geteuid(peercred); 1162706f2543Smrg if (lcc->euid != -1) 1163706f2543Smrg lcc->fieldsSet |= LCC_UID_SET; 1164706f2543Smrg lcc->egid = ucred_getegid(peercred); 1165706f2543Smrg if (lcc->egid != -1) 1166706f2543Smrg lcc->fieldsSet |= LCC_GID_SET; 1167706f2543Smrg lcc->pid = ucred_getpid(peercred); 1168706f2543Smrg if (lcc->pid != -1) 1169706f2543Smrg lcc->fieldsSet |= LCC_PID_SET; 1170706f2543Smrg#ifdef HAVE_GETZONEID 1171706f2543Smrg lcc->zoneid = ucred_getzoneid(peercred); 1172706f2543Smrg if (lcc->zoneid != -1) 1173706f2543Smrg lcc->fieldsSet |= LCC_ZID_SET; 1174706f2543Smrg#endif 1175706f2543Smrg lcc->nSuppGids = ucred_getgroups(peercred, &gids); 1176706f2543Smrg if (lcc->nSuppGids > 0) { 1177706f2543Smrg lcc->pSuppGids = calloc(lcc->nSuppGids, sizeof(int)); 1178706f2543Smrg if (lcc->pSuppGids == NULL) { 1179706f2543Smrg lcc->nSuppGids = 0; 1180706f2543Smrg } else { 1181706f2543Smrg int i; 1182706f2543Smrg for (i = 0 ; i < lcc->nSuppGids; i++) { 1183706f2543Smrg (lcc->pSuppGids)[i] = (int) gids[i]; 1184706f2543Smrg } 1185706f2543Smrg } 1186706f2543Smrg } else { 1187706f2543Smrg lcc->nSuppGids = 0; 1188706f2543Smrg } 1189706f2543Smrg ucred_free(peercred); 1190706f2543Smrg return 0; 1191706f2543Smrg#elif defined(SO_PEERCRED) 1192706f2543Smrg if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) == -1) { 1193706f2543Smrg FreeLocalClientCreds(lcc); 1194706f2543Smrg return -1; 1195706f2543Smrg } 1196706f2543Smrg lcc->euid = peercred.uid; 1197706f2543Smrg lcc->egid = peercred.gid; 1198706f2543Smrg lcc->pid = peercred.pid; 1199706f2543Smrg lcc->fieldsSet = LCC_UID_SET | LCC_GID_SET | LCC_PID_SET; 1200706f2543Smrg return 0; 1201706f2543Smrg#endif 1202706f2543Smrg#else 1203706f2543Smrg /* No system call available to get the credentials of the peer */ 1204706f2543Smrg#define NO_LOCAL_CLIENT_CRED 1205706f2543Smrg return -1; 1206706f2543Smrg#endif 1207706f2543Smrg} 1208706f2543Smrg 1209706f2543Smrgvoid 1210706f2543SmrgFreeLocalClientCreds(LocalClientCredRec *lcc) 1211706f2543Smrg{ 1212706f2543Smrg if (lcc != NULL) { 1213706f2543Smrg if (lcc->nSuppGids > 0) { 1214706f2543Smrg free(lcc->pSuppGids); 1215706f2543Smrg } 1216706f2543Smrg free(lcc); 1217706f2543Smrg } 1218706f2543Smrg} 1219706f2543Smrg 1220706f2543Smrgstatic int 1221706f2543SmrgAuthorizedClient(ClientPtr client) 1222706f2543Smrg{ 1223706f2543Smrg int rc; 1224706f2543Smrg 1225706f2543Smrg if (!client || defeatAccessControl) 1226706f2543Smrg return Success; 1227706f2543Smrg 1228706f2543Smrg /* untrusted clients can't change host access */ 1229706f2543Smrg rc = XaceHook(XACE_SERVER_ACCESS, client, DixManageAccess); 1230706f2543Smrg if (rc != Success) 1231706f2543Smrg return rc; 1232706f2543Smrg 1233706f2543Smrg return LocalClient(client) ? Success : BadAccess; 1234706f2543Smrg} 1235706f2543Smrg 1236706f2543Smrg/* Add a host to the access control list. This is the external interface 1237706f2543Smrg * called from the dispatcher */ 1238706f2543Smrg 1239706f2543Smrgint 1240706f2543SmrgAddHost (ClientPtr client, 1241706f2543Smrg int family, 1242706f2543Smrg unsigned length, /* of bytes in pAddr */ 1243706f2543Smrg const void * pAddr) 1244706f2543Smrg{ 1245706f2543Smrg int rc, len; 1246706f2543Smrg 1247706f2543Smrg rc = AuthorizedClient(client); 1248706f2543Smrg if (rc != Success) 1249706f2543Smrg return rc; 1250706f2543Smrg switch (family) { 1251706f2543Smrg case FamilyLocalHost: 1252706f2543Smrg len = length; 1253706f2543Smrg LocalHostEnabled = TRUE; 1254706f2543Smrg break; 1255706f2543Smrg#ifdef SECURE_RPC 1256706f2543Smrg case FamilyNetname: 1257706f2543Smrg len = length; 1258706f2543Smrg SecureRPCInit (); 1259706f2543Smrg break; 1260706f2543Smrg#endif 1261706f2543Smrg case FamilyInternet: 1262706f2543Smrg#if defined(IPv6) && defined(AF_INET6) 1263706f2543Smrg case FamilyInternet6: 1264706f2543Smrg#endif 1265706f2543Smrg case FamilyDECnet: 1266706f2543Smrg case FamilyChaos: 1267706f2543Smrg case FamilyServerInterpreted: 1268706f2543Smrg if ((len = CheckAddr (family, pAddr, length)) < 0) 1269706f2543Smrg { 1270706f2543Smrg client->errorValue = length; 1271706f2543Smrg return BadValue; 1272706f2543Smrg } 1273706f2543Smrg break; 1274706f2543Smrg case FamilyLocal: 1275706f2543Smrg default: 1276706f2543Smrg client->errorValue = family; 1277706f2543Smrg return BadValue; 1278706f2543Smrg } 1279706f2543Smrg if (NewHost (family, pAddr, len, FALSE)) 1280706f2543Smrg return Success; 1281706f2543Smrg return BadAlloc; 1282706f2543Smrg} 1283706f2543Smrg 1284706f2543SmrgBool 1285706f2543SmrgForEachHostInFamily (int family, 1286706f2543Smrg Bool (*func)( 1287706f2543Smrg unsigned char * /* addr */, 1288706f2543Smrg short /* len */, 1289706f2543Smrg pointer /* closure */), 1290706f2543Smrg pointer closure) 1291706f2543Smrg{ 1292706f2543Smrg HOST *host; 1293706f2543Smrg 1294706f2543Smrg for (host = validhosts; host; host = host->next) 1295706f2543Smrg if (family == host->family && func (host->addr, host->len, closure)) 1296706f2543Smrg return TRUE; 1297706f2543Smrg return FALSE; 1298706f2543Smrg} 1299706f2543Smrg 1300706f2543Smrg/* Add a host to the access control list. This is the internal interface 1301706f2543Smrg * called when starting or resetting the server */ 1302706f2543Smrgstatic Bool 1303706f2543SmrgNewHost (int family, 1304706f2543Smrg const void * addr, 1305706f2543Smrg int len, 1306706f2543Smrg int addingLocalHosts) 1307706f2543Smrg{ 1308706f2543Smrg register HOST *host; 1309706f2543Smrg 1310706f2543Smrg for (host = validhosts; host; host = host->next) 1311706f2543Smrg { 1312706f2543Smrg if (addrEqual (family, addr, len, host)) 1313706f2543Smrg return TRUE; 1314706f2543Smrg } 1315706f2543Smrg if (!addingLocalHosts) { /* Fix for XFree86 bug #156 */ 1316706f2543Smrg for (host = selfhosts; host; host = host->next) { 1317706f2543Smrg if (addrEqual (family, addr, len, host)) { 1318706f2543Smrg host->requested = TRUE; 1319706f2543Smrg break; 1320706f2543Smrg } 1321706f2543Smrg } 1322706f2543Smrg } 1323706f2543Smrg MakeHost(host,len) 1324706f2543Smrg if (!host) 1325706f2543Smrg return FALSE; 1326706f2543Smrg host->family = family; 1327706f2543Smrg host->len = len; 1328706f2543Smrg acopy(addr, host->addr, len); 1329706f2543Smrg host->next = validhosts; 1330706f2543Smrg validhosts = host; 1331706f2543Smrg return TRUE; 1332706f2543Smrg} 1333706f2543Smrg 1334706f2543Smrg/* Remove a host from the access control list */ 1335706f2543Smrg 1336706f2543Smrgint 1337706f2543SmrgRemoveHost ( 1338706f2543Smrg ClientPtr client, 1339706f2543Smrg int family, 1340706f2543Smrg unsigned length, /* of bytes in pAddr */ 1341706f2543Smrg pointer pAddr) 1342706f2543Smrg{ 1343706f2543Smrg int rc, len; 1344706f2543Smrg register HOST *host, **prev; 1345706f2543Smrg 1346706f2543Smrg rc = AuthorizedClient(client); 1347706f2543Smrg if (rc != Success) 1348706f2543Smrg return rc; 1349706f2543Smrg switch (family) { 1350706f2543Smrg case FamilyLocalHost: 1351706f2543Smrg len = length; 1352706f2543Smrg LocalHostEnabled = FALSE; 1353706f2543Smrg break; 1354706f2543Smrg#ifdef SECURE_RPC 1355706f2543Smrg case FamilyNetname: 1356706f2543Smrg len = length; 1357706f2543Smrg break; 1358706f2543Smrg#endif 1359706f2543Smrg case FamilyInternet: 1360706f2543Smrg#if defined(IPv6) && defined(AF_INET6) 1361706f2543Smrg case FamilyInternet6: 1362706f2543Smrg#endif 1363706f2543Smrg case FamilyDECnet: 1364706f2543Smrg case FamilyChaos: 1365706f2543Smrg case FamilyServerInterpreted: 1366706f2543Smrg if ((len = CheckAddr (family, pAddr, length)) < 0) 1367706f2543Smrg { 1368706f2543Smrg client->errorValue = length; 1369706f2543Smrg return BadValue; 1370706f2543Smrg } 1371706f2543Smrg break; 1372706f2543Smrg case FamilyLocal: 1373706f2543Smrg default: 1374706f2543Smrg client->errorValue = family; 1375706f2543Smrg return BadValue; 1376706f2543Smrg } 1377706f2543Smrg for (prev = &validhosts; 1378706f2543Smrg (host = *prev) && (!addrEqual (family, pAddr, len, host)); 1379706f2543Smrg prev = &host->next) 1380706f2543Smrg ; 1381706f2543Smrg if (host) 1382706f2543Smrg { 1383706f2543Smrg *prev = host->next; 1384706f2543Smrg FreeHost (host); 1385706f2543Smrg } 1386706f2543Smrg return Success; 1387706f2543Smrg} 1388706f2543Smrg 1389706f2543Smrg/* Get all hosts in the access control list */ 1390706f2543Smrgint 1391706f2543SmrgGetHosts ( 1392706f2543Smrg pointer *data, 1393706f2543Smrg int *pnHosts, 1394706f2543Smrg int *pLen, 1395706f2543Smrg BOOL *pEnabled) 1396706f2543Smrg{ 1397706f2543Smrg int len; 1398706f2543Smrg register int n = 0; 1399706f2543Smrg register unsigned char *ptr; 1400706f2543Smrg register HOST *host; 1401706f2543Smrg int nHosts = 0; 1402706f2543Smrg 1403706f2543Smrg *pEnabled = AccessEnabled ? EnableAccess : DisableAccess; 1404706f2543Smrg for (host = validhosts; host; host = host->next) 1405706f2543Smrg { 1406706f2543Smrg nHosts++; 1407706f2543Smrg n += pad_to_int32(host->len) + sizeof(xHostEntry); 1408706f2543Smrg /* Could check for INT_MAX, but in reality having more than 1mb of 1409706f2543Smrg hostnames in the access list is ridiculous */ 1410706f2543Smrg if (n >= 1048576) 1411706f2543Smrg break; 1412706f2543Smrg } 1413706f2543Smrg if (n) 1414706f2543Smrg { 1415706f2543Smrg *data = ptr = malloc(n); 1416706f2543Smrg if (!ptr) 1417706f2543Smrg { 1418706f2543Smrg return BadAlloc; 1419706f2543Smrg } 1420706f2543Smrg for (host = validhosts; host; host = host->next) 1421706f2543Smrg { 1422706f2543Smrg len = host->len; 1423706f2543Smrg if ((ptr + sizeof(xHostEntry) + len) > ((unsigned char *) *data + n)) 1424706f2543Smrg break; 1425706f2543Smrg ((xHostEntry *)ptr)->family = host->family; 1426706f2543Smrg ((xHostEntry *)ptr)->length = len; 1427706f2543Smrg ptr += sizeof(xHostEntry); 1428706f2543Smrg acopy (host->addr, ptr, len); 1429706f2543Smrg ptr += pad_to_int32(len); 1430706f2543Smrg } 1431706f2543Smrg } else { 1432706f2543Smrg *data = NULL; 1433706f2543Smrg } 1434706f2543Smrg *pnHosts = nHosts; 1435706f2543Smrg *pLen = n; 1436706f2543Smrg return Success; 1437706f2543Smrg} 1438706f2543Smrg 1439706f2543Smrg/* Check for valid address family and length, and return address length. */ 1440706f2543Smrg 1441706f2543Smrg/*ARGSUSED*/ 1442706f2543Smrgstatic int 1443706f2543SmrgCheckAddr ( 1444706f2543Smrg int family, 1445706f2543Smrg const void * pAddr, 1446706f2543Smrg unsigned length) 1447706f2543Smrg{ 1448706f2543Smrg int len; 1449706f2543Smrg 1450706f2543Smrg switch (family) 1451706f2543Smrg { 1452706f2543Smrg#if defined(TCPCONN) || defined(STREAMSCONN) 1453706f2543Smrg case FamilyInternet: 1454706f2543Smrg if (length == sizeof (struct in_addr)) 1455706f2543Smrg len = length; 1456706f2543Smrg else 1457706f2543Smrg len = -1; 1458706f2543Smrg break; 1459706f2543Smrg#if defined(IPv6) && defined(AF_INET6) 1460706f2543Smrg case FamilyInternet6: 1461706f2543Smrg if (length == sizeof (struct in6_addr)) 1462706f2543Smrg len = length; 1463706f2543Smrg else 1464706f2543Smrg len = -1; 1465706f2543Smrg break; 1466706f2543Smrg#endif 1467706f2543Smrg#endif 1468706f2543Smrg case FamilyServerInterpreted: 1469706f2543Smrg len = siCheckAddr(pAddr, length); 1470706f2543Smrg break; 1471706f2543Smrg default: 1472706f2543Smrg len = -1; 1473706f2543Smrg } 1474706f2543Smrg return len; 1475706f2543Smrg} 1476706f2543Smrg 1477706f2543Smrg/* Check if a host is not in the access control list. 1478706f2543Smrg * Returns 1 if host is invalid, 0 if we've found it. */ 1479706f2543Smrg 1480706f2543Smrgint 1481706f2543SmrgInvalidHost ( 1482706f2543Smrg register struct sockaddr *saddr, 1483706f2543Smrg int len, 1484706f2543Smrg ClientPtr client) 1485706f2543Smrg{ 1486706f2543Smrg int family; 1487706f2543Smrg pointer addr; 1488706f2543Smrg register HOST *selfhost, *host; 1489706f2543Smrg 1490706f2543Smrg if (!AccessEnabled) /* just let them in */ 1491706f2543Smrg return 0; 1492706f2543Smrg family = ConvertAddr (saddr, &len, (pointer *)&addr); 1493706f2543Smrg if (family == -1) 1494706f2543Smrg return 1; 1495706f2543Smrg if (family == FamilyLocal) 1496706f2543Smrg { 1497706f2543Smrg if (!LocalHostEnabled) 1498706f2543Smrg { 1499706f2543Smrg /* 1500706f2543Smrg * check to see if any local address is enabled. This 1501706f2543Smrg * implicitly enables local connections. 1502706f2543Smrg */ 1503706f2543Smrg for (selfhost = selfhosts; selfhost; selfhost=selfhost->next) 1504706f2543Smrg { 1505706f2543Smrg for (host = validhosts; host; host=host->next) 1506706f2543Smrg { 1507706f2543Smrg if (addrEqual (selfhost->family, selfhost->addr, 1508706f2543Smrg selfhost->len, host)) 1509706f2543Smrg return 0; 1510706f2543Smrg } 1511706f2543Smrg } 1512706f2543Smrg } else 1513706f2543Smrg return 0; 1514706f2543Smrg } 1515706f2543Smrg for (host = validhosts; host; host = host->next) 1516706f2543Smrg { 1517706f2543Smrg if (host->family == FamilyServerInterpreted) { 1518706f2543Smrg if (siAddrMatch (family, addr, len, host, client)) { 1519706f2543Smrg return 0; 1520706f2543Smrg } 1521706f2543Smrg } else { 1522706f2543Smrg if (addrEqual (family, addr, len, host)) 1523706f2543Smrg return 0; 1524706f2543Smrg } 1525706f2543Smrg 1526706f2543Smrg } 1527706f2543Smrg return 1; 1528706f2543Smrg} 1529706f2543Smrg 1530706f2543Smrgstatic int 1531706f2543SmrgConvertAddr ( 1532706f2543Smrg register struct sockaddr *saddr, 1533706f2543Smrg int *len, 1534706f2543Smrg pointer *addr) 1535706f2543Smrg{ 1536706f2543Smrg if (*len == 0) 1537706f2543Smrg return FamilyLocal; 1538706f2543Smrg switch (saddr->sa_family) 1539706f2543Smrg { 1540706f2543Smrg case AF_UNSPEC: 1541706f2543Smrg#if defined(UNIXCONN) || defined(LOCALCONN) 1542706f2543Smrg case AF_UNIX: 1543706f2543Smrg#endif 1544706f2543Smrg return FamilyLocal; 1545706f2543Smrg#if defined(TCPCONN) || defined(STREAMSCONN) 1546706f2543Smrg case AF_INET: 1547706f2543Smrg#ifdef WIN32 1548706f2543Smrg if (16777343 == *(long*)&((struct sockaddr_in *) saddr)->sin_addr) 1549706f2543Smrg return FamilyLocal; 1550706f2543Smrg#endif 1551706f2543Smrg *len = sizeof (struct in_addr); 1552706f2543Smrg *addr = (pointer) &(((struct sockaddr_in *) saddr)->sin_addr); 1553706f2543Smrg return FamilyInternet; 1554706f2543Smrg#if defined(IPv6) && defined(AF_INET6) 1555706f2543Smrg case AF_INET6: 1556706f2543Smrg { 1557706f2543Smrg struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *) saddr; 1558706f2543Smrg if (IN6_IS_ADDR_V4MAPPED(&(saddr6->sin6_addr))) { 1559706f2543Smrg *len = sizeof (struct in_addr); 1560706f2543Smrg *addr = (pointer) &(saddr6->sin6_addr.s6_addr[12]); 1561706f2543Smrg return FamilyInternet; 1562706f2543Smrg } else { 1563706f2543Smrg *len = sizeof (struct in6_addr); 1564706f2543Smrg *addr = (pointer) &(saddr6->sin6_addr); 1565706f2543Smrg return FamilyInternet6; 1566706f2543Smrg } 1567706f2543Smrg } 1568706f2543Smrg#endif 1569706f2543Smrg#endif 1570706f2543Smrg default: 1571706f2543Smrg return -1; 1572706f2543Smrg } 1573706f2543Smrg} 1574706f2543Smrg 1575706f2543Smrgint 1576706f2543SmrgChangeAccessControl( 1577706f2543Smrg ClientPtr client, 1578706f2543Smrg int fEnabled) 1579706f2543Smrg{ 1580706f2543Smrg int rc = AuthorizedClient(client); 1581706f2543Smrg if (rc != Success) 1582706f2543Smrg return rc; 1583706f2543Smrg AccessEnabled = fEnabled; 1584706f2543Smrg return Success; 1585706f2543Smrg} 1586706f2543Smrg 1587706f2543Smrg/* returns FALSE if xhost + in effect, else TRUE */ 1588706f2543Smrgint 1589706f2543SmrgGetAccessControl(void) 1590706f2543Smrg{ 1591706f2543Smrg return AccessEnabled; 1592706f2543Smrg} 1593706f2543Smrg 1594706f2543Smrg/***************************************************************************** 1595706f2543Smrg * FamilyServerInterpreted host entry implementation 1596706f2543Smrg * 1597706f2543Smrg * Supports an extensible system of host types which the server can interpret 1598706f2543Smrg * See the IPv6 extensions to the X11 protocol spec for the definition. 1599706f2543Smrg * 1600706f2543Smrg * Currently supported schemes: 1601706f2543Smrg * 1602706f2543Smrg * hostname - hostname as defined in IETF RFC 2396 1603706f2543Smrg * ipv6 - IPv6 literal address as defined in IETF RFC's 3513 and <TBD> 1604706f2543Smrg * 1605706f2543Smrg * See xc/doc/specs/SIAddresses for formal definitions of each type. 1606706f2543Smrg */ 1607706f2543Smrg 1608706f2543Smrg/* These definitions and the siTypeAdd function could be exported in the 1609706f2543Smrg * future to enable loading additional host types, but that was not done for 1610706f2543Smrg * the initial implementation. 1611706f2543Smrg */ 1612706f2543Smrgtypedef Bool (*siAddrMatchFunc)(int family, pointer addr, int len, 1613706f2543Smrg const char *siAddr, int siAddrlen, ClientPtr client, void *siTypePriv); 1614706f2543Smrgtypedef int (*siCheckAddrFunc)(const char *addrString, int length, 1615706f2543Smrg void *siTypePriv); 1616706f2543Smrg 1617706f2543Smrgstruct siType { 1618706f2543Smrg struct siType * next; 1619706f2543Smrg const char * typeName; 1620706f2543Smrg siAddrMatchFunc addrMatch; 1621706f2543Smrg siCheckAddrFunc checkAddr; 1622706f2543Smrg void * typePriv; /* Private data for type routines */ 1623706f2543Smrg}; 1624706f2543Smrg 1625706f2543Smrgstatic struct siType *siTypeList; 1626706f2543Smrg 1627706f2543Smrgstatic int 1628706f2543SmrgsiTypeAdd(const char *typeName, siAddrMatchFunc addrMatch, 1629706f2543Smrg siCheckAddrFunc checkAddr, void *typePriv) 1630706f2543Smrg{ 1631706f2543Smrg struct siType *s, *p; 1632706f2543Smrg 1633706f2543Smrg if ((typeName == NULL) || (addrMatch == NULL) || (checkAddr == NULL)) 1634706f2543Smrg return BadValue; 1635706f2543Smrg 1636706f2543Smrg for (s = siTypeList, p = NULL; s != NULL ; p = s, s = s->next) { 1637706f2543Smrg if (strcmp(typeName, s->typeName) == 0) { 1638706f2543Smrg s->addrMatch = addrMatch; 1639706f2543Smrg s->checkAddr = checkAddr; 1640706f2543Smrg s->typePriv = typePriv; 1641706f2543Smrg return Success; 1642706f2543Smrg } 1643706f2543Smrg } 1644706f2543Smrg 1645706f2543Smrg s = malloc(sizeof(struct siType)); 1646706f2543Smrg if (s == NULL) 1647706f2543Smrg return BadAlloc; 1648706f2543Smrg 1649706f2543Smrg if (p == NULL) 1650706f2543Smrg siTypeList = s; 1651706f2543Smrg else 1652706f2543Smrg p->next = s; 1653706f2543Smrg 1654706f2543Smrg s->next = NULL; 1655706f2543Smrg s->typeName = typeName; 1656706f2543Smrg s->addrMatch = addrMatch; 1657706f2543Smrg s->checkAddr = checkAddr; 1658706f2543Smrg s->typePriv = typePriv; 1659706f2543Smrg return Success; 1660706f2543Smrg} 1661706f2543Smrg 1662706f2543Smrg/* Checks to see if a host matches a server-interpreted host entry */ 1663706f2543Smrgstatic Bool 1664706f2543SmrgsiAddrMatch(int family, pointer addr, int len, HOST *host, ClientPtr client) 1665706f2543Smrg{ 1666706f2543Smrg Bool matches = FALSE; 1667706f2543Smrg struct siType *s; 1668706f2543Smrg const char *valueString; 1669706f2543Smrg int addrlen; 1670706f2543Smrg 1671706f2543Smrg valueString = (const char *) memchr(host->addr, '\0', host->len); 1672706f2543Smrg if (valueString != NULL) { 1673706f2543Smrg for (s = siTypeList; s != NULL ; s = s->next) { 1674706f2543Smrg if (strcmp((char *) host->addr, s->typeName) == 0) { 1675706f2543Smrg addrlen = host->len - (strlen((char *)host->addr) + 1); 1676706f2543Smrg matches = s->addrMatch(family, addr, len, 1677706f2543Smrg valueString + 1, addrlen, client, s->typePriv); 1678706f2543Smrg break; 1679706f2543Smrg } 1680706f2543Smrg } 1681706f2543Smrg#ifdef FAMILY_SI_DEBUG 1682706f2543Smrg ErrorF( 1683706f2543Smrg "Xserver: siAddrMatch(): type = %s, value = %*.*s -- %s\n", 1684706f2543Smrg host->addr, addrlen, addrlen, valueString + 1, 1685706f2543Smrg (matches) ? "accepted" : "rejected"); 1686706f2543Smrg#endif 1687706f2543Smrg } 1688706f2543Smrg return matches; 1689706f2543Smrg} 1690706f2543Smrg 1691706f2543Smrgstatic int 1692706f2543SmrgsiCheckAddr(const char *addrString, int length) 1693706f2543Smrg{ 1694706f2543Smrg const char *valueString; 1695706f2543Smrg int addrlen, typelen; 1696706f2543Smrg int len = -1; 1697706f2543Smrg struct siType *s; 1698706f2543Smrg 1699706f2543Smrg /* Make sure there is a \0 byte inside the specified length 1700706f2543Smrg to separate the address type from the address value. */ 1701706f2543Smrg valueString = (const char *) memchr(addrString, '\0', length); 1702706f2543Smrg if (valueString != NULL) { 1703706f2543Smrg /* Make sure the first string is a recognized address type, 1704706f2543Smrg * and the second string is a valid address of that type. 1705706f2543Smrg */ 1706706f2543Smrg typelen = strlen(addrString) + 1; 1707706f2543Smrg addrlen = length - typelen; 1708706f2543Smrg 1709706f2543Smrg for (s = siTypeList; s != NULL ; s = s->next) { 1710706f2543Smrg if (strcmp(addrString, s->typeName) == 0) { 1711706f2543Smrg len = s->checkAddr(valueString + 1, addrlen, s->typePriv); 1712706f2543Smrg if (len >= 0) { 1713706f2543Smrg len += typelen; 1714706f2543Smrg } 1715706f2543Smrg break; 1716706f2543Smrg } 1717706f2543Smrg } 1718706f2543Smrg#ifdef FAMILY_SI_DEBUG 1719706f2543Smrg { 1720706f2543Smrg const char *resultMsg; 1721706f2543Smrg 1722706f2543Smrg if (s == NULL) { 1723706f2543Smrg resultMsg = "type not registered"; 1724706f2543Smrg } else { 1725706f2543Smrg if (len == -1) 1726706f2543Smrg resultMsg = "rejected"; 1727706f2543Smrg else 1728706f2543Smrg resultMsg = "accepted"; 1729706f2543Smrg } 1730706f2543Smrg 1731706f2543Smrg ErrorF("Xserver: siCheckAddr(): type = %s, value = %*.*s, len = %d -- %s\n", 1732706f2543Smrg addrString, addrlen, addrlen, valueString + 1, len, resultMsg); 1733706f2543Smrg } 1734706f2543Smrg#endif 1735706f2543Smrg } 1736706f2543Smrg return len; 1737706f2543Smrg} 1738706f2543Smrg 1739706f2543Smrg 1740706f2543Smrg/*** 1741706f2543Smrg * Hostname server-interpreted host type 1742706f2543Smrg * 1743706f2543Smrg * Stored as hostname string, explicitly defined to be resolved ONLY 1744706f2543Smrg * at access check time, to allow for hosts with dynamic addresses 1745706f2543Smrg * but static hostnames, such as found in some DHCP & mobile setups. 1746706f2543Smrg * 1747706f2543Smrg * Hostname must conform to IETF RFC 2396 sec. 3.2.2, which defines it as: 1748706f2543Smrg * hostname = *( domainlabel "." ) toplabel [ "." ] 1749706f2543Smrg * domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum 1750706f2543Smrg * toplabel = alpha | alpha *( alphanum | "-" ) alphanum 1751706f2543Smrg */ 1752706f2543Smrg 1753706f2543Smrg#ifdef NI_MAXHOST 1754706f2543Smrg# define SI_HOSTNAME_MAXLEN NI_MAXHOST 1755706f2543Smrg#else 1756706f2543Smrg# ifdef MAXHOSTNAMELEN 1757706f2543Smrg# define SI_HOSTNAME_MAXLEN MAXHOSTNAMELEN 1758706f2543Smrg# else 1759706f2543Smrg# define SI_HOSTNAME_MAXLEN 256 1760706f2543Smrg# endif 1761706f2543Smrg#endif 1762706f2543Smrg 1763706f2543Smrgstatic Bool 1764706f2543SmrgsiHostnameAddrMatch(int family, pointer addr, int len, 1765706f2543Smrg const char *siAddr, int siAddrLen, ClientPtr client, void *typePriv) 1766706f2543Smrg{ 1767706f2543Smrg Bool res = FALSE; 1768706f2543Smrg 1769706f2543Smrg/* Currently only supports checking against IPv4 & IPv6 connections, but 1770706f2543Smrg * support for other address families, such as DECnet, could be added if 1771706f2543Smrg * desired. 1772706f2543Smrg */ 1773706f2543Smrg#if defined(IPv6) && defined(AF_INET6) 1774706f2543Smrg if ((family == FamilyInternet) || (family == FamilyInternet6)) { 1775706f2543Smrg char hostname[SI_HOSTNAME_MAXLEN]; 1776706f2543Smrg struct addrinfo *addresses; 1777706f2543Smrg struct addrinfo *a; 1778706f2543Smrg int f, hostaddrlen; 1779706f2543Smrg pointer hostaddr; 1780706f2543Smrg 1781706f2543Smrg if (siAddrLen >= sizeof(hostname)) 1782706f2543Smrg return FALSE; 1783706f2543Smrg 1784706f2543Smrg strncpy(hostname, siAddr, siAddrLen); 1785706f2543Smrg hostname[siAddrLen] = '\0'; 1786706f2543Smrg 1787706f2543Smrg if (getaddrinfo(hostname, NULL, NULL, &addresses) == 0) { 1788706f2543Smrg for (a = addresses ; a != NULL ; a = a->ai_next) { 1789706f2543Smrg hostaddrlen = a->ai_addrlen; 1790706f2543Smrg f = ConvertAddr(a->ai_addr,&hostaddrlen,&hostaddr); 1791706f2543Smrg if ((f == family) && (len == hostaddrlen) && 1792706f2543Smrg (acmp (addr, hostaddr, len) == 0) ) { 1793706f2543Smrg res = TRUE; 1794706f2543Smrg break; 1795706f2543Smrg } 1796706f2543Smrg } 1797706f2543Smrg freeaddrinfo(addresses); 1798706f2543Smrg } 1799706f2543Smrg } 1800706f2543Smrg#else /* IPv6 not supported, use gethostbyname instead for IPv4 */ 1801706f2543Smrg if (family == FamilyInternet) { 1802706f2543Smrg register struct hostent *hp; 1803706f2543Smrg#ifdef XTHREADS_NEEDS_BYNAMEPARAMS 1804706f2543Smrg _Xgethostbynameparams hparams; 1805706f2543Smrg#endif 1806706f2543Smrg char hostname[SI_HOSTNAME_MAXLEN]; 1807706f2543Smrg int f, hostaddrlen; 1808706f2543Smrg pointer hostaddr; 1809706f2543Smrg const char **addrlist; 1810706f2543Smrg 1811706f2543Smrg if (siAddrLen >= sizeof(hostname)) 1812706f2543Smrg return FALSE; 1813706f2543Smrg 1814706f2543Smrg strncpy(hostname, siAddr, siAddrLen); 1815706f2543Smrg hostname[siAddrLen] = '\0'; 1816706f2543Smrg 1817706f2543Smrg if ((hp = _XGethostbyname(hostname, hparams)) != NULL) { 1818706f2543Smrg#ifdef h_addr /* new 4.3bsd version of gethostent */ 1819706f2543Smrg /* iterate over the addresses */ 1820706f2543Smrg for (addrlist = hp->h_addr_list; *addrlist; addrlist++) 1821706f2543Smrg#else 1822706f2543Smrg addrlist = &hp->h_addr; 1823706f2543Smrg#endif 1824706f2543Smrg { 1825706f2543Smrg struct sockaddr_in sin; 1826706f2543Smrg 1827706f2543Smrg sin.sin_family = hp->h_addrtype; 1828706f2543Smrg acopy ( *addrlist, &(sin.sin_addr), hp->h_length); 1829706f2543Smrg hostaddrlen = sizeof(sin); 1830706f2543Smrg f = ConvertAddr ((struct sockaddr *)&sin, 1831706f2543Smrg &hostaddrlen, &hostaddr); 1832706f2543Smrg if ((f == family) && (len == hostaddrlen) && 1833706f2543Smrg (acmp (addr, hostaddr, len) == 0) ) { 1834706f2543Smrg res = TRUE; 1835706f2543Smrg break; 1836706f2543Smrg } 1837706f2543Smrg } 1838706f2543Smrg } 1839706f2543Smrg } 1840706f2543Smrg#endif 1841706f2543Smrg return res; 1842706f2543Smrg} 1843706f2543Smrg 1844706f2543Smrg 1845706f2543Smrgstatic int 1846706f2543SmrgsiHostnameCheckAddr(const char *valueString, int length, void *typePriv) 1847706f2543Smrg{ 1848706f2543Smrg /* Check conformance of hostname to RFC 2396 sec. 3.2.2 definition. 1849706f2543Smrg * We do not use ctype functions here to avoid locale-specific 1850706f2543Smrg * character sets. Hostnames must be pure ASCII. 1851706f2543Smrg */ 1852706f2543Smrg int len = length; 1853706f2543Smrg int i; 1854706f2543Smrg Bool dotAllowed = FALSE; 1855706f2543Smrg Bool dashAllowed = FALSE; 1856706f2543Smrg 1857706f2543Smrg if ((length <= 0) || (length >= SI_HOSTNAME_MAXLEN)) { 1858706f2543Smrg len = -1; 1859706f2543Smrg } else { 1860706f2543Smrg for (i = 0; i < length; i++) { 1861706f2543Smrg char c = valueString[i]; 1862706f2543Smrg 1863706f2543Smrg if (c == 0x2E) { /* '.' */ 1864706f2543Smrg if (dotAllowed == FALSE) { 1865706f2543Smrg len = -1; 1866706f2543Smrg break; 1867706f2543Smrg } else { 1868706f2543Smrg dotAllowed = FALSE; 1869706f2543Smrg dashAllowed = FALSE; 1870706f2543Smrg } 1871706f2543Smrg } else if (c == 0x2D) { /* '-' */ 1872706f2543Smrg if (dashAllowed == FALSE) { 1873706f2543Smrg len = -1; 1874706f2543Smrg break; 1875706f2543Smrg } else { 1876706f2543Smrg dotAllowed = FALSE; 1877706f2543Smrg } 1878706f2543Smrg } else if (((c >= 0x30) && (c <= 0x3A)) /* 0-9 */ || 1879706f2543Smrg ((c >= 0x61) && (c <= 0x7A)) /* a-z */ || 1880706f2543Smrg ((c >= 0x41) && (c <= 0x5A)) /* A-Z */) { 1881706f2543Smrg dotAllowed = TRUE; 1882706f2543Smrg dashAllowed = TRUE; 1883706f2543Smrg } else { /* Invalid character */ 1884706f2543Smrg len = -1; 1885706f2543Smrg break; 1886706f2543Smrg } 1887706f2543Smrg } 1888706f2543Smrg } 1889706f2543Smrg return len; 1890706f2543Smrg} 1891706f2543Smrg 1892706f2543Smrg#if defined(IPv6) && defined(AF_INET6) 1893706f2543Smrg/*** 1894706f2543Smrg * "ipv6" server interpreted type 1895706f2543Smrg * 1896706f2543Smrg * Currently supports only IPv6 literal address as specified in IETF RFC 3513 1897706f2543Smrg * 1898706f2543Smrg * Once draft-ietf-ipv6-scoping-arch-00.txt becomes an RFC, support will be 1899706f2543Smrg * added for the scoped address format it specifies. 1900706f2543Smrg */ 1901706f2543Smrg 1902706f2543Smrg/* Maximum length of an IPv6 address string - increase when adding support 1903706f2543Smrg * for scoped address qualifiers. Includes room for trailing NUL byte. 1904706f2543Smrg */ 1905706f2543Smrg#define SI_IPv6_MAXLEN INET6_ADDRSTRLEN 1906706f2543Smrg 1907706f2543Smrgstatic Bool 1908706f2543SmrgsiIPv6AddrMatch(int family, pointer addr, int len, 1909706f2543Smrg const char *siAddr, int siAddrlen, ClientPtr client, void *typePriv) 1910706f2543Smrg{ 1911706f2543Smrg struct in6_addr addr6; 1912706f2543Smrg char addrbuf[SI_IPv6_MAXLEN]; 1913706f2543Smrg 1914706f2543Smrg if ((family != FamilyInternet6) || (len != sizeof(addr6))) 1915706f2543Smrg return FALSE; 1916706f2543Smrg 1917706f2543Smrg memcpy(addrbuf, siAddr, siAddrlen); 1918706f2543Smrg addrbuf[siAddrlen] = '\0'; 1919706f2543Smrg 1920706f2543Smrg if (inet_pton(AF_INET6, addrbuf, &addr6) != 1) { 1921706f2543Smrg perror("inet_pton"); 1922706f2543Smrg return FALSE; 1923706f2543Smrg } 1924706f2543Smrg 1925706f2543Smrg if (memcmp(addr, &addr6, len) == 0) { 1926706f2543Smrg return TRUE; 1927706f2543Smrg } else { 1928706f2543Smrg return FALSE; 1929706f2543Smrg } 1930706f2543Smrg} 1931706f2543Smrg 1932706f2543Smrgstatic int 1933706f2543SmrgsiIPv6CheckAddr(const char *addrString, int length, void *typePriv) 1934706f2543Smrg{ 1935706f2543Smrg int len; 1936706f2543Smrg 1937706f2543Smrg /* Minimum length is 3 (smallest legal address is "::1") */ 1938706f2543Smrg if (length < 3) { 1939706f2543Smrg /* Address is too short! */ 1940706f2543Smrg len = -1; 1941706f2543Smrg } else if (length >= SI_IPv6_MAXLEN) { 1942706f2543Smrg /* Address is too long! */ 1943706f2543Smrg len = -1; 1944706f2543Smrg } else { 1945706f2543Smrg /* Assume inet_pton is sufficient validation */ 1946706f2543Smrg struct in6_addr addr6; 1947706f2543Smrg char addrbuf[SI_IPv6_MAXLEN]; 1948706f2543Smrg 1949706f2543Smrg memcpy(addrbuf, addrString, length); 1950706f2543Smrg addrbuf[length] = '\0'; 1951706f2543Smrg 1952706f2543Smrg if (inet_pton(AF_INET6, addrbuf, &addr6) != 1) { 1953706f2543Smrg perror("inet_pton"); 1954706f2543Smrg len = -1; 1955706f2543Smrg } else { 1956706f2543Smrg len = length; 1957706f2543Smrg } 1958706f2543Smrg } 1959706f2543Smrg return len; 1960706f2543Smrg} 1961706f2543Smrg#endif /* IPv6 */ 1962706f2543Smrg 1963706f2543Smrg#if !defined(NO_LOCAL_CLIENT_CRED) 1964706f2543Smrg/*** 1965706f2543Smrg * "localuser" & "localgroup" server interpreted types 1966706f2543Smrg * 1967706f2543Smrg * Allows local connections from a given local user or group 1968706f2543Smrg */ 1969706f2543Smrg 1970706f2543Smrg#include <pwd.h> 1971706f2543Smrg#include <grp.h> 1972706f2543Smrg 1973706f2543Smrg#define LOCAL_USER 1 1974706f2543Smrg#define LOCAL_GROUP 2 1975706f2543Smrg 1976706f2543Smrgtypedef struct { 1977706f2543Smrg int credType; 1978706f2543Smrg} siLocalCredPrivRec, *siLocalCredPrivPtr; 1979706f2543Smrg 1980706f2543Smrgstatic siLocalCredPrivRec siLocalUserPriv = { LOCAL_USER }; 1981706f2543Smrgstatic siLocalCredPrivRec siLocalGroupPriv = { LOCAL_GROUP }; 1982706f2543Smrg 1983706f2543Smrgstatic Bool 1984706f2543SmrgsiLocalCredGetId(const char *addr, int len, siLocalCredPrivPtr lcPriv, int *id) 1985706f2543Smrg{ 1986706f2543Smrg Bool parsedOK = FALSE; 1987706f2543Smrg char *addrbuf = malloc(len + 1); 1988706f2543Smrg 1989706f2543Smrg if (addrbuf == NULL) { 1990706f2543Smrg return FALSE; 1991706f2543Smrg } 1992706f2543Smrg 1993706f2543Smrg memcpy(addrbuf, addr, len); 1994706f2543Smrg addrbuf[len] = '\0'; 1995706f2543Smrg 1996706f2543Smrg if (addr[0] == '#') { /* numeric id */ 1997706f2543Smrg char *cp; 1998706f2543Smrg errno = 0; 1999706f2543Smrg *id = strtol(addrbuf + 1, &cp, 0); 2000706f2543Smrg if ((errno == 0) && (cp != (addrbuf+1))) { 2001706f2543Smrg parsedOK = TRUE; 2002706f2543Smrg } 2003706f2543Smrg } else { /* non-numeric name */ 2004706f2543Smrg if (lcPriv->credType == LOCAL_USER) { 2005706f2543Smrg struct passwd *pw = getpwnam(addrbuf); 2006706f2543Smrg 2007706f2543Smrg if (pw != NULL) { 2008706f2543Smrg *id = (int) pw->pw_uid; 2009706f2543Smrg parsedOK = TRUE; 2010706f2543Smrg } 2011706f2543Smrg } else { /* group */ 2012706f2543Smrg struct group *gr = getgrnam(addrbuf); 2013706f2543Smrg 2014706f2543Smrg if (gr != NULL) { 2015706f2543Smrg *id = (int) gr->gr_gid; 2016706f2543Smrg parsedOK = TRUE; 2017706f2543Smrg } 2018706f2543Smrg } 2019706f2543Smrg } 2020706f2543Smrg 2021706f2543Smrg free(addrbuf); 2022706f2543Smrg return parsedOK; 2023706f2543Smrg} 2024706f2543Smrg 2025706f2543Smrgstatic Bool 2026706f2543SmrgsiLocalCredAddrMatch(int family, pointer addr, int len, 2027706f2543Smrg const char *siAddr, int siAddrlen, ClientPtr client, void *typePriv) 2028706f2543Smrg{ 2029706f2543Smrg int siAddrId; 2030706f2543Smrg LocalClientCredRec *lcc; 2031706f2543Smrg siLocalCredPrivPtr lcPriv = (siLocalCredPrivPtr) typePriv; 2032706f2543Smrg 2033706f2543Smrg if (GetLocalClientCreds(client, &lcc) == -1) { 2034706f2543Smrg return FALSE; 2035706f2543Smrg } 2036706f2543Smrg 2037706f2543Smrg#ifdef HAVE_GETZONEID /* Ensure process is in the same zone */ 2038706f2543Smrg if ((lcc->fieldsSet & LCC_ZID_SET) && (lcc->zoneid != getzoneid())) { 2039706f2543Smrg FreeLocalClientCreds(lcc); 2040706f2543Smrg return FALSE; 2041706f2543Smrg } 2042706f2543Smrg#endif 2043706f2543Smrg 2044706f2543Smrg if (siLocalCredGetId(siAddr, siAddrlen, lcPriv, &siAddrId) == FALSE) { 2045706f2543Smrg FreeLocalClientCreds(lcc); 2046706f2543Smrg return FALSE; 2047706f2543Smrg } 2048706f2543Smrg 2049706f2543Smrg if (lcPriv->credType == LOCAL_USER) { 2050706f2543Smrg if ((lcc->fieldsSet & LCC_UID_SET) && (lcc->euid == siAddrId)) { 2051706f2543Smrg FreeLocalClientCreds(lcc); 2052706f2543Smrg return TRUE; 2053706f2543Smrg } 2054706f2543Smrg } else { 2055706f2543Smrg if ((lcc->fieldsSet & LCC_GID_SET) && (lcc->egid == siAddrId)) { 2056706f2543Smrg FreeLocalClientCreds(lcc); 2057706f2543Smrg return TRUE; 2058706f2543Smrg } 2059706f2543Smrg if (lcc->pSuppGids != NULL) { 2060706f2543Smrg int i; 2061706f2543Smrg 2062706f2543Smrg for (i = 0 ; i < lcc->nSuppGids; i++) { 2063706f2543Smrg if (lcc->pSuppGids[i] == siAddrId) { 2064706f2543Smrg FreeLocalClientCreds(lcc); 2065706f2543Smrg return TRUE; 2066706f2543Smrg } 2067706f2543Smrg } 2068706f2543Smrg } 2069706f2543Smrg } 2070706f2543Smrg FreeLocalClientCreds(lcc); 2071706f2543Smrg return FALSE; 2072706f2543Smrg} 2073706f2543Smrg 2074706f2543Smrgstatic int 2075706f2543SmrgsiLocalCredCheckAddr(const char *addrString, int length, void *typePriv) 2076706f2543Smrg{ 2077706f2543Smrg int len = length; 2078706f2543Smrg int id; 2079706f2543Smrg 2080706f2543Smrg if (siLocalCredGetId(addrString, length, 2081706f2543Smrg (siLocalCredPrivPtr)typePriv, &id) == FALSE) { 2082706f2543Smrg len = -1; 2083706f2543Smrg } 2084706f2543Smrg return len; 2085706f2543Smrg} 2086706f2543Smrg#endif /* localuser */ 2087706f2543Smrg 2088706f2543Smrgstatic void 2089706f2543SmrgsiTypesInitialize(void) 2090706f2543Smrg{ 2091706f2543Smrg siTypeAdd("hostname", siHostnameAddrMatch, siHostnameCheckAddr, NULL); 2092706f2543Smrg#if defined(IPv6) && defined(AF_INET6) 2093706f2543Smrg siTypeAdd("ipv6", siIPv6AddrMatch, siIPv6CheckAddr, NULL); 2094706f2543Smrg#endif 2095706f2543Smrg#if !defined(NO_LOCAL_CLIENT_CRED) 2096706f2543Smrg siTypeAdd("localuser", siLocalCredAddrMatch, siLocalCredCheckAddr, 2097706f2543Smrg &siLocalUserPriv); 2098706f2543Smrg siTypeAdd("localgroup", siLocalCredAddrMatch, siLocalCredCheckAddr, 2099706f2543Smrg &siLocalGroupPriv); 2100706f2543Smrg#endif 2101706f2543Smrg} 2102