auth.c revision 629baa8c
1/* 2 3Copyright 1988, 1998 The Open Group 4 5Permission to use, copy, modify, distribute, and sell this software and its 6documentation for any purpose is hereby granted without fee, provided that 7the above copyright notice appear in all copies and that both that 8copyright notice and this permission notice appear in supporting 9documentation. 10 11The above copyright notice and this permission notice shall be included 12in all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 18OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20OTHER DEALINGS IN THE SOFTWARE. 21 22Except as contained in this notice, the name of The Open Group shall 23not be used in advertising or otherwise to promote the sale, use or 24other dealings in this Software without prior written authorization 25from The Open Group. 26 27*/ 28 29/* 30 * xdm - display manager daemon 31 * Author: Keith Packard, MIT X Consortium 32 * 33 * auth.c 34 * 35 * maintain the authorization generation daemon 36 */ 37 38#include <X11/X.h> 39#include <X11/Xlibint.h> 40#include <sys/types.h> 41#include <sys/stat.h> 42 43#include "dm.h" 44#include "dm_auth.h" 45#include "dm_error.h" 46 47#include <errno.h> 48 49#include <sys/ioctl.h> 50 51#if defined(TCPCONN) || defined(STREAMSCONN) 52# include "dm_socket.h" 53#endif 54#ifdef DNETCONN 55# include <netdnet/dn.h> 56# include <netdnet/dnetdb.h> 57#endif 58 59#if defined(hpux) 60# include <sys/utsname.h> 61#endif 62 63#if defined(SYSV) && defined(i386) 64# include <sys/stream.h> 65# ifdef ISC 66# include <stropts.h> 67# include <sys/sioctl.h> 68# endif /* ISC */ 69#endif /* i386 */ 70 71#ifdef SVR4 72# include <netdb.h> 73# include <sys/sockio.h> 74# include <sys/stropts.h> 75#endif 76#ifdef __convex__ 77# include <sync/queue.h> 78# include <sync/sema.h> 79#endif 80#ifdef __GNU__ 81# include <netdb.h> 82# undef SIOCGIFCONF 83#else /* __GNU__ */ 84# include <net/if.h> 85#endif /* __GNU__ */ 86 87#if defined(TCPCONN) && !defined(WIN32) 88# include <netinet/in.h> 89#endif 90 91/* Solaris provides an extended interface SIOCGLIFCONF for IPv6 support. 92 */ 93#ifdef SIOCGLIFCONF 94# define USE_SIOCGLIFCONF 95#endif 96 97#if ((defined(SVR4) && !defined(sun)) || defined(ISC)) && \ 98 defined(SIOCGIFCONF) && !defined(USE_SIOCGLIFCONF) 99# define SYSV_SIOCGIFCONF 100#endif 101 102#ifdef HAVE_SYS_PARAM_H 103#include <sys/param.h> 104# ifdef BSD 105# if (BSD >= 199103) 106# define VARIABLE_IFREQ 107# endif 108# endif 109#endif 110 111#ifdef __UNIXOS2__ 112# define link rename 113int chown(int a,int b,int c) {} 114# include <io.h> 115#endif 116 117struct AuthProtocol { 118 unsigned short name_length; 119 char *name; 120 void (*InitAuth)(unsigned short len, char *name); 121 Xauth *(*GetAuth)(unsigned short len, char *name); 122 void (*GetXdmcpAuth)( 123 struct protoDisplay *pdpy, 124 unsigned short authorizationNameLen, 125 char *authorizationName); 126 int inited; 127}; 128 129static struct AuthProtocol AuthProtocols[] = { 130{ (unsigned short) 18, "MIT-MAGIC-COOKIE-1", 131 MitInitAuth, MitGetAuth, NULL 132}, 133#ifdef HASXDMAUTH 134{ (unsigned short) 19, "XDM-AUTHORIZATION-1", 135 XdmInitAuth, XdmGetAuth, XdmGetXdmcpAuth, 136}, 137#endif 138#ifdef SECURE_RPC 139{ (unsigned short) 9, "SUN-DES-1", 140 SecureRPCInitAuth, SecureRPCGetAuth, NULL, 141}, 142#endif 143#ifdef K5AUTH 144{ (unsigned short) 14, "MIT-KERBEROS-5", 145 Krb5InitAuth, Krb5GetAuth, NULL, 146}, 147#endif 148}; 149 150#define NUM_AUTHORIZATION (sizeof (AuthProtocols) / sizeof (AuthProtocols[0])) 151 152static struct AuthProtocol * 153findProtocol (unsigned short name_length, char *name) 154{ 155 int i; 156 157 for (i = 0; i < NUM_AUTHORIZATION; i++) 158 if (AuthProtocols[i].name_length == name_length && 159 memcmp(AuthProtocols[i].name, name, name_length) == 0) 160 { 161 return &AuthProtocols[i]; 162 } 163 return (struct AuthProtocol *) 0; 164} 165 166int 167ValidAuthorization (unsigned short name_length, char *name) 168{ 169 if (findProtocol (name_length, name)) 170 return TRUE; 171 return FALSE; 172} 173 174static Xauth * 175GenerateAuthorization (unsigned short name_length, char *name) 176{ 177 struct AuthProtocol *a; 178 Xauth *auth = NULL; 179 int i; 180 181 Debug ("GenerateAuthorization %*.*s\n", 182 name_length, name_length, name); 183 a = findProtocol (name_length, name); 184 if (a) 185 { 186 if (!a->inited) 187 { 188 (*a->InitAuth) (name_length, name); 189 a->inited = TRUE; 190 } 191 auth = (*a->GetAuth) (name_length, name); 192 if (auth) 193 { 194 Debug ("Got %p (%d %*.*s) ", auth, 195 auth->name_length, auth->name_length, 196 auth->name_length, auth->name); 197 for (i = 0; i < (int)auth->data_length; i++) 198 Debug (" %02x", auth->data[i] & 0xff); 199 Debug ("\n"); 200 } 201 else 202 Debug ("Got (null)\n"); 203 } 204 else 205 { 206 Debug ("Unknown authorization %*.*s\n", name_length, name_length, name); 207 } 208 return auth; 209} 210 211#ifdef XDMCP 212 213void 214SetProtoDisplayAuthorization ( 215 struct protoDisplay *pdpy, 216 unsigned short authorizationNameLen, 217 char *authorizationName) 218{ 219 struct AuthProtocol *a; 220 Xauth *auth; 221 222 a = findProtocol (authorizationNameLen, authorizationName); 223 pdpy->xdmcpAuthorization = pdpy->fileAuthorization = NULL; 224 if (a) 225 { 226 if (!a->inited) 227 { 228 (*a->InitAuth) (authorizationNameLen, authorizationName); 229 a->inited = TRUE; 230 } 231 if (a->GetXdmcpAuth) 232 { 233 (*a->GetXdmcpAuth) (pdpy, authorizationNameLen, authorizationName); 234 auth = pdpy->xdmcpAuthorization; 235 } 236 else 237 { 238 auth = (*a->GetAuth) (authorizationNameLen, authorizationName); 239 pdpy->fileAuthorization = auth; 240 pdpy->xdmcpAuthorization = NULL; 241 } 242 if (auth) 243 Debug ("Got %p (%d %*.*s)\n", auth, 244 auth->name_length, auth->name_length, 245 auth->name_length, auth->name); 246 else 247 Debug ("Got (null)\n"); 248 } 249} 250 251#endif /* XDMCP */ 252 253void 254CleanUpFileName (char *src, char *dst, int len) 255{ 256 while (*src) { 257 if (--len <= 0) 258 break; 259 switch (*src & 0x7f) 260 { 261 case '/': 262 *dst++ = '_'; 263 break; 264 case '-': 265 *dst++ = '.'; 266 break; 267 default: 268 *dst++ = (*src & 0x7f); 269 } 270 ++src; 271 } 272 *dst = '\0'; 273} 274 275/* Checks to see if specified directory exists, makes it if not 276 * Returns: 0 if already exists, 1 if created, < 0 if error occured 277 */ 278static int 279CheckServerAuthDir (const char *path, struct stat *statb, int mode) 280{ 281 int r = stat(path, statb); 282 283 if (r != 0) { 284 if (errno == ENOENT) { 285 r = mkdir(path, mode); 286 if (r < 0) { 287 LogError ("cannot make authentication directory %s: %s\n", 288 path, _SysErrorMsg (errno)); 289 } else { 290 r = 1; 291 } 292 } else { 293 LogError ("cannot access authentication directory %s: %s\n", 294 path, _SysErrorMsg (errno)); 295 } 296 } else { /* Directory already exists */ 297 if (!S_ISDIR(statb->st_mode)) { 298 LogError ("cannot make authentication directory %s: %s\n", 299 path, "file with that name already exists"); 300 return -1; 301 } 302 } 303 304 return r; 305} 306 307static char authdir1[] = "authdir"; 308static char authdir2[] = "authfiles"; 309 310static int 311MakeServerAuthFile (struct display *d, FILE ** file) 312{ 313 int len; 314#ifdef MAXNAMELEN 315# define NAMELEN MAXNAMELEN 316#else 317# define NAMELEN 255 318#endif 319 char cleanname[NAMELEN]; 320 int r; 321#ifdef HAVE_MKSTEMP 322 int fd; 323#endif 324 struct stat statb; 325 326 *file = NULL; 327 328 if (!d->authFile) { 329 if (d->clientAuthFile && *d->clientAuthFile) { 330 d->authFile = strdup(d->clientAuthFile); 331 if (!d->authFile) 332 return FALSE; 333 } else { 334 CleanUpFileName (d->name, cleanname, NAMELEN - 8); 335 336 /* Make authDir if it doesn't already exist */ 337 r = CheckServerAuthDir(authDir, &statb, 0755); 338 if (r < 0) { 339 return FALSE; 340 } 341 342 len = strlen (authDir) + strlen (authdir1) + strlen (authdir2) 343 + strlen (cleanname) + 14; 344 d->authFile = malloc (len); 345 if (!d->authFile) 346 return FALSE; 347 348 snprintf (d->authFile, len, "%s/%s", authDir, authdir1); 349 r = CheckServerAuthDir(d->authFile, &statb, 0700); 350 if (r == 0) { 351 if (statb.st_uid != 0) 352 (void) chown(d->authFile, 0, statb.st_gid); 353 if ((statb.st_mode & 0077) != 0) 354 (void) chmod(d->authFile, statb.st_mode & 0700); 355 } else if (r < 0) { 356 free (d->authFile); 357 d->authFile = NULL; 358 return FALSE; 359 } 360 361 snprintf (d->authFile, len, "%s/%s/%s", 362 authDir, authdir1, authdir2); 363 r = CheckServerAuthDir(d->authFile, &statb, 0700); 364 if (r < 0) { 365 free (d->authFile); 366 d->authFile = NULL; 367 return FALSE; 368 } 369 snprintf (d->authFile, len, "%s/%s/%s/A%s-XXXXXX", 370 authDir, authdir1, authdir2, cleanname); 371#ifdef HAVE_MKSTEMP 372 fd = mkstemp (d->authFile); 373 if (fd < 0) { 374 LogError ("cannot make authentication file %s: %s\n", 375 d->authFile, _SysErrorMsg (errno)); 376 free (d->authFile); 377 d->authFile = NULL; 378 return FALSE; 379 } 380 381 *file = fdopen(fd, "w"); 382 if (!*file) 383 (void) close (fd); 384 return TRUE; 385#else 386 (void) mktemp (d->authFile); 387#endif 388 } 389 } 390 391 (void) unlink (d->authFile); 392 *file = fopen (d->authFile, "w"); 393 return TRUE; 394} 395 396int 397SaveServerAuthorizations ( 398 struct display *d, 399 Xauth **auths, 400 int count) 401{ 402 FILE *auth_file; 403 mode_t mask; 404 int ret; 405 int i; 406 const char dummy_auth[] = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" 407 "XXXXXXXXXXXXXXXXX"; /* 64 "X"s */ 408 int err = 0; 409 410 mask = umask (0077); 411 ret = MakeServerAuthFile(d, &auth_file); 412 umask (mask); 413 if (!ret) 414 return FALSE; 415 if (!auth_file) { 416 LogError ("cannot open server authorization file %s: %s\n", 417 d->authFile, _SysErrorMsg (errno)); 418 ret = FALSE; 419 } 420 else 421 { 422 Debug ("File: %s auth: %p\n", d->authFile, auths); 423 ret = TRUE; 424 if (count == 0) 425 { 426 /* 427 * This is a crude hack to determine whether we really can 428 * write to the auth file even if we don't have real data 429 * to write right now. 430 */ 431 432 /* 433 * Write garbage data to file to provoke ENOSPC and other 434 * errors. 435 */ 436 (void) fprintf (auth_file, "%s", dummy_auth); 437 (void) fflush (auth_file); 438 if (ferror (auth_file)) 439 { 440 err = errno; 441 ret = FALSE; 442 } 443 /* 444 * Rewind so that the garbage data is overwritten later. 445 */ 446 rewind(auth_file); 447 } 448 for (i = 0; i < count; i++) 449 { 450 /* 451 * User-based auths may not have data until 452 * a user logs in. In which case don't write 453 * to the auth file so xrdb and setup programs don't fail. 454 */ 455 if (auths[i]->data_length > 0) 456 if (!XauWriteAuth (auth_file, auths[i])) 457 { 458 Debug ("XauWriteAuth() failed\n"); 459 } 460 (void) fflush (auth_file); 461 if (ferror (auth_file)) 462 { 463 err = errno; 464 ret = FALSE; 465 } 466 } 467 /* 468 * XXX: This is not elegant, but stdio has no truncation function. 469 */ 470 if (ftruncate(fileno(auth_file), ftell(auth_file))) 471 { 472 Debug ("ftruncate() failed\n"); 473 } 474 fclose (auth_file); 475 476 } 477 if (ret == FALSE) 478 { 479 LogError ("Cannot write to server authorization file %s%s%s\n", 480 d->authFile, 481 err ? ": " : "", 482 err ? _SysErrorMsg (errno) : ""); 483 free (d->authFile); 484 d->authFile = NULL; 485 } 486 return ret; 487} 488 489void 490SetLocalAuthorization (struct display *d) 491{ 492 Xauth *auth, **auths; 493 int i, j; 494 495 if (d->authorizations) 496 { 497 for (i = 0; i < d->authNum; i++) 498 XauDisposeAuth (d->authorizations[i]); 499 free (d->authorizations); 500 d->authorizations = (Xauth **) NULL; 501 d->authNum = 0; 502 } 503 if (!d->authNames) 504 return; 505 for (i = 0; d->authNames[i]; i++) 506 ; 507 d->authNameNum = i; 508 free (d->authNameLens); 509 d->authNameLens = malloc (d->authNameNum * sizeof (unsigned short)); 510 if (!d->authNameLens) 511 return; 512 for (i = 0; i < d->authNameNum; i++) 513 d->authNameLens[i] = strlen (d->authNames[i]); 514 auths = malloc (d->authNameNum * sizeof (Xauth *)); 515 if (!auths) 516 return; 517 j = 0; 518 for (i = 0; i < d->authNameNum; i++) 519 { 520 auth = GenerateAuthorization (d->authNameLens[i], d->authNames[i]); 521 if (auth) 522 auths[j++] = auth; 523 } 524 if (SaveServerAuthorizations (d, auths, j)) 525 { 526 d->authorizations = auths; 527 d->authNum = j; 528 } 529 else 530 { 531 for (i = 0; i < j; i++) 532 XauDisposeAuth (auths[i]); 533 free (auths); 534 } 535} 536 537/* 538 * Set the authorization to use for xdm's initial connection 539 * to the X server. Cannot use user-based authorizations 540 * because no one has logged in yet, so we don't have any 541 * user credentials. 542 * Well, actually we could use SUN-DES-1 because we tell the server 543 * to allow root in. This is bogus and should be fixed. 544 */ 545void 546SetAuthorization (struct display *d) 547{ 548 register Xauth **auth = d->authorizations; 549 int i; 550 551 for (i = 0; i < d->authNum; i++) 552 { 553 if (auth[i]->name_length == 9 && 554 memcmp(auth[i]->name, "SUN-DES-1", 9) == 0) 555 continue; 556 if (auth[i]->name_length == 14 && 557 memcmp(auth[i]->name, "MIT-KERBEROS-5", 14) == 0) 558 continue; 559 XSetAuthorization (auth[i]->name, (int) auth[i]->name_length, 560 auth[i]->data, (int) auth[i]->data_length); 561 } 562} 563 564static int 565openFiles (char *name, char *new_name, FILE **oldp, FILE **newp) 566{ 567 mode_t mask; 568 int newfd; 569 570 strcpy (new_name, name); 571 strcat (new_name, "-n"); 572 /* 573 * Set safe umask for file creation operations. 574 */ 575 mask = umask (0077); 576 /* 577 * Unlink the authorization file we intend to create, and then open 578 * it with O_CREAT | O_EXCL to avoid race-based symlink attacks. 579 */ 580 (void) unlink (new_name); 581 newfd = open (new_name, O_WRONLY | O_CREAT | O_EXCL, 0600); 582 if (newfd >= 0) 583 *newp = fdopen (newfd, "w"); 584 else 585 { 586 LogError ("Cannot create file %s: %s\n", new_name, 587 _SysErrorMsg (errno)); 588 *newp = NULL; 589 } 590 /* 591 * There are no more attempts to create files after this point; 592 * restore the original umask. 593 */ 594 (void) umask (mask); 595 if (!*newp) { 596 Debug ("can't open new file %s\n", new_name); 597 return 0; 598 } 599 if (!*oldp) 600 *oldp = fopen (name, "r"); 601 Debug ("opens succeeded %s %s\n", name, new_name); 602 return 1; 603} 604 605static int 606binaryEqual (char *a, char *b, unsigned short len) 607{ 608 while (len-- > 0) 609 if (*a++ != *b++) 610 return FALSE; 611 return TRUE; 612} 613 614static void 615dumpBytes (unsigned short len, char *data) 616{ 617 unsigned short i; 618 619 Debug ("%d: ", len); 620 for (i = 0; i < len; i++) 621 Debug ("%02x ", data[i] & 0377); 622 Debug ("\n"); 623} 624 625static void 626dumpAuth (Xauth *auth) 627{ 628 Debug ("family: %d\n", auth->family); 629 Debug ("addr: "); 630 dumpBytes (auth->address_length, auth->address); 631 Debug ("number: "); 632 dumpBytes (auth->number_length, auth->number); 633 Debug ("name: "); 634 dumpBytes (auth->name_length, auth->name); 635 Debug ("data: "); 636 dumpBytes (auth->data_length, auth->data); 637} 638 639struct addrList { 640 unsigned short family; 641 unsigned short address_length; 642 char *address; 643 unsigned short number_length; 644 char *number; 645 unsigned short name_length; 646 char *name; 647 struct addrList *next; 648}; 649 650static struct addrList *addrs; 651 652static void 653initAddrs (void) 654{ 655 addrs = NULL; 656} 657 658static void 659doneAddrs (void) 660{ 661 struct addrList *a, *n; 662 for (a = addrs; a; a = n) { 663 n = a->next; 664 free (a->address); 665 free (a->number); 666 free (a); 667 } 668} 669 670static int checkEntry (Xauth *auth); 671 672static void 673saveEntry (Xauth *auth) 674{ 675 struct addrList *new; 676 677 new = malloc (sizeof (struct addrList)); 678 if (!new) { 679 LogOutOfMem ("saveEntry"); 680 return; 681 } 682 if ((new->address_length = auth->address_length) > 0) { 683 new->address = malloc (auth->address_length); 684 if (!new->address) { 685 LogOutOfMem ("saveEntry"); 686 free (new); 687 return; 688 } 689 memmove( new->address, auth->address, (int) auth->address_length); 690 } else 691 new->address = NULL; 692 if ((new->number_length = auth->number_length) > 0) { 693 new->number = malloc (auth->number_length); 694 if (!new->number) { 695 LogOutOfMem ("saveEntry"); 696 free (new->address); 697 free (new); 698 return; 699 } 700 memmove( new->number, auth->number, (int) auth->number_length); 701 } else 702 new->number = NULL; 703 if ((new->name_length = auth->name_length) > 0) { 704 new->name = malloc (auth->name_length); 705 if (!new->name) { 706 LogOutOfMem ("saveEntry"); 707 free (new->number); 708 free (new->address); 709 free (new); 710 return; 711 } 712 memmove( new->name, auth->name, (int) auth->name_length); 713 } else 714 new->name = NULL; 715 new->family = auth->family; 716 new->next = addrs; 717 addrs = new; 718} 719 720static int 721checkEntry (Xauth *auth) 722{ 723 struct addrList *a; 724 725 for (a = addrs; a; a = a->next) { 726 if (a->family == auth->family && 727 a->address_length == auth->address_length && 728 binaryEqual (a->address, auth->address, auth->address_length) && 729 a->number_length == auth->number_length && 730 binaryEqual (a->number, auth->number, auth->number_length) && 731 a->name_length == auth->name_length && 732 binaryEqual (a->name, auth->name, auth->name_length)) 733 { 734 return 1; 735 } 736 } 737 return 0; 738} 739 740static int doWrite; 741 742static void 743writeAuth (FILE *file, Xauth *auth) 744{ 745 if (debugLevel >= 15) { /* normally too verbose */ 746 Debug ("writeAuth: doWrite = %d\n", doWrite); 747 dumpAuth (auth); /* does Debug only */ 748 } 749 if (doWrite) 750 XauWriteAuth (file, auth); 751} 752 753static void 754writeAddr ( 755 int family, 756 int addr_length, 757 char *addr, 758 FILE *file, 759 Xauth *auth) 760{ 761 auth->family = (unsigned short) family; 762 auth->address_length = addr_length; 763 auth->address = addr; 764 Debug ("writeAddr: writing and saving an entry\n"); 765 writeAuth (file, auth); 766 saveEntry (auth); 767} 768 769static void 770DefineLocal (FILE *file, Xauth *auth) 771{ 772 char displayname[100]; 773 int len = _XGetHostname (displayname, sizeof(displayname)); 774 775/* Make sure this produces the same string as _XGetHostname in lib/X/XlibInt.c. 776 * Otherwise, Xau will not be able to find your cookies in the Xauthority file. 777 * 778 * Note: POSIX says that the ``nodename'' member of utsname does _not_ have 779 * to have sufficient information for interfacing to the network, 780 * and so, you may be better off using gethostname (if it exists). 781 */ 782 783#if defined(hpux) 784 /* 785 * For HP-UX, HP's Xlib expects a fully-qualified domain name, which 786 * is achieved by using gethostname(). For compatability, we must 787 * also still create the entry using uname(). 788 */ 789 char tmp_displayname[100]; 790 struct utsname name; 791 792 tmp_displayname[0] = 0; 793 uname(&name); 794 snprintf(tmp_displayname, sizeof(tmp_displayname), "%s", name.nodename); 795 writeAddr (FamilyLocal, strlen (tmp_displayname), tmp_displayname, 796 file, auth); 797 798 /* 799 * If _XGetHostname() returned the same value as uname(), don't 800 * write a duplicate entry. 801 */ 802 if (strcmp (displayname, tmp_displayname)) 803#endif 804 805 writeAddr (FamilyLocal, len, displayname, file, auth); 806} 807 808#ifdef HAVE_GETIFADDRS 809# include <ifaddrs.h> 810 811static void 812DefineSelf(int fd, FILE *file, Xauth *auth) 813{ 814 struct ifaddrs *ifap, *ifr; 815 char *addr; 816 int family, len; 817 818 Debug("DefineSelf\n"); 819 if (getifaddrs(&ifap) < 0) 820 return; 821 for (ifr = ifap; ifr != NULL; ifr = ifr->ifa_next) { 822 len = sizeof(*(ifr->ifa_addr)); 823 family = ConvertAddr((XdmcpNetaddr)(ifr->ifa_addr), &len, &addr); 824 if (family == -1 || family == FamilyLocal) 825 continue; 826 /* 827 * don't write out 'localhost' entries, as 828 * they may conflict with other local entries. 829 * DefineLocal will always be called to add 830 * the local entry anyway, so this one can 831 * be tossed. 832 */ 833 if (family == FamilyInternet && len == 4 && addr[0] == 127) 834 { 835 Debug ("Skipping localhost address\n"); 836 continue; 837 } 838# if defined(IPv6) && defined(AF_INET6) 839 if(family == FamilyInternet6) { 840 if (IN6_IS_ADDR_LOOPBACK(((struct in6_addr *)addr))) { 841 Debug ("Skipping IPv6 localhost address\n"); 842 continue; 843 } 844 /* Also skip XDM-AUTHORIZATION-1 */ 845 if (auth->name_length == 19 && 846 strcmp(auth->name, "XDM-AUTHORIZATION-1") == 0) { 847 Debug ("Skipping IPv6 XDM-AUTHORIZATION-1\n"); 848 continue; 849 } 850 } 851# endif 852 writeAddr(family, len, addr, file, auth); 853 } 854 freeifaddrs(ifap); 855 Debug("DefineSelf done\n"); 856} 857#else /* GETIFADDRS */ 858 859# ifdef SYSV_SIOCGIFCONF 860 861/* Deal with different SIOCGIFCONF ioctl semantics on SYSV, SVR4 */ 862 863static int 864ifioctl (int fd, int cmd, char *arg) 865{ 866 struct strioctl ioc; 867 int ret; 868 869 bzero((char *) &ioc, sizeof(ioc)); 870 ioc.ic_cmd = cmd; 871 ioc.ic_timout = 0; 872 if (cmd == SIOCGIFCONF) 873 { 874 ioc.ic_len = ((struct ifconf *) arg)->ifc_len; 875 ioc.ic_dp = ((struct ifconf *) arg)->ifc_buf; 876# ifdef ISC 877 /* SIOCGIFCONF is somewhat brain damaged on ISC. The argument 878 * buffer must contain the ifconf structure as header. Ifc_req 879 * is also not a pointer but a one element array of ifreq 880 * structures. On return this array is extended by enough 881 * ifreq fields to hold all interfaces. The return buffer length 882 * is placed in the buffer header. 883 */ 884 ((struct ifconf *) ioc.ic_dp)->ifc_len = 885 ioc.ic_len - sizeof(struct ifconf); 886# endif 887 } 888 else 889 { 890 ioc.ic_len = sizeof(struct ifreq); 891 ioc.ic_dp = arg; 892 } 893 ret = ioctl(fd, I_STR, (char *) &ioc); 894 if (ret >= 0 && cmd == SIOCGIFCONF) 895# ifdef SVR4 896 ((struct ifconf *) arg)->ifc_len = ioc.ic_len; 897# endif 898# ifdef ISC 899 { 900 ((struct ifconf *) arg)->ifc_len = 901 ((struct ifconf *)ioc.ic_dp)->ifc_len; 902 ((struct ifconf *) arg)->ifc_buf = 903 (caddr_t)((struct ifconf *)ioc.ic_dp)->ifc_req; 904 } 905# endif 906 return(ret); 907} 908# else /* SYSV_SIOCGIFCONF */ 909# define ifioctl ioctl 910# endif /* SYSV_SIOCGIFCONF */ 911 912# if defined(STREAMSCONN) && !defined(SYSV_SIOCGIFCONF) && !defined(NCR) 913 914# include <tiuser.h> 915 916/* Define this host for access control. Find all the hosts the OS knows about 917 * for this fd and add them to the selfhosts list. 918 * TLI version, written without sufficient documentation. 919 */ 920static void 921DefineSelf (int fd, FILE *file, Xauth *auth) 922{ 923 struct netbuf netb; 924 char addrret[1024]; /* easier than t_alloc */ 925 926 netb.maxlen = sizeof(addrret); 927 netb.buf = addrret; 928 if (t_getname (fd, &netb, LOCALNAME) == -1) 929 t_error ("t_getname"); 930 /* what a kludge */ 931 writeAddr (FamilyInternet, 4, netb.buf+4, file, auth); 932} 933 934# else 935 936# ifdef WINTCP /* NCR with Wollongong TCP */ 937 938# include <sys/un.h> 939# include <stropts.h> 940# include <tiuser.h> 941 942# include <sys/stream.h> 943# include <net/if.h> 944# include <netinet/ip.h> 945# include <netinet/ip_var.h> 946# include <netinet/in.h> 947# include <netinet/in_var.h> 948 949static void 950DefineSelf (int fd, FILE *file, Xauth *auth) 951{ 952 /* 953 * The Wollongong drivers used by NCR SVR4/MP-RAS don't understand the 954 * socket IO calls that most other drivers seem to like. Because of 955 * this, this routine must be special cased for NCR. Eventually, 956 * this will be cleared up. 957 */ 958 959 struct ipb ifnet; 960 struct in_ifaddr ifaddr; 961 struct strioctl str; 962 unsigned char *addr; 963 int len, ipfd; 964 965 if ((ipfd = open ("/dev/ip", O_RDWR, 0 )) < 0) 966 LogError ("cannot get interface configuration; cannot open /dev/ip: " 967 "%s\n", _SysErrorMsg (errno)); 968 969 /* Indicate that we want to start at the begining */ 970 ifnet.ib_next = (struct ipb *) 1; 971 972 while (ifnet.ib_next) 973 { 974 str.ic_cmd = IPIOC_GETIPB; 975 str.ic_timout = 0; 976 str.ic_len = sizeof (struct ipb); 977 str.ic_dp = (char *) &ifnet; 978 979 if (ioctl (ipfd, (int) I_STR, (char *) &str) < 0) 980 { 981 LogError ("cannot get interface configuration; ioctl failed: %s\n", 982 _SysErrorMsg (errno)); 983 close (ipfd); 984 } 985 986 ifaddr.ia_next = (struct in_ifaddr *) ifnet.if_addrlist; 987 str.ic_cmd = IPIOC_GETINADDR; 988 str.ic_timout = 0; 989 str.ic_len = sizeof (struct in_ifaddr); 990 str.ic_dp = (char *) &ifaddr; 991 992 if (ioctl (ipfd, (int) I_STR, (char *) &str) < 0) 993 { 994 LogError ("cannot get interface configuration; ioctl failed: %s\n", 995 _SysErrorMsg (errno)); 996 close (ipfd); 997 } 998 999 /* 1000 * Ignore the 127.0.0.1 entry. 1001 */ 1002 if (IA_SIN(&ifaddr)->sin_addr.s_addr == htonl(0x7f000001) ) 1003 continue; 1004 1005 writeAddr (FamilyInternet, 4, (char *)&(IA_SIN(&ifaddr)->sin_addr), file, auth); 1006 1007 } 1008 close(ipfd); 1009} 1010 1011# else /* WINTCP */ 1012 1013# if defined(SIOCGIFCONF) || defined (USE_SIOCGLIFCONF) 1014 1015# ifdef USE_SIOCGLIFCONF 1016# define ifr_type struct lifreq 1017# else 1018# define ifr_type struct ifreq 1019# endif 1020 1021/* Handle variable length ifreq in BNR2 and later */ 1022# ifdef VARIABLE_IFREQ 1023# define ifr_size(p) (sizeof (struct ifreq) + \ 1024 (p->ifr_addr.sa_len > sizeof (p->ifr_addr) ? \ 1025 p->ifr_addr.sa_len - sizeof (p->ifr_addr) : 0)) 1026# else 1027# define ifr_size(p) (sizeof (ifr_type)) 1028# endif 1029 1030/* Define this host for access control. Find all the hosts the OS knows about 1031 * for this fd and add them to the selfhosts list. 1032 */ 1033static void 1034DefineSelf (int fd, FILE *file, Xauth *auth) 1035{ 1036 char buf[2048], *cp, *cplim; 1037 int len; 1038 char *addr; 1039 int family; 1040 register ifr_type *ifr; 1041# ifdef USE_SIOCGLIFCONF 1042 void * bufptr = buf; 1043 size_t buflen = sizeof(buf); 1044 struct lifconf ifc; 1045# ifdef SIOCGLIFNUM 1046 struct lifnum ifn; 1047# endif 1048# else 1049 struct ifconf ifc; 1050# endif 1051 1052# if defined(SIOCGLIFNUM) && defined(SIOCGLIFCONF) 1053 ifn.lifn_family = AF_UNSPEC; 1054 ifn.lifn_flags = 0; 1055 if (ioctl (fd, (int) SIOCGLIFNUM, (char *) &ifn) < 0) 1056 LogError ("Failed getting interface count"); 1057 if (buflen < (ifn.lifn_count * sizeof(struct lifreq))) { 1058 buflen = ifn.lifn_count * sizeof(struct lifreq); 1059 bufptr = malloc(buflen); 1060 } 1061# endif 1062 1063# ifdef USE_SIOCGLIFCONF 1064 ifc.lifc_family = AF_UNSPEC; 1065 ifc.lifc_flags = 0; 1066 ifc.lifc_len = buflen; 1067 ifc.lifc_buf = bufptr; 1068 1069# define IFC_IOCTL_REQ SIOCGLIFCONF 1070# define IFC_IFC_REQ ifc.lifc_req 1071# define IFC_IFC_LEN ifc.lifc_len 1072# define IFR_IFR_ADDR ifr->lifr_addr 1073# define IFR_IFR_NAME ifr->lifr_name 1074 1075# else 1076 ifc.ifc_len = sizeof (buf); 1077 ifc.ifc_buf = buf; 1078 1079# define IFC_IOCTL_REQ SIOCGIFCONF 1080# ifdef ISC 1081# define IFC_IFC_REQ (struct ifreq *) ifc.ifc_buf 1082# else 1083# define IFC_IFC_REQ ifc.ifc_req 1084# endif 1085# define IFC_IFC_LEN ifc.ifc_len 1086# define IFR_IFR_ADDR ifr->ifr_addr 1087# define IFR_IFR_NAME ifr->ifr_name 1088# endif 1089 1090 if (ifioctl (fd, IFC_IOCTL_REQ, (char *) &ifc) < 0) { 1091 LogError ("Trouble getting network interface configuration"); 1092 1093# ifdef USE_SIOCGLIFCONF 1094 if (bufptr != buf) { 1095 free(bufptr); 1096 } 1097# endif 1098 return; 1099 } 1100 1101 cplim = (char *) IFC_IFC_REQ + IFC_IFC_LEN; 1102 1103 for (cp = (char *) IFC_IFC_REQ; cp < cplim; cp += ifr_size (ifr)) 1104 { 1105 ifr = (ifr_type *) cp; 1106# ifdef DNETCONN 1107 /* 1108 * this is ugly but SIOCGIFCONF returns decnet addresses in 1109 * a different form from other decnet calls 1110 */ 1111 if (IFR_IFR_ADDR.sa_family == AF_DECnet) { 1112 len = sizeof (struct dn_naddr); 1113 addr = (char *)ifr->ifr_addr.sa_data; 1114 family = FamilyDECnet; 1115 } else 1116# endif 1117 { 1118 family = ConvertAddr ((XdmcpNetaddr) &IFR_IFR_ADDR, &len, &addr); 1119 if (family < 0) 1120 continue; 1121 1122 if (len == 0) 1123 { 1124 Debug ("Skipping zero length address\n"); 1125 continue; 1126 } 1127 /* 1128 * don't write out 'localhost' entries, as 1129 * they may conflict with other local entries. 1130 * DefineLocal will always be called to add 1131 * the local entry anyway, so this one can 1132 * be tossed. 1133 */ 1134 if (family == FamilyInternet && len == 4 && 1135 addr[0] == 127 && addr[1] == 0 && 1136 addr[2] == 0 && addr[3] == 1) 1137 { 1138 Debug ("Skipping localhost address\n"); 1139 continue; 1140 } 1141# if defined(IPv6) && defined(AF_INET6) 1142 if(family == FamilyInternet6) { 1143 if (IN6_IS_ADDR_LOOPBACK(((struct in6_addr *)addr))) { 1144 Debug ("Skipping IPv6 localhost address\n"); 1145 continue; 1146 } 1147 /* Also skip XDM-AUTHORIZATION-1 */ 1148 if (auth->name_length == 19 && 1149 strcmp(auth->name, "XDM-AUTHORIZATION-1") == 0) { 1150 Debug ("Skipping IPv6 XDM-AUTHORIZATION-1\n"); 1151 continue; 1152 } 1153 } 1154# endif 1155 } 1156 Debug ("DefineSelf: write network address, length %d\n", len); 1157 writeAddr (family, len, addr, file, auth); 1158 } 1159} 1160 1161# else /* SIOCGIFCONF */ 1162 1163/* Define this host for access control. Find all the hosts the OS knows about 1164 * for this fd and add them to the selfhosts list. 1165 */ 1166static void 1167DefineSelf (int fd, int file, int auth) 1168{ 1169 register int n; 1170 int len; 1171 caddr_t addr; 1172 int family; 1173 1174 struct utsname name; 1175 register struct hostent *hp; 1176 1177 union { 1178 struct sockaddr sa; 1179 struct sockaddr_in in; 1180 } saddr; 1181 1182 struct sockaddr_in *inetaddr; 1183 1184 /* hpux: 1185 * Why not use gethostname()? Well, at least on my system, I've had to 1186 * make an ugly kernel patch to get a name longer than 8 characters, and 1187 * uname() lets me access to the whole string (it smashes release, you 1188 * see), whereas gethostname() kindly truncates it for me. 1189 */ 1190 uname(&name); 1191 hp = gethostbyname (name.nodename); 1192 if (hp != NULL) { 1193 saddr.sa.sa_family = hp->h_addrtype; 1194 inetaddr = (struct sockaddr_in *) (&(saddr.sa)); 1195 memmove( (char *) &(inetaddr->sin_addr), (char *) hp->h_addr, (int) hp->h_length); 1196 family = ConvertAddr ( &(saddr.sa), &len, &addr); 1197 if ( family >= 0) { 1198 writeAddr (FamilyInternet, sizeof (inetaddr->sin_addr), 1199 (char *) (&inetaddr->sin_addr), file, auth); 1200 } 1201 } 1202} 1203 1204 1205# endif /* SIOCGIFCONF else */ 1206# endif /* WINTCP else */ 1207# endif /* STREAMSCONN && !SYSV_SIOCGIFCONF else */ 1208#endif /* HAVE_GETIFADDRS */ 1209 1210static void 1211setAuthNumber (Xauth *auth, char *name) 1212{ 1213 char *colon; 1214 char *dot, *number; 1215 1216 Debug ("setAuthNumber %s\n", name); 1217 colon = strrchr(name, ':'); 1218 if (colon) { 1219 ++colon; 1220 dot = strchr(colon, '.'); 1221 if (dot) 1222 auth->number_length = dot - colon; 1223 else 1224 auth->number_length = strlen (colon); 1225 number = malloc (auth->number_length + 1); 1226 if (number) { 1227 strncpy (number, colon, auth->number_length); 1228 number[auth->number_length] = '\0'; 1229 } else { 1230 LogOutOfMem ("setAuthNumber"); 1231 auth->number_length = 0; 1232 } 1233 auth->number = number; 1234 Debug ("setAuthNumber: %s\n", number); 1235 } 1236} 1237 1238static void 1239writeLocalAuth (FILE *file, Xauth *auth, char *name) 1240{ 1241 int fd; 1242 1243 Debug ("writeLocalAuth: %s %.*s\n", name, auth->name_length, auth->name); 1244 setAuthNumber (auth, name); 1245#ifdef STREAMSCONN 1246 fd = t_open ("/dev/tcp", O_RDWR, 0); 1247 t_bind(fd, NULL, NULL); 1248 DefineSelf (fd, file, auth); 1249 t_unbind (fd); 1250 t_close (fd); 1251#endif 1252#ifdef TCPCONN 1253# if defined(IPv6) && defined(AF_INET6) 1254 fd = socket (AF_INET6, SOCK_STREAM, 0); 1255 if (fd < 0) 1256# endif 1257 fd = socket (AF_INET, SOCK_STREAM, 0); 1258 DefineSelf (fd, file, auth); 1259 close (fd); 1260#endif 1261#ifdef DNETCONN 1262 fd = socket (AF_DECnet, SOCK_STREAM, 0); 1263 DefineSelf (fd, file, auth); 1264 close (fd); 1265#endif 1266 DefineLocal (file, auth); 1267} 1268 1269#ifdef XDMCP 1270 1271static void 1272writeRemoteAuth (FILE *file, Xauth *auth, XdmcpNetaddr peer, int peerlen, char *name) 1273{ 1274 int family = FamilyLocal; 1275 char *addr; 1276 1277 Debug ("writeRemoteAuth: %s %.*s\n", name, auth->name_length, auth->name); 1278 if (!peer || peerlen < 2) 1279 return; 1280 setAuthNumber (auth, name); 1281 family = ConvertAddr (peer, &peerlen, &addr); 1282 Debug ("writeRemoteAuth: family %d\n", family); 1283 if (family != FamilyLocal) 1284 { 1285 Debug ("writeRemoteAuth: %d, %d, %x\n", 1286 family, peerlen, *(int *)addr); 1287 writeAddr (family, peerlen, addr, file, auth); 1288 } 1289 else 1290 { 1291 writeLocalAuth (file, auth, name); 1292 } 1293} 1294 1295#endif /* XDMCP */ 1296 1297void 1298SetUserAuthorization (struct display *d, struct verify_info *verify) 1299{ 1300 FILE *old = NULL, *new; 1301 char home_name[1024], backup_name[1024], new_name[1024]; 1302 char *name = NULL; 1303 char *home; 1304 char *envname = NULL; 1305 int lockStatus; 1306 Xauth *entry, **auths; 1307 int setenv = 0; 1308 struct stat statb; 1309 int i; 1310 int magicCookie; 1311 int data_len; 1312#ifdef HAVE_MKSTEMP 1313 int fd; 1314#endif 1315 1316 Debug ("SetUserAuthorization\n"); 1317 auths = d->authorizations; 1318 if (auths) { 1319 home = getEnv (verify->userEnviron, "HOME"); 1320 lockStatus = LOCK_ERROR; 1321 if (home) { 1322 snprintf (home_name, sizeof(home_name), "%s/.Xauthority", home); 1323 Debug ("XauLockAuth %s\n", home_name); 1324 lockStatus = XauLockAuth (home_name, 1, 2, 10); 1325 Debug ("Lock is %d\n", lockStatus); 1326 if (lockStatus == LOCK_SUCCESS) { 1327 if (openFiles (home_name, new_name, &old, &new) 1328 && (old != NULL) && (new != NULL)) { 1329 name = home_name; 1330 setenv = 0; 1331 } else { 1332 Debug ("openFiles failed\n"); 1333 XauUnlockAuth (home_name); 1334 lockStatus = LOCK_ERROR; 1335 if (old != NULL) { 1336 (void) fclose (old); 1337 old = NULL; 1338 } 1339 if (new != NULL) 1340 (void) fclose (new); 1341 } 1342 } 1343 } 1344 if (lockStatus != LOCK_SUCCESS) { 1345 snprintf (backup_name, sizeof(backup_name), 1346 "%s/.XauthXXXXXX", d->userAuthDir); 1347#ifdef HAVE_MKSTEMP 1348 fd = mkstemp (backup_name); 1349 if (fd >= 0) { 1350 old = fdopen (fd, "r"); 1351 if (old == NULL) 1352 (void) close(fd); 1353 } 1354 1355 if (old != NULL) 1356#else 1357 (void) mktemp (backup_name); 1358#endif 1359 { 1360 lockStatus = XauLockAuth (backup_name, 1, 2, 10); 1361 Debug ("backup lock is %d\n", lockStatus); 1362 if (lockStatus == LOCK_SUCCESS) { 1363 if (openFiles (backup_name, new_name, &old, &new) 1364 && (old != NULL) && (new != NULL)) { 1365 name = backup_name; 1366 setenv = 1; 1367 } else { 1368 XauUnlockAuth (backup_name); 1369 lockStatus = LOCK_ERROR; 1370 if (old != NULL) { 1371 (void) fclose (old); 1372 old = NULL; 1373 } 1374 if (new != NULL) 1375 (void) fclose (new); 1376 } 1377#ifdef HAVE_MKSTEMP 1378 } else { 1379 (void) fclose (old); 1380#endif 1381 } 1382 } 1383 } 1384 if (lockStatus != LOCK_SUCCESS) { 1385 Debug ("can't lock auth file %s or backup %s\n", 1386 home_name, backup_name); 1387 LogError ("can't lock authorization file %s or backup %s\n", 1388 home_name, backup_name); 1389 return; 1390 } 1391 initAddrs (); 1392 doWrite = 1; 1393 Debug ("%d authorization protocols for %s\n", d->authNum, d->name); 1394 /* 1395 * Write MIT-MAGIC-COOKIE-1 authorization first, so that 1396 * R4 clients which only knew that, and used the first 1397 * matching entry will continue to function 1398 */ 1399 magicCookie = -1; 1400 for (i = 0; i < d->authNum; i++) 1401 { 1402 if (auths[i]->name_length == 18 && 1403 !strncmp (auths[i]->name, "MIT-MAGIC-COOKIE-1", 18)) 1404 { 1405 magicCookie = i; 1406 if (d->displayType.location == Local) 1407 writeLocalAuth (new, auths[i], d->name); 1408#ifdef XDMCP 1409 else 1410 writeRemoteAuth (new, auths[i], d->peer, d->peerlen, d->name); 1411#endif 1412 break; 1413 } 1414 } 1415 /* now write other authorizations */ 1416 for (i = 0; i < d->authNum; i++) 1417 { 1418 if (i != magicCookie) 1419 { 1420 data_len = auths[i]->data_length; 1421 /* client will just use default Kerberos cache, so don't 1422 * even write cache info into the authority file. 1423 */ 1424 if (auths[i]->name_length == 14 && 1425 !strncmp (auths[i]->name, "MIT-KERBEROS-5", 14)) 1426 auths[i]->data_length = 0; 1427 if (d->displayType.location == Local) 1428 writeLocalAuth (new, auths[i], d->name); 1429#ifdef XDMCP 1430 else 1431 writeRemoteAuth (new, auths[i], d->peer, d->peerlen, d->name); 1432#endif 1433 auths[i]->data_length = data_len; 1434 } 1435 } 1436 if (old) { 1437 if (fstat (fileno (old), &statb) != -1) 1438 chmod (new_name, (int) (statb.st_mode & 0777)); 1439 /*SUPPRESS 560*/ 1440 while ((entry = XauReadAuth (old))) { 1441 if (!checkEntry (entry)) 1442 { 1443 Debug ("Writing an entry\n"); 1444 writeAuth (new, entry); 1445 } 1446 XauDisposeAuth (entry); 1447 } 1448 fclose (old); 1449 } 1450 doneAddrs (); 1451 fclose (new); 1452 if (unlink (name) == -1) 1453 if (errno != ENOENT) 1454 LogError ("cannot remove old authorization file %s: %s\n", 1455 name, _SysErrorMsg (errno)); 1456 envname = name; 1457 if (link (new_name, name) == -1) { 1458 LogError ("cannot link temporary authorization file %s to old " 1459 "location %s: %s\n", new_name, name, 1460 _SysErrorMsg (errno)); 1461 setenv = 1; 1462 envname = new_name; 1463 } else { 1464 Debug ("authorization file %s successfully updated\n", name); 1465 if (unlink (new_name)) 1466 if (errno != ENOENT) 1467 LogError ("cannot remove new authorization file %s:" 1468 " %s\n", new_name, _SysErrorMsg (errno)); 1469 } 1470 if (setenv) { 1471 verify->userEnviron = setEnv (verify->userEnviron, 1472 "XAUTHORITY", envname); 1473 verify->systemEnviron = setEnv (verify->systemEnviron, 1474 "XAUTHORITY", envname); 1475 } 1476 XauUnlockAuth (name); 1477 if (envname) 1478 chown (envname, verify->uid, verify->gid); 1479 } 1480 Debug ("done SetUserAuthorization\n"); 1481} 1482 1483void 1484RemoveUserAuthorization (struct display *d, struct verify_info *verify) 1485{ 1486 char *home; 1487 Xauth **auths, *entry; 1488 char name[1024], new_name[1024]; 1489 int lockStatus; 1490 FILE *old, *new; 1491 struct stat statb; 1492 int i; 1493 1494 if (!(auths = d->authorizations)) 1495 return; 1496 home = getEnv (verify->userEnviron, "HOME"); 1497 if (!home) 1498 return; 1499 Debug ("RemoveUserAuthorization\n"); 1500 snprintf(name, sizeof(name), "%s/.Xauthority", home); 1501 Debug ("XauLockAuth %s\n", name); 1502 lockStatus = XauLockAuth (name, 1, 2, 10); 1503 Debug ("Lock is %d\n", lockStatus); 1504 if (lockStatus != LOCK_SUCCESS) 1505 return; 1506 old = NULL; 1507 if (openFiles (name, new_name, &old, &new)) 1508 { 1509 initAddrs (); 1510 doWrite = 0; 1511 for (i = 0; i < d->authNum; i++) 1512 { 1513 if (d->displayType.location == Local) 1514 writeLocalAuth (new, auths[i], d->name); 1515#ifdef XDMCP 1516 else 1517 writeRemoteAuth (new, auths[i], d->peer, d->peerlen, d->name); 1518#endif 1519 } 1520 doWrite = 1; 1521 if (old) { 1522 if (fstat (fileno (old), &statb) != -1) 1523 chmod (new_name, (int) (statb.st_mode & 0777)); 1524 /*SUPPRESS 560*/ 1525 while ((entry = XauReadAuth (old))) { 1526 if (!checkEntry (entry)) 1527 { 1528 Debug ("Writing an entry\n"); 1529 writeAuth (new, entry); 1530 } 1531 XauDisposeAuth (entry); 1532 } 1533 fclose (old); 1534 } 1535 doneAddrs (); 1536 fclose (new); 1537 if (unlink (name) == -1) 1538 if (errno != ENOENT) 1539 LogError ("cannot remove new authorization file %s: %s\n", 1540 name, _SysErrorMsg (errno)); 1541 if (link (new_name, name) == -1) { 1542 LogError ("cannot link temporary authorization file %s to old " 1543 "location %s: %s\n", new_name, name, 1544 _SysErrorMsg (errno)); 1545 } else { 1546 Debug ("authorization file %s successfully updated\n", name); 1547 if (unlink (new_name)) 1548 if (errno != ENOENT) 1549 LogError ("cannot remove new authorization file %s:" 1550 " %s\n", new_name, _SysErrorMsg (errno)); 1551 } 1552 } 1553 XauUnlockAuth (name); 1554} 1555