auth.c revision f9f7a7f2
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 268da2e2ef6Smrg * Returns: 0 if already exists, 1 if created, < 0 if error occurred 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 } 664da2e2ef6Smrg addrs = NULL; 665629baa8cSmrg} 666629baa8cSmrg 667629baa8cSmrgstatic int checkEntry (Xauth *auth); 668629baa8cSmrg 669629baa8cSmrgstatic void 670629baa8cSmrgsaveEntry (Xauth *auth) 671629baa8cSmrg{ 672629baa8cSmrg struct addrList *new; 673629baa8cSmrg 674629baa8cSmrg new = malloc (sizeof (struct addrList)); 675629baa8cSmrg if (!new) { 676629baa8cSmrg LogOutOfMem ("saveEntry"); 677629baa8cSmrg return; 678629baa8cSmrg } 679629baa8cSmrg if ((new->address_length = auth->address_length) > 0) { 680629baa8cSmrg new->address = malloc (auth->address_length); 681629baa8cSmrg if (!new->address) { 682629baa8cSmrg LogOutOfMem ("saveEntry"); 683629baa8cSmrg free (new); 684629baa8cSmrg return; 685629baa8cSmrg } 686f9f7a7f2Smrg memcpy(new->address, auth->address, (int) auth->address_length); 687629baa8cSmrg } else 688629baa8cSmrg new->address = NULL; 689629baa8cSmrg if ((new->number_length = auth->number_length) > 0) { 690629baa8cSmrg new->number = malloc (auth->number_length); 691629baa8cSmrg if (!new->number) { 692629baa8cSmrg LogOutOfMem ("saveEntry"); 693629baa8cSmrg free (new->address); 694629baa8cSmrg free (new); 695629baa8cSmrg return; 696629baa8cSmrg } 697f9f7a7f2Smrg memcpy(new->number, auth->number, (int) auth->number_length); 698629baa8cSmrg } else 699629baa8cSmrg new->number = NULL; 700629baa8cSmrg if ((new->name_length = auth->name_length) > 0) { 701629baa8cSmrg new->name = malloc (auth->name_length); 702629baa8cSmrg if (!new->name) { 703629baa8cSmrg LogOutOfMem ("saveEntry"); 704629baa8cSmrg free (new->number); 705629baa8cSmrg free (new->address); 706629baa8cSmrg free (new); 707629baa8cSmrg return; 708629baa8cSmrg } 709f9f7a7f2Smrg memcpy(new->name, auth->name, (int) auth->name_length); 710629baa8cSmrg } else 711629baa8cSmrg new->name = NULL; 712629baa8cSmrg new->family = auth->family; 713629baa8cSmrg new->next = addrs; 714629baa8cSmrg addrs = new; 715629baa8cSmrg} 716629baa8cSmrg 717629baa8cSmrgstatic int 718629baa8cSmrgcheckEntry (Xauth *auth) 719629baa8cSmrg{ 720629baa8cSmrg struct addrList *a; 721629baa8cSmrg 722629baa8cSmrg for (a = addrs; a; a = a->next) { 723629baa8cSmrg if (a->family == auth->family && 724629baa8cSmrg a->address_length == auth->address_length && 725629baa8cSmrg binaryEqual (a->address, auth->address, auth->address_length) && 726629baa8cSmrg a->number_length == auth->number_length && 727629baa8cSmrg binaryEqual (a->number, auth->number, auth->number_length) && 728629baa8cSmrg a->name_length == auth->name_length && 729629baa8cSmrg binaryEqual (a->name, auth->name, auth->name_length)) 730629baa8cSmrg { 731629baa8cSmrg return 1; 732629baa8cSmrg } 733629baa8cSmrg } 734629baa8cSmrg return 0; 735629baa8cSmrg} 736629baa8cSmrg 737629baa8cSmrgstatic int doWrite; 738629baa8cSmrg 739629baa8cSmrgstatic void 740629baa8cSmrgwriteAuth (FILE *file, Xauth *auth) 741629baa8cSmrg{ 742629baa8cSmrg if (debugLevel >= 15) { /* normally too verbose */ 743629baa8cSmrg Debug ("writeAuth: doWrite = %d\n", doWrite); 744629baa8cSmrg dumpAuth (auth); /* does Debug only */ 745629baa8cSmrg } 746629baa8cSmrg if (doWrite) 747629baa8cSmrg XauWriteAuth (file, auth); 748629baa8cSmrg} 749629baa8cSmrg 750629baa8cSmrgstatic void 751629baa8cSmrgwriteAddr ( 752629baa8cSmrg int family, 753629baa8cSmrg int addr_length, 754629baa8cSmrg char *addr, 755629baa8cSmrg FILE *file, 756629baa8cSmrg Xauth *auth) 757629baa8cSmrg{ 758629baa8cSmrg auth->family = (unsigned short) family; 759629baa8cSmrg auth->address_length = addr_length; 760629baa8cSmrg auth->address = addr; 761629baa8cSmrg Debug ("writeAddr: writing and saving an entry\n"); 762629baa8cSmrg writeAuth (file, auth); 763629baa8cSmrg saveEntry (auth); 764629baa8cSmrg} 765629baa8cSmrg 766629baa8cSmrgstatic void 767629baa8cSmrgDefineLocal (FILE *file, Xauth *auth) 768629baa8cSmrg{ 769629baa8cSmrg char displayname[100]; 770629baa8cSmrg int len = _XGetHostname (displayname, sizeof(displayname)); 771629baa8cSmrg 772629baa8cSmrg/* Make sure this produces the same string as _XGetHostname in lib/X/XlibInt.c. 773629baa8cSmrg * Otherwise, Xau will not be able to find your cookies in the Xauthority file. 774629baa8cSmrg * 775629baa8cSmrg * Note: POSIX says that the ``nodename'' member of utsname does _not_ have 776629baa8cSmrg * to have sufficient information for interfacing to the network, 777629baa8cSmrg * and so, you may be better off using gethostname (if it exists). 778629baa8cSmrg */ 779629baa8cSmrg 780629baa8cSmrg#if defined(hpux) 781629baa8cSmrg /* 782629baa8cSmrg * For HP-UX, HP's Xlib expects a fully-qualified domain name, which 783da2e2ef6Smrg * is achieved by using gethostname(). For compatibility, we must 784629baa8cSmrg * also still create the entry using uname(). 785629baa8cSmrg */ 786629baa8cSmrg char tmp_displayname[100]; 787629baa8cSmrg struct utsname name; 788629baa8cSmrg 789629baa8cSmrg tmp_displayname[0] = 0; 790629baa8cSmrg uname(&name); 791629baa8cSmrg snprintf(tmp_displayname, sizeof(tmp_displayname), "%s", name.nodename); 792629baa8cSmrg writeAddr (FamilyLocal, strlen (tmp_displayname), tmp_displayname, 793629baa8cSmrg file, auth); 794629baa8cSmrg 795629baa8cSmrg /* 796629baa8cSmrg * If _XGetHostname() returned the same value as uname(), don't 797629baa8cSmrg * write a duplicate entry. 798629baa8cSmrg */ 799629baa8cSmrg if (strcmp (displayname, tmp_displayname)) 800629baa8cSmrg#endif 801629baa8cSmrg 802629baa8cSmrg writeAddr (FamilyLocal, len, displayname, file, auth); 803629baa8cSmrg} 804629baa8cSmrg 805629baa8cSmrg#ifdef HAVE_GETIFADDRS 806629baa8cSmrg# include <ifaddrs.h> 807629baa8cSmrg 808629baa8cSmrgstatic void 809629baa8cSmrgDefineSelf(int fd, FILE *file, Xauth *auth) 810629baa8cSmrg{ 811629baa8cSmrg struct ifaddrs *ifap, *ifr; 812629baa8cSmrg char *addr; 813629baa8cSmrg int family, len; 814629baa8cSmrg 815629baa8cSmrg Debug("DefineSelf\n"); 816629baa8cSmrg if (getifaddrs(&ifap) < 0) 817629baa8cSmrg return; 818629baa8cSmrg for (ifr = ifap; ifr != NULL; ifr = ifr->ifa_next) { 819629baa8cSmrg len = sizeof(*(ifr->ifa_addr)); 820629baa8cSmrg family = ConvertAddr((XdmcpNetaddr)(ifr->ifa_addr), &len, &addr); 821629baa8cSmrg if (family == -1 || family == FamilyLocal) 822629baa8cSmrg continue; 823629baa8cSmrg /* 824629baa8cSmrg * don't write out 'localhost' entries, as 825629baa8cSmrg * they may conflict with other local entries. 826629baa8cSmrg * DefineLocal will always be called to add 827629baa8cSmrg * the local entry anyway, so this one can 828629baa8cSmrg * be tossed. 829629baa8cSmrg */ 830629baa8cSmrg if (family == FamilyInternet && len == 4 && addr[0] == 127) 831629baa8cSmrg { 832629baa8cSmrg Debug ("Skipping localhost address\n"); 833629baa8cSmrg continue; 834629baa8cSmrg } 835629baa8cSmrg# if defined(IPv6) && defined(AF_INET6) 836629baa8cSmrg if(family == FamilyInternet6) { 837629baa8cSmrg if (IN6_IS_ADDR_LOOPBACK(((struct in6_addr *)addr))) { 838629baa8cSmrg Debug ("Skipping IPv6 localhost address\n"); 839629baa8cSmrg continue; 840629baa8cSmrg } 841629baa8cSmrg /* Also skip XDM-AUTHORIZATION-1 */ 842629baa8cSmrg if (auth->name_length == 19 && 843629baa8cSmrg strcmp(auth->name, "XDM-AUTHORIZATION-1") == 0) { 844629baa8cSmrg Debug ("Skipping IPv6 XDM-AUTHORIZATION-1\n"); 845629baa8cSmrg continue; 846629baa8cSmrg } 847629baa8cSmrg } 848629baa8cSmrg# endif 849629baa8cSmrg writeAddr(family, len, addr, file, auth); 850629baa8cSmrg } 851629baa8cSmrg freeifaddrs(ifap); 852629baa8cSmrg Debug("DefineSelf done\n"); 853629baa8cSmrg} 854629baa8cSmrg#else /* GETIFADDRS */ 855629baa8cSmrg 856629baa8cSmrg# ifdef SYSV_SIOCGIFCONF 857629baa8cSmrg 858629baa8cSmrg/* Deal with different SIOCGIFCONF ioctl semantics on SYSV, SVR4 */ 859629baa8cSmrg 860629baa8cSmrgstatic int 861629baa8cSmrgifioctl (int fd, int cmd, char *arg) 862629baa8cSmrg{ 863629baa8cSmrg struct strioctl ioc; 864629baa8cSmrg int ret; 865629baa8cSmrg 866629baa8cSmrg bzero((char *) &ioc, sizeof(ioc)); 867629baa8cSmrg ioc.ic_cmd = cmd; 868629baa8cSmrg ioc.ic_timout = 0; 869629baa8cSmrg if (cmd == SIOCGIFCONF) 870629baa8cSmrg { 871629baa8cSmrg ioc.ic_len = ((struct ifconf *) arg)->ifc_len; 872629baa8cSmrg ioc.ic_dp = ((struct ifconf *) arg)->ifc_buf; 873629baa8cSmrg } 874629baa8cSmrg else 875629baa8cSmrg { 876629baa8cSmrg ioc.ic_len = sizeof(struct ifreq); 877629baa8cSmrg ioc.ic_dp = arg; 878629baa8cSmrg } 879629baa8cSmrg ret = ioctl(fd, I_STR, (char *) &ioc); 880629baa8cSmrg if (ret >= 0 && cmd == SIOCGIFCONF) 881629baa8cSmrg ((struct ifconf *) arg)->ifc_len = ioc.ic_len; 882629baa8cSmrg return(ret); 883629baa8cSmrg} 884629baa8cSmrg# else /* SYSV_SIOCGIFCONF */ 885629baa8cSmrg# define ifioctl ioctl 886629baa8cSmrg# endif /* SYSV_SIOCGIFCONF */ 887629baa8cSmrg 888629baa8cSmrg 889629baa8cSmrg 890b7d26471Smrg# if defined(SIOCGIFCONF) || defined (USE_SIOCGLIFCONF) 891629baa8cSmrg 892b7d26471Smrg# ifdef USE_SIOCGLIFCONF 893b7d26471Smrg# define ifr_type struct lifreq 894b7d26471Smrg# else 895b7d26471Smrg# define ifr_type struct ifreq 896b7d26471Smrg# endif 897629baa8cSmrg 898629baa8cSmrg/* Handle variable length ifreq in BNR2 and later */ 899b7d26471Smrg# ifdef VARIABLE_IFREQ 900b7d26471Smrg# define ifr_size(p) (sizeof (struct ifreq) + \ 901629baa8cSmrg (p->ifr_addr.sa_len > sizeof (p->ifr_addr) ? \ 902629baa8cSmrg p->ifr_addr.sa_len - sizeof (p->ifr_addr) : 0)) 903b7d26471Smrg# else 904b7d26471Smrg# define ifr_size(p) (sizeof (ifr_type)) 905b7d26471Smrg# endif 906629baa8cSmrg 907629baa8cSmrg/* Define this host for access control. Find all the hosts the OS knows about 908629baa8cSmrg * for this fd and add them to the selfhosts list. 909629baa8cSmrg */ 910629baa8cSmrgstatic void 911629baa8cSmrgDefineSelf (int fd, FILE *file, Xauth *auth) 912629baa8cSmrg{ 913629baa8cSmrg char buf[2048], *cp, *cplim; 914629baa8cSmrg int len; 915629baa8cSmrg char *addr; 916629baa8cSmrg int family; 917629baa8cSmrg register ifr_type *ifr; 918b7d26471Smrg# ifdef USE_SIOCGLIFCONF 919629baa8cSmrg void * bufptr = buf; 920629baa8cSmrg size_t buflen = sizeof(buf); 921629baa8cSmrg struct lifconf ifc; 922b7d26471Smrg# ifdef SIOCGLIFNUM 923629baa8cSmrg struct lifnum ifn; 924b7d26471Smrg# endif 925b7d26471Smrg# else 926629baa8cSmrg struct ifconf ifc; 927b7d26471Smrg# endif 928629baa8cSmrg 929b7d26471Smrg# if defined(SIOCGLIFNUM) && defined(SIOCGLIFCONF) 930629baa8cSmrg ifn.lifn_family = AF_UNSPEC; 931629baa8cSmrg ifn.lifn_flags = 0; 932629baa8cSmrg if (ioctl (fd, (int) SIOCGLIFNUM, (char *) &ifn) < 0) 933629baa8cSmrg LogError ("Failed getting interface count"); 934629baa8cSmrg if (buflen < (ifn.lifn_count * sizeof(struct lifreq))) { 935629baa8cSmrg buflen = ifn.lifn_count * sizeof(struct lifreq); 936629baa8cSmrg bufptr = malloc(buflen); 937629baa8cSmrg } 938b7d26471Smrg# endif 939629baa8cSmrg 940b7d26471Smrg# ifdef USE_SIOCGLIFCONF 941629baa8cSmrg ifc.lifc_family = AF_UNSPEC; 942629baa8cSmrg ifc.lifc_flags = 0; 943629baa8cSmrg ifc.lifc_len = buflen; 944629baa8cSmrg ifc.lifc_buf = bufptr; 945629baa8cSmrg 946b7d26471Smrg# define IFC_IOCTL_REQ SIOCGLIFCONF 947b7d26471Smrg# define IFC_IFC_REQ ifc.lifc_req 948b7d26471Smrg# define IFC_IFC_LEN ifc.lifc_len 949b7d26471Smrg# define IFR_IFR_ADDR ifr->lifr_addr 950b7d26471Smrg# define IFR_IFR_NAME ifr->lifr_name 951629baa8cSmrg 952b7d26471Smrg# else 953629baa8cSmrg ifc.ifc_len = sizeof (buf); 954629baa8cSmrg ifc.ifc_buf = buf; 955629baa8cSmrg 956b7d26471Smrg# define IFC_IOCTL_REQ SIOCGIFCONF 957b7d26471Smrg# define IFC_IFC_REQ ifc.ifc_req 958b7d26471Smrg# define IFC_IFC_LEN ifc.ifc_len 959b7d26471Smrg# define IFR_IFR_ADDR ifr->ifr_addr 960b7d26471Smrg# define IFR_IFR_NAME ifr->ifr_name 961b7d26471Smrg# endif 962629baa8cSmrg 963629baa8cSmrg if (ifioctl (fd, IFC_IOCTL_REQ, (char *) &ifc) < 0) { 964629baa8cSmrg LogError ("Trouble getting network interface configuration"); 965629baa8cSmrg 966b7d26471Smrg# ifdef USE_SIOCGLIFCONF 967629baa8cSmrg if (bufptr != buf) { 968629baa8cSmrg free(bufptr); 969629baa8cSmrg } 970b7d26471Smrg# endif 971629baa8cSmrg return; 972629baa8cSmrg } 973629baa8cSmrg 974629baa8cSmrg cplim = (char *) IFC_IFC_REQ + IFC_IFC_LEN; 975629baa8cSmrg 976629baa8cSmrg for (cp = (char *) IFC_IFC_REQ; cp < cplim; cp += ifr_size (ifr)) 977629baa8cSmrg { 978629baa8cSmrg ifr = (ifr_type *) cp; 979b7d26471Smrg family = ConvertAddr ((XdmcpNetaddr) &IFR_IFR_ADDR, &len, &addr); 980b7d26471Smrg if (family < 0) 981b7d26471Smrg continue; 982b7d26471Smrg 983b7d26471Smrg if (len == 0) 984b7d26471Smrg { 985b7d26471Smrg Debug ("Skipping zero length address\n"); 986b7d26471Smrg continue; 987b7d26471Smrg } 988629baa8cSmrg /* 989b7d26471Smrg * don't write out 'localhost' entries, as 990b7d26471Smrg * they may conflict with other local entries. 991b7d26471Smrg * DefineLocal will always be called to add 992b7d26471Smrg * the local entry anyway, so this one can 993b7d26471Smrg * be tossed. 994629baa8cSmrg */ 995b7d26471Smrg if (family == FamilyInternet && len == 4 && 996b7d26471Smrg addr[0] == 127 && addr[1] == 0 && 997b7d26471Smrg addr[2] == 0 && addr[3] == 1) 998629baa8cSmrg { 999b7d26471Smrg Debug ("Skipping localhost address\n"); 1000b7d26471Smrg continue; 1001b7d26471Smrg } 1002b7d26471Smrg# if defined(IPv6) && defined(AF_INET6) 1003b7d26471Smrg if (family == FamilyInternet6) { 1004b7d26471Smrg if (IN6_IS_ADDR_LOOPBACK(((struct in6_addr *)addr))) { 1005b7d26471Smrg Debug ("Skipping IPv6 localhost address\n"); 1006629baa8cSmrg continue; 1007629baa8cSmrg } 1008b7d26471Smrg /* Also skip XDM-AUTHORIZATION-1 */ 1009b7d26471Smrg if (auth->name_length == 19 && 1010b7d26471Smrg strcmp(auth->name, "XDM-AUTHORIZATION-1") == 0) { 1011b7d26471Smrg Debug ("Skipping IPv6 XDM-AUTHORIZATION-1\n"); 1012b7d26471Smrg continue; 1013629baa8cSmrg } 1014629baa8cSmrg } 1015b7d26471Smrg# endif 1016629baa8cSmrg Debug ("DefineSelf: write network address, length %d\n", len); 1017629baa8cSmrg writeAddr (family, len, addr, file, auth); 1018629baa8cSmrg } 1019629baa8cSmrg} 1020629baa8cSmrg 1021b7d26471Smrg# else /* SIOCGIFCONF */ 1022629baa8cSmrg 1023629baa8cSmrg/* Define this host for access control. Find all the hosts the OS knows about 1024629baa8cSmrg * for this fd and add them to the selfhosts list. 1025629baa8cSmrg */ 1026629baa8cSmrgstatic void 1027629baa8cSmrgDefineSelf (int fd, int file, int auth) 1028629baa8cSmrg{ 1029629baa8cSmrg register int n; 1030629baa8cSmrg int len; 1031629baa8cSmrg caddr_t addr; 1032629baa8cSmrg int family; 1033629baa8cSmrg 1034629baa8cSmrg struct utsname name; 1035629baa8cSmrg register struct hostent *hp; 1036629baa8cSmrg 1037629baa8cSmrg union { 1038629baa8cSmrg struct sockaddr sa; 1039629baa8cSmrg struct sockaddr_in in; 1040629baa8cSmrg } saddr; 1041629baa8cSmrg 1042629baa8cSmrg struct sockaddr_in *inetaddr; 1043629baa8cSmrg 1044629baa8cSmrg /* hpux: 1045629baa8cSmrg * Why not use gethostname()? Well, at least on my system, I've had to 1046629baa8cSmrg * make an ugly kernel patch to get a name longer than 8 characters, and 1047629baa8cSmrg * uname() lets me access to the whole string (it smashes release, you 1048629baa8cSmrg * see), whereas gethostname() kindly truncates it for me. 1049629baa8cSmrg */ 1050629baa8cSmrg uname(&name); 1051629baa8cSmrg hp = gethostbyname (name.nodename); 1052629baa8cSmrg if (hp != NULL) { 1053629baa8cSmrg saddr.sa.sa_family = hp->h_addrtype; 1054629baa8cSmrg inetaddr = (struct sockaddr_in *) (&(saddr.sa)); 1055f9f7a7f2Smrg memcpy(&(inetaddr->sin_addr), hp->h_addr, hp->h_length); 1056629baa8cSmrg family = ConvertAddr ( &(saddr.sa), &len, &addr); 1057629baa8cSmrg if ( family >= 0) { 1058629baa8cSmrg writeAddr (FamilyInternet, sizeof (inetaddr->sin_addr), 1059629baa8cSmrg (char *) (&inetaddr->sin_addr), file, auth); 1060629baa8cSmrg } 1061629baa8cSmrg } 1062629baa8cSmrg} 1063629baa8cSmrg 1064629baa8cSmrg 1065b7d26471Smrg# endif /* SIOCGIFCONF else */ 1066629baa8cSmrg#endif /* HAVE_GETIFADDRS */ 1067629baa8cSmrg 1068629baa8cSmrgstatic void 1069629baa8cSmrgsetAuthNumber (Xauth *auth, char *name) 1070629baa8cSmrg{ 1071629baa8cSmrg char *colon; 1072629baa8cSmrg char *dot, *number; 1073629baa8cSmrg 1074629baa8cSmrg Debug ("setAuthNumber %s\n", name); 1075629baa8cSmrg colon = strrchr(name, ':'); 1076629baa8cSmrg if (colon) { 1077629baa8cSmrg ++colon; 1078629baa8cSmrg dot = strchr(colon, '.'); 1079629baa8cSmrg if (dot) 1080629baa8cSmrg auth->number_length = dot - colon; 1081629baa8cSmrg else 1082629baa8cSmrg auth->number_length = strlen (colon); 1083629baa8cSmrg number = malloc (auth->number_length + 1); 1084629baa8cSmrg if (number) { 1085629baa8cSmrg strncpy (number, colon, auth->number_length); 1086629baa8cSmrg number[auth->number_length] = '\0'; 1087629baa8cSmrg } else { 1088629baa8cSmrg LogOutOfMem ("setAuthNumber"); 1089629baa8cSmrg auth->number_length = 0; 1090629baa8cSmrg } 1091629baa8cSmrg auth->number = number; 1092629baa8cSmrg Debug ("setAuthNumber: %s\n", number); 1093629baa8cSmrg } 1094629baa8cSmrg} 1095629baa8cSmrg 1096629baa8cSmrgstatic void 1097629baa8cSmrgwriteLocalAuth (FILE *file, Xauth *auth, char *name) 1098629baa8cSmrg{ 1099629baa8cSmrg int fd; 1100629baa8cSmrg 1101629baa8cSmrg Debug ("writeLocalAuth: %s %.*s\n", name, auth->name_length, auth->name); 1102629baa8cSmrg setAuthNumber (auth, name); 1103629baa8cSmrg#ifdef TCPCONN 1104629baa8cSmrg# if defined(IPv6) && defined(AF_INET6) 1105629baa8cSmrg fd = socket (AF_INET6, SOCK_STREAM, 0); 1106629baa8cSmrg if (fd < 0) 1107629baa8cSmrg# endif 1108629baa8cSmrg fd = socket (AF_INET, SOCK_STREAM, 0); 1109629baa8cSmrg DefineSelf (fd, file, auth); 1110629baa8cSmrg close (fd); 1111629baa8cSmrg#endif 1112629baa8cSmrg DefineLocal (file, auth); 1113629baa8cSmrg} 1114629baa8cSmrg 1115629baa8cSmrg#ifdef XDMCP 1116629baa8cSmrg 1117629baa8cSmrgstatic void 1118629baa8cSmrgwriteRemoteAuth (FILE *file, Xauth *auth, XdmcpNetaddr peer, int peerlen, char *name) 1119629baa8cSmrg{ 1120629baa8cSmrg int family = FamilyLocal; 1121629baa8cSmrg char *addr; 1122629baa8cSmrg 1123629baa8cSmrg Debug ("writeRemoteAuth: %s %.*s\n", name, auth->name_length, auth->name); 1124629baa8cSmrg if (!peer || peerlen < 2) 1125629baa8cSmrg return; 1126629baa8cSmrg setAuthNumber (auth, name); 1127629baa8cSmrg family = ConvertAddr (peer, &peerlen, &addr); 1128629baa8cSmrg Debug ("writeRemoteAuth: family %d\n", family); 1129629baa8cSmrg if (family != FamilyLocal) 1130629baa8cSmrg { 1131629baa8cSmrg Debug ("writeRemoteAuth: %d, %d, %x\n", 1132629baa8cSmrg family, peerlen, *(int *)addr); 1133629baa8cSmrg writeAddr (family, peerlen, addr, file, auth); 1134629baa8cSmrg } 1135629baa8cSmrg else 1136629baa8cSmrg { 1137629baa8cSmrg writeLocalAuth (file, auth, name); 1138629baa8cSmrg } 1139629baa8cSmrg} 1140629baa8cSmrg 1141629baa8cSmrg#endif /* XDMCP */ 1142629baa8cSmrg 1143629baa8cSmrgvoid 1144629baa8cSmrgSetUserAuthorization (struct display *d, struct verify_info *verify) 1145629baa8cSmrg{ 1146629baa8cSmrg FILE *old = NULL, *new; 1147629baa8cSmrg char home_name[1024], backup_name[1024], new_name[1024]; 1148629baa8cSmrg char *name = NULL; 1149629baa8cSmrg char *home; 1150629baa8cSmrg char *envname = NULL; 1151629baa8cSmrg int lockStatus; 1152629baa8cSmrg Xauth *entry, **auths; 1153629baa8cSmrg int setenv = 0; 1154629baa8cSmrg struct stat statb; 1155629baa8cSmrg int i; 1156629baa8cSmrg int magicCookie; 1157629baa8cSmrg int data_len; 1158629baa8cSmrg#ifdef HAVE_MKSTEMP 1159629baa8cSmrg int fd; 1160629baa8cSmrg#endif 1161629baa8cSmrg 1162629baa8cSmrg Debug ("SetUserAuthorization\n"); 1163629baa8cSmrg auths = d->authorizations; 1164629baa8cSmrg if (auths) { 1165629baa8cSmrg home = getEnv (verify->userEnviron, "HOME"); 1166629baa8cSmrg lockStatus = LOCK_ERROR; 1167629baa8cSmrg if (home) { 1168629baa8cSmrg snprintf (home_name, sizeof(home_name), "%s/.Xauthority", home); 1169629baa8cSmrg Debug ("XauLockAuth %s\n", home_name); 1170629baa8cSmrg lockStatus = XauLockAuth (home_name, 1, 2, 10); 1171629baa8cSmrg Debug ("Lock is %d\n", lockStatus); 1172629baa8cSmrg if (lockStatus == LOCK_SUCCESS) { 1173629baa8cSmrg if (openFiles (home_name, new_name, &old, &new) 1174629baa8cSmrg && (old != NULL) && (new != NULL)) { 1175629baa8cSmrg name = home_name; 1176629baa8cSmrg setenv = 0; 1177629baa8cSmrg } else { 1178629baa8cSmrg Debug ("openFiles failed\n"); 1179629baa8cSmrg XauUnlockAuth (home_name); 1180629baa8cSmrg lockStatus = LOCK_ERROR; 1181629baa8cSmrg if (old != NULL) { 1182629baa8cSmrg (void) fclose (old); 1183629baa8cSmrg old = NULL; 1184629baa8cSmrg } 1185629baa8cSmrg if (new != NULL) 1186629baa8cSmrg (void) fclose (new); 1187629baa8cSmrg } 1188629baa8cSmrg } 1189629baa8cSmrg } 1190629baa8cSmrg if (lockStatus != LOCK_SUCCESS) { 1191629baa8cSmrg snprintf (backup_name, sizeof(backup_name), 1192629baa8cSmrg "%s/.XauthXXXXXX", d->userAuthDir); 1193629baa8cSmrg#ifdef HAVE_MKSTEMP 1194629baa8cSmrg fd = mkstemp (backup_name); 1195629baa8cSmrg if (fd >= 0) { 1196629baa8cSmrg old = fdopen (fd, "r"); 1197629baa8cSmrg if (old == NULL) 1198629baa8cSmrg (void) close(fd); 1199629baa8cSmrg } 1200629baa8cSmrg 1201629baa8cSmrg if (old != NULL) 1202629baa8cSmrg#else 1203629baa8cSmrg (void) mktemp (backup_name); 1204629baa8cSmrg#endif 1205629baa8cSmrg { 1206629baa8cSmrg lockStatus = XauLockAuth (backup_name, 1, 2, 10); 1207629baa8cSmrg Debug ("backup lock is %d\n", lockStatus); 1208629baa8cSmrg if (lockStatus == LOCK_SUCCESS) { 1209629baa8cSmrg if (openFiles (backup_name, new_name, &old, &new) 1210629baa8cSmrg && (old != NULL) && (new != NULL)) { 1211629baa8cSmrg name = backup_name; 1212629baa8cSmrg setenv = 1; 1213629baa8cSmrg } else { 1214629baa8cSmrg XauUnlockAuth (backup_name); 1215629baa8cSmrg lockStatus = LOCK_ERROR; 1216629baa8cSmrg if (old != NULL) { 1217629baa8cSmrg (void) fclose (old); 1218629baa8cSmrg old = NULL; 1219629baa8cSmrg } 1220629baa8cSmrg if (new != NULL) 1221629baa8cSmrg (void) fclose (new); 1222629baa8cSmrg } 1223629baa8cSmrg#ifdef HAVE_MKSTEMP 1224629baa8cSmrg } else { 1225629baa8cSmrg (void) fclose (old); 1226629baa8cSmrg#endif 1227629baa8cSmrg } 1228629baa8cSmrg } 1229629baa8cSmrg } 1230629baa8cSmrg if (lockStatus != LOCK_SUCCESS) { 1231629baa8cSmrg Debug ("can't lock auth file %s or backup %s\n", 1232629baa8cSmrg home_name, backup_name); 1233629baa8cSmrg LogError ("can't lock authorization file %s or backup %s\n", 1234629baa8cSmrg home_name, backup_name); 1235629baa8cSmrg return; 1236629baa8cSmrg } 1237629baa8cSmrg initAddrs (); 1238629baa8cSmrg doWrite = 1; 1239629baa8cSmrg Debug ("%d authorization protocols for %s\n", d->authNum, d->name); 1240629baa8cSmrg /* 1241629baa8cSmrg * Write MIT-MAGIC-COOKIE-1 authorization first, so that 1242629baa8cSmrg * R4 clients which only knew that, and used the first 1243629baa8cSmrg * matching entry will continue to function 1244629baa8cSmrg */ 1245629baa8cSmrg magicCookie = -1; 1246629baa8cSmrg for (i = 0; i < d->authNum; i++) 1247629baa8cSmrg { 1248629baa8cSmrg if (auths[i]->name_length == 18 && 1249629baa8cSmrg !strncmp (auths[i]->name, "MIT-MAGIC-COOKIE-1", 18)) 1250629baa8cSmrg { 1251629baa8cSmrg magicCookie = i; 1252629baa8cSmrg if (d->displayType.location == Local) 1253629baa8cSmrg writeLocalAuth (new, auths[i], d->name); 1254629baa8cSmrg#ifdef XDMCP 1255629baa8cSmrg else 1256629baa8cSmrg writeRemoteAuth (new, auths[i], d->peer, d->peerlen, d->name); 1257629baa8cSmrg#endif 1258629baa8cSmrg break; 1259629baa8cSmrg } 1260629baa8cSmrg } 1261629baa8cSmrg /* now write other authorizations */ 1262629baa8cSmrg for (i = 0; i < d->authNum; i++) 1263629baa8cSmrg { 1264629baa8cSmrg if (i != magicCookie) 1265629baa8cSmrg { 1266629baa8cSmrg data_len = auths[i]->data_length; 1267629baa8cSmrg /* client will just use default Kerberos cache, so don't 1268629baa8cSmrg * even write cache info into the authority file. 1269629baa8cSmrg */ 1270629baa8cSmrg if (auths[i]->name_length == 14 && 1271629baa8cSmrg !strncmp (auths[i]->name, "MIT-KERBEROS-5", 14)) 1272629baa8cSmrg auths[i]->data_length = 0; 1273629baa8cSmrg if (d->displayType.location == Local) 1274629baa8cSmrg writeLocalAuth (new, auths[i], d->name); 1275629baa8cSmrg#ifdef XDMCP 1276629baa8cSmrg else 1277629baa8cSmrg writeRemoteAuth (new, auths[i], d->peer, d->peerlen, d->name); 1278629baa8cSmrg#endif 1279629baa8cSmrg auths[i]->data_length = data_len; 1280629baa8cSmrg } 1281629baa8cSmrg } 1282629baa8cSmrg if (old) { 1283629baa8cSmrg if (fstat (fileno (old), &statb) != -1) 1284629baa8cSmrg chmod (new_name, (int) (statb.st_mode & 0777)); 1285629baa8cSmrg /*SUPPRESS 560*/ 1286629baa8cSmrg while ((entry = XauReadAuth (old))) { 1287629baa8cSmrg if (!checkEntry (entry)) 1288629baa8cSmrg { 1289629baa8cSmrg Debug ("Writing an entry\n"); 1290629baa8cSmrg writeAuth (new, entry); 1291629baa8cSmrg } 1292629baa8cSmrg XauDisposeAuth (entry); 1293629baa8cSmrg } 1294629baa8cSmrg fclose (old); 1295629baa8cSmrg } 1296629baa8cSmrg doneAddrs (); 1297629baa8cSmrg fclose (new); 1298629baa8cSmrg if (unlink (name) == -1) 1299629baa8cSmrg if (errno != ENOENT) 1300629baa8cSmrg LogError ("cannot remove old authorization file %s: %s\n", 1301629baa8cSmrg name, _SysErrorMsg (errno)); 1302629baa8cSmrg envname = name; 1303629baa8cSmrg if (link (new_name, name) == -1) { 1304629baa8cSmrg LogError ("cannot link temporary authorization file %s to old " 1305629baa8cSmrg "location %s: %s\n", new_name, name, 1306629baa8cSmrg _SysErrorMsg (errno)); 1307629baa8cSmrg setenv = 1; 1308629baa8cSmrg envname = new_name; 1309629baa8cSmrg } else { 1310629baa8cSmrg Debug ("authorization file %s successfully updated\n", name); 1311629baa8cSmrg if (unlink (new_name)) 1312629baa8cSmrg if (errno != ENOENT) 1313629baa8cSmrg LogError ("cannot remove new authorization file %s:" 1314629baa8cSmrg " %s\n", new_name, _SysErrorMsg (errno)); 1315629baa8cSmrg } 1316629baa8cSmrg if (setenv) { 1317629baa8cSmrg verify->userEnviron = setEnv (verify->userEnviron, 1318629baa8cSmrg "XAUTHORITY", envname); 1319629baa8cSmrg verify->systemEnviron = setEnv (verify->systemEnviron, 1320629baa8cSmrg "XAUTHORITY", envname); 1321629baa8cSmrg } 1322629baa8cSmrg XauUnlockAuth (name); 1323629baa8cSmrg if (envname) 1324629baa8cSmrg chown (envname, verify->uid, verify->gid); 1325629baa8cSmrg } 1326629baa8cSmrg Debug ("done SetUserAuthorization\n"); 1327629baa8cSmrg} 1328629baa8cSmrg 1329629baa8cSmrgvoid 1330629baa8cSmrgRemoveUserAuthorization (struct display *d, struct verify_info *verify) 1331629baa8cSmrg{ 1332629baa8cSmrg char *home; 1333629baa8cSmrg Xauth **auths, *entry; 1334629baa8cSmrg char name[1024], new_name[1024]; 1335629baa8cSmrg int lockStatus; 1336629baa8cSmrg FILE *old, *new; 1337629baa8cSmrg struct stat statb; 1338629baa8cSmrg int i; 1339629baa8cSmrg 1340629baa8cSmrg if (!(auths = d->authorizations)) 1341629baa8cSmrg return; 1342629baa8cSmrg home = getEnv (verify->userEnviron, "HOME"); 1343629baa8cSmrg if (!home) 1344629baa8cSmrg return; 1345629baa8cSmrg Debug ("RemoveUserAuthorization\n"); 1346629baa8cSmrg snprintf(name, sizeof(name), "%s/.Xauthority", home); 1347629baa8cSmrg Debug ("XauLockAuth %s\n", name); 1348629baa8cSmrg lockStatus = XauLockAuth (name, 1, 2, 10); 1349629baa8cSmrg Debug ("Lock is %d\n", lockStatus); 1350629baa8cSmrg if (lockStatus != LOCK_SUCCESS) 1351629baa8cSmrg return; 1352629baa8cSmrg old = NULL; 1353629baa8cSmrg if (openFiles (name, new_name, &old, &new)) 1354629baa8cSmrg { 1355629baa8cSmrg initAddrs (); 1356629baa8cSmrg doWrite = 0; 1357629baa8cSmrg for (i = 0; i < d->authNum; i++) 1358629baa8cSmrg { 1359629baa8cSmrg if (d->displayType.location == Local) 1360629baa8cSmrg writeLocalAuth (new, auths[i], d->name); 1361629baa8cSmrg#ifdef XDMCP 1362629baa8cSmrg else 1363629baa8cSmrg writeRemoteAuth (new, auths[i], d->peer, d->peerlen, d->name); 1364629baa8cSmrg#endif 1365629baa8cSmrg } 1366629baa8cSmrg doWrite = 1; 1367629baa8cSmrg if (old) { 1368629baa8cSmrg if (fstat (fileno (old), &statb) != -1) 1369629baa8cSmrg chmod (new_name, (int) (statb.st_mode & 0777)); 1370629baa8cSmrg /*SUPPRESS 560*/ 1371629baa8cSmrg while ((entry = XauReadAuth (old))) { 1372629baa8cSmrg if (!checkEntry (entry)) 1373629baa8cSmrg { 1374629baa8cSmrg Debug ("Writing an entry\n"); 1375629baa8cSmrg writeAuth (new, entry); 1376629baa8cSmrg } 1377629baa8cSmrg XauDisposeAuth (entry); 1378629baa8cSmrg } 1379629baa8cSmrg fclose (old); 1380629baa8cSmrg } 1381629baa8cSmrg doneAddrs (); 1382629baa8cSmrg fclose (new); 1383629baa8cSmrg if (unlink (name) == -1) 1384629baa8cSmrg if (errno != ENOENT) 1385629baa8cSmrg LogError ("cannot remove new authorization file %s: %s\n", 1386629baa8cSmrg name, _SysErrorMsg (errno)); 1387629baa8cSmrg if (link (new_name, name) == -1) { 1388629baa8cSmrg LogError ("cannot link temporary authorization file %s to old " 1389629baa8cSmrg "location %s: %s\n", new_name, name, 1390629baa8cSmrg _SysErrorMsg (errno)); 1391629baa8cSmrg } else { 1392629baa8cSmrg Debug ("authorization file %s successfully updated\n", name); 1393629baa8cSmrg if (unlink (new_name)) 1394629baa8cSmrg if (errno != ENOENT) 1395629baa8cSmrg LogError ("cannot remove new authorization file %s:" 1396629baa8cSmrg " %s\n", new_name, _SysErrorMsg (errno)); 1397629baa8cSmrg } 1398629baa8cSmrg } 1399629baa8cSmrg XauUnlockAuth (name); 1400629baa8cSmrg} 1401