auth.c revision b7d26471
1629baa8cSmrg/* 2629baa8cSmrg 3629baa8cSmrgCopyright 1988, 1998 The Open Group 4629baa8cSmrg 5629baa8cSmrgPermission to use, copy, modify, distribute, and sell this software and its 6629baa8cSmrgdocumentation for any purpose is hereby granted without fee, provided that 7629baa8cSmrgthe above copyright notice appear in all copies and that both that 8629baa8cSmrgcopyright notice and this permission notice appear in supporting 9629baa8cSmrgdocumentation. 10629baa8cSmrg 11629baa8cSmrgThe above copyright notice and this permission notice shall be included 12629baa8cSmrgin all copies or substantial portions of the Software. 13629baa8cSmrg 14629baa8cSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15629baa8cSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16629baa8cSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17629baa8cSmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 18629baa8cSmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19629baa8cSmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20629baa8cSmrgOTHER DEALINGS IN THE SOFTWARE. 21629baa8cSmrg 22629baa8cSmrgExcept as contained in this notice, the name of The Open Group shall 23629baa8cSmrgnot be used in advertising or otherwise to promote the sale, use or 24629baa8cSmrgother dealings in this Software without prior written authorization 25629baa8cSmrgfrom The Open Group. 26629baa8cSmrg 27629baa8cSmrg*/ 28629baa8cSmrg 29629baa8cSmrg/* 30629baa8cSmrg * xdm - display manager daemon 31629baa8cSmrg * Author: Keith Packard, MIT X Consortium 32629baa8cSmrg * 33629baa8cSmrg * auth.c 34629baa8cSmrg * 35629baa8cSmrg * maintain the authorization generation daemon 36629baa8cSmrg */ 37629baa8cSmrg 38629baa8cSmrg#include <X11/X.h> 39629baa8cSmrg#include <X11/Xlibint.h> 40629baa8cSmrg#include <sys/types.h> 41629baa8cSmrg#include <sys/stat.h> 42629baa8cSmrg 43629baa8cSmrg#include "dm.h" 44629baa8cSmrg#include "dm_auth.h" 45629baa8cSmrg#include "dm_error.h" 46629baa8cSmrg 47629baa8cSmrg#include <errno.h> 48629baa8cSmrg 49629baa8cSmrg#include <sys/ioctl.h> 50629baa8cSmrg 51b7d26471Smrg#ifdef TCPCONN 52629baa8cSmrg# include "dm_socket.h" 53629baa8cSmrg#endif 54629baa8cSmrg 55629baa8cSmrg#if defined(hpux) 56629baa8cSmrg# include <sys/utsname.h> 57629baa8cSmrg#endif 58629baa8cSmrg 59629baa8cSmrg#if defined(SYSV) && defined(i386) 60629baa8cSmrg# include <sys/stream.h> 61629baa8cSmrg#endif /* i386 */ 62629baa8cSmrg 63629baa8cSmrg#ifdef SVR4 64629baa8cSmrg# include <netdb.h> 65629baa8cSmrg# include <sys/sockio.h> 66629baa8cSmrg# include <sys/stropts.h> 67629baa8cSmrg#endif 68629baa8cSmrg#ifdef __convex__ 69629baa8cSmrg# include <sync/queue.h> 70629baa8cSmrg# include <sync/sema.h> 71629baa8cSmrg#endif 72629baa8cSmrg#ifdef __GNU__ 73629baa8cSmrg# include <netdb.h> 74629baa8cSmrg# undef SIOCGIFCONF 75629baa8cSmrg#else /* __GNU__ */ 76629baa8cSmrg# include <net/if.h> 77629baa8cSmrg#endif /* __GNU__ */ 78629baa8cSmrg 79629baa8cSmrg#if defined(TCPCONN) && !defined(WIN32) 80629baa8cSmrg# include <netinet/in.h> 81629baa8cSmrg#endif 82629baa8cSmrg 83629baa8cSmrg/* Solaris provides an extended interface SIOCGLIFCONF for IPv6 support. 84629baa8cSmrg */ 85629baa8cSmrg#ifdef SIOCGLIFCONF 86629baa8cSmrg# define USE_SIOCGLIFCONF 87629baa8cSmrg#endif 88629baa8cSmrg 89b7d26471Smrg#if (defined(SVR4) && !defined(sun)) && \ 90629baa8cSmrg defined(SIOCGIFCONF) && !defined(USE_SIOCGLIFCONF) 91629baa8cSmrg# define SYSV_SIOCGIFCONF 92629baa8cSmrg#endif 93629baa8cSmrg 94629baa8cSmrg#ifdef HAVE_SYS_PARAM_H 95b7d26471Smrg# include <sys/param.h> 96629baa8cSmrg# ifdef BSD 97629baa8cSmrg# if (BSD >= 199103) 98629baa8cSmrg# define VARIABLE_IFREQ 99629baa8cSmrg# endif 100629baa8cSmrg# endif 101629baa8cSmrg#endif 102629baa8cSmrg 103629baa8cSmrg#ifdef __UNIXOS2__ 104629baa8cSmrg# define link rename 105629baa8cSmrgint chown(int a,int b,int c) {} 106629baa8cSmrg# include <io.h> 107629baa8cSmrg#endif 108629baa8cSmrg 109629baa8cSmrgstruct AuthProtocol { 110629baa8cSmrg unsigned short name_length; 111b7d26471Smrg const char *name; 112629baa8cSmrg void (*InitAuth)(unsigned short len, char *name); 113629baa8cSmrg Xauth *(*GetAuth)(unsigned short len, char *name); 114629baa8cSmrg void (*GetXdmcpAuth)( 115629baa8cSmrg struct protoDisplay *pdpy, 116629baa8cSmrg unsigned short authorizationNameLen, 117629baa8cSmrg char *authorizationName); 118629baa8cSmrg int inited; 119629baa8cSmrg}; 120629baa8cSmrg 121629baa8cSmrgstatic struct AuthProtocol AuthProtocols[] = { 122629baa8cSmrg{ (unsigned short) 18, "MIT-MAGIC-COOKIE-1", 123629baa8cSmrg MitInitAuth, MitGetAuth, NULL 124629baa8cSmrg}, 125629baa8cSmrg#ifdef HASXDMAUTH 126629baa8cSmrg{ (unsigned short) 19, "XDM-AUTHORIZATION-1", 127629baa8cSmrg XdmInitAuth, XdmGetAuth, XdmGetXdmcpAuth, 128629baa8cSmrg}, 129629baa8cSmrg#endif 130629baa8cSmrg#ifdef SECURE_RPC 131629baa8cSmrg{ (unsigned short) 9, "SUN-DES-1", 132629baa8cSmrg SecureRPCInitAuth, SecureRPCGetAuth, NULL, 133629baa8cSmrg}, 134629baa8cSmrg#endif 135629baa8cSmrg#ifdef K5AUTH 136629baa8cSmrg{ (unsigned short) 14, "MIT-KERBEROS-5", 137629baa8cSmrg Krb5InitAuth, Krb5GetAuth, NULL, 138629baa8cSmrg}, 139629baa8cSmrg#endif 140629baa8cSmrg}; 141629baa8cSmrg 142629baa8cSmrg#define NUM_AUTHORIZATION (sizeof (AuthProtocols) / sizeof (AuthProtocols[0])) 143629baa8cSmrg 144629baa8cSmrgstatic struct AuthProtocol * 145629baa8cSmrgfindProtocol (unsigned short name_length, char *name) 146629baa8cSmrg{ 147629baa8cSmrg int i; 148629baa8cSmrg 149629baa8cSmrg for (i = 0; i < NUM_AUTHORIZATION; i++) 150629baa8cSmrg if (AuthProtocols[i].name_length == name_length && 151629baa8cSmrg memcmp(AuthProtocols[i].name, name, name_length) == 0) 152629baa8cSmrg { 153629baa8cSmrg return &AuthProtocols[i]; 154629baa8cSmrg } 155629baa8cSmrg return (struct AuthProtocol *) 0; 156629baa8cSmrg} 157629baa8cSmrg 158629baa8cSmrgint 159629baa8cSmrgValidAuthorization (unsigned short name_length, char *name) 160629baa8cSmrg{ 161629baa8cSmrg if (findProtocol (name_length, name)) 162629baa8cSmrg return TRUE; 163629baa8cSmrg return FALSE; 164629baa8cSmrg} 165629baa8cSmrg 166629baa8cSmrgstatic Xauth * 167629baa8cSmrgGenerateAuthorization (unsigned short name_length, char *name) 168629baa8cSmrg{ 169629baa8cSmrg struct AuthProtocol *a; 170629baa8cSmrg Xauth *auth = NULL; 171629baa8cSmrg int i; 172629baa8cSmrg 173629baa8cSmrg Debug ("GenerateAuthorization %*.*s\n", 174629baa8cSmrg name_length, name_length, name); 175629baa8cSmrg a = findProtocol (name_length, name); 176629baa8cSmrg if (a) 177629baa8cSmrg { 178629baa8cSmrg if (!a->inited) 179629baa8cSmrg { 180629baa8cSmrg (*a->InitAuth) (name_length, name); 181629baa8cSmrg a->inited = TRUE; 182629baa8cSmrg } 183629baa8cSmrg auth = (*a->GetAuth) (name_length, name); 184629baa8cSmrg if (auth) 185629baa8cSmrg { 186629baa8cSmrg Debug ("Got %p (%d %*.*s) ", auth, 187629baa8cSmrg auth->name_length, auth->name_length, 188629baa8cSmrg auth->name_length, auth->name); 189629baa8cSmrg for (i = 0; i < (int)auth->data_length; i++) 190629baa8cSmrg Debug (" %02x", auth->data[i] & 0xff); 191629baa8cSmrg Debug ("\n"); 192629baa8cSmrg } 193629baa8cSmrg else 194629baa8cSmrg Debug ("Got (null)\n"); 195629baa8cSmrg } 196629baa8cSmrg else 197629baa8cSmrg { 198629baa8cSmrg Debug ("Unknown authorization %*.*s\n", name_length, name_length, name); 199629baa8cSmrg } 200629baa8cSmrg return auth; 201629baa8cSmrg} 202629baa8cSmrg 203629baa8cSmrg#ifdef XDMCP 204629baa8cSmrg 205629baa8cSmrgvoid 206629baa8cSmrgSetProtoDisplayAuthorization ( 207629baa8cSmrg struct protoDisplay *pdpy, 208629baa8cSmrg unsigned short authorizationNameLen, 209629baa8cSmrg char *authorizationName) 210629baa8cSmrg{ 211629baa8cSmrg struct AuthProtocol *a; 212629baa8cSmrg Xauth *auth; 213629baa8cSmrg 214629baa8cSmrg a = findProtocol (authorizationNameLen, authorizationName); 215629baa8cSmrg pdpy->xdmcpAuthorization = pdpy->fileAuthorization = NULL; 216629baa8cSmrg if (a) 217629baa8cSmrg { 218629baa8cSmrg if (!a->inited) 219629baa8cSmrg { 220629baa8cSmrg (*a->InitAuth) (authorizationNameLen, authorizationName); 221629baa8cSmrg a->inited = TRUE; 222629baa8cSmrg } 223629baa8cSmrg if (a->GetXdmcpAuth) 224629baa8cSmrg { 225629baa8cSmrg (*a->GetXdmcpAuth) (pdpy, authorizationNameLen, authorizationName); 226629baa8cSmrg auth = pdpy->xdmcpAuthorization; 227629baa8cSmrg } 228629baa8cSmrg else 229629baa8cSmrg { 230629baa8cSmrg auth = (*a->GetAuth) (authorizationNameLen, authorizationName); 231629baa8cSmrg pdpy->fileAuthorization = auth; 232629baa8cSmrg pdpy->xdmcpAuthorization = NULL; 233629baa8cSmrg } 234629baa8cSmrg if (auth) 235629baa8cSmrg Debug ("Got %p (%d %*.*s)\n", auth, 236629baa8cSmrg auth->name_length, auth->name_length, 237629baa8cSmrg auth->name_length, auth->name); 238629baa8cSmrg else 239629baa8cSmrg Debug ("Got (null)\n"); 240629baa8cSmrg } 241629baa8cSmrg} 242629baa8cSmrg 243629baa8cSmrg#endif /* XDMCP */ 244629baa8cSmrg 245629baa8cSmrgvoid 246629baa8cSmrgCleanUpFileName (char *src, char *dst, int len) 247629baa8cSmrg{ 248629baa8cSmrg while (*src) { 249629baa8cSmrg if (--len <= 0) 250629baa8cSmrg break; 251629baa8cSmrg switch (*src & 0x7f) 252629baa8cSmrg { 253629baa8cSmrg case '/': 254629baa8cSmrg *dst++ = '_'; 255629baa8cSmrg break; 256629baa8cSmrg case '-': 257629baa8cSmrg *dst++ = '.'; 258629baa8cSmrg break; 259629baa8cSmrg default: 260629baa8cSmrg *dst++ = (*src & 0x7f); 261629baa8cSmrg } 262629baa8cSmrg ++src; 263629baa8cSmrg } 264629baa8cSmrg *dst = '\0'; 265629baa8cSmrg} 266629baa8cSmrg 267629baa8cSmrg/* Checks to see if specified directory exists, makes it if not 268629baa8cSmrg * Returns: 0 if already exists, 1 if created, < 0 if error occured 269629baa8cSmrg */ 270629baa8cSmrgstatic int 271629baa8cSmrgCheckServerAuthDir (const char *path, struct stat *statb, int mode) 272629baa8cSmrg{ 273629baa8cSmrg int r = stat(path, statb); 274629baa8cSmrg 275629baa8cSmrg if (r != 0) { 276629baa8cSmrg if (errno == ENOENT) { 277629baa8cSmrg r = mkdir(path, mode); 278629baa8cSmrg if (r < 0) { 279629baa8cSmrg LogError ("cannot make authentication directory %s: %s\n", 280629baa8cSmrg path, _SysErrorMsg (errno)); 281629baa8cSmrg } else { 282629baa8cSmrg r = 1; 283629baa8cSmrg } 284629baa8cSmrg } else { 285629baa8cSmrg LogError ("cannot access authentication directory %s: %s\n", 286629baa8cSmrg path, _SysErrorMsg (errno)); 287629baa8cSmrg } 288629baa8cSmrg } else { /* Directory already exists */ 289629baa8cSmrg if (!S_ISDIR(statb->st_mode)) { 290629baa8cSmrg LogError ("cannot make authentication directory %s: %s\n", 291629baa8cSmrg path, "file with that name already exists"); 292629baa8cSmrg return -1; 293629baa8cSmrg } 294629baa8cSmrg } 295629baa8cSmrg 296629baa8cSmrg return r; 297629baa8cSmrg} 298629baa8cSmrg 299629baa8cSmrgstatic char authdir1[] = "authdir"; 300629baa8cSmrgstatic char authdir2[] = "authfiles"; 301629baa8cSmrg 302629baa8cSmrgstatic int 303629baa8cSmrgMakeServerAuthFile (struct display *d, FILE ** file) 304629baa8cSmrg{ 305629baa8cSmrg int len; 306629baa8cSmrg#ifdef MAXNAMELEN 307629baa8cSmrg# define NAMELEN MAXNAMELEN 308629baa8cSmrg#else 309629baa8cSmrg# define NAMELEN 255 310629baa8cSmrg#endif 311629baa8cSmrg char cleanname[NAMELEN]; 312629baa8cSmrg int r; 313629baa8cSmrg#ifdef HAVE_MKSTEMP 314629baa8cSmrg int fd; 315629baa8cSmrg#endif 316629baa8cSmrg struct stat statb; 317629baa8cSmrg 318629baa8cSmrg *file = NULL; 319629baa8cSmrg 320629baa8cSmrg if (!d->authFile) { 321629baa8cSmrg if (d->clientAuthFile && *d->clientAuthFile) { 322629baa8cSmrg d->authFile = strdup(d->clientAuthFile); 323629baa8cSmrg if (!d->authFile) 324629baa8cSmrg return FALSE; 325629baa8cSmrg } else { 326629baa8cSmrg CleanUpFileName (d->name, cleanname, NAMELEN - 8); 327629baa8cSmrg 328629baa8cSmrg /* Make authDir if it doesn't already exist */ 329629baa8cSmrg r = CheckServerAuthDir(authDir, &statb, 0755); 330629baa8cSmrg if (r < 0) { 331629baa8cSmrg return FALSE; 332629baa8cSmrg } 333629baa8cSmrg 334629baa8cSmrg len = strlen (authDir) + strlen (authdir1) + strlen (authdir2) 335629baa8cSmrg + strlen (cleanname) + 14; 336629baa8cSmrg d->authFile = malloc (len); 337629baa8cSmrg if (!d->authFile) 338629baa8cSmrg return FALSE; 339629baa8cSmrg 340629baa8cSmrg snprintf (d->authFile, len, "%s/%s", authDir, authdir1); 341629baa8cSmrg r = CheckServerAuthDir(d->authFile, &statb, 0700); 342629baa8cSmrg if (r == 0) { 343629baa8cSmrg if (statb.st_uid != 0) 344629baa8cSmrg (void) chown(d->authFile, 0, statb.st_gid); 345629baa8cSmrg if ((statb.st_mode & 0077) != 0) 346629baa8cSmrg (void) chmod(d->authFile, statb.st_mode & 0700); 347629baa8cSmrg } else if (r < 0) { 348629baa8cSmrg free (d->authFile); 349629baa8cSmrg d->authFile = NULL; 350629baa8cSmrg return FALSE; 351629baa8cSmrg } 352629baa8cSmrg 353629baa8cSmrg snprintf (d->authFile, len, "%s/%s/%s", 354629baa8cSmrg authDir, authdir1, authdir2); 355629baa8cSmrg r = CheckServerAuthDir(d->authFile, &statb, 0700); 356629baa8cSmrg if (r < 0) { 357629baa8cSmrg free (d->authFile); 358629baa8cSmrg d->authFile = NULL; 359629baa8cSmrg return FALSE; 360629baa8cSmrg } 361629baa8cSmrg snprintf (d->authFile, len, "%s/%s/%s/A%s-XXXXXX", 362629baa8cSmrg authDir, authdir1, authdir2, cleanname); 363629baa8cSmrg#ifdef HAVE_MKSTEMP 364629baa8cSmrg fd = mkstemp (d->authFile); 365629baa8cSmrg if (fd < 0) { 366629baa8cSmrg LogError ("cannot make authentication file %s: %s\n", 367629baa8cSmrg d->authFile, _SysErrorMsg (errno)); 368629baa8cSmrg free (d->authFile); 369629baa8cSmrg d->authFile = NULL; 370629baa8cSmrg return FALSE; 371629baa8cSmrg } 372629baa8cSmrg 373629baa8cSmrg *file = fdopen(fd, "w"); 374629baa8cSmrg if (!*file) 375629baa8cSmrg (void) close (fd); 376629baa8cSmrg return TRUE; 377629baa8cSmrg#else 378629baa8cSmrg (void) mktemp (d->authFile); 379629baa8cSmrg#endif 380629baa8cSmrg } 381629baa8cSmrg } 382629baa8cSmrg 383629baa8cSmrg (void) unlink (d->authFile); 384629baa8cSmrg *file = fopen (d->authFile, "w"); 385629baa8cSmrg return TRUE; 386629baa8cSmrg} 387629baa8cSmrg 388629baa8cSmrgint 389629baa8cSmrgSaveServerAuthorizations ( 390629baa8cSmrg struct display *d, 391629baa8cSmrg Xauth **auths, 392629baa8cSmrg int count) 393629baa8cSmrg{ 394629baa8cSmrg FILE *auth_file; 395629baa8cSmrg mode_t mask; 396629baa8cSmrg int ret; 397629baa8cSmrg int i; 398629baa8cSmrg const char dummy_auth[] = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" 399629baa8cSmrg "XXXXXXXXXXXXXXXXX"; /* 64 "X"s */ 400629baa8cSmrg int err = 0; 401629baa8cSmrg 402629baa8cSmrg mask = umask (0077); 403629baa8cSmrg ret = MakeServerAuthFile(d, &auth_file); 404629baa8cSmrg umask (mask); 405629baa8cSmrg if (!ret) 406629baa8cSmrg return FALSE; 407629baa8cSmrg if (!auth_file) { 408629baa8cSmrg LogError ("cannot open server authorization file %s: %s\n", 409629baa8cSmrg d->authFile, _SysErrorMsg (errno)); 410629baa8cSmrg ret = FALSE; 411629baa8cSmrg } 412629baa8cSmrg else 413629baa8cSmrg { 414629baa8cSmrg Debug ("File: %s auth: %p\n", d->authFile, auths); 415629baa8cSmrg ret = TRUE; 416629baa8cSmrg if (count == 0) 417629baa8cSmrg { 418629baa8cSmrg /* 419629baa8cSmrg * This is a crude hack to determine whether we really can 420629baa8cSmrg * write to the auth file even if we don't have real data 421629baa8cSmrg * to write right now. 422629baa8cSmrg */ 423629baa8cSmrg 424629baa8cSmrg /* 425629baa8cSmrg * Write garbage data to file to provoke ENOSPC and other 426629baa8cSmrg * errors. 427629baa8cSmrg */ 428629baa8cSmrg (void) fprintf (auth_file, "%s", dummy_auth); 429629baa8cSmrg (void) fflush (auth_file); 430629baa8cSmrg if (ferror (auth_file)) 431629baa8cSmrg { 432629baa8cSmrg err = errno; 433629baa8cSmrg ret = FALSE; 434629baa8cSmrg } 435629baa8cSmrg /* 436629baa8cSmrg * Rewind so that the garbage data is overwritten later. 437629baa8cSmrg */ 438629baa8cSmrg rewind(auth_file); 439629baa8cSmrg } 440629baa8cSmrg for (i = 0; i < count; i++) 441629baa8cSmrg { 442629baa8cSmrg /* 443629baa8cSmrg * User-based auths may not have data until 444629baa8cSmrg * a user logs in. In which case don't write 445629baa8cSmrg * to the auth file so xrdb and setup programs don't fail. 446629baa8cSmrg */ 447b7d26471Smrg if (auths[i]->data_length > 0) { 448629baa8cSmrg if (!XauWriteAuth (auth_file, auths[i])) 449629baa8cSmrg { 450629baa8cSmrg Debug ("XauWriteAuth() failed\n"); 451629baa8cSmrg } 452629baa8cSmrg (void) fflush (auth_file); 453629baa8cSmrg if (ferror (auth_file)) 454629baa8cSmrg { 455629baa8cSmrg err = errno; 456629baa8cSmrg ret = FALSE; 457629baa8cSmrg } 458b7d26471Smrg } 459629baa8cSmrg } 460629baa8cSmrg /* 461629baa8cSmrg * XXX: This is not elegant, but stdio has no truncation function. 462629baa8cSmrg */ 463629baa8cSmrg if (ftruncate(fileno(auth_file), ftell(auth_file))) 464629baa8cSmrg { 465629baa8cSmrg Debug ("ftruncate() failed\n"); 466629baa8cSmrg } 467629baa8cSmrg fclose (auth_file); 468629baa8cSmrg 469629baa8cSmrg } 470629baa8cSmrg if (ret == FALSE) 471629baa8cSmrg { 472629baa8cSmrg LogError ("Cannot write to server authorization file %s%s%s\n", 473629baa8cSmrg d->authFile, 474629baa8cSmrg err ? ": " : "", 475629baa8cSmrg err ? _SysErrorMsg (errno) : ""); 476629baa8cSmrg free (d->authFile); 477629baa8cSmrg d->authFile = NULL; 478629baa8cSmrg } 479629baa8cSmrg return ret; 480629baa8cSmrg} 481629baa8cSmrg 482629baa8cSmrgvoid 483629baa8cSmrgSetLocalAuthorization (struct display *d) 484629baa8cSmrg{ 485629baa8cSmrg Xauth *auth, **auths; 486629baa8cSmrg int i, j; 487629baa8cSmrg 488629baa8cSmrg if (d->authorizations) 489629baa8cSmrg { 490629baa8cSmrg for (i = 0; i < d->authNum; i++) 491629baa8cSmrg XauDisposeAuth (d->authorizations[i]); 492629baa8cSmrg free (d->authorizations); 493629baa8cSmrg d->authorizations = (Xauth **) NULL; 494629baa8cSmrg d->authNum = 0; 495629baa8cSmrg } 496629baa8cSmrg if (!d->authNames) 497629baa8cSmrg return; 498629baa8cSmrg for (i = 0; d->authNames[i]; i++) 499629baa8cSmrg ; 500629baa8cSmrg d->authNameNum = i; 501629baa8cSmrg free (d->authNameLens); 502629baa8cSmrg d->authNameLens = malloc (d->authNameNum * sizeof (unsigned short)); 503629baa8cSmrg if (!d->authNameLens) 504629baa8cSmrg return; 505629baa8cSmrg for (i = 0; i < d->authNameNum; i++) 506629baa8cSmrg d->authNameLens[i] = strlen (d->authNames[i]); 507629baa8cSmrg auths = malloc (d->authNameNum * sizeof (Xauth *)); 508629baa8cSmrg if (!auths) 509629baa8cSmrg return; 510629baa8cSmrg j = 0; 511629baa8cSmrg for (i = 0; i < d->authNameNum; i++) 512629baa8cSmrg { 513629baa8cSmrg auth = GenerateAuthorization (d->authNameLens[i], d->authNames[i]); 514629baa8cSmrg if (auth) 515629baa8cSmrg auths[j++] = auth; 516629baa8cSmrg } 517629baa8cSmrg if (SaveServerAuthorizations (d, auths, j)) 518629baa8cSmrg { 519629baa8cSmrg d->authorizations = auths; 520629baa8cSmrg d->authNum = j; 521629baa8cSmrg } 522629baa8cSmrg else 523629baa8cSmrg { 524629baa8cSmrg for (i = 0; i < j; i++) 525629baa8cSmrg XauDisposeAuth (auths[i]); 526629baa8cSmrg free (auths); 527629baa8cSmrg } 528629baa8cSmrg} 529629baa8cSmrg 530629baa8cSmrg/* 531629baa8cSmrg * Set the authorization to use for xdm's initial connection 532629baa8cSmrg * to the X server. Cannot use user-based authorizations 533629baa8cSmrg * because no one has logged in yet, so we don't have any 534629baa8cSmrg * user credentials. 535629baa8cSmrg * Well, actually we could use SUN-DES-1 because we tell the server 536629baa8cSmrg * to allow root in. This is bogus and should be fixed. 537629baa8cSmrg */ 538629baa8cSmrgvoid 539629baa8cSmrgSetAuthorization (struct display *d) 540629baa8cSmrg{ 541629baa8cSmrg register Xauth **auth = d->authorizations; 542629baa8cSmrg int i; 543629baa8cSmrg 544629baa8cSmrg for (i = 0; i < d->authNum; i++) 545629baa8cSmrg { 546629baa8cSmrg if (auth[i]->name_length == 9 && 547629baa8cSmrg memcmp(auth[i]->name, "SUN-DES-1", 9) == 0) 548629baa8cSmrg continue; 549629baa8cSmrg if (auth[i]->name_length == 14 && 550629baa8cSmrg memcmp(auth[i]->name, "MIT-KERBEROS-5", 14) == 0) 551629baa8cSmrg continue; 552629baa8cSmrg XSetAuthorization (auth[i]->name, (int) auth[i]->name_length, 553629baa8cSmrg auth[i]->data, (int) auth[i]->data_length); 554629baa8cSmrg } 555629baa8cSmrg} 556629baa8cSmrg 557629baa8cSmrgstatic int 558629baa8cSmrgopenFiles (char *name, char *new_name, FILE **oldp, FILE **newp) 559629baa8cSmrg{ 560629baa8cSmrg mode_t mask; 561629baa8cSmrg int newfd; 562629baa8cSmrg 563629baa8cSmrg strcpy (new_name, name); 564629baa8cSmrg strcat (new_name, "-n"); 565629baa8cSmrg /* 566629baa8cSmrg * Set safe umask for file creation operations. 567629baa8cSmrg */ 568629baa8cSmrg mask = umask (0077); 569629baa8cSmrg /* 570629baa8cSmrg * Unlink the authorization file we intend to create, and then open 571629baa8cSmrg * it with O_CREAT | O_EXCL to avoid race-based symlink attacks. 572629baa8cSmrg */ 573629baa8cSmrg (void) unlink (new_name); 574629baa8cSmrg newfd = open (new_name, O_WRONLY | O_CREAT | O_EXCL, 0600); 575b7d26471Smrg if (newfd >= 0) { 576629baa8cSmrg *newp = fdopen (newfd, "w"); 577b7d26471Smrg if (*newp == NULL) 578b7d26471Smrg close(newfd); 579b7d26471Smrg } 580629baa8cSmrg else 581629baa8cSmrg { 582629baa8cSmrg LogError ("Cannot create file %s: %s\n", new_name, 583629baa8cSmrg _SysErrorMsg (errno)); 584629baa8cSmrg *newp = NULL; 585629baa8cSmrg } 586629baa8cSmrg /* 587629baa8cSmrg * There are no more attempts to create files after this point; 588629baa8cSmrg * restore the original umask. 589629baa8cSmrg */ 590629baa8cSmrg (void) umask (mask); 591629baa8cSmrg if (!*newp) { 592629baa8cSmrg Debug ("can't open new file %s\n", new_name); 593629baa8cSmrg return 0; 594629baa8cSmrg } 595629baa8cSmrg if (!*oldp) 596629baa8cSmrg *oldp = fopen (name, "r"); 597629baa8cSmrg Debug ("opens succeeded %s %s\n", name, new_name); 598629baa8cSmrg return 1; 599629baa8cSmrg} 600629baa8cSmrg 601629baa8cSmrgstatic int 602629baa8cSmrgbinaryEqual (char *a, char *b, unsigned short len) 603629baa8cSmrg{ 604629baa8cSmrg while (len-- > 0) 605629baa8cSmrg if (*a++ != *b++) 606629baa8cSmrg return FALSE; 607629baa8cSmrg return TRUE; 608629baa8cSmrg} 609629baa8cSmrg 610629baa8cSmrgstatic void 611629baa8cSmrgdumpBytes (unsigned short len, char *data) 612629baa8cSmrg{ 613629baa8cSmrg unsigned short i; 614629baa8cSmrg 615629baa8cSmrg Debug ("%d: ", len); 616629baa8cSmrg for (i = 0; i < len; i++) 617629baa8cSmrg Debug ("%02x ", data[i] & 0377); 618629baa8cSmrg Debug ("\n"); 619629baa8cSmrg} 620629baa8cSmrg 621629baa8cSmrgstatic void 622629baa8cSmrgdumpAuth (Xauth *auth) 623629baa8cSmrg{ 624629baa8cSmrg Debug ("family: %d\n", auth->family); 625629baa8cSmrg Debug ("addr: "); 626629baa8cSmrg dumpBytes (auth->address_length, auth->address); 627629baa8cSmrg Debug ("number: "); 628629baa8cSmrg dumpBytes (auth->number_length, auth->number); 629629baa8cSmrg Debug ("name: "); 630629baa8cSmrg dumpBytes (auth->name_length, auth->name); 631629baa8cSmrg Debug ("data: "); 632629baa8cSmrg dumpBytes (auth->data_length, auth->data); 633629baa8cSmrg} 634629baa8cSmrg 635629baa8cSmrgstruct addrList { 636629baa8cSmrg unsigned short family; 637629baa8cSmrg unsigned short address_length; 638629baa8cSmrg char *address; 639629baa8cSmrg unsigned short number_length; 640629baa8cSmrg char *number; 641629baa8cSmrg unsigned short name_length; 642629baa8cSmrg char *name; 643629baa8cSmrg struct addrList *next; 644629baa8cSmrg}; 645629baa8cSmrg 646629baa8cSmrgstatic struct addrList *addrs; 647629baa8cSmrg 648629baa8cSmrgstatic void 649629baa8cSmrginitAddrs (void) 650629baa8cSmrg{ 651629baa8cSmrg addrs = NULL; 652629baa8cSmrg} 653629baa8cSmrg 654629baa8cSmrgstatic void 655629baa8cSmrgdoneAddrs (void) 656629baa8cSmrg{ 657629baa8cSmrg struct addrList *a, *n; 658629baa8cSmrg for (a = addrs; a; a = n) { 659629baa8cSmrg n = a->next; 660629baa8cSmrg free (a->address); 661629baa8cSmrg free (a->number); 662629baa8cSmrg free (a); 663629baa8cSmrg } 664629baa8cSmrg} 665629baa8cSmrg 666629baa8cSmrgstatic int checkEntry (Xauth *auth); 667629baa8cSmrg 668629baa8cSmrgstatic void 669629baa8cSmrgsaveEntry (Xauth *auth) 670629baa8cSmrg{ 671629baa8cSmrg struct addrList *new; 672629baa8cSmrg 673629baa8cSmrg new = malloc (sizeof (struct addrList)); 674629baa8cSmrg if (!new) { 675629baa8cSmrg LogOutOfMem ("saveEntry"); 676629baa8cSmrg return; 677629baa8cSmrg } 678629baa8cSmrg if ((new->address_length = auth->address_length) > 0) { 679629baa8cSmrg new->address = malloc (auth->address_length); 680629baa8cSmrg if (!new->address) { 681629baa8cSmrg LogOutOfMem ("saveEntry"); 682629baa8cSmrg free (new); 683629baa8cSmrg return; 684629baa8cSmrg } 685629baa8cSmrg memmove( new->address, auth->address, (int) auth->address_length); 686629baa8cSmrg } else 687629baa8cSmrg new->address = NULL; 688629baa8cSmrg if ((new->number_length = auth->number_length) > 0) { 689629baa8cSmrg new->number = malloc (auth->number_length); 690629baa8cSmrg if (!new->number) { 691629baa8cSmrg LogOutOfMem ("saveEntry"); 692629baa8cSmrg free (new->address); 693629baa8cSmrg free (new); 694629baa8cSmrg return; 695629baa8cSmrg } 696629baa8cSmrg memmove( new->number, auth->number, (int) auth->number_length); 697629baa8cSmrg } else 698629baa8cSmrg new->number = NULL; 699629baa8cSmrg if ((new->name_length = auth->name_length) > 0) { 700629baa8cSmrg new->name = malloc (auth->name_length); 701629baa8cSmrg if (!new->name) { 702629baa8cSmrg LogOutOfMem ("saveEntry"); 703629baa8cSmrg free (new->number); 704629baa8cSmrg free (new->address); 705629baa8cSmrg free (new); 706629baa8cSmrg return; 707629baa8cSmrg } 708629baa8cSmrg memmove( new->name, auth->name, (int) auth->name_length); 709629baa8cSmrg } else 710629baa8cSmrg new->name = NULL; 711629baa8cSmrg new->family = auth->family; 712629baa8cSmrg new->next = addrs; 713629baa8cSmrg addrs = new; 714629baa8cSmrg} 715629baa8cSmrg 716629baa8cSmrgstatic int 717629baa8cSmrgcheckEntry (Xauth *auth) 718629baa8cSmrg{ 719629baa8cSmrg struct addrList *a; 720629baa8cSmrg 721629baa8cSmrg for (a = addrs; a; a = a->next) { 722629baa8cSmrg if (a->family == auth->family && 723629baa8cSmrg a->address_length == auth->address_length && 724629baa8cSmrg binaryEqual (a->address, auth->address, auth->address_length) && 725629baa8cSmrg a->number_length == auth->number_length && 726629baa8cSmrg binaryEqual (a->number, auth->number, auth->number_length) && 727629baa8cSmrg a->name_length == auth->name_length && 728629baa8cSmrg binaryEqual (a->name, auth->name, auth->name_length)) 729629baa8cSmrg { 730629baa8cSmrg return 1; 731629baa8cSmrg } 732629baa8cSmrg } 733629baa8cSmrg return 0; 734629baa8cSmrg} 735629baa8cSmrg 736629baa8cSmrgstatic int doWrite; 737629baa8cSmrg 738629baa8cSmrgstatic void 739629baa8cSmrgwriteAuth (FILE *file, Xauth *auth) 740629baa8cSmrg{ 741629baa8cSmrg if (debugLevel >= 15) { /* normally too verbose */ 742629baa8cSmrg Debug ("writeAuth: doWrite = %d\n", doWrite); 743629baa8cSmrg dumpAuth (auth); /* does Debug only */ 744629baa8cSmrg } 745629baa8cSmrg if (doWrite) 746629baa8cSmrg XauWriteAuth (file, auth); 747629baa8cSmrg} 748629baa8cSmrg 749629baa8cSmrgstatic void 750629baa8cSmrgwriteAddr ( 751629baa8cSmrg int family, 752629baa8cSmrg int addr_length, 753629baa8cSmrg char *addr, 754629baa8cSmrg FILE *file, 755629baa8cSmrg Xauth *auth) 756629baa8cSmrg{ 757629baa8cSmrg auth->family = (unsigned short) family; 758629baa8cSmrg auth->address_length = addr_length; 759629baa8cSmrg auth->address = addr; 760629baa8cSmrg Debug ("writeAddr: writing and saving an entry\n"); 761629baa8cSmrg writeAuth (file, auth); 762629baa8cSmrg saveEntry (auth); 763629baa8cSmrg} 764629baa8cSmrg 765629baa8cSmrgstatic void 766629baa8cSmrgDefineLocal (FILE *file, Xauth *auth) 767629baa8cSmrg{ 768629baa8cSmrg char displayname[100]; 769629baa8cSmrg int len = _XGetHostname (displayname, sizeof(displayname)); 770629baa8cSmrg 771629baa8cSmrg/* Make sure this produces the same string as _XGetHostname in lib/X/XlibInt.c. 772629baa8cSmrg * Otherwise, Xau will not be able to find your cookies in the Xauthority file. 773629baa8cSmrg * 774629baa8cSmrg * Note: POSIX says that the ``nodename'' member of utsname does _not_ have 775629baa8cSmrg * to have sufficient information for interfacing to the network, 776629baa8cSmrg * and so, you may be better off using gethostname (if it exists). 777629baa8cSmrg */ 778629baa8cSmrg 779629baa8cSmrg#if defined(hpux) 780629baa8cSmrg /* 781629baa8cSmrg * For HP-UX, HP's Xlib expects a fully-qualified domain name, which 782629baa8cSmrg * is achieved by using gethostname(). For compatability, we must 783629baa8cSmrg * also still create the entry using uname(). 784629baa8cSmrg */ 785629baa8cSmrg char tmp_displayname[100]; 786629baa8cSmrg struct utsname name; 787629baa8cSmrg 788629baa8cSmrg tmp_displayname[0] = 0; 789629baa8cSmrg uname(&name); 790629baa8cSmrg snprintf(tmp_displayname, sizeof(tmp_displayname), "%s", name.nodename); 791629baa8cSmrg writeAddr (FamilyLocal, strlen (tmp_displayname), tmp_displayname, 792629baa8cSmrg file, auth); 793629baa8cSmrg 794629baa8cSmrg /* 795629baa8cSmrg * If _XGetHostname() returned the same value as uname(), don't 796629baa8cSmrg * write a duplicate entry. 797629baa8cSmrg */ 798629baa8cSmrg if (strcmp (displayname, tmp_displayname)) 799629baa8cSmrg#endif 800629baa8cSmrg 801629baa8cSmrg writeAddr (FamilyLocal, len, displayname, file, auth); 802629baa8cSmrg} 803629baa8cSmrg 804629baa8cSmrg#ifdef HAVE_GETIFADDRS 805629baa8cSmrg# include <ifaddrs.h> 806629baa8cSmrg 807629baa8cSmrgstatic void 808629baa8cSmrgDefineSelf(int fd, FILE *file, Xauth *auth) 809629baa8cSmrg{ 810629baa8cSmrg struct ifaddrs *ifap, *ifr; 811629baa8cSmrg char *addr; 812629baa8cSmrg int family, len; 813629baa8cSmrg 814629baa8cSmrg Debug("DefineSelf\n"); 815629baa8cSmrg if (getifaddrs(&ifap) < 0) 816629baa8cSmrg return; 817629baa8cSmrg for (ifr = ifap; ifr != NULL; ifr = ifr->ifa_next) { 818629baa8cSmrg len = sizeof(*(ifr->ifa_addr)); 819629baa8cSmrg family = ConvertAddr((XdmcpNetaddr)(ifr->ifa_addr), &len, &addr); 820629baa8cSmrg if (family == -1 || family == FamilyLocal) 821629baa8cSmrg continue; 822629baa8cSmrg /* 823629baa8cSmrg * don't write out 'localhost' entries, as 824629baa8cSmrg * they may conflict with other local entries. 825629baa8cSmrg * DefineLocal will always be called to add 826629baa8cSmrg * the local entry anyway, so this one can 827629baa8cSmrg * be tossed. 828629baa8cSmrg */ 829629baa8cSmrg if (family == FamilyInternet && len == 4 && addr[0] == 127) 830629baa8cSmrg { 831629baa8cSmrg Debug ("Skipping localhost address\n"); 832629baa8cSmrg continue; 833629baa8cSmrg } 834629baa8cSmrg# if defined(IPv6) && defined(AF_INET6) 835629baa8cSmrg if(family == FamilyInternet6) { 836629baa8cSmrg if (IN6_IS_ADDR_LOOPBACK(((struct in6_addr *)addr))) { 837629baa8cSmrg Debug ("Skipping IPv6 localhost address\n"); 838629baa8cSmrg continue; 839629baa8cSmrg } 840629baa8cSmrg /* Also skip XDM-AUTHORIZATION-1 */ 841629baa8cSmrg if (auth->name_length == 19 && 842629baa8cSmrg strcmp(auth->name, "XDM-AUTHORIZATION-1") == 0) { 843629baa8cSmrg Debug ("Skipping IPv6 XDM-AUTHORIZATION-1\n"); 844629baa8cSmrg continue; 845629baa8cSmrg } 846629baa8cSmrg } 847629baa8cSmrg# endif 848629baa8cSmrg writeAddr(family, len, addr, file, auth); 849629baa8cSmrg } 850629baa8cSmrg freeifaddrs(ifap); 851629baa8cSmrg Debug("DefineSelf done\n"); 852629baa8cSmrg} 853629baa8cSmrg#else /* GETIFADDRS */ 854629baa8cSmrg 855629baa8cSmrg# ifdef SYSV_SIOCGIFCONF 856629baa8cSmrg 857629baa8cSmrg/* Deal with different SIOCGIFCONF ioctl semantics on SYSV, SVR4 */ 858629baa8cSmrg 859629baa8cSmrgstatic int 860629baa8cSmrgifioctl (int fd, int cmd, char *arg) 861629baa8cSmrg{ 862629baa8cSmrg struct strioctl ioc; 863629baa8cSmrg int ret; 864629baa8cSmrg 865629baa8cSmrg bzero((char *) &ioc, sizeof(ioc)); 866629baa8cSmrg ioc.ic_cmd = cmd; 867629baa8cSmrg ioc.ic_timout = 0; 868629baa8cSmrg if (cmd == SIOCGIFCONF) 869629baa8cSmrg { 870629baa8cSmrg ioc.ic_len = ((struct ifconf *) arg)->ifc_len; 871629baa8cSmrg ioc.ic_dp = ((struct ifconf *) arg)->ifc_buf; 872629baa8cSmrg } 873629baa8cSmrg else 874629baa8cSmrg { 875629baa8cSmrg ioc.ic_len = sizeof(struct ifreq); 876629baa8cSmrg ioc.ic_dp = arg; 877629baa8cSmrg } 878629baa8cSmrg ret = ioctl(fd, I_STR, (char *) &ioc); 879629baa8cSmrg if (ret >= 0 && cmd == SIOCGIFCONF) 880629baa8cSmrg ((struct ifconf *) arg)->ifc_len = ioc.ic_len; 881629baa8cSmrg return(ret); 882629baa8cSmrg} 883629baa8cSmrg# else /* SYSV_SIOCGIFCONF */ 884629baa8cSmrg# define ifioctl ioctl 885629baa8cSmrg# endif /* SYSV_SIOCGIFCONF */ 886629baa8cSmrg 887629baa8cSmrg 888629baa8cSmrg 889b7d26471Smrg# if defined(SIOCGIFCONF) || defined (USE_SIOCGLIFCONF) 890629baa8cSmrg 891b7d26471Smrg# ifdef USE_SIOCGLIFCONF 892b7d26471Smrg# define ifr_type struct lifreq 893b7d26471Smrg# else 894b7d26471Smrg# define ifr_type struct ifreq 895b7d26471Smrg# endif 896629baa8cSmrg 897629baa8cSmrg/* Handle variable length ifreq in BNR2 and later */ 898b7d26471Smrg# ifdef VARIABLE_IFREQ 899b7d26471Smrg# define ifr_size(p) (sizeof (struct ifreq) + \ 900629baa8cSmrg (p->ifr_addr.sa_len > sizeof (p->ifr_addr) ? \ 901629baa8cSmrg p->ifr_addr.sa_len - sizeof (p->ifr_addr) : 0)) 902b7d26471Smrg# else 903b7d26471Smrg# define ifr_size(p) (sizeof (ifr_type)) 904b7d26471Smrg# endif 905629baa8cSmrg 906629baa8cSmrg/* Define this host for access control. Find all the hosts the OS knows about 907629baa8cSmrg * for this fd and add them to the selfhosts list. 908629baa8cSmrg */ 909629baa8cSmrgstatic void 910629baa8cSmrgDefineSelf (int fd, FILE *file, Xauth *auth) 911629baa8cSmrg{ 912629baa8cSmrg char buf[2048], *cp, *cplim; 913629baa8cSmrg int len; 914629baa8cSmrg char *addr; 915629baa8cSmrg int family; 916629baa8cSmrg register ifr_type *ifr; 917b7d26471Smrg# ifdef USE_SIOCGLIFCONF 918629baa8cSmrg void * bufptr = buf; 919629baa8cSmrg size_t buflen = sizeof(buf); 920629baa8cSmrg struct lifconf ifc; 921b7d26471Smrg# ifdef SIOCGLIFNUM 922629baa8cSmrg struct lifnum ifn; 923b7d26471Smrg# endif 924b7d26471Smrg# else 925629baa8cSmrg struct ifconf ifc; 926b7d26471Smrg# endif 927629baa8cSmrg 928b7d26471Smrg# if defined(SIOCGLIFNUM) && defined(SIOCGLIFCONF) 929629baa8cSmrg ifn.lifn_family = AF_UNSPEC; 930629baa8cSmrg ifn.lifn_flags = 0; 931629baa8cSmrg if (ioctl (fd, (int) SIOCGLIFNUM, (char *) &ifn) < 0) 932629baa8cSmrg LogError ("Failed getting interface count"); 933629baa8cSmrg if (buflen < (ifn.lifn_count * sizeof(struct lifreq))) { 934629baa8cSmrg buflen = ifn.lifn_count * sizeof(struct lifreq); 935629baa8cSmrg bufptr = malloc(buflen); 936629baa8cSmrg } 937b7d26471Smrg# endif 938629baa8cSmrg 939b7d26471Smrg# ifdef USE_SIOCGLIFCONF 940629baa8cSmrg ifc.lifc_family = AF_UNSPEC; 941629baa8cSmrg ifc.lifc_flags = 0; 942629baa8cSmrg ifc.lifc_len = buflen; 943629baa8cSmrg ifc.lifc_buf = bufptr; 944629baa8cSmrg 945b7d26471Smrg# define IFC_IOCTL_REQ SIOCGLIFCONF 946b7d26471Smrg# define IFC_IFC_REQ ifc.lifc_req 947b7d26471Smrg# define IFC_IFC_LEN ifc.lifc_len 948b7d26471Smrg# define IFR_IFR_ADDR ifr->lifr_addr 949b7d26471Smrg# define IFR_IFR_NAME ifr->lifr_name 950629baa8cSmrg 951b7d26471Smrg# else 952629baa8cSmrg ifc.ifc_len = sizeof (buf); 953629baa8cSmrg ifc.ifc_buf = buf; 954629baa8cSmrg 955b7d26471Smrg# define IFC_IOCTL_REQ SIOCGIFCONF 956b7d26471Smrg# define IFC_IFC_REQ ifc.ifc_req 957b7d26471Smrg# define IFC_IFC_LEN ifc.ifc_len 958b7d26471Smrg# define IFR_IFR_ADDR ifr->ifr_addr 959b7d26471Smrg# define IFR_IFR_NAME ifr->ifr_name 960b7d26471Smrg# endif 961629baa8cSmrg 962629baa8cSmrg if (ifioctl (fd, IFC_IOCTL_REQ, (char *) &ifc) < 0) { 963629baa8cSmrg LogError ("Trouble getting network interface configuration"); 964629baa8cSmrg 965b7d26471Smrg# ifdef USE_SIOCGLIFCONF 966629baa8cSmrg if (bufptr != buf) { 967629baa8cSmrg free(bufptr); 968629baa8cSmrg } 969b7d26471Smrg# endif 970629baa8cSmrg return; 971629baa8cSmrg } 972629baa8cSmrg 973629baa8cSmrg cplim = (char *) IFC_IFC_REQ + IFC_IFC_LEN; 974629baa8cSmrg 975629baa8cSmrg for (cp = (char *) IFC_IFC_REQ; cp < cplim; cp += ifr_size (ifr)) 976629baa8cSmrg { 977629baa8cSmrg ifr = (ifr_type *) cp; 978b7d26471Smrg family = ConvertAddr ((XdmcpNetaddr) &IFR_IFR_ADDR, &len, &addr); 979b7d26471Smrg if (family < 0) 980b7d26471Smrg continue; 981b7d26471Smrg 982b7d26471Smrg if (len == 0) 983b7d26471Smrg { 984b7d26471Smrg Debug ("Skipping zero length address\n"); 985b7d26471Smrg continue; 986b7d26471Smrg } 987629baa8cSmrg /* 988b7d26471Smrg * don't write out 'localhost' entries, as 989b7d26471Smrg * they may conflict with other local entries. 990b7d26471Smrg * DefineLocal will always be called to add 991b7d26471Smrg * the local entry anyway, so this one can 992b7d26471Smrg * be tossed. 993629baa8cSmrg */ 994b7d26471Smrg if (family == FamilyInternet && len == 4 && 995b7d26471Smrg addr[0] == 127 && addr[1] == 0 && 996b7d26471Smrg addr[2] == 0 && addr[3] == 1) 997629baa8cSmrg { 998b7d26471Smrg Debug ("Skipping localhost address\n"); 999b7d26471Smrg continue; 1000b7d26471Smrg } 1001b7d26471Smrg# if defined(IPv6) && defined(AF_INET6) 1002b7d26471Smrg if (family == FamilyInternet6) { 1003b7d26471Smrg if (IN6_IS_ADDR_LOOPBACK(((struct in6_addr *)addr))) { 1004b7d26471Smrg Debug ("Skipping IPv6 localhost address\n"); 1005629baa8cSmrg continue; 1006629baa8cSmrg } 1007b7d26471Smrg /* Also skip XDM-AUTHORIZATION-1 */ 1008b7d26471Smrg if (auth->name_length == 19 && 1009b7d26471Smrg strcmp(auth->name, "XDM-AUTHORIZATION-1") == 0) { 1010b7d26471Smrg Debug ("Skipping IPv6 XDM-AUTHORIZATION-1\n"); 1011b7d26471Smrg continue; 1012629baa8cSmrg } 1013629baa8cSmrg } 1014b7d26471Smrg# endif 1015629baa8cSmrg Debug ("DefineSelf: write network address, length %d\n", len); 1016629baa8cSmrg writeAddr (family, len, addr, file, auth); 1017629baa8cSmrg } 1018629baa8cSmrg} 1019629baa8cSmrg 1020b7d26471Smrg# else /* SIOCGIFCONF */ 1021629baa8cSmrg 1022629baa8cSmrg/* Define this host for access control. Find all the hosts the OS knows about 1023629baa8cSmrg * for this fd and add them to the selfhosts list. 1024629baa8cSmrg */ 1025629baa8cSmrgstatic void 1026629baa8cSmrgDefineSelf (int fd, int file, int auth) 1027629baa8cSmrg{ 1028629baa8cSmrg register int n; 1029629baa8cSmrg int len; 1030629baa8cSmrg caddr_t addr; 1031629baa8cSmrg int family; 1032629baa8cSmrg 1033629baa8cSmrg struct utsname name; 1034629baa8cSmrg register struct hostent *hp; 1035629baa8cSmrg 1036629baa8cSmrg union { 1037629baa8cSmrg struct sockaddr sa; 1038629baa8cSmrg struct sockaddr_in in; 1039629baa8cSmrg } saddr; 1040629baa8cSmrg 1041629baa8cSmrg struct sockaddr_in *inetaddr; 1042629baa8cSmrg 1043629baa8cSmrg /* hpux: 1044629baa8cSmrg * Why not use gethostname()? Well, at least on my system, I've had to 1045629baa8cSmrg * make an ugly kernel patch to get a name longer than 8 characters, and 1046629baa8cSmrg * uname() lets me access to the whole string (it smashes release, you 1047629baa8cSmrg * see), whereas gethostname() kindly truncates it for me. 1048629baa8cSmrg */ 1049629baa8cSmrg uname(&name); 1050629baa8cSmrg hp = gethostbyname (name.nodename); 1051629baa8cSmrg if (hp != NULL) { 1052629baa8cSmrg saddr.sa.sa_family = hp->h_addrtype; 1053629baa8cSmrg inetaddr = (struct sockaddr_in *) (&(saddr.sa)); 1054629baa8cSmrg memmove( (char *) &(inetaddr->sin_addr), (char *) hp->h_addr, (int) hp->h_length); 1055629baa8cSmrg family = ConvertAddr ( &(saddr.sa), &len, &addr); 1056629baa8cSmrg if ( family >= 0) { 1057629baa8cSmrg writeAddr (FamilyInternet, sizeof (inetaddr->sin_addr), 1058629baa8cSmrg (char *) (&inetaddr->sin_addr), file, auth); 1059629baa8cSmrg } 1060629baa8cSmrg } 1061629baa8cSmrg} 1062629baa8cSmrg 1063629baa8cSmrg 1064b7d26471Smrg# endif /* SIOCGIFCONF else */ 1065629baa8cSmrg#endif /* HAVE_GETIFADDRS */ 1066629baa8cSmrg 1067629baa8cSmrgstatic void 1068629baa8cSmrgsetAuthNumber (Xauth *auth, char *name) 1069629baa8cSmrg{ 1070629baa8cSmrg char *colon; 1071629baa8cSmrg char *dot, *number; 1072629baa8cSmrg 1073629baa8cSmrg Debug ("setAuthNumber %s\n", name); 1074629baa8cSmrg colon = strrchr(name, ':'); 1075629baa8cSmrg if (colon) { 1076629baa8cSmrg ++colon; 1077629baa8cSmrg dot = strchr(colon, '.'); 1078629baa8cSmrg if (dot) 1079629baa8cSmrg auth->number_length = dot - colon; 1080629baa8cSmrg else 1081629baa8cSmrg auth->number_length = strlen (colon); 1082629baa8cSmrg number = malloc (auth->number_length + 1); 1083629baa8cSmrg if (number) { 1084629baa8cSmrg strncpy (number, colon, auth->number_length); 1085629baa8cSmrg number[auth->number_length] = '\0'; 1086629baa8cSmrg } else { 1087629baa8cSmrg LogOutOfMem ("setAuthNumber"); 1088629baa8cSmrg auth->number_length = 0; 1089629baa8cSmrg } 1090629baa8cSmrg auth->number = number; 1091629baa8cSmrg Debug ("setAuthNumber: %s\n", number); 1092629baa8cSmrg } 1093629baa8cSmrg} 1094629baa8cSmrg 1095629baa8cSmrgstatic void 1096629baa8cSmrgwriteLocalAuth (FILE *file, Xauth *auth, char *name) 1097629baa8cSmrg{ 1098629baa8cSmrg int fd; 1099629baa8cSmrg 1100629baa8cSmrg Debug ("writeLocalAuth: %s %.*s\n", name, auth->name_length, auth->name); 1101629baa8cSmrg setAuthNumber (auth, name); 1102629baa8cSmrg#ifdef TCPCONN 1103629baa8cSmrg# if defined(IPv6) && defined(AF_INET6) 1104629baa8cSmrg fd = socket (AF_INET6, SOCK_STREAM, 0); 1105629baa8cSmrg if (fd < 0) 1106629baa8cSmrg# endif 1107629baa8cSmrg fd = socket (AF_INET, SOCK_STREAM, 0); 1108629baa8cSmrg DefineSelf (fd, file, auth); 1109629baa8cSmrg close (fd); 1110629baa8cSmrg#endif 1111629baa8cSmrg DefineLocal (file, auth); 1112629baa8cSmrg} 1113629baa8cSmrg 1114629baa8cSmrg#ifdef XDMCP 1115629baa8cSmrg 1116629baa8cSmrgstatic void 1117629baa8cSmrgwriteRemoteAuth (FILE *file, Xauth *auth, XdmcpNetaddr peer, int peerlen, char *name) 1118629baa8cSmrg{ 1119629baa8cSmrg int family = FamilyLocal; 1120629baa8cSmrg char *addr; 1121629baa8cSmrg 1122629baa8cSmrg Debug ("writeRemoteAuth: %s %.*s\n", name, auth->name_length, auth->name); 1123629baa8cSmrg if (!peer || peerlen < 2) 1124629baa8cSmrg return; 1125629baa8cSmrg setAuthNumber (auth, name); 1126629baa8cSmrg family = ConvertAddr (peer, &peerlen, &addr); 1127629baa8cSmrg Debug ("writeRemoteAuth: family %d\n", family); 1128629baa8cSmrg if (family != FamilyLocal) 1129629baa8cSmrg { 1130629baa8cSmrg Debug ("writeRemoteAuth: %d, %d, %x\n", 1131629baa8cSmrg family, peerlen, *(int *)addr); 1132629baa8cSmrg writeAddr (family, peerlen, addr, file, auth); 1133629baa8cSmrg } 1134629baa8cSmrg else 1135629baa8cSmrg { 1136629baa8cSmrg writeLocalAuth (file, auth, name); 1137629baa8cSmrg } 1138629baa8cSmrg} 1139629baa8cSmrg 1140629baa8cSmrg#endif /* XDMCP */ 1141629baa8cSmrg 1142629baa8cSmrgvoid 1143629baa8cSmrgSetUserAuthorization (struct display *d, struct verify_info *verify) 1144629baa8cSmrg{ 1145629baa8cSmrg FILE *old = NULL, *new; 1146629baa8cSmrg char home_name[1024], backup_name[1024], new_name[1024]; 1147629baa8cSmrg char *name = NULL; 1148629baa8cSmrg char *home; 1149629baa8cSmrg char *envname = NULL; 1150629baa8cSmrg int lockStatus; 1151629baa8cSmrg Xauth *entry, **auths; 1152629baa8cSmrg int setenv = 0; 1153629baa8cSmrg struct stat statb; 1154629baa8cSmrg int i; 1155629baa8cSmrg int magicCookie; 1156629baa8cSmrg int data_len; 1157629baa8cSmrg#ifdef HAVE_MKSTEMP 1158629baa8cSmrg int fd; 1159629baa8cSmrg#endif 1160629baa8cSmrg 1161629baa8cSmrg Debug ("SetUserAuthorization\n"); 1162629baa8cSmrg auths = d->authorizations; 1163629baa8cSmrg if (auths) { 1164629baa8cSmrg home = getEnv (verify->userEnviron, "HOME"); 1165629baa8cSmrg lockStatus = LOCK_ERROR; 1166629baa8cSmrg if (home) { 1167629baa8cSmrg snprintf (home_name, sizeof(home_name), "%s/.Xauthority", home); 1168629baa8cSmrg Debug ("XauLockAuth %s\n", home_name); 1169629baa8cSmrg lockStatus = XauLockAuth (home_name, 1, 2, 10); 1170629baa8cSmrg Debug ("Lock is %d\n", lockStatus); 1171629baa8cSmrg if (lockStatus == LOCK_SUCCESS) { 1172629baa8cSmrg if (openFiles (home_name, new_name, &old, &new) 1173629baa8cSmrg && (old != NULL) && (new != NULL)) { 1174629baa8cSmrg name = home_name; 1175629baa8cSmrg setenv = 0; 1176629baa8cSmrg } else { 1177629baa8cSmrg Debug ("openFiles failed\n"); 1178629baa8cSmrg XauUnlockAuth (home_name); 1179629baa8cSmrg lockStatus = LOCK_ERROR; 1180629baa8cSmrg if (old != NULL) { 1181629baa8cSmrg (void) fclose (old); 1182629baa8cSmrg old = NULL; 1183629baa8cSmrg } 1184629baa8cSmrg if (new != NULL) 1185629baa8cSmrg (void) fclose (new); 1186629baa8cSmrg } 1187629baa8cSmrg } 1188629baa8cSmrg } 1189629baa8cSmrg if (lockStatus != LOCK_SUCCESS) { 1190629baa8cSmrg snprintf (backup_name, sizeof(backup_name), 1191629baa8cSmrg "%s/.XauthXXXXXX", d->userAuthDir); 1192629baa8cSmrg#ifdef HAVE_MKSTEMP 1193629baa8cSmrg fd = mkstemp (backup_name); 1194629baa8cSmrg if (fd >= 0) { 1195629baa8cSmrg old = fdopen (fd, "r"); 1196629baa8cSmrg if (old == NULL) 1197629baa8cSmrg (void) close(fd); 1198629baa8cSmrg } 1199629baa8cSmrg 1200629baa8cSmrg if (old != NULL) 1201629baa8cSmrg#else 1202629baa8cSmrg (void) mktemp (backup_name); 1203629baa8cSmrg#endif 1204629baa8cSmrg { 1205629baa8cSmrg lockStatus = XauLockAuth (backup_name, 1, 2, 10); 1206629baa8cSmrg Debug ("backup lock is %d\n", lockStatus); 1207629baa8cSmrg if (lockStatus == LOCK_SUCCESS) { 1208629baa8cSmrg if (openFiles (backup_name, new_name, &old, &new) 1209629baa8cSmrg && (old != NULL) && (new != NULL)) { 1210629baa8cSmrg name = backup_name; 1211629baa8cSmrg setenv = 1; 1212629baa8cSmrg } else { 1213629baa8cSmrg XauUnlockAuth (backup_name); 1214629baa8cSmrg lockStatus = LOCK_ERROR; 1215629baa8cSmrg if (old != NULL) { 1216629baa8cSmrg (void) fclose (old); 1217629baa8cSmrg old = NULL; 1218629baa8cSmrg } 1219629baa8cSmrg if (new != NULL) 1220629baa8cSmrg (void) fclose (new); 1221629baa8cSmrg } 1222629baa8cSmrg#ifdef HAVE_MKSTEMP 1223629baa8cSmrg } else { 1224629baa8cSmrg (void) fclose (old); 1225629baa8cSmrg#endif 1226629baa8cSmrg } 1227629baa8cSmrg } 1228629baa8cSmrg } 1229629baa8cSmrg if (lockStatus != LOCK_SUCCESS) { 1230629baa8cSmrg Debug ("can't lock auth file %s or backup %s\n", 1231629baa8cSmrg home_name, backup_name); 1232629baa8cSmrg LogError ("can't lock authorization file %s or backup %s\n", 1233629baa8cSmrg home_name, backup_name); 1234629baa8cSmrg return; 1235629baa8cSmrg } 1236629baa8cSmrg initAddrs (); 1237629baa8cSmrg doWrite = 1; 1238629baa8cSmrg Debug ("%d authorization protocols for %s\n", d->authNum, d->name); 1239629baa8cSmrg /* 1240629baa8cSmrg * Write MIT-MAGIC-COOKIE-1 authorization first, so that 1241629baa8cSmrg * R4 clients which only knew that, and used the first 1242629baa8cSmrg * matching entry will continue to function 1243629baa8cSmrg */ 1244629baa8cSmrg magicCookie = -1; 1245629baa8cSmrg for (i = 0; i < d->authNum; i++) 1246629baa8cSmrg { 1247629baa8cSmrg if (auths[i]->name_length == 18 && 1248629baa8cSmrg !strncmp (auths[i]->name, "MIT-MAGIC-COOKIE-1", 18)) 1249629baa8cSmrg { 1250629baa8cSmrg magicCookie = i; 1251629baa8cSmrg if (d->displayType.location == Local) 1252629baa8cSmrg writeLocalAuth (new, auths[i], d->name); 1253629baa8cSmrg#ifdef XDMCP 1254629baa8cSmrg else 1255629baa8cSmrg writeRemoteAuth (new, auths[i], d->peer, d->peerlen, d->name); 1256629baa8cSmrg#endif 1257629baa8cSmrg break; 1258629baa8cSmrg } 1259629baa8cSmrg } 1260629baa8cSmrg /* now write other authorizations */ 1261629baa8cSmrg for (i = 0; i < d->authNum; i++) 1262629baa8cSmrg { 1263629baa8cSmrg if (i != magicCookie) 1264629baa8cSmrg { 1265629baa8cSmrg data_len = auths[i]->data_length; 1266629baa8cSmrg /* client will just use default Kerberos cache, so don't 1267629baa8cSmrg * even write cache info into the authority file. 1268629baa8cSmrg */ 1269629baa8cSmrg if (auths[i]->name_length == 14 && 1270629baa8cSmrg !strncmp (auths[i]->name, "MIT-KERBEROS-5", 14)) 1271629baa8cSmrg auths[i]->data_length = 0; 1272629baa8cSmrg if (d->displayType.location == Local) 1273629baa8cSmrg writeLocalAuth (new, auths[i], d->name); 1274629baa8cSmrg#ifdef XDMCP 1275629baa8cSmrg else 1276629baa8cSmrg writeRemoteAuth (new, auths[i], d->peer, d->peerlen, d->name); 1277629baa8cSmrg#endif 1278629baa8cSmrg auths[i]->data_length = data_len; 1279629baa8cSmrg } 1280629baa8cSmrg } 1281629baa8cSmrg if (old) { 1282629baa8cSmrg if (fstat (fileno (old), &statb) != -1) 1283629baa8cSmrg chmod (new_name, (int) (statb.st_mode & 0777)); 1284629baa8cSmrg /*SUPPRESS 560*/ 1285629baa8cSmrg while ((entry = XauReadAuth (old))) { 1286629baa8cSmrg if (!checkEntry (entry)) 1287629baa8cSmrg { 1288629baa8cSmrg Debug ("Writing an entry\n"); 1289629baa8cSmrg writeAuth (new, entry); 1290629baa8cSmrg } 1291629baa8cSmrg XauDisposeAuth (entry); 1292629baa8cSmrg } 1293629baa8cSmrg fclose (old); 1294629baa8cSmrg } 1295629baa8cSmrg doneAddrs (); 1296629baa8cSmrg fclose (new); 1297629baa8cSmrg if (unlink (name) == -1) 1298629baa8cSmrg if (errno != ENOENT) 1299629baa8cSmrg LogError ("cannot remove old authorization file %s: %s\n", 1300629baa8cSmrg name, _SysErrorMsg (errno)); 1301629baa8cSmrg envname = name; 1302629baa8cSmrg if (link (new_name, name) == -1) { 1303629baa8cSmrg LogError ("cannot link temporary authorization file %s to old " 1304629baa8cSmrg "location %s: %s\n", new_name, name, 1305629baa8cSmrg _SysErrorMsg (errno)); 1306629baa8cSmrg setenv = 1; 1307629baa8cSmrg envname = new_name; 1308629baa8cSmrg } else { 1309629baa8cSmrg Debug ("authorization file %s successfully updated\n", name); 1310629baa8cSmrg if (unlink (new_name)) 1311629baa8cSmrg if (errno != ENOENT) 1312629baa8cSmrg LogError ("cannot remove new authorization file %s:" 1313629baa8cSmrg " %s\n", new_name, _SysErrorMsg (errno)); 1314629baa8cSmrg } 1315629baa8cSmrg if (setenv) { 1316629baa8cSmrg verify->userEnviron = setEnv (verify->userEnviron, 1317629baa8cSmrg "XAUTHORITY", envname); 1318629baa8cSmrg verify->systemEnviron = setEnv (verify->systemEnviron, 1319629baa8cSmrg "XAUTHORITY", envname); 1320629baa8cSmrg } 1321629baa8cSmrg XauUnlockAuth (name); 1322629baa8cSmrg if (envname) 1323629baa8cSmrg chown (envname, verify->uid, verify->gid); 1324629baa8cSmrg } 1325629baa8cSmrg Debug ("done SetUserAuthorization\n"); 1326629baa8cSmrg} 1327629baa8cSmrg 1328629baa8cSmrgvoid 1329629baa8cSmrgRemoveUserAuthorization (struct display *d, struct verify_info *verify) 1330629baa8cSmrg{ 1331629baa8cSmrg char *home; 1332629baa8cSmrg Xauth **auths, *entry; 1333629baa8cSmrg char name[1024], new_name[1024]; 1334629baa8cSmrg int lockStatus; 1335629baa8cSmrg FILE *old, *new; 1336629baa8cSmrg struct stat statb; 1337629baa8cSmrg int i; 1338629baa8cSmrg 1339629baa8cSmrg if (!(auths = d->authorizations)) 1340629baa8cSmrg return; 1341629baa8cSmrg home = getEnv (verify->userEnviron, "HOME"); 1342629baa8cSmrg if (!home) 1343629baa8cSmrg return; 1344629baa8cSmrg Debug ("RemoveUserAuthorization\n"); 1345629baa8cSmrg snprintf(name, sizeof(name), "%s/.Xauthority", home); 1346629baa8cSmrg Debug ("XauLockAuth %s\n", name); 1347629baa8cSmrg lockStatus = XauLockAuth (name, 1, 2, 10); 1348629baa8cSmrg Debug ("Lock is %d\n", lockStatus); 1349629baa8cSmrg if (lockStatus != LOCK_SUCCESS) 1350629baa8cSmrg return; 1351629baa8cSmrg old = NULL; 1352629baa8cSmrg if (openFiles (name, new_name, &old, &new)) 1353629baa8cSmrg { 1354629baa8cSmrg initAddrs (); 1355629baa8cSmrg doWrite = 0; 1356629baa8cSmrg for (i = 0; i < d->authNum; i++) 1357629baa8cSmrg { 1358629baa8cSmrg if (d->displayType.location == Local) 1359629baa8cSmrg writeLocalAuth (new, auths[i], d->name); 1360629baa8cSmrg#ifdef XDMCP 1361629baa8cSmrg else 1362629baa8cSmrg writeRemoteAuth (new, auths[i], d->peer, d->peerlen, d->name); 1363629baa8cSmrg#endif 1364629baa8cSmrg } 1365629baa8cSmrg doWrite = 1; 1366629baa8cSmrg if (old) { 1367629baa8cSmrg if (fstat (fileno (old), &statb) != -1) 1368629baa8cSmrg chmod (new_name, (int) (statb.st_mode & 0777)); 1369629baa8cSmrg /*SUPPRESS 560*/ 1370629baa8cSmrg while ((entry = XauReadAuth (old))) { 1371629baa8cSmrg if (!checkEntry (entry)) 1372629baa8cSmrg { 1373629baa8cSmrg Debug ("Writing an entry\n"); 1374629baa8cSmrg writeAuth (new, entry); 1375629baa8cSmrg } 1376629baa8cSmrg XauDisposeAuth (entry); 1377629baa8cSmrg } 1378629baa8cSmrg fclose (old); 1379629baa8cSmrg } 1380629baa8cSmrg doneAddrs (); 1381629baa8cSmrg fclose (new); 1382629baa8cSmrg if (unlink (name) == -1) 1383629baa8cSmrg if (errno != ENOENT) 1384629baa8cSmrg LogError ("cannot remove new authorization file %s: %s\n", 1385629baa8cSmrg name, _SysErrorMsg (errno)); 1386629baa8cSmrg if (link (new_name, name) == -1) { 1387629baa8cSmrg LogError ("cannot link temporary authorization file %s to old " 1388629baa8cSmrg "location %s: %s\n", new_name, name, 1389629baa8cSmrg _SysErrorMsg (errno)); 1390629baa8cSmrg } else { 1391629baa8cSmrg Debug ("authorization file %s successfully updated\n", name); 1392629baa8cSmrg if (unlink (new_name)) 1393629baa8cSmrg if (errno != ENOENT) 1394629baa8cSmrg LogError ("cannot remove new authorization file %s:" 1395629baa8cSmrg " %s\n", new_name, _SysErrorMsg (errno)); 1396629baa8cSmrg } 1397629baa8cSmrg } 1398629baa8cSmrg XauUnlockAuth (name); 1399629baa8cSmrg} 1400