home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1996 May / PCOnline_05_1996.bin / linux / source / n / tcpip / nfs-serv.1 / nfs-serv / nfs-server-2.1 / auth_clnt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-11  |  5.6 KB  |  228 lines

  1. /*
  2.  * auth_clnt.c    This module takes care of request authorization.
  3.  *
  4.  * Authors:    Don Becker, <becker@super.org>
  5.  *        Rick Sladkey, <jrs@world.std.com>
  6.  *        Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  7.  *
  8.  *        This software maybe be used for any purpose provided
  9.  *        the above copyright notice is retained.  It is supplied
  10.  *        as is, with no warranty expressed or implied.
  11.  */
  12.  
  13. #include "nfsd.h"
  14.  
  15. #ifndef svc_getcaller
  16. #define svc_getcaller(x) ((struct sockaddr_in *) &(x)->xp_rtaddr.buf)
  17. #endif
  18.  
  19. static _PRO(int hostmatch, (struct hostent *, char *));
  20. static _PRO(int pathmatch, (char *, char *));
  21.  
  22. static int hostmatch(hent, pattern)
  23. struct hostent *hent;
  24. char *pattern;
  25. {
  26.     const char *hname = hent->h_name;
  27.     int seen_dot = 0;
  28.  
  29. #ifdef AUTH_DEBUG
  30.     dprintf(1, "host matching %s to %s\n", hname, pattern);
  31. #endif
  32.  
  33.     for (;;) {
  34.         if (*hname == '\0' || *pattern == '\0')
  35.             return (*hname == *pattern);
  36.         switch (*pattern) {
  37.         case '*':
  38.             while (*hname != '.' && *hname != '\0')
  39.                 hname++;
  40.             seen_dot = 1;
  41.             pattern++;
  42.             break;
  43.         case '?':
  44.             if (*hname == '.')
  45.                 return (0);
  46.             hname++;
  47.             pattern++;
  48.             break;
  49.         default:
  50.             if (seen_dot) {
  51.                 if (tolower(*hname) != tolower(*pattern))
  52.                     return (0);
  53.             }
  54.             else if (*hname != *pattern)
  55.                 return (0);
  56.             if (*pattern == '.')
  57.                 seen_dot = 1;
  58.             hname++;
  59.             pattern++;
  60.             break;
  61.         }
  62.     }
  63. }
  64.  
  65. static int pathmatch(path, pattern)
  66. char *path;
  67. char *pattern;
  68. {
  69.     int len, c;
  70.  
  71.     if (!path || !pattern)
  72.         return (1);
  73. #ifdef AUTH_DEBUG
  74.     dprintf(1, "path matching %s to %s\n", path, pattern);
  75. #endif
  76.     len = strlen(pattern);
  77.     if (strncmp(path, pattern, len) == 0 &&
  78.         ((len && pattern[len - 1] == '/') ||
  79.         ((c = path[len]) == '/') || c == '\0'))
  80.         return (1);
  81.     return (0);
  82. }
  83.  
  84. clnt_param *auth_clnt(rqstp, path)
  85. struct svc_req *rqstp;
  86. char *path;
  87. {
  88.     clnt_param **cpp, *cp, *ncp;
  89.     long addr = svc_getcaller(rqstp->rq_xprt)->sin_addr.s_addr;
  90.     int known_client = 0;
  91.  
  92.     /* Find host parameter struct. */
  93.     for (cpp = &clients; *cpp != NULL; cpp = &((*cpp)->next)) {
  94.         if ((*cpp)->clnt_addr.s_addr == addr) {
  95.             cp = *cpp;
  96.             if (path == NULL || pathmatch(path, cp->mount_point)) {
  97.                 if (cp != clients) {
  98.                     /* Move to front. */
  99.                     *cpp = cp->next;
  100.                     cp->next = clients;
  101.                     clients = cp;
  102.                 }
  103.                 goto found_it;
  104.             }
  105.             known_client = 1;
  106.         }
  107.     }
  108.  
  109.     /* Check the list of patterns or clients we didn't know at start-up. */
  110.     for (cpp = &unknown_clients; (cp = *cpp) != NULL; ) {
  111.         struct hostent *hent;
  112.  
  113.         if (!pathmatch(path, cp->mount_point)) {
  114.             cpp = &(cp->next);    /* the normal iteration    */
  115.             continue;
  116.         }
  117.         if (cp->clnt_name == NULL) {
  118.             if ((ncp = malloc(sizeof *ncp)) == NULL)
  119.                 mallocfailed();
  120.             *ncp = *cp;
  121.             ncp->clnt_addr = svc_getcaller(rqstp->rq_xprt)->sin_addr;
  122.             ncp->next = clients;
  123.             clients = ncp;
  124. #ifdef AUTH_DEBUG
  125.             dprintf(1, "anonymous NFS request from %s\n",
  126.                 inet_ntoa(*(struct in_addr *) &addr));
  127. #endif
  128.             goto found_it;
  129.         }
  130.         else if (strchr(cp->clnt_name, '*')
  131.             || strchr(cp->clnt_name, '?')) {
  132.             hent = gethostbyaddr((char *) &addr, sizeof addr,
  133.                 AF_INET);
  134.             if (hent && hostmatch(hent, cp->clnt_name)) {
  135.                 /*
  136.                  * Resolved client entry inherits properties
  137.                  * from pattern.
  138.                  */
  139.                 if ((ncp = malloc(sizeof *ncp)) == NULL)
  140.                     mallocfailed();
  141.                 *ncp = *cp;
  142.                 ncp->clnt_addr = *((struct in_addr *)
  143.                     hent->h_addr);
  144.                 if ((ncp->clnt_name = malloc(strlen(hent->h_name) + 1)) == NULL)
  145.                     mallocfailed();
  146.                 strcpy(ncp->clnt_name, hent->h_name);
  147.                 ncp->next = clients;
  148.                 clients = ncp;
  149. #ifdef AUTH_DEBUG
  150.                 dprintf(1, "requester %s matched pattern %s\n",
  151.                     ncp->clnt_name, cp->clnt_name);
  152. #endif
  153.                 goto found_it;
  154.             }
  155.             cpp = &(cp->next);    /* the normal iteration    */
  156.         }
  157.         else if ((hent = gethostbyname(cp->clnt_name)) != NULL) {
  158.             cp->clnt_addr = *((struct in_addr *) hent->h_addr);
  159.  
  160.             /* Remove from "unknown clients" list. */
  161.             *cpp = cp->next;
  162.  
  163.             /* Add to the front of "known clients" list. */
  164.             cp->next = clients;
  165.             clients = cp;
  166.  
  167. #ifdef AUTH_DEBUG
  168.             dprintf(1, "Found previously unknown host %s.\n",
  169.                 cp->clnt_name);
  170. #endif
  171.             if (cp->clnt_addr.s_addr == addr)
  172.                 goto found_it;
  173.         }
  174.         else
  175.             cpp = &(cp->next);    /* normal iteration    */
  176.  
  177.         if (default_client != NULL &&
  178.             pathmatch(path, default_client->mount_point)) {
  179.             cp = default_client;
  180.         }
  181.         else if (!known_client || trace_spoof) {
  182.             dprintf(0, "Unknown NFS client %s tried to access %s\n",
  183.                 inet_ntoa(*(struct in_addr *) &addr), path);
  184.             return (NULL);
  185.         }
  186.         else
  187.             return (NULL);
  188.     }
  189.  
  190.     /* If we got here, they tried to mount a short path. */
  191.     if (!cp) {
  192.         if (!known_client || trace_spoof) {
  193.             dprintf(0, "Unknown NFS client %s tried to access %s\n",
  194.                 inet_ntoa(*(struct in_addr *) &addr), path);
  195.         }
  196.         return (NULL);
  197.     }
  198.  
  199. found_it:
  200.     /* Check request originated on a privileged port. */
  201.     if (!allow_non_root && cp->o.secure_port &&
  202.         ntohs(svc_getcaller(rqstp->rq_xprt)->sin_port) >= IPPORT_RESERVED) {
  203.         dprintf(0, "NFS request from %s originated on insecure port, %s\n",
  204.             inet_ntoa(*(struct in_addr *) &addr),
  205.             "psychoanalysis suggested");
  206.         return (NULL);
  207.     }
  208.  
  209.     /* Check for the root squash option. If we were so inclined,
  210.      * we could also implement the ugidd stuff here... later.
  211.      */
  212.     if ((rqstp->rq_cred.oa_flavor == AUTH_UNIX) && cp->o.root_squash) {
  213.         struct authunix_parms *unix_cred;
  214.         int    i;
  215.  
  216.         unix_cred = (struct authunix_parms *) rqstp->rq_clntcred;
  217.         if (!unix_cred->aup_uid)
  218.             unix_cred->aup_uid = NOBODY_UID;
  219.         if (!unix_cred->aup_gid)
  220.             unix_cred->aup_gid = NOBODY_GID;
  221.         for (i = 0; i < unix_cred->aup_len; i++) {
  222.             if (!unix_cred->aup_gids[i])
  223.                 unix_cred->aup_gids[i] = NOBODY_GID;
  224.         }
  225.     }
  226.     return (cp);
  227. }
  228.