xhost.c revision fb23d3a8
1/* $Xorg: xhost.c,v 1.4 2001/02/09 02:05:46 xorgcvs Exp $ */ 2/* $XdotOrg: app/xhost/xhost.c,v 1.4 2005/06/18 08:03:35 alanc Exp $ */ 3/* 4 5Copyright 1985, 1986, 1987, 1998 The Open Group 6Copyright 2004 Sun Microsystems, Inc. 7 8All rights reserved. 9 10Permission is hereby granted, free of charge, to any person obtaining a 11copy of this software and associated documentation files (the 12"Software"), to deal in the Software without restriction, including 13without limitation the rights to use, copy, modify, merge, publish, 14distribute, and/or sell copies of the Software, and to permit persons 15to whom the Software is furnished to do so, provided that the above 16copyright notice(s) and this permission notice appear in all copies of 17the Software and that both the above copyright notice(s) and this 18permission notice appear in supporting documentation. 19 20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 21OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 23OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 24HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL 25INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING 26FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 27NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 28WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 29 30Except as contained in this notice, the name of a copyright holder 31shall not be used in advertising or otherwise to promote the sale, use 32or other dealings in this Software without prior written authorization 33of the copyright holder. 34 35X Window System is a trademark of The Open Group. 36 37*/ 38/* $XFree86: xc/programs/xhost/xhost.c,v 3.26 2003/07/27 14:05:45 herrb Exp $ */ 39 40#ifdef HAVE_CONFIG_H 41#include "config.h" 42#endif 43 44#if defined(TCPCONN) || defined(STREAMSCONN) 45#define NEEDSOCKETS 46#endif 47#ifdef UNIXCONN 48#define NEEDSOCKETS 49#endif 50#ifdef DNETCONN 51#define NEEDSOCKETS 52#endif 53 54#include <X11/Xlib.h> 55#include <X11/Xos.h> 56#include <X11/Xproto.h> 57#include <X11/Xfuncs.h> 58#include <stdio.h> 59#include <stdlib.h> 60#include <signal.h> 61#ifdef X_NOT_POSIX 62#include <setjmp.h> 63#endif 64#include <ctype.h> 65#include <X11/Xauth.h> 66#include <X11/Xmu/Error.h> 67#include <stdlib.h> 68 69#ifdef NEEDSOCKETS 70#ifdef att 71typedef unsigned short unsign16; 72typedef unsigned long unsign32; 73typedef short sign16; 74typedef long sign32; 75#include <interlan/socket.h> 76#include <interlan/netdb.h> 77#include <interlan/in.h> 78#else 79#ifndef Lynx 80#include <sys/socket.h> 81#else 82#include <socket.h> 83#endif 84#include <netdb.h> 85#include <netinet/in.h> 86#endif 87#endif /* NEEDSOCKETS */ 88 89#ifndef BAD_ARPAINET 90#include <arpa/inet.h> 91#else 92/* bogus definition of inet_makeaddr() in BSD 4.2 and Ultrix */ 93extern unsigned long inet_makeaddr(); 94#endif 95 96#ifdef DNETCONN 97#include <netdnet/dn.h> 98#include <netdnet/dnetdb.h> 99#endif 100 101#ifdef SECURE_RPC 102#include <pwd.h> 103#include <rpc/rpc.h> 104#ifdef X_POSIX_C_SOURCE 105#define _POSIX_C_SOURCE X_POSIX_C_SOURCE 106#include <limits.h> 107#undef _POSIX_C_SOURCE 108#else 109#if defined(X_NOT_POSIX) || defined(_POSIX_SOURCE) 110#include <limits.h> 111#else 112#define _POSIX_SOURCE 113#include <limits.h> 114#undef _POSIX_SOURCE 115#endif 116#endif 117#ifndef NGROUPS_MAX 118#include <sys/param.h> 119#define NGROUPS_MAX NGROUPS 120#endif 121#ifdef sun 122/* Go figure, there's no getdomainname() prototype available */ 123extern int getdomainname(char *name, size_t len); 124#endif 125#endif 126 127static int change_host(Display *dpy, char *name, Bool add); 128static char *get_hostname(XHostAddress *ha); 129static int local_xerror(Display *dpy, XErrorEvent *rep); 130 131#ifdef RETSIGTYPE /* autoconf AC_TYPE_SIGNAL */ 132# define signal_t RETSIGTYPE 133#else /* Imake */ 134#ifdef SIGNALRETURNSINT 135#define signal_t int 136#else 137#define signal_t void 138#endif 139#endif /* RETSIGTYPE */ 140static signal_t nameserver_lost(int sig); 141 142#define NAMESERVER_TIMEOUT 5 /* time to wait for nameserver */ 143 144static volatile int nameserver_timedout; 145 146static char *ProgramName; 147 148#ifdef NEEDSOCKETS 149static int 150XFamily(int af) 151{ 152 int i; 153 static struct _familyMap { 154 int af, xf; 155 } familyMap[] = { 156#ifdef AF_DECnet 157 { AF_DECnet, FamilyDECnet }, 158#endif 159#ifdef AF_CHAOS 160 { AF_CHAOS, FamilyChaos }, 161#endif 162#ifdef AF_INET 163 { AF_INET, FamilyInternet }, 164#if defined(IPv6) && defined(AF_INET6) 165 { AF_INET6, FamilyInternet6 }, 166#endif 167#endif 168}; 169 170#define FAMILIES ((sizeof familyMap)/(sizeof familyMap[0])) 171 172 for (i = 0; i < FAMILIES; i++) 173 if (familyMap[i].af == af) return familyMap[i].xf; 174 return -1; 175} 176#endif /* NEEDSOCKETS */ 177 178static Display *dpy; 179 180int 181main(int argc, char *argv[]) 182{ 183 register char *arg; 184 int i, nhosts = 0; 185 char *hostname; 186 int nfailed = 0; 187 XHostAddress *list; 188 Bool enabled = False; 189#ifdef DNETCONN 190 char *dnet_htoa(); 191 struct nodeent *np; 192 struct dn_naddr *nlist, dnaddr, *dnaddrp, *dnet_addr(); 193 char *cp; 194#endif 195 196 ProgramName = argv[0]; 197 198 if ((dpy = XOpenDisplay(NULL)) == NULL) { 199 fprintf(stderr, "%s: unable to open display \"%s\"\n", 200 ProgramName, XDisplayName (NULL)); 201 exit(1); 202 } 203 204 XSetErrorHandler(local_xerror); 205 206 207 if (argc == 1) { 208#ifdef DNETCONN 209 setnodeent(1); /* keep the database accessed */ 210#endif 211 sethostent(1); /* don't close the data base each time */ 212 list = XListHosts(dpy, &nhosts, &enabled); 213 if (enabled) 214 printf ("access control enabled, only authorized clients can connect\n"); 215 else 216 printf ("access control disabled, clients can connect from any host\n"); 217 218 if (nhosts != 0) { 219 for (i = 0; i < nhosts; i++ ) { 220 hostname = get_hostname(&list[i]); 221 if (hostname) { 222 switch (list[i].family) { 223 case FamilyInternet: 224 printf("INET:"); 225 break; 226 case FamilyInternet6: 227 printf("INET6:"); 228 break; 229 case FamilyDECnet: 230 printf("DNET:"); 231 break; 232 case FamilyNetname: 233 printf("NIS:"); 234 break; 235 case FamilyKrb5Principal: 236 printf("KRB:"); 237 break; 238 case FamilyLocalHost: 239 printf("LOCAL:"); 240 break; 241 case FamilyServerInterpreted: 242 printf("SI:"); 243 break; 244 default: 245 printf("<unknown family type %d>:", list[i].family); 246 break; 247 } 248 printf ("%s", hostname); 249 } else { 250 printf ("<unknown address in family %d>", 251 list[i].family); 252 } 253 if (nameserver_timedout) { 254 printf("\t(no nameserver response within %d seconds)\n", 255 NAMESERVER_TIMEOUT); 256 nameserver_timedout = 0; 257 } else 258 printf("\n"); 259 } 260 free(list); 261 endhostent(); 262 } 263 exit(0); 264 } 265 266 if (argc == 2 && !strcmp(argv[1], "-help")) { 267 fprintf(stderr, "usage: %s [[+-]hostname ...]\n", argv[0]); 268 exit(1); 269 } 270 271 for (i = 1; i < argc; i++) { 272 arg = argv[i]; 273 if (*arg == '-') { 274 275 if (!argv[i][1] && ((i+1) == argc)) { 276 printf ("access control enabled, only authorized clients can connect\n"); 277 XEnableAccessControl(dpy); 278 } else { 279 arg = argv[i][1]? &argv[i][1] : argv[++i]; 280 if (!change_host (dpy, arg, False)) { 281 fprintf (stderr, "%s: bad hostname \"%s\"\n", 282 ProgramName, arg); 283 nfailed++; 284 } 285 } 286 } else { 287 if (*arg == '+' && !argv[i][1] && ((i+1) == argc)) { 288 printf ("access control disabled, clients can connect from any host\n"); 289 XDisableAccessControl(dpy); 290 } else { 291 if (*arg == '+') { 292 arg = argv[i][1]? &argv[i][1] : argv[++i]; 293 } 294 if (!change_host (dpy, arg, True)) { 295 fprintf (stderr, "%s: bad hostname \"%s\"\n", 296 ProgramName, arg); 297 nfailed++; 298 } 299 } 300 } 301 } 302 XCloseDisplay (dpy); /* does an XSync first */ 303 exit(nfailed); 304} 305 306 307 308/* 309 * change_host - edit the list of hosts that may connect to the server; 310 * it parses DECnet names (expo::), Internet addresses (18.30.0.212), or 311 * Internet names (expo.lcs.mit.edu); if 4.3bsd macro h_addr is defined 312 * (from <netdb.h>), it will add or remove all addresses with the given 313 * address. 314 */ 315 316static int 317change_host(Display *dpy, char *name, Bool add) 318{ 319 XHostAddress ha; 320 char *lname; 321 int namelen, i, family = FamilyWild; 322#ifdef K5AUTH 323 krb5_principal princ; 324 krb5_data kbuf; 325#endif 326#ifdef NEEDSOCKETS 327 static struct in_addr addr; /* so we can point at it */ 328#if defined(IPv6) && defined(AF_INET6) 329 static struct in6_addr addr6; /* so we can point at it */ 330#else 331 struct hostent *hp; 332#endif 333#endif 334 char *cp; 335#ifdef DNETCONN 336 struct dn_naddr *dnaddrp; 337 struct nodeent *np; 338 static struct dn_naddr dnaddr; 339#endif /* DNETCONN */ 340 static char *add_msg = "being added to access control list"; 341 static char *remove_msg = "being removed from access control list"; 342 343 namelen = strlen(name); 344 if ((lname = (char *)malloc(namelen+1)) == NULL) { 345 fprintf (stderr, "%s: malloc bombed in change_host\n", ProgramName); 346 exit (1); 347 } 348 for (i = 0; i < namelen; i++) { 349 lname[i] = tolower(name[i]); 350 } 351 lname[namelen] = '\0'; 352 if (!strncmp("inet:", lname, 5)) { 353#if defined(TCPCONN) || defined(STREAMSCONN) 354 family = FamilyInternet; 355 name += 5; 356#else 357 fprintf (stderr, "%s: not compiled for TCP/IP\n", ProgramName); 358 free(lname); 359 return 0; 360#endif 361 } 362 else if (!strncmp("inet6:", lname, 6)) { 363#if (defined(TCPCONN) || defined(STREAMSCONN)) && \ 364 defined(IPv6) && defined(AF_INET6) 365 family = FamilyInternet6; 366 name += 6; 367#else 368 fprintf (stderr, "%s: not compiled for IPv6\n", ProgramName); 369 free(lname); 370 return 0; 371#endif 372 } 373#ifdef ACCEPT_INETV6 /* Allow inetv6 as an alias for inet6 for compatibility 374 with original X11 over IPv6 draft. */ 375 else if (!strncmp("inetv6:", lname, 7)) { 376#if (defined(TCPCONN) || defined(STREAMSCONN)) && \ 377 defined(IPv6) && defined(AF_INET6) 378 family = FamilyInternet6; 379 name += 7; 380#else 381 fprintf (stderr, "%s: not compiled for IPv6\n", ProgramName); 382 free(lname); 383 return 0; 384#endif 385 } 386#endif /* ACCEPT_INETV6 */ 387 else if (!strncmp("dnet:", lname, 5)) { 388#ifdef DNETCONN 389 family = FamilyDECnet; 390 name += 5; 391#else 392 fprintf (stderr, "%s: not compiled for DECnet\n", ProgramName); 393 free(lname); 394 return 0; 395#endif 396 } 397 else if (!strncmp("nis:", lname, 4)) { 398#ifdef SECURE_RPC 399 family = FamilyNetname; 400 name += 4; 401#else 402 fprintf (stderr, "%s: not compiled for Secure RPC\n", ProgramName); 403 free(lname); 404 return 0; 405#endif 406 } 407 else if (!strncmp("krb:", lname, 4)) { 408#ifdef K5AUTH 409 family = FamilyKrb5Principal; 410 name +=4; 411#else 412 fprintf (stderr, "%s: not compiled for Kerberos 5\n", ProgramName); 413 free(lname); 414 return 0; 415#endif 416 } 417 else if (!strncmp("local:", lname, 6)) { 418 family = FamilyLocalHost; 419 } 420 else if (!strncmp("si:", lname, 3)) { 421 family = FamilyServerInterpreted; 422 name += 3; 423 } 424 if (family == FamilyWild && (cp = strchr(lname, ':'))) { 425 *cp = '\0'; 426 fprintf (stderr, "%s: unknown address family \"%s\"\n", 427 ProgramName, lname); 428 free(lname); 429 return 0; 430 } 431 free(lname); 432 433 if (family == FamilyServerInterpreted) { 434 XServerInterpretedAddress siaddr; 435 int namelen; 436 437 cp = strchr(name, ':'); 438 if (cp == NULL || cp == name) { 439 fprintf(stderr, 440 "%s: type must be specified for server interpreted family \"%s\"\n", 441 ProgramName, name); 442 return 0; 443 } 444 ha.family = FamilyServerInterpreted; 445 ha.address = (char *) &siaddr; 446 namelen = strlen(name); 447 siaddr.type = malloc(namelen); 448 if (siaddr.type == NULL) { 449 return 0; 450 } 451 memcpy(siaddr.type, name, namelen); 452 siaddr.typelength = cp - name; 453 siaddr.type[siaddr.typelength] = '\0'; 454 siaddr.value = siaddr.type + siaddr.typelength + 1; 455 siaddr.valuelength = namelen - (siaddr.typelength + 1); 456 if (add) 457 XAddHost(dpy, &ha); 458 else 459 XRemoveHost(dpy, &ha); 460 free(siaddr.type); 461 printf( "%s %s\n", name, add ? add_msg : remove_msg); 462 return 1; 463 } 464 465#ifdef DNETCONN 466 if (family == FamilyDECnet || ((family == FamilyWild) && 467 (cp = strchr(name, ':')) && (*(cp + 1) == ':') && 468 !(*cp = '\0'))) { 469 ha.family = FamilyDECnet; 470 if (dnaddrp = dnet_addr(name)) { 471 dnaddr = *dnaddrp; 472 } else { 473 if ((np = getnodebyname (name)) == NULL) { 474 fprintf (stderr, "%s: unable to get node name for \"%s::\"\n", 475 ProgramName, name); 476 return 0; 477 } 478 dnaddr.a_len = np->n_length; 479 memmove( dnaddr.a_addr, np->n_addr, np->n_length); 480 } 481 ha.length = sizeof(struct dn_naddr); 482 ha.address = (char *)&dnaddr; 483 if (add) { 484 XAddHost (dpy, &ha); 485 printf ("%s:: %s\n", name, add_msg); 486 } else { 487 XRemoveHost (dpy, &ha); 488 printf ("%s:: %s\n", name, remove_msg); 489 } 490 return 1; 491 } 492#endif /* DNETCONN */ 493#ifdef K5AUTH 494 if (family == FamilyKrb5Principal) { 495 krb5_error_code retval; 496 497 retval = krb5_parse_name(name, &princ); 498 if (retval) { 499 krb5_init_ets(); /* init krb errs for error_message() */ 500 fprintf(stderr, "%s: cannot parse Kerberos name: %s\n", 501 ProgramName, error_message(retval)); 502 return 0; 503 } 504 XauKrb5Encode(princ, &kbuf); 505 ha.length = kbuf.length; 506 ha.address = kbuf.data; 507 ha.family = family; 508 if (add) 509 XAddHost(dpy, &ha); 510 else 511 XRemoveHost(dpy, &ha); 512 krb5_free_principal(princ); 513 free(kbuf.data); 514 printf( "%s %s\n", name, add ? add_msg : remove_msg); 515 return 1; 516 } 517#endif 518 if (family == FamilyLocalHost) { 519 ha.length = 0; 520 ha.address = ""; 521 ha.family = family; 522 if (add) 523 XAddHost(dpy, &ha); 524 else 525 XRemoveHost(dpy, &ha); 526 printf( "non-network local connections %s\n", add ? add_msg : remove_msg); 527 return 1; 528 } 529 /* 530 * If it has an '@', it's a netname 531 */ 532 if ((family == FamilyNetname && (cp = strchr(name, '@'))) || 533 (cp = strchr(name, '@'))) { 534 char *netname = name; 535#ifdef SECURE_RPC 536 static char username[MAXNETNAMELEN]; 537 538 if (!cp[1]) { 539 struct passwd *pwd; 540 static char domainname[128]; 541 542 *cp = '\0'; 543 pwd = getpwnam(name); 544 if (!pwd) { 545 fprintf(stderr, "no such user \"%s\"\n", name); 546 return 0; 547 } 548 getdomainname(domainname, sizeof(domainname)); 549 if (!user2netname(username, pwd->pw_uid, domainname)) { 550 fprintf(stderr, "failed to get netname for \"%s\"\n", name); 551 return 0; 552 } 553 netname = username; 554 } 555#endif 556 ha.family = FamilyNetname; 557 ha.length = strlen(netname); 558 ha.address = netname; 559 if (add) 560 XAddHost (dpy, &ha); 561 else 562 XRemoveHost (dpy, &ha); 563 if (netname != name) 564 printf ("%s@ (%s) %s\n", name, netname, add ? add_msg : remove_msg); 565 else 566 printf ("%s %s\n", netname, add ? add_msg : remove_msg); 567 return 1; 568 } 569#ifdef NEEDSOCKETS 570 /* 571 * First see if inet_addr() can grok the name; if so, then use it. 572 */ 573 if (((family == FamilyWild) || (family == FamilyInternet)) && 574 ((addr.s_addr = inet_addr(name)) != -1)) { 575 ha.family = FamilyInternet; 576 ha.length = 4; /* but for Cray would be sizeof(addr.s_addr) */ 577 ha.address = (char *)&addr; /* but for Cray would be &addr.s_addr */ 578 if (add) { 579 XAddHost (dpy, &ha); 580 printf ("%s %s\n", name, add_msg); 581 } else { 582 XRemoveHost (dpy, &ha); 583 printf ("%s %s\n", name, remove_msg); 584 } 585 return 1; 586 } 587#if defined(IPv6) && defined(AF_INET6) 588 /* 589 * Check to see if inet_pton() can grok it as an IPv6 address 590 */ 591 else if (((family == FamilyWild) || (family == FamilyInternet6)) && 592 (inet_pton(AF_INET6, name, &addr6.s6_addr) == 1)) { 593 ha.family = FamilyInternet6; 594 ha.length = sizeof(addr6.s6_addr); 595 ha.address = (char *) &addr6.s6_addr; 596 if (add) { 597 XAddHost (dpy, &ha); 598 printf ("%s %s\n", name, add_msg); 599 } else { 600 XRemoveHost (dpy, &ha); 601 printf ("%s %s\n", name, remove_msg); 602 } 603 return 1; 604 } else { 605 /* 606 * Is it in the namespace? 607 * 608 * If no family was specified, use both Internet v4 & v6 addresses. 609 * Otherwise, use only addresses matching specified family. 610 */ 611 struct addrinfo *addresses; 612 struct addrinfo *a; 613 Bool didit = False; 614 615 if (getaddrinfo(name, NULL, NULL, &addresses) != 0) 616 return 0; 617 618 for (a = addresses; a != NULL; a = a->ai_next) { 619 if ( ((a->ai_family == AF_INET) && (family != FamilyInternet6)) 620 || ((a->ai_family == AF_INET6) && (family != FamilyInternet)) ) { 621 char ad[INET6_ADDRSTRLEN]; 622 ha.family = XFamily(a->ai_family); 623 if (a->ai_family == AF_INET6) { 624 ha.address = (char *) 625 &((struct sockaddr_in6 *) a->ai_addr)->sin6_addr; 626 ha.length = 627 sizeof (((struct sockaddr_in6 *) a->ai_addr)->sin6_addr); 628 } else { 629 ha.address = (char *) 630 &((struct sockaddr_in *) a->ai_addr)->sin_addr; 631 ha.length = 632 sizeof (((struct sockaddr_in *) a->ai_addr)->sin_addr); 633 } 634 inet_ntop(a->ai_family, ha.address, ad, sizeof(ad)); 635 /* printf("Family: %d\nLength: %d\n", a->ai_family, ha.length); */ 636 /* printf("Address: %s\n", ad); */ 637 638 if (add) { 639 XAddHost (dpy, &ha); 640 } else { 641 XRemoveHost (dpy, &ha); 642 } 643 didit = True; 644 } 645 } 646 if (didit == True) { 647 printf ("%s %s\n", name, add ? add_msg : remove_msg); 648 } else { 649 const char *familyMsg = ""; 650 651 if (family == FamilyInternet6) { 652 familyMsg = "inet6 "; 653 } else if (family == FamilyInternet) { 654 familyMsg = "inet "; 655 } 656 657 fprintf(stderr, "%s: unable to get %saddress for \"%s\"\n", 658 ProgramName, familyMsg, name); 659 } 660 freeaddrinfo(addresses); 661 return 1; 662 } 663#else /* !IPv6 */ 664 /* 665 * Is it in the namespace? 666 */ 667 else if (((hp = gethostbyname(name)) == (struct hostent *)NULL) 668 || hp->h_addrtype != AF_INET) { 669 return 0; 670 } else { 671 ha.family = XFamily(hp->h_addrtype); 672 ha.length = hp->h_length; 673#ifdef h_addr /* new 4.3bsd version of gethostent */ 674 { 675 char **list; 676 677 /* iterate over the hosts */ 678 for (list = hp->h_addr_list; *list; list++) { 679 ha.address = *list; 680 if (add) { 681 XAddHost (dpy, &ha); 682 } else { 683 XRemoveHost (dpy, &ha); 684 } 685 } 686 } 687#else 688 ha.address = hp->h_addr; 689 if (add) { 690 XAddHost (dpy, &ha); 691 } else { 692 XRemoveHost (dpy, &ha); 693 } 694#endif 695 printf ("%s %s\n", name, add ? add_msg : remove_msg); 696 return 1; 697 } 698#endif /* IPv6 */ 699#else /* NEEDSOCKETS */ 700 return 0; 701#endif /* NEEDSOCKETS */ 702} 703 704 705/* 706 * get_hostname - Given an internet address, return a name (CHARON.MIT.EDU) 707 * or a string representing the address (18.58.0.13) if the name cannot 708 * be found. 709 */ 710 711#ifdef X_NOT_POSIX 712jmp_buf env; 713#endif 714 715static char * 716get_hostname(XHostAddress *ha) 717{ 718#if (defined(TCPCONN) || defined(STREAMSCONN)) && \ 719 (!defined(IPv6) || !defined(AF_INET6)) 720 static struct hostent *hp = NULL; 721#endif 722#ifdef DNETCONN 723 struct nodeent *np; 724 static char nodeaddr[5 + 2 * DN_MAXADDL]; 725#endif /* DNETCONN */ 726#ifdef K5AUTH 727 krb5_principal princ; 728 krb5_data kbuf; 729 char *kname; 730 static char kname_out[255]; 731#endif 732#ifndef X_NOT_POSIX 733 struct sigaction sa; 734#endif 735 736#if defined(TCPCONN) || defined(STREAMSCONN) 737#if defined(IPv6) && defined(AF_INET6) 738 if ((ha->family == FamilyInternet) || (ha->family == FamilyInternet6)) { 739 struct sockaddr_storage saddr; 740 static char inetname[NI_MAXHOST]; 741 int saddrlen; 742 743 inetname[0] = '\0'; 744 memset(&saddr, 0, sizeof saddr); 745 if (ha->family == FamilyInternet) { 746 struct sockaddr_in *sin = (struct sockaddr_in *) &saddr; 747#ifdef BSD44SOCKETS 748 sin->sin_len = sizeof(struct sockaddr_in); 749#endif 750 sin->sin_family = AF_INET; 751 sin->sin_port = 0; 752 memcpy(&sin->sin_addr, ha->address, sizeof(sin->sin_addr)); 753 saddrlen = sizeof(struct sockaddr_in); 754 } else { 755 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &saddr; 756#ifdef SIN6_LEN 757 sin6->sin6_len = sizeof(struct sockaddr_in6); 758#endif 759 sin6->sin6_family = AF_INET6; 760 sin6->sin6_port = 0; 761 memcpy(&sin6->sin6_addr, ha->address, sizeof(sin6->sin6_addr)); 762 saddrlen = sizeof(struct sockaddr_in6); 763 } 764 765 /* gethostbyaddr can take a LONG time if the host does not exist. 766 Assume that if it does not respond in NAMESERVER_TIMEOUT seconds 767 that something is wrong and do not make the user wait. 768 gethostbyaddr will continue after a signal, so we have to 769 jump out of it. 770 */ 771#ifndef X_NOT_POSIX 772 memset(&sa, 0, sizeof sa); 773 sa.sa_handler = nameserver_lost; 774 sa.sa_flags = 0; /* don't restart syscalls */ 775 sigaction(SIGALRM, &sa, NULL); 776#else 777 signal(SIGALRM, nameserver_lost); 778#endif 779 alarm(NAMESERVER_TIMEOUT); 780#ifdef X_NOT_POSIX 781 if (setjmp(env) == 0) 782#endif 783 { 784 getnameinfo((struct sockaddr *) &saddr, saddrlen, inetname, 785 sizeof(inetname), NULL, 0, 0); 786 } 787 alarm(0); 788 if (nameserver_timedout || inetname[0] == '\0') 789 inet_ntop(((struct sockaddr *)&saddr)->sa_family, ha->address, 790 inetname, sizeof(inetname)); 791 return inetname; 792 } 793#else 794 if (ha->family == FamilyInternet) { 795#ifdef CRAY 796 struct in_addr t_addr; 797 bzero((char *)&t_addr, sizeof(t_addr)); 798 bcopy(ha->address, (char *)&t_addr, 4); 799 ha->address = (char *)&t_addr; 800#endif 801 /* gethostbyaddr can take a LONG time if the host does not exist. 802 Assume that if it does not respond in NAMESERVER_TIMEOUT seconds 803 that something is wrong and do not make the user wait. 804 gethostbyaddr will continue after a signal, so we have to 805 jump out of it. 806 */ 807#ifndef X_NOT_POSIX 808 memset(&sa, 0, sizeof sa); 809 sa.sa_handler = nameserver_lost; 810 sa.sa_flags = 0; /* don't restart syscalls */ 811 sigaction(SIGALRM, &sa, NULL); 812#else 813 signal(SIGALRM, nameserver_lost); 814#endif 815 alarm(4); 816#ifdef X_NOT_POSIX 817 if (setjmp(env) == 0) { 818#endif 819 hp = gethostbyaddr (ha->address, ha->length, AF_INET); 820#ifdef X_NOT_POSIX 821 } 822#endif 823 alarm(0); 824 if (hp) 825 return (hp->h_name); 826 else return (inet_ntoa(*((struct in_addr *)(ha->address)))); 827 } 828#endif /* IPv6 */ 829#endif 830 if (ha->family == FamilyNetname) { 831 static char netname[512]; 832 int len; 833#ifdef SECURE_RPC 834 int gidlen; 835 uid_t uid; 836 gid_t gid, gidlist[NGROUPS_MAX]; 837#endif 838 839 if (ha->length < sizeof(netname) - 1) 840 len = ha->length; 841 else 842 len = sizeof(netname) - 1; 843 memmove( netname, ha->address, len); 844 netname[len] = '\0'; 845#ifdef SECURE_RPC 846 if (netname2user(netname, &uid, &gid, &gidlen, gidlist)) { 847 struct passwd *pwd; 848 849 pwd = getpwuid(uid); 850 if (pwd) 851 sprintf(netname, "%s@ (%*.*s)", pwd->pw_name, 852 ha->length, ha->length, ha->address); 853 } 854#endif 855 return (netname); 856 } 857#ifdef DNETCONN 858 if (ha->family == FamilyDECnet) { 859 struct dn_naddr *addr_ptr = (struct dn_naddr *) ha->address; 860 861 if (np = getnodebyaddr(addr_ptr->a_addr, addr_ptr->a_len, AF_DECnet)) { 862 sprintf(nodeaddr, "%s", np->n_name); 863 } else { 864 sprintf(nodeaddr, "%s", dnet_htoa(ha->address)); 865 } 866 return(nodeaddr); 867 } 868#endif 869#ifdef K5AUTH 870 if (ha->family == FamilyKrb5Principal) { 871 kbuf.data = ha->address; 872 kbuf.length = ha->length; 873 XauKrb5Decode(kbuf, &princ); 874 krb5_unparse_name(princ, &kname); 875 krb5_free_principal(princ); 876 strncpy(kname_out, kname, sizeof (kname_out)); 877 free(kname); 878 return kname_out; 879 } 880#endif 881 if (ha->family == FamilyLocalHost) { 882 return ""; 883 } 884 if (ha->family == FamilyServerInterpreted) { 885 XServerInterpretedAddress *sip; 886 static char *addressString; 887 static size_t addressStringSize; 888 size_t neededSize; 889 890 sip = (XServerInterpretedAddress *) ha->address; 891 neededSize = sip->typelength + sip->valuelength + 2; 892 893 if (addressStringSize < neededSize) { 894 if (addressString != NULL) { 895 free(addressString); 896 } 897 addressStringSize = neededSize; 898 addressString = malloc(addressStringSize); 899 } 900 if (addressString != NULL) { 901 char *cp = addressString; 902 903 memcpy(cp, sip->type, sip->typelength); 904 cp += sip->typelength; 905 *cp++ = ':'; 906 memcpy(cp, sip->value, sip->valuelength); 907 cp += sip->valuelength; 908 *cp = '\0'; 909 } 910 return addressString; 911 } 912 return (NULL); 913} 914 915/*ARGUSED*/ 916static signal_t 917nameserver_lost(int sig) 918{ 919 nameserver_timedout = 1; 920#ifdef X_NOT_POSIX 921 /* not needed with POSIX signals - stuck syscalls will not 922 be restarted after signal delivery */ 923 longjmp(env, -1); 924#endif 925} 926 927/* 928 * local_xerror - local non-fatal error handling routine. If the error was 929 * that an X_GetHosts request for an unknown address format was received, just 930 * return, otherwise print the normal error message and continue. 931 */ 932static int 933local_xerror(Display *dpy, XErrorEvent *rep) 934{ 935 if ((rep->error_code == BadAccess) && (rep->request_code == X_ChangeHosts)) { 936 fprintf (stderr, 937 "%s: must be on local machine to add or remove hosts.\n", 938 ProgramName); 939 return 1; 940 } else if ((rep->error_code == BadAccess) && 941 (rep->request_code == X_SetAccessControl)) { 942 fprintf (stderr, 943 "%s: must be on local machine to enable or disable access control.\n", 944 ProgramName); 945 return 1; 946 } else if ((rep->error_code == BadValue) && 947 (rep->request_code == X_ListHosts)) { 948 return 1; 949 } 950 951 XmuPrintDefaultErrorMessage (dpy, rep, stderr); 952 return 0; 953} 954 955#ifdef __CYGWIN__ 956void sethostent(int x) 957{} 958 959void endhostent() 960{} 961#endif 962 963