auth.c revision 1d778f8e
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 56629baa8cSmrg 57629baa8cSmrg#ifdef SVR4 58629baa8cSmrg# include <netdb.h> 59629baa8cSmrg# include <sys/sockio.h> 60629baa8cSmrg# include <sys/stropts.h> 61629baa8cSmrg#endif 62629baa8cSmrg#ifdef __GNU__ 63629baa8cSmrg# include <netdb.h> 64629baa8cSmrg# undef SIOCGIFCONF 65629baa8cSmrg#else /* __GNU__ */ 66629baa8cSmrg# include <net/if.h> 67629baa8cSmrg#endif /* __GNU__ */ 68629baa8cSmrg 69629baa8cSmrg#if defined(TCPCONN) && !defined(WIN32) 70629baa8cSmrg# include <netinet/in.h> 71629baa8cSmrg#endif 72629baa8cSmrg 73629baa8cSmrg/* Solaris provides an extended interface SIOCGLIFCONF for IPv6 support. 74629baa8cSmrg */ 75629baa8cSmrg#ifdef SIOCGLIFCONF 76629baa8cSmrg# define USE_SIOCGLIFCONF 77629baa8cSmrg#endif 78629baa8cSmrg 79629baa8cSmrg#ifdef HAVE_SYS_PARAM_H 80b7d26471Smrg# include <sys/param.h> 81629baa8cSmrg# ifdef BSD 82629baa8cSmrg# if (BSD >= 199103) 83629baa8cSmrg# define VARIABLE_IFREQ 84629baa8cSmrg# endif 85629baa8cSmrg# endif 86629baa8cSmrg#endif 87629baa8cSmrg 88629baa8cSmrg 89629baa8cSmrgstruct AuthProtocol { 90629baa8cSmrg unsigned short name_length; 91b7d26471Smrg const char *name; 92629baa8cSmrg void (*InitAuth)(unsigned short len, char *name); 93629baa8cSmrg Xauth *(*GetAuth)(unsigned short len, char *name); 94629baa8cSmrg void (*GetXdmcpAuth)( 95629baa8cSmrg struct protoDisplay *pdpy, 96629baa8cSmrg unsigned short authorizationNameLen, 97629baa8cSmrg char *authorizationName); 98629baa8cSmrg int inited; 99629baa8cSmrg}; 100629baa8cSmrg 101629baa8cSmrgstatic struct AuthProtocol AuthProtocols[] = { 102629baa8cSmrg{ (unsigned short) 18, "MIT-MAGIC-COOKIE-1", 103629baa8cSmrg MitInitAuth, MitGetAuth, NULL 104629baa8cSmrg}, 105629baa8cSmrg#ifdef HASXDMAUTH 106629baa8cSmrg{ (unsigned short) 19, "XDM-AUTHORIZATION-1", 107629baa8cSmrg XdmInitAuth, XdmGetAuth, XdmGetXdmcpAuth, 108629baa8cSmrg}, 109629baa8cSmrg#endif 110629baa8cSmrg#ifdef SECURE_RPC 111629baa8cSmrg{ (unsigned short) 9, "SUN-DES-1", 112629baa8cSmrg SecureRPCInitAuth, SecureRPCGetAuth, NULL, 113629baa8cSmrg}, 114629baa8cSmrg#endif 115629baa8cSmrg#ifdef K5AUTH 116629baa8cSmrg{ (unsigned short) 14, "MIT-KERBEROS-5", 117629baa8cSmrg Krb5InitAuth, Krb5GetAuth, NULL, 118629baa8cSmrg}, 119629baa8cSmrg#endif 120629baa8cSmrg}; 121629baa8cSmrg 122629baa8cSmrg#define NUM_AUTHORIZATION (sizeof (AuthProtocols) / sizeof (AuthProtocols[0])) 123629baa8cSmrg 124629baa8cSmrgstatic struct AuthProtocol * 125629baa8cSmrgfindProtocol (unsigned short name_length, char *name) 126629baa8cSmrg{ 127629baa8cSmrg int i; 128629baa8cSmrg 129629baa8cSmrg for (i = 0; i < NUM_AUTHORIZATION; i++) 130629baa8cSmrg if (AuthProtocols[i].name_length == name_length && 131629baa8cSmrg memcmp(AuthProtocols[i].name, name, name_length) == 0) 132629baa8cSmrg { 133629baa8cSmrg return &AuthProtocols[i]; 134629baa8cSmrg } 135629baa8cSmrg return (struct AuthProtocol *) 0; 136629baa8cSmrg} 137629baa8cSmrg 138629baa8cSmrgint 139629baa8cSmrgValidAuthorization (unsigned short name_length, char *name) 140629baa8cSmrg{ 141629baa8cSmrg if (findProtocol (name_length, name)) 142629baa8cSmrg return TRUE; 143629baa8cSmrg return FALSE; 144629baa8cSmrg} 145629baa8cSmrg 146629baa8cSmrgstatic Xauth * 147629baa8cSmrgGenerateAuthorization (unsigned short name_length, char *name) 148629baa8cSmrg{ 149629baa8cSmrg struct AuthProtocol *a; 150629baa8cSmrg Xauth *auth = NULL; 151629baa8cSmrg int i; 152629baa8cSmrg 153629baa8cSmrg Debug ("GenerateAuthorization %*.*s\n", 154629baa8cSmrg name_length, name_length, name); 155629baa8cSmrg a = findProtocol (name_length, name); 156629baa8cSmrg if (a) 157629baa8cSmrg { 158629baa8cSmrg if (!a->inited) 159629baa8cSmrg { 160629baa8cSmrg (*a->InitAuth) (name_length, name); 161629baa8cSmrg a->inited = TRUE; 162629baa8cSmrg } 163629baa8cSmrg auth = (*a->GetAuth) (name_length, name); 164629baa8cSmrg if (auth) 165629baa8cSmrg { 166629baa8cSmrg Debug ("Got %p (%d %*.*s) ", auth, 167629baa8cSmrg auth->name_length, auth->name_length, 168629baa8cSmrg auth->name_length, auth->name); 169629baa8cSmrg for (i = 0; i < (int)auth->data_length; i++) 170629baa8cSmrg Debug (" %02x", auth->data[i] & 0xff); 171629baa8cSmrg Debug ("\n"); 172629baa8cSmrg } 173629baa8cSmrg else 174629baa8cSmrg Debug ("Got (null)\n"); 175629baa8cSmrg } 176629baa8cSmrg else 177629baa8cSmrg { 178629baa8cSmrg Debug ("Unknown authorization %*.*s\n", name_length, name_length, name); 179629baa8cSmrg } 180629baa8cSmrg return auth; 181629baa8cSmrg} 182629baa8cSmrg 183629baa8cSmrg#ifdef XDMCP 184629baa8cSmrg 185629baa8cSmrgvoid 186629baa8cSmrgSetProtoDisplayAuthorization ( 187629baa8cSmrg struct protoDisplay *pdpy, 188629baa8cSmrg unsigned short authorizationNameLen, 189629baa8cSmrg char *authorizationName) 190629baa8cSmrg{ 191629baa8cSmrg struct AuthProtocol *a; 192629baa8cSmrg Xauth *auth; 193629baa8cSmrg 194629baa8cSmrg a = findProtocol (authorizationNameLen, authorizationName); 195629baa8cSmrg pdpy->xdmcpAuthorization = pdpy->fileAuthorization = NULL; 196629baa8cSmrg if (a) 197629baa8cSmrg { 198629baa8cSmrg if (!a->inited) 199629baa8cSmrg { 200629baa8cSmrg (*a->InitAuth) (authorizationNameLen, authorizationName); 201629baa8cSmrg a->inited = TRUE; 202629baa8cSmrg } 203629baa8cSmrg if (a->GetXdmcpAuth) 204629baa8cSmrg { 205629baa8cSmrg (*a->GetXdmcpAuth) (pdpy, authorizationNameLen, authorizationName); 206629baa8cSmrg auth = pdpy->xdmcpAuthorization; 207629baa8cSmrg } 208629baa8cSmrg else 209629baa8cSmrg { 210629baa8cSmrg auth = (*a->GetAuth) (authorizationNameLen, authorizationName); 211629baa8cSmrg pdpy->fileAuthorization = auth; 212629baa8cSmrg pdpy->xdmcpAuthorization = NULL; 213629baa8cSmrg } 214629baa8cSmrg if (auth) 215629baa8cSmrg Debug ("Got %p (%d %*.*s)\n", auth, 216629baa8cSmrg auth->name_length, auth->name_length, 217629baa8cSmrg auth->name_length, auth->name); 218629baa8cSmrg else 219629baa8cSmrg Debug ("Got (null)\n"); 220629baa8cSmrg } 221629baa8cSmrg} 222629baa8cSmrg 223629baa8cSmrg#endif /* XDMCP */ 224629baa8cSmrg 225629baa8cSmrgvoid 226629baa8cSmrgCleanUpFileName (char *src, char *dst, int len) 227629baa8cSmrg{ 228629baa8cSmrg while (*src) { 229629baa8cSmrg if (--len <= 0) 230629baa8cSmrg break; 231629baa8cSmrg switch (*src & 0x7f) 232629baa8cSmrg { 233629baa8cSmrg case '/': 234629baa8cSmrg *dst++ = '_'; 235629baa8cSmrg break; 236629baa8cSmrg case '-': 237629baa8cSmrg *dst++ = '.'; 238629baa8cSmrg break; 239629baa8cSmrg default: 240629baa8cSmrg *dst++ = (*src & 0x7f); 241629baa8cSmrg } 242629baa8cSmrg ++src; 243629baa8cSmrg } 244629baa8cSmrg *dst = '\0'; 245629baa8cSmrg} 246629baa8cSmrg 247629baa8cSmrg/* Checks to see if specified directory exists, makes it if not 248da2e2ef6Smrg * Returns: 0 if already exists, 1 if created, < 0 if error occurred 249629baa8cSmrg */ 250629baa8cSmrgstatic int 251629baa8cSmrgCheckServerAuthDir (const char *path, struct stat *statb, int mode) 252629baa8cSmrg{ 253629baa8cSmrg int r = stat(path, statb); 254629baa8cSmrg 255629baa8cSmrg if (r != 0) { 256629baa8cSmrg if (errno == ENOENT) { 257629baa8cSmrg r = mkdir(path, mode); 258629baa8cSmrg if (r < 0) { 259629baa8cSmrg LogError ("cannot make authentication directory %s: %s\n", 260629baa8cSmrg path, _SysErrorMsg (errno)); 261629baa8cSmrg } else { 262629baa8cSmrg r = 1; 263629baa8cSmrg } 264629baa8cSmrg } else { 265629baa8cSmrg LogError ("cannot access authentication directory %s: %s\n", 266629baa8cSmrg path, _SysErrorMsg (errno)); 267629baa8cSmrg } 268629baa8cSmrg } else { /* Directory already exists */ 269629baa8cSmrg if (!S_ISDIR(statb->st_mode)) { 270629baa8cSmrg LogError ("cannot make authentication directory %s: %s\n", 271629baa8cSmrg path, "file with that name already exists"); 272629baa8cSmrg return -1; 273629baa8cSmrg } 274629baa8cSmrg } 275629baa8cSmrg 276629baa8cSmrg return r; 277629baa8cSmrg} 278629baa8cSmrg 279629baa8cSmrgstatic char authdir1[] = "authdir"; 280629baa8cSmrgstatic char authdir2[] = "authfiles"; 281629baa8cSmrg 282629baa8cSmrgstatic int 283629baa8cSmrgMakeServerAuthFile (struct display *d, FILE ** file) 284629baa8cSmrg{ 285629baa8cSmrg int len; 286629baa8cSmrg#ifdef MAXNAMELEN 287629baa8cSmrg# define NAMELEN MAXNAMELEN 288629baa8cSmrg#else 289629baa8cSmrg# define NAMELEN 255 290629baa8cSmrg#endif 291629baa8cSmrg char cleanname[NAMELEN]; 292629baa8cSmrg int r; 293629baa8cSmrg#ifdef HAVE_MKSTEMP 294629baa8cSmrg int fd; 295629baa8cSmrg#endif 296629baa8cSmrg struct stat statb; 297629baa8cSmrg 298629baa8cSmrg *file = NULL; 299629baa8cSmrg 300629baa8cSmrg if (!d->authFile) { 301629baa8cSmrg if (d->clientAuthFile && *d->clientAuthFile) { 302629baa8cSmrg d->authFile = strdup(d->clientAuthFile); 303629baa8cSmrg if (!d->authFile) 304629baa8cSmrg return FALSE; 305629baa8cSmrg } else { 306629baa8cSmrg CleanUpFileName (d->name, cleanname, NAMELEN - 8); 307629baa8cSmrg 308629baa8cSmrg /* Make authDir if it doesn't already exist */ 309629baa8cSmrg r = CheckServerAuthDir(authDir, &statb, 0755); 310629baa8cSmrg if (r < 0) { 311629baa8cSmrg return FALSE; 312629baa8cSmrg } 313629baa8cSmrg 314629baa8cSmrg len = strlen (authDir) + strlen (authdir1) + strlen (authdir2) 315629baa8cSmrg + strlen (cleanname) + 14; 316629baa8cSmrg d->authFile = malloc (len); 317629baa8cSmrg if (!d->authFile) 318629baa8cSmrg return FALSE; 319629baa8cSmrg 320629baa8cSmrg snprintf (d->authFile, len, "%s/%s", authDir, authdir1); 321629baa8cSmrg r = CheckServerAuthDir(d->authFile, &statb, 0700); 322629baa8cSmrg if (r == 0) { 323629baa8cSmrg if (statb.st_uid != 0) 324629baa8cSmrg (void) chown(d->authFile, 0, statb.st_gid); 325629baa8cSmrg if ((statb.st_mode & 0077) != 0) 326629baa8cSmrg (void) chmod(d->authFile, statb.st_mode & 0700); 327629baa8cSmrg } else if (r < 0) { 328629baa8cSmrg free (d->authFile); 329629baa8cSmrg d->authFile = NULL; 330629baa8cSmrg return FALSE; 331629baa8cSmrg } 332629baa8cSmrg 333629baa8cSmrg snprintf (d->authFile, len, "%s/%s/%s", 334629baa8cSmrg authDir, authdir1, authdir2); 335629baa8cSmrg r = CheckServerAuthDir(d->authFile, &statb, 0700); 336629baa8cSmrg if (r < 0) { 337629baa8cSmrg free (d->authFile); 338629baa8cSmrg d->authFile = NULL; 339629baa8cSmrg return FALSE; 340629baa8cSmrg } 341629baa8cSmrg snprintf (d->authFile, len, "%s/%s/%s/A%s-XXXXXX", 342629baa8cSmrg authDir, authdir1, authdir2, cleanname); 343629baa8cSmrg#ifdef HAVE_MKSTEMP 344629baa8cSmrg fd = mkstemp (d->authFile); 345629baa8cSmrg if (fd < 0) { 346629baa8cSmrg LogError ("cannot make authentication file %s: %s\n", 347629baa8cSmrg d->authFile, _SysErrorMsg (errno)); 348629baa8cSmrg free (d->authFile); 349629baa8cSmrg d->authFile = NULL; 350629baa8cSmrg return FALSE; 351629baa8cSmrg } 352629baa8cSmrg 353629baa8cSmrg *file = fdopen(fd, "w"); 354629baa8cSmrg if (!*file) 355629baa8cSmrg (void) close (fd); 356629baa8cSmrg return TRUE; 357629baa8cSmrg#else 358629baa8cSmrg (void) mktemp (d->authFile); 359629baa8cSmrg#endif 360629baa8cSmrg } 361629baa8cSmrg } 362629baa8cSmrg 363629baa8cSmrg (void) unlink (d->authFile); 364629baa8cSmrg *file = fopen (d->authFile, "w"); 365629baa8cSmrg return TRUE; 366629baa8cSmrg} 367629baa8cSmrg 368629baa8cSmrgint 369629baa8cSmrgSaveServerAuthorizations ( 370629baa8cSmrg struct display *d, 371629baa8cSmrg Xauth **auths, 372629baa8cSmrg int count) 373629baa8cSmrg{ 374629baa8cSmrg FILE *auth_file; 375629baa8cSmrg mode_t mask; 376629baa8cSmrg int ret; 377629baa8cSmrg int i; 378629baa8cSmrg const char dummy_auth[] = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" 379629baa8cSmrg "XXXXXXXXXXXXXXXXX"; /* 64 "X"s */ 380629baa8cSmrg int err = 0; 381629baa8cSmrg 382629baa8cSmrg mask = umask (0077); 383629baa8cSmrg ret = MakeServerAuthFile(d, &auth_file); 384629baa8cSmrg umask (mask); 385629baa8cSmrg if (!ret) 386629baa8cSmrg return FALSE; 387629baa8cSmrg if (!auth_file) { 388629baa8cSmrg LogError ("cannot open server authorization file %s: %s\n", 389629baa8cSmrg d->authFile, _SysErrorMsg (errno)); 390629baa8cSmrg ret = FALSE; 391629baa8cSmrg } 392629baa8cSmrg else 393629baa8cSmrg { 394629baa8cSmrg Debug ("File: %s auth: %p\n", d->authFile, auths); 395629baa8cSmrg ret = TRUE; 396629baa8cSmrg if (count == 0) 397629baa8cSmrg { 398629baa8cSmrg /* 399629baa8cSmrg * This is a crude hack to determine whether we really can 400629baa8cSmrg * write to the auth file even if we don't have real data 401629baa8cSmrg * to write right now. 402629baa8cSmrg */ 403629baa8cSmrg 404629baa8cSmrg /* 405629baa8cSmrg * Write garbage data to file to provoke ENOSPC and other 406629baa8cSmrg * errors. 407629baa8cSmrg */ 408629baa8cSmrg (void) fprintf (auth_file, "%s", dummy_auth); 409629baa8cSmrg (void) fflush (auth_file); 410629baa8cSmrg if (ferror (auth_file)) 411629baa8cSmrg { 412629baa8cSmrg err = errno; 413629baa8cSmrg ret = FALSE; 414629baa8cSmrg } 415629baa8cSmrg /* 416629baa8cSmrg * Rewind so that the garbage data is overwritten later. 417629baa8cSmrg */ 418629baa8cSmrg rewind(auth_file); 419629baa8cSmrg } 420629baa8cSmrg for (i = 0; i < count; i++) 421629baa8cSmrg { 422629baa8cSmrg /* 423629baa8cSmrg * User-based auths may not have data until 424629baa8cSmrg * a user logs in. In which case don't write 425629baa8cSmrg * to the auth file so xrdb and setup programs don't fail. 426629baa8cSmrg */ 427b7d26471Smrg if (auths[i]->data_length > 0) { 428629baa8cSmrg if (!XauWriteAuth (auth_file, auths[i])) 429629baa8cSmrg { 430629baa8cSmrg Debug ("XauWriteAuth() failed\n"); 431629baa8cSmrg } 432629baa8cSmrg (void) fflush (auth_file); 433629baa8cSmrg if (ferror (auth_file)) 434629baa8cSmrg { 435629baa8cSmrg err = errno; 436629baa8cSmrg ret = FALSE; 437629baa8cSmrg } 438b7d26471Smrg } 439629baa8cSmrg } 440629baa8cSmrg /* 441629baa8cSmrg * XXX: This is not elegant, but stdio has no truncation function. 442629baa8cSmrg */ 443629baa8cSmrg if (ftruncate(fileno(auth_file), ftell(auth_file))) 444629baa8cSmrg { 445629baa8cSmrg Debug ("ftruncate() failed\n"); 446629baa8cSmrg } 447629baa8cSmrg fclose (auth_file); 448629baa8cSmrg 449629baa8cSmrg } 450629baa8cSmrg if (ret == FALSE) 451629baa8cSmrg { 452629baa8cSmrg LogError ("Cannot write to server authorization file %s%s%s\n", 453629baa8cSmrg d->authFile, 454629baa8cSmrg err ? ": " : "", 455629baa8cSmrg err ? _SysErrorMsg (errno) : ""); 456629baa8cSmrg free (d->authFile); 457629baa8cSmrg d->authFile = NULL; 458629baa8cSmrg } 459629baa8cSmrg return ret; 460629baa8cSmrg} 461629baa8cSmrg 462629baa8cSmrgvoid 463629baa8cSmrgSetLocalAuthorization (struct display *d) 464629baa8cSmrg{ 465629baa8cSmrg Xauth *auth, **auths; 466629baa8cSmrg int i, j; 467629baa8cSmrg 468629baa8cSmrg if (d->authorizations) 469629baa8cSmrg { 470629baa8cSmrg for (i = 0; i < d->authNum; i++) 471629baa8cSmrg XauDisposeAuth (d->authorizations[i]); 472629baa8cSmrg free (d->authorizations); 473629baa8cSmrg d->authorizations = (Xauth **) NULL; 474629baa8cSmrg d->authNum = 0; 475629baa8cSmrg } 476629baa8cSmrg if (!d->authNames) 477629baa8cSmrg return; 478629baa8cSmrg for (i = 0; d->authNames[i]; i++) 479629baa8cSmrg ; 480629baa8cSmrg d->authNameNum = i; 481629baa8cSmrg free (d->authNameLens); 482629baa8cSmrg d->authNameLens = malloc (d->authNameNum * sizeof (unsigned short)); 483629baa8cSmrg if (!d->authNameLens) 484629baa8cSmrg return; 485629baa8cSmrg for (i = 0; i < d->authNameNum; i++) 486629baa8cSmrg d->authNameLens[i] = strlen (d->authNames[i]); 487629baa8cSmrg auths = malloc (d->authNameNum * sizeof (Xauth *)); 488629baa8cSmrg if (!auths) 489629baa8cSmrg return; 490629baa8cSmrg j = 0; 491629baa8cSmrg for (i = 0; i < d->authNameNum; i++) 492629baa8cSmrg { 493629baa8cSmrg auth = GenerateAuthorization (d->authNameLens[i], d->authNames[i]); 494629baa8cSmrg if (auth) 495629baa8cSmrg auths[j++] = auth; 496629baa8cSmrg } 497629baa8cSmrg if (SaveServerAuthorizations (d, auths, j)) 498629baa8cSmrg { 499629baa8cSmrg d->authorizations = auths; 500629baa8cSmrg d->authNum = j; 501629baa8cSmrg } 502629baa8cSmrg else 503629baa8cSmrg { 504629baa8cSmrg for (i = 0; i < j; i++) 505629baa8cSmrg XauDisposeAuth (auths[i]); 506629baa8cSmrg free (auths); 507629baa8cSmrg } 508629baa8cSmrg} 509629baa8cSmrg 510629baa8cSmrg/* 511629baa8cSmrg * Set the authorization to use for xdm's initial connection 512629baa8cSmrg * to the X server. Cannot use user-based authorizations 513629baa8cSmrg * because no one has logged in yet, so we don't have any 514629baa8cSmrg * user credentials. 515629baa8cSmrg * Well, actually we could use SUN-DES-1 because we tell the server 516629baa8cSmrg * to allow root in. This is bogus and should be fixed. 517629baa8cSmrg */ 518629baa8cSmrgvoid 519629baa8cSmrgSetAuthorization (struct display *d) 520629baa8cSmrg{ 521629baa8cSmrg register Xauth **auth = d->authorizations; 522629baa8cSmrg int i; 523629baa8cSmrg 524629baa8cSmrg for (i = 0; i < d->authNum; i++) 525629baa8cSmrg { 526629baa8cSmrg if (auth[i]->name_length == 9 && 527629baa8cSmrg memcmp(auth[i]->name, "SUN-DES-1", 9) == 0) 528629baa8cSmrg continue; 529629baa8cSmrg if (auth[i]->name_length == 14 && 530629baa8cSmrg memcmp(auth[i]->name, "MIT-KERBEROS-5", 14) == 0) 531629baa8cSmrg continue; 532629baa8cSmrg XSetAuthorization (auth[i]->name, (int) auth[i]->name_length, 533629baa8cSmrg auth[i]->data, (int) auth[i]->data_length); 534629baa8cSmrg } 535629baa8cSmrg} 536629baa8cSmrg 537629baa8cSmrgstatic int 538629baa8cSmrgopenFiles (char *name, char *new_name, FILE **oldp, FILE **newp) 539629baa8cSmrg{ 540629baa8cSmrg mode_t mask; 541629baa8cSmrg int newfd; 542629baa8cSmrg 543629baa8cSmrg strcpy (new_name, name); 544629baa8cSmrg strcat (new_name, "-n"); 545629baa8cSmrg /* 546629baa8cSmrg * Set safe umask for file creation operations. 547629baa8cSmrg */ 548629baa8cSmrg mask = umask (0077); 549629baa8cSmrg /* 550629baa8cSmrg * Unlink the authorization file we intend to create, and then open 551629baa8cSmrg * it with O_CREAT | O_EXCL to avoid race-based symlink attacks. 552629baa8cSmrg */ 553629baa8cSmrg (void) unlink (new_name); 554629baa8cSmrg newfd = open (new_name, O_WRONLY | O_CREAT | O_EXCL, 0600); 555b7d26471Smrg if (newfd >= 0) { 556629baa8cSmrg *newp = fdopen (newfd, "w"); 557b7d26471Smrg if (*newp == NULL) 558b7d26471Smrg close(newfd); 559b7d26471Smrg } 560629baa8cSmrg else 561629baa8cSmrg { 562629baa8cSmrg LogError ("Cannot create file %s: %s\n", new_name, 563629baa8cSmrg _SysErrorMsg (errno)); 564629baa8cSmrg *newp = NULL; 565629baa8cSmrg } 566629baa8cSmrg /* 567629baa8cSmrg * There are no more attempts to create files after this point; 568629baa8cSmrg * restore the original umask. 569629baa8cSmrg */ 570629baa8cSmrg (void) umask (mask); 571629baa8cSmrg if (!*newp) { 572629baa8cSmrg Debug ("can't open new file %s\n", new_name); 573629baa8cSmrg return 0; 574629baa8cSmrg } 575629baa8cSmrg if (!*oldp) 576629baa8cSmrg *oldp = fopen (name, "r"); 577629baa8cSmrg Debug ("opens succeeded %s %s\n", name, new_name); 578629baa8cSmrg return 1; 579629baa8cSmrg} 580629baa8cSmrg 581629baa8cSmrgstatic int 582629baa8cSmrgbinaryEqual (char *a, char *b, unsigned short len) 583629baa8cSmrg{ 584629baa8cSmrg while (len-- > 0) 585629baa8cSmrg if (*a++ != *b++) 586629baa8cSmrg return FALSE; 587629baa8cSmrg return TRUE; 588629baa8cSmrg} 589629baa8cSmrg 590629baa8cSmrgstatic void 591629baa8cSmrgdumpBytes (unsigned short len, char *data) 592629baa8cSmrg{ 593629baa8cSmrg unsigned short i; 594629baa8cSmrg 595629baa8cSmrg Debug ("%d: ", len); 596629baa8cSmrg for (i = 0; i < len; i++) 597629baa8cSmrg Debug ("%02x ", data[i] & 0377); 598629baa8cSmrg Debug ("\n"); 599629baa8cSmrg} 600629baa8cSmrg 601629baa8cSmrgstatic void 602629baa8cSmrgdumpAuth (Xauth *auth) 603629baa8cSmrg{ 604629baa8cSmrg Debug ("family: %d\n", auth->family); 605629baa8cSmrg Debug ("addr: "); 606629baa8cSmrg dumpBytes (auth->address_length, auth->address); 607629baa8cSmrg Debug ("number: "); 608629baa8cSmrg dumpBytes (auth->number_length, auth->number); 609629baa8cSmrg Debug ("name: "); 610629baa8cSmrg dumpBytes (auth->name_length, auth->name); 611629baa8cSmrg Debug ("data: "); 612629baa8cSmrg dumpBytes (auth->data_length, auth->data); 613629baa8cSmrg} 614629baa8cSmrg 615629baa8cSmrgstruct addrList { 616629baa8cSmrg unsigned short family; 617629baa8cSmrg unsigned short address_length; 618629baa8cSmrg char *address; 619629baa8cSmrg unsigned short number_length; 620629baa8cSmrg char *number; 621629baa8cSmrg unsigned short name_length; 622629baa8cSmrg char *name; 623629baa8cSmrg struct addrList *next; 624629baa8cSmrg}; 625629baa8cSmrg 626629baa8cSmrgstatic struct addrList *addrs; 627629baa8cSmrg 628629baa8cSmrgstatic void 629629baa8cSmrginitAddrs (void) 630629baa8cSmrg{ 631629baa8cSmrg addrs = NULL; 632629baa8cSmrg} 633629baa8cSmrg 634629baa8cSmrgstatic void 635629baa8cSmrgdoneAddrs (void) 636629baa8cSmrg{ 637629baa8cSmrg struct addrList *a, *n; 638629baa8cSmrg for (a = addrs; a; a = n) { 639629baa8cSmrg n = a->next; 640629baa8cSmrg free (a->address); 641629baa8cSmrg free (a->number); 642629baa8cSmrg free (a); 643629baa8cSmrg } 644da2e2ef6Smrg addrs = NULL; 645629baa8cSmrg} 646629baa8cSmrg 647629baa8cSmrgstatic int checkEntry (Xauth *auth); 648629baa8cSmrg 649629baa8cSmrgstatic void 650629baa8cSmrgsaveEntry (Xauth *auth) 651629baa8cSmrg{ 652629baa8cSmrg struct addrList *new; 653629baa8cSmrg 654629baa8cSmrg new = malloc (sizeof (struct addrList)); 655629baa8cSmrg if (!new) { 656629baa8cSmrg LogOutOfMem ("saveEntry"); 657629baa8cSmrg return; 658629baa8cSmrg } 659629baa8cSmrg if ((new->address_length = auth->address_length) > 0) { 660629baa8cSmrg new->address = malloc (auth->address_length); 661629baa8cSmrg if (!new->address) { 662629baa8cSmrg LogOutOfMem ("saveEntry"); 663629baa8cSmrg free (new); 664629baa8cSmrg return; 665629baa8cSmrg } 666f9f7a7f2Smrg memcpy(new->address, auth->address, (int) auth->address_length); 667629baa8cSmrg } else 668629baa8cSmrg new->address = NULL; 669629baa8cSmrg if ((new->number_length = auth->number_length) > 0) { 670629baa8cSmrg new->number = malloc (auth->number_length); 671629baa8cSmrg if (!new->number) { 672629baa8cSmrg LogOutOfMem ("saveEntry"); 673629baa8cSmrg free (new->address); 674629baa8cSmrg free (new); 675629baa8cSmrg return; 676629baa8cSmrg } 677f9f7a7f2Smrg memcpy(new->number, auth->number, (int) auth->number_length); 678629baa8cSmrg } else 679629baa8cSmrg new->number = NULL; 680629baa8cSmrg if ((new->name_length = auth->name_length) > 0) { 681629baa8cSmrg new->name = malloc (auth->name_length); 682629baa8cSmrg if (!new->name) { 683629baa8cSmrg LogOutOfMem ("saveEntry"); 684629baa8cSmrg free (new->number); 685629baa8cSmrg free (new->address); 686629baa8cSmrg free (new); 687629baa8cSmrg return; 688629baa8cSmrg } 689f9f7a7f2Smrg memcpy(new->name, auth->name, (int) auth->name_length); 690629baa8cSmrg } else 691629baa8cSmrg new->name = NULL; 692629baa8cSmrg new->family = auth->family; 693629baa8cSmrg new->next = addrs; 694629baa8cSmrg addrs = new; 695629baa8cSmrg} 696629baa8cSmrg 697629baa8cSmrgstatic int 698629baa8cSmrgcheckEntry (Xauth *auth) 699629baa8cSmrg{ 700629baa8cSmrg struct addrList *a; 701629baa8cSmrg 702629baa8cSmrg for (a = addrs; a; a = a->next) { 703629baa8cSmrg if (a->family == auth->family && 704629baa8cSmrg a->address_length == auth->address_length && 705629baa8cSmrg binaryEqual (a->address, auth->address, auth->address_length) && 706629baa8cSmrg a->number_length == auth->number_length && 707629baa8cSmrg binaryEqual (a->number, auth->number, auth->number_length) && 708629baa8cSmrg a->name_length == auth->name_length && 709629baa8cSmrg binaryEqual (a->name, auth->name, auth->name_length)) 710629baa8cSmrg { 711629baa8cSmrg return 1; 712629baa8cSmrg } 713629baa8cSmrg } 714629baa8cSmrg return 0; 715629baa8cSmrg} 716629baa8cSmrg 717629baa8cSmrgstatic int doWrite; 718629baa8cSmrg 719629baa8cSmrgstatic void 720629baa8cSmrgwriteAuth (FILE *file, Xauth *auth) 721629baa8cSmrg{ 722629baa8cSmrg if (debugLevel >= 15) { /* normally too verbose */ 723629baa8cSmrg Debug ("writeAuth: doWrite = %d\n", doWrite); 724629baa8cSmrg dumpAuth (auth); /* does Debug only */ 725629baa8cSmrg } 726629baa8cSmrg if (doWrite) 727629baa8cSmrg XauWriteAuth (file, auth); 728629baa8cSmrg} 729629baa8cSmrg 730629baa8cSmrgstatic void 731629baa8cSmrgwriteAddr ( 732629baa8cSmrg int family, 733629baa8cSmrg int addr_length, 734629baa8cSmrg char *addr, 735629baa8cSmrg FILE *file, 736629baa8cSmrg Xauth *auth) 737629baa8cSmrg{ 738629baa8cSmrg auth->family = (unsigned short) family; 739629baa8cSmrg auth->address_length = addr_length; 740629baa8cSmrg auth->address = addr; 741629baa8cSmrg Debug ("writeAddr: writing and saving an entry\n"); 742629baa8cSmrg writeAuth (file, auth); 743629baa8cSmrg saveEntry (auth); 744629baa8cSmrg} 745629baa8cSmrg 746629baa8cSmrgstatic void 747629baa8cSmrgDefineLocal (FILE *file, Xauth *auth) 748629baa8cSmrg{ 749629baa8cSmrg char displayname[100]; 750629baa8cSmrg int len = _XGetHostname (displayname, sizeof(displayname)); 751629baa8cSmrg 752629baa8cSmrg/* Make sure this produces the same string as _XGetHostname in lib/X/XlibInt.c. 753629baa8cSmrg * Otherwise, Xau will not be able to find your cookies in the Xauthority file. 754629baa8cSmrg * 755629baa8cSmrg * Note: POSIX says that the ``nodename'' member of utsname does _not_ have 756629baa8cSmrg * to have sufficient information for interfacing to the network, 757629baa8cSmrg * and so, you may be better off using gethostname (if it exists). 758629baa8cSmrg */ 759629baa8cSmrg 760629baa8cSmrg 761629baa8cSmrg writeAddr (FamilyLocal, len, displayname, file, auth); 762629baa8cSmrg} 763629baa8cSmrg 764629baa8cSmrg#ifdef HAVE_GETIFADDRS 765629baa8cSmrg# include <ifaddrs.h> 766629baa8cSmrg 767629baa8cSmrgstatic void 768629baa8cSmrgDefineSelf(int fd, FILE *file, Xauth *auth) 769629baa8cSmrg{ 770629baa8cSmrg struct ifaddrs *ifap, *ifr; 771629baa8cSmrg char *addr; 772629baa8cSmrg int family, len; 773629baa8cSmrg 774629baa8cSmrg Debug("DefineSelf\n"); 775629baa8cSmrg if (getifaddrs(&ifap) < 0) 776629baa8cSmrg return; 777629baa8cSmrg for (ifr = ifap; ifr != NULL; ifr = ifr->ifa_next) { 778629baa8cSmrg len = sizeof(*(ifr->ifa_addr)); 779629baa8cSmrg family = ConvertAddr((XdmcpNetaddr)(ifr->ifa_addr), &len, &addr); 780629baa8cSmrg if (family == -1 || family == FamilyLocal) 781629baa8cSmrg continue; 782629baa8cSmrg /* 783629baa8cSmrg * don't write out 'localhost' entries, as 784629baa8cSmrg * they may conflict with other local entries. 785629baa8cSmrg * DefineLocal will always be called to add 786629baa8cSmrg * the local entry anyway, so this one can 787629baa8cSmrg * be tossed. 788629baa8cSmrg */ 789629baa8cSmrg if (family == FamilyInternet && len == 4 && addr[0] == 127) 790629baa8cSmrg { 791629baa8cSmrg Debug ("Skipping localhost address\n"); 792629baa8cSmrg continue; 793629baa8cSmrg } 7941d778f8eSmrg# ifdef IPv6 795629baa8cSmrg if(family == FamilyInternet6) { 796629baa8cSmrg if (IN6_IS_ADDR_LOOPBACK(((struct in6_addr *)addr))) { 797629baa8cSmrg Debug ("Skipping IPv6 localhost address\n"); 798629baa8cSmrg continue; 799629baa8cSmrg } 800629baa8cSmrg /* Also skip XDM-AUTHORIZATION-1 */ 801629baa8cSmrg if (auth->name_length == 19 && 802629baa8cSmrg strcmp(auth->name, "XDM-AUTHORIZATION-1") == 0) { 803629baa8cSmrg Debug ("Skipping IPv6 XDM-AUTHORIZATION-1\n"); 804629baa8cSmrg continue; 805629baa8cSmrg } 806629baa8cSmrg } 807629baa8cSmrg# endif 808629baa8cSmrg writeAddr(family, len, addr, file, auth); 809629baa8cSmrg } 810629baa8cSmrg freeifaddrs(ifap); 811629baa8cSmrg Debug("DefineSelf done\n"); 812629baa8cSmrg} 813629baa8cSmrg#else /* GETIFADDRS */ 814629baa8cSmrg 815b7d26471Smrg# if defined(SIOCGIFCONF) || defined (USE_SIOCGLIFCONF) 816629baa8cSmrg 817b7d26471Smrg# ifdef USE_SIOCGLIFCONF 818b7d26471Smrg# define ifr_type struct lifreq 819b7d26471Smrg# else 820b7d26471Smrg# define ifr_type struct ifreq 821b7d26471Smrg# endif 822629baa8cSmrg 823629baa8cSmrg/* Handle variable length ifreq in BNR2 and later */ 824b7d26471Smrg# ifdef VARIABLE_IFREQ 825b7d26471Smrg# define ifr_size(p) (sizeof (struct ifreq) + \ 826629baa8cSmrg (p->ifr_addr.sa_len > sizeof (p->ifr_addr) ? \ 827629baa8cSmrg p->ifr_addr.sa_len - sizeof (p->ifr_addr) : 0)) 828b7d26471Smrg# else 829b7d26471Smrg# define ifr_size(p) (sizeof (ifr_type)) 830b7d26471Smrg# endif 831629baa8cSmrg 832629baa8cSmrg/* Define this host for access control. Find all the hosts the OS knows about 833629baa8cSmrg * for this fd and add them to the selfhosts list. 834629baa8cSmrg */ 835629baa8cSmrgstatic void 836629baa8cSmrgDefineSelf (int fd, FILE *file, Xauth *auth) 837629baa8cSmrg{ 838629baa8cSmrg char buf[2048], *cp, *cplim; 839629baa8cSmrg int len; 840629baa8cSmrg char *addr; 841629baa8cSmrg int family; 842629baa8cSmrg register ifr_type *ifr; 843b7d26471Smrg# ifdef USE_SIOCGLIFCONF 844629baa8cSmrg void * bufptr = buf; 845629baa8cSmrg size_t buflen = sizeof(buf); 846629baa8cSmrg struct lifconf ifc; 847b7d26471Smrg# ifdef SIOCGLIFNUM 848629baa8cSmrg struct lifnum ifn; 849b7d26471Smrg# endif 850b7d26471Smrg# else 851629baa8cSmrg struct ifconf ifc; 852b7d26471Smrg# endif 853629baa8cSmrg 854b7d26471Smrg# if defined(SIOCGLIFNUM) && defined(SIOCGLIFCONF) 855629baa8cSmrg ifn.lifn_family = AF_UNSPEC; 856629baa8cSmrg ifn.lifn_flags = 0; 857629baa8cSmrg if (ioctl (fd, (int) SIOCGLIFNUM, (char *) &ifn) < 0) 858629baa8cSmrg LogError ("Failed getting interface count"); 859629baa8cSmrg if (buflen < (ifn.lifn_count * sizeof(struct lifreq))) { 860629baa8cSmrg buflen = ifn.lifn_count * sizeof(struct lifreq); 861629baa8cSmrg bufptr = malloc(buflen); 862629baa8cSmrg } 863b7d26471Smrg# endif 864629baa8cSmrg 865b7d26471Smrg# ifdef USE_SIOCGLIFCONF 866629baa8cSmrg ifc.lifc_family = AF_UNSPEC; 867629baa8cSmrg ifc.lifc_flags = 0; 868629baa8cSmrg ifc.lifc_len = buflen; 869629baa8cSmrg ifc.lifc_buf = bufptr; 870629baa8cSmrg 871b7d26471Smrg# define IFC_IOCTL_REQ SIOCGLIFCONF 872b7d26471Smrg# define IFC_IFC_REQ ifc.lifc_req 873b7d26471Smrg# define IFC_IFC_LEN ifc.lifc_len 874b7d26471Smrg# define IFR_IFR_ADDR ifr->lifr_addr 875b7d26471Smrg# define IFR_IFR_NAME ifr->lifr_name 876629baa8cSmrg 877b7d26471Smrg# else 878629baa8cSmrg ifc.ifc_len = sizeof (buf); 879629baa8cSmrg ifc.ifc_buf = buf; 880629baa8cSmrg 881b7d26471Smrg# define IFC_IOCTL_REQ SIOCGIFCONF 882b7d26471Smrg# define IFC_IFC_REQ ifc.ifc_req 883b7d26471Smrg# define IFC_IFC_LEN ifc.ifc_len 884b7d26471Smrg# define IFR_IFR_ADDR ifr->ifr_addr 885b7d26471Smrg# define IFR_IFR_NAME ifr->ifr_name 886b7d26471Smrg# endif 887629baa8cSmrg 8884901b09eSmrg if (ioctl (fd, IFC_IOCTL_REQ, (char *) &ifc) < 0) { 889629baa8cSmrg LogError ("Trouble getting network interface configuration"); 890629baa8cSmrg 891b7d26471Smrg# ifdef USE_SIOCGLIFCONF 892629baa8cSmrg if (bufptr != buf) { 893629baa8cSmrg free(bufptr); 894629baa8cSmrg } 895b7d26471Smrg# endif 896629baa8cSmrg return; 897629baa8cSmrg } 898629baa8cSmrg 899629baa8cSmrg cplim = (char *) IFC_IFC_REQ + IFC_IFC_LEN; 900629baa8cSmrg 901629baa8cSmrg for (cp = (char *) IFC_IFC_REQ; cp < cplim; cp += ifr_size (ifr)) 902629baa8cSmrg { 903629baa8cSmrg ifr = (ifr_type *) cp; 904b7d26471Smrg family = ConvertAddr ((XdmcpNetaddr) &IFR_IFR_ADDR, &len, &addr); 905b7d26471Smrg if (family < 0) 906b7d26471Smrg continue; 907b7d26471Smrg 908b7d26471Smrg if (len == 0) 909b7d26471Smrg { 910b7d26471Smrg Debug ("Skipping zero length address\n"); 911b7d26471Smrg continue; 912b7d26471Smrg } 913629baa8cSmrg /* 914b7d26471Smrg * don't write out 'localhost' entries, as 915b7d26471Smrg * they may conflict with other local entries. 916b7d26471Smrg * DefineLocal will always be called to add 917b7d26471Smrg * the local entry anyway, so this one can 918b7d26471Smrg * be tossed. 919629baa8cSmrg */ 920b7d26471Smrg if (family == FamilyInternet && len == 4 && 921b7d26471Smrg addr[0] == 127 && addr[1] == 0 && 922b7d26471Smrg addr[2] == 0 && addr[3] == 1) 923629baa8cSmrg { 924b7d26471Smrg Debug ("Skipping localhost address\n"); 925b7d26471Smrg continue; 926b7d26471Smrg } 9271d778f8eSmrg# ifdef IPv6 928b7d26471Smrg if (family == FamilyInternet6) { 929b7d26471Smrg if (IN6_IS_ADDR_LOOPBACK(((struct in6_addr *)addr))) { 930b7d26471Smrg Debug ("Skipping IPv6 localhost address\n"); 931629baa8cSmrg continue; 932629baa8cSmrg } 933b7d26471Smrg /* Also skip XDM-AUTHORIZATION-1 */ 934b7d26471Smrg if (auth->name_length == 19 && 935b7d26471Smrg strcmp(auth->name, "XDM-AUTHORIZATION-1") == 0) { 936b7d26471Smrg Debug ("Skipping IPv6 XDM-AUTHORIZATION-1\n"); 937b7d26471Smrg continue; 938629baa8cSmrg } 939629baa8cSmrg } 940b7d26471Smrg# endif 941629baa8cSmrg Debug ("DefineSelf: write network address, length %d\n", len); 942629baa8cSmrg writeAddr (family, len, addr, file, auth); 943629baa8cSmrg } 944629baa8cSmrg} 945629baa8cSmrg 946b7d26471Smrg# else /* SIOCGIFCONF */ 947629baa8cSmrg 948629baa8cSmrg/* Define this host for access control. Find all the hosts the OS knows about 949629baa8cSmrg * for this fd and add them to the selfhosts list. 950629baa8cSmrg */ 951629baa8cSmrgstatic void 952629baa8cSmrgDefineSelf (int fd, int file, int auth) 953629baa8cSmrg{ 954629baa8cSmrg register int n; 955629baa8cSmrg int len; 956629baa8cSmrg caddr_t addr; 957629baa8cSmrg int family; 958629baa8cSmrg 959629baa8cSmrg struct utsname name; 960629baa8cSmrg register struct hostent *hp; 961629baa8cSmrg 962629baa8cSmrg union { 963629baa8cSmrg struct sockaddr sa; 964629baa8cSmrg struct sockaddr_in in; 965629baa8cSmrg } saddr; 966629baa8cSmrg 967629baa8cSmrg struct sockaddr_in *inetaddr; 968629baa8cSmrg 969629baa8cSmrg /* hpux: 970629baa8cSmrg * Why not use gethostname()? Well, at least on my system, I've had to 971629baa8cSmrg * make an ugly kernel patch to get a name longer than 8 characters, and 972629baa8cSmrg * uname() lets me access to the whole string (it smashes release, you 973629baa8cSmrg * see), whereas gethostname() kindly truncates it for me. 974629baa8cSmrg */ 975629baa8cSmrg uname(&name); 976629baa8cSmrg hp = gethostbyname (name.nodename); 977629baa8cSmrg if (hp != NULL) { 978629baa8cSmrg saddr.sa.sa_family = hp->h_addrtype; 979629baa8cSmrg inetaddr = (struct sockaddr_in *) (&(saddr.sa)); 980f9f7a7f2Smrg memcpy(&(inetaddr->sin_addr), hp->h_addr, hp->h_length); 981629baa8cSmrg family = ConvertAddr ( &(saddr.sa), &len, &addr); 982629baa8cSmrg if ( family >= 0) { 983629baa8cSmrg writeAddr (FamilyInternet, sizeof (inetaddr->sin_addr), 984629baa8cSmrg (char *) (&inetaddr->sin_addr), file, auth); 985629baa8cSmrg } 986629baa8cSmrg } 987629baa8cSmrg} 988629baa8cSmrg 989629baa8cSmrg 990b7d26471Smrg# endif /* SIOCGIFCONF else */ 991629baa8cSmrg#endif /* HAVE_GETIFADDRS */ 992629baa8cSmrg 993629baa8cSmrgstatic void 994629baa8cSmrgsetAuthNumber (Xauth *auth, char *name) 995629baa8cSmrg{ 996629baa8cSmrg char *colon; 997629baa8cSmrg char *dot, *number; 998629baa8cSmrg 999629baa8cSmrg Debug ("setAuthNumber %s\n", name); 1000629baa8cSmrg colon = strrchr(name, ':'); 1001629baa8cSmrg if (colon) { 1002629baa8cSmrg ++colon; 1003629baa8cSmrg dot = strchr(colon, '.'); 1004629baa8cSmrg if (dot) 1005629baa8cSmrg auth->number_length = dot - colon; 1006629baa8cSmrg else 1007629baa8cSmrg auth->number_length = strlen (colon); 1008629baa8cSmrg number = malloc (auth->number_length + 1); 1009629baa8cSmrg if (number) { 1010629baa8cSmrg strncpy (number, colon, auth->number_length); 1011629baa8cSmrg number[auth->number_length] = '\0'; 1012629baa8cSmrg } else { 1013629baa8cSmrg LogOutOfMem ("setAuthNumber"); 1014629baa8cSmrg auth->number_length = 0; 1015629baa8cSmrg } 1016629baa8cSmrg auth->number = number; 1017629baa8cSmrg Debug ("setAuthNumber: %s\n", number); 1018629baa8cSmrg } 1019629baa8cSmrg} 1020629baa8cSmrg 1021629baa8cSmrgstatic void 1022629baa8cSmrgwriteLocalAuth (FILE *file, Xauth *auth, char *name) 1023629baa8cSmrg{ 1024629baa8cSmrg int fd; 1025629baa8cSmrg 1026629baa8cSmrg Debug ("writeLocalAuth: %s %.*s\n", name, auth->name_length, auth->name); 1027629baa8cSmrg setAuthNumber (auth, name); 1028629baa8cSmrg#ifdef TCPCONN 10291d778f8eSmrg# ifdef IPv6 1030629baa8cSmrg fd = socket (AF_INET6, SOCK_STREAM, 0); 1031629baa8cSmrg if (fd < 0) 1032629baa8cSmrg# endif 1033629baa8cSmrg fd = socket (AF_INET, SOCK_STREAM, 0); 1034629baa8cSmrg DefineSelf (fd, file, auth); 1035629baa8cSmrg close (fd); 1036629baa8cSmrg#endif 1037629baa8cSmrg DefineLocal (file, auth); 1038629baa8cSmrg} 1039629baa8cSmrg 1040629baa8cSmrg#ifdef XDMCP 1041629baa8cSmrg 1042629baa8cSmrgstatic void 1043629baa8cSmrgwriteRemoteAuth (FILE *file, Xauth *auth, XdmcpNetaddr peer, int peerlen, char *name) 1044629baa8cSmrg{ 1045629baa8cSmrg int family = FamilyLocal; 1046629baa8cSmrg char *addr; 1047629baa8cSmrg 1048629baa8cSmrg Debug ("writeRemoteAuth: %s %.*s\n", name, auth->name_length, auth->name); 1049629baa8cSmrg if (!peer || peerlen < 2) 1050629baa8cSmrg return; 1051629baa8cSmrg setAuthNumber (auth, name); 1052629baa8cSmrg family = ConvertAddr (peer, &peerlen, &addr); 1053629baa8cSmrg Debug ("writeRemoteAuth: family %d\n", family); 1054629baa8cSmrg if (family != FamilyLocal) 1055629baa8cSmrg { 1056629baa8cSmrg Debug ("writeRemoteAuth: %d, %d, %x\n", 1057629baa8cSmrg family, peerlen, *(int *)addr); 1058629baa8cSmrg writeAddr (family, peerlen, addr, file, auth); 1059629baa8cSmrg } 1060629baa8cSmrg else 1061629baa8cSmrg { 1062629baa8cSmrg writeLocalAuth (file, auth, name); 1063629baa8cSmrg } 1064629baa8cSmrg} 1065629baa8cSmrg 1066629baa8cSmrg#endif /* XDMCP */ 1067629baa8cSmrg 1068629baa8cSmrgvoid 1069629baa8cSmrgSetUserAuthorization (struct display *d, struct verify_info *verify) 1070629baa8cSmrg{ 1071629baa8cSmrg FILE *old = NULL, *new; 1072629baa8cSmrg char home_name[1024], backup_name[1024], new_name[1024]; 1073629baa8cSmrg char *name = NULL; 1074629baa8cSmrg char *home; 1075629baa8cSmrg char *envname = NULL; 1076629baa8cSmrg int lockStatus; 1077629baa8cSmrg Xauth *entry, **auths; 1078629baa8cSmrg int setenv = 0; 1079629baa8cSmrg struct stat statb; 1080629baa8cSmrg int i; 1081629baa8cSmrg int magicCookie; 1082629baa8cSmrg int data_len; 1083629baa8cSmrg#ifdef HAVE_MKSTEMP 1084629baa8cSmrg int fd; 1085629baa8cSmrg#endif 1086629baa8cSmrg 1087629baa8cSmrg Debug ("SetUserAuthorization\n"); 1088629baa8cSmrg auths = d->authorizations; 1089629baa8cSmrg if (auths) { 1090629baa8cSmrg home = getEnv (verify->userEnviron, "HOME"); 1091629baa8cSmrg lockStatus = LOCK_ERROR; 1092629baa8cSmrg if (home) { 1093629baa8cSmrg snprintf (home_name, sizeof(home_name), "%s/.Xauthority", home); 1094629baa8cSmrg Debug ("XauLockAuth %s\n", home_name); 1095629baa8cSmrg lockStatus = XauLockAuth (home_name, 1, 2, 10); 1096629baa8cSmrg Debug ("Lock is %d\n", lockStatus); 1097629baa8cSmrg if (lockStatus == LOCK_SUCCESS) { 1098629baa8cSmrg if (openFiles (home_name, new_name, &old, &new) 1099629baa8cSmrg && (old != NULL) && (new != NULL)) { 1100629baa8cSmrg name = home_name; 1101629baa8cSmrg setenv = 0; 1102629baa8cSmrg } else { 1103629baa8cSmrg Debug ("openFiles failed\n"); 1104629baa8cSmrg XauUnlockAuth (home_name); 1105629baa8cSmrg lockStatus = LOCK_ERROR; 1106629baa8cSmrg if (old != NULL) { 1107629baa8cSmrg (void) fclose (old); 1108629baa8cSmrg old = NULL; 1109629baa8cSmrg } 1110629baa8cSmrg if (new != NULL) 1111629baa8cSmrg (void) fclose (new); 1112629baa8cSmrg } 1113629baa8cSmrg } 1114629baa8cSmrg } 1115629baa8cSmrg if (lockStatus != LOCK_SUCCESS) { 1116629baa8cSmrg snprintf (backup_name, sizeof(backup_name), 1117629baa8cSmrg "%s/.XauthXXXXXX", d->userAuthDir); 1118629baa8cSmrg#ifdef HAVE_MKSTEMP 1119629baa8cSmrg fd = mkstemp (backup_name); 1120629baa8cSmrg if (fd >= 0) { 1121629baa8cSmrg old = fdopen (fd, "r"); 1122629baa8cSmrg if (old == NULL) 1123629baa8cSmrg (void) close(fd); 1124629baa8cSmrg } 1125629baa8cSmrg 1126629baa8cSmrg if (old != NULL) 1127629baa8cSmrg#else 1128629baa8cSmrg (void) mktemp (backup_name); 1129629baa8cSmrg#endif 1130629baa8cSmrg { 1131629baa8cSmrg lockStatus = XauLockAuth (backup_name, 1, 2, 10); 1132629baa8cSmrg Debug ("backup lock is %d\n", lockStatus); 1133629baa8cSmrg if (lockStatus == LOCK_SUCCESS) { 1134629baa8cSmrg if (openFiles (backup_name, new_name, &old, &new) 1135629baa8cSmrg && (old != NULL) && (new != NULL)) { 1136629baa8cSmrg name = backup_name; 1137629baa8cSmrg setenv = 1; 1138629baa8cSmrg } else { 1139629baa8cSmrg XauUnlockAuth (backup_name); 1140629baa8cSmrg lockStatus = LOCK_ERROR; 1141629baa8cSmrg if (old != NULL) { 1142629baa8cSmrg (void) fclose (old); 1143629baa8cSmrg old = NULL; 1144629baa8cSmrg } 1145629baa8cSmrg if (new != NULL) 1146629baa8cSmrg (void) fclose (new); 1147629baa8cSmrg } 1148629baa8cSmrg#ifdef HAVE_MKSTEMP 1149629baa8cSmrg } else { 1150629baa8cSmrg (void) fclose (old); 1151629baa8cSmrg#endif 1152629baa8cSmrg } 1153629baa8cSmrg } 1154629baa8cSmrg } 1155629baa8cSmrg if (lockStatus != LOCK_SUCCESS) { 1156629baa8cSmrg Debug ("can't lock auth file %s or backup %s\n", 1157629baa8cSmrg home_name, backup_name); 1158629baa8cSmrg LogError ("can't lock authorization file %s or backup %s\n", 1159629baa8cSmrg home_name, backup_name); 1160629baa8cSmrg return; 1161629baa8cSmrg } 1162629baa8cSmrg initAddrs (); 1163629baa8cSmrg doWrite = 1; 1164629baa8cSmrg Debug ("%d authorization protocols for %s\n", d->authNum, d->name); 1165629baa8cSmrg /* 1166629baa8cSmrg * Write MIT-MAGIC-COOKIE-1 authorization first, so that 1167629baa8cSmrg * R4 clients which only knew that, and used the first 1168629baa8cSmrg * matching entry will continue to function 1169629baa8cSmrg */ 1170629baa8cSmrg magicCookie = -1; 1171629baa8cSmrg for (i = 0; i < d->authNum; i++) 1172629baa8cSmrg { 1173629baa8cSmrg if (auths[i]->name_length == 18 && 1174629baa8cSmrg !strncmp (auths[i]->name, "MIT-MAGIC-COOKIE-1", 18)) 1175629baa8cSmrg { 1176629baa8cSmrg magicCookie = i; 1177629baa8cSmrg if (d->displayType.location == Local) 1178629baa8cSmrg writeLocalAuth (new, auths[i], d->name); 1179629baa8cSmrg#ifdef XDMCP 1180629baa8cSmrg else 1181629baa8cSmrg writeRemoteAuth (new, auths[i], d->peer, d->peerlen, d->name); 1182629baa8cSmrg#endif 1183629baa8cSmrg break; 1184629baa8cSmrg } 1185629baa8cSmrg } 1186629baa8cSmrg /* now write other authorizations */ 1187629baa8cSmrg for (i = 0; i < d->authNum; i++) 1188629baa8cSmrg { 1189629baa8cSmrg if (i != magicCookie) 1190629baa8cSmrg { 1191629baa8cSmrg data_len = auths[i]->data_length; 1192629baa8cSmrg /* client will just use default Kerberos cache, so don't 1193629baa8cSmrg * even write cache info into the authority file. 1194629baa8cSmrg */ 1195629baa8cSmrg if (auths[i]->name_length == 14 && 1196629baa8cSmrg !strncmp (auths[i]->name, "MIT-KERBEROS-5", 14)) 1197629baa8cSmrg auths[i]->data_length = 0; 1198629baa8cSmrg if (d->displayType.location == Local) 1199629baa8cSmrg writeLocalAuth (new, auths[i], d->name); 1200629baa8cSmrg#ifdef XDMCP 1201629baa8cSmrg else 1202629baa8cSmrg writeRemoteAuth (new, auths[i], d->peer, d->peerlen, d->name); 1203629baa8cSmrg#endif 1204629baa8cSmrg auths[i]->data_length = data_len; 1205629baa8cSmrg } 1206629baa8cSmrg } 1207629baa8cSmrg if (old) { 1208629baa8cSmrg if (fstat (fileno (old), &statb) != -1) 1209629baa8cSmrg chmod (new_name, (int) (statb.st_mode & 0777)); 1210629baa8cSmrg /*SUPPRESS 560*/ 1211629baa8cSmrg while ((entry = XauReadAuth (old))) { 1212629baa8cSmrg if (!checkEntry (entry)) 1213629baa8cSmrg { 1214629baa8cSmrg Debug ("Writing an entry\n"); 1215629baa8cSmrg writeAuth (new, entry); 1216629baa8cSmrg } 1217629baa8cSmrg XauDisposeAuth (entry); 1218629baa8cSmrg } 1219629baa8cSmrg fclose (old); 1220629baa8cSmrg } 1221629baa8cSmrg doneAddrs (); 1222629baa8cSmrg fclose (new); 1223629baa8cSmrg if (unlink (name) == -1) 1224629baa8cSmrg if (errno != ENOENT) 1225629baa8cSmrg LogError ("cannot remove old authorization file %s: %s\n", 1226629baa8cSmrg name, _SysErrorMsg (errno)); 1227629baa8cSmrg envname = name; 1228629baa8cSmrg if (link (new_name, name) == -1) { 1229629baa8cSmrg LogError ("cannot link temporary authorization file %s to old " 1230629baa8cSmrg "location %s: %s\n", new_name, name, 1231629baa8cSmrg _SysErrorMsg (errno)); 1232629baa8cSmrg setenv = 1; 1233629baa8cSmrg envname = new_name; 1234629baa8cSmrg } else { 1235629baa8cSmrg Debug ("authorization file %s successfully updated\n", name); 1236629baa8cSmrg if (unlink (new_name)) 1237629baa8cSmrg if (errno != ENOENT) 1238629baa8cSmrg LogError ("cannot remove new authorization file %s:" 1239629baa8cSmrg " %s\n", new_name, _SysErrorMsg (errno)); 1240629baa8cSmrg } 1241629baa8cSmrg if (setenv) { 1242629baa8cSmrg verify->userEnviron = setEnv (verify->userEnviron, 1243629baa8cSmrg "XAUTHORITY", envname); 1244629baa8cSmrg verify->systemEnviron = setEnv (verify->systemEnviron, 1245629baa8cSmrg "XAUTHORITY", envname); 1246629baa8cSmrg } 1247629baa8cSmrg XauUnlockAuth (name); 1248629baa8cSmrg if (envname) 1249629baa8cSmrg chown (envname, verify->uid, verify->gid); 1250629baa8cSmrg } 1251629baa8cSmrg Debug ("done SetUserAuthorization\n"); 1252629baa8cSmrg} 1253629baa8cSmrg 1254629baa8cSmrgvoid 1255629baa8cSmrgRemoveUserAuthorization (struct display *d, struct verify_info *verify) 1256629baa8cSmrg{ 1257629baa8cSmrg char *home; 1258629baa8cSmrg Xauth **auths, *entry; 1259629baa8cSmrg char name[1024], new_name[1024]; 1260629baa8cSmrg int lockStatus; 1261629baa8cSmrg FILE *old, *new; 1262629baa8cSmrg struct stat statb; 1263629baa8cSmrg int i; 1264629baa8cSmrg 1265629baa8cSmrg if (!(auths = d->authorizations)) 1266629baa8cSmrg return; 1267629baa8cSmrg home = getEnv (verify->userEnviron, "HOME"); 1268629baa8cSmrg if (!home) 1269629baa8cSmrg return; 1270629baa8cSmrg Debug ("RemoveUserAuthorization\n"); 1271629baa8cSmrg snprintf(name, sizeof(name), "%s/.Xauthority", home); 1272629baa8cSmrg Debug ("XauLockAuth %s\n", name); 1273629baa8cSmrg lockStatus = XauLockAuth (name, 1, 2, 10); 1274629baa8cSmrg Debug ("Lock is %d\n", lockStatus); 1275629baa8cSmrg if (lockStatus != LOCK_SUCCESS) 1276629baa8cSmrg return; 1277629baa8cSmrg old = NULL; 1278629baa8cSmrg if (openFiles (name, new_name, &old, &new)) 1279629baa8cSmrg { 1280629baa8cSmrg initAddrs (); 1281629baa8cSmrg doWrite = 0; 1282629baa8cSmrg for (i = 0; i < d->authNum; i++) 1283629baa8cSmrg { 1284629baa8cSmrg if (d->displayType.location == Local) 1285629baa8cSmrg writeLocalAuth (new, auths[i], d->name); 1286629baa8cSmrg#ifdef XDMCP 1287629baa8cSmrg else 1288629baa8cSmrg writeRemoteAuth (new, auths[i], d->peer, d->peerlen, d->name); 1289629baa8cSmrg#endif 1290629baa8cSmrg } 1291629baa8cSmrg doWrite = 1; 1292629baa8cSmrg if (old) { 1293629baa8cSmrg if (fstat (fileno (old), &statb) != -1) 1294629baa8cSmrg chmod (new_name, (int) (statb.st_mode & 0777)); 1295629baa8cSmrg /*SUPPRESS 560*/ 1296629baa8cSmrg while ((entry = XauReadAuth (old))) { 1297629baa8cSmrg if (!checkEntry (entry)) 1298629baa8cSmrg { 1299629baa8cSmrg Debug ("Writing an entry\n"); 1300629baa8cSmrg writeAuth (new, entry); 1301629baa8cSmrg } 1302629baa8cSmrg XauDisposeAuth (entry); 1303629baa8cSmrg } 1304629baa8cSmrg fclose (old); 1305629baa8cSmrg } 1306629baa8cSmrg doneAddrs (); 1307629baa8cSmrg fclose (new); 1308629baa8cSmrg if (unlink (name) == -1) 1309629baa8cSmrg if (errno != ENOENT) 1310629baa8cSmrg LogError ("cannot remove new authorization file %s: %s\n", 1311629baa8cSmrg name, _SysErrorMsg (errno)); 1312629baa8cSmrg if (link (new_name, name) == -1) { 1313629baa8cSmrg LogError ("cannot link temporary authorization file %s to old " 1314629baa8cSmrg "location %s: %s\n", new_name, name, 1315629baa8cSmrg _SysErrorMsg (errno)); 1316629baa8cSmrg } else { 1317629baa8cSmrg Debug ("authorization file %s successfully updated\n", name); 1318629baa8cSmrg if (unlink (new_name)) 1319629baa8cSmrg if (errno != ENOENT) 1320629baa8cSmrg LogError ("cannot remove new authorization file %s:" 1321629baa8cSmrg " %s\n", new_name, _SysErrorMsg (errno)); 1322629baa8cSmrg } 1323629baa8cSmrg } 1324629baa8cSmrg XauUnlockAuth (name); 1325629baa8cSmrg} 1326