access.c
上传用户:zibowangxu
上传日期:2007-01-04
资源大小:331k
文件大小:39k
源码类别:

Ftp客户端

开发平台:

Unix_Linux

  1. /****************************************************************************  
  2.  
  3.   Copyright (c) 1999 WU-FTPD Development Group.  
  4.   All rights reserved.
  5.   
  6.   Portions Copyright (c) 1980, 1985, 1988, 1989, 1990, 1991, 1993, 1994
  7.     The Regents of the University of California.
  8.   Portions Copyright (c) 1993, 1994 Washington University in Saint Louis.
  9.   Portions Copyright (c) 1996, 1998 Berkeley Software Design, Inc.
  10.   Portions Copyright (c) 1989 Massachusetts Institute of Technology.
  11.   Portions Copyright (c) 1998 Sendmail, Inc.
  12.   Portions Copyright (c) 1983, 1995, 1996, 1997 Eric P.  Allman.
  13.   Portions Copyright (c) 1997 by Stan Barber.
  14.   Portions Copyright (c) 1997 by Kent Landfield.
  15.   Portions Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996, 1997
  16.     Free Software Foundation, Inc.  
  17.  
  18.   Use and distribution of this software and its source code are governed 
  19.   by the terms and conditions of the WU-FTPD Software License ("LICENSE").
  20.  
  21.   If you did not receive a copy of the license, it may be obtained online
  22.   at http://www.wu-ftpd.org/license.html.
  23.  
  24.   $Id: access.c,v 1.28 1999/10/03 13:13:08 wuftpd Exp $
  25.  
  26. ****************************************************************************/
  27. #include "config.h"
  28. #include <stdio.h>
  29. #include <errno.h>
  30. #include <string.h>
  31. #include <stdlib.h>
  32. #ifdef HAVE_SYS_SYSLOG_H
  33. #include <sys/syslog.h>
  34. #elif defined(HAVE_SYSLOG_H) || !defined(AUTOCONF)
  35. #include <syslog.h>
  36. #endif
  37. #ifdef TIME_WITH_SYS_TIME
  38. #include <time.h>
  39. #include <sys/time.h>
  40. #elif defined(HAVE_SYS_TIME_H)
  41. #include <sys/time.h>
  42. #else
  43. #include <time.h>
  44. #endif
  45. #include <ctype.h>
  46. #include <pwd.h>
  47. #include <grp.h>
  48. #include <sys/types.h>
  49. #include <sys/stat.h>
  50. #include <sys/file.h>
  51. #include <sys/param.h>
  52. #ifdef HAVE_PATHS_H
  53. #include <paths.h>
  54. #endif
  55. #include "pathnames.h"
  56. #include "extensions.h"
  57. #include "proto.h"
  58. #if defined(HAVE_FCNTL_H)
  59. #include <fcntl.h>
  60. #endif
  61. extern char remotehost[], remoteaddr[], *remoteident, *aclbuf;
  62. extern int nameserved, anonymous, guest, TCPwindowsize, use_accessfile;
  63. extern mode_t defumask;
  64. char Shutdown[MAXPATHLEN];
  65. int keepalive = 0;
  66. #define MAXLINE 80
  67. static char incline[MAXLINE];
  68. int pidfd = -1;
  69. extern int Bypass_PID_Files;
  70. #ifndef HELP_CRACKERS
  71. extern char DelayedMessageFile[];
  72. #endif
  73. #include "wu_fnmatch.h"
  74. extern void load_timeouts(void);
  75. /*************************************************************************/
  76. /* FUNCTION  : parse_time                                                */
  77. /* PURPOSE   : Check a single valid-time-string against the current time */
  78. /*             and return whether or not a match occurs.                 */
  79. /* ARGUMENTS : a pointer to the time-string                              */
  80. /*************************************************************************/
  81. int parsetime(char *whattime)
  82. {
  83.     static char *days[] =
  84.     {"Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Wk"};
  85.     time_t clock;
  86.     struct tm *curtime;
  87.     int wday, start, stop, ltime, validday, loop, match;
  88.     (void) time(&clock);
  89.     curtime = localtime(&clock);
  90.     wday = curtime->tm_wday;
  91.     validday = 0;
  92.     match = 1;
  93.     while (match && isalpha(*whattime) && isupper(*whattime)) {
  94. match = 0;
  95. for (loop = 0; loop < 8; loop++) {
  96.     if (strncmp(days[loop], whattime, 2) == 0) {
  97. whattime += 2;
  98. match = 1;
  99. if ((wday == loop) || ((loop == 7) && wday && (wday < 6))) {
  100.     validday = 1;
  101. }
  102.     }
  103. }
  104.     }
  105.     if (!validday) {
  106. if (strncmp(whattime, "Any", 3) == 0) {
  107.     validday = 1;
  108.     whattime += 3;
  109. }
  110. else
  111.     return (0);
  112.     }
  113.     if (sscanf(whattime, "%d-%d", &start, &stop) == 2) {
  114. ltime = curtime->tm_min + 100 * curtime->tm_hour;
  115. if ((start < stop) && ((ltime >= start) && ltime < stop))
  116.     return (1);
  117. if ((start > stop) && ((ltime >= start) || ltime < stop))
  118.     return (1);
  119.     }
  120.     else
  121. return (1);
  122.     return (0);
  123. }
  124. /*************************************************************************/
  125. /* FUNCTION  : validtime                                                 */
  126. /* PURPOSE   : Break apart a set of valid time-strings and pass them to  */
  127. /*             parse_time, returning whether or not ANY matches occurred */
  128. /* ARGUMENTS : a pointer to the time-string                              */
  129. /*************************************************************************/
  130. int validtime(char *ptr)
  131. {
  132.     char *nextptr;
  133.     int good;
  134.     while (1) {
  135. nextptr = strchr(ptr, '|');
  136. if (strchr(ptr, '|') == NULL)
  137.     return (parsetime(ptr));
  138. *nextptr = '';
  139. good = parsetime(ptr);
  140. /* gotta restore the | or things get skipped! */
  141. *nextptr++ = '|';
  142. if (good)
  143.     return (1);
  144. ptr = nextptr;
  145.     }
  146. }
  147. /*************************************************************************/
  148. /* FUNCTION  : hostmatch                                                 */
  149. /* PURPOSE   : Match remote hostname or address against a glob string    */
  150. /* ARGUMENTS : The string to match                                       */
  151. /* RETURNS   : 0 if no match, 1 if a match occurs                        */
  152. /*************************************************************************/
  153. int hostmatch(char *addr, char *remoteaddr, char *remotehost)
  154. {
  155.     FILE *incfile;
  156.     char *ptr;
  157.     int found = 1;
  158.     int not_found = 0;
  159.     int match = 0;
  160.     int i, a[4], m[4], r[4], cidr;
  161.     if (addr == NULL)
  162. return (0);
  163.     if (*addr == '!') {
  164. found = 0;
  165. not_found = 1;
  166. addr++;
  167.     }
  168.     if (sscanf(addr, "%d.%d.%d.%d/%d", a, a + 1, a + 2, a + 3, &cidr) == 5) {
  169. m[0] = 0;
  170. m[1] = 0;
  171. m[2] = 0;
  172. m[3] = 0;
  173. if (cidr < 0)
  174.     cidr = 0;
  175. else if (cidr > 32)
  176.     cidr = 32;
  177. for (i = 0; cidr > 8; i++) {
  178.     m[i] = 255;
  179.     cidr -= 8;
  180. }
  181. switch (cidr) {
  182. case 8:
  183.     m[i] += 1;
  184. case 7:
  185.     m[i] += 2;
  186. case 6:
  187.     m[i] += 4;
  188. case 5:
  189.     m[i] += 8;
  190. case 4:
  191.     m[i] += 16;
  192. case 3:
  193.     m[i] += 32;
  194. case 2:
  195.     m[i] += 64;
  196. case 1:
  197.     m[i] += 128;
  198. }
  199. sscanf(remoteaddr, "%d.%d.%d.%d", r, r + 1, r + 2, r + 3);
  200. for (i = 0; i < 4; i++)
  201.     if ((a[i] & m[i]) != (r[i] & m[i]))
  202. return not_found;
  203. return found;
  204.     }
  205.     else if (sscanf(addr, "%d.%d.%d.%d:%d.%d.%d.%d", a, a + 1, a + 2, a + 3, m, m + 1, m + 2, m + 3) == 8) {
  206. sscanf(remoteaddr, "%d.%d.%d.%d", r, r + 1, r + 2, r + 3);
  207. for (i = 0; i < 4; i++)
  208.     if ((a[i] & m[i]) != (r[i] & m[i]))
  209. return not_found;
  210. return found;
  211.     }
  212.     else if (sscanf(addr, "%d.%d.%d.%d", a, a + 1, a + 2, a + 3) == 4) {
  213. sscanf(remoteaddr, "%d.%d.%d.%d", r, r + 1, r + 2, r + 3);
  214. for (i = 0; i < 4; i++)
  215.     if (a[i] != r[i])
  216. return not_found;
  217. return found;
  218.     }
  219.     else if (sscanf(addr, "%d.%d.%d.*", a, a + 1, a + 2) == 3) {
  220. sscanf(remoteaddr, "%d.%d.%d.%d", r, r + 1, r + 2, r + 3);
  221. for (i = 0; i < 3; i++)
  222.     if (a[i] != r[i])
  223. return not_found;
  224. return found;
  225.     }
  226.     else if (sscanf(addr, "%d.%d.*.*", a, a + 1) == 2) {
  227. sscanf(remoteaddr, "%d.%d.%d.%d", r, r + 1, r + 2, r + 3);
  228. for (i = 0; i < 2; i++)
  229.     if (a[i] != r[i])
  230. return not_found;
  231. return found;
  232.     }
  233.     else if (sscanf(addr, "%d.*.*.*", a) == 1) {
  234. sscanf(remoteaddr, "%d.%d.%d.%d", r, r + 1, r + 2, r + 3);
  235. for (i = 0; i < 1; i++)
  236.     if (a[i] != r[i])
  237. return not_found;
  238. return found;
  239.     }
  240.     else if (*addr == '/') {
  241. /*
  242.  * read addrglobs from named path using similar format as addrglobs
  243.  * in access file
  244.  */
  245. if ((incfile = fopen(addr, "r")) == NULL) {
  246.     if (errno != ENOENT)
  247. syslog(LOG_ERR,
  248.        "cannot open addrglob file %s: %m", addr);
  249.     return (0);
  250. }
  251. while (!match && (fgets(incline, MAXLINE, incfile) != NULL)) {
  252.     ptr = strtok(incline, " tn");
  253.     if (ptr && hostmatch(ptr, remoteaddr, remotehost))
  254. match = 1;
  255.     while (!match && ((ptr = strtok(NULL, " tn")) != NULL)) {
  256. if (ptr && hostmatch(ptr, remoteaddr, remotehost))
  257.     match = 1;
  258.     }
  259. }
  260. fclose(incfile);
  261. return (match ? found : not_found);
  262.     }
  263.     else { /* match a hostname or hostname glob */
  264. match = !wu_fnmatch(addr, remotehost, FNM_CASEFOLD);
  265. return (match ? found : not_found);
  266.     }
  267. }
  268. /*************************************************************************/
  269. /* FUNCTION  : acl_guestgroup                                            */
  270. /* PURPOSE   : If the real user is a member of any of the listed groups, */
  271. /*             return 1.  Otherwise return 0.                            */
  272. /* ARGUMENTS : pw, a pointer to the passwd struct for the user           */
  273. /*************************************************************************/
  274. int acl_guestgroup(struct passwd *pw)
  275. {
  276.     struct aclmember *entry = NULL;
  277.     struct group *grp;
  278.     int which;
  279.     char **member;
  280.     /*
  281.      * guestuser <name> [<name> ...]
  282.      *
  283.      * If name begins with '%' treat as numeric.
  284.      * Numeric names may be ranges.
  285.      *   %<uid>       A single numeric UID
  286.      *   %<uid>+      All UIDs greater or equal to UID
  287.      *   %<uid>-      All UIDs greater or equal to UID
  288.      *   %-<uid>      All UIDs less or equal to UID
  289.      *   %<uid>-<uid> All UIDs between the two (inclusive)
  290.      *   *            All UIDs
  291.      */
  292.     while (getaclentry("guestuser", &entry)) {
  293. for (which = 0; (which < MAXARGS) && ARG[which]; which++) {
  294.     if (!strcmp(ARG[which], "*"))
  295. return (1);
  296.     if (ARG[which][0] == '%') {
  297. char *ptr = strchr(ARG[which] + 1, '-');
  298. if (!ptr) {
  299.     ptr = strchr(ARG[which] + 1, '+');
  300.     if (!ptr) {
  301. if (pw->pw_uid == strtoul(ARG[which] + 1, NULL, 0))
  302.     return (1);
  303.     }
  304.     else {
  305. *ptr++ = '';
  306. if ((ARG[which][1] == '')
  307.     || (pw->pw_uid >= strtoul(ARG[which] + 1, NULL, 0))) {
  308.     *--ptr = '+';
  309.     return (1);
  310. }
  311. *--ptr = '+';
  312.     }
  313. }
  314. else {
  315.     *ptr++ = '';
  316.     if (((ARG[which][1] == '')
  317.  || (pw->pw_uid >= strtoul(ARG[which] + 1, NULL, 0)))
  318. && ((*ptr == '')
  319.     || (pw->pw_uid <= strtoul(ptr, NULL, 0)))) {
  320. *--ptr = '-';
  321. return (1);
  322.     }
  323.     *--ptr = '-';
  324. }
  325.     }
  326.     else {
  327. struct passwd *g_pw = getpwnam(ARG[which]);
  328. if (g_pw && (g_pw->pw_uid == pw->pw_uid))
  329.     return (1);
  330.     }
  331. }
  332.     }
  333.     /*
  334.      * guestgroup <group> [<group> ...]
  335.      *
  336.      * If group begins with '%' treat as numeric.
  337.      * Numeric groups may be ranges.
  338.      *   %<gid>       A single GID
  339.      *   %<gid>+      All GIDs greater or equal to GID
  340.      *   %<gid>-      All GIDs greater or equal to GID
  341.      *   %-<gid>      All GIDs less or equal to GID
  342.      *   %<gid>-<gid> All GIDs between the two (inclusive)
  343.      *   *            All GIDs
  344.      */
  345.     while (getaclentry("guestgroup", &entry)) {
  346. for (which = 0; (which < MAXARGS) && ARG[which]; which++) {
  347.     if (!strcmp(ARG[which], "*"))
  348. return (1);
  349.     if (ARG[which][0] == '%') {
  350. char *ptr = strchr(ARG[which] + 1, '-');
  351. if (!ptr) {
  352.     ptr = strchr(ARG[which] + 1, '+');
  353.     if (!ptr) {
  354. if (pw->pw_gid == strtoul(ARG[which] + 1, NULL, 0))
  355.     return (1);
  356.     }
  357.     else {
  358. *ptr++ = '';
  359. if ((ARG[which][1] == '')
  360.     || (pw->pw_gid >= strtoul(ARG[which] + 1, NULL, 0))) {
  361.     *--ptr = '+';
  362.     return (1);
  363. }
  364. *--ptr = '+';
  365.     }
  366. }
  367. else {
  368.     *ptr++ = '';
  369.     if (((ARG[which][1] == '')
  370.  || (pw->pw_gid >= strtoul(ARG[which] + 1, NULL, 0)))
  371. && ((*ptr == '')
  372.     || (pw->pw_gid <= strtoul(ptr, NULL, 0)))) {
  373. *--ptr = '-';
  374. return (1);
  375.     }
  376.     *--ptr = '-';
  377. }
  378.     }
  379.     else {
  380. if ((grp = getgrnam(ARG[which]))) {
  381.     if (grp->gr_gid == pw->pw_gid)
  382. return (1);
  383.     for (member = grp->gr_mem; *member; member++)
  384. if (!strcasecmp(*member, pw->pw_name))
  385.     return (1);
  386. }
  387.     }
  388. }
  389.     }
  390.     return (0);
  391. }
  392. int acl_realgroup(struct passwd *pw)
  393. {
  394.     struct aclmember *entry = NULL;
  395.     struct group *grp;
  396.     int which;
  397.     char **member;
  398.     /*
  399.      * realuser <name> [<name> ...]
  400.      *
  401.      * If name begins with '%' treat as numeric.
  402.      * Numeric names may be ranges.
  403.      *   %<uid>       A single numeric UID
  404.      *   %<uid>+      All UIDs greater or equal to UID
  405.      *   %<uid>-      All UIDs greater or equal to UID
  406.      *   %-<uid>      All UIDs less or equal to UID
  407.      *   %<uid>-<uid> All UIDs between the two (inclusive)
  408.      *   *            All UIDs
  409.      */
  410.     while (getaclentry("realuser", &entry)) {
  411. for (which = 0; (which < MAXARGS) && ARG[which]; which++) {
  412.     if (!strcmp(ARG[which], "*"))
  413. return (1);
  414.     if (ARG[which][0] == '%') {
  415. char *ptr = strchr(ARG[which] + 1, '-');
  416. if (!ptr) {
  417.     ptr = strchr(ARG[which] + 1, '+');
  418.     if (!ptr) {
  419. if (pw->pw_uid == strtoul(ARG[which] + 1, NULL, 0))
  420.     return (1);
  421.     }
  422.     else {
  423. *ptr++ = '';
  424. if ((ARG[which][1] == '')
  425.     || (pw->pw_uid >= strtoul(ARG[which] + 1, NULL, 0))) {
  426.     *--ptr = '+';
  427.     return (1);
  428. }
  429. *--ptr = '+';
  430.     }
  431. }
  432. else {
  433.     *ptr++ = '';
  434.     if (((ARG[which][1] == '')
  435.  || (pw->pw_uid >= strtoul(ARG[which] + 1, NULL, 0)))
  436. && ((*ptr == '')
  437.     || (pw->pw_uid <= strtoul(ptr, NULL, 0)))) {
  438. *--ptr = '-';
  439. return (1);
  440.     }
  441.     *--ptr = '-';
  442. }
  443.     }
  444.     else {
  445. struct passwd *g_pw = getpwnam(ARG[which]);
  446. if (g_pw && (g_pw->pw_uid == pw->pw_uid))
  447.     return (1);
  448.     }
  449. }
  450.     }
  451.     /*
  452.      * realgroup <group> [<group> ...]
  453.      *
  454.      * If group begins with '%' treat as numeric.
  455.      * Numeric groups may be ranges.
  456.      *   %<gid>       A single GID
  457.      *   %<gid>+      All GIDs greater or equal to GID
  458.      *   %<gid>-      All GIDs greater or equal to GID
  459.      *   %-<gid>      All GIDs less or equal to GID
  460.      *   %<gid>-<gid> All GIDs between the two (inclusive)
  461.      *   *            All GIDs
  462.      */
  463.     while (getaclentry("realgroup", &entry)) {
  464. for (which = 0; (which < MAXARGS) && ARG[which]; which++) {
  465.     if (!strcmp(ARG[which], "*"))
  466. return (1);
  467.     if (ARG[which][0] == '%') {
  468. char *ptr = strchr(ARG[which] + 1, '-');
  469. if (!ptr) {
  470.     ptr = strchr(ARG[which] + 1, '+');
  471.     if (!ptr) {
  472. if (pw->pw_gid == strtoul(ARG[which] + 1, NULL, 0))
  473.     return (1);
  474.     }
  475.     else {
  476. *ptr++ = '';
  477. if ((ARG[which][1] == '')
  478.     || (pw->pw_gid >= strtoul(ARG[which] + 1, NULL, 0))) {
  479.     *--ptr = '+';
  480.     return (1);
  481. }
  482. *--ptr = '+';
  483.     }
  484. }
  485. else {
  486.     *ptr++ = '';
  487.     if (((ARG[which][1] == '')
  488.  || (pw->pw_gid >= strtoul(ARG[which] + 1, NULL, 0)))
  489. && ((*ptr == '')
  490.     || (pw->pw_gid <= strtoul(ptr, NULL, 0)))) {
  491. *--ptr = '-';
  492. return (1);
  493.     }
  494.     *--ptr = '-';
  495. }
  496.     }
  497.     else {
  498. if ((grp = getgrnam(ARG[which]))) {
  499.     if (grp->gr_gid == pw->pw_gid)
  500. return (1);
  501.     for (member = grp->gr_mem; *member; member++)
  502. if (!strcasecmp(*member, pw->pw_name))
  503.     return (1);
  504. }
  505.     }
  506. }
  507.     }
  508.     return (0);
  509. }
  510. /*************************************************************************/
  511. /* FUNCTION  : acl_autogroup                                             */
  512. /* PURPOSE   : If the guest user is a member of any of the classes in    */
  513. /*             the autogroup comment, cause a setegid() to the specified */
  514. /*             group.                                                    */
  515. /* ARGUMENTS : pw, a pointer to the passwd struct for the user           */
  516. /*************************************************************************/
  517. void acl_autogroup(struct passwd *pw)
  518. {
  519.     char class[1024];
  520.     struct aclmember *entry = NULL;
  521.     struct group *grp;
  522.     int which;
  523.     (void) acl_getclass(class);
  524.     /* autogroup <group> <class> [<class> ...] */
  525.     while (getaclentry("autogroup", &entry)) {
  526. if (!ARG0 || !ARG1)
  527.     continue;
  528. for (which = 1; (which < MAXARGS) && ARG[which]; which++) {
  529.     if (!strcasecmp(ARG[which], class)) {
  530. if (ARG0[0] == '%')
  531.     pw->pw_gid = atoi(ARG0 + 1);
  532. else {
  533.     if ((grp = getgrnam(ARG0)))
  534. pw->pw_gid = grp->gr_gid;
  535.     else
  536. syslog(LOG_ERR, "autogroup: set group %s not found", ARG0);
  537.     endgrent();
  538. }
  539. return;
  540.     }
  541. }
  542.     }
  543. }
  544. /*************************************************************************/
  545. /* FUNCTION  : acl_setfunctions                                          */
  546. /* PURPOSE   : Scan the ACL buffer and determine what logging to perform */
  547. /*             for this user, and whether or not user is allowed to use  */
  548. /*             the automatic TAR and COMPRESS functions.  Also, set the  */
  549. /*             current process priority of this copy of the ftpd server  */
  550. /*             to a `nice' value value if this user is a member of a     */
  551. /*             group which the ftpaccess file says should be nice'd.     */
  552. /* ARGUMENTS : pointer to buffer to class name, pointer to ACL buffer    */
  553. /*************************************************************************/
  554. void acl_setfunctions(void)
  555. {
  556.     char class[1024];
  557.     extern int log_incoming_xfers, log_outbound_xfers, mangleopts, log_commands,
  558.         log_security, syslogmsg, lgi_failure_threshold;
  559.     struct aclmember *entry = NULL;
  560.     int l_compress, l_tar, inbound = 0, outbound = 0, which, set;
  561.     log_incoming_xfers = 0;
  562.     log_outbound_xfers = 0;
  563.     log_commands = 0;
  564.     log_security = 0;
  565.     memset((void *) &class[0], 0, sizeof(class));
  566.     (void) acl_getclass(class);
  567.     entry = (struct aclmember *) NULL;
  568.     if (getaclentry("loginfails", &entry) && ARG0 != NULL) {
  569. lgi_failure_threshold = atoi(ARG0);
  570.     }
  571. #ifndef NO_PRIVATE
  572.     entry = (struct aclmember *) NULL;
  573.     if (getaclentry("private", &entry) && !strcasecmp(ARG0, "yes"))
  574. priv_setup(_path_private);
  575. #endif /* !NO_PRIVATE */
  576.     entry = (struct aclmember *) NULL;
  577.     set = 0;
  578.     while (!set && getaclentry("compress", &entry)) {
  579. l_compress = 0;
  580. if (!strcasecmp(ARG0, "yes"))
  581.     l_compress = 1;
  582. for (which = 1; (which < MAXARGS) && ARG[which]; which++) {
  583.     if (!wu_fnmatch(ARG[which], class, FNM_CASEFOLD)) {
  584. mangleopts |= l_compress * (O_COMPRESS | O_UNCOMPRESS);
  585. set = 1;
  586.     }
  587. }
  588.     }
  589.     entry = (struct aclmember *) NULL;
  590.     set = 0;
  591.     while (!set && getaclentry("tar", &entry)) {
  592. l_tar = 0;
  593. if (!strcasecmp(ARG0, "yes"))
  594.     l_tar = 1;
  595. for (which = 1; (which < MAXARGS) && ARG[which]; which++) {
  596.     if (!wu_fnmatch(ARG[which], class, FNM_CASEFOLD)) {
  597. mangleopts |= l_tar * O_TAR;
  598. set = 1;
  599.     }
  600. }
  601.     }
  602.     /* plan on expanding command syntax to include classes for each of these */
  603.     entry = (struct aclmember *) NULL;
  604.     while (getaclentry("log", &entry)) {
  605. if (!strcasecmp(ARG0, "commands")) {
  606.     if (anonymous && strcasestr(ARG1, "anonymous"))
  607. log_commands = 1;
  608.     if (guest && strcasestr(ARG1, "guest"))
  609. log_commands = 1;
  610.     if (!guest && !anonymous && strcasestr(ARG1, "real"))
  611. log_commands = 1;
  612. }
  613. if (!strcasecmp(ARG0, "transfers")) {
  614.     set = 0;
  615.     if (strcasestr(ARG1, "anonymous") && anonymous)
  616. set = 1;
  617.     if (strcasestr(ARG1, "guest") && guest)
  618. set = 1;
  619.     if (strcasestr(ARG1, "real") && !guest && !anonymous)
  620. set = 1;
  621.     if (strcasestr(ARG2, "inbound"))
  622. inbound = 1;
  623.     if (strcasestr(ARG2, "outbound"))
  624. outbound = 1;
  625.     if (set)
  626. log_incoming_xfers = inbound;
  627.     if (set)
  628. log_outbound_xfers = outbound;
  629. }
  630. if (!strcasecmp(ARG0, "security")) {
  631.     if (strcasestr(ARG1, "anonymous") && anonymous)
  632. log_security = 1;
  633.     if (strcasestr(ARG1, "guest") && guest)
  634. log_security = 1;
  635.     if (strcasestr(ARG1, "real") && !guest && !anonymous)
  636. log_security = 1;
  637. }
  638. if (!strcasecmp(ARG0, "syslog"))
  639.     syslogmsg = 1;
  640. if (!strcasecmp(ARG0, "xferlog"))
  641.     syslogmsg = 0;
  642. if (!strcasecmp(ARG0, "syslog+xferlog")
  643.     || !strcasecmp(ARG0, "xferlog+syslog"))
  644.     syslogmsg = 2;
  645.     }
  646. }
  647. /*************************************************************************/
  648. /* FUNCTION  : acl_getclass                                              */
  649. /* PURPOSE   : Scan the ACL buffer and determine what class user is in   */
  650. /* ARGUMENTS : pointer to buffer to class name, pointer to ACL buffer    */
  651. /*************************************************************************/
  652. int acl_getclass(char *classbuf)
  653. {
  654.     int which;
  655.     struct aclmember *entry = NULL;
  656.     while (getaclentry("class", &entry)) {
  657. if (ARG0)
  658.     strcpy(classbuf, ARG0);
  659. for (which = 2; (which < MAXARGS) && ARG[which]; which++) {
  660.     if (anonymous && strcasestr(ARG1, "anonymous") &&
  661. hostmatch(ARG[which], remoteaddr, remotehost))
  662. return (1);
  663.     if (guest && strcasestr(ARG1, "guest") && hostmatch(ARG[which], remoteaddr, remotehost))
  664. return (1);
  665.     if (!guest && !anonymous && strcasestr(ARG1, "real") &&
  666. hostmatch(ARG[which], remoteaddr, remotehost))
  667. return (1);
  668. }
  669.     }
  670.     *classbuf = (char) NULL;
  671.     return (0);
  672. }
  673. /*************************************************************************/
  674. /* FUNCTION  : acl_getlimit                                              */
  675. /* PURPOSE   : Scan the ACL buffer and determine what limit applies to   */
  676. /*             the user                                                  */
  677. /* ARGUMENTS : pointer class name, pointer to ACL buffer                 */
  678. /*************************************************************************/
  679. int acl_getlimit(char *class, char *msgpathbuf)
  680. {
  681.     int limit;
  682.     struct aclmember *entry = NULL;
  683.     if (msgpathbuf)
  684. *msgpathbuf = '';
  685.     /* limit <class> <n> <times> [<message_file>] */
  686.     while (getaclentry("limit", &entry)) {
  687. if (!ARG0 || !ARG1 || !ARG2)
  688.     continue;
  689. if (!strcasecmp(class, ARG0)) {
  690.     limit = atoi(ARG1);
  691.     if (validtime(ARG2)) {
  692. if (ARG3 && msgpathbuf)
  693.     strcpy(msgpathbuf, ARG3);
  694. return (limit);
  695.     }
  696. }
  697.     }
  698.     return (-1);
  699. }
  700. /*************************************************************************/
  701. /* FUNCTION  : acl_getnice                                               */
  702. /* PURPOSE   : Scan the ACL buffer and determine what nice value applies */
  703. /*             to the user                                               */
  704. /* ARGUMENTS : pointer class name                                        */
  705. /*************************************************************************/
  706. int acl_getnice(char *class)
  707. {
  708.     int nice_delta_for_class_found = 0;
  709.     int nice_delta = 0;
  710.     int default_nice_delta = 0;
  711.     struct aclmember *entry = NULL;
  712.     /* nice <nice_delta> [<class>] */
  713.     while (getaclentry("nice", &entry)) {
  714. if (!ARG0)
  715.     continue;
  716. if (!ARG1)
  717.     default_nice_delta = atoi(ARG0);
  718. else if (!strcasecmp(class, ARG1)) {
  719.     nice_delta_for_class_found = 1;
  720.     nice_delta = atoi(ARG0);
  721. }
  722.     }
  723.     if (!nice_delta_for_class_found)
  724. nice_delta = default_nice_delta;
  725.     return nice_delta;
  726. }
  727. /*************************************************************************/
  728. /* FUNCTION  : acl_getdefumask                                           */
  729. /* PURPOSE   : Scan the ACL buffer to determine what umask value applies */
  730. /*             to the user                                               */
  731. /* ARGUMENTS : pointer to class name                                     */
  732. /*************************************************************************/
  733. void acl_getdefumask(char *class)
  734. {
  735.     struct aclmember *entry = NULL;
  736.     /* defumask <umask> [<class>] */
  737.     while (getaclentry("defumask", &entry)) {
  738. if (!ARG0)
  739.     continue;
  740. if (!ARG1)
  741.     defumask = strtoul(ARG0, NULL, 0);
  742. else if (!strcasecmp(class, ARG1)) {
  743.     defumask = strtoul(ARG0, NULL, 0);
  744.     break;
  745. }
  746.     }
  747.     umask(defumask);
  748. }
  749. /*************************************************************************/
  750. /* FUNCTION  : acl_tcpwindow                                             */
  751. /* PURPOSE   : Scan the ACL buffer and determine what TCP window size to */
  752. /*             use based upon the class                                  */
  753. /* ARGUMENTS : pointer to class name                                     */
  754. /*************************************************************************/
  755. void acl_tcpwindow(char *class)
  756. {
  757.     struct aclmember *entry = NULL;
  758.     /* tcpwindow <size> [<class>] */
  759.     while (getaclentry("tcpwindow", &entry)) {
  760. if (!ARG0)
  761.     continue;
  762. if (!ARG1)
  763.     TCPwindowsize = strtoul(ARG0, NULL, 0);
  764. else if (!strcasecmp(class, ARG1)) {
  765.     TCPwindowsize = strtoul(ARG0, NULL, 0);
  766.     break;
  767. }
  768.     }
  769. }
  770. #ifdef TRANSFER_COUNT
  771. #ifdef TRANSFER_LIMIT
  772. /*************************************************************************/
  773. /* FUNCTION  : acl_filelimit                                             */
  774. /* PURPOSE   : Scan the ACL buffer and determine what file limit to use  */
  775. /*             based upon the class                                      */
  776. /* ARGUMENTS : pointer to class name                                     */
  777. /*************************************************************************/
  778. void acl_filelimit(char *class)
  779. {
  780.     struct aclmember *entry = NULL;
  781.     int raw_in = 0;
  782.     int raw_out = 0;
  783.     int raw_total = 0;
  784.     int data_in = 0;
  785.     int data_out = 0;
  786.     int data_total = 0;
  787.     extern int file_limit_raw_in;
  788.     extern int file_limit_raw_out;
  789.     extern int file_limit_raw_total;
  790.     extern int file_limit_data_in;
  791.     extern int file_limit_data_out;
  792.     extern int file_limit_data_total;
  793.     /* file-limit [<raw>] <in|out|total> <count> [<class>] */
  794.     while (getaclentry("file-limit", &entry)) {
  795. if (!ARG0 || !ARG1)
  796.     continue;
  797. if (!strcasecmp(ARG0, "raw")) {
  798.     if (!ARG2)
  799. continue;
  800.     if (!strcasecmp(ARG1, "in")) {
  801. if (!ARG3) {
  802.     if (!raw_in)
  803. file_limit_raw_in = atoi(ARG2);
  804. }
  805. else if (!strcasecmp(class, ARG3)) {
  806.     raw_in = 1;
  807.     file_limit_raw_in = atoi(ARG2);
  808. }
  809.     }
  810.     else if (!strcasecmp(ARG1, "out")) {
  811. if (!ARG3) {
  812.     if (!raw_out)
  813. file_limit_raw_out = atoi(ARG2);
  814. }
  815. else if (!strcasecmp(class, ARG3)) {
  816.     raw_out = 1;
  817.     file_limit_raw_out = atoi(ARG2);
  818. }
  819.     }
  820.     else if (!strcasecmp(ARG1, "total")) {
  821. if (!ARG3) {
  822.     if (!raw_total)
  823. file_limit_raw_total = atoi(ARG2);
  824. }
  825. else if (!strcasecmp(class, ARG3)) {
  826.     raw_total = 1;
  827.     file_limit_raw_total = atoi(ARG2);
  828. }
  829.     }
  830. }
  831. else if (!strcasecmp(ARG0, "in")) {
  832.     if (!ARG2) {
  833. if (!data_in)
  834.     file_limit_data_in = atoi(ARG1);
  835.     }
  836.     else if (!strcasecmp(class, ARG2)) {
  837. data_in = 1;
  838. file_limit_data_in = atoi(ARG1);
  839.     }
  840. }
  841. else if (!strcasecmp(ARG0, "out")) {
  842.     if (!ARG2) {
  843. if (!data_out)
  844.     file_limit_data_out = atoi(ARG1);
  845.     }
  846.     else if (!strcasecmp(class, ARG2)) {
  847. data_out = 1;
  848. file_limit_data_out = atoi(ARG1);
  849.     }
  850. }
  851. else if (!strcasecmp(ARG0, "total")) {
  852.     if (!ARG2) {
  853. if (!data_total)
  854.     file_limit_data_total = atoi(ARG1);
  855.     }
  856.     else if (!strcasecmp(class, ARG2)) {
  857. data_total = 1;
  858. file_limit_data_total = atoi(ARG1);
  859.     }
  860. }
  861.     }
  862. }
  863. /*************************************************************************/
  864. /* FUNCTION  : acl_datalimit                                             */
  865. /* PURPOSE   : Scan the ACL buffer and determine what data limit to use  */
  866. /*             based upon the class                                      */
  867. /* ARGUMENTS : pointer to class name                                     */
  868. /*************************************************************************/
  869. void acl_datalimit(char *class)
  870. {
  871.     struct aclmember *entry = NULL;
  872.     int raw_in = 0;
  873.     int raw_out = 0;
  874.     int raw_total = 0;
  875.     int data_in = 0;
  876.     int data_out = 0;
  877.     int data_total = 0;
  878.     extern int data_limit_raw_in;
  879.     extern int data_limit_raw_out;
  880.     extern int data_limit_raw_total;
  881.     extern int data_limit_data_in;
  882.     extern int data_limit_data_out;
  883.     extern int data_limit_data_total;
  884.     /* data-limit [<raw>] <in|out|total> <count> [<class>] */
  885.     while (getaclentry("data-limit", &entry)) {
  886. if (!ARG0 || !ARG1)
  887.     continue;
  888. if (!strcasecmp(ARG0, "raw")) {
  889.     if (!ARG2)
  890. continue;
  891.     if (!strcasecmp(ARG1, "in")) {
  892. if (!ARG3) {
  893.     if (!raw_in)
  894. data_limit_raw_in = atoi(ARG2);
  895. }
  896. else if (!strcasecmp(class, ARG3)) {
  897.     raw_in = 1;
  898.     data_limit_raw_in = atoi(ARG2);
  899. }
  900.     }
  901.     else if (!strcasecmp(ARG1, "out")) {
  902. if (!ARG3) {
  903.     if (!raw_out)
  904. data_limit_raw_out = atoi(ARG2);
  905. }
  906. else if (!strcasecmp(class, ARG3)) {
  907.     raw_out = 1;
  908.     data_limit_raw_out = atoi(ARG2);
  909. }
  910.     }
  911.     else if (!strcasecmp(ARG1, "total")) {
  912. if (!ARG3) {
  913.     if (!raw_total)
  914. data_limit_raw_total = atoi(ARG2);
  915. }
  916. else if (!strcasecmp(class, ARG3)) {
  917.     raw_total = 1;
  918.     data_limit_raw_total = atoi(ARG2);
  919. }
  920.     }
  921. }
  922. else if (!strcasecmp(ARG0, "in")) {
  923.     if (!ARG2) {
  924. if (!data_in)
  925.     data_limit_data_in = atoi(ARG1);
  926.     }
  927.     else if (!strcasecmp(class, ARG2)) {
  928. data_in = 1;
  929. data_limit_data_in = atoi(ARG1);
  930.     }
  931. }
  932. else if (!strcasecmp(ARG0, "out")) {
  933.     if (!ARG2) {
  934. if (!data_out)
  935.     data_limit_data_out = atoi(ARG1);
  936.     }
  937.     else if (!strcasecmp(class, ARG2)) {
  938. data_out = 1;
  939. data_limit_data_out = atoi(ARG1);
  940.     }
  941. }
  942. else if (!strcasecmp(ARG0, "total")) {
  943.     if (!ARG2) {
  944. if (!data_total)
  945.     data_limit_data_total = atoi(ARG1);
  946.     }
  947.     else if (!strcasecmp(class, ARG2)) {
  948. data_total = 1;
  949. data_limit_data_total = atoi(ARG1);
  950.     }
  951. }
  952.     }
  953. }
  954. #endif
  955. #endif
  956. /*************************************************************************/
  957. /* FUNCTION  : acl_deny                                                  */
  958. /* PURPOSE   : Scan the ACL buffer and determine a deny command applies  */
  959. /* ARGUMENTS : pointer class name, pointer to ACL buffer                 */
  960. /*************************************************************************/
  961. int acl_deny(char *msgpathbuf)
  962. {
  963.     struct aclmember *entry = NULL;
  964.     if (msgpathbuf)
  965. *msgpathbuf = (char) NULL;
  966.     /* deny <addrglob> [<message_file>] */
  967.     while (getaclentry("deny", &entry)) {
  968. if (!ARG0)
  969.     continue;
  970. if (strcasecmp(ARG0, "!nameserved") == 0) {
  971.     if (!nameserved) {
  972. if (ARG1)
  973.     strcpy(msgpathbuf, entry->arg[1]);
  974. return (1);
  975.     }
  976. }
  977. else if (hostmatch(ARG0, remoteaddr, remotehost)) {
  978.     if (ARG1)
  979. strcpy(msgpathbuf, entry->arg[1]);
  980.     return (1);
  981. }
  982.     }
  983.     return (0);
  984. }
  985. /*************************************************************************/
  986. /* FUNCTION  : acl_countusers                                            */
  987. /* PURPOSE   : Check the anonymous FTP access lists to see if this       */
  988. /*             access is permitted.                                      */
  989. /* ARGUMENTS : none                                                      */
  990. /*************************************************************************/
  991. int acl_countusers(char *class)
  992. {
  993.     int count, which;
  994.     char pidfile[MAXPATHLEN];
  995.     pid_t buf[MAXUSERS];
  996. #ifndef HAVE_FLOCK
  997.     struct flock arg;
  998. #endif
  999.     if (Bypass_PID_Files)
  1000. return (0);
  1001.     /* 
  1002.      * if pidfd was not opened previously... 
  1003.      * pidfd must stay open after the chroot(~ftp)  
  1004.      */
  1005.     sprintf(pidfile, _PATH_PIDNAMES, class);
  1006.     if (pidfd < 0) {
  1007. mode_t oldmask;
  1008. oldmask = umask(0);
  1009. pidfd = open(pidfile, O_RDWR | O_CREAT, 0644);
  1010. (void) umask(oldmask);
  1011.     }
  1012.     if (pidfd < 0) {
  1013. syslog(LOG_ERR, "cannot open pid file %s: %m", pidfile);
  1014. return -1;
  1015.     }
  1016. #ifdef HAVE_FLOCK
  1017.     while (flock(pidfd, LOCK_EX)) {
  1018. #ifndef NO_PID_SLEEP_MSGS
  1019. syslog(LOG_ERR, "sleeping: flock of pid file failed: %m");
  1020. #endif
  1021. #else
  1022.     arg.l_type = F_WRLCK;
  1023.     arg.l_whence = arg.l_start = arg.l_len = 0;
  1024.     while (-1 == fcntl(pidfd, F_SETLK, &arg)) {
  1025. #ifndef NO_PID_SLEEP_MSGS
  1026. syslog(LOG_ERR, "sleeping: fcntl lock of pid file failed: %m");
  1027. #endif
  1028. #endif
  1029. sleep(1);
  1030.     }
  1031.     lseek(pidfd, (off_t) 0, SEEK_SET);
  1032.     count = 0;
  1033.     if (read(pidfd, (void *) buf, sizeof(buf)) == sizeof(buf)) {
  1034. for (which = 0; which < MAXUSERS; which++)
  1035.     if (buf[which] && !kill(buf[which], 0))
  1036. count++;
  1037.     }
  1038. #ifdef HAVE_FLOCK
  1039.     flock(pidfd, LOCK_UN);
  1040. #else
  1041.     arg.l_type = F_UNLCK;
  1042.     arg.l_whence = arg.l_start = arg.l_len = 0;
  1043.     fcntl(pidfd, F_SETLK, &arg);
  1044. #endif
  1045.     return (count);
  1046. }
  1047. /*************************************************************************/
  1048. /* FUNCTION  : acl_join                                                  */
  1049. /* PURPOSE   : Add the current process to the list of processes in the   */
  1050. /*             specified class.                                          */
  1051. /* ARGUMENTS : The name of the class to join                             */
  1052. /*************************************************************************/
  1053. void acl_join(char *class)
  1054. {
  1055.     int which, avail;
  1056.     pid_t buf[MAXUSERS];
  1057.     char pidfile[MAXPATHLEN];
  1058.     pid_t procid;
  1059. #ifndef HAVE_FLOCK
  1060.     struct flock arg;
  1061. #endif
  1062.     if (Bypass_PID_Files)
  1063. return;
  1064.     /* 
  1065.      * if pidfd was not opened previously... 
  1066.      * pidfd must stay open after the chroot(~ftp)  
  1067.      */
  1068.     sprintf(pidfile, _PATH_PIDNAMES, class);
  1069.     if (pidfd < 0) {
  1070. mode_t oldmask;
  1071. oldmask = umask(0);
  1072. pidfd = open(pidfile, O_RDWR | O_CREAT, 0644);
  1073. (void) umask(oldmask);
  1074.     }
  1075.     if (pidfd < 0) {
  1076. syslog(LOG_ERR, "cannot open pid file %s: %m", pidfile);
  1077. return;
  1078.     }
  1079. #ifdef HAVE_FLOCK
  1080.     while (flock(pidfd, LOCK_EX)) {
  1081. #ifndef NO_PID_SLEEP_MSGS
  1082. syslog(LOG_ERR, "sleeping: flock of pid file failed: %m");
  1083. #endif
  1084. #else
  1085.     arg.l_type = F_WRLCK;
  1086.     arg.l_whence = arg.l_start = arg.l_len = 0;
  1087.     while (-1 == fcntl(pidfd, F_SETLK, &arg)) {
  1088. #ifndef NO_PID_SLEEP_MSGS
  1089. syslog(LOG_ERR, "sleeping: fcntl lock of pid file failed: %m");
  1090. #endif
  1091. #endif
  1092. sleep(1);
  1093.     }
  1094.     procid = getpid();
  1095.     lseek(pidfd, (off_t) 0, SEEK_SET);
  1096.     if (read(pidfd, (void *) buf, sizeof(buf)) < sizeof(buf))
  1097. for (which = 0; which < MAXUSERS; buf[which++] = 0)
  1098.     continue;
  1099.     avail = 0;
  1100.     for (which = 0; which < MAXUSERS; which++) {
  1101. if ((buf[which] == 0) || (kill(buf[which], 0) == -1)) {
  1102.     avail = which;
  1103.     buf[which] = 0;
  1104. }
  1105. else if (buf[which] == procid) {
  1106.     /* already exists in pid file... */
  1107. #ifdef HAVE_FLOCK
  1108.     flock(pidfd, LOCK_UN);
  1109. #else
  1110.     arg.l_type = F_UNLCK;
  1111.     arg.l_whence = arg.l_start = arg.l_len = 0;
  1112.     fcntl(pidfd, F_SETLK, &arg);
  1113. #endif
  1114.     return;
  1115. }
  1116.     }
  1117.     buf[avail] = procid;
  1118.     lseek(pidfd, (off_t) 0, SEEK_SET);
  1119.     write(pidfd, (void *) buf, sizeof(buf));
  1120. #ifdef HAVE_FLOCK
  1121.     flock(pidfd, LOCK_UN);
  1122. #else
  1123.     arg.l_type = F_UNLCK;
  1124.     arg.l_whence = arg.l_start = arg.l_len = 0;
  1125.     fcntl(pidfd, F_SETLK, &arg);
  1126. #endif
  1127. }
  1128. /*************************************************************************/
  1129. /* FUNCTION  : acl_remove                                                */
  1130. /* PURPOSE   : remove the current process to the list of processes in    */
  1131. /*             the specified class.                                      */
  1132. /* ARGUMENTS : The name of the class to remove                           */
  1133. /*************************************************************************/
  1134. void acl_remove(void)
  1135. {
  1136.     char class[1024];
  1137.     int which, avail;
  1138.     pid_t buf[MAXUSERS];
  1139.     char pidfile[MAXPATHLEN];
  1140.     pid_t procid;
  1141. #ifndef HAVE_FLOCK
  1142.     struct flock arg;
  1143. #endif
  1144.     if (Bypass_PID_Files)
  1145. return;
  1146.     if (!acl_getclass(class)) {
  1147. return;
  1148.     }
  1149.     /* 
  1150.      * if pidfd was not opened previously... 
  1151.      * pidfd must stay open after the chroot(~ftp)  
  1152.      */
  1153.     sprintf(pidfile, _PATH_PIDNAMES, class);
  1154.     if (pidfd < 0) {
  1155. mode_t oldmask;
  1156. oldmask = umask(0);
  1157. pidfd = open(pidfile, O_RDWR | O_CREAT, 0644);
  1158. (void) umask(oldmask);
  1159.     }
  1160.     if (pidfd < 0) {
  1161. syslog(LOG_ERR, "cannot open pid file %s: %m", pidfile);
  1162. return;
  1163.     }
  1164. #ifdef HAVE_FLOCK
  1165.     while (flock(pidfd, LOCK_EX)) {
  1166. #ifndef NO_PID_SLEEP_MSGS
  1167. syslog(LOG_ERR, "sleeping: flock of pid file failed: %m");
  1168. #endif
  1169. #else
  1170.     arg.l_type = F_WRLCK;
  1171.     arg.l_whence = arg.l_start = arg.l_len = 0;
  1172.     while (-1 == fcntl(pidfd, F_SETLK, &arg)) {
  1173. #ifndef NO_PID_SLEEP_MSGS
  1174. syslog(LOG_ERR, "sleeping: fcntl lock of pid file failed: %m");
  1175. #endif
  1176. #endif
  1177. sleep(1);
  1178.     }
  1179.     procid = getpid();
  1180.     lseek(pidfd, (off_t) 0, SEEK_SET);
  1181.     if (read(pidfd, (void *) buf, sizeof(buf)) < sizeof(buf))
  1182. for (which = 0; which < MAXUSERS; buf[which++] = 0)
  1183.     continue;
  1184.     avail = 0;
  1185.     for (which = 0; which < MAXUSERS; which++) {
  1186. if ((buf[which] == 0) || (kill(buf[which], 0) == -1)) {
  1187.     avail = which;
  1188.     buf[which] = 0;
  1189. }
  1190. else if (buf[which] == procid) {
  1191.     buf[which] = 0;
  1192. }
  1193.     }
  1194.     lseek(pidfd, (off_t) 0, SEEK_SET);
  1195.     write(pidfd, (void *) buf, sizeof(buf));
  1196. #ifdef HAVE_FLOCK
  1197.     flock(pidfd, LOCK_UN);
  1198. #else
  1199.     arg.l_type = F_UNLCK;
  1200.     arg.l_whence = arg.l_start = arg.l_len = 0;
  1201.     fcntl(pidfd, F_SETLK, &arg);
  1202. #endif
  1203.     close(pidfd);
  1204.     pidfd = -1;
  1205. }
  1206. /*************************************************************************/
  1207. /* FUNCTION  : pr_mesg                                                   */
  1208. /* PURPOSE   : Display a message to the user                             */
  1209. /* ARGUMENTS : message code, name of file to display                     */
  1210. /*************************************************************************/
  1211. void pr_mesg(int msgcode, char *msgfile)
  1212. {
  1213.     FILE *infile;
  1214.     char inbuf[1024], outbuf[1024], *cr;
  1215.     if (msgfile && (int) strlen(msgfile) > 0) {
  1216. infile = fopen(msgfile, "r");
  1217. if (infile) {
  1218.     while (fgets(inbuf, sizeof(inbuf), infile) != NULL) {
  1219. if ((cr = strchr(inbuf, 'n')) != NULL)
  1220.     *cr = '';
  1221. msg_massage(inbuf, outbuf, sizeof(outbuf));
  1222. lreply(msgcode, "%s", outbuf);
  1223.     }
  1224.     fclose(infile);
  1225. }
  1226.     }
  1227. }
  1228. /*************************************************************************/
  1229. /* FUNCTION  : access_init                                               */
  1230. /* PURPOSE   : Read and parse the access lists to set things up          */
  1231. /* ARGUMENTS : none                                                      */
  1232. /*************************************************************************/
  1233. void access_init(void)
  1234. {
  1235.     struct aclmember *entry;
  1236.     if (!readacl(_path_ftpaccess))
  1237. return;
  1238.     (void) parseacl();
  1239.     Shutdown[0] = '';
  1240.     entry = (struct aclmember *) NULL;
  1241.     if (getaclentry("shutdown", &entry) && ARG0 != NULL)
  1242. (void) strncpy(Shutdown, ARG0, sizeof(Shutdown));
  1243.     entry = (struct aclmember *) NULL;
  1244.     if (getaclentry("keepalive", &entry) && ARG0 != NULL)
  1245. if (!strcasecmp(ARG0, "yes"))
  1246.     keepalive = 1;
  1247.     load_timeouts();
  1248. }
  1249. /*************************************************************************/
  1250. /* FUNCTION  : access_ok                                                 */
  1251. /* PURPOSE   : Check the anonymous FTP access lists to see if this       */
  1252. /*             access is permitted.                                      */
  1253. /* ARGUMENTS : none                                                      */
  1254. /*************************************************************************/
  1255. int access_ok(int msgcode)
  1256. {
  1257.     char class[1024], msgfile[MAXPATHLEN];
  1258.     int limit;
  1259.     int nice_delta;
  1260.     if (!use_accessfile)
  1261. return (1);
  1262.     if (aclbuf == NULL) {
  1263. syslog(LOG_NOTICE,
  1264.        "ACCESS DENIED (error reading access file) TO %s",
  1265.        remoteident);
  1266. return (0);
  1267.     }
  1268.     if (acl_deny(msgfile)) {
  1269. #ifndef HELP_CRACKERS
  1270. memcpy(DelayedMessageFile, msgfile, sizeof(msgfile));
  1271. #else
  1272. pr_mesg(msgcode, msgfile);
  1273. #endif
  1274. syslog(LOG_NOTICE, "ACCESS DENIED (deny command) TO %s",
  1275.        remoteident);
  1276. return (0);
  1277.     }
  1278.     /* if user is not in any class, deny access */
  1279.     if (!acl_getclass(class)) {
  1280. syslog(LOG_NOTICE, "ACCESS DENIED (not in any class) TO %s",
  1281.        remoteident);
  1282. return (0);
  1283.     }
  1284.     if ((nice_delta = acl_getnice(class))) {
  1285. if (nice_delta < 0)
  1286.     syslog(LOG_NOTICE, "Process nice value adjusted by %d", nice_delta);
  1287. nice(nice_delta);
  1288.     }
  1289.     acl_getdefumask(class);
  1290.     acl_tcpwindow(class);
  1291. #ifdef TRANSFER_COUNT
  1292. #ifdef TRANSFER_LIMIT
  1293.     acl_filelimit(class);
  1294.     acl_datalimit(class);
  1295. #endif
  1296. #endif
  1297.     /* if no limits defined, no limits apply -- access OK */
  1298.     limit = acl_getlimit(class, msgfile);
  1299.     if ((limit == -1) || (acl_countusers(class) < limit)) {
  1300. acl_join(class);
  1301. return (1);
  1302.     }
  1303.     else {
  1304. #ifdef LOG_TOOMANY
  1305. syslog(LOG_NOTICE, "ACCESS DENIED (user limit %d; class %s) TO %s",
  1306.        limit, class, remoteident);
  1307. #endif
  1308. #ifndef HELP_CRACKERS
  1309. memcpy(DelayedMessageFile, msgfile, sizeof(msgfile));
  1310. #else
  1311. pr_mesg(msgcode, msgfile);
  1312. #endif
  1313. return (-1);
  1314.     }
  1315.     /* NOTREACHED */
  1316. }