home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / server / os / access.c next >
Encoding:
C/C++ Source or Header  |  1993-07-21  |  18.2 KB  |  803 lines

  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. /* $XConsortium: access.c,v 1.54 92/05/19 17:23:02 keith Exp $ */
  26.  
  27. #include "Xos.h"
  28. #include "X.h"
  29. #include "Xproto.h"
  30. #include "misc.h"
  31. #include "site.h"
  32. #include <errno.h>
  33. #include <sys/socket.h>
  34. #include <sys/ioctl.h>
  35. #include <X11/Xauth.h>
  36.  
  37. #ifdef TCPCONN
  38. #include <netinet/in.h>
  39. #endif /* TCPCONN */
  40. #ifdef DNETCONN
  41. #include <netdnet/dn.h>
  42. #include <netdnet/dnetdb.h>
  43. #endif
  44.  
  45. #ifdef hpux
  46. # include <sys/utsname.h>
  47. # ifdef HAS_IFREQ
  48. #  include <net/if.h>
  49. # endif
  50. #else
  51. #if defined(SVR4) || defined(SYSV386)
  52. # include <sys/utsname.h>
  53. #endif
  54. #if defined(SYSV) && defined(SYSV386)
  55. # include <sys/stream.h>
  56. #endif
  57. # include <net/if.h>
  58. #endif /* hpux */
  59.  
  60. #include <netdb.h>
  61. #undef NULL
  62. #include <stdio.h>
  63. #include "dixstruct.h"
  64. #include "osdep.h"
  65.  
  66. Bool defeatAccessControl = FALSE;
  67.  
  68. #define acmp(a1, a2, len) bcmp((char *)(a1), (char *)(a2), len)
  69. #define acopy(a1, a2, len) bcopy((char *)(a1), (char *)(a2), len)
  70. #define addrEqual(fam, address, length, host) \
  71.              ((fam) == (host)->family &&\
  72.               (length) == (host)->len &&\
  73.               !acmp (address, (host)->addr, length))
  74.  
  75. #ifdef hpux
  76. #define getpeername(fd, from, fromlen)    hpux_getpeername(fd, from, fromlen)
  77. #endif
  78.  
  79. static int ConvertAddr(), CheckAddr();
  80. static Bool NewHost();
  81.  
  82. typedef struct _host {
  83.     short        family;
  84.     short        len;
  85.     unsigned char    *addr;
  86.     struct _host *next;
  87. } HOST;
  88.  
  89. #define MakeHost(h,l)    (h)=(HOST *) xalloc(sizeof *(h)+(l));\
  90.             (h)->addr=(unsigned char *) ((h) + 1);
  91. #define FreeHost(h)    xfree(h)
  92. static HOST *selfhosts = NULL;
  93. static HOST *validhosts = NULL;
  94. static int AccessEnabled = DEFAULT_ACCESS_CONTROL;
  95. static int LocalHostEnabled = FALSE;
  96. static int UsingXdmcp = FALSE;
  97.  
  98. /*
  99.  * called when authorization is not enabled to add the
  100.  * local host to the access list
  101.  */
  102.  
  103. EnableLocalHost ()
  104. {
  105.     if (!UsingXdmcp)
  106.     {
  107.     LocalHostEnabled = TRUE;
  108.     AddLocalHosts ();
  109.     }
  110. }
  111.  
  112. /*
  113.  * called at init time when XDMCP will be used; xdmcp always
  114.  * adds local hosts manually when needed
  115.  */
  116.  
  117. AccessUsingXdmcp ()
  118. {
  119.     UsingXdmcp = TRUE;
  120.     LocalHostEnabled = FALSE;
  121. }
  122.  
  123. #if defined(SVR4) || defined (SYSV386) || (defined (hpux) && ! defined (HAS_IFREQ))
  124. /* Define this host for access control.  Find all the hosts the OS knows about 
  125.  * for this fd and add them to the selfhosts list.
  126.  * hpux, SVR4, and SYSV386 do not have SIOCGIFCONF ioctl;
  127.  */
  128. DefineSelf (fd)
  129.     int fd;
  130. {
  131.     register int n;
  132.     int    len;
  133.     caddr_t    addr;
  134.     int        family;
  135.     register HOST    *host;
  136.  
  137.     struct utsname name;
  138.     register struct hostent  *hp;
  139.  
  140.     union {
  141.     struct  sockaddr   sa;
  142.     struct  sockaddr_in  in;
  143.     } saddr;
  144.     
  145.     struct    sockaddr_in    *inetaddr;
  146.  
  147.     /* Why not use gethostname()?  Well, at least on my system, I've had to
  148.      * make an ugly kernel patch to get a name longer than 8 characters, and
  149.      * uname() lets me access to the whole string (it smashes release, you
  150.      * see), whereas gethostname() kindly truncates it for me.
  151.      */
  152.     uname(&name);
  153.     hp = gethostbyname (name.nodename);
  154.     if (hp != NULL)
  155.     {
  156.     saddr.sa.sa_family = hp->h_addrtype;
  157.     inetaddr = (struct sockaddr_in *) (&(saddr.sa));
  158.     acopy ( hp->h_addr, &(inetaddr->sin_addr), hp->h_length);
  159.     len = sizeof(saddr.sa);
  160.     family = ConvertAddr ( &(saddr.sa), &len, &addr);
  161.     if ( family != -1 && family != FamilyLocal )
  162.     {
  163.         for (host = selfhosts;
  164.          host && !addrEqual (family, addr, len, host);
  165.          host = host->next) ;
  166.         if (!host)
  167.         {
  168.         /* add this host to the host list.    */
  169.         MakeHost(host,len)
  170.         if (host)
  171.         {
  172.             host->family = family;
  173.             host->len = len;
  174.             acopy ( addr, host->addr, len);
  175.             host->next = selfhosts;
  176.             selfhosts = host;
  177.         }
  178.         }
  179.     }
  180.     }
  181. }
  182.  
  183. #else
  184. /* Define this host for access control.  Find all the hosts the OS knows about 
  185.  * for this fd and add them to the selfhosts list.
  186.  */
  187. DefineSelf (fd)
  188.     int fd;
  189. {
  190.     char        buf[2048];
  191.     struct ifconf    ifc;
  192.     register int    n;
  193.     int         len;
  194.     pointer         addr;
  195.     int         family;
  196.     register HOST     *host;
  197.     register struct ifreq *ifr;
  198.     
  199. #ifdef DNETCONN
  200.     struct dn_naddr *dnaddr = getnodeadd(0);
  201.     /*
  202.      * AF_DECnet may not be listed in the interface list.  Instead use
  203.      * the supported library call to find out the local address (if any).
  204.      */
  205.     if (dnaddr)
  206.     {    
  207.     addr = (pointer) dnaddr;
  208.     len = dnaddr->a_len + sizeof(dnaddr->a_len);
  209.     family = AF_DECnet;
  210.     for (host = selfhosts;
  211.          host && !addrEqual (family, addr, len, host);
  212.          host = host->next)
  213.         ;
  214.         if (!host)
  215.     {
  216.         MakeHost(host,len)
  217.         if (host)
  218.         {
  219.         host->family = family;
  220.         host->len = len;
  221.         acopy(addr, host->addr, len);
  222.         host->next = selfhosts;
  223.         selfhosts = host;
  224.         }
  225.     }
  226.     }
  227. #endif
  228.     ifc.ifc_len = sizeof (buf);
  229.     ifc.ifc_buf = buf;
  230.     if (ioctl (fd, (int) SIOCGIFCONF, (pointer) &ifc) < 0)
  231.         Error ("Getting interface configuration");
  232.     for (ifr = ifc.ifc_req, n = ifc.ifc_len / sizeof (struct ifreq); --n >= 0;
  233.      ifr++)
  234.     {
  235.     len = sizeof(ifr->ifr_addr);
  236. #ifdef DNETCONN
  237.     /*
  238.      * DECnet was handled up above.
  239.      */
  240.     if (ifr->ifr_addr.sa_family == AF_DECnet)
  241.         continue;
  242. #endif /* DNETCONN */
  243.     family = ConvertAddr (&ifr->ifr_addr, &len, &addr);
  244.         if (family == -1 || family == FamilyLocal)
  245.         continue;
  246.         for (host = selfhosts;
  247.           host && !addrEqual (family, addr, len, host);
  248.          host = host->next)
  249.         ;
  250.         if (host)
  251.         continue;
  252.     MakeHost(host,len)
  253.     if (host)
  254.     {
  255.         host->family = family;
  256.         host->len = len;
  257.         acopy(addr, host->addr, len);
  258.         host->next = selfhosts;
  259.         selfhosts = host;
  260.     }
  261. #ifdef XDMCP
  262.     {
  263.         struct sockaddr broad_addr;
  264.  
  265.         /*
  266.          * If this isn't an Internet Address, don't register it.
  267.          */
  268.         if (family != FamilyInternet)
  269.         continue;
  270.  
  271.         /*
  272.           * ignore 'localhost' entries as they're not useful
  273.          * on the other end of the wire
  274.          */
  275.         if (len == 4 &&
  276.         addr[0] == 127 && addr[1] == 0 &&
  277.         addr[2] == 0 && addr[3] == 1)
  278.         continue;
  279.  
  280.         XdmcpRegisterConnection (family, (char *)addr, len);
  281.         broad_addr = ifr->ifr_addr;
  282.         ((struct sockaddr_in *) &broad_addr)->sin_addr.s_addr =
  283.         htonl (INADDR_BROADCAST);
  284. #ifdef SIOCGIFBRDADDR
  285.         {
  286.             struct ifreq    broad_req;
  287.     
  288.             broad_req = *ifr;
  289.         if (ioctl (fd, SIOCGIFFLAGS, (char *) &broad_req) != -1 &&
  290.             (broad_req.ifr_flags & IFF_BROADCAST) &&
  291.             (broad_req.ifr_flags & IFF_UP)
  292.             )
  293.         {
  294.             broad_req = *ifr;
  295.             if (ioctl (fd, SIOCGIFBRDADDR, &broad_req) != -1)
  296.             broad_addr = broad_req.ifr_addr;
  297.             else
  298.             continue;
  299.         }
  300.         else
  301.             continue;
  302.         }
  303. #endif
  304.         XdmcpRegisterBroadcastAddress ((struct sockaddr_in *) &broad_addr);
  305.     }
  306. #endif
  307.     }
  308. }
  309. #endif /* hpux && !HAS_IFREQ */
  310.  
  311. #ifdef XDMCP
  312. void
  313. AugmentSelf(from, len)
  314.     struct sockaddr *from;
  315.     int            len;
  316. {
  317.     int family;
  318.     pointer addr;
  319.     register HOST *host;
  320.  
  321.     family = ConvertAddr(from, &len, &addr);
  322.     if (family == -1 || family == FamilyLocal)
  323.     return;
  324.     for (host = selfhosts; host; host = host->next)
  325.     {
  326.     if (addrEqual(family, addr, len, host))
  327.         return;
  328.     }
  329.     MakeHost(host,len)
  330.     if (!host)
  331.     return;
  332.     host->family = family;
  333.     host->len = len;
  334.     acopy(addr, host->addr, len);
  335.     host->next = selfhosts;
  336.     selfhosts = host;
  337. }
  338. #endif
  339.  
  340. AddLocalHosts ()
  341. {
  342.     HOST    *self;
  343.  
  344.     for (self = selfhosts; self; self = self->next)
  345.     (void) NewHost (self->family, self->addr, self->len);
  346. }
  347.  
  348. /* Reset access control list to initial hosts */
  349. ResetHosts (display)
  350.     char *display;
  351. {
  352.     register HOST    *host;
  353.     char         hostname[120];
  354.     char        fname[32];
  355.     FILE        *fd;
  356.     char        *ptr;
  357.     union {
  358.         struct sockaddr    sa;
  359. #ifdef TCPCONN
  360.         struct sockaddr_in in;
  361. #endif /* TCPCONN */
  362. #ifdef DNETCONN
  363.         struct sockaddr_dn dn;
  364. #endif
  365.     }             saddr;
  366. #ifdef DNETCONN
  367.     struct nodeent     *np;
  368.     struct dn_naddr     dnaddr, *dnaddrp, *dnet_addr();
  369. #endif
  370.     int            family;
  371.     int            len;
  372.     pointer        addr;
  373.     register struct hostent *hp;
  374.  
  375.     AccessEnabled = defeatAccessControl ? FALSE : DEFAULT_ACCESS_CONTROL;
  376.     LocalHostEnabled = FALSE;
  377.     while (host = validhosts)
  378.     {
  379.         validhosts = host->next;
  380.         FreeHost (host);
  381.     }
  382.     strcpy (fname, "/etc/X");
  383.     strcat (fname, display);
  384.     strcat (fname, ".hosts");
  385.     if (fd = fopen (fname, "r")) 
  386.     {
  387.         while (fgets (hostname, sizeof (hostname), fd))
  388.     {
  389.         if (ptr = index (hostname, '\n'))
  390.             *ptr = 0;
  391. #ifdef DNETCONN
  392.         if ((ptr = index (hostname, ':')) && (*(ptr + 1) == ':'))
  393.     {
  394.             /* node name (DECnet names end in "::") */
  395.             *ptr = 0;
  396.         dnaddrp = dnet_addr(hostname);
  397.             if (!dnaddrp && (np = getnodebyname (hostname)))
  398.         {
  399.         /* node was specified by name */
  400.         saddr.sa.sa_family = np->n_addrtype;
  401.         len = sizeof(saddr.sa);
  402.         if (ConvertAddr (&saddr.sa, &len, &addr) == FamilyDECnet)
  403.         {
  404.             bzero ((char *) &dnaddr, sizeof (dnaddr));
  405.             dnaddr.a_len = np->n_length;
  406.             acopy (np->n_addr, dnaddr.a_addr, np->n_length);
  407.             dnaddrp = &dnaddr;
  408.         }
  409.             }
  410.         if (dnaddrp)
  411.         (void) NewHost((short)FamilyDECnet, (pointer)dnaddrp,
  412.             (int)(dnaddrp->a_len + sizeof(dnaddrp->a_len)));
  413.         }
  414.     else
  415. #endif /* DNETCONN */
  416. #ifdef SECURE_RPC
  417.     if (index (hostname, '@'))
  418.     {
  419.         SecureRPCInit ();
  420.         (void) NewHost (FamilyNetname, hostname, strlen (hostname));
  421.     }
  422.     else
  423. #endif /* SECURE_RPC */
  424. #ifdef TCPCONN
  425.     {
  426.             /* host name */
  427.             if (hp = gethostbyname (hostname))
  428.         {
  429.             saddr.sa.sa_family = hp->h_addrtype;
  430.         len = sizeof(saddr.sa);
  431.             if ((family = ConvertAddr (&saddr.sa, &len, &addr)) != -1)
  432.         {
  433. #ifdef h_addr                /* new 4.3bsd version of gethostent */
  434.             char **list;
  435.  
  436.             /* iterate over the addresses */
  437.             for (list = hp->h_addr_list; *list; list++)
  438.             (void) NewHost (family, (pointer)*list, len);
  439. #else
  440.                 (void) NewHost (family, (pointer)hp->h_addr, len);
  441. #endif
  442.         }
  443.             }
  444.         }    
  445. #endif /* TCPCONN */
  446.         }
  447.         fclose (fd);
  448.     }
  449. }
  450.  
  451. static Bool
  452. AuthorizedClient(client)
  453.     ClientPtr client;
  454. {
  455.     int            alen, family;
  456.     struct sockaddr    from;
  457.     pointer        addr;
  458.     register HOST    *host;
  459.  
  460.     if (!client || defeatAccessControl)
  461.     return TRUE;
  462.     alen = sizeof (from);
  463.     if (!getpeername (((OsCommPtr)client->osPrivate)->fd, &from, &alen))
  464.     {
  465.     family = ConvertAddr (&from, &alen, &addr);
  466.     if (family == -1)
  467.         return FALSE;
  468.     if (family == FamilyLocal)
  469.         return TRUE;
  470.     for (host = selfhosts; host; host = host->next)
  471.     {
  472.         if (addrEqual (family, addr, alen, host))
  473.         return TRUE;
  474.     }
  475.     }
  476.     return FALSE;
  477. }
  478.  
  479. /* Add a host to the access control list.  This is the external interface
  480.  * called from the dispatcher */
  481.  
  482. int
  483. AddHost (client, family, length, pAddr)
  484.     ClientPtr        client;
  485.     int                 family;
  486.     unsigned            length;        /* of bytes in pAddr */
  487.     pointer             pAddr;
  488. {
  489.     int            len;
  490.     register HOST    *host;
  491.     int                 unixFamily;
  492.  
  493.     if (!AuthorizedClient(client))
  494.     return(BadAccess);
  495.     switch (family) {
  496. #ifdef SECURE_RPC
  497.     case FamilyNetname:
  498.     len = length;
  499.     SecureRPCInit ();
  500.     break;
  501. #endif
  502.     case FamilyInternet:
  503.     case FamilyDECnet:
  504.     case FamilyChaos:
  505.     if ((len = CheckAddr (family, pAddr, length)) < 0)
  506.     {
  507.         client->errorValue = length;
  508.         return (BadValue);
  509.     }
  510.     break;
  511.     case FamilyLocal:
  512.     default:
  513.     client->errorValue = family;
  514.     return (BadValue);
  515.     }
  516.     if (NewHost (family, pAddr, len))
  517.     return Success;
  518.     return BadAlloc;
  519. }
  520.  
  521. Bool
  522. ForEachHostInFamily (family, func, closure)
  523.     int        family;
  524.     Bool    (*func)();
  525.     pointer closure;
  526. {
  527.     HOST    *host;
  528.  
  529.     for (host = validhosts; host; host = host->next)
  530.     if (family == host->family && func (host->addr, host->len, closure))
  531.         return TRUE;
  532.     return FALSE;
  533. }
  534.  
  535. /* Add a host to the access control list. This is the internal interface 
  536.  * called when starting or resetting the server */
  537. static Bool
  538. NewHost (family, addr, len)
  539.     short    family;
  540.     pointer    addr;
  541.     int        len;
  542. {
  543.     register HOST *host;
  544.  
  545.     for (host = validhosts; host; host = host->next)
  546.     {
  547.         if (addrEqual (family, addr, len, host))
  548.         return TRUE;
  549.     }
  550.     MakeHost(host,len)
  551.     if (!host)
  552.     return FALSE;
  553.     host->family = family;
  554.     host->len = len;
  555.     acopy(addr, host->addr, len);
  556.     host->next = validhosts;
  557.     validhosts = host;
  558.     return TRUE;
  559. }
  560.  
  561. /* Remove a host from the access control list */
  562.  
  563. int
  564. RemoveHost (client, family, length, pAddr)
  565.     ClientPtr        client;
  566.     int                 family;
  567.     unsigned            length;        /* of bytes in pAddr */
  568.     pointer             pAddr;
  569. {
  570.     int            len;
  571.     register HOST    *host, **prev;
  572.  
  573.     if (!AuthorizedClient(client))
  574.     return(BadAccess);
  575.     switch (family) {
  576. #ifdef SECURE_RPC
  577.     case FamilyNetname:
  578.     len = length;
  579.     break;
  580. #endif
  581.     case FamilyInternet:
  582.     case FamilyDECnet:
  583.     case FamilyChaos:
  584.         if ((len = CheckAddr (family, pAddr, length)) < 0)
  585.         {
  586.         client->errorValue = length;
  587.             return(BadValue);
  588.         }
  589.     break;
  590.     case FamilyLocal:
  591.     default:
  592.     client->errorValue = family;
  593.         return(BadValue);
  594.     }
  595.     for (prev = &validhosts;
  596.          (host = *prev) && (!addrEqual (family, pAddr, len, host));
  597.          prev = &host->next)
  598.         ;
  599.     if (host)
  600.     {
  601.         *prev = host->next;
  602.         FreeHost (host);
  603.     }
  604.     return (Success);
  605. }
  606.  
  607. /* Get all hosts in the access control list */
  608. int
  609. GetHosts (data, pnHosts, pLen, pEnabled)
  610.     pointer        *data;
  611.     int            *pnHosts;
  612.     int            *pLen;
  613.     BOOL        *pEnabled;
  614. {
  615.     int            len;
  616.     register int     n = 0;
  617.     register pointer    ptr;
  618.     register HOST    *host;
  619.     int            nHosts = 0;
  620.     int            *lengths = (int *) NULL;
  621.     int            *newlens;
  622.  
  623.     *pEnabled = AccessEnabled ? EnableAccess : DisableAccess;
  624.     for (host = validhosts; host; host = host->next)
  625.     {
  626.     newlens = (int *) xrealloc(lengths, (nHosts + 1) * sizeof(int));
  627.     if (!newlens)
  628.     {
  629.         xfree(lengths);
  630.         return(BadAlloc);
  631.     }
  632.     lengths = newlens;
  633.     lengths[nHosts++] = host->len;
  634.     n += (((host->len + 3) >> 2) << 2) + sizeof(xHostEntry);
  635.     }
  636.     if (n)
  637.     {
  638.         *data = ptr = (pointer) xalloc (n);
  639.     if (!ptr)
  640.     {
  641.         xfree(lengths);
  642.         return(BadAlloc);
  643.     }
  644.     nHosts = 0;
  645.         for (host = validhosts; host; host = host->next)
  646.     {
  647.  
  648.         len = lengths[nHosts++];
  649.         ((xHostEntry *)ptr)->family = host->family;
  650.         ((xHostEntry *)ptr)->length = len;
  651.         ptr += sizeof(xHostEntry);
  652.         acopy (host->addr, ptr, len);
  653.         ptr += ((len + 3) >> 2) << 2;
  654.         }
  655.     } else {
  656.     *data = NULL;
  657.     }
  658.     *pnHosts = nHosts;
  659.     *pLen = n;
  660.     xfree(lengths);
  661.     return(Success);
  662. }
  663.  
  664. /* Check for valid address family and length, and return address length. */
  665.  
  666. /*ARGSUSED*/
  667. static int
  668. CheckAddr (family, pAddr, length)
  669.     int            family;
  670.     pointer        pAddr;
  671.     unsigned        length;
  672. {
  673.     int    len;
  674.  
  675.     switch (family)
  676.     {
  677. #ifdef TCPCONN
  678.       case FamilyInternet:
  679.     if (length == sizeof (struct in_addr))
  680.         len = length;
  681.     else
  682.         len = -1;
  683.         break;
  684. #endif 
  685. #ifdef DNETCONN
  686.       case FamilyDECnet:
  687.         {
  688.         struct dn_naddr *dnaddr = (struct dn_naddr *) pAddr;
  689.  
  690.         if ((length < sizeof(dnaddr->a_len)) ||
  691.         (length < dnaddr->a_len + sizeof(dnaddr->a_len)))
  692.         len = -1;
  693.         else
  694.         len = dnaddr->a_len + sizeof(dnaddr->a_len);
  695.         if (len > sizeof(struct dn_naddr))
  696.         len = -1;
  697.     }
  698.         break;
  699. #endif
  700.       default:
  701.         len = -1;
  702.     }
  703.     return (len);
  704. }
  705.  
  706. /* Check if a host is not in the access control list. 
  707.  * Returns 1 if host is invalid, 0 if we've found it. */
  708.  
  709. InvalidHost (saddr, len)
  710.     register struct sockaddr    *saddr;
  711.     int                len;
  712. {
  713.     int             family;
  714.     pointer            addr;
  715.     register HOST         *selfhost, *host;
  716.  
  717.     if (!AccessEnabled)   /* just let them in */
  718.         return(0);    
  719.     family = ConvertAddr (saddr, &len, &addr);
  720.     if (family == -1)
  721.         return 1;
  722.     if (family == FamilyLocal)
  723.     {
  724.     if (!LocalHostEnabled)
  725.      {
  726.         /*
  727.          * check to see if any local address is enabled.  This 
  728.          * implicitly enables local connections.
  729.          */
  730.         for (selfhost = selfhosts; selfhost; selfhost=selfhost->next)
  731.          {
  732.         for (host = validhosts; host; host=host->next)
  733.         {
  734.             if (addrEqual (selfhost->family, selfhost->addr,
  735.                    selfhost->len, host))
  736.             return 0;
  737.         }
  738.         }
  739.         return 1;
  740.     } else
  741.         return 0;
  742.     }
  743.     for (host = validhosts; host; host = host->next)
  744.     {
  745.         if (addrEqual (family, addr, len, host))
  746.             return (0);
  747.     }
  748.     return (1);
  749. }
  750.  
  751. static int
  752. ConvertAddr (saddr, len, addr)
  753.     register struct sockaddr    *saddr;
  754.     int                *len;
  755.     pointer            *addr;
  756. {
  757.     if (*len == 0)
  758.         return (FamilyLocal);
  759.     switch (saddr->sa_family)
  760.     {
  761.     case AF_UNSPEC:
  762. #ifdef UNIXCONN
  763.     case AF_UNIX:
  764. #endif
  765.         return FamilyLocal;
  766. #ifdef TCPCONN
  767.     case AF_INET:
  768.         *len = sizeof (struct in_addr);
  769.         *addr = (pointer) &(((struct sockaddr_in *) saddr)->sin_addr);
  770.         return FamilyInternet;
  771. #endif
  772. #ifdef DNETCONN
  773.     case AF_DECnet:
  774.     {
  775.         struct sockaddr_dn *sdn = (struct sockaddr_dn *) saddr;
  776.         *len = sdn->sdn_nodeaddrl + sizeof(sdn->sdn_nodeaddrl);
  777.         *addr = (pointer) &(sdn->sdn_add);
  778.     }
  779.         return FamilyDECnet;
  780. #endif
  781. #ifdef CHAOSCONN
  782.     case AF_CHAOS:
  783.     {
  784.         not implemented
  785.     }
  786.     return FamilyChaos;
  787. #endif
  788.     default:
  789.         return -1;
  790.     }
  791. }
  792.  
  793. int
  794. ChangeAccessControl(client, fEnabled)
  795.     ClientPtr client;
  796.     int fEnabled;
  797. {
  798.     if (!AuthorizedClient(client))
  799.     return BadAccess;
  800.     AccessEnabled = fEnabled;
  801.     return Success;
  802. }
  803.