home *** CD-ROM | disk | FTP | other *** search
/ The CDPD Public Domain Collection for CDTV 4 / CDPD_IV.bin / networking / tcpip / amitcp-support / wustl-ftpdaemon / src / private.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-29  |  8.6 KB  |  287 lines

  1. /* Copyright (c) 1993, 1994  Washington University in Saint Louis
  2.  * All rights reserved.
  3.  *
  4.  * Redistribution and use in source and binary forms, with or without
  5.  * modification, are permitted provided that the following conditions are
  6.  * met: 1. Redistributions of source code must retain the above copyright
  7.  * notice, this list of conditions and the following disclaimer. 2.
  8.  * Redistributions in binary form must reproduce the above copyright notice,
  9.  * this list of conditions and the following disclaimer in the documentation
  10.  * and/or other materials provided with the distribution. 3. All advertising
  11.  * materials mentioning features or use of this software must display the
  12.  * following acknowledgement: This product includes software developed by the
  13.  * Washington University in Saint Louis and its contributors. 4. Neither the
  14.  * name of the University nor the names of its contributors may be used to
  15.  * endorse or promote products derived from this software without specific
  16.  * prior written permission.
  17.  *
  18.  * THIS SOFTWARE IS PROVIDED BY WASHINGTON UNIVERSITY AND CONTRIBUTORS
  19.  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20.  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  21.  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASHINGTON
  22.  * UNIVERSITY OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  23.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  24.  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  25.  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  26.  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  27.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  28.  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  29.  * POSSIBILITY OF SUCH DAMAGE.
  30.  */
  31.  
  32. #ifndef NO_PRIVATE
  33.  
  34. #include "config.h"
  35.  
  36. #include <stdio.h>
  37. #include <errno.h>
  38. #include <string.h>
  39. #ifdef SYSSYSLOG
  40. #include <sys/syslog.h>
  41. #else
  42. #include <syslog.h>
  43. #endif
  44. #include <grp.h>
  45.  
  46. #include <sys/types.h>
  47. #include <sys/stat.h>
  48. #ifndef AMIGA
  49. #include <sys/file.h>
  50. #endif
  51.  
  52. #include "pathnames.h"
  53. #include "extensions.h"
  54.  
  55. #define MAXGROUPLEN 100
  56. char *passbuf = NULL;
  57. char groupname[MAXGROUPLEN];
  58. int group_given = 0;
  59.  
  60. struct acgrp {
  61.     char  gname[MAXGROUPLEN];    /* access group name */
  62.     char  gpass[MAXGROUPLEN];    /* access group password */
  63.     char  gr_name[MAXGROUPLEN];  /* group to setgid() to */
  64.     gid_t gr_gid;
  65.     struct acgrp *next;
  66. };
  67.  
  68. struct acgrp *privptr;
  69.  
  70. extern int lgi_failure_threshold,
  71.   autospout_free;
  72. extern char remotehost[],
  73.   remoteaddr[],
  74.  *autospout;
  75. int group_attempts;
  76.  
  77. void
  78. parsepriv(void)
  79. {
  80.     char *ptr;
  81.     char *acptr = passbuf,
  82.      *line;
  83.     char **argv[51],
  84.     **ap = (char **) argv,
  85.      *p,
  86.      *val;
  87.     struct acgrp *aptr;
  88.     struct group *gr;
  89.  
  90.     if (!passbuf || !(*passbuf))
  91.         return;
  92.  
  93.     /* build list, initialize to zero. */
  94.     privptr = (struct acgrp *) calloc(1, sizeof(struct acgrp));
  95.  
  96.     /* read through passbuf, stripping comments. */
  97.     while (*acptr != '\0') {
  98.         line = acptr;
  99.         while (*acptr && *acptr != '\n')
  100.             acptr++;
  101.         *acptr++ = '\0';
  102.  
  103.         /* deal with comments */
  104.         if ((ptr = strchr(line, '#')) != NULL)
  105.             *ptr = '\0';
  106.  
  107.         if (*line == '\0')
  108.             continue;
  109.  
  110.         ap = (char **) argv;
  111.  
  112.         /* parse the lines... */
  113.         for (p = line; p != NULL;) {
  114.             while ((val = (char *) strsep(&p, ":\n")) != NULL
  115.                    && *val == '\0') ;
  116.             *ap = val;
  117.             if (**ap == ' ')
  118.                 *ap = NULL;
  119.             *ap++;
  120.         }
  121.         *ap = 0;
  122.  
  123.         if ((gr = getgrnam((char *) argv[2])) != NULL)  {
  124.             aptr = (struct acgrp *) calloc(1, sizeof(struct acgrp));
  125.             
  126.             /* if we didn't read 3 things, skip that line... */
  127.  
  128.             /* add element to beginning of list */
  129.  
  130.             aptr->next = privptr;
  131.             privptr = aptr;
  132.  
  133.             strcpy(aptr->gname, (char *) argv[0]);
  134.             strcpy(aptr->gpass, (char *) argv[1]);
  135.             strcpy(aptr->gr_name, (char *) argv[2]);
  136.             aptr->gr_gid = gr->gr_gid;
  137.         }
  138.     }
  139. }
  140.  
  141. /*************************************************************************/
  142. /* FUNCTION  : priv_setup                                                */
  143. /* PURPOSE   : Set things up to use the private access password file.    */
  144. /* ARGUMENTS : path, the path to the private access password file        */
  145. /*************************************************************************/
  146.  
  147. void
  148. priv_setup(char *path)
  149. {
  150.     FILE *prvfile;
  151.     struct stat finfo;
  152.  
  153.     passbuf = (char *) NULL;
  154.  
  155.     if (stat(path, &finfo) != 0) {
  156.         syslog(LOG_ERR, "cannot stat private access file %s: %s", path,
  157.                strerror(errno));
  158.         return;
  159.     }
  160.     if ((prvfile = fopen(path, "r")) == NULL) {
  161.         if (errno != ENOENT)
  162.             syslog(LOG_ERR, "cannot open private access file %s: %s",
  163.                    path, strerror(errno));
  164.         return;
  165.     }
  166.     if (finfo.st_size == 0) {
  167.         passbuf = (char *) calloc(1, 1);
  168.     } else {
  169.         if (!(passbuf = malloc((unsigned) finfo.st_size + 1))) {
  170.             (void) syslog(LOG_ERR, "could not malloc passbuf (%d bytes)",
  171.                           finfo.st_size + 1);
  172.             return;
  173.         }
  174.         if (!fread(passbuf, (size_t) finfo.st_size, 1, prvfile)) {
  175.             (void) syslog(LOG_ERR, "error reading private access file %s: %s",
  176.                           path, strerror(errno));
  177.         }
  178.         *(passbuf + finfo.st_size) = '\0';
  179.     }
  180.  
  181.     (void) parsepriv();
  182. }
  183.  
  184. /*************************************************************************/
  185. /* FUNCTION  : priv_getent                                               */
  186. /* PURPOSE   : Retrieve an entry from the in-memory copy of the group    */
  187. /* access file.                                              */
  188. /* ARGUMENTS : pointer to group name                                     */
  189. /*************************************************************************/
  190.  
  191. struct acgrp *
  192. priv_getent(char *group)
  193. {
  194.     struct acgrp *ptr;
  195.  
  196.     for (ptr = privptr; ptr; ptr=ptr->next)
  197.         if (!strcmp(group, ptr->gname))
  198.             return(ptr);
  199.  
  200.     return (NULL);
  201. }
  202.  
  203. /*************************************************************************/
  204. /* FUNCTION  : priv_group                                                */
  205. /* PURPOSE   :                                                           */
  206. /* ARGUMENTS :                                                           */
  207. /*************************************************************************/
  208.  
  209. void
  210. priv_group(char *group)
  211. {
  212.     if (strlen(group) < MAXGROUPLEN) {
  213.         strncpy(groupname, group, MAXGROUPLEN);
  214.         group_given = 1;
  215.         reply(200, "Request for access to group %s accepted.", group);
  216.     } else {
  217.         group_given = 0;
  218.         reply(500, "Illegal group name");
  219.     }
  220.  
  221. }
  222.  
  223. /*************************************************************************/
  224. /* FUNCTION  : priv_gpass                                                */
  225. /* PURPOSE   : validate the group access request, and if OK place user   */
  226. /* in the proper group.                                      */
  227. /* ARGUMENTS : group access password                                     */
  228. /*************************************************************************/
  229.  
  230. void
  231. priv_gpass(char *gpass)
  232. {
  233.     char *xgpass,
  234.      *salt;
  235. #ifndef NO_CRYPT_PROTO
  236.     char *crypt(const char *, const char *);
  237. #endif
  238.     struct acgrp *grp;
  239.     uid_t uid;
  240.     gid_t gid;
  241.  
  242.     if (group_given == 0) {
  243.         reply(503, "Give group name with SITE GROUP first.");
  244.         return;
  245.     }
  246.     /* OK, now they're getting a chance to specify a password.  Make them
  247.      * give the group name again if they fail... */
  248.     group_given = 0;
  249.  
  250.     if (passbuf != NULL) {
  251.         grp = priv_getent(groupname);
  252.  
  253.         if (grp == NULL)
  254.             salt = "xx";
  255.         else
  256.             salt = grp->gpass;
  257.  
  258.         xgpass = crypt(gpass, salt);
  259.     } else
  260.         grp = NULL;
  261.  
  262.     /* The strcmp does not catch null passwords! */
  263.     if (grp == NULL || *grp->gpass == '\0' || strcmp(xgpass, grp->gpass)) {
  264.         reply(530, "Group access request incorrect.");
  265.         grp = NULL;
  266.         if (++group_attempts >= lgi_failure_threshold) {
  267.             syslog(LOG_NOTICE,
  268.                    "repeated group access failures from %s [%s], group %s",
  269.                    remotehost, remoteaddr, groupname);
  270.             exit(0);
  271.         }
  272.         sleep(group_attempts);  /* slow down password crackers */
  273.         return;
  274.     }
  275.  
  276.     uid = geteuid();
  277.     gid = grp->gr_gid;
  278.  
  279.     seteuid(0);
  280.     setegid(gid);
  281.     seteuid(uid);
  282.  
  283.     reply(200, "Group access enabled.");
  284.     group_attempts = 0;
  285. }
  286. #endif /* !NO_PRIVATE */
  287.