|
|
1.1 root 1: /*
2:
3: Copyright 1985, 1986, 1987 by the Massachusetts Institute of Technology
4:
5: Permission to use, copy, modify, and distribute this
6: software and its documentation for any purpose and without
7: fee is hereby granted, provided that the above copyright
8: notice appear in all copies and that both that copyright
9: notice and this permission notice appear in supporting
10: documentation, and that the name of M.I.T. not be used in
11: advertising or publicity pertaining to distribution of the
12: software without specific, written prior permission.
13: M.I.T. makes no representations about the suitability of
14: this software for any purpose. It is provided "as is"
15: without express or implied warranty.
16:
17: */
18:
19: #ifndef lint
20: static char *rcsid_xhost_c = "$XConsortium: xhost.c,v 11.28 88/10/11 12:48:06 jim Exp $";
21: #endif
22:
23: #include <signal.h>
24: #include <setjmp.h>
25: #include <ctype.h>
26: #include <sys/types.h>
27: #include <sys/socket.h>
28: #include <stdio.h>
29: #include <netdb.h>
30: #include <netinet/in.h>
31: #ifdef notdef
32: #include <arpa/inet.h>
33: bogus definition of inet_makeaddr() in BSD 4.2 and Ultrix
34: #else
35: extern unsigned long inet_makeaddr();
36: #endif
37: #ifdef DNETCONN
38: #include <netdnet/dn.h>
39: #include <netdnet/dnetdb.h>
40: #endif
41: #include <X11/Xos.h>
42: #include <X11/Xlib.h>
43: #include <X11/Xproto.h>
44: #include <X11/Xmu.h>
45: #ifdef ISOCONN
46: #include <isode/psap.h>
47: #include <isode/tsap.h>
48: #include <isode/isoservent.h>
49: #include "../server/osdep.h"
50: #endif /* ISOCONN */
51:
52: static int local_xerror();
53:
54: #define NAMESERVER_TIMEOUT 5 /* time to wait for nameserver */
55:
56: typedef struct {
57: int af, xf;
58: } FamilyMap;
59:
60: static FamilyMap familyMap[] = {
61: #ifdef AF_DECnet
62: {AF_DECnet, FamilyDECnet},
63: #endif
64: #ifdef AF_CHAOS
65: {AF_CHAOS, FamilyChaos},
66: #endif
67: #ifdef AF_OSI
68: {AF_OSI, FamilyIso},
69: #endif
70: #ifdef AF_INET
71: {AF_INET, FamilyInternet}
72: #endif
73: };
74:
75: #define FAMILIES ((sizeof familyMap)/(sizeof familyMap[0]))
76:
77: int nameserver_timedout;
78:
79: char *ProgramName;
80:
81: static int XFamily(af)
82: int af;
83: {
84: int i;
85: for (i = 0; i < FAMILIES; i++)
86: if (familyMap[i].af == af)
87: return familyMap[i].xf;
88: return -1;
89: }
90:
91:
92: main(argc, argv)
93: int argc;
94: char **argv;
95: {
96: Display *dpy;
97: char host[256];
98: register char *arg;
99: int display, i, w, nhosts;
100: char *hostname, *get_hostname();
101: XHostAddress *list;
102: Bool enabled = False;
103: #ifdef DNETCONN
104: char *dnet_htoa();
105: struct nodeent *np;
106: struct dn_naddr *nlist, dnaddr, *dnaddrp, *dnet_addr();
107: char *cp;
108: #endif
109:
110: ProgramName = argv[0];
111:
112: #ifdef ISOCONN
113: /*
114: * XXX Shouldd parse -display display here
115: */
116: if ((dpy = XOpenDisplay("perky:X0")) == NULL) {
117: #else
118: if ((dpy = XOpenDisplay(NULL)) == NULL) {
119: #endif
120: fprintf(stderr, "%s: unable to open display \"%s\"\n",
121: ProgramName, XDisplayName (NULL));
122: exit(1);
123: }
124:
125: XSetErrorHandler(local_xerror);
126:
127:
128: if (argc == 1) {
129: #ifdef DNETCONN
130: setnodeent(1); /* keep the database accessed */
131: #endif
132: sethostent(1); /* don't close the data base each time */
133: list = XListHosts(dpy, &nhosts, &enabled);
134: printf ("access control %s\n",
135: (enabled ?
136: "enabled (only the following hosts are allowed)":
137: "disabled (any host is allowed)"));
138: if (nhosts != 0) {
139: for (i = 0; i < nhosts; i++ ) {
140: hostname = get_hostname(&list[i]);
141: printf("%s\t", hostname);
142: if (nameserver_timedout)
143: printf("(nameserver did not respond in %d seconds)\n",
144: NAMESERVER_TIMEOUT);
145: else printf("\n");
146: }
147: free(list);
148: endhostent();
149: }
150: exit(0);
151: }
152:
153: for (i = 1; i < argc; i++) {
154: arg = argv[i];
155: if (*arg == '-') {
156:
157: if (!argv[i][1] && ((i+1) == argc)) {
158: printf ("all hosts being restricted (access control enabled)\n");
159: XEnableAccessControl(dpy);
160: } else {
161: arg = argv[i][1]? &argv[i][1] : argv[++i];
162: if (!change_host (dpy, arg, False)) {
163: fprintf (stderr, "%s: bad hostname \"%s\"\n",
164: ProgramName, arg);
165: }
166: }
167: } else {
168: if (*arg == '+' && !argv[i][1] && ((i+1) == argc)) {
169: printf ("all hosts being allowed (access control disabled)\n");
170: XDisableAccessControl(dpy);
171: } else {
172: if (*arg == '+') {
173: arg = argv[i][1]? &argv[i][1] : argv[++i];
174: }
175: if (!change_host (dpy, arg, True)) {
176: fprintf (stderr, "%s: bad hostname \"%s\"\n",
177: ProgramName, arg);
178: }
179: }
180: }
181: }
182: XCloseDisplay (dpy); /* does an XSync first */
183: exit(0);
184: }
185:
186:
187:
188: /*
189: * change_host - edit the list of hosts that may connect to the server;
190: * it parses DECnet names (expo::), Internet addresses (18.30.0.212), or
191: * Internet names (expo.lcs.mit.edu); if 4.3bsd macro h_addr is defined
192: * (from <netdb.h>), it will add or remove all addresses with the given
193: * address.
194: */
195: #ifdef ISOCONN
196: /*
197: * ISO T-Service is selected by server:T-Name:Display
198: * where T-Name must start non numeric (i.e. default is by ommission
199: *
200: */
201: #endif /* ISOCONN */
202:
203: int change_host (dpy, name, add)
204: Display *dpy;
205: char *name;
206: Bool add;
207: {
208: struct hostent *hp;
209: XHostAddress ha;
210: static struct in_addr addr; /* so we can point at it */
211: #ifdef DNETCONN
212: struct dn_naddr *dnaddrp;
213: struct nodeent *np;
214: char *cp;
215: static struct dn_naddr dnaddr;
216: #endif /* DNETCONN */
217: static char *add_msg = "being added to access control list";
218: static char *remove_msg = "being removed from access control list";
219: #ifdef ISOCONN
220: char *cp;
221: #endif /* ISOCONN */
222:
223: #ifdef DNETCONN
224: if ((cp = index (name, ':')) && (*(cp + 1) == ':')) {
225: *cp = '\0';
226: ha.family = FamilyDECnet;
227: if (dnaddrp = dnet_addr(name)) {
228: dnaddr = *dnaddrp;
229: } else {
230: if ((np = getnodebyname (name)) == NULL) {
231: fprintf (stderr, "%s: unble to get node name for \"%s::\"\n",
232: ProgramName, name);
233: return 0;
234: }
235: dnaddr.a_len = np->n_length;
236: bcopy (np->n_addr, dnaddr.a_addr, np->n_length);
237: }
238: ha.length = sizeof(struct dn_naddr);
239: ha.address = (char *)&dnaddr;
240: if (add) {
241: XAddHost (dpy, &ha);
242: printf ("%s:: %s\n", name, add_msg);
243: } else {
244: XRemoveHost (dpy, &ha);
245: printf ("%s:: %s\n", name, remove_msg);
246: }
247: return 1;
248: }
249: #endif /* DNETCONN */
250: #ifdef ISOCONN
251: /*
252: * TServiceNameDisplayNumber...
253: */
254: if ((cp = index (name, ':')) && ( (*(cp + 1) == 'X')|| (*(cp + 1) == 'T'))) {
255: AEI aei;
256: struct PSAPaddr *pa;
257: *(cp++) = '\0';
258: ha.family = FamilyIso;
259: if (cp)
260: aei = str2aei(name, cp);
261: else
262: aei = str2aei(name, DEFAULTTSERVICE);
263: if (aei == NULLAEI) {
264: fprintf (stderr, "%s: unble to get AEI for \"%s::\"\n",
265: ProgramName, name);
266: return 0;
267: }
268: if ((pa = aei2addr (aei)) == NULLPA) {
269: fprintf (stderr, "address translation failed");
270: return 0;
271: }
272: ha.length = NASIZE;
273: ha.address = (char *)&(pa->pa_addr.sa_addr);
274: /*
275: * XXXX
276: */
277: {
278: int i; char *hp = ha.address;
279: for(i=0;i<sizeof(struct TSAPaddr); i++) {
280: fprintf(stderr, "%x ", *hp & 0xff);
281: hp++;
282: }
283: fprintf(stderr, "\n");
284: }
285: if (add) {
286: XAddHost (dpy, &ha);
287: printf ("%s:: %s\n", name, add_msg);
288: } else {
289: XRemoveHost (dpy, &ha);
290: printf ("%s:: %s\n", name, remove_msg);
291: }
292: return 1;
293: }
294: #endif /* ISOCONN */
295: /*
296: * First see if inet_addr() can grok the name; if so, then use it.
297: */
298: if ((addr.s_addr = inet_addr(name)) != -1) {
299: ha.family = FamilyInternet;
300: ha.length = sizeof(addr.s_addr);
301: ha.address = (char *)&addr.s_addr;
302: if (add) {
303: XAddHost (dpy, &ha);
304: printf ("%s %s\n", name, add_msg);
305: } else {
306: XRemoveHost (dpy, &ha);
307: printf ("%s %s\n", name, remove_msg);
308: }
309: return 1;
310: }
311: /*
312: * Is it in the namespace?
313: */
314: else if (((hp = gethostbyname(name)) == (struct hostent *)NULL)
315: || hp->h_addrtype != AF_INET) {
316: return 0;
317: } else {
318: ha.family = XFamily(hp->h_addrtype);
319: ha.length = hp->h_length;
320: #ifdef h_addr /* new 4.3bsd version of gethostent */
321: {
322: char **list;
323:
324: /* iterate over the hosts */
325: for (list = hp->h_addr_list; *list; list++) {
326: ha.address = *list;
327: if (add) {
328: XAddHost (dpy, &ha);
329: } else {
330: XRemoveHost (dpy, &ha);
331: }
332: }
333: }
334: #else
335: ha.address = hp->h_addr;
336: if (add) {
337: XAddHost (dpy, &ha);
338: } else {
339: XRemoveHost (dpy, &ha);
340: }
341: #endif
342: printf ("%s %s\n", name, add ? add_msg : remove_msg);
343: return 1;
344: }
345: /* NOTREACHED */
346: }
347:
348:
349: /*
350: * get_hostname - Given an internet address, return a name (CHARON.MIT.EDU)
351: * or a string representing the address (18.58.0.13) if the name cannot
352: * be found.
353: */
354:
355: jmp_buf env;
356:
357: char *get_hostname (ha)
358: XHostAddress *ha;
359: {
360: struct hostent *hp = NULL;
361: int nameserver_lost();
362: char *inet_ntoa();
363: #ifdef DNETCONN
364: struct nodeent *np;
365: static char nodeaddr[16];
366: #endif /* DNETCONN */
367:
368: if (ha->family == FamilyInternet) {
369: /* gethostbyaddr can take a LONG time if the host does not exist.
370: Assume that if it does not respond in NAMESERVER_TIMEOUT seconds
371: that something is wrong and do not make the user wait.
372: gethostbyaddr will continue after a signal, so we have to
373: jump out of it.
374: */
375: nameserver_timedout = 0;
376: signal(SIGALRM, nameserver_lost);
377: alarm(4);
378: if (setjmp(env) == 0) {
379: hp = gethostbyaddr (ha->address, ha->length, AF_INET);
380: }
381: alarm(0);
382: if (hp)
383: return (hp->h_name);
384: else return (inet_ntoa(*((struct in_addr *)(ha->address))));
385: }
386: #ifdef DNETCONN
387: if (ha->family == FamilyDECnet) {
388: if (np = getnodebyaddr(ha->address, ha->length, AF_DECnet)) {
389: sprintf(nodeaddr, "%s::", np->n_name);
390: } else {
391: sprintf(nodeaddr, "%s::", dnet_htoa(ha->address));
392: }
393: return(nodeaddr);
394: }
395: #endif
396: #ifdef ISOCONN
397: /*
398: * We really truly need an nsap to AEI here...
399: */
400: if (ha->family == FamilyIso) {
401: return(ha->address);
402: }
403: #endif /* ISOCONN */
404:
405: return (NULL);
406: }
407:
408: nameserver_lost()
409: {
410: nameserver_timedout = 1;
411: longjmp(env, -1);
412: }
413:
414: /*
415: * local_xerror - local non-fatal error handling routine. If the error was
416: * that an X_GetHosts request for an unknown address format was received, just
417: * return, otherwise print the normal error message and continue.
418: */
419: static int local_xerror (dpy, rep)
420: Display *dpy;
421: XErrorEvent *rep;
422: {
423: if ((rep->error_code == BadAccess) && (rep->request_code == X_ChangeHosts)) {
424: fprintf (stderr,
425: "%s: must be on local machine to add or remove hosts.\n",
426: ProgramName);
427: return 1;
428: } else if ((rep->error_code == BadAccess) &&
429: (rep->request_code == X_SetAccessControl)) {
430: fprintf (stderr,
431: "%s: must be on local machine to enable or disable access control.\n",
432: ProgramName);
433: return 1;
434: } else if ((rep->error_code == BadValue) &&
435: (rep->request_code == X_ListHosts)) {
436: return 1;
437: }
438:
439: XmuPrintDefaultErrorMessage (dpy, rep, stderr);
440: return 0;
441: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.