home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / UNIX / Networking / wu-ftpd-2.4.2b13-MIHS / src / private.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-03-03  |  9.4 KB  |  329 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 lint
  33. static char rcsid[] = "@(#)$Id: private.c,v 1.8 1997/01/16 09:54:38 sob Exp $";
  34. #endif /* not lint */
  35.  
  36. #ifndef NO_PRIVATE
  37.  
  38. #include "config.h"
  39.  
  40. #include <stdio.h>
  41. #include <errno.h>
  42. #include <string.h>
  43. #ifdef SYSSYSLOG
  44. #include <sys/syslog.h>
  45. #else
  46. #include <syslog.h>
  47. #endif
  48. #include <grp.h>
  49.  
  50. #include <sys/types.h>
  51. #include <sys/stat.h>
  52. #include <sys/file.h>
  53.  
  54. #include "pathnames.h"
  55. #include "extensions.h"
  56.  
  57. #define MAXGROUPLEN 100
  58. char *passbuf = NULL;
  59. char groupname[MAXGROUPLEN];
  60. int group_given = 0;
  61.  
  62. struct acgrp {
  63.     char  gname[MAXGROUPLEN];    /* access group name */
  64.     char  gpass[MAXGROUPLEN];    /* access group password */
  65.     char  gr_name[MAXGROUPLEN];  /* group to setgid() to */
  66.     gid_t gr_gid;
  67.     struct acgrp *next;
  68. };
  69.  
  70. struct acgrp *privptr;
  71.  
  72. extern int lgi_failure_threshold,
  73.   autospout_free;
  74. extern char remotehost[],
  75.   remoteaddr[],
  76.  *autospout;
  77. int group_attempts;
  78.  
  79. void
  80. #ifdef __STDC__
  81. parsepriv(void)
  82. #else
  83. parsepriv()
  84. #endif
  85. {
  86.     char *ptr;
  87.     char *acptr = passbuf,
  88.      *line;
  89.     char **argv[51],
  90.     **ap = (char **) argv,
  91.      *p,
  92.      *val;
  93.     struct acgrp *aptr;
  94.     struct group *gr;
  95.  
  96.     if (!passbuf || !(*passbuf))
  97.         return;
  98.  
  99.     /* build list, initialize to zero. */
  100.     privptr = (struct acgrp *) calloc(1, sizeof(struct acgrp));
  101.  
  102.     /* read through passbuf, stripping comments. */
  103.     while (*acptr != '\0') {
  104.         line = acptr;
  105.         while (*acptr && *acptr != '\n')
  106.             acptr++;
  107.         *acptr++ = '\0';
  108.  
  109.         /* deal with comments */
  110.         if ((ptr = strchr(line, '#')) != NULL)
  111.             *ptr = '\0';
  112.  
  113.         if (*line == '\0')
  114.             continue;
  115.  
  116.         ap = (char **) argv;
  117.  
  118.         /* parse the lines... */
  119.         for (p = line; p != NULL;) {
  120.             while ((val = (char *) strsep(&p, ":\n")) != NULL
  121.                    && *val == '\0') ;
  122.             *ap = val;
  123.             if (**ap == ' ')
  124.                 *ap = NULL;
  125.             *ap++;
  126.         }
  127.         *ap = 0;
  128.  
  129.         if ((gr = getgrnam((char *) argv[2])) != NULL)  {
  130.             aptr = (struct acgrp *) calloc(1, sizeof(struct acgrp));
  131.             
  132.             /* if we didn't read 3 things, skip that line... */
  133.  
  134.             /* add element to beginning of list */
  135.  
  136.             aptr->next = privptr;
  137.             privptr = aptr;
  138.  
  139.             strcpy(aptr->gname, (char *) argv[0]);
  140.             strcpy(aptr->gpass, (char *) argv[1]);
  141.             strcpy(aptr->gr_name, (char *) argv[2]);
  142.             aptr->gr_gid = gr->gr_gid;
  143.         }
  144.     endgrent();
  145.     }
  146. }
  147.  
  148. /*************************************************************************/
  149. /* FUNCTION  : priv_setup                                                */
  150. /* PURPOSE   : Set things up to use the private access password file.    */
  151. /* ARGUMENTS : path, the path to the private access password file        */
  152. /*************************************************************************/
  153.  
  154. void
  155. #ifdef __STDC__
  156. priv_setup(char *path)
  157. #else
  158. priv_setup(path)
  159. char *path;
  160. #endif
  161. {
  162.     FILE *prvfile;
  163.     struct stat finfo;
  164.  
  165.     passbuf = (char *) NULL;
  166.  
  167.     if ((prvfile = fopen(path, "r")) == NULL) {
  168.         if (errno != ENOENT)
  169.             syslog(LOG_ERR, "cannot open private access file %s: %s",
  170.                    path, strerror(errno));
  171.         return;
  172.     }
  173.     if (fstat(fileno(prvfile), &finfo) != 0) {
  174.         syslog(LOG_ERR, "cannot fstat private access file %s: %s", path,
  175.                strerror(errno));
  176.         (void) fclose(prvfile);
  177.         return;
  178.     }
  179.     if (finfo.st_size == 0) {
  180.         passbuf = (char *) calloc(1, 1);
  181.     } else {
  182.         if (!(passbuf = (char *)malloc((unsigned) finfo.st_size + 1))) {
  183.             (void) syslog(LOG_ERR, "could not malloc passbuf (%d bytes)",
  184.                           finfo.st_size + 1);
  185.             (void) fclose(prvfile);
  186.             return;
  187.         }
  188.         if (!fread(passbuf, (size_t) finfo.st_size, 1, prvfile)) {
  189.             (void) syslog(LOG_ERR, "error reading private access file %s: %s",
  190.                           path, strerror(errno));
  191.             (void) fclose(prvfile);
  192.             return;
  193.         }
  194.         *(passbuf + finfo.st_size) = '\0';
  195.     }
  196.     (void) fclose(prvfile);
  197.     (void) parsepriv();
  198. }
  199.  
  200. /*************************************************************************/
  201. /* FUNCTION  : priv_getent                                               */
  202. /* PURPOSE   : Retrieve an entry from the in-memory copy of the group    */
  203. /* access file.                                              */
  204. /* ARGUMENTS : pointer to group name                                     */
  205. /*************************************************************************/
  206.  
  207. struct acgrp *
  208. #ifdef __STDC__
  209. priv_getent(char *group)
  210. #else
  211. priv_getent(group)
  212. char *group;
  213. #endif
  214. {
  215.     struct acgrp *ptr;
  216.  
  217.     for (ptr = privptr; ptr; ptr=ptr->next)
  218.         if (!strcmp(group, ptr->gname))
  219.             return(ptr);
  220.  
  221.     return (NULL);
  222. }
  223.  
  224. /*************************************************************************/
  225. /* FUNCTION  : priv_group                                                */
  226. /* PURPOSE   :                                                           */
  227. /* ARGUMENTS :                                                           */
  228. /*************************************************************************/
  229.  
  230. void
  231. #ifdef __STDC__
  232. priv_group(char *group)
  233. #else
  234. priv_group(group)
  235. char *group;
  236. #endif
  237. {
  238.     if ((int)strlen(group) < MAXGROUPLEN) {
  239.         strncpy(groupname, group, MAXGROUPLEN);
  240.         group_given = 1;
  241.         reply(200, "Request for access to group %s accepted.", group);
  242.     } else {
  243.         group_given = 0;
  244.         reply(500, "Illegal group name");
  245.     }
  246.  
  247. }
  248.  
  249. /*************************************************************************/
  250. /* FUNCTION  : priv_gpass                                                */
  251. /* PURPOSE   : validate the group access request, and if OK place user   */
  252. /* in the proper group.                                      */
  253. /* ARGUMENTS : group access password                                     */
  254. /*************************************************************************/
  255.  
  256. void
  257. #ifdef __STDC__
  258. priv_gpass(char *gpass)
  259. #else
  260. priv_gpass(gpass)
  261. char *gpass;
  262. #endif
  263. {
  264.     char *xgpass,
  265.      *salt;
  266. #ifndef NO_CRYPT_PROTO
  267. #ifdef __STDC__
  268.     char *crypt(const char *, const char *);
  269. #else
  270. #ifdef _M_UNIX
  271.     char *crypt(const char *, const char *);
  272. #else
  273.     char *crypt();
  274. #endif
  275. #endif
  276. #endif
  277.     struct acgrp *grp;
  278.     struct group *gr;
  279.     uid_t uid;
  280.     gid_t gid;
  281.  
  282.     if (group_given == 0) {
  283.         reply(503, "Give group name with SITE GROUP first.");
  284.         return;
  285.     }
  286.     /* OK, now they're getting a chance to specify a password.  Make them
  287.      * give the group name again if they fail... */
  288.     group_given = 0;
  289.  
  290.     if (passbuf != NULL) {
  291.         grp = priv_getent(groupname);
  292.  
  293.         if (grp == NULL)
  294.             salt = "xx"; /* XXX */
  295.         else
  296.             salt = grp->gpass;
  297.  
  298.         xgpass = crypt(gpass, salt);
  299.     } else
  300.         grp = NULL;
  301.  
  302.     /* The strcmp does not catch null passwords! */
  303.     if (grp == NULL || *grp->gpass == '\0' || strcmp(xgpass, grp->gpass)) {
  304.         reply(530, "Group access request incorrect.");
  305.         grp = NULL;
  306.         if (++group_attempts >= lgi_failure_threshold) {
  307.             syslog(LOG_NOTICE,
  308.                    "repeated group access failures from %s [%s], group %s",
  309.                    remotehost, remoteaddr, groupname);
  310.             exit(0);
  311.         }
  312.         sleep(group_attempts);  /* slow down password crackers */
  313.         return;
  314.     }
  315.  
  316.     uid = geteuid();
  317.     gid = grp->gr_gid;
  318.  
  319.     delay_signaling(); /* we can't allow any signals while euid==0: kinch */
  320.     seteuid(0);
  321.     setegid(gid);
  322.     seteuid(uid);
  323.     enable_signaling(); /* we can allow signals once again: kinch */
  324.  
  325.     reply(200, "Group access enabled.");
  326.     group_attempts = 0;
  327. }
  328. #endif /* !NO_PRIVATE */
  329.