home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1996 May / PCOnline_05_1996.bin / linux / source / n / tcpip / wu-ftpd-.000 / wu-ftpd- / wu-ftpd-2.4 / src / extensions.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-08  |  25.8 KB  |  943 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. #include "config.h"
  33.  
  34. #include <stdio.h>
  35. #include <errno.h>
  36. #include <string.h>
  37. #ifdef SYSSYSLOG
  38. #include <sys/syslog.h>
  39. #else
  40. #include <syslog.h>
  41. #endif
  42. #include <time.h>
  43. #include <pwd.h>
  44. #include <grp.h>
  45.  
  46. #include <sys/types.h>
  47. #include <sys/stat.h>
  48. #include <sys/file.h>
  49. #include <sys/param.h>
  50.  
  51. #ifdef HAVE_STATVFS
  52. #include <sys/statvfs.h>
  53. #endif
  54.  
  55. #include <arpa/ftp.h>
  56.  
  57. #include "pathnames.h"
  58. #include "extensions.h"
  59. #include "support/ftw.h"
  60.  
  61. #ifdef HAVE_REGEX_H
  62. #include <regex.h>
  63. #endif
  64.  
  65. #if defined(REGEX) && defined(SOLARIS_21)
  66. #include <libgen.h>
  67. #endif
  68.  
  69. extern int fnmatch(),
  70.   type,
  71.   transflag,
  72.   autospout_free,
  73.   data,
  74.   anonymous,
  75.   guest;
  76. extern char **ftpglob(register char *v),
  77.  *globerr,
  78.   remotehost[],
  79.   hostname[],
  80.  *autospout,
  81.   Shutdown[];
  82.  
  83. char shuttime[30],
  84.   denytime[30],
  85.   disctime[30];
  86.  
  87. #ifndef REGEX
  88. char *re_comp();
  89. #elif defined(M_UNIX)
  90. extern char *regcmp(), *regex();
  91. #endif
  92.  
  93. extern FILE *dataconn(char *name, off_t size, char *mode);
  94. FILE *dout;
  95.  
  96. time_t newer_time;
  97.  
  98. int show_fullinfo;
  99.  
  100. check_newer(char *path, struct stat *st, int flag)
  101. {
  102.  
  103.     if (st->st_mtime > newer_time) {
  104.         if (show_fullinfo != 0) {
  105.             if (flag == FTW_F || flag == FTW_D) {
  106.                 fprintf(dout, "%s %d %d %s", flag == FTW_F ? "F" : "D",
  107.                         st->st_size, st->st_mtime, path);
  108.             }
  109.         } else if (flag == FTW_F)
  110.             fprintf(dout, "%s", path);
  111.     }
  112.     return 0;
  113. }
  114.  
  115. #ifdef HAVE_STATVFS
  116. int getSize(s)
  117. char *s;
  118. {
  119.     int c;
  120.     struct statvfs buf;
  121.  
  122.     if (( c = statvfs(s, &buf)) != 0)
  123.         return(0);
  124.  
  125.     return(buf.f_bavail * buf.f_frsize / 1024);
  126. }
  127. #endif
  128.  
  129. /*************************************************************************/
  130. /* FUNCTION  : msg_massage                                               */
  131. /* PURPOSE   : Scan a message line for magic cookies, replacing them as  */
  132. /*             needed.                                                   */
  133. /* ARGUMENTS : pointer input and output buffers                          */
  134. /*************************************************************************/
  135.  
  136. int
  137. msg_massage(char *inbuf, char *outbuf)
  138. {
  139.     char *inptr = inbuf;
  140.     char *outptr = outbuf;
  141.     char buffer[MAXPATHLEN];
  142.     time_t curtime;
  143.     int limit;
  144.     extern struct passwd *pw;
  145.     struct aclmember *entry = NULL;
  146.  
  147.     (void) time(&curtime);
  148.     (void) acl_getclass(buffer);
  149.  
  150.     limit = acl_getlimit(buffer, NULL);
  151.  
  152.     while (*inptr) {
  153.         if (*inptr != '%')
  154.             *outptr++ = *inptr;
  155.         else {
  156.             switch (*++inptr) {
  157.             case 'E':
  158.                 if ( (getaclentry("email", &entry)) && ARG0 )
  159.                     sprintf(outptr, "%s", ARG0); 
  160.                 break;
  161.             case 'N': 
  162.                 sprintf(outptr, "%d", acl_countusers(buffer)); 
  163.                 break; 
  164.             case 'M':
  165.                 sprintf(outptr, "%d", limit);
  166.                 break;
  167.  
  168.             case 'T':
  169.                 strncpy(outptr, ctime(&curtime), 24);
  170.                 *(outptr + 24) = NULL;
  171.                 break;
  172.  
  173.             case 'F':
  174. #ifdef HAVE_STATVFS
  175.                 sprintf(outptr, "%lu", getSize("."));
  176. #endif
  177.                 break;
  178.  
  179.             case 'C':
  180. #ifdef HAVE_GETCWD
  181.                 (void) getcwd(outptr, MAXPATHLEN);
  182. #else
  183.                 (void) getwd(outptr);
  184. #endif
  185.                 break;
  186.  
  187.             case 'R':
  188.                 strcpy(outptr, remotehost);
  189.                 break;
  190.  
  191.             case 'L':
  192.                 strcpy(outptr, hostname);
  193.                 break;
  194.  
  195.             case 'U':
  196.                 strcpy(outptr, pw->pw_name);
  197.                 break;
  198.  
  199.             case 's':
  200.                 strncpy(outptr, shuttime, 24);
  201.                 *(outptr + 24) = NULL;
  202.                 break;
  203.  
  204.             case 'd':
  205.                 strncpy(outptr, disctime, 24);
  206.                 *(outptr + 24) = NULL;
  207.                 break;
  208.  
  209.             case 'r':
  210.                 strncpy(outptr, denytime, 24);
  211.                 *(outptr + 24) = NULL;
  212.                 break;
  213.  
  214.             case '%':
  215.                 *outptr++ = '%';
  216.                 *outptr = '\0';
  217.                 break;
  218.  
  219.             default:
  220.                 *outptr++ = '%';
  221.                 *outptr++ = '?';
  222.                 *outptr = '\0';
  223.                 break;
  224.             }
  225.             while (*outptr)
  226.                 outptr++;
  227.         }
  228.         inptr++;
  229.     }
  230.     *outptr = NULL;
  231. }
  232.  
  233. /*************************************************************************/
  234. /* FUNCTION  : cwd_beenhere                                              */
  235. /* PURPOSE   : Return 1 if the user has already visited this directory   */
  236. /*             via C_WD.                                                 */
  237. /* ARGUMENTS : a power-of-two directory function code (README, MESSAGE)  */
  238. /*************************************************************************/
  239.  
  240. int
  241. cwd_beenhere(int dircode)
  242. {
  243.     struct dirlist {
  244.         struct dirlist *next;
  245.         int dircode;
  246.         char dirname[1];
  247.     };
  248.  
  249.     static struct dirlist *head = NULL;
  250.     struct dirlist *curptr;
  251.     char cwd[MAXPATHLEN];
  252.  
  253.     (void) realpath(".", cwd);
  254.  
  255.     for (curptr = head; curptr != NULL; curptr = curptr->next)
  256.         if (strcmp(curptr->dirname, cwd) == NULL) {
  257.             if (!(curptr->dircode & dircode)) {
  258.                 curptr->dircode |= dircode;
  259.                 return (0);
  260.             }
  261.             return (1);
  262.         }
  263.     curptr = (struct dirlist *) malloc(strlen(cwd) + 1 + sizeof(struct dirlist));
  264.  
  265.     if (curptr != NULL) {
  266.         curptr->next = head;
  267.         head = curptr;
  268.         curptr->dircode = dircode;
  269.         strcpy(curptr->dirname, cwd);
  270.     }
  271.     return (0);
  272. }
  273.  
  274. /*************************************************************************/
  275. /* FUNCTION  : show_banner                                               */
  276. /* PURPOSE   : Display a banner on the user's terminal before login      */
  277. /* ARGUMENTS : reply code to use                                         */
  278. /*************************************************************************/
  279.  
  280. void
  281. show_banner(int msgcode)
  282. {
  283.     char *crptr,
  284.       linebuf[1024],
  285.       outbuf[1024];
  286.     struct aclmember *entry = NULL;
  287.     FILE *infile;
  288.  
  289.     /* banner <path> */
  290.     while (getaclentry("banner", &entry)) {
  291.         if (ARG0 && strlen(ARG0) > 0) {
  292.             infile = fopen(ARG0, "r");
  293.             if (infile) {
  294.                 while (fgets(linebuf, 255, infile) != NULL) {
  295.                     if ((crptr = strchr(linebuf, '\n')) != NULL)
  296.                         *crptr = '\0';
  297.                     msg_massage(linebuf, outbuf);
  298.                     lreply(msgcode, "%s", outbuf);
  299.                 }
  300.                 fclose(infile);
  301.                 lreply(msgcode, "");
  302.             }
  303.         }
  304.     }
  305. }
  306.  
  307. /*************************************************************************/
  308. /* FUNCTION  : show_message                                              */
  309. /* PURPOSE   : Display a message on the user's terminal if the current   */
  310. /*             conditions are right                                      */
  311. /* ARGUMENTS : reply code to use, LOG_IN|CMD                             */
  312. /*************************************************************************/
  313.  
  314. void
  315. show_message(int msgcode, int mode)
  316. {
  317.     char *crptr,
  318.       linebuf[1024],
  319.       outbuf[1024],
  320.       class[MAXPATHLEN],
  321.       cwd[MAXPATHLEN];
  322.     int show,
  323.       which;
  324.     struct aclmember *entry = NULL;
  325.     FILE *infile;
  326.  
  327.     if (cwd_beenhere(1) != 0)
  328.         return;
  329.  
  330. #ifdef HAVE_GETCWD
  331.     (void) getcwd(cwd,MAXPATHLEN-1);
  332. #else
  333.     (void) getwd(cwd);
  334. #endif
  335.     (void) acl_getclass(class);
  336.  
  337.     /* message <path> [<when> [<class>]] */
  338.     while (getaclentry("message", &entry)) {
  339.         if (!ARG0)
  340.             continue;
  341.         show = 0;
  342.  
  343.         if (mode == LOG_IN && (!ARG1 || !strcasecmp(ARG1, "login")))
  344.             if (!ARG2)
  345.                 show++;
  346.             else {
  347.                 for (which = 2; (which < MAXARGS) && ARG[which]; which++)
  348.                     if (strcasecmp(class, ARG[which]) == NULL)
  349.                         show++;
  350.             }
  351.         if (mode == C_WD && ARG1 && !strncasecmp(ARG1, "cwd=", 4) &&
  352.             (!strcmp((ARG1) + 4, cwd) || *(ARG1 + 4) == '*' ||
  353.             fnmatch((ARG1) + 4, cwd, FNM_PATHNAME)))
  354.             if (!ARG2)
  355.                 show++;
  356.             else {
  357.                 for (which = 2; (which < MAXARGS) && ARG[which]; which++)
  358.                     if (strcasecmp(class, ARG[which]) == NULL)
  359.                         show++;
  360.             }
  361.         if (show && strlen(ARG0) > 0) {
  362.             infile = fopen(ARG0, "r");
  363.             if (infile) {
  364.                 while (fgets(linebuf, 255, infile) != NULL) {
  365.                     if ((crptr = strchr(linebuf, '\n')) != NULL)
  366.                         *crptr = '\0';
  367.                     msg_massage(linebuf, outbuf);
  368.                     lreply(msgcode, "%s", outbuf);
  369.                 }
  370.                 fclose(infile);
  371.                 lreply(msgcode, "");
  372.             }
  373.         }
  374.     }
  375. }
  376.  
  377. /*************************************************************************/
  378. /* FUNCTION  : show_readme                                               */
  379. /* PURPOSE   : Display a message about a README file to the user if the  */
  380. /*             current conditions are right                              */
  381. /* ARGUMENTS : pointer to ACL buffer, reply code, LOG_IN|C_WD            */
  382. /*************************************************************************/
  383.  
  384. void
  385. show_readme(int code, int mode)
  386. {
  387.     char **filelist,
  388.       class[MAXPATHLEN],
  389.       cwd[MAXPATHLEN];
  390.     int show,
  391.       which,
  392.       days;
  393.     time_t clock;
  394.  
  395.     struct stat buf;
  396.     struct tm *tp;
  397.     struct aclmember *entry = NULL;
  398.  
  399.     if (cwd_beenhere(2) != 0)
  400.         return;
  401.  
  402. #ifdef HAVE_GETCWD
  403.     (void) getcwd(cwd,MAXPATHLEN-1);
  404. #else
  405.     (void) getwd(cwd);
  406. #endif
  407.     (void) acl_getclass(class);
  408.  
  409.     /* readme  <path> {<when>} */
  410.     while (getaclentry("readme", &entry)) {
  411.         if (!ARG0)
  412.             continue;
  413.         show = 0;
  414.  
  415.         if (mode == LOG_IN && (!ARG1 || !strcasecmp(ARG1, "login")))
  416.             if (!ARG2)
  417.                 show++;
  418.             else {
  419.                 for (which = 2; (which < MAXARGS) && ARG[which]; which++)
  420.                     if (strcasecmp(class, ARG[which]) == NULL)
  421.                         show++;
  422.             }
  423.         if (mode == C_WD && ARG1 && !strncasecmp(ARG1, "cwd=", 4)
  424.             && (!strcmp((ARG1) + 4, cwd) || *(ARG1 + 4) == '*' ||
  425.                 fnmatch((ARG1) + 4, cwd, FNM_PATHNAME)))
  426.             if (!ARG2)
  427.                 show++;
  428.             else {
  429.                 for (which = 2; (which < MAXARGS) && ARG[which]; which++)
  430.                     if (strcasecmp(class, ARG[which]) == NULL)
  431.                         show++;
  432.             }
  433.         if (show) {
  434.             globerr = NULL;
  435.             filelist = ftpglob(ARG0);
  436.             if (!globerr) {
  437.                 while (filelist && *filelist) {
  438.                    errno = 0;
  439.                    if (!stat(*filelist, &buf)) {
  440.                        lreply(code, "Please read the file %s", *filelist);
  441.                        (void) time(&clock);
  442.                        tp = localtime(&clock);
  443.                        days = 365 * tp->tm_year + tp->tm_yday;
  444.                        tp = localtime(&buf.st_mtime);
  445.                        days -= 365 * tp->tm_year + tp->tm_yday;
  446. /*
  447.                        if (days == 0) {
  448.                          lreply(code, "  it was last modified on %.24s - Today",
  449.                            ctime(&buf.st_mtime));
  450.                        } else {
  451. */
  452.                          lreply(code, 
  453.                            "  it was last modified on %.24s - %d day%s ago",
  454.                            ctime(&buf.st_mtime), days, days == 1 ? "" : "s");
  455. /*
  456.                        }
  457. */
  458.                    }
  459.                    filelist++;
  460.                 }
  461.             }
  462.         }
  463.     }
  464. }
  465.  
  466. /*************************************************************************/
  467. /* FUNCTION  : deny_badxfertype                                          */
  468. /* PURPOSE   : If user is in ASCII transfer mode and tries to retrieve a */
  469. /*             binary file, abort transfer and display appropriate error */
  470. /* ARGUMENTS : message code to use for denial, path of file to check for */
  471. /*             binary contents or NULL to assume binary file             */
  472. /*************************************************************************/
  473.  
  474. int
  475. deny_badasciixfer(int msgcode, char *filepath)
  476. {
  477.  
  478.     if (type == TYPE_A && !*filepath) {
  479.         reply(msgcode, "This is a BINARY file, using ASCII mode to transfer will corrupt it.");
  480.         return (1);
  481.     }
  482.     /* The hooks are here to prevent transfers of actual binary files, not
  483.      * just TAR or COMPRESS mode files... */
  484.     return (0);
  485. }
  486.  
  487. /*************************************************************************/
  488. /* FUNCTION  : is_shutdown                                               */
  489. /* PURPOSE   :                                                           */
  490. /* ARGUMENTS :                                                           */
  491. /*************************************************************************/
  492.  
  493. int
  494. is_shutdown(int quiet)
  495. {
  496.     static struct tm tmbuf;
  497.     static struct stat s_last;
  498.     static time_t last = 0,
  499.       shut,
  500.       deny,
  501.       disc;
  502.  
  503.     static char text[2048];
  504.  
  505.     struct stat s_cur;
  506.  
  507.     FILE *fp;
  508.  
  509.     int deny_off,
  510.       disc_off;
  511.  
  512.     time_t curtime = time(NULL);
  513.  
  514.     char buf[1024],
  515.       linebuf[1024];
  516.  
  517.     if (Shutdown[0] == '\0' || stat(Shutdown, &s_cur))
  518.         return (0);
  519.  
  520.     if (s_last.st_mtime != s_cur.st_mtime) {
  521.         s_last = s_cur;
  522.  
  523.         fp = fopen(Shutdown, "r");
  524.         if (fp == NULL)
  525.             return (0);
  526.         fgets(buf, sizeof(buf), fp);
  527.         if (sscanf(buf, "%d %d %d %d %d %d %d", &tmbuf.tm_year, &tmbuf.tm_mon,
  528.         &tmbuf.tm_mday, &tmbuf.tm_hour, &tmbuf.tm_min, &deny, &disc) != 7) {
  529.             return (0);
  530.         }
  531.         deny_off = 3600 * (deny / 100) + 60 * (deny % 100);
  532.         disc_off = 3600 * (disc / 100) + 60 * (disc % 100);
  533.  
  534.         tmbuf.tm_year -= 1900;
  535.         tmbuf.tm_isdst = -1;
  536.         shut = mktime(&tmbuf);
  537.         strcpy(shuttime, ctime(&shut));
  538.  
  539.         disc = shut - disc_off;
  540.         strcpy(disctime, ctime(&disc));
  541.  
  542.         deny = shut - deny_off;
  543.         strcpy(denytime, ctime(&deny));
  544.  
  545.         text[0] = '\0';
  546.  
  547.         while (fgets(buf, sizeof(buf), fp) != NULL) {
  548.             msg_massage(buf, linebuf);
  549.             if ((strlen(text) + strlen(linebuf)) < sizeof(text))
  550.                 strcat(text, linebuf);
  551.         }
  552.  
  553.         (void) fclose(fp);
  554.     }
  555.     /* if last == 0, then is_shutdown() only called with quiet == 1 so far */
  556.     if (last == 0 && !quiet) {
  557.         autospout = text;       /* warn them for the first time */
  558.         autospout_free = 0;
  559.         last = curtime;
  560.     }
  561.     /* if past disconnect time, tell caller to drop 'em */
  562.     if (curtime > disc)
  563.         return (1);
  564.  
  565.     /* if less than 60 seconds to disconnection, warn 'em continuously */
  566.     if (curtime > (disc - 60) && !quiet) {
  567.         autospout = text;
  568.         autospout_free = 0;
  569.         last = curtime;
  570.     }
  571.     /* if less than 15 minutes to disconnection, warn 'em every 5 mins */
  572.     if (curtime > (disc - 60 * 15)) {
  573.         if ((curtime - last) > (60 * 5) && !quiet) {
  574.             autospout = text;
  575.             autospout_free = 0;
  576.             last = curtime;
  577.         }
  578.     }
  579.     /* if less than 24 hours to disconnection, warn 'em every 30 mins */
  580.     if (curtime < (disc - 24 * 60 * 60) && !quiet) {
  581.         if ((curtime - last) > (60 * 30)) {
  582.             autospout = text;
  583.             autospout_free = 0;
  584.             last = curtime;
  585.         }
  586.     }
  587.     /* if more than 24 hours to disconnection, warn 'em every 60 mins */
  588.     if (curtime > (disc - 24 * 60 * 60) && !quiet) {
  589.         if ((curtime - last) >= (24 * 60 * 60)) {
  590.             autospout = text;
  591.             autospout_free = 0;
  592.             last = curtime;
  593.         }
  594.     }
  595.     return (0);
  596. }
  597.  
  598. newer(char *date, char *path, int showlots)
  599. {
  600.     struct tm tm;
  601.  
  602.     if (sscanf(date, "%04d%02d%02d%02d%02d%02d",
  603.                &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
  604.                &tm.tm_hour, &tm.tm_min, &tm.tm_sec) == 6) {
  605.  
  606.         tm.tm_year -= 1900;
  607.         tm.tm_mon--;
  608.         tm.tm_isdst = -1;
  609.         newer_time = mktime(&tm);
  610.         dout = dataconn("file list", (off_t) - 1, "w");
  611.         /* dout = dataconn("file list", (off_t)-1, "w", 0); */
  612.         transflag++;
  613.         if (dout != NULL) {
  614.  
  615.             show_fullinfo = showlots;
  616. #if defined(HAVE_FTW)
  617.             ftw(path, check_newer, -1);
  618. #else
  619.             treewalk(path, check_newer, -1, NULL);
  620. #endif
  621.  
  622.             if (ferror(dout) != 0)
  623.                 perror_reply(550, "Data connection");
  624.             else
  625.                 reply(226, "Transfer complete.");
  626.  
  627.             (void) fclose(dout);
  628.             data = -1;
  629.         }
  630.     } else
  631.         reply(501, "Bad DATE format");
  632.     transflag = 0;
  633. }
  634.  
  635. int
  636. type_match(char *typelist)
  637. {
  638.     if (anonymous && strcasestr(typelist, "anonymous"))
  639.         return (1);
  640.     if (guest && strcasestr(typelist, "guest"))
  641.         return (1);
  642.     if (!guest && !anonymous && strcasestr(typelist, "real"))
  643.         return (1);
  644.  
  645.     return (0);
  646. }
  647.  
  648. int
  649. path_compare(char *p1, char *p2)
  650. {
  651.     if ( fnmatch(p1, p2, NULL) != 0 )
  652.         return(strlen(p1));
  653.     else
  654.         return(-1);
  655. }
  656.  
  657. void
  658. expand_id(void)
  659. {
  660.     struct aclmember *entry = NULL;
  661.     struct passwd *pwent;
  662.     struct group *grent;
  663.     char buf[BUFSIZ];
  664.  
  665.     while (getaclentry("upload", &entry) && ARG0 && ARG1 && ARG2 != NULL) {
  666.         if (ARG3 && ARG4) {
  667.             pwent = getpwnam(ARG3);
  668.             grent = getgrnam(ARG4);
  669.  
  670.             if (pwent)  sprintf(buf, "%d", pwent->pw_uid);
  671.             else        sprintf(buf, "%d", 0);
  672.             ARG3 = (char *) malloc(strlen(buf) + 1);
  673.             strcpy(ARG3, buf);
  674.  
  675.             if (grent)  sprintf(buf, "%d", grent->gr_gid);
  676.             else        sprintf(buf, "%d", 0);
  677.             ARG4 = (char *) malloc(strlen(buf) + 1);
  678.             strcpy(ARG4, buf);
  679.         }
  680.     }
  681. }
  682.  
  683. int
  684. fn_check(char *name)
  685. {
  686.   /* check to see if this is a valid file name... path-filter <type>
  687.    * <message_file> <allowed_charset> <disallowed> */
  688.  
  689.   struct aclmember *entry = NULL;
  690.   int   j;
  691.   char *sp;
  692.   char *path;
  693. #ifdef M_UNIX
  694. # ifdef REGEX
  695.   char *regp;
  696. # endif
  697. #endif
  698.  
  699. #ifdef REGEXEC
  700.   regex_t regexbuf;
  701.   regmatch_t regmatchbuf;
  702. #endif
  703.  
  704.   while (getaclentry("path-filter", &entry) && ARG0 != NULL) {
  705.       if (type_match(ARG0) && ARG1 && ARG2) {
  706.  
  707.           /*
  708.            * check *only* the basename
  709.            */
  710.  
  711.           if (path = strrchr(name, '/'))  ++path;
  712.           else    path = name;
  713.  
  714.           /* is it in the allowed character set? */
  715. #if defined(REGEXEC)
  716.           if (regcomp(®exbuf, ARG2, REG_EXTENDED|REG_ICASE) != 0) {
  717.               reply(553, "REGEX error");
  718. #elif defined(REGEX)
  719.           if ((sp = regcmp(ARG2, (char *) 0)) == NULL) {
  720.               reply(553, "REGEX error");
  721. #else
  722.           if ((sp = re_comp(ARG2)) != 0) {
  723.               perror_reply(553, sp);
  724. #endif
  725.               return(0);
  726.           }
  727. #if defined(REGEXEC)
  728.           if (regexec(®exbuf, path, 1, ®matchbuf, 0) != 0) {
  729. #elif defined(REGEX)
  730. # ifdef M_UNIX
  731.           regp = regex(sp, path);
  732.           free(sp);
  733.           if (regp == NULL) {
  734. # else
  735.           if ((regex(sp, path)) == NULL) {
  736. # endif
  737. #else
  738.           if ((re_exec(path)) != 1) {
  739. #endif
  740.               pr_mesg(553, ARG1);
  741.               reply(553, "%s: Permission denied. (Filename (accept))", name);
  742.               return(0);
  743.           }
  744.           /* is it in any of the disallowed regexps */
  745.  
  746.           for (j = 3; j < MAXARGS; ++j) {
  747.               /* ARGj == entry->arg[j] */
  748.               if (entry->arg[j]) {
  749. #if defined(REGEXEC)
  750.                   if (regcomp(®exbuf, entry->arg[j], 
  751.                         REG_EXTENDED|REG_ICASE) !=0) {
  752.                       reply(553, "REGEX error");
  753. #elif defined(REGEX)
  754.                   if ((sp = regcmp(entry->arg[j], (char *) 0)) == NULL) {
  755.                       reply(553, "REGEX error");
  756. #else
  757.                   if ((sp = re_comp(entry->arg[j])) != 0) {
  758.                       perror_reply(553, sp);
  759. #endif
  760.                       return(0);
  761.                   }
  762. #if defined(REGEXEC)
  763.                   if (regexec(®exbuf, path, 1, ®matchbuf, 0) == 0) {
  764. #elif defined(REGEX)
  765. # ifdef M_UNIX
  766.                   regp = regex(sp, path);
  767.                   free(sp);
  768.                   if (regp != NULL) {
  769. # else
  770.                   if ((regex(sp, path)) != NULL) {
  771. # endif
  772. #else
  773.                   if ((re_exec(path)) == 1) {
  774. #endif
  775.                       pr_mesg(553, ARG1);
  776.                       reply(553, "%s: Permission denied. (Filename (deny))", name);
  777.                       return(0);
  778.                   }
  779.               }
  780.           }
  781.       }
  782.   }
  783.   return(1);
  784. }
  785.  
  786. int
  787. dir_check(char *name, uid_t *uid, gid_t *gid, int *valid)
  788. {
  789.   struct aclmember *entry = NULL;
  790.  
  791.   int i,
  792.     match_value = -1;
  793.   char *ap2 = NULL,
  794.        *ap3 = NULL,
  795.        *ap4 = NULL,
  796.        *ap6 = NULL;
  797.   char cwdir[BUFSIZ];
  798.   char path[BUFSIZ];
  799.   char *sp;
  800.   extern struct passwd *pw;
  801.  
  802.   *valid = 0;
  803.  
  804.   strcpy(path, name);
  805.   if (sp = strrchr(path, '/'))  *sp = '\0';
  806.   else strcpy(path, ".");
  807.  
  808.   if ((realpath(path, cwdir)) == NULL) {
  809.       perror_reply(553, "Could not determine cwdir");
  810.       return(0);
  811.   }
  812.  
  813.   i = match_value;
  814.   while (getaclentry("upload", &entry) && ARG0 && ARG1 && ARG2 != NULL) {
  815.       if ( (!strcmp(ARG0, pw->pw_dir))  &&
  816.            ((i = path_compare(ARG1, cwdir)) >= match_value) ) {
  817.           match_value = i;
  818.           ap2 = ARG2;
  819.           if (ARG3)  ap3 = ARG3;
  820.           else       ap3 = NULL;
  821.           if (ARG4)  ap4 = ARG4;
  822.           else       ap4 = NULL;
  823.           if (ARG6)  ap6 = ARG6;
  824.           else       ap6 = NULL;
  825.       }
  826.   }
  827.  
  828.   if ( ((ap2 && !strcasecmp(ap2, "no")) && (ap3 && strcasecmp(ap3, "dirs"))) || 
  829.         (ap3 && !strcasecmp(ap3, "nodirs")) ||
  830.         (ap6 && !strcasecmp(ap6, "nodirs")) ) {
  831.       reply(530, "%s: Permission denied.  (Upload)", name);
  832.       return(0);
  833.   }
  834.  
  835.   if (ap3)
  836.      *uid = atoi(ap3);    /* the uid  */
  837.   if (ap4) {
  838.      *gid = atoi(ap4);    /* the gid  */
  839.      *valid = 1;
  840.    }
  841.   return(1);
  842. }
  843.  
  844. int
  845. upl_check(char *name, uid_t *uid, gid_t *gid, int *f_mode, int *valid)
  846. {
  847.   int  match_value = -1;
  848.   char cwdir[BUFSIZ];
  849.   char path[BUFSIZ];
  850.   char *sp;
  851.   int  i;
  852.  
  853.   char *ap1 = NULL,
  854.    *ap2 = NULL,
  855.    *ap3 = NULL,
  856.    *ap4 = NULL,
  857.    *ap5 = NULL;
  858.  
  859.   struct aclmember *entry = NULL;
  860.   extern struct passwd *pw;
  861.  
  862.   *valid = 0;
  863.  
  864.       /* what's our current directory? */
  865.  
  866.       strcpy(path, name);
  867.       if (sp = strrchr(path, '/'))  *sp = '\0';
  868.       else strcpy(path, ".");
  869.  
  870.       if ((realpath(path, cwdir)) == NULL) {
  871.           perror_reply(553, "Could not determine cwdir");
  872.           return(-1);
  873.       }
  874.  
  875.       /* we are doing a "best match"... ..so we keep track of what "match
  876.        * value" we have received so far... */
  877.  
  878.       entry = NULL;
  879.       match_value = -1;
  880.       i = match_value;
  881.       while (getaclentry("upload", &entry) && ARG0 && ARG1 && ARG2 != NULL) {
  882.           if ( (!strcmp(ARG0, pw->pw_dir))  &&
  883.                ((i = path_compare(ARG1, cwdir)) >= match_value) ) {
  884.               match_value = i;
  885.               ap1 = ARG1;
  886.               ap2 = ARG2;
  887.               if (ARG3) ap3 = ARG3;
  888.               else      ap3 = NULL;
  889.               if (ARG4) ap4 = ARG4;
  890.               else      ap4 = NULL;
  891.               if (ARG5) ap5 = ARG5;
  892.               else      ap5 = NULL;
  893.           }
  894.       }
  895.  
  896.       if (ap3 && ( (!strcasecmp("dirs",ap3)) || (!strcasecmp("nodirs", ap3)) ))
  897.         ap3 = NULL;
  898.  
  899.       /* if we did get matches... ..else don't do any of this stuff */
  900.       if (match_value >= 0) {
  901.           if (!strcasecmp(ap2, "yes")) {
  902.               if (ap3)
  903.                   *uid = atoi(ap3);    /* the uid  */
  904.               if (ap4) {
  905.                   *gid = atoi(ap4);    /* the gid  */
  906.           *valid = 1;
  907.         }
  908.               if (ap5)
  909.                   sscanf(ap5, "%o", f_mode); /* the mode */
  910.           } else {
  911.               reply(553, "%s: Permission denied. (Upload)", name);
  912.               return(-1);
  913.           }
  914.       } else {
  915.           /*
  916.            * upload defaults to "permitted"
  917.            */
  918.           return(1);
  919.       }
  920.  
  921.   return(match_value);
  922. }
  923.  
  924. int
  925. del_check(char *name)
  926. {
  927.   int pdelete = 1;
  928.   struct aclmember *entry = NULL;
  929.  
  930.   while (getaclentry("delete", &entry) && ARG0 && ARG1 != NULL) {
  931.       if (type_match(ARG1))
  932.           if (*ARG0 == 'n')
  933.               pdelete = 0;
  934.   }
  935.  
  936.   if (!pdelete) {
  937.       reply(553, "%s: Permission denied. (Delete)", name);
  938.       return(0);
  939.   } else {
  940.       return(1);
  941.   }
  942. }
  943.