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