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_init.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-10  |  8.1 KB  |  346 lines

  1. /*
  2.  * auth_init.c    This module takes care of request authorization.
  3.  *
  4.  * Authors:    Donald J. 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. #define LINE_SIZE    1024
  16. #define CHUNK_SIZE    1024    /* the 'typical' maximum line length    */
  17.  
  18. #ifndef EXPORTSFILE
  19. #define EXPORTSFILE    "/etc/exports"
  20. #endif
  21.  
  22. clnt_param *clients = NULL;
  23. clnt_param *unknown_clients = NULL;
  24. clnt_param *default_client = NULL;
  25. exportnode *export_list = NULL;
  26. int allow_non_root = 0;
  27. int promiscuous = 0;
  28. int re_export = 0;
  29. int auth_initialized = 0;
  30. int trace_spoof = 1;
  31. options default_options = {
  32.     identity, 1, 1, 0, 0
  33. };
  34.  
  35. /*
  36.  * These are extern vars in nfsd.h where they are used to determine
  37.  * file system attributes.
  38.  */
  39. struct svc_req        *svc_rqstp;
  40. int            client_authenticate;
  41.  
  42. static _PRO(int filt_getc, (FILE *));
  43. static _PRO(int getline, (char **, FILE *));
  44. static _PRO(char *parse_opts, (char *, char, options *, char *));
  45. static _PRO(char *h_strerror, (int));
  46.  
  47. static int filt_getc(f)
  48. FILE *f;
  49. {
  50.     int c;
  51.  
  52.     c = getc(f);
  53.     if (c == '\\') {
  54.         c = getc(f);
  55.         if (c == '\n')
  56.             return (' ');
  57.         if (c != EOF)
  58.             ungetc(c, f);
  59.         return ('\\');
  60.     } else if (c == '#') {
  61.         int lastc = c;
  62.         while ((c = getc(f)) != '\n' && c != EOF)
  63.             lastc = c;
  64.         if (c == '\n' && lastc == '\\')
  65.             c = getc(f);
  66.     }
  67.     return (c);
  68. }
  69.  
  70. static int getline(lbuf, f)
  71. char **lbuf;
  72. FILE *f;
  73. {
  74.     register c;
  75.     register char *p;
  76.     char *buf;
  77.     int sz = CHUNK_SIZE;
  78.  
  79.     if ((buf = malloc(CHUNK_SIZE)) == NULL)
  80.         mallocfailed();
  81.     p = buf;
  82.     while ((c = filt_getc(f)) != '\n' && c != EOF) {
  83.         if (p - buf == sz - 2) {
  84.             if ((buf = realloc(buf, sz * 2)) == NULL)
  85.                 mallocfailed();
  86.             p = buf + sz - 2;
  87.             sz *= 2;
  88.         }
  89.         *p++ = c;
  90.     }
  91.     if (c == EOF && p == buf) {
  92.         free(buf);
  93.         *lbuf = NULL;
  94.         return (0);
  95.     }
  96.     *p++ = '\0';
  97.     *lbuf = buf;
  98.     return (1);
  99. }
  100.  
  101. /* Parse option string pointed to by s and set o accordingly. */
  102. static char *parse_opts(cp, terminator, o, client_name)
  103. char *cp;
  104. char terminator;
  105. options *o;
  106. char *client_name;
  107. {
  108.     char kwdbuf[LINE_SIZE];
  109.     char *k;
  110.  
  111.     /* skip white */
  112.     while (isspace(*cp))
  113.         cp++;
  114.     while (*cp != terminator) {
  115.         k = kwdbuf;
  116.         while (isalnum(*cp) || *cp == '_')
  117.             *k++ = *cp++;
  118.         *k = '\0';
  119.  
  120.         /* process keyword */
  121.         if (strcmp(kwdbuf, "secure") == 0)
  122.             o->secure_port = 1;
  123.         else if (strcmp(kwdbuf, "insecure") == 0)
  124.             o->secure_port = 0;
  125.         else if (strcmp(kwdbuf, "root_squash") == 0)
  126.             o->root_squash = 1;
  127.         else if (strcmp(kwdbuf, "no_root_squash") == 0)
  128.             o->root_squash = 0;
  129.         else if (strcmp(kwdbuf, "ro") == 0)
  130.             o->read_only = 1;
  131.         else if (strcmp(kwdbuf, "rw") == 0)
  132.             o->read_only = 0;
  133.         else if (strcmp(kwdbuf, "link_relative") == 0)
  134.             o->link_relative = 1;
  135.         else if (strcmp(kwdbuf, "link_absolute") == 0)
  136.             o->link_relative = 0;
  137.         else if (strcmp(kwdbuf, "map_daemon") == 0)
  138.             o->uidmap = map_daemon;
  139.         else if (strcmp(kwdbuf, "map_identity") == 0)
  140.             o->uidmap = identity;
  141.         else
  142.             dprintf(0, "Unknown keyword \"%s\"\n", kwdbuf);
  143.         while (isspace(*cp))
  144.             cp++;
  145.         if (*cp == terminator)
  146.             break;
  147.         if (*cp == ',')
  148.             cp++;
  149.         else if (!isalnum(*cp) && *cp != '_' && *cp != '\0') {
  150.             if (client_name == NULL)
  151.                 dprintf(0,
  152.                     "Comma expected in opt list for dflt clnt (found '%c')\n", *cp);
  153.             else
  154.                 dprintf(0,
  155.                     "Comma expected in opt list for clnt %s (found '%c')\n",
  156.                     client_name, *cp);
  157.         }
  158.         while (isspace(*cp))
  159.             cp++;
  160.  
  161.         if (*cp == '\0' && *cp != terminator) {
  162.             dprintf(0, "missing terminator \"%c\" on option list\n",
  163.                 terminator);
  164.             return (cp);
  165.         }
  166.     }
  167.     if (*cp != terminator)
  168.         dprintf(0, "Trouble in parser, character '%c'.\n", *cp);
  169.  
  170.     cp++;            /* Skip past terminator */
  171.     while (isspace(*cp))
  172.         cp++;
  173.     return (cp);
  174. }
  175.  
  176. void auth_init(fname)
  177. char *fname;
  178. {
  179.     FILE *ef;
  180.     char *cp;        /* Current line position */
  181.     char *sp;        /* Secondary pointer */
  182.     char *fs_name;
  183.     clnt_param *new_param;
  184.     exportnode *resex;
  185.     groupnode *resgr;
  186.     char path[PATH_MAX];
  187.     char resolved_path[PATH_MAX];
  188.  
  189.     if (fname == NULL)
  190.         fname = EXPORTSFILE;
  191.  
  192.     if ((ef = fopen(fname, "r")) == NULL) {
  193.         dprintf(0, "Could not open exports file %s: %s\n",
  194.             fname, strerror(errno));
  195.         exit(1);
  196.     }
  197.     while (getline(&cp, ef)) {
  198.         char *saved_line = cp;    /* For free()ing it later. */
  199.         char *mount_point, *host_name;
  200.         struct hostent *hent;
  201.  
  202.         /* Check for "empty" lines. */
  203.         if (*cp == '\0')
  204.             continue;
  205.  
  206.         while (isspace(*cp))
  207.             cp++;
  208.  
  209.         /* Get the file-system name. */
  210.         fs_name = cp;
  211.         while (*cp != '\0' && !isspace(*cp))
  212.             cp++;
  213.         for (sp = path; fs_name < cp;)
  214.             *sp++ = *fs_name++;
  215.         *sp = '\0';
  216.  
  217.         /* Make sure it's symlink-free, if possible. */
  218.         if (realpath(path, resolved_path) == NULL)
  219.             strcpy(resolved_path, path);
  220.  
  221.         /* Copy it into a new string. */
  222.         if ((mount_point = malloc(strlen(resolved_path) + 1)) == NULL)
  223.             mallocfailed();
  224.         strcpy(mount_point, resolved_path);
  225.  
  226.         /* Build the RPC mount export list data structure. */
  227.         if ((resex = malloc(sizeof *resex)) == NULL)
  228.             mallocfailed();
  229.         resex->ex_dir = mount_point;
  230.         resex->ex_groups = NULL;
  231.         resex->ex_next = export_list;
  232.         export_list = resex;
  233.  
  234.         while (isspace(*cp))
  235.             cp++;
  236.  
  237. #ifndef NEW_STYLE_EXPORTS_FILE
  238.         /* Special case for anononymous NFS. */
  239.         if (*cp == '\0' || *cp == '(') {
  240.             new_param = (clnt_param *) malloc(sizeof *new_param);
  241.             if (new_param == NULL)
  242.                 mallocfailed();
  243.             new_param->clnt_name = NULL;
  244.             new_param->mount_point = mount_point;
  245.             new_param->o = default_options;
  246.             new_param->next = unknown_clients;
  247.             unknown_clients = new_param;
  248.             if (*cp == '(')
  249.                 cp = parse_opts(cp + 1, ')',
  250.                         &(new_param->o),
  251.                         new_param->clnt_name);
  252.         }
  253.         while (*cp != '\0') {
  254.             host_name = cp;
  255.  
  256.             /* Host name. */
  257.             while (*cp != '\0' && !isspace(*cp) && *cp != '(')
  258.                 cp++;
  259.             new_param = (clnt_param *) malloc(sizeof *new_param);
  260.             if (new_param == NULL ||
  261.                 (new_param->clnt_name = malloc(cp - host_name + 1)) == NULL)
  262.                 mallocfailed();
  263.             for (sp = new_param->clnt_name; host_name < cp;)
  264.                 *sp++ = *host_name++;
  265.             *sp = '\0';
  266.  
  267.             /* Finish parsing options. */
  268.             new_param->o = default_options;
  269.             while (isspace(*cp))
  270.                 cp++;
  271.             if (*cp == '(')
  272.                 cp = parse_opts(cp + 1, ')', &(new_param->o),
  273.                         new_param->clnt_name);
  274.  
  275.             new_param->mount_point = mount_point;
  276.             if ((resgr = malloc(sizeof *resgr)) == NULL)
  277.                 mallocfailed();
  278.             resgr->gr_name = new_param->clnt_name;
  279.             resgr->gr_next = resex->ex_groups;
  280.             resex->ex_groups = resgr;
  281.  
  282.             if (strchr(new_param->clnt_name, '*') ||
  283.                 strchr(new_param->clnt_name, '?')) {
  284.                 /* Add this host pattern to the unknown list. */
  285.                 new_param->next = unknown_clients;
  286.                 unknown_clients = new_param;
  287.             } else if ((hent = gethostbyname(new_param->clnt_name)) == NULL) {
  288.                 dprintf(0, "Unknown host %s in %s (%s)\n",
  289.                     new_param->clnt_name, fname,
  290.                     h_strerror(h_errno));
  291.  
  292.                 /* Add this loser to the list of unknowns. */
  293.                 new_param->next = unknown_clients;
  294.                 unknown_clients = new_param;
  295.             } else {
  296.                 /*
  297.                  * This should be changed to handle the address
  298.                  * list under BSD 4.3 and compatible systems.
  299.                  */
  300.                 new_param->clnt_addr = *((struct in_addr *) hent->h_addr);
  301.                 new_param->next = clients;    /* Add to client list */
  302.                 clients = new_param;
  303.             }
  304.         }
  305. #endif
  306.         free(saved_line);
  307.     }
  308.     fclose(ef);
  309.  
  310.     if (promiscuous) {
  311.         if ((new_param = (clnt_param *) malloc(sizeof *new_param)) == NULL)
  312.             mallocfailed();
  313.         new_param->clnt_name = NULL;
  314.         new_param->mount_point = NULL;
  315.         default_client = new_param;
  316.         new_param->o = default_options;
  317.     }
  318.     auth_initialized = 1;
  319. }
  320.  
  321. static char *h_strerror(errnum)
  322. int errnum;
  323. {
  324.     char *reason;
  325.  
  326.     switch (h_errno) {
  327. #ifdef HOST_NOT_FOUND        /* Only on BSD 4.3 and compatible systems. */
  328.     case HOST_NOT_FOUND:
  329.         reason = "Authoritative -- the host exists only in your imagination.";
  330.         break;
  331.     case TRY_AGAIN:
  332.         reason = "Non-Authoritative -- the host might exist.";
  333.         break;
  334.     case NO_RECOVERY:
  335.         reason = "Non-recoverable error.";
  336.         break;
  337.     case NO_ADDRESS:
  338.         reason = "Valid host name, but no address.";
  339.         break;
  340. #endif
  341.     default:
  342.         reason = "Unknown reason.";
  343.     }
  344.     return reason;
  345. }
  346.