xhost.c revision aadd013e
1169a0819Smrg/* 2169a0819Smrg * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. 3169a0819Smrg * 4169a0819Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5169a0819Smrg * copy of this software and associated documentation files (the "Software"), 6169a0819Smrg * to deal in the Software without restriction, including without limitation 7169a0819Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8169a0819Smrg * and/or sell copies of the Software, and to permit persons to whom the 9169a0819Smrg * Software is furnished to do so, subject to the following conditions: 10169a0819Smrg * 11169a0819Smrg * The above copyright notice and this permission notice (including the next 12169a0819Smrg * paragraph) shall be included in all copies or substantial portions of the 13169a0819Smrg * Software. 14169a0819Smrg * 15169a0819Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16169a0819Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17169a0819Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18169a0819Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19169a0819Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20169a0819Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21169a0819Smrg * DEALINGS IN THE SOFTWARE. 22169a0819Smrg */ 2364ce7165Smrg/* 2464ce7165Smrg 2564ce7165SmrgCopyright 1985, 1986, 1987, 1998 The Open Group 2664ce7165Smrg 2764ce7165SmrgAll rights reserved. 2864ce7165Smrg 2964ce7165SmrgPermission is hereby granted, free of charge, to any person obtaining a 3064ce7165Smrgcopy of this software and associated documentation files (the 3164ce7165Smrg"Software"), to deal in the Software without restriction, including 3264ce7165Smrgwithout limitation the rights to use, copy, modify, merge, publish, 3364ce7165Smrgdistribute, and/or sell copies of the Software, and to permit persons 3464ce7165Smrgto whom the Software is furnished to do so, provided that the above 3564ce7165Smrgcopyright notice(s) and this permission notice appear in all copies of 3664ce7165Smrgthe Software and that both the above copyright notice(s) and this 3764ce7165Smrgpermission notice appear in supporting documentation. 3864ce7165Smrg 3964ce7165SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 4064ce7165SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 4164ce7165SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 4264ce7165SmrgOF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 4364ce7165SmrgHOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL 4464ce7165SmrgINDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING 4564ce7165SmrgFROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 4664ce7165SmrgNEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 4764ce7165SmrgWITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 4864ce7165Smrg 4964ce7165SmrgExcept as contained in this notice, the name of a copyright holder 5064ce7165Smrgshall not be used in advertising or otherwise to promote the sale, use 5164ce7165Smrgor other dealings in this Software without prior written authorization 5264ce7165Smrgof the copyright holder. 5364ce7165Smrg 5464ce7165SmrgX Window System is a trademark of The Open Group. 5564ce7165Smrg 5664ce7165Smrg*/ 5764ce7165Smrg 5864ce7165Smrg#ifdef HAVE_CONFIG_H 5964ce7165Smrg#include "config.h" 6064ce7165Smrg#endif 6164ce7165Smrg 6281440437Smrg#ifdef TCPCONN 6364ce7165Smrg#define NEEDSOCKETS 6464ce7165Smrg#endif 6564ce7165Smrg#ifdef UNIXCONN 6664ce7165Smrg#define NEEDSOCKETS 6764ce7165Smrg#endif 6864ce7165Smrg 6964ce7165Smrg#include <X11/Xlib.h> 7064ce7165Smrg#include <X11/Xos.h> 7164ce7165Smrg#include <X11/Xproto.h> 7264ce7165Smrg#include <X11/Xfuncs.h> 7364ce7165Smrg#include <stdio.h> 7464ce7165Smrg#include <stdlib.h> 7564ce7165Smrg#include <signal.h> 7664ce7165Smrg#include <ctype.h> 7764ce7165Smrg#include <X11/Xauth.h> 7864ce7165Smrg#include <X11/Xmu/Error.h> 7964ce7165Smrg#include <stdlib.h> 8064ce7165Smrg 8164ce7165Smrg#ifdef NEEDSOCKETS 8281440437Smrg#ifdef WIN32 8381440437Smrg#include <X11/Xwinsock.h> 8464ce7165Smrg#else 8564ce7165Smrg#include <sys/socket.h> 8664ce7165Smrg#include <netdb.h> 8764ce7165Smrg#include <netinet/in.h> 8864ce7165Smrg#endif 8964ce7165Smrg#endif /* NEEDSOCKETS */ 9064ce7165Smrg 9181440437Smrg#ifndef WIN32 9264ce7165Smrg#include <arpa/inet.h> 9364ce7165Smrg#endif 9464ce7165Smrg 9564ce7165Smrg 9664ce7165Smrg#ifdef SECURE_RPC 9764ce7165Smrg#include <pwd.h> 9864ce7165Smrg#include <rpc/rpc.h> 9964ce7165Smrg#ifdef X_POSIX_C_SOURCE 10064ce7165Smrg#define _POSIX_C_SOURCE X_POSIX_C_SOURCE 10164ce7165Smrg#include <limits.h> 10264ce7165Smrg#undef _POSIX_C_SOURCE 10364ce7165Smrg#else 10481440437Smrg#ifdef _POSIX_SOURCE 10564ce7165Smrg#include <limits.h> 10664ce7165Smrg#else 10764ce7165Smrg#define _POSIX_SOURCE 10864ce7165Smrg#include <limits.h> 10964ce7165Smrg#undef _POSIX_SOURCE 11064ce7165Smrg#endif 11164ce7165Smrg#endif 11264ce7165Smrg#ifndef NGROUPS_MAX 11364ce7165Smrg#include <sys/param.h> 11464ce7165Smrg#define NGROUPS_MAX NGROUPS 11564ce7165Smrg#endif 11664ce7165Smrg#ifdef sun 11764ce7165Smrg/* Go figure, there's no getdomainname() prototype available */ 11864ce7165Smrgextern int getdomainname(char *name, size_t len); 11964ce7165Smrg#endif 12064ce7165Smrg#endif 12164ce7165Smrg 12264ce7165Smrgstatic int change_host(Display *dpy, char *name, Bool add); 1233544ea2eSmrgstatic const char *get_hostname(XHostAddress *ha); 12464ce7165Smrgstatic int local_xerror(Display *dpy, XErrorEvent *rep); 12581440437Smrgstatic void nameserver_lost(int sig); 12664ce7165Smrg 12764ce7165Smrg#define NAMESERVER_TIMEOUT 5 /* time to wait for nameserver */ 12864ce7165Smrg 129fb23d3a8Smrgstatic volatile int nameserver_timedout; 130fb23d3a8Smrg 131fb23d3a8Smrgstatic char *ProgramName; 13264ce7165Smrg 13364ce7165Smrg#ifdef NEEDSOCKETS 13464ce7165Smrgstatic int 13564ce7165SmrgXFamily(int af) 13664ce7165Smrg{ 13781440437Smrg unsigned int i; 13864ce7165Smrg static struct _familyMap { 13964ce7165Smrg int af, xf; 14064ce7165Smrg } familyMap[] = { 14164ce7165Smrg#ifdef AF_DECnet 14264ce7165Smrg { AF_DECnet, FamilyDECnet }, 14364ce7165Smrg#endif 14464ce7165Smrg#ifdef AF_CHAOS 14564ce7165Smrg { AF_CHAOS, FamilyChaos }, 14664ce7165Smrg#endif 14764ce7165Smrg#ifdef AF_INET 14864ce7165Smrg { AF_INET, FamilyInternet }, 14964ce7165Smrg#if defined(IPv6) && defined(AF_INET6) 15064ce7165Smrg { AF_INET6, FamilyInternet6 }, 15164ce7165Smrg#endif 15264ce7165Smrg#endif 15364ce7165Smrg}; 15464ce7165Smrg 15564ce7165Smrg#define FAMILIES ((sizeof familyMap)/(sizeof familyMap[0])) 15664ce7165Smrg 15764ce7165Smrg for (i = 0; i < FAMILIES; i++) 15864ce7165Smrg if (familyMap[i].af == af) return familyMap[i].xf; 15964ce7165Smrg return -1; 16064ce7165Smrg} 16164ce7165Smrg#endif /* NEEDSOCKETS */ 16264ce7165Smrg 163aadd013eSmrg#if defined(__CYGWIN__) || defined(WIN32) 164aadd013eSmrgvoid sethostent(int x) 165aadd013eSmrg{} 166aadd013eSmrg 167aadd013eSmrgvoid endhostent() 168aadd013eSmrg{} 169aadd013eSmrg#endif 170aadd013eSmrg 17164ce7165Smrgint 17264ce7165Smrgmain(int argc, char *argv[]) 17364ce7165Smrg{ 17464ce7165Smrg register char *arg; 17564ce7165Smrg int i, nhosts = 0; 1763544ea2eSmrg const char *hostname; 17764ce7165Smrg int nfailed = 0; 17864ce7165Smrg XHostAddress *list; 17964ce7165Smrg Bool enabled = False; 18081440437Smrg Display *dpy; 18164ce7165Smrg 18264ce7165Smrg ProgramName = argv[0]; 18364ce7165Smrg 1843544ea2eSmrg if (argc == 2 && !strcmp(argv[1], "-help")) { 1853544ea2eSmrg fprintf(stderr, "usage: %s [[+-]hostname ...]\n", argv[0]); 1863544ea2eSmrg exit(1); 1873544ea2eSmrg } 1883544ea2eSmrg 18964ce7165Smrg if ((dpy = XOpenDisplay(NULL)) == NULL) { 19064ce7165Smrg fprintf(stderr, "%s: unable to open display \"%s\"\n", 19164ce7165Smrg ProgramName, XDisplayName (NULL)); 19264ce7165Smrg exit(1); 19364ce7165Smrg } 19464ce7165Smrg 19564ce7165Smrg XSetErrorHandler(local_xerror); 19664ce7165Smrg 19764ce7165Smrg 19864ce7165Smrg if (argc == 1) { 19964ce7165Smrg sethostent(1); /* don't close the data base each time */ 20064ce7165Smrg list = XListHosts(dpy, &nhosts, &enabled); 20164ce7165Smrg if (enabled) 20264ce7165Smrg printf ("access control enabled, only authorized clients can connect\n"); 20364ce7165Smrg else 20464ce7165Smrg printf ("access control disabled, clients can connect from any host\n"); 20564ce7165Smrg 20664ce7165Smrg if (nhosts != 0) { 20764ce7165Smrg for (i = 0; i < nhosts; i++ ) { 20864ce7165Smrg hostname = get_hostname(&list[i]); 20964ce7165Smrg if (hostname) { 21064ce7165Smrg switch (list[i].family) { 21164ce7165Smrg case FamilyInternet: 21264ce7165Smrg printf("INET:"); 21364ce7165Smrg break; 21464ce7165Smrg case FamilyInternet6: 21564ce7165Smrg printf("INET6:"); 21664ce7165Smrg break; 21764ce7165Smrg case FamilyDECnet: 21864ce7165Smrg printf("DNET:"); 21964ce7165Smrg break; 22064ce7165Smrg case FamilyNetname: 22164ce7165Smrg printf("NIS:"); 22264ce7165Smrg break; 22364ce7165Smrg case FamilyKrb5Principal: 22464ce7165Smrg printf("KRB:"); 22564ce7165Smrg break; 22664ce7165Smrg case FamilyLocalHost: 22764ce7165Smrg printf("LOCAL:"); 22864ce7165Smrg break; 22964ce7165Smrg case FamilyServerInterpreted: 23064ce7165Smrg printf("SI:"); 23164ce7165Smrg break; 23264ce7165Smrg default: 23364ce7165Smrg printf("<unknown family type %d>:", list[i].family); 23464ce7165Smrg break; 23564ce7165Smrg } 23664ce7165Smrg printf ("%s", hostname); 23764ce7165Smrg } else { 23864ce7165Smrg printf ("<unknown address in family %d>", 23964ce7165Smrg list[i].family); 24064ce7165Smrg } 24164ce7165Smrg if (nameserver_timedout) { 24264ce7165Smrg printf("\t(no nameserver response within %d seconds)\n", 24364ce7165Smrg NAMESERVER_TIMEOUT); 24464ce7165Smrg nameserver_timedout = 0; 24564ce7165Smrg } else 24664ce7165Smrg printf("\n"); 24764ce7165Smrg } 24864ce7165Smrg free(list); 24964ce7165Smrg endhostent(); 25064ce7165Smrg } 25164ce7165Smrg exit(0); 25264ce7165Smrg } 25364ce7165Smrg 25464ce7165Smrg for (i = 1; i < argc; i++) { 25564ce7165Smrg arg = argv[i]; 25664ce7165Smrg if (*arg == '-') { 25764ce7165Smrg 25864ce7165Smrg if (!argv[i][1] && ((i+1) == argc)) { 25964ce7165Smrg printf ("access control enabled, only authorized clients can connect\n"); 26064ce7165Smrg XEnableAccessControl(dpy); 26164ce7165Smrg } else { 26264ce7165Smrg arg = argv[i][1]? &argv[i][1] : argv[++i]; 26364ce7165Smrg if (!change_host (dpy, arg, False)) { 26464ce7165Smrg fprintf (stderr, "%s: bad hostname \"%s\"\n", 26564ce7165Smrg ProgramName, arg); 26664ce7165Smrg nfailed++; 26764ce7165Smrg } 26864ce7165Smrg } 26964ce7165Smrg } else { 27064ce7165Smrg if (*arg == '+' && !argv[i][1] && ((i+1) == argc)) { 27164ce7165Smrg printf ("access control disabled, clients can connect from any host\n"); 27264ce7165Smrg XDisableAccessControl(dpy); 27364ce7165Smrg } else { 27464ce7165Smrg if (*arg == '+') { 27564ce7165Smrg arg = argv[i][1]? &argv[i][1] : argv[++i]; 27664ce7165Smrg } 27764ce7165Smrg if (!change_host (dpy, arg, True)) { 27864ce7165Smrg fprintf (stderr, "%s: bad hostname \"%s\"\n", 27964ce7165Smrg ProgramName, arg); 28064ce7165Smrg nfailed++; 28164ce7165Smrg } 28264ce7165Smrg } 28364ce7165Smrg } 28464ce7165Smrg } 28564ce7165Smrg XCloseDisplay (dpy); /* does an XSync first */ 28664ce7165Smrg exit(nfailed); 28764ce7165Smrg} 28864ce7165Smrg 28964ce7165Smrg 29064ce7165Smrg 29164ce7165Smrg/* 29264ce7165Smrg * change_host - edit the list of hosts that may connect to the server; 29364ce7165Smrg * it parses DECnet names (expo::), Internet addresses (18.30.0.212), or 29464ce7165Smrg * Internet names (expo.lcs.mit.edu); if 4.3bsd macro h_addr is defined 29564ce7165Smrg * (from <netdb.h>), it will add or remove all addresses with the given 29664ce7165Smrg * address. 29764ce7165Smrg */ 29864ce7165Smrg 29964ce7165Smrgstatic int 30064ce7165Smrgchange_host(Display *dpy, char *name, Bool add) 30164ce7165Smrg{ 30264ce7165Smrg XHostAddress ha; 30364ce7165Smrg char *lname; 30481440437Smrg size_t namelen, i; 30581440437Smrg int family = FamilyWild; 30664ce7165Smrg#ifdef K5AUTH 30764ce7165Smrg krb5_principal princ; 30864ce7165Smrg krb5_data kbuf; 30964ce7165Smrg#endif 31064ce7165Smrg#ifdef NEEDSOCKETS 31164ce7165Smrg static struct in_addr addr; /* so we can point at it */ 31264ce7165Smrg#if defined(IPv6) && defined(AF_INET6) 31364ce7165Smrg static struct in6_addr addr6; /* so we can point at it */ 31464ce7165Smrg#else 31564ce7165Smrg struct hostent *hp; 31664ce7165Smrg#endif 31764ce7165Smrg#endif 31864ce7165Smrg char *cp; 3193544ea2eSmrg static const char *add_msg = "being added to access control list"; 3203544ea2eSmrg static const char *remove_msg = "being removed from access control list"; 32164ce7165Smrg 32264ce7165Smrg namelen = strlen(name); 32364ce7165Smrg if ((lname = (char *)malloc(namelen+1)) == NULL) { 32464ce7165Smrg fprintf (stderr, "%s: malloc bombed in change_host\n", ProgramName); 32564ce7165Smrg exit (1); 32664ce7165Smrg } 32764ce7165Smrg for (i = 0; i < namelen; i++) { 32864ce7165Smrg lname[i] = tolower(name[i]); 32964ce7165Smrg } 33064ce7165Smrg lname[namelen] = '\0'; 33164ce7165Smrg if (!strncmp("inet:", lname, 5)) { 33281440437Smrg#ifdef TCPCONN 33364ce7165Smrg family = FamilyInternet; 33464ce7165Smrg name += 5; 33564ce7165Smrg#else 33664ce7165Smrg fprintf (stderr, "%s: not compiled for TCP/IP\n", ProgramName); 33764ce7165Smrg free(lname); 33864ce7165Smrg return 0; 33964ce7165Smrg#endif 34064ce7165Smrg } 34164ce7165Smrg else if (!strncmp("inet6:", lname, 6)) { 34281440437Smrg#if defined(TCPCONN) && defined(IPv6) && defined(AF_INET6) 34364ce7165Smrg family = FamilyInternet6; 34464ce7165Smrg name += 6; 34564ce7165Smrg#else 34664ce7165Smrg fprintf (stderr, "%s: not compiled for IPv6\n", ProgramName); 34764ce7165Smrg free(lname); 34864ce7165Smrg return 0; 34964ce7165Smrg#endif 35064ce7165Smrg } 35164ce7165Smrg#ifdef ACCEPT_INETV6 /* Allow inetv6 as an alias for inet6 for compatibility 35264ce7165Smrg with original X11 over IPv6 draft. */ 35364ce7165Smrg else if (!strncmp("inetv6:", lname, 7)) { 35481440437Smrg#if defined(TCPCONN) && defined(IPv6) && defined(AF_INET6) 35564ce7165Smrg family = FamilyInternet6; 35664ce7165Smrg name += 7; 35764ce7165Smrg#else 35864ce7165Smrg fprintf (stderr, "%s: not compiled for IPv6\n", ProgramName); 35964ce7165Smrg free(lname); 36064ce7165Smrg return 0; 36164ce7165Smrg#endif 36264ce7165Smrg } 36364ce7165Smrg#endif /* ACCEPT_INETV6 */ 36464ce7165Smrg else if (!strncmp("dnet:", lname, 5)) { 36564ce7165Smrg fprintf (stderr, "%s: not compiled for DECnet\n", ProgramName); 36664ce7165Smrg free(lname); 36764ce7165Smrg return 0; 36864ce7165Smrg } 36964ce7165Smrg else if (!strncmp("nis:", lname, 4)) { 37064ce7165Smrg#ifdef SECURE_RPC 37164ce7165Smrg family = FamilyNetname; 37264ce7165Smrg name += 4; 37364ce7165Smrg#else 37464ce7165Smrg fprintf (stderr, "%s: not compiled for Secure RPC\n", ProgramName); 37564ce7165Smrg free(lname); 37664ce7165Smrg return 0; 37764ce7165Smrg#endif 37864ce7165Smrg } 37964ce7165Smrg else if (!strncmp("krb:", lname, 4)) { 38064ce7165Smrg#ifdef K5AUTH 38164ce7165Smrg family = FamilyKrb5Principal; 38264ce7165Smrg name +=4; 38364ce7165Smrg#else 38464ce7165Smrg fprintf (stderr, "%s: not compiled for Kerberos 5\n", ProgramName); 38564ce7165Smrg free(lname); 38664ce7165Smrg return 0; 38764ce7165Smrg#endif 38864ce7165Smrg } 38964ce7165Smrg else if (!strncmp("local:", lname, 6)) { 39064ce7165Smrg family = FamilyLocalHost; 39164ce7165Smrg } 39264ce7165Smrg else if (!strncmp("si:", lname, 3)) { 39364ce7165Smrg family = FamilyServerInterpreted; 39464ce7165Smrg name += 3; 39564ce7165Smrg } 39664ce7165Smrg if (family == FamilyWild && (cp = strchr(lname, ':'))) { 39764ce7165Smrg *cp = '\0'; 39864ce7165Smrg fprintf (stderr, "%s: unknown address family \"%s\"\n", 39964ce7165Smrg ProgramName, lname); 40064ce7165Smrg free(lname); 40164ce7165Smrg return 0; 40264ce7165Smrg } 40364ce7165Smrg free(lname); 40464ce7165Smrg 40564ce7165Smrg if (family == FamilyServerInterpreted) { 40664ce7165Smrg XServerInterpretedAddress siaddr; 4073544ea2eSmrg int rc; 40864ce7165Smrg 40964ce7165Smrg cp = strchr(name, ':'); 41064ce7165Smrg if (cp == NULL || cp == name) { 41164ce7165Smrg fprintf(stderr, 41264ce7165Smrg "%s: type must be specified for server interpreted family \"%s\"\n", 41364ce7165Smrg ProgramName, name); 41464ce7165Smrg return 0; 41564ce7165Smrg } 4163544ea2eSmrg siaddr.type = name; 4173544ea2eSmrg siaddr.typelength = cp - name; 4183544ea2eSmrg siaddr.value = ++cp; 4193544ea2eSmrg siaddr.valuelength = strlen(cp); 42064ce7165Smrg ha.family = FamilyServerInterpreted; 42164ce7165Smrg ha.address = (char *) &siaddr; 42264ce7165Smrg if (add) 4233544ea2eSmrg rc = XAddHost(dpy, &ha); 42464ce7165Smrg else 4253544ea2eSmrg rc = XRemoveHost(dpy, &ha); 4263544ea2eSmrg printf( "%s %s%s\n", name, rc == 1 ? "" : "failed when ", 4273544ea2eSmrg add ? add_msg : remove_msg); 4283544ea2eSmrg if (rc != 1) 4293544ea2eSmrg return 0; 43064ce7165Smrg return 1; 43164ce7165Smrg } 43264ce7165Smrg 43364ce7165Smrg#ifdef K5AUTH 43464ce7165Smrg if (family == FamilyKrb5Principal) { 43564ce7165Smrg krb5_error_code retval; 43664ce7165Smrg 43764ce7165Smrg retval = krb5_parse_name(name, &princ); 43864ce7165Smrg if (retval) { 43964ce7165Smrg krb5_init_ets(); /* init krb errs for error_message() */ 44064ce7165Smrg fprintf(stderr, "%s: cannot parse Kerberos name: %s\n", 44164ce7165Smrg ProgramName, error_message(retval)); 44264ce7165Smrg return 0; 44364ce7165Smrg } 44464ce7165Smrg XauKrb5Encode(princ, &kbuf); 44564ce7165Smrg ha.length = kbuf.length; 44664ce7165Smrg ha.address = kbuf.data; 44764ce7165Smrg ha.family = family; 44864ce7165Smrg if (add) 44964ce7165Smrg XAddHost(dpy, &ha); 45064ce7165Smrg else 45164ce7165Smrg XRemoveHost(dpy, &ha); 45264ce7165Smrg krb5_free_principal(princ); 45364ce7165Smrg free(kbuf.data); 45464ce7165Smrg printf( "%s %s\n", name, add ? add_msg : remove_msg); 45564ce7165Smrg return 1; 45664ce7165Smrg } 45764ce7165Smrg#endif 45864ce7165Smrg if (family == FamilyLocalHost) { 45981440437Smrg char empty[] = ""; 46064ce7165Smrg ha.length = 0; 46181440437Smrg ha.address = empty; 46264ce7165Smrg ha.family = family; 46364ce7165Smrg if (add) 46464ce7165Smrg XAddHost(dpy, &ha); 46564ce7165Smrg else 46664ce7165Smrg XRemoveHost(dpy, &ha); 46764ce7165Smrg printf( "non-network local connections %s\n", add ? add_msg : remove_msg); 46864ce7165Smrg return 1; 46964ce7165Smrg } 47064ce7165Smrg /* 47164ce7165Smrg * If it has an '@', it's a netname 47264ce7165Smrg */ 47364ce7165Smrg if ((family == FamilyNetname && (cp = strchr(name, '@'))) || 47464ce7165Smrg (cp = strchr(name, '@'))) { 47564ce7165Smrg char *netname = name; 47664ce7165Smrg#ifdef SECURE_RPC 47764ce7165Smrg static char username[MAXNETNAMELEN]; 47864ce7165Smrg 47964ce7165Smrg if (!cp[1]) { 48064ce7165Smrg struct passwd *pwd; 48164ce7165Smrg static char domainname[128]; 48264ce7165Smrg 48364ce7165Smrg *cp = '\0'; 48464ce7165Smrg pwd = getpwnam(name); 48564ce7165Smrg if (!pwd) { 48664ce7165Smrg fprintf(stderr, "no such user \"%s\"\n", name); 48764ce7165Smrg return 0; 48864ce7165Smrg } 48964ce7165Smrg getdomainname(domainname, sizeof(domainname)); 49064ce7165Smrg if (!user2netname(username, pwd->pw_uid, domainname)) { 49164ce7165Smrg fprintf(stderr, "failed to get netname for \"%s\"\n", name); 49264ce7165Smrg return 0; 49364ce7165Smrg } 49464ce7165Smrg netname = username; 49564ce7165Smrg } 49664ce7165Smrg#endif 49764ce7165Smrg ha.family = FamilyNetname; 49864ce7165Smrg ha.length = strlen(netname); 49964ce7165Smrg ha.address = netname; 50064ce7165Smrg if (add) 50164ce7165Smrg XAddHost (dpy, &ha); 50264ce7165Smrg else 50364ce7165Smrg XRemoveHost (dpy, &ha); 50464ce7165Smrg if (netname != name) 50564ce7165Smrg printf ("%s@ (%s) %s\n", name, netname, add ? add_msg : remove_msg); 50664ce7165Smrg else 50764ce7165Smrg printf ("%s %s\n", netname, add ? add_msg : remove_msg); 50864ce7165Smrg return 1; 50964ce7165Smrg } 51064ce7165Smrg#ifdef NEEDSOCKETS 51164ce7165Smrg /* 512aadd013eSmrg * First see if inet_aton/inet_addr can grok the name; if so, then use it. 51364ce7165Smrg */ 51464ce7165Smrg if (((family == FamilyWild) || (family == FamilyInternet)) && 515aadd013eSmrg#ifdef HAVE_INET_ATON 516aadd013eSmrg (inet_aton (name, &addr) != 0) 517aadd013eSmrg#else 518aadd013eSmrg ((addr.s_addr = inet_addr(name)) != -1) 519aadd013eSmrg#endif 520aadd013eSmrg ) { 52164ce7165Smrg ha.family = FamilyInternet; 522aadd013eSmrg ha.length = sizeof(addr.s_addr); 523aadd013eSmrg ha.address = (char *) &addr.s_addr; 52464ce7165Smrg if (add) { 52564ce7165Smrg XAddHost (dpy, &ha); 52664ce7165Smrg printf ("%s %s\n", name, add_msg); 52764ce7165Smrg } else { 52864ce7165Smrg XRemoveHost (dpy, &ha); 52964ce7165Smrg printf ("%s %s\n", name, remove_msg); 53064ce7165Smrg } 53164ce7165Smrg return 1; 53264ce7165Smrg } 53364ce7165Smrg#if defined(IPv6) && defined(AF_INET6) 53464ce7165Smrg /* 53564ce7165Smrg * Check to see if inet_pton() can grok it as an IPv6 address 53664ce7165Smrg */ 53764ce7165Smrg else if (((family == FamilyWild) || (family == FamilyInternet6)) && 53864ce7165Smrg (inet_pton(AF_INET6, name, &addr6.s6_addr) == 1)) { 53964ce7165Smrg ha.family = FamilyInternet6; 54064ce7165Smrg ha.length = sizeof(addr6.s6_addr); 54164ce7165Smrg ha.address = (char *) &addr6.s6_addr; 54264ce7165Smrg if (add) { 54364ce7165Smrg XAddHost (dpy, &ha); 54464ce7165Smrg printf ("%s %s\n", name, add_msg); 54564ce7165Smrg } else { 54664ce7165Smrg XRemoveHost (dpy, &ha); 54764ce7165Smrg printf ("%s %s\n", name, remove_msg); 54864ce7165Smrg } 54964ce7165Smrg return 1; 55064ce7165Smrg } else { 55164ce7165Smrg /* 55264ce7165Smrg * Is it in the namespace? 55364ce7165Smrg * 55464ce7165Smrg * If no family was specified, use both Internet v4 & v6 addresses. 55564ce7165Smrg * Otherwise, use only addresses matching specified family. 55664ce7165Smrg */ 55764ce7165Smrg struct addrinfo *addresses; 55864ce7165Smrg struct addrinfo *a; 55964ce7165Smrg Bool didit = False; 56064ce7165Smrg 56164ce7165Smrg if (getaddrinfo(name, NULL, NULL, &addresses) != 0) 56264ce7165Smrg return 0; 56364ce7165Smrg 56464ce7165Smrg for (a = addresses; a != NULL; a = a->ai_next) { 56564ce7165Smrg if ( ((a->ai_family == AF_INET) && (family != FamilyInternet6)) 56664ce7165Smrg || ((a->ai_family == AF_INET6) && (family != FamilyInternet)) ) { 56764ce7165Smrg char ad[INET6_ADDRSTRLEN]; 56864ce7165Smrg ha.family = XFamily(a->ai_family); 56964ce7165Smrg if (a->ai_family == AF_INET6) { 57064ce7165Smrg ha.address = (char *) 57164ce7165Smrg &((struct sockaddr_in6 *) a->ai_addr)->sin6_addr; 57264ce7165Smrg ha.length = 57364ce7165Smrg sizeof (((struct sockaddr_in6 *) a->ai_addr)->sin6_addr); 57464ce7165Smrg } else { 57564ce7165Smrg ha.address = (char *) 57664ce7165Smrg &((struct sockaddr_in *) a->ai_addr)->sin_addr; 57764ce7165Smrg ha.length = 57864ce7165Smrg sizeof (((struct sockaddr_in *) a->ai_addr)->sin_addr); 57964ce7165Smrg } 58064ce7165Smrg inet_ntop(a->ai_family, ha.address, ad, sizeof(ad)); 58164ce7165Smrg /* printf("Family: %d\nLength: %d\n", a->ai_family, ha.length); */ 58264ce7165Smrg /* printf("Address: %s\n", ad); */ 58364ce7165Smrg 58464ce7165Smrg if (add) { 58564ce7165Smrg XAddHost (dpy, &ha); 58664ce7165Smrg } else { 58764ce7165Smrg XRemoveHost (dpy, &ha); 58864ce7165Smrg } 58964ce7165Smrg didit = True; 59064ce7165Smrg } 59164ce7165Smrg } 59264ce7165Smrg if (didit == True) { 59364ce7165Smrg printf ("%s %s\n", name, add ? add_msg : remove_msg); 59464ce7165Smrg } else { 59564ce7165Smrg const char *familyMsg = ""; 59664ce7165Smrg 59764ce7165Smrg if (family == FamilyInternet6) { 59864ce7165Smrg familyMsg = "inet6 "; 59964ce7165Smrg } else if (family == FamilyInternet) { 60064ce7165Smrg familyMsg = "inet "; 60164ce7165Smrg } 60264ce7165Smrg 60364ce7165Smrg fprintf(stderr, "%s: unable to get %saddress for \"%s\"\n", 60464ce7165Smrg ProgramName, familyMsg, name); 60564ce7165Smrg } 60664ce7165Smrg freeaddrinfo(addresses); 60764ce7165Smrg return 1; 60864ce7165Smrg } 60964ce7165Smrg#else /* !IPv6 */ 61064ce7165Smrg /* 61164ce7165Smrg * Is it in the namespace? 61264ce7165Smrg */ 61364ce7165Smrg else if (((hp = gethostbyname(name)) == (struct hostent *)NULL) 61464ce7165Smrg || hp->h_addrtype != AF_INET) { 61564ce7165Smrg return 0; 61664ce7165Smrg } else { 61764ce7165Smrg ha.family = XFamily(hp->h_addrtype); 61864ce7165Smrg ha.length = hp->h_length; 61964ce7165Smrg#ifdef h_addr /* new 4.3bsd version of gethostent */ 62064ce7165Smrg { 62164ce7165Smrg char **list; 62264ce7165Smrg 62364ce7165Smrg /* iterate over the hosts */ 62464ce7165Smrg for (list = hp->h_addr_list; *list; list++) { 62564ce7165Smrg ha.address = *list; 62664ce7165Smrg if (add) { 62764ce7165Smrg XAddHost (dpy, &ha); 62864ce7165Smrg } else { 62964ce7165Smrg XRemoveHost (dpy, &ha); 63064ce7165Smrg } 63164ce7165Smrg } 63264ce7165Smrg } 63364ce7165Smrg#else 63464ce7165Smrg ha.address = hp->h_addr; 63564ce7165Smrg if (add) { 63664ce7165Smrg XAddHost (dpy, &ha); 63764ce7165Smrg } else { 63864ce7165Smrg XRemoveHost (dpy, &ha); 63964ce7165Smrg } 64064ce7165Smrg#endif 64164ce7165Smrg printf ("%s %s\n", name, add ? add_msg : remove_msg); 64264ce7165Smrg return 1; 64364ce7165Smrg } 64464ce7165Smrg#endif /* IPv6 */ 64564ce7165Smrg#else /* NEEDSOCKETS */ 64664ce7165Smrg return 0; 64764ce7165Smrg#endif /* NEEDSOCKETS */ 64864ce7165Smrg} 64964ce7165Smrg 65064ce7165Smrg 65164ce7165Smrg/* 65264ce7165Smrg * get_hostname - Given an internet address, return a name (CHARON.MIT.EDU) 65364ce7165Smrg * or a string representing the address (18.58.0.13) if the name cannot 65464ce7165Smrg * be found. 65564ce7165Smrg */ 65664ce7165Smrg 65764ce7165Smrg 6583544ea2eSmrgstatic const char * 65964ce7165Smrgget_hostname(XHostAddress *ha) 66064ce7165Smrg{ 66181440437Smrg#if defined(TCPCONN) && (!defined(IPv6) || !defined(AF_INET6)) 66264ce7165Smrg static struct hostent *hp = NULL; 66364ce7165Smrg#endif 66464ce7165Smrg#ifdef K5AUTH 66564ce7165Smrg krb5_principal princ; 66664ce7165Smrg krb5_data kbuf; 66764ce7165Smrg char *kname; 66864ce7165Smrg static char kname_out[255]; 66964ce7165Smrg#endif 67081440437Smrg#ifdef SIGALRM 67164ce7165Smrg struct sigaction sa; 67264ce7165Smrg#endif 67364ce7165Smrg 67481440437Smrg#ifdef TCPCONN 67564ce7165Smrg#if defined(IPv6) && defined(AF_INET6) 67664ce7165Smrg if ((ha->family == FamilyInternet) || (ha->family == FamilyInternet6)) { 67764ce7165Smrg struct sockaddr_storage saddr; 67864ce7165Smrg static char inetname[NI_MAXHOST]; 67981440437Smrg unsigned int saddrlen; 68064ce7165Smrg 68164ce7165Smrg inetname[0] = '\0'; 68264ce7165Smrg memset(&saddr, 0, sizeof saddr); 68364ce7165Smrg if (ha->family == FamilyInternet) { 68464ce7165Smrg struct sockaddr_in *sin = (struct sockaddr_in *) &saddr; 68564ce7165Smrg#ifdef BSD44SOCKETS 68664ce7165Smrg sin->sin_len = sizeof(struct sockaddr_in); 68764ce7165Smrg#endif 68864ce7165Smrg sin->sin_family = AF_INET; 68964ce7165Smrg sin->sin_port = 0; 690aadd013eSmrg if (sizeof(sin->sin_addr) > ha->length) 691aadd013eSmrg return ""; 69264ce7165Smrg memcpy(&sin->sin_addr, ha->address, sizeof(sin->sin_addr)); 69364ce7165Smrg saddrlen = sizeof(struct sockaddr_in); 69464ce7165Smrg } else { 69564ce7165Smrg struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &saddr; 69664ce7165Smrg#ifdef SIN6_LEN 69764ce7165Smrg sin6->sin6_len = sizeof(struct sockaddr_in6); 69864ce7165Smrg#endif 69964ce7165Smrg sin6->sin6_family = AF_INET6; 70064ce7165Smrg sin6->sin6_port = 0; 701aadd013eSmrg if (sizeof(sin6->sin6_addr) > ha->length) 702aadd013eSmrg return ""; 70364ce7165Smrg memcpy(&sin6->sin6_addr, ha->address, sizeof(sin6->sin6_addr)); 70464ce7165Smrg saddrlen = sizeof(struct sockaddr_in6); 70564ce7165Smrg } 70664ce7165Smrg 70764ce7165Smrg /* gethostbyaddr can take a LONG time if the host does not exist. 70864ce7165Smrg Assume that if it does not respond in NAMESERVER_TIMEOUT seconds 70964ce7165Smrg that something is wrong and do not make the user wait. 71064ce7165Smrg gethostbyaddr will continue after a signal, so we have to 71164ce7165Smrg jump out of it. 71264ce7165Smrg */ 71381440437Smrg#ifdef SIGALRM 71464ce7165Smrg memset(&sa, 0, sizeof sa); 71564ce7165Smrg sa.sa_handler = nameserver_lost; 71664ce7165Smrg sa.sa_flags = 0; /* don't restart syscalls */ 71764ce7165Smrg sigaction(SIGALRM, &sa, NULL); 71864ce7165Smrg alarm(NAMESERVER_TIMEOUT); 71964ce7165Smrg#endif 72081440437Smrg getnameinfo((struct sockaddr *) &saddr, saddrlen, inetname, 72181440437Smrg sizeof(inetname), NULL, 0, 0); 72281440437Smrg#ifdef SIGALRM 72364ce7165Smrg alarm(0); 72481440437Smrg#endif 72564ce7165Smrg if (nameserver_timedout || inetname[0] == '\0') 72664ce7165Smrg inet_ntop(((struct sockaddr *)&saddr)->sa_family, ha->address, 72764ce7165Smrg inetname, sizeof(inetname)); 72864ce7165Smrg return inetname; 72964ce7165Smrg } 73064ce7165Smrg#else 73164ce7165Smrg if (ha->family == FamilyInternet) { 73264ce7165Smrg /* gethostbyaddr can take a LONG time if the host does not exist. 73364ce7165Smrg Assume that if it does not respond in NAMESERVER_TIMEOUT seconds 73464ce7165Smrg that something is wrong and do not make the user wait. 73564ce7165Smrg gethostbyaddr will continue after a signal, so we have to 73664ce7165Smrg jump out of it. 73764ce7165Smrg */ 73881440437Smrg#ifdef SIGALRM 73964ce7165Smrg memset(&sa, 0, sizeof sa); 74064ce7165Smrg sa.sa_handler = nameserver_lost; 74164ce7165Smrg sa.sa_flags = 0; /* don't restart syscalls */ 74264ce7165Smrg sigaction(SIGALRM, &sa, NULL); 74364ce7165Smrg alarm(4); 74464ce7165Smrg#endif 74581440437Smrg hp = gethostbyaddr (ha->address, ha->length, AF_INET); 74681440437Smrg#ifdef SIGALRM 74764ce7165Smrg alarm(0); 74881440437Smrg#endif 74964ce7165Smrg if (hp) 75064ce7165Smrg return (hp->h_name); 75164ce7165Smrg else return (inet_ntoa(*((struct in_addr *)(ha->address)))); 75264ce7165Smrg } 75364ce7165Smrg#endif /* IPv6 */ 75464ce7165Smrg#endif 75564ce7165Smrg if (ha->family == FamilyNetname) { 75664ce7165Smrg static char netname[512]; 75764ce7165Smrg int len; 75864ce7165Smrg#ifdef SECURE_RPC 75964ce7165Smrg int gidlen; 76064ce7165Smrg uid_t uid; 76164ce7165Smrg gid_t gid, gidlist[NGROUPS_MAX]; 76264ce7165Smrg#endif 76364ce7165Smrg 76464ce7165Smrg if (ha->length < sizeof(netname) - 1) 76564ce7165Smrg len = ha->length; 76664ce7165Smrg else 76764ce7165Smrg len = sizeof(netname) - 1; 76864ce7165Smrg memmove( netname, ha->address, len); 76964ce7165Smrg netname[len] = '\0'; 77064ce7165Smrg#ifdef SECURE_RPC 77164ce7165Smrg if (netname2user(netname, &uid, &gid, &gidlen, gidlist)) { 77264ce7165Smrg struct passwd *pwd; 77364ce7165Smrg 77464ce7165Smrg pwd = getpwuid(uid); 77564ce7165Smrg if (pwd) 77681440437Smrg snprintf(netname, sizeof(netname), "%s@ (%*.*s)", 77781440437Smrg pwd->pw_name, ha->length, ha->length, ha->address); 77864ce7165Smrg } 77964ce7165Smrg#endif 78064ce7165Smrg return (netname); 78164ce7165Smrg } 78264ce7165Smrg#ifdef K5AUTH 78364ce7165Smrg if (ha->family == FamilyKrb5Principal) { 78464ce7165Smrg kbuf.data = ha->address; 78564ce7165Smrg kbuf.length = ha->length; 78664ce7165Smrg XauKrb5Decode(kbuf, &princ); 78764ce7165Smrg krb5_unparse_name(princ, &kname); 78864ce7165Smrg krb5_free_principal(princ); 78964ce7165Smrg strncpy(kname_out, kname, sizeof (kname_out)); 79064ce7165Smrg free(kname); 79164ce7165Smrg return kname_out; 79264ce7165Smrg } 79364ce7165Smrg#endif 79464ce7165Smrg if (ha->family == FamilyLocalHost) { 79564ce7165Smrg return ""; 79664ce7165Smrg } 79764ce7165Smrg if (ha->family == FamilyServerInterpreted) { 79864ce7165Smrg XServerInterpretedAddress *sip; 79964ce7165Smrg static char *addressString; 80064ce7165Smrg static size_t addressStringSize; 80164ce7165Smrg size_t neededSize; 80264ce7165Smrg 80364ce7165Smrg sip = (XServerInterpretedAddress *) ha->address; 80464ce7165Smrg neededSize = sip->typelength + sip->valuelength + 2; 80564ce7165Smrg 80664ce7165Smrg if (addressStringSize < neededSize) { 80764ce7165Smrg if (addressString != NULL) { 80864ce7165Smrg free(addressString); 80964ce7165Smrg } 81064ce7165Smrg addressStringSize = neededSize; 81164ce7165Smrg addressString = malloc(addressStringSize); 81264ce7165Smrg } 81364ce7165Smrg if (addressString != NULL) { 81464ce7165Smrg char *cp = addressString; 81564ce7165Smrg 81664ce7165Smrg memcpy(cp, sip->type, sip->typelength); 81764ce7165Smrg cp += sip->typelength; 81864ce7165Smrg *cp++ = ':'; 81964ce7165Smrg memcpy(cp, sip->value, sip->valuelength); 82064ce7165Smrg cp += sip->valuelength; 82164ce7165Smrg *cp = '\0'; 82264ce7165Smrg } 82364ce7165Smrg return addressString; 82464ce7165Smrg } 82564ce7165Smrg return (NULL); 82664ce7165Smrg} 82764ce7165Smrg 82864ce7165Smrg/*ARGUSED*/ 82981440437Smrgstatic void 83081440437Smrgnameserver_lost(_X_UNUSED int sig) 83164ce7165Smrg{ 83264ce7165Smrg nameserver_timedout = 1; 83364ce7165Smrg} 83464ce7165Smrg 83564ce7165Smrg/* 83664ce7165Smrg * local_xerror - local non-fatal error handling routine. If the error was 83764ce7165Smrg * that an X_GetHosts request for an unknown address format was received, just 83864ce7165Smrg * return, otherwise print the normal error message and continue. 83964ce7165Smrg */ 84064ce7165Smrgstatic int 84164ce7165Smrglocal_xerror(Display *dpy, XErrorEvent *rep) 84264ce7165Smrg{ 84364ce7165Smrg if ((rep->error_code == BadAccess) && (rep->request_code == X_ChangeHosts)) { 84464ce7165Smrg fprintf (stderr, 84564ce7165Smrg "%s: must be on local machine to add or remove hosts.\n", 84664ce7165Smrg ProgramName); 84764ce7165Smrg return 1; 84864ce7165Smrg } else if ((rep->error_code == BadAccess) && 84964ce7165Smrg (rep->request_code == X_SetAccessControl)) { 85064ce7165Smrg fprintf (stderr, 85164ce7165Smrg "%s: must be on local machine to enable or disable access control.\n", 85264ce7165Smrg ProgramName); 85364ce7165Smrg return 1; 85464ce7165Smrg } else if ((rep->error_code == BadValue) && 85564ce7165Smrg (rep->request_code == X_ListHosts)) { 85664ce7165Smrg return 1; 85764ce7165Smrg } 85864ce7165Smrg 85964ce7165Smrg XmuPrintDefaultErrorMessage (dpy, rep, stderr); 86064ce7165Smrg return 0; 86164ce7165Smrg} 862