diff options
Diffstat (limited to 'kdm/backend/auth.c')
-rw-r--r-- | kdm/backend/auth.c | 1238 |
1 files changed, 0 insertions, 1238 deletions
diff --git a/kdm/backend/auth.c b/kdm/backend/auth.c deleted file mode 100644 index bd183142c..000000000 --- a/kdm/backend/auth.c +++ /dev/null @@ -1,1238 +0,0 @@ -/* - -Copyright 1988, 1998 The Open Group -Copyright 2000-2004 Oswald Buddenhagen <ossi@kde.org> - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -the above copyright notice appear in all copies and that both that -copyright notice and this permission notice appear in supporting -documentation. - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -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. -IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE 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 -from the copyright holder. - -*/ - -/* - * xdm - display manager daemon - * Author: Keith Packard, MIT X Consortium - * - * maintain the authorization generation daemon - */ - -#include "dm.h" -#include "dm_auth.h" -#include "dm_error.h" - -#include <sys/stat.h> -#include <fcntl.h> -#include <stdlib.h> - -#include <sys/ioctl.h> - -#include "dm_socket.h" -#ifdef DNETCONN -# include <netdnet/dnetdb.h> -#endif - -#if (defined(_POSIX_SOURCE) && !defined(_AIX) && !defined(__QNX__)) || defined(__hpux) || defined(__svr4__) /* XXX */ -# define NEED_UTSNAME -# include <sys/utsname.h> -#endif - -#ifdef __GNU__ -# include <netdb.h> -# undef SIOCGIFCONF -#else /* __GNU__ */ -# include <net/if.h> -# ifdef __svr4__ -# include <netdb.h> -# include <sys/sockio.h> -# include <sys/stropts.h> -# endif -# ifdef __EMX__ -# define link rename -# define chown(a,b,c) -# include <io.h> -# endif -#endif /* __GNU__ */ - -struct AuthProtocol { - unsigned short name_length; - const char *name; - void (*InitAuth)( unsigned short len, const char *name ); - Xauth *(*GetAuth)( unsigned short len, const char *name ); -#ifdef XDMCP - void (*GetXdmcpAuth)( struct protoDisplay *pdpy, - unsigned short authorizationNameLen, - const char *authorizationName ); -#endif - int inited; -}; - -#ifdef XDMCP -# define xdmcpauth(arg) , arg -#else -# define xdmcpauth(arg) -#endif - -static struct AuthProtocol AuthProtocols[] = { -{ (unsigned short)18, "MIT-MAGIC-COOKIE-1", - MitInitAuth, MitGetAuth xdmcpauth(NULL), 0 -}, -#ifdef HASXDMAUTH -{ (unsigned short)19, "XDM-AUTHORIZATION-1", - XdmInitAuth, XdmGetAuth xdmcpauth(XdmGetXdmcpAuth), 0 -}, -#endif -#ifdef SECURE_RPC -{ (unsigned short)9, "SUN-DES-1", - SecureRPCInitAuth, SecureRPCGetAuth xdmcpauth(NULL), 0 -}, -#endif -#ifdef K5AUTH -{ (unsigned short)14, "MIT-KERBEROS-5", - Krb5InitAuth, Krb5GetAuth xdmcpauth(NULL), 0 -}, -#endif -}; - -static struct AuthProtocol * -findProtocol( unsigned short name_length, const char *name ) -{ - unsigned i; - - for (i = 0; i < as(AuthProtocols); i++) - if (AuthProtocols[i].name_length == name_length && - memcmp( AuthProtocols[i].name, name, name_length ) == 0) - { - return &AuthProtocols[i]; - } - return (struct AuthProtocol *)0; -} - -int -ValidAuthorization( unsigned short name_length, const char *name ) -{ - if (findProtocol( name_length, name )) - return TRUE; - return FALSE; -} - -static Xauth * -GenerateAuthorization( unsigned short name_length, const char *name ) -{ - struct AuthProtocol *a; - Xauth *auth = 0; - - Debug( "GenerateAuthorization %s\n", name ); - if ((a = findProtocol( name_length, name ))) { - if (!a->inited) { - (*a->InitAuth)( name_length, name ); - a->inited = TRUE; - } - auth = (*a->GetAuth)( name_length, name ); - if (auth) { - Debug( "got %p (%d %.*s) %02[*hhx\n", auth, - auth->name_length, auth->name_length, auth->name, - auth->data_length, auth->data ); - } else - Debug( "got (null)\n" ); - } else - Debug( "unknown authorization %s\n", name ); - return auth; -} - -#ifdef XDMCP - -void -SetProtoDisplayAuthorization( struct protoDisplay *pdpy, - unsigned short authorizationNameLen, - const char *authorizationName ) -{ - struct AuthProtocol *a; - Xauth *auth; - - a = findProtocol( authorizationNameLen, authorizationName ); - pdpy->xdmcpAuthorization = pdpy->fileAuthorization = 0; - if (a) { - if (!a->inited) { - (*a->InitAuth)( authorizationNameLen, authorizationName ); - a->inited = TRUE; - } - if (a->GetXdmcpAuth) { - (*a->GetXdmcpAuth)( pdpy, authorizationNameLen, authorizationName ); - auth = pdpy->xdmcpAuthorization; - } else { - auth = (*a->GetAuth)( authorizationNameLen, authorizationName ); - pdpy->fileAuthorization = auth; - pdpy->xdmcpAuthorization = 0; - } - if (auth) - Debug( "got %p (%d %.*s)\n", auth, - auth->name_length, auth->name_length, auth->name ); - else - Debug( "got (null)\n" ); - } -} - -#endif /* XDMCP */ - -void -CleanUpFileName( const char *src, char *dst, int len ) -{ - while (*src) { - if (--len <= 0) - break; - switch (*src & 0x7f) { - case '/': - *dst++ = '_'; - break; - case '-': - *dst++ = '.'; - break; - default: - *dst++ = (*src & 0x7f); - } - ++src; - } - *dst = '\0'; -} - - -static FILE * -fdOpenW( int fd ) -{ - FILE *f; - - if (fd >= 0) { - if ((f = fdopen( fd, "w" ))) - return f; - close( fd ); - } - return 0; -} - -static FILE * -mkTempFile( char *nambuf, int namelen ) -{ - FILE *f; - int r; - - for (r = 0; r < 100; r++) { - randomStr( nambuf + namelen ); - if ((f = fdOpenW( open( nambuf, O_WRONLY | O_CREAT | O_EXCL, 0600 ) ))) - return f; - if (errno != EEXIST) - break; - } - return 0; -} - -#define NAMELEN 255 - -static FILE * -MakeServerAuthFile( struct display *d ) -{ - FILE *f; - int i; - char cleanname[NAMELEN], nambuf[NAMELEN+128]; - - /* - * Some paranoid, but still not sufficient (DoS was still possible) - * checks used to be here. I removed all this stuff because - * a) authDir is supposed to be /var/run/xauth (=safe) or similar and - * b) even if it's not (say, /tmp), we create files safely (hopefully). - */ - if (mkdir( authDir, 0755 ) < 0 && errno != EEXIST) - return 0; - CleanUpFileName( d->name, cleanname, NAMELEN - 8 ); - i = sprintf( nambuf, "%s/A%s-", authDir, cleanname ); - if ((f = mkTempFile( nambuf, i ))) { - StrDup( &d->authFile, nambuf ); - return f; - } - return 0; -} - -int -SaveServerAuthorizations( struct display *d, Xauth **auths, int count ) -{ - FILE *auth_file; - int i; - - if (!d->authFile && d->clientAuthFile && *d->clientAuthFile) - StrDup( &d->authFile, d->clientAuthFile ); - if (d->authFile) { - if (!(auth_file = fdOpenW( creat( d->authFile, 0600 ) ))) { - LogError( "Cannot open X server authorization file %s\n", d->authFile ); - free( d->authFile ); - d->authFile = NULL; - return FALSE; - } - } else { - if (!(auth_file = MakeServerAuthFile( d ))) { - LogError( "Cannot create X server authorization file\n" ); - return FALSE; - } - } - Debug( "file: %s auth: %p\n", d->authFile, auths ); - for (i = 0; i < count; i++) { - /* - * User-based auths may not have data until - * a user logs in. In which case don't write - * to the auth file so xrdb and setup programs don't fail. - */ - if (auths[i]->data_length > 0) - if (!XauWriteAuth( auth_file, auths[i] ) || - fflush( auth_file ) == EOF) - { - fclose( auth_file ); - LogError( "Cannot write X server authorization file %s\n", - d->authFile ); - free( d->authFile ); - d->authFile = NULL; - return FALSE; - } - } - fclose( auth_file ); - return TRUE; -} - -void -SetLocalAuthorization( struct display *d ) -{ - Xauth *auth, **auths; - int i, j; - - if (d->authorizations) - { - for (i = 0; i < d->authNum; i++) - XauDisposeAuth( d->authorizations[i] ); - free( (char *)d->authorizations ); - d->authorizations = (Xauth **)NULL; - d->authNum = 0; - } - Debug( "SetLocalAuthorization %s, auths %[s\n", d->name, d->authNames ); - if (!d->authNames) - return; - for (i = 0; d->authNames[i]; i++) - ; - d->authNameNum = i; - if (d->authNameLens) - free( (char *)d->authNameLens ); - d->authNameLens = (unsigned short *)Malloc( d->authNameNum * sizeof(unsigned short) ); - if (!d->authNameLens) - return; - for (i = 0; i < d->authNameNum; i++) - d->authNameLens[i] = strlen( d->authNames[i] ); - auths = (Xauth **)Malloc( d->authNameNum * sizeof(Xauth *) ); - if (!auths) - return; - j = 0; - for (i = 0; i < d->authNameNum; i++) { - auth = GenerateAuthorization( d->authNameLens[i], d->authNames[i] ); - if (auth) - auths[j++] = auth; - } - if (SaveServerAuthorizations( d, auths, j )) { - d->authorizations = auths; - d->authNum = j; - } else { - for (i = 0; i < j; i++) - XauDisposeAuth( auths[i] ); - free( (char *)auths ); - } -} - -/* - * Set the authorization to use for xdm's initial connection - * to the X server. Cannot use user-based authorizations - * because no one has logged in yet, so we don't have any - * user credentials. - * Well, actually we could use SUN-DES-1 because we tell the server - * to allow root in. This is bogus and should be fixed. - */ -void -SetAuthorization( struct display *d ) -{ - register Xauth **auth = d->authorizations; - int i; - - for (i = 0; i < d->authNum; i++) { - if (auth[i]->name_length == 9 && - memcmp( auth[i]->name, "SUN-DES-1", 9 ) == 0) - continue; - if (auth[i]->name_length == 14 && - memcmp( auth[i]->name, "MIT-KERBEROS-5", 14 ) == 0) - continue; - XSetAuthorization( auth[i]->name, (int)auth[i]->name_length, - auth[i]->data, (int)auth[i]->data_length ); - } -} - -static int -openFiles( const char *name, char *new_name, FILE **oldp, FILE **newp ) -{ - strcat( strcpy( new_name, name ), "-n" ); - if (!(*newp = - fdOpenW( creat( new_name, 0600 ) ))) { - Debug( "can't open new file %s\n", new_name ); - return 0; - } - *oldp = fopen( name, "r" ); - Debug( "opens succeeded %s %s\n", name, new_name ); - return 1; -} - -struct addrList { - struct addrList *next; - unsigned short family, address_length, number_length; - char data[1]; -}; - -static struct addrList *addrs; - -static void -initAddrs( void ) -{ - addrs = 0; -} - -static void -doneAddrs( void ) -{ - struct addrList *a, *n; - for (a = addrs; a; a = n) { - n = a->next; - free( a ); - } -} - -static void -saveEntry( Xauth *auth ) -{ - struct addrList *new; - - if (!(new = Malloc( offsetof(struct addrList, data) + - auth->address_length + auth->number_length ))) - return; - new->address_length = auth->address_length; - new->number_length = auth->number_length; - memcpy( new->data, auth->address, (int)auth->address_length ); - memcpy( new->data + (int)auth->address_length, - auth->number, (int)auth->number_length ); - new->family = auth->family; - new->next = addrs; - addrs = new; -} - -static int -checkEntry( Xauth *auth ) -{ - struct addrList *a; - - for (a = addrs; a; a = a->next) - if (a->family == auth->family && - a->address_length == auth->address_length && - !memcmp( a->data, auth->address, auth->address_length ) && - a->number_length == auth->number_length && - !memcmp( a->data + a->address_length, - auth->number, auth->number_length )) - return 1; - return 0; -} - -static void -writeAuth( FILE *file, Xauth *auth, int *ok ) -{ - if (debugLevel & DEBUG_AUTH) /* normally too verbose */ - Debug( "writeAuth: doWrite = %d\n" - "family: %d\n" - "addr: %02[*:hhx\n" - "number: %02[*:hhx\n" - "name: %02[*:hhx\n" - "data: %02[*:hhx\n", - ok != 0, auth->family, - auth->address_length, auth->address, - auth->number_length, auth->number, - auth->name_length, auth->name, - auth->data_length, auth->data ); - if (ok && !XauWriteAuth( file, auth )) - *ok = FALSE; -} - -static void -writeAddr( int family, int addr_length, char *addr, - FILE *file, Xauth *auth, int *ok ) -{ - auth->family = (unsigned short)family; - auth->address_length = addr_length; - auth->address = addr; - Debug( "writeAddr: writing and saving an entry\n" ); - writeAuth( file, auth, ok ); - if (!checkEntry( auth )) - saveEntry( auth ); -} - -static void -DefineLocal( FILE *file, Xauth *auth, int *ok ) -{ -#if !defined(NEED_UTSNAME) || defined(__hpux) - char displayname[100]; -#endif -#ifdef NEED_UTSNAME - struct utsname name; -#endif - - /* stolen from xinit.c */ - -/* Make sure this produces the same string as _XGetHostname in lib/X/XlibInt.c. - * Otherwise, Xau will not be able to find your cookies in the Xauthority file. - * - * Note: POSIX says that the ``nodename'' member of utsname does _not_ have - * to have sufficient information for interfacing to the network, - * and so, you may be better off using gethostname (if it exists). - */ - -#ifdef NEED_UTSNAME - - /* hpux: - * 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 ); - writeAddr( FamilyLocal, strlen( name.nodename ), name.nodename, - file, auth, ok ); -#endif - -#if !defined(NEED_UTSNAME) || defined(__hpux) - /* _AIX: - * In _AIX, _POSIX_SOURCE is defined, but uname gives only first - * field of hostname. Thus, we use gethostname instead. - */ - - /* - * For HP-UX, HP's Xlib expects a fully-qualified domain name, which - * is achieved by using gethostname(). For compatability, we must - * also still create the entry using uname() above. - */ - displayname[0] = 0; - if (!gethostname( displayname, sizeof(displayname) )) - displayname[sizeof(displayname) - 1] = 0; - -# ifdef NEED_UTSNAME - /* - * If gethostname and uname both returned the same name, - * do not write a duplicate entry. - */ - if (strcmp( displayname, name.nodename )) -# endif - writeAddr( FamilyLocal, strlen( displayname ), displayname, - file, auth, ok ); -#endif -} - -#ifdef SYSV_SIOCGIFCONF - -/* Deal with different SIOCGIFCONF ioctl semantics on SYSV, SVR4 */ - -int -ifioctl (int fd, int cmd, char *arg) -{ - struct strioctl ioc; - int ret; - - bzero( (char *)&ioc, sizeof(ioc) ); - ioc.ic_cmd = cmd; - ioc.ic_timout = 0; - if (cmd == SIOCGIFCONF) { - ioc.ic_len = ((struct ifconf *)arg)->ifc_len; - ioc.ic_dp = ((struct ifconf *)arg)->ifc_buf; - } else { - ioc.ic_len = sizeof(struct ifreq); - ioc.ic_dp = arg; - } - ret = ioctl( fd, I_STR, (char *)&ioc ); - if (ret >= 0 && cmd == SIOCGIFCONF) - ((struct ifconf *)arg)->ifc_len = ioc.ic_len; - return (ret); -} - -#endif /* SYSV_SIOCGIFCONF */ - -#ifdef HAVE_GETIFADDRS -# include <ifaddrs.h> - -static void -DefineSelf( FILE *file, Xauth *auth, int *ok ) -{ - struct ifaddrs *ifap, *ifr; - char *addr; - int family, len; - - if (getifaddrs( &ifap ) < 0) - return; - for (ifr = ifap; ifr; ifr = ifr->ifa_next) { - if (!ifr->ifa_addr) - continue; - family = ConvertAddr( (char *)(ifr->ifa_addr), &len, &addr ); - if (family == -1 || family == FamilyLocal) - continue; - /* - * don't write out 'localhost' entries, as - * they may conflict with other local entries. - * DefineLocal will always be called to add - * the local entry anyway, so this one can - * be tossed. - */ - if (family == FamilyInternet && - addr[0] == 127 && addr[1] == 0 && addr[2] == 0 && addr[3] == 1) - { - Debug( "Skipping localhost address\n" ); - continue; - } -# if defined(IPv6) && defined(AF_INET6) - if (family == FamilyInternet6) { - if (IN6_IS_ADDR_LOOPBACK( ((struct in6_addr *)addr) )) { - Debug( "Skipping IPv6 localhost address\n" ); - continue; - } - /* Also skip XDM-AUTHORIZATION-1 */ - if (auth->name_length == 19 && - !memcmp( auth->name, "XDM-AUTHORIZATION-1", 19 )) { - Debug( "Skipping IPv6 XDM-AUTHORIZATION-1\n" ); - continue; - } - } -# endif - writeAddr( family, len, addr, file, auth, ok ); - } - freeifaddrs( ifap ); -} -#else /* GETIFADDRS */ - -#if defined(STREAMSCONN) && !defined(SYSV_SIOCGIFCONF) && !defined(WINTCP) - -#include <tiuser.h> - -/* Define this host for access control. Find all the hosts the OS knows about - * for this fd and add them to the selfhosts list. - * TLI version, written without sufficient documentation. - */ -static void -DefineSelf( int fd, FILE *file, Xauth *auth, int *ok ) -{ - struct netbuf netb; - char addrret[1024]; /* easier than t_alloc */ - - netb.maxlen = sizeof(addrret); - netb.buf = addrret; - if (t_getname( fd, &netb, LOCALNAME ) == -1) - t_error( "t_getname" ); - /* what a kludge */ - writeAddr( FamilyInternet, 4, netb.buf+4, file, auth, ok ); -} - -#else - -#ifdef WINTCP /* NCR with Wollongong TCP */ - -#include <stropts.h> -#include <tiuser.h> - -#include <sys/stream.h> -#include <net/if.h> -#include <netinet/ip.h> -#include <netinet/ip_var.h> -#include <netinet/in.h> -#include <netinet/in_var.h> - -static void -DefineSelf( int fd, FILE *file, Xauth *auth, int *ok ) -{ - /* - * The Wollongong drivers used by NCR SVR4/MP-RAS don't understand the - * socket IO calls that most other drivers seem to like. Because of - * this, this routine must be special cased for NCR. Eventually, - * this will be cleared up. - */ - - struct ipb ifnet; - struct in_ifaddr ifaddr; - struct strioctl str; - unsigned char *addr; - int len, ipfd; - - if ((ipfd = open( "/dev/ip", O_RDWR, 0 )) < 0) { - LogError( "Trouble getting interface configuration\n" ); - return; - } - - /* Indicate that we want to start at the begining */ - ifnet.ib_next = (struct ipb *)1; - - while (ifnet.ib_next) { - str.ic_cmd = IPIOC_GETIPB; - str.ic_timout = 0; - str.ic_len = sizeof(struct ipb); - str.ic_dp = (char *)&ifnet; - - if (ioctl( ipfd, (int)I_STR, (char *)&str ) < 0) { - close( ipfd ); - LogError( "Trouble getting interface configuration\n" ); - return; - } - - ifaddr.ia_next = (struct in_ifaddr *)ifnet.if_addrlist; - str.ic_cmd = IPIOC_GETINADDR; - str.ic_timout = 0; - str.ic_len = sizeof(struct in_ifaddr); - str.ic_dp = (char *)&ifaddr; - - if (ioctl( ipfd, (int)I_STR, (char *)&str ) < 0) { - close( ipfd ); - LogError( "Trouble getting interface configuration\n" ); - return; - } - - /* - * Ignore the 127.0.0.1 entry. - */ - if (IA_SIN( &ifaddr )->sin_addr.s_addr == htonl( 0x7f000001 ) ) - continue; - - writeAddr( FamilyInternet, 4, (char *)&(IA_SIN( &ifaddr )->sin_addr), - file, auth, ok ); - - } - close( ipfd ); -} - -#else /* WINTCP */ - -/* 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 - -#if defined(SIOCGIFCONF) || defined (USE_SIOCGLIFCONF) - -#if !defined(SYSV_SIOCGIFCONF) || defined(USE_SIOCGLIFCONF) -# define ifioctl ioctl -#endif - -#ifdef USE_SIOCGLIFCONF -# define ifr_type struct lifreq -#else -# define ifr_type struct ifreq -#endif - -/* Handle variable length ifreq in BNR2 and later */ -#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)) -#else -# define ifr_size(p) (sizeof(ifr_type)) -#endif - -#ifdef USE_SIOCGLIFCONF -# define IFC_IOCTL_REQ SIOCGLIFCONF -# define IFC_REQ(ifc) ifc.lifc_req -# define IFC_LEN(ifc) ifc.lifc_len -# define IFR_ADDR(ifr) ifr->lifr_addr -# define IFR_NAME(ifr) ifr->lifr_name -#else -# define IFC_IOCTL_REQ SIOCGIFCONF -# define IFC_REQ(ifc) ifc.ifc_req -# define IFC_LEN(ifc) ifc.ifc_len -# define IFR_ADDR(ifr) ifr->ifr_addr -# define IFR_NAME(ifr) ifr->ifr_name -#endif - -/* Define this host for access control. Find all the hosts the OS knows about - * for this fd and add them to the selfhosts list. - */ -static void -DefineSelf( int fd, FILE *file, Xauth *auth, int *ok ) -{ - char buf[2048], *cp, *cplim; - int len; - char *addr; - int family; - ifr_type *ifr; -#ifdef USE_SIOCGLIFCONF - int n; - void * bufptr = buf; - size_t buflen = sizeof(buf); - struct lifconf ifc; -# ifdef SIOCGLIFNUM - struct lifnum ifn; -# endif -#else - struct ifconf ifc; -#endif - -#if defined(SIOCGLIFNUM) && defined(SIOCGLIFCONF) - ifn.lifn_family = AF_UNSPEC; - ifn.lifn_flags = 0; - if (ioctl( fd, (int)SIOCGLIFNUM, (char *)&ifn ) < 0) - LogError( "Failed getting interface count\n" ); - if (buflen < (ifn.lifn_count * sizeof(struct lifreq))) { - buflen = ifn.lifn_count * sizeof(struct lifreq); - bufptr = Malloc( buflen ); - } -#endif - -#ifdef USE_SIOCGLIFCONF - ifc.lifc_family = AF_UNSPEC; - ifc.lifc_flags = 0; - ifc.lifc_len = buflen; - ifc.lifc_buf = bufptr; -#else - ifc.ifc_len = sizeof(buf); - ifc.ifc_buf = buf; -#endif - if (ifioctl (fd, IFC_IOCTL_REQ, (char *)&ifc) < 0) { - LogError( "Trouble getting network interface configuration\n" ); -#if defined(SIOCGLIFNUM) && defined(SIOCGLIFCONF) - if (bufptr != buf) - free( bufptr ); -#endif - return; - } - - cplim = (char *)IFC_REQ( ifc ) + IFC_LEN( ifc ); - - for (cp = (char *)IFC_REQ( ifc ); cp < cplim; cp += ifr_size (ifr)) { - ifr = (ifr_type *) cp; -#ifdef DNETCONN - /* - * this is ugly but SIOCGIFCONF returns decnet addresses in - * a different form from other decnet calls - */ - if (IFR_ADDR( ifr ).sa_family == AF_DECnet) { - len = sizeof(struct dn_naddr); - addr = (char *)IFR_ADDR( ifr ).sa_data; - family = FamilyDECnet; - } else -#endif - { - family = ConvertAddr( (char *)&IFR_ADDR( ifr ), &len, &addr ); - if (family < 0) - continue; - - if (len == 0) { - Debug( "skipping zero length address\n" ); - continue; - } - /* - * don't write out 'localhost' entries, as - * they may conflict with other local entries. - * DefineLocal will always be called to add - * the local entry anyway, so this one can - * be tossed. - */ - if (family == FamilyInternet && - addr[0] == 127 && addr[1] == 0 && - addr[2] == 0 && addr[3] == 1) - { - Debug( "skipping localhost address\n" ); - continue; - } -#if defined(IPv6) && defined(AF_INET6) - if (family == FamilyInternet6) { - if (IN6_IS_ADDR_LOOPBACK( ((struct in6_addr *)addr) )) { - Debug( "Skipping IPv6 localhost address\n" ); - continue; - } - /* Also skip XDM-AUTHORIZATION-1 */ - if (auth->name_length == 19 && - !memcmp( auth->name, "XDM-AUTHORIZATION-1", 19 )) { - Debug( "Skipping IPv6 XDM-AUTHORIZATION-1\n" ); - continue; - } - } -#endif - } - Debug( "DefineSelf: write network address, length %d\n", len ); - writeAddr( family, len, addr, file, auth, ok ); - } -#if defined(SIOCGLIFNUM) && defined(SIOCGLIFCONF) - if (bufptr != buf) - free( bufptr ); -#endif -} - -#else /* SIOCGIFCONF */ - -/* Define this host for access control. Find all the hosts the OS knows about - * for this fd and add them to the selfhosts list. - */ -static void -DefineSelf( int fd, int file, int auth, int *ok ) -{ - int len; - caddr_t addr; - int family; - - struct utsname name; - register struct hostent *hp; - - union { - struct sockaddr sa; - struct sockaddr_in in; - } saddr; - - struct sockaddr_in *inetaddr; - - /* hpux: - * 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 ); - if ((hp = gethostbyname( name.nodename ))) { - saddr.sa.sa_family = hp->h_addrtype; - inetaddr = (struct sockaddr_in *)(&(saddr.sa)); - memmove( (char *)&(inetaddr->sin_addr), (char *)hp->h_addr, - (int)hp->h_length ); - if ( (family = ConvertAddr( &(saddr.sa), &len, &addr )) >= 0) - writeAddr( FamilyInternet, sizeof(inetaddr->sin_addr), - (char *)(&inetaddr->sin_addr), file, auth, ok ); - } -} - -#endif /* SIOCGIFCONF else */ -#endif /* WINTCP else */ -#endif /* STREAMSCONN && !SYSV_SIOCGIFCONF else */ -#endif /* HAVE_GETIFADDRS */ - -static void -setAuthNumber( Xauth *auth, const char *name ) -{ - char *colon; - char *dot; - - Debug( "setAuthNumber %s\n", name ); - colon = strrchr( name, ':' ); - if (colon) { - ++colon; - dot = strchr( colon, '.' ); - if (dot) - auth->number_length = dot - colon; - else - auth->number_length = strlen( colon ); - if (!StrNDup( &auth->number, colon, auth->number_length )) - auth->number_length = 0; - Debug( "setAuthNumber: %s\n", auth->number ); - } -} - -static void -writeLocalAuth( FILE *file, Xauth *auth, const char *name, int *ok ) -{ -#if defined(STREAMSCONN) || !defined(HAVE_GETIFADDRS) - int fd; -#endif - - Debug( "writeLocalAuth: %s %.*s\n", name, auth->name_length, auth->name ); - setAuthNumber( auth, name ); -# ifdef STREAMSCONN - fd = t_open( "/dev/tcp", O_RDWR, 0 ); - t_bind( fd, NULL, NULL ); - DefineSelf( fd, file, auth, ok ); - t_unbind( fd ); - t_close( fd ); -# elif defined(HAVE_GETIFADDRS) - DefineSelf( file, auth, ok ); -# else -# ifdef TCPCONN -# if defined(IPv6) && defined(AF_INET6) - fd = socket( AF_INET6, SOCK_STREAM, 0 ); - if (fd < 0) -# endif - fd = socket( AF_INET, SOCK_STREAM, 0 ); - DefineSelf( fd, file, auth, ok ); - close( fd ); -# endif -# ifdef DNETCONN - fd = socket( AF_DECnet, SOCK_STREAM, 0 ); - DefineSelf( fd, file, auth, ok ); - close( fd ); -# endif -# endif /* HAVE_GETIFADDRS */ - DefineLocal( file, auth, ok ); -} - -#ifdef XDMCP - -/* - * Call ConvertAddr(), and if it returns an IPv4 localhost, convert it - * to a local display name. Meets the _XTransConvertAddress's localhost - * hack. - */ - -static int -ConvertAuthAddr( char *saddr, int *len, char **addr ) -{ - int ret = ConvertAddr( saddr, len, addr ); - if (ret == FamilyInternet && - ((struct in_addr *)*addr)->s_addr == htonl( 0x7F000001L )) - ret = FamilyLocal; - return ret; -} - -static void -writeRemoteAuth( FILE *file, Xauth *auth, XdmcpNetaddr peer, int peerlen, - const char *name, int *ok ) -{ - int family = FamilyLocal; - char *addr; - - Debug( "writeRemoteAuth: %s %.*s\n", name, auth->name_length, auth->name ); - if (!peer || peerlen < 2) - return; - setAuthNumber( auth, name ); - family = ConvertAuthAddr( peer, &peerlen, &addr ); - Debug( "writeRemoteAuth: family %d\n", family ); - if (family != FamilyLocal) { - Debug( "writeRemoteAuth: %d, %02[*:hhx\n", - family, peerlen, addr ); - writeAddr( family, peerlen, addr, file, auth, ok ); - } else - writeLocalAuth( file, auth, name, ok ); -} - -#endif /* XDMCP */ - -#define NBSIZE 1024 - -static void -startUserAuth( char *buf, char *nbuf, FILE **old, FILE **new ) -{ - const char *home; - int lockStatus; - - initAddrs(); - *new = 0; - if ((home = getEnv( userEnviron, "HOME" )) && strlen( home ) < NBSIZE - 12) { - sprintf( buf, "%s/.Xauthority", home ); - Debug( "XauLockAuth %s\n", buf ); - lockStatus = XauLockAuth( buf, 1, 2, 10 ); - Debug( "lock is %d\n", lockStatus ); - if (lockStatus == LOCK_SUCCESS) - if (!openFiles( buf, nbuf, old, new )) - XauUnlockAuth( buf ); - } - if (!*new) - LogWarn( "Can't update authorization file in home dir %s\n", home ); -} - -static int -endUserAuth( FILE *old, FILE *new, const char *nname, int ok ) -{ - Xauth *entry; - struct stat statb; - - if (old) { - if (fstat( fileno( old ), &statb ) != -1) - chmod( nname, (int)(statb.st_mode & 0777) ); - /*SUPPRESS 560*/ - while ((entry = XauReadAuth( old ))) { - if (!checkEntry( entry )) { - Debug( "writing an entry\n" ); - writeAuth( new, entry, &ok ); - } - XauDisposeAuth( entry ); - } - fclose( old ); - } - if (fclose( new ) == EOF) - ok = FALSE; - doneAddrs(); - return ok; -} - -static void -undoUserAuth( const char *name, const char *new_name ) -{ - LogWarn( "Can't save user authorization in home dir\n" ); - unlink( new_name ); - XauUnlockAuth( name ); -} - -static char * -moveUserAuth( const char *name, char *new_name, char *envname ) -{ - if (unlink( name )) - Debug( "unlink %s failed\n", name ); - if (link( new_name, name )) { - Debug( "link failed %s %s\n", new_name, name ); - LogError( "Can't move user authorization into place\n" ); - envname = new_name; - } else { - Debug( "new authorization moved into place\n" ); - unlink( new_name ); - } - XauUnlockAuth( name ); - return envname; -} - -void -SetUserAuthorization( struct display *d ) -{ - FILE *old, *new; - char *name; - char *envname; - Xauth **auths; - int i, ok; - int magicCookie; - int data_len; - char name_buf[NBSIZE], new_name[NBSIZE + 2]; - - Debug( "SetUserAuthorization\n" ); - auths = d->authorizations; - if (auths) { - startUserAuth( name_buf, new_name, &old, &new ); - if (new) { - envname = 0; - name = name_buf; - } else { - fallback: - if (strlen( d->userAuthDir ) >= NBSIZE - 13) - return; - /* - * Note, that we don't lock the auth file here, as it's - * temporary - we can assume, that we are the only ones - * knowing about this file anyway. - */ - i = sprintf( name_buf, "%s/.Xauth", d->userAuthDir ); - new = mkTempFile( name_buf, i ); - if (!new) { - LogError( "Can't create authorization file in %s\n", - d->userAuthDir ); - return; - } - name = 0; - envname = name_buf; - old = 0; - } - ok = TRUE; - Debug( "%d authorization protocols for %s\n", d->authNum, d->name ); - /* - * Write MIT-MAGIC-COOKIE-1 authorization first, so that - * R4 clients which only knew that, and used the first - * matching entry will continue to function - */ - magicCookie = -1; - for (i = 0; i < d->authNum; i++) { - if (auths[i]->name_length == 18 && - !memcmp( auths[i]->name, "MIT-MAGIC-COOKIE-1", 18 )) - { - magicCookie = i; - if ((d->displayType & d_location) == dLocal) - writeLocalAuth( new, auths[i], d->name, &ok ); -#ifdef XDMCP - else - writeRemoteAuth( new, auths[i], (XdmcpNetaddr)d->peer.data, - d->peer.length, d->name, &ok ); -#endif - break; - } - } - /* now write other authorizations */ - for (i = 0; i < d->authNum; i++) { - if (i != magicCookie) { - data_len = auths[i]->data_length; - /* client will just use default Kerberos cache, so don't - * even write cache info into the authority file. - */ - if (auths[i]->name_length == 14 && - !strncmp( auths[i]->name, "MIT-KERBEROS-5", 14 )) - auths[i]->data_length = 0; - if ((d->displayType & d_location) == dLocal) - writeLocalAuth( new, auths[i], d->name, &ok ); -#ifdef XDMCP - else - writeRemoteAuth( new, auths[i], (XdmcpNetaddr)d->peer.data, - d->peer.length, d->name, &ok ); -#endif - auths[i]->data_length = data_len; - } - } - if (!endUserAuth( old, new, new_name, ok )) { - if (!name) { - LogError( "Can't save user authorization\n" ); - return; - } - undoUserAuth( name, new_name ); - initAddrs(); - goto fallback; - } - if (name) - envname = moveUserAuth( name, new_name, envname ); - if (envname) { - userEnviron = setEnv( userEnviron, "XAUTHORITY", envname ); - systemEnviron = setEnv( systemEnviron, "XAUTHORITY", envname ); - } - /* a chown() used to be here, but this code runs as user anyway */ - } - Debug( "done SetUserAuthorization\n" ); -} - -void -RemoveUserAuthorization( struct display *d ) -{ - Xauth **auths; - FILE *old, *new; - int i; - char name[NBSIZE], new_name[NBSIZE + 2]; - - if (!(auths = d->authorizations)) - return; - Debug( "RemoveUserAuthorization\n" ); - startUserAuth( name, new_name, &old, &new ); - if (new) { - for (i = 0; i < d->authNum; i++) { - if ((d->displayType & d_location) == dLocal) - writeLocalAuth( new, auths[i], d->name, 0 ); -#ifdef XDMCP - else - writeRemoteAuth( new, auths[i], (XdmcpNetaddr)d->peer.data, - d->peer.length, d->name, 0 ); -#endif - } - if (endUserAuth( old, new, new_name, TRUE )) - (void)moveUserAuth( name, new_name, 0 ); - else - undoUserAuth( name, new_name ); - } - Debug( "done RemoveUserAuthorization\n" ); -} |