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