123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953 |
- /***********************************************************
- Copyright 1987, 1998 The Open Group
- Copyright 2004 Sun Microsystems, Inc.
- All rights reserved.
- Permission is hereby granted, free of charge, to any person obtaining a
- copy of this software and associated documentation files (the
- "Software"), to deal in the Software without restriction, including
- without limitation the rights to use, copy, modify, merge, publish,
- distribute, and/or sell copies of the Software, and to permit persons
- to whom the Software is furnished to do so, provided that the above
- copyright notice(s) and this permission notice appear in all copies of
- the Software and that both the above copyright notice(s) and this
- permission notice appear in supporting documentation.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
- OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
- HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
- INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
- FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
- NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
- WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- Except as contained in this notice, the name of a copyright holder
- shall not be used in advertising or otherwise to promote the sale, use
- or other dealings in this Software without prior written authorization
- of the copyright holder.
- X Window System is a trademark of The Open Group.
- Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
- All Rights Reserved
- Permission to use, copy, modify, and distribute this software and its
- documentation for any purpose and without fee is hereby granted,
- provided that the above copyright notice appear in all copies and that
- both that copyright notice and this permission notice appear in
- supporting documentation, and that the name of Digital not be
- used in advertising or publicity pertaining to distribution of the
- software without specific, written prior permission.
- DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
- ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
- DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
- ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
- WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
- ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- SOFTWARE.
- ******************************************************************/
- #ifdef HAVE_DIX_CONFIG_H
- #include <dix-config.h>
- #endif
- #include <stdio.h>
- #include <stdlib.h>
- #define XSERV_t
- #define TRANS_SERVER
- #define TRANS_REOPEN
- #include <X11/Xtrans/Xtrans.h>
- #include <X11/Xauth.h>
- #include <X11/X.h>
- #include <X11/Xproto.h>
- #include "misc.h"
- #include "site.h"
- #include <errno.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <sys/ioctl.h>
- #include <ctype.h>
- #if defined(TCPCONN)
- #include <netinet/in.h>
- #endif /* TCPCONN */
- #ifdef HAS_GETPEERUCRED
- # include <ucred.h>
- #endif
- #if (defined(SYSV) && defined(i386)) || defined(__GNU__)
- # include <sys/utsname.h>
- #endif
- #ifdef __GNU__
- #undef SIOCGIFCONF
- #include <netdb.h>
- #else /*!__GNU__*/
- # include <net/if.h>
- #endif /*__GNU__ */
- #include <netdb.h>
- #ifdef CSRG_BASED
- #include <sys/param.h>
- #if (BSD >= 199103)
- #define VARIABLE_IFREQ
- #endif
- #endif
- #ifdef BSD44SOCKETS
- #ifndef VARIABLE_IFREQ
- #define VARIABLE_IFREQ
- #endif
- #endif
- #ifdef HAS_GETIFADDRS
- #include <ifaddrs.h>
- #endif
- /* Solaris provides an extended interface SIOCGLIFCONF. Other systems
- * may have this as well, but the code has only been tested on Solaris
- * so far, so we only enable it there. Other platforms may be added as
- * needed.
- *
- * Test for Solaris commented out -- TSI @ UQV 2003.06.13
- */
- #ifdef SIOCGLIFCONF
- /* #if defined(sun) */
- #define USE_SIOCGLIFCONF
- /* #endif */
- #endif
- #ifndef PATH_MAX
- #include <sys/param.h>
- #ifndef PATH_MAX
- #ifdef MAXPATHLEN
- #define PATH_MAX MAXPATHLEN
- #else
- #define PATH_MAX 1024
- #endif
- #endif
- #endif
- #define X_INCLUDE_NETDB_H
- #include <X11/Xos_r.h>
- #include "dixstruct.h"
- #include "osdep.h"
- #ifndef PATH_MAX
- #ifdef MAXPATHLEN
- #define PATH_MAX MAXPATHLEN
- #else
- #define PATH_MAX 1024
- #endif
- #endif
- Bool defeatAccessControl = FALSE;
- #define acmp(a1, a2, len) memcmp((char *)(a1), (char *)(a2), len)
- #define acopy(a1, a2, len) memmove((char *)(a2), (char *)(a1), len)
- #define addrEqual(fam, address, length, host) \
- ((fam) == (host)->family &&\
- (length) == (host)->len &&\
- !acmp (address, (host)->addr, length))
- static int ConvertAddr(struct sockaddr * /*saddr*/,
- int * /*len*/,
- pointer * /*addr*/);
- static int CheckAddr(int /*family*/,
- const void * /*pAddr*/,
- unsigned /*length*/);
- static Bool NewHost(int /*family*/,
- const void * /*addr*/,
- int /*len*/,
- int /* addingLocalHosts */);
- int LocalClientCredAndGroups(ClientPtr client, int *pUid, int *pGid,
- int **pSuppGids, int *nSuppGids);
- /* XFree86 bug #156: To keep track of which hosts were explicitly requested in
- /etc/X<display>.hosts, we've added a requested field to the HOST struct,
- and a LocalHostRequested variable. These default to FALSE, but are set
- to TRUE in ResetHosts when reading in /etc/X<display>.hosts. They are
- checked in DisableLocalHost(), which is called to disable the default
- local host entries when stronger authentication is turned on. */
- typedef struct _host {
- short family;
- short len;
- unsigned char *addr;
- struct _host *next;
- int requested;
- } HOST;
- #define MakeHost(h,l) (h)=malloc(sizeof *(h)+(l));\
- if (h) { \
- (h)->addr=(unsigned char *) ((h) + 1);\
- (h)->requested = FALSE; \
- }
- #define FreeHost(h) free(h)
- static HOST *selfhosts = NULL;
- static HOST *validhosts = NULL;
- static int AccessEnabled = DEFAULT_ACCESS_CONTROL;
- static int LocalHostEnabled = FALSE;
- static int LocalHostRequested = FALSE;
- static int UsingXdmcp = FALSE;
- /* FamilyServerInterpreted implementation */
- static Bool siAddrMatch(int family, pointer addr, int len, HOST *host,
- ClientPtr client);
- static int siCheckAddr(const char *addrString, int length);
- static void siTypesInitialize(void);
- /*
- * called when authorization is not enabled to add the
- * local host to the access list
- */
- void
- EnableLocalHost (void)
- {
- if (!UsingXdmcp)
- {
- LocalHostEnabled = TRUE;
- AddLocalHosts ();
- }
- }
- /*
- * called when authorization is enabled to keep us secure
- */
- void
- DisableLocalHost (void)
- {
- HOST *self;
- if (!LocalHostRequested) /* Fix for XFree86 bug #156 */
- LocalHostEnabled = FALSE;
- for (self = selfhosts; self; self = self->next) {
- if (!self->requested) /* Fix for XFree86 bug #156 */
- (void) RemoveHost ((ClientPtr)NULL, self->family, self->len, (pointer)self->addr);
- }
- }
- /*
- * called at init time when XDMCP will be used; xdmcp always
- * adds local hosts manually when needed
- */
- void
- AccessUsingXdmcp (void)
- {
- UsingXdmcp = TRUE;
- LocalHostEnabled = FALSE;
- }
- #define ifioctl ioctl
- /*
- * DefineSelf (fd):
- *
- * Define this host for access control. Find all the hosts the OS knows about
- * for this fd and add them to the selfhosts list.
- */
- #if !defined(SIOCGIFCONF) || (defined (hpux) && ! defined (HAS_IFREQ)) || defined(QNX4)
- void
- DefineSelf (int fd)
- {
- #if !defined(TCPCONN) && !defined(UNIXCONN)
- return;
- #else
- int len;
- caddr_t addr;
- int family;
- HOST *host;
- struct utsname name;
- struct hostent *hp;
- union {
- struct sockaddr sa;
- struct sockaddr_in in;
- #if defined(IPv6) && defined(AF_INET6)
- struct sockaddr_in6 in6;
- #endif
- } saddr;
- struct sockaddr_in *inetaddr;
- struct sockaddr_in6 *inet6addr;
- struct sockaddr_in broad_addr;
- #ifdef XTHREADS_NEEDS_BYNAMEPARAMS
- _Xgethostbynameparams hparams;
- #endif
- /* Why not use gethostname()? Well, at least on my system, I've had to
- * make an ugly kernel patch to get a name longer than 8 characters, and
- * uname() lets me access to the whole string (it smashes release, you
- * see), whereas gethostname() kindly truncates it for me.
- */
- uname(&name);
- hp = _XGethostbyname(name.nodename, hparams);
- if (hp != NULL)
- {
- saddr.sa.sa_family = hp->h_addrtype;
- switch (hp->h_addrtype) {
- case AF_INET:
- inetaddr = (struct sockaddr_in *) (&(saddr.sa));
- acopy ( hp->h_addr, &(inetaddr->sin_addr), hp->h_length);
- len = sizeof(saddr.sa);
- break;
- #if defined(IPv6) && defined(AF_INET6)
- case AF_INET6:
- inet6addr = (struct sockaddr_in6 *) (&(saddr.sa));
- acopy ( hp->h_addr, &(inet6addr->sin6_addr), hp->h_length);
- len = sizeof(saddr.in6);
- break;
- #endif
- default:
- goto DefineLocalHost;
- }
- family = ConvertAddr ( &(saddr.sa), &len, (pointer *)&addr);
- if ( family != -1 && family != FamilyLocal )
- {
- for (host = selfhosts;
- host && !addrEqual (family, addr, len, host);
- host = host->next) ;
- if (!host)
- {
- /* add this host to the host list. */
- MakeHost(host,len)
- if (host)
- {
- host->family = family;
- host->len = len;
- acopy ( addr, host->addr, len);
- host->next = selfhosts;
- selfhosts = host;
- }
- #ifdef XDMCP
- /*
- * If this is an Internet Address, but not the localhost
- * address (127.0.0.1), nor the bogus address (0.0.0.0),
- * register it.
- */
- if (family == FamilyInternet &&
- !(len == 4 &&
- ((addr[0] == 127 && addr[1] == 0 &&
- addr[2] == 0 && addr[3] == 1) ||
- (addr[0] == 0 && addr[1] == 0 &&
- addr[2] == 0 && addr[3] == 0)))
- )
- {
- XdmcpRegisterConnection (family, (char *)addr, len);
- broad_addr = *inetaddr;
- ((struct sockaddr_in *) &broad_addr)->sin_addr.s_addr =
- htonl (INADDR_BROADCAST);
- XdmcpRegisterBroadcastAddress ((struct sockaddr_in *)
- &broad_addr);
- }
- #if defined(IPv6) && defined(AF_INET6)
- else if (family == FamilyInternet6 &&
- !(IN6_IS_ADDR_LOOPBACK((struct in6_addr *)addr)))
- {
- XdmcpRegisterConnection (family, (char *)addr, len);
- }
- #endif
- #endif /* XDMCP */
- }
- }
- }
- /*
- * now add a host of family FamilyLocalHost...
- */
- DefineLocalHost:
- for (host = selfhosts;
- host && !addrEqual(FamilyLocalHost, "", 0, host);
- host = host->next);
- if (!host)
- {
- MakeHost(host, 0);
- if (host)
- {
- host->family = FamilyLocalHost;
- host->len = 0;
- acopy("", host->addr, 0);
- host->next = selfhosts;
- selfhosts = host;
- }
- }
- #endif /* !TCPCONN && !UNIXCONN */
- }
- #else
- #ifdef USE_SIOCGLIFCONF
- #define ifr_type struct lifreq
- #else
- #define ifr_type struct ifreq
- #endif
- #ifdef VARIABLE_IFREQ
- #define ifr_size(p) (sizeof (struct ifreq) + \
- (p->ifr_addr.sa_len > sizeof (p->ifr_addr) ? \
- p->ifr_addr.sa_len - sizeof (p->ifr_addr) : 0))
- #define ifraddr_size(a) (a.sa_len)
- #else
- #define ifr_size(p) (sizeof (ifr_type))
- #define ifraddr_size(a) (sizeof (a))
- #endif
- #if defined(DEF_SELF_DEBUG) || (defined(IPv6) && defined(AF_INET6))
- #include <arpa/inet.h>
- #endif
- #if defined(IPv6) && defined(AF_INET6)
- static void
- in6_fillscopeid(struct sockaddr_in6 *sin6)
- {
- #if defined(__KAME__)
- if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
- sin6->sin6_scope_id =
- ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]);
- sin6->sin6_addr.s6_addr[2] = sin6->sin6_addr.s6_addr[3] = 0;
- }
- #endif
- }
- #endif
- void
- DefineSelf (int fd)
- {
- #ifndef HAS_GETIFADDRS
- char buf[2048], *cp, *cplim;
- void * bufptr = buf;
- #ifdef USE_SIOCGLIFCONF
- struct lifconf ifc;
- struct lifreq *ifr;
- #ifdef SIOCGLIFNUM
- struct lifnum ifn;
- #endif
- #else
- struct ifconf ifc;
- struct ifreq *ifr;
- #endif
- #else
- struct ifaddrs * ifap, *ifr;
- #endif
- int len;
- unsigned char * addr;
- int family;
- HOST *host;
- #ifndef HAS_GETIFADDRS
- len = sizeof(buf);
- #ifdef USE_SIOCGLIFCONF
- #ifdef SIOCGLIFNUM
- ifn.lifn_family = AF_UNSPEC;
- ifn.lifn_flags = 0;
- if (ioctl (fd, SIOCGLIFNUM, (char *) &ifn) < 0)
- Error ("Getting interface count");
- if (len < (ifn.lifn_count * sizeof(struct lifreq))) {
- len = ifn.lifn_count * sizeof(struct lifreq);
- bufptr = malloc(len);
- }
- #endif
- ifc.lifc_family = AF_UNSPEC;
- ifc.lifc_flags = 0;
- ifc.lifc_len = len;
- ifc.lifc_buf = bufptr;
- #define IFC_IOCTL_REQ SIOCGLIFCONF
- #define IFC_IFC_REQ ifc.lifc_req
- #define IFC_IFC_LEN ifc.lifc_len
- #define IFR_IFR_ADDR ifr->lifr_addr
- #define IFR_IFR_NAME ifr->lifr_name
- #else /* Use SIOCGIFCONF */
- ifc.ifc_len = len;
- ifc.ifc_buf = bufptr;
- #define IFC_IOCTL_REQ SIOCGIFCONF
- #define IFC_IFC_REQ ifc.ifc_req
- #define IFC_IFC_LEN ifc.ifc_len
- #define IFR_IFR_ADDR ifr->ifr_addr
- #define IFR_IFR_NAME ifr->ifr_name
- #endif
- if (ifioctl (fd, IFC_IOCTL_REQ, (pointer) &ifc) < 0)
- Error ("Getting interface configuration (4)");
- cplim = (char *) IFC_IFC_REQ + IFC_IFC_LEN;
- for (cp = (char *) IFC_IFC_REQ; cp < cplim; cp += ifr_size (ifr))
- {
- ifr = (ifr_type *) cp;
- len = ifraddr_size (IFR_IFR_ADDR);
- family = ConvertAddr ((struct sockaddr *) &IFR_IFR_ADDR,
- &len, (pointer *)&addr);
- if (family == -1 || family == FamilyLocal)
- continue;
- #if defined(IPv6) && defined(AF_INET6)
- if (family == FamilyInternet6)
- in6_fillscopeid((struct sockaddr_in6 *)&IFR_IFR_ADDR);
- #endif
- #ifdef DEF_SELF_DEBUG
- if (family == FamilyInternet)
- ErrorF("Xserver: DefineSelf(): ifname = %s, addr = %d.%d.%d.%d\n",
- IFR_IFR_NAME, addr[0], addr[1], addr[2], addr[3]);
- #if defined(IPv6) && defined(AF_INET6)
- else if (family == FamilyInternet6) {
- char cp[INET6_ADDRSTRLEN] = "";
- inet_ntop(AF_INET6, addr, cp, sizeof(cp));
- ErrorF("Xserver: DefineSelf(): ifname = %s, addr = %s\n",
- IFR_IFR_NAME, cp);
- }
- #endif
- #endif /* DEF_SELF_DEBUG */
- for (host = selfhosts;
- host && !addrEqual (family, addr, len, host);
- host = host->next)
- ;
- if (host)
- continue;
- MakeHost(host,len)
- if (host)
- {
- host->family = family;
- host->len = len;
- acopy(addr, host->addr, len);
- host->next = selfhosts;
- selfhosts = host;
- }
- #ifdef XDMCP
- {
- #ifdef USE_SIOCGLIFCONF
- struct sockaddr_storage broad_addr;
- #else
- struct sockaddr broad_addr;
- #endif
- /*
- * If this isn't an Internet Address, don't register it.
- */
- if (family != FamilyInternet
- #if defined(IPv6) && defined(AF_INET6)
- && family != FamilyInternet6
- #endif
- )
- continue;
- /*
- * ignore 'localhost' entries as they're not useful
- * on the other end of the wire
- */
- if (family == FamilyInternet &&
- addr[0] == 127 && addr[1] == 0 &&
- addr[2] == 0 && addr[3] == 1)
- continue;
- #if defined(IPv6) && defined(AF_INET6)
- else if (family == FamilyInternet6 &&
- IN6_IS_ADDR_LOOPBACK((struct in6_addr *)addr))
- continue;
- #endif
- /*
- * Ignore '0.0.0.0' entries as they are
- * returned by some OSes for unconfigured NICs but they are
- * not useful on the other end of the wire.
- */
- if (len == 4 &&
- addr[0] == 0 && addr[1] == 0 &&
- addr[2] == 0 && addr[3] == 0)
- continue;
- XdmcpRegisterConnection (family, (char *)addr, len);
- #if defined(IPv6) && defined(AF_INET6)
- /* IPv6 doesn't support broadcasting, so we drop out here */
- if (family == FamilyInternet6)
- continue;
- #endif
- broad_addr = IFR_IFR_ADDR;
- ((struct sockaddr_in *) &broad_addr)->sin_addr.s_addr =
- htonl (INADDR_BROADCAST);
- #if defined(USE_SIOCGLIFCONF) && defined(SIOCGLIFBRDADDR)
- {
- struct lifreq broad_req;
- broad_req = *ifr;
- if (ioctl (fd, SIOCGLIFFLAGS, (char *) &broad_req) != -1 &&
- (broad_req.lifr_flags & IFF_BROADCAST) &&
- (broad_req.lifr_flags & IFF_UP)
- )
- {
- broad_req = *ifr;
- if (ioctl (fd, SIOCGLIFBRDADDR, &broad_req) != -1)
- broad_addr = broad_req.lifr_broadaddr;
- else
- continue;
- }
- else
- continue;
- }
- #elif defined(SIOCGIFBRDADDR)
- {
- struct ifreq broad_req;
- broad_req = *ifr;
- if (ifioctl (fd, SIOCGIFFLAGS, (pointer) &broad_req) != -1 &&
- (broad_req.ifr_flags & IFF_BROADCAST) &&
- (broad_req.ifr_flags & IFF_UP)
- )
- {
- broad_req = *ifr;
- if (ifioctl (fd, SIOCGIFBRDADDR, (pointer) &broad_req) != -1)
- broad_addr = broad_req.ifr_addr;
- else
- continue;
- }
- else
- continue;
- }
- #endif /* SIOCGIFBRDADDR */
- #ifdef DEF_SELF_DEBUG
- ErrorF("Xserver: DefineSelf(): ifname = %s, baddr = %s\n",
- IFR_IFR_NAME,
- inet_ntoa(((struct sockaddr_in *) &broad_addr)->sin_addr));
- #endif /* DEF_SELF_DEBUG */
- XdmcpRegisterBroadcastAddress ((struct sockaddr_in *) &broad_addr);
- }
- #endif /* XDMCP */
- }
- if (bufptr != buf)
- free(bufptr);
- #else /* HAS_GETIFADDRS */
- if (getifaddrs(&ifap) < 0) {
- ErrorF("Warning: getifaddrs returns %s\n", strerror(errno));
- return;
- }
- for (ifr = ifap; ifr != NULL; ifr = ifr->ifa_next) {
- if (!ifr->ifa_addr)
- continue;
- len = sizeof(*(ifr->ifa_addr));
- family = ConvertAddr((struct sockaddr *) ifr->ifa_addr, &len,
- (pointer *)&addr);
- if (family == -1 || family == FamilyLocal)
- continue;
- #if defined(IPv6) && defined(AF_INET6)
- if (family == FamilyInternet6)
- in6_fillscopeid((struct sockaddr_in6 *)ifr->ifa_addr);
- #endif
- #ifdef DEF_SELF_DEBUG
- if (family == FamilyInternet)
- ErrorF("Xserver: DefineSelf(): ifname = %s, addr = %d.%d.%d.%d\n",
- ifr->ifa_name, addr[0], addr[1], addr[2], addr[3]);
- #if defined(IPv6) && defined(AF_INET6)
- else if (family == FamilyInternet6) {
- char cp[INET6_ADDRSTRLEN];
- inet_ntop(AF_INET6, addr, cp, sizeof(cp));
- ErrorF("Xserver: DefineSelf(): ifname = %s addr = %s\n",
- ifr->ifa_name, cp);
- }
- #endif
- #endif /* DEF_SELF_DEBUG */
- for (host = selfhosts;
- host != NULL && !addrEqual(family, addr, len, host);
- host = host->next)
- ;
- if (host != NULL)
- continue;
- MakeHost(host, len);
- if (host != NULL) {
- host->family = family;
- host->len = len;
- acopy(addr, host->addr, len);
- host->next = selfhosts;
- selfhosts = host;
- }
- #ifdef XDMCP
- {
- struct sockaddr broad_addr;
- /*
- * If this isn't an Internet Address, don't register it.
- */
- if (family != FamilyInternet
- #if defined(IPv6) && defined(AF_INET6)
- && family != FamilyInternet6
- #endif
- )
- continue;
- /*
- * ignore 'localhost' entries as they're not useful
- * on the other end of the wire
- */
- if (ifr->ifa_flags & IFF_LOOPBACK)
- continue;
- if (family == FamilyInternet &&
- addr[0] == 127 && addr[1] == 0 &&
- addr[2] == 0 && addr[3] == 1)
- continue;
- /*
- * Ignore '0.0.0.0' entries as they are
- * returned by some OSes for unconfigured NICs but they are
- * not useful on the other end of the wire.
- */
- if (len == 4 &&
- addr[0] == 0 && addr[1] == 0 &&
- addr[2] == 0 && addr[3] == 0)
- continue;
- #if defined(IPv6) && defined(AF_INET6)
- else if (family == FamilyInternet6 &&
- IN6_IS_ADDR_LOOPBACK((struct in6_addr *)addr))
- continue;
- #endif
- XdmcpRegisterConnection(family, (char *)addr, len);
- #if defined(IPv6) && defined(AF_INET6)
- if (family == FamilyInternet6)
- /* IPv6 doesn't support broadcasting, so we drop out here */
- continue;
- #endif
- if ((ifr->ifa_flags & IFF_BROADCAST) &&
- (ifr->ifa_flags & IFF_UP))
- broad_addr = *ifr->ifa_broadaddr;
- else
- continue;
- #ifdef DEF_SELF_DEBUG
- ErrorF("Xserver: DefineSelf(): ifname = %s, baddr = %s\n",
- ifr->ifa_name,
- inet_ntoa(((struct sockaddr_in *) &broad_addr)->sin_addr));
- #endif /* DEF_SELF_DEBUG */
- XdmcpRegisterBroadcastAddress((struct sockaddr_in *)
- &broad_addr);
- }
- #endif /* XDMCP */
- } /* for */
- freeifaddrs(ifap);
- #endif /* HAS_GETIFADDRS */
- /*
- * add something of FamilyLocalHost
- */
- for (host = selfhosts;
- host && !addrEqual(FamilyLocalHost, "", 0, host);
- host = host->next);
- if (!host)
- {
- MakeHost(host, 0);
- if (host)
- {
- host->family = FamilyLocalHost;
- host->len = 0;
- acopy("", host->addr, 0);
- host->next = selfhosts;
- selfhosts = host;
- }
- }
- }
- #endif /* hpux && !HAS_IFREQ */
- #ifdef XDMCP
- void
- AugmentSelf(pointer from, int len)
- {
- int family;
- pointer addr;
- HOST *host;
- family = ConvertAddr(from, &len, (pointer *)&addr);
- if (family == -1 || family == FamilyLocal)
- return;
- for (host = selfhosts; host; host = host->next)
- {
- if (addrEqual(family, addr, len, host))
- return;
- }
- MakeHost(host,len)
- if (!host)
- return;
- host->family = family;
- host->len = len;
- acopy(addr, host->addr, len);
- host->next = selfhosts;
- selfhosts = host;
- }
- #endif
- void
- AddLocalHosts (void)
- {
- HOST *self;
- for (self = selfhosts; self; self = self->next)
- /* Fix for XFree86 bug #156: pass addingLocal = TRUE to
- * NewHost to tell that we are adding the default local
- * host entries and not to flag the entries as being
- * explicitely requested */
- (void) NewHost (self->family, self->addr, self->len, TRUE);
- }
- /* Reset access control list to initial hosts */
- void
- ResetHosts (const char *display)
- {
- HOST *host;
- char lhostname[120], ohostname[120];
- char *hostname;
- char fname[PATH_MAX + 1];
- int fnamelen;
- FILE *fd;
- char *ptr;
- int i, hostlen;
- #if (defined(TCPCONN) && \
- (!defined(IPv6) || !defined(AF_INET6)))
- union {
- struct sockaddr sa;
- #if defined(TCPCONN)
- struct sockaddr_in in;
- #endif /* TCPCONN */
- } saddr;
- #endif
- int family = 0;
- pointer addr = NULL;
- int len;
- siTypesInitialize();
- AccessEnabled = defeatAccessControl ? FALSE : DEFAULT_ACCESS_CONTROL;
- LocalHostEnabled = FALSE;
- while ((host = validhosts) != 0)
- {
- validhosts = host->next;
- FreeHost (host);
- }
- #define ETC_HOST_PREFIX "/etc/X"
- #define ETC_HOST_SUFFIX ".hosts"
- fnamelen = strlen(ETC_HOST_PREFIX) + strlen(ETC_HOST_SUFFIX) +
- strlen(display) + 1;
- if (fnamelen > sizeof(fname))
- FatalError("Display name `%s' is too long\n", display);
- sprintf(fname, ETC_HOST_PREFIX "%s" ETC_HOST_SUFFIX, display);
- if ((fd = fopen (fname, "r")) != 0)
- {
- while (fgets (ohostname, sizeof (ohostname), fd))
- {
- family = FamilyWild;
- if (*ohostname == '#')
- continue;
- if ((ptr = strchr(ohostname, '\n')) != 0)
- *ptr = 0;
- hostlen = strlen(ohostname) + 1;
- for (i = 0; i < hostlen; i++)
- lhostname[i] = tolower(ohostname[i]);
- hostname = ohostname;
- if (!strncmp("local:", lhostname, 6))
- {
- family = FamilyLocalHost;
- NewHost(family, "", 0, FALSE);
- LocalHostRequested = TRUE; /* Fix for XFree86 bug #156 */
- }
- #if defined(TCPCONN)
- else if (!strncmp("inet:", lhostname, 5))
- {
- family = FamilyInternet;
- hostname = ohostname + 5;
- }
- #if defined(IPv6) && defined(AF_INET6)
- else if (!strncmp("inet6:", lhostname, 6))
- {
- family = FamilyInternet6;
- hostname = ohostname + 6;
- }
- #endif
- #endif
- #ifdef SECURE_RPC
- else if (!strncmp("nis:", lhostname, 4))
- {
- family = FamilyNetname;
- hostname = ohostname + 4;
- }
- #endif
- else if (!strncmp("si:", lhostname, 3))
- {
- family = FamilyServerInterpreted;
- hostname = ohostname + 3;
- hostlen -= 3;
- }
- if (family == FamilyServerInterpreted)
- {
- len = siCheckAddr(hostname, hostlen);
- if (len >= 0) {
- NewHost(family, hostname, len, FALSE);
- }
- }
- else
- #ifdef SECURE_RPC
- if ((family == FamilyNetname) || (strchr(hostname, '@')))
- {
- SecureRPCInit ();
- (void) NewHost (FamilyNetname, hostname, strlen (hostname), FALSE);
- }
- else
- #endif /* SECURE_RPC */
- #if defined(TCPCONN)
- {
- #if defined(IPv6) && defined(AF_INET6)
- if ( (family == FamilyInternet) || (family == FamilyInternet6) ||
- (family == FamilyWild) )
- {
- struct addrinfo *addresses;
- struct addrinfo *a;
- int f;
- if (getaddrinfo(hostname, NULL, NULL, &addresses) == 0) {
- for (a = addresses ; a != NULL ; a = a->ai_next) {
- len = a->ai_addrlen;
- f = ConvertAddr(a->ai_addr,&len,(pointer *)&addr);
- if ( (family == f) ||
- ((family == FamilyWild) && (f != -1)) ) {
- NewHost(f, addr, len, FALSE);
- }
- }
- freeaddrinfo(addresses);
- }
- }
- #else
- #ifdef XTHREADS_NEEDS_BYNAMEPARAMS
- _Xgethostbynameparams hparams;
- #endif
- struct hostent *hp;
- /* host name */
- if ((family == FamilyInternet &&
- ((hp = _XGethostbyname(hostname, hparams)) != 0)) ||
- ((hp = _XGethostbyname(hostname, hparams)) != 0))
- {
- saddr.sa.sa_family = hp->h_addrtype;
- len = sizeof(saddr.sa);
- if ((family = ConvertAddr (&saddr.sa, &len, (pointer *)&addr)) != -1)
- {
- #ifdef h_addr /* new 4.3bsd version of gethostent */
- char **list;
- /* iterate over the addresses */
- for (list = hp->h_addr_list; *list; list++)
- (void) NewHost (family, (pointer)*list, len, FALSE);
- #else
- (void) NewHost (family, (pointer)hp->h_addr, len, FALSE);
- #endif
- }
- }
- #endif /* IPv6 */
- }
- #endif /* TCPCONN */
- // family = FamilyWild;
- }
- fclose (fd);
- }
- }
- /* Is client on the local host */
- _X_EXPORT Bool LocalClient(ClientPtr client)
- {
- int alen, family, notused;
- Xtransaddr *from = NULL;
- pointer addr;
- HOST *host;
- if (!_XSERVTransGetPeerAddr (((OsCommPtr)client->osPrivate)->trans_conn,
- ¬used, &alen, &from))
- {
- family = ConvertAddr ((struct sockaddr *) from,
- &alen, (pointer *)&addr);
- if (family == -1)
- {
- free((char *) from);
- return FALSE;
- }
- if (family == FamilyLocal)
- {
- free((char *) from);
- return TRUE;
- }
- for (host = selfhosts; host; host = host->next)
- {
- if (addrEqual (family, addr, alen, host))
- return TRUE;
- }
- free((char *) from);
- }
- return FALSE;
- }
- /*
- * Return the uid and gid of a connected local client
- * or the uid/gid for nobody those ids cannot be determined
- *
- * Used by XShm to test access rights to shared memory segments
- */
- int
- LocalClientCred(ClientPtr client, int *pUid, int *pGid)
- {
- return LocalClientCredAndGroups(client, pUid, pGid, NULL, NULL);
- }
- /*
- * Return the uid and all gids of a connected local client
- * or the uid/gid for nobody those ids cannot be determined
- *
- * If the caller passes non-NULL values for pSuppGids & nSuppGids,
- * they are responsible for calling XFree(*pSuppGids) to release the
- * memory allocated for the supplemental group ids list.
- *
- * Used by localuser & localgroup ServerInterpreted access control forms below
- */
- int
- LocalClientCredAndGroups(ClientPtr client, int *pUid, int *pGid,
- int **pSuppGids, int *nSuppGids)
- {
- #if defined(HAS_GETPEEREID) || defined(HAS_GETPEERUCRED) || defined(SO_PEERCRED)
- int fd;
- XtransConnInfo ci;
- #ifdef HAS_GETPEEREID
- uid_t uid;
- gid_t gid;
- #elif defined(HAS_GETPEERUCRED)
- ucred_t *peercred = NULL;
- #elif defined(SO_PEERCRED)
- struct ucred peercred;
- socklen_t so_len = sizeof(peercred);
- #endif
- if (client == NULL)
- return -1;
- ci = ((OsCommPtr)client->osPrivate)->trans_conn;
- /* Most implementations can only determine peer credentials for Unix
- * domain sockets - Solaris getpeerucred can work with a bit more, so
- * we just let it tell us if the connection type is supported or not
- */
- if (!_XSERVTransIsLocal(ci)) {
- return -1;
- }
- if (pSuppGids != NULL)
- *pSuppGids = NULL;
- if (nSuppGids != NULL)
- *nSuppGids = 0;
- fd = _XSERVTransGetConnectionNumber(ci);
- #ifdef HAS_GETPEEREID
- if (getpeereid(fd, &uid, &gid) == -1)
- return -1;
- if (pUid != NULL)
- *pUid = uid;
- if (pGid != NULL)
- *pGid = gid;
- return 0;
- #elif defined(HAS_GETPEERUCRED)
- if (getpeerucred(fd, &peercred) < 0)
- return -1;
- if (pUid != NULL)
- *pUid = ucred_geteuid(peercred);
- if (pGid != NULL)
- *pGid = ucred_getegid(peercred);
- if (pSuppGids != NULL && nSuppGids != NULL) {
- const gid_t *gids;
- *nSuppGids = ucred_getgroups(peercred, &gids);
- if (*nSuppGids > 0) {
- *pSuppGids = malloc(sizeof(int) * (*nSuppGids));
- if (*pSuppGids == NULL) {
- *nSuppGids = 0;
- } else {
- int i;
- for (i = 0 ; i < *nSuppGids; i++) {
- (*pSuppGids)[i] = (int) gids[i];
- }
- }
- }
- }
- ucred_free(peercred);
- return 0;
- #elif defined(SO_PEERCRED)
- if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) == -1)
- return -1;
- if (pUid != NULL)
- *pUid = peercred.uid;
- if (pGid != NULL)
- *pGid = peercred.gid;
- return 0;
- #endif
- #else
- /* No system call available to get the credentials of the peer */
- #define NO_LOCAL_CLIENT_CRED
- return -1;
- #endif
- }
- static Bool
- AuthorizedClient(ClientPtr client)
- {
- if (!client || defeatAccessControl)
- return TRUE;
- return LocalClient(client);
- }
- /* Add a host to the access control list. This is the external interface
- * called from the dispatcher */
- int
- AddHost (ClientPtr client,
- int family,
- unsigned length, /* of bytes in pAddr */
- const void * pAddr)
- {
- int len;
- if (!AuthorizedClient(client))
- return(BadAccess);
- switch (family) {
- case FamilyLocalHost:
- len = length;
- LocalHostEnabled = TRUE;
- break;
- #ifdef SECURE_RPC
- case FamilyNetname:
- len = length;
- SecureRPCInit ();
- break;
- #endif
- case FamilyInternet:
- #if defined(IPv6) && defined(AF_INET6)
- case FamilyInternet6:
- #endif
- case FamilyDECnet:
- case FamilyChaos:
- case FamilyServerInterpreted:
- if ((len = CheckAddr (family, pAddr, length)) < 0)
- {
- if (client) client->errorValue = length;
- return (BadValue);
- }
- break;
- case FamilyLocal:
- default:
- if (client) client->errorValue = family;
- return (BadValue);
- }
- if (NewHost (family, pAddr, len, FALSE))
- return Success;
- return BadAlloc;
- }
- /* Add a host to the access control list. This is the internal interface
- * called when starting or resetting the server */
- static Bool
- NewHost (int family,
- const void * addr,
- int len,
- int addingLocalHosts)
- {
- HOST *host;
- for (host = validhosts; host; host = host->next)
- {
- if (addrEqual (family, addr, len, host))
- return TRUE;
- }
- if (!addingLocalHosts) { /* Fix for XFree86 bug #156 */
- for (host = selfhosts; host; host = host->next) {
- if (addrEqual (family, addr, len, host)) {
- host->requested = TRUE;
- break;
- }
- }
- }
- MakeHost(host,len)
- if (!host)
- return FALSE;
- host->family = family;
- host->len = len;
- acopy(addr, host->addr, len);
- host->next = validhosts;
- validhosts = host;
- return TRUE;
- }
- /* Remove a host from the access control list */
- int
- RemoveHost (
- ClientPtr client,
- int family,
- unsigned length, /* of bytes in pAddr */
- pointer pAddr)
- {
- int len;
- HOST *host, **prev;
- if (!AuthorizedClient(client))
- return(BadAccess);
- switch (family) {
- case FamilyLocalHost:
- len = length;
- LocalHostEnabled = FALSE;
- break;
- #ifdef SECURE_RPC
- case FamilyNetname:
- len = length;
- break;
- #endif
- case FamilyInternet:
- #if defined(IPv6) && defined(AF_INET6)
- case FamilyInternet6:
- #endif
- case FamilyDECnet:
- case FamilyChaos:
- case FamilyServerInterpreted:
- if ((len = CheckAddr (family, pAddr, length)) < 0)
- {
- client->errorValue = length;
- return(BadValue);
- }
- break;
- case FamilyLocal:
- default:
- client->errorValue = family;
- return(BadValue);
- }
- for (prev = &validhosts;
- (host = *prev) && (!addrEqual (family, pAddr, len, host));
- prev = &host->next)
- ;
- if (host)
- {
- *prev = host->next;
- FreeHost (host);
- }
- return (Success);
- }
- /* Get all hosts in the access control list */
- int
- GetHosts (
- pointer *data,
- int *pnHosts,
- int *pLen,
- BOOL *pEnabled)
- {
- int len;
- int n = 0;
- unsigned char *ptr;
- HOST *host;
- int nHosts = 0;
- *pEnabled = AccessEnabled ? EnableAccess : DisableAccess;
- for (host = validhosts; host; host = host->next)
- {
- nHosts++;
- n += (((host->len + 3) >> 2) << 2) + sizeof(xHostEntry);
- }
- if (n)
- {
- *data = ptr = malloc(n);
- if (!ptr)
- {
- return(BadAlloc);
- }
- for (host = validhosts; host; host = host->next)
- {
- len = host->len;
- ((xHostEntry *)ptr)->family = host->family;
- ((xHostEntry *)ptr)->length = len;
- ptr += sizeof(xHostEntry);
- acopy (host->addr, ptr, len);
- ptr += ((len + 3) >> 2) << 2;
- }
- } else {
- *data = NULL;
- }
- *pnHosts = nHosts;
- *pLen = n;
- return(Success);
- }
- /* Check for valid address family and length, and return address length. */
- /*ARGSUSED*/
- static int
- CheckAddr (
- int family,
- const void * pAddr,
- unsigned length)
- {
- int len;
- switch (family)
- {
- #if defined(TCPCONN)
- case FamilyInternet:
- if (length == sizeof (struct in_addr))
- len = length;
- else
- len = -1;
- break;
- #if defined(IPv6) && defined(AF_INET6)
- case FamilyInternet6:
- if (length == sizeof (struct in6_addr))
- len = length;
- else
- len = -1;
- break;
- #endif
- #endif
- case FamilyServerInterpreted:
- len = siCheckAddr(pAddr, length);
- break;
- default:
- len = -1;
- }
- return (len);
- }
- /* Check if a host is not in the access control list.
- * Returns 1 if host is invalid, 0 if we've found it. */
- int
- InvalidHost (
- register struct sockaddr *saddr,
- int len,
- ClientPtr client)
- {
- int family;
- pointer addr = NULL;
- HOST *selfhost, *host;
- if (!AccessEnabled) /* just let them in */
- return(0);
- family = ConvertAddr (saddr, &len, (pointer *)&addr);
- if (family == -1)
- return 1;
- if (family == FamilyLocal)
- {
- if (!LocalHostEnabled)
- {
- /*
- * check to see if any local address is enabled. This
- * implicitly enables local connections.
- */
- for (selfhost = selfhosts; selfhost; selfhost=selfhost->next)
- {
- for (host = validhosts; host; host=host->next)
- {
- if (addrEqual (selfhost->family, selfhost->addr,
- selfhost->len, host))
- return 0;
- }
- }
- } else
- return 0;
- }
- for (host = validhosts; host; host = host->next)
- {
- if ((host->family == FamilyServerInterpreted)) {
- if (siAddrMatch (family, addr, len, host, client)) {
- return (0);
- }
- } else {
- if (addrEqual (family, addr, len, host))
- return (0);
- }
- }
- return (1);
- }
- static int
- ConvertAddr (
- register struct sockaddr *saddr,
- int *len,
- pointer *addr)
- {
- if (*len == 0)
- return (FamilyLocal);
- switch (saddr->sa_family)
- {
- case AF_UNSPEC:
- #if defined(UNIXCONN) || defined(LOCALCONN)
- case AF_UNIX:
- #endif
- return FamilyLocal;
- #if defined(TCPCONN)
- case AF_INET:
- *len = sizeof (struct in_addr);
- *addr = (pointer) &(((struct sockaddr_in *) saddr)->sin_addr);
- return FamilyInternet;
- #if defined(IPv6) && defined(AF_INET6)
- case AF_INET6:
- {
- struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *) saddr;
- if (IN6_IS_ADDR_V4MAPPED(&(saddr6->sin6_addr))) {
- *len = sizeof (struct in_addr);
- *addr = (pointer) &(saddr6->sin6_addr.s6_addr[12]);
- return FamilyInternet;
- } else {
- *len = sizeof (struct in6_addr);
- *addr = (pointer) &(saddr6->sin6_addr);
- return FamilyInternet6;
- }
- }
- #endif
- #endif
- default:
- return -1;
- }
- }
- int
- ChangeAccessControl(
- ClientPtr client,
- int fEnabled)
- {
- if (!AuthorizedClient(client))
- return BadAccess;
- AccessEnabled = fEnabled;
- return Success;
- }
- /*****************************************************************************
- * FamilyServerInterpreted host entry implementation
- *
- * Supports an extensible system of host types which the server can interpret
- * See the IPv6 extensions to the X11 protocol spec for the definition.
- *
- * Currently supported schemes:
- *
- * hostname - hostname as defined in IETF RFC 2396
- * ipv6 - IPv6 literal address as defined in IETF RFC's 3513 and <TBD>
- *
- * See xc/doc/specs/SIAddresses for formal definitions of each type.
- */
- /* These definitions and the siTypeAdd function could be exported in the
- * future to enable loading additional host types, but that was not done for
- * the initial implementation.
- */
- typedef Bool (*siAddrMatchFunc)(int family, pointer addr, int len,
- const char *siAddr, int siAddrlen, ClientPtr client, void *siTypePriv);
- typedef int (*siCheckAddrFunc)(const char *addrString, int length,
- void *siTypePriv);
- struct siType {
- struct siType * next;
- const char * typeName;
- siAddrMatchFunc addrMatch;
- siCheckAddrFunc checkAddr;
- void * typePriv; /* Private data for type routines */
- };
- static struct siType *siTypeList;
- static int
- siTypeAdd(const char *typeName, siAddrMatchFunc addrMatch,
- siCheckAddrFunc checkAddr, void *typePriv)
- {
- struct siType *s, *p;
- if ((typeName == NULL) || (addrMatch == NULL) || (checkAddr == NULL))
- return BadValue;
- for (s = siTypeList, p = NULL; s != NULL ; p = s, s = s->next) {
- if (strcmp(typeName, s->typeName) == 0) {
- s->addrMatch = addrMatch;
- s->checkAddr = checkAddr;
- s->typePriv = typePriv;
- return Success;
- }
- }
- s = malloc(sizeof(struct siType));
- if (s == NULL)
- return BadAlloc;
- if (p == NULL)
- siTypeList = s;
- else
- p->next = s;
- s->next = NULL;
- s->typeName = typeName;
- s->addrMatch = addrMatch;
- s->checkAddr = checkAddr;
- s->typePriv = typePriv;
- return Success;
- }
- /* Checks to see if a host matches a server-interpreted host entry */
- static Bool
- siAddrMatch(int family, pointer addr, int len, HOST *host, ClientPtr client)
- {
- Bool matches = FALSE;
- struct siType *s;
- const char *valueString;
- int addrlen;
- valueString = (const char *) memchr(host->addr, '\0', host->len);
- if (valueString != NULL) {
- for (s = siTypeList; s != NULL ; s = s->next) {
- if (strcmp((char *) host->addr, s->typeName) == 0) {
- addrlen = host->len - (strlen((char *)host->addr) + 1);
- matches = s->addrMatch(family, addr, len,
- valueString + 1, addrlen, client, s->typePriv);
- break;
- }
- }
- #ifdef FAMILY_SI_DEBUG
- ErrorF(
- "Xserver: siAddrMatch(): type = %s, value = %*.*s -- %s\n",
- host->addr, addrlen, addrlen, valueString + 1,
- (matches) ? "accepted" : "rejected");
- #endif
- }
- return matches;
- }
- static int
- siCheckAddr(const char *addrString, int length)
- {
- const char *valueString;
- int addrlen, typelen;
- int len = -1;
- struct siType *s;
- /* Make sure there is a \0 byte inside the specified length
- to separate the address type from the address value. */
- valueString = (const char *) memchr(addrString, '\0', length);
- if (valueString != NULL) {
- /* Make sure the first string is a recognized address type,
- * and the second string is a valid address of that type.
- */
- typelen = strlen(addrString) + 1;
- addrlen = length - typelen;
- for (s = siTypeList; s != NULL ; s = s->next) {
- if (strcmp(addrString, s->typeName) == 0) {
- len = s->checkAddr(valueString + 1, addrlen, s->typePriv);
- if (len >= 0) {
- len += typelen;
- }
- break;
- }
- }
- #ifdef FAMILY_SI_DEBUG
- {
- const char *resultMsg;
- if (s == NULL) {
- resultMsg = "type not registered";
- } else {
- if (len == -1)
- resultMsg = "rejected";
- else
- resultMsg = "accepted";
- }
- ErrorF("Xserver: siCheckAddr(): type = %s, value = %*.*s, len = %d -- %s\n",
- addrString, addrlen, addrlen, valueString + 1, len, resultMsg);
- }
- #endif
- }
- return len;
- }
- /***
- * Hostname server-interpreted host type
- *
- * Stored as hostname string, explicitly defined to be resolved ONLY
- * at access check time, to allow for hosts with dynamic addresses
- * but static hostnames, such as found in some DHCP & mobile setups.
- *
- * Hostname must conform to IETF RFC 2396 sec. 3.2.2, which defines it as:
- * hostname = *( domainlabel "." ) toplabel [ "." ]
- * domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
- * toplabel = alpha | alpha *( alphanum | "-" ) alphanum
- */
- #ifdef NI_MAXHOST
- # define SI_HOSTNAME_MAXLEN NI_MAXHOST
- #else
- # ifdef MAXHOSTNAMELEN
- # define SI_HOSTNAME_MAXLEN MAXHOSTNAMELEN
- # else
- # define SI_HOSTNAME_MAXLEN 256
- # endif
- #endif
- static Bool
- siHostnameAddrMatch(int family, pointer addr, int len,
- const char *siAddr, int siAddrLen, ClientPtr client, void *typePriv)
- {
- Bool res = FALSE;
- /* Currently only supports checking against IPv4 & IPv6 connections, but
- * support for other address families, such as DECnet, could be added if
- * desired.
- */
- #if defined(IPv6) && defined(AF_INET6)
- if ((family == FamilyInternet) || (family == FamilyInternet6)) {
- char hostname[SI_HOSTNAME_MAXLEN];
- struct addrinfo *addresses;
- struct addrinfo *a;
- int f, hostaddrlen;
- pointer hostaddr = NULL;
- if (siAddrLen >= sizeof(hostname))
- return FALSE;
- strncpy(hostname, siAddr, siAddrLen);
- hostname[siAddrLen] = '\0';
- if (getaddrinfo(hostname, NULL, NULL, &addresses) == 0) {
- for (a = addresses ; a != NULL ; a = a->ai_next) {
- hostaddrlen = a->ai_addrlen;
- f = ConvertAddr(a->ai_addr,&hostaddrlen,&hostaddr);
- if ((f == family) && (len == hostaddrlen) &&
- (acmp (addr, hostaddr, len) == 0) ) {
- res = TRUE;
- break;
- }
- }
- freeaddrinfo(addresses);
- }
- }
- #else /* IPv6 not supported, use gethostbyname instead for IPv4 */
- if (family == FamilyInternet) {
- struct hostent *hp;
- #ifdef XTHREADS_NEEDS_BYNAMEPARAMS
- _Xgethostbynameparams hparams;
- #endif
- char hostname[SI_HOSTNAME_MAXLEN];
- int f, hostaddrlen;
- pointer hostaddr;
- const char **addrlist;
- if (siAddrLen >= sizeof(hostname))
- return FALSE;
- strncpy(hostname, siAddr, siAddrLen);
- hostname[siAddrLen] = '\0';
- if ((hp = _XGethostbyname(hostname, hparams)) != NULL) {
- #ifdef h_addr /* new 4.3bsd version of gethostent */
- /* iterate over the addresses */
- for (addrlist = hp->h_addr_list; *addrlist; addrlist++)
- #else
- addrlist = &hp->h_addr;
- #endif
- {
- struct sockaddr_in sin;
- sin.sin_family = hp->h_addrtype;
- acopy ( *addrlist, &(sin.sin_addr), hp->h_length);
- hostaddrlen = sizeof(sin);
- f = ConvertAddr ((struct sockaddr *)&sin,
- &hostaddrlen, &hostaddr);
- if ((f == family) && (len == hostaddrlen) &&
- (acmp (addr, hostaddr, len) == 0) ) {
- res = TRUE;
- break;
- }
- }
- }
- }
- #endif
- return res;
- }
- static int
- siHostnameCheckAddr(const char *valueString, int length, void *typePriv)
- {
- /* Check conformance of hostname to RFC 2396 sec. 3.2.2 definition.
- * We do not use ctype functions here to avoid locale-specific
- * character sets. Hostnames must be pure ASCII.
- */
- int len = length;
- int i;
- Bool dotAllowed = FALSE;
- Bool dashAllowed = FALSE;
- if ((length <= 0) || (length >= SI_HOSTNAME_MAXLEN)) {
- len = -1;
- } else {
- for (i = 0; i < length; i++) {
- char c = valueString[i];
- if (c == 0x2E) { /* '.' */
- if (dotAllowed == FALSE) {
- len = -1;
- break;
- } else {
- dotAllowed = FALSE;
- dashAllowed = FALSE;
- }
- } else if (c == 0x2D) { /* '-' */
- if (dashAllowed == FALSE) {
- len = -1;
- break;
- } else {
- dotAllowed = FALSE;
- }
- } else if (((c >= 0x30) && (c <= 0x3A)) /* 0-9 */ ||
- ((c >= 0x61) && (c <= 0x7A)) /* a-z */ ||
- ((c >= 0x41) && (c <= 0x5A)) /* A-Z */) {
- dotAllowed = TRUE;
- dashAllowed = TRUE;
- } else { /* Invalid character */
- len = -1;
- break;
- }
- }
- }
- return len;
- }
- #if defined(IPv6) && defined(AF_INET6)
- /***
- * "ipv6" server interpreted type
- *
- * Currently supports only IPv6 literal address as specified in IETF RFC 3513
- *
- * Once draft-ietf-ipv6-scoping-arch-00.txt becomes an RFC, support will be
- * added for the scoped address format it specifies.
- */
- /* Maximum length of an IPv6 address string - increase when adding support
- * for scoped address qualifiers. Includes room for trailing NUL byte.
- */
- #define SI_IPv6_MAXLEN INET6_ADDRSTRLEN
- static Bool
- siIPv6AddrMatch(int family, pointer addr, int len,
- const char *siAddr, int siAddrlen, ClientPtr client, void *typePriv)
- {
- struct in6_addr addr6;
- char addrbuf[SI_IPv6_MAXLEN];
- if ((family != FamilyInternet6) || (len != sizeof(addr6)))
- return FALSE;
- memcpy(addrbuf, siAddr, siAddrlen);
- addrbuf[siAddrlen] = '\0';
- if (inet_pton(AF_INET6, addrbuf, &addr6) != 1) {
- perror("inet_pton");
- return FALSE;
- }
- if (memcmp(addr, &addr6, len) == 0) {
- return TRUE;
- } else {
- return FALSE;
- }
- }
- static int
- siIPv6CheckAddr(const char *addrString, int length, void *typePriv)
- {
- int len;
- /* Minimum length is 3 (smallest legal address is "::1") */
- if (length < 3) {
- /* Address is too short! */
- len = -1;
- } else if (length >= SI_IPv6_MAXLEN) {
- /* Address is too long! */
- len = -1;
- } else {
- /* Assume inet_pton is sufficient validation */
- struct in6_addr addr6;
- char addrbuf[SI_IPv6_MAXLEN];
- memcpy(addrbuf, addrString, length);
- addrbuf[length] = '\0';
- if (inet_pton(AF_INET6, addrbuf, &addr6) != 1) {
- perror("inet_pton");
- len = -1;
- } else {
- len = length;
- }
- }
- return len;
- }
- #endif /* IPv6 */
- #if !defined(NO_LOCAL_CLIENT_CRED)
- /***
- * "localuser" & "localgroup" server interpreted types
- *
- * Allows local connections from a given local user or group
- */
- #include <pwd.h>
- #include <grp.h>
- #define LOCAL_USER 1
- #define LOCAL_GROUP 2
- typedef struct {
- int credType;
- } siLocalCredPrivRec, *siLocalCredPrivPtr;
- static siLocalCredPrivRec siLocalUserPriv = { LOCAL_USER };
- static siLocalCredPrivRec siLocalGroupPriv = { LOCAL_GROUP };
- static Bool
- siLocalCredGetId(const char *addr, int len, siLocalCredPrivPtr lcPriv, int *id)
- {
- Bool parsedOK = FALSE;
- char *addrbuf = malloc(len + 1);
- if (addrbuf == NULL) {
- return FALSE;
- }
- memcpy(addrbuf, addr, len);
- addrbuf[len] = '\0';
- if (addr[0] == '#') { /* numeric id */
- char *cp;
- errno = 0;
- *id = strtol(addrbuf + 1, &cp, 0);
- if ((errno == 0) && (cp != (addrbuf+1))) {
- parsedOK = TRUE;
- }
- } else { /* non-numeric name */
- if (lcPriv->credType == LOCAL_USER) {
- struct passwd *pw = getpwnam(addrbuf);
- if (pw != NULL) {
- *id = (int) pw->pw_uid;
- parsedOK = TRUE;
- }
- } else { /* group */
- struct group *gr = getgrnam(addrbuf);
- if (gr != NULL) {
- *id = (int) gr->gr_gid;
- parsedOK = TRUE;
- }
- }
- }
- free(addrbuf);
- return parsedOK;
- }
- static Bool
- siLocalCredAddrMatch(int family, pointer addr, int len,
- const char *siAddr, int siAddrlen, ClientPtr client, void *typePriv)
- {
- int connUid, connGid, *connSuppGids, connNumSuppGids, siAddrId;
- siLocalCredPrivPtr lcPriv = (siLocalCredPrivPtr) typePriv;
- if (LocalClientCredAndGroups(client, &connUid, &connGid,
- &connSuppGids, &connNumSuppGids) == -1) {
- return FALSE;
- }
- if (siLocalCredGetId(siAddr, siAddrlen, lcPriv, &siAddrId) == FALSE) {
- return FALSE;
- }
- if (lcPriv->credType == LOCAL_USER) {
- if (connUid == siAddrId) {
- return TRUE;
- }
- } else {
- if (connGid == siAddrId) {
- return TRUE;
- }
- if (connSuppGids != NULL) {
- int i;
- for (i = 0 ; i < connNumSuppGids; i++) {
- if (connSuppGids[i] == siAddrId) {
- free(connSuppGids);
- return TRUE;
- }
- }
- free(connSuppGids);
- }
- }
- return FALSE;
- }
- static int
- siLocalCredCheckAddr(const char *addrString, int length, void *typePriv)
- {
- int len = length;
- int id;
- if (siLocalCredGetId(addrString, length,
- (siLocalCredPrivPtr)typePriv, &id) == FALSE) {
- len = -1;
- }
- return len;
- }
- #endif /* localuser */
- static void
- siTypesInitialize(void)
- {
- siTypeAdd("hostname", siHostnameAddrMatch, siHostnameCheckAddr, NULL);
- #if defined(IPv6) && defined(AF_INET6)
- siTypeAdd("ipv6", siIPv6AddrMatch, siIPv6CheckAddr, NULL);
- #endif
- #if !defined(NO_LOCAL_CLIENT_CRED)
- siTypeAdd("localuser", siLocalCredAddrMatch, siLocalCredCheckAddr,
- &siLocalUserPriv);
- siTypeAdd("localgroup", siLocalCredAddrMatch, siLocalCredCheckAddr,
- &siLocalGroupPriv);
- #endif
- }
|