|
|
1.1 root 1: /***********************************************************
2: Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
3: and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
4:
5: All Rights Reserved
6:
7: Permission to use, copy, modify, and distribute this software and its
8: documentation for any purpose and without fee is hereby granted,
9: provided that the above copyright notice appear in all copies and that
10: both that copyright notice and this permission notice appear in
11: supporting documentation, and that the names of Digital or MIT not be
12: used in advertising or publicity pertaining to distribution of the
13: software without specific, written prior permission.
14:
15: DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
16: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
17: DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
18: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
19: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
20: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
21: SOFTWARE.
22:
23: ******************************************************************/
24:
25: /* $Header: access.c,v 1.18 87/09/03 14:24:02 toddb Exp $ */
26:
27: #include "X.h"
28: #include "Xproto.h"
29: #include "misc.h"
30: #include <errno.h>
31: #include <sys/types.h>
32: #include <sys/socket.h>
33: #include <sys/ioctl.h>
34: #include <net/if.h>
35: #include <netdb.h>
36: #ifdef TCPCONN
37: #include <netinet/in.h>
38: #endif /* TCPCONN */
39: #ifdef DNETCONN
40: #include <netdnet/dn.h>
41: #include <netdnet/dnetdb.h>
42: #endif
43: #undef NULL
44: #include <stdio.h>
45: #include "dixstruct.h"
46: #include "osdep.h"
47:
48:
49: #define DONT_CHECK -1
50: extern char *index();
51:
52: typedef struct _host {
53: short family;
54: short len;
55: unsigned char addr[4]; /* will need to be bigger eventually */
56: struct _host *next;
57: } HOST;
58:
59: static HOST *selfhosts = NULL;
60: static HOST *validhosts = NULL;
61: static int AccessEnabled = TRUE;
62:
63: typedef struct {
64: int af, xf;
65: } FamilyMap;
66:
67: static FamilyMap familyMap[] = {
68: #ifdef AF_DECnet
69: {AF_DECnet, FamilyDECnet},
70: #endif /* AF_DECnet */
71: #ifdef AF_CHAOS
72: {AF_CHAOS, FamilyChaos},
73: #endif /* AF_CHAOS */
74: #ifdef AF_INET
75: {AF_INET, FamilyInternet}
76: #endif
77: };
78:
79: #define FAMILIES ((sizeof familyMap)/(sizeof familyMap[0]))
80:
81: /* Define this host for access control. Find all the hosts the OS knows about
82: * for this fd and add them to the selfhosts list.
83: */
84: DefineSelf (fd)
85: int fd;
86: {
87: char buf[2048];
88: struct ifconf ifc;
89: register int n;
90: int len;
91: pointer addr;
92: short family;
93: register HOST *host;
94: register struct ifreq *ifr;
95:
96: ifc.ifc_len = sizeof (buf);
97: ifc.ifc_buf = buf;
98: if (ioctl (fd, (int) SIOCGIFCONF, (pointer) &ifc) < 0)
99: Error ("Getting interface configuration");
100: for (ifr = ifc.ifc_req, n = ifc.ifc_len / sizeof (struct ifreq); --n >= 0;
101: ifr++)
102: {
103: #ifdef DNETCONN
104: /*
105: * this is ugly but SIOCGIFCONF returns decnet addresses in
106: * a different form from other decnet calls
107: */
108: if (ifr->ifr_addr.sa_family == AF_DECnet) {
109: len = sizeof (struct dn_naddr);
110: addr = (pointer)ifr->ifr_addr.sa_data;
111: family = AF_DECnet;
112: } else
113: #endif /* DNETCONN */
114: if ((family = ConvertAddr (&ifr->ifr_addr, &len, &addr)) <= 0)
115: continue;
116: for (host = selfhosts; host && (family != host->family ||
117: bcmp (addr, host->addr, len)); host = host->next)
118: ;
119: if (host)
120: continue;
121: host = (HOST *) Xalloc (sizeof (HOST));
122: host->family = family;
123: host->len = len;
124: bcopy(addr, host->addr, len);
125: host->next = selfhosts;
126: selfhosts = host;
127: }
128: }
129:
130: /* Reset access control list to initial hosts */
131: ResetHosts (display)
132: char *display;
133: {
134: register HOST *host, *self;
135: char hostname[120];
136: char fname[32];
137: FILE *fd;
138: char *ptr;
139: union {
140: struct sockaddr sa;
141: #ifdef TCPCONN
142: struct sockaddr_in in;
143: #endif /* TCPCONN */
144: #ifdef DNETCONN
145: struct sockaddr_dn dn;
146: #endif
147: } saddr;
148: #ifdef DNETCONN
149: struct nodeent *np;
150: struct dn_naddr dnaddr, *dnaddrp, *dnet_addr();
151: #endif
152: short family;
153: int len;
154: pointer addr;
155: register struct hostent *hp;
156:
157: while (host = validhosts)
158: {
159: validhosts = host->next;
160: Xfree ((pointer) host);
161: }
162: for (self = selfhosts; self; self = self->next)
163: {
164: host = (HOST *) Xalloc (sizeof (HOST));
165: *host = *self;
166: host->next = validhosts;
167: validhosts = host;
168: }
169: strcpy (fname, "/etc/X");
170: strcat (fname, display);
171: strcat (fname, ".hosts");
172: if (fd = fopen (fname, "r"))
173: {
174: while (fgets (hostname, sizeof (hostname), fd))
175: {
176: if (ptr = index (hostname, '\n'))
177: *ptr = 0;
178: #ifdef DNETCONN
179: if ((ptr = index (hostname, ':')) && (*(ptr + 1) == ':'))
180: {
181: /* node name (DECnet names end in "::") */
182: *ptr = 0;
183: if (dnaddrp = dnet_addr(hostname))
184: {
185: /* allow nodes to be specified by address */
186: NewHost (AF_DECnet, (pointer) dnaddrp);
187: }
188: else
189: {
190: if (np = getnodebyname (hostname))
191: {
192: /* node was specified by name */
193: saddr.sa.sa_family = np->n_addrtype;
194: if ((family = ConvertAddr (&saddr.sa, &len, &addr)) ==
195: AF_DECnet)
196: {
197: bzero ((pointer) &dnaddr, sizeof (dnaddr));
198: dnaddr.a_len = np->n_length;
199: bcopy (np->n_addr, (pointer) dnaddr.a_addr,
200: np->n_length);
201: NewHost (family, (pointer) &dnaddr);
202: }
203: }
204: }
205: }
206: else
207: {
208: #endif /* DNETCONN */
209: #ifdef TCPCONN
210: /* host name */
211: if (hp = gethostbyname (hostname))
212: {
213: saddr.sa.sa_family = hp->h_addrtype;
214: if ((family = ConvertAddr (&saddr.sa, &len, &addr)) > 0)
215: #ifdef NEW_HEADER_WITH_OLD_LIBRARY
216: NewHost (family, hp->h_addr_list);
217: #else
218: NewHost (family, hp->h_addr);
219: #endif
220:
221: }
222: #endif /* TCPCONN */
223: #ifdef DNETCONN
224: }
225: #endif /* DNETCONN */
226: }
227: fclose (fd);
228: }
229: }
230:
231: /* Add a host to the access control list. This is the external interface
232: * called from the dispatcher */
233:
234: int
235: AddHost (client, family, length, pAddr)
236: int client;
237: int family;
238: int length; /* of bytes in pAddr */
239: pointer pAddr;
240: {
241: int len;
242: register HOST *host;
243: int unixFamily;
244:
245: unixFamily = UnixFamily(family);
246: if ((len = CheckFamily (DONT_CHECK, unixFamily)) < 0)
247: return BadMatch;
248:
249: if (len != length)
250: return BadMatch;
251: for (host = validhosts; host; host = host->next)
252: {
253: if (unixFamily == host->family && !bcmp (pAddr, host->addr, len))
254: return Success;
255: }
256: host = (HOST *) Xalloc (sizeof (HOST));
257: host->family = unixFamily;
258: host->len = len;
259: bcopy(pAddr, host->addr, len);
260: host->next = validhosts;
261: validhosts = host;
262: return Success;
263: }
264:
265: /* Add a host to the access control list. This is the internal interface
266: * called when starting or resetting the server */
267: NewHost (family, addr)
268: short family;
269: pointer addr;
270: {
271: int len;
272: register HOST *host;
273:
274: if ((len = CheckFamily (DONT_CHECK, family)) < 0)
275: return;
276: for (host = validhosts; host; host = host->next)
277: {
278: if (family == host->family && !bcmp (addr, host->addr, len))
279: return;
280: }
281: host = (HOST *) Xalloc (sizeof (HOST));
282: host->family = family;
283: host->len = len;
284: bcopy(addr, host->addr, len);
285: host->next = validhosts;
286: validhosts = host;
287: }
288:
289: /* Remove a host from the access control list */
290:
291: int
292: RemoveHost (client, family, length, pAddr)
293: int client;
294: int family;
295: int length; /* of bytes in pAddr */
296: pointer pAddr;
297: {
298: int len,
299: unixFamily;
300: register HOST *host, **prev;
301:
302: unixFamily = UnixFamily(family);
303: if ((len = CheckFamily (DONT_CHECK, unixFamily)) < 0)
304: return BadMatch;
305: if (len != length)
306: return BadMatch;
307: for (prev = &validhosts;
308: (host = *prev) && (unixFamily != host->family ||
309: bcmp (pAddr, host->addr, len));
310: prev = &host->next)
311: ;
312: if (host)
313: {
314: *prev = host->next;
315: Xfree ((pointer) host);
316: }
317: return Success;
318: }
319:
320: /* Get all hosts in the access control list */
321: int
322: GetHosts (data, pnHosts, pEnabled)
323: pointer *data;
324: int *pnHosts;
325: BOOL *pEnabled;
326: {
327: int len;
328: register int n = 0;
329: register pointer ptr;
330: register HOST *host;
331: int nHosts = 0;
332: int *lengths = (int *) NULL;
333:
334: *pEnabled = AccessEnabled ? EnableAccess : DisableAccess;
335: for (host = validhosts; host; host = host->next)
336: {
337: if ((len = CheckFamily (DONT_CHECK, host->family)) < 0)
338: return (-1);
339: lengths = (int *) Xrealloc(lengths, (nHosts + 1) * sizeof(int));
340: lengths[nHosts++] = len;
341: n += (((len + 3) >> 2) << 2) + sizeof(xHostEntry);
342: }
343: if (n)
344: {
345: *data = ptr = (pointer) Xalloc (n);
346: nHosts = 0;
347: for (host = validhosts; host; host = host->next)
348: {
349:
350: len = lengths[nHosts++];
351: ((xHostEntry *)ptr)->family = XFamily(host->family);
352: ((xHostEntry *)ptr)->length = len;
353: ptr += sizeof(xHostEntry);
354: bcopy (host->addr, ptr, len);
355: ptr += ((len + 3) >> 2) << 2;
356: }
357: }
358: *pnHosts = nHosts;
359: Xfree(lengths);
360: return (n);
361: }
362:
363: /* Check for valid address family, and for local host if client modification.
364: * Return address length.
365: */
366:
367: CheckFamily (connection, family)
368: int connection;
369: short family;
370: {
371: struct sockaddr from;
372: int alen;
373: pointer addr;
374: register HOST *host;
375: int len;
376:
377: switch (family)
378: {
379: #ifdef TCPCONN
380: case AF_INET:
381: len = sizeof (struct in_addr);
382: break;
383: #endif
384: #ifdef DNETCONN
385: case AF_DECnet:
386: len = sizeof (struct dn_naddr);
387: break;
388: #endif
389: default:
390: /* BadValue */
391: return (-1);
392: }
393: if (connection == DONT_CHECK)
394: return (len);
395: alen = sizeof (from);
396: if (!getpeername (connection, &from, &alen))
397: {
398: if ((family = ConvertAddr (&from, &alen, &addr)) >= 0)
399: {
400: if (family == 0)
401: return (len);
402: for (host = selfhosts; host; host = host->next)
403: {
404: if (family == host->family &&
405: !bcmp (addr, host->addr, alen))
406: return (len);
407: }
408: }
409: }
410: /* Bad Access */
411: return (-1);
412: }
413:
414: /* Check if a host is not in the access control list.
415: * Returns 1 if host is invalid, 0 if we've found it. */
416:
417: InvalidHost (saddr, len)
418: register struct sockaddr *saddr;
419: int len;
420: {
421: short family;
422: pointer addr;
423: register HOST *host;
424: if ((family = ConvertAddr (saddr, len ? &len : 0, &addr)) < 0)
425: return (1);
426: if (family == 0)
427: return (0);
428: if (!AccessEnabled) /* just let them in */
429: return(0);
430: for (host = validhosts; host; host = host->next)
431: {
432: if (family == host->family && !bcmp (addr, host->addr, len))
433: return (0);
434: }
435: return (1);
436: }
437:
438: ConvertAddr (saddr, len, addr)
439: register struct sockaddr *saddr;
440: int *len;
441: pointer *addr;
442: {
443: if (len == 0)
444: return (0);
445: switch (saddr->sa_family)
446: {
447: case AF_UNSPEC:
448: case AF_UNIX:
449: return (0);
450: case AF_INET:
451: #ifdef TCPCONN
452: *len = sizeof (struct in_addr);
453: *addr = (pointer) &(((struct sockaddr_in *) saddr)->sin_addr);
454: return (AF_INET);
455: #else TCPCONN
456: break;
457: #endif TCPCONN
458:
459: #ifdef DNETCONN
460: case AF_DECnet:
461: *len = sizeof (struct dn_naddr);
462: *addr = (pointer) &(((struct sockaddr_dn *) saddr)->sdn_add);
463: return (AF_DECnet);
464: #else DNETCONN
465: break;
466: #endif DNETCONN
467:
468: default:
469: break;
470: }
471: return (-1);
472: }
473:
474: ChangeAccessControl(client, fEnabled)
475: ClientPtr client;
476: int fEnabled;
477: {
478: int alen, family;
479: struct sockaddr from;
480: pointer addr;
481: register HOST *host;
482:
483: alen = sizeof (from);
484: if (!getpeername (((osPrivPtr)client->osPrivate)->fd, &from, &alen))
485: {
486: if ((family = ConvertAddr (&from, &alen, &addr)) >= 0)
487: {
488: if (family == 0)
489: AccessEnabled = fEnabled;
490: for (host = selfhosts; host; host = host->next)
491: {
492: if (family == host->family &&
493: !bcmp (addr, host->addr, alen))
494: AccessEnabled = fEnabled;
495: }
496: }
497: }
498: }
499:
500: static int XFamily(af)
501: int af;
502: {
503: int i;
504: for (i = 0; i < FAMILIES; i++)
505: if (familyMap[i].af == af)
506: return familyMap[i].xf;
507: return -1;
508: }
509:
510: static int UnixFamily(xf)
511: int xf;
512: {
513: int i;
514: for (i = 0; i < FAMILIES; i++)
515: if (familyMap[i].xf == xf)
516: return familyMap[i].af;
517: return -1;
518: }
519:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.