|
|
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.