Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/libexec/ftpd Features:



details:   https://anonhg.NetBSD.org/src/rev/72a9843dc03e
branches:  trunk
changeset: 500753:72a9843dc03e
user:      lukem <lukem%NetBSD.org@localhost>
date:      Mon Dec 18 02:32:50 2000 +0000

description:
Features:

* Add ftpd.conf(5) directive `advertise'; change the address that is
  advertised to the client for PASV transfers. this may be useful in
  certain firewall/NAT environments.

  Feature requested in [bin/9606] by Scott Presnell.

* Add -X option; syslog wu-ftpd style xferlog messages, prefixed with
  `xferlog: '.  An example line from syslog (wrapped):
        Dec 16 18:50:24 odysseus ftpd[571]: xferlog: Sat Dec 16 18:50:24 2000
        2 localhost 3747328 /pub/WLW2K601.EXE b _ o a lukem@ FTP 0 * c

  These messages can be converted to a wu-ftpd style xferlog file
  suitable for parsing with third-party tools with something like:
        grep 'xferlog: ' /var/log/xferlog | \
            sed -e 's/^.*xferlog: //' >wuxferlog

  The format is the same as the wu-ftpd xferlog entries (with the leading
  syslog stuff), but different from the wu-ftpd syslogged xferlog entries
  because the latter is not as easy to convert into the standard xferlog
  file format.

  The choice to only syslog the xferlog messages rather than append to
  a /var/log/xferlog file was made because the latter doesn't work to
  well in the situation where the logfile is rotated and compressed and
  a long-running ftpd still has a file-descriptor to the now nonexistant
  xferlog file, and the log message will then get lost.

  Feature requested in [bin/11651] by Hubert Feyrer.


Fixes:

* In ftpd(8), clarify the -a and -c options.

* More clarifications in ftpd.conf(5).

* Ensure that all ftpd.conf commands set a parameter back to sane defaults
  if an argument of `none' or bad settings are given.

* Support the `chroot' directive for `REAL' users too (for consistency).

* For `GUEST' users, store the supplied password in pw->pw_passwd for use
  later in the xferlog.

* If show_chdir_messages() is given a code of -1, flush the cache of
  visited directories.  Invoke show_chdir_messages(-1) in end_login().

* Only syslog session stats if logging is requested.

* Rename logcmd() -> logxfer(), and dolog() -> logremotehost().

* Use cprintf() instead of fprintf() where appropriate.

* Minor KNF, and make a couple of functions static that were declared static.

diffstat:

 libexec/ftpd/cmds.c      |   24 ++--
 libexec/ftpd/conf.c      |  135 +++++++++++++++++++++-----
 libexec/ftpd/extern.h    |   69 +++++++------
 libexec/ftpd/ftpcmd.y    |   10 +-
 libexec/ftpd/ftpd.8      |   48 +++++++-
 libexec/ftpd/ftpd.c      |  235 ++++++++++++++++++++++++++++++++++------------
 libexec/ftpd/ftpd.conf.5 |  175 +++++++++++++++++++++++++---------
 libexec/ftpd/version.h   |    4 +-
 8 files changed, 503 insertions(+), 197 deletions(-)

diffs (truncated from 1499 to 300 lines):

diff -r b7bd7a2a8f20 -r 72a9843dc03e libexec/ftpd/cmds.c
--- a/libexec/ftpd/cmds.c       Mon Dec 18 00:46:47 2000 +0000
+++ b/libexec/ftpd/cmds.c       Mon Dec 18 02:32:50 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: cmds.c,v 1.9 2000/12/04 10:50:39 itojun Exp $  */
+/*     $NetBSD: cmds.c,v 1.10 2000/12/18 02:32:50 lukem Exp $  */
 
 /*
  * Copyright (c) 1999-2000 The NetBSD Foundation, Inc.
@@ -101,7 +101,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: cmds.c,v 1.9 2000/12/04 10:50:39 itojun Exp $");
+__RCSID("$NetBSD: cmds.c,v 1.10 2000/12/18 02:32:50 lukem Exp $");
 #endif /* not lint */
 
 #include <sys/param.h>
@@ -188,7 +188,7 @@
                perror_reply(550, name);
        } else
                ack("DELE");
-       logcmd("delete", -1, name, NULL, NULL, p);
+       logxfer("delete", -1, name, NULL, NULL, p);
 }
 
 void
@@ -219,7 +219,7 @@
                perror_reply(550, name);
        } else
                replydirname(name, "directory created.");
-       logcmd("mkdir", -1, name, NULL, NULL, p);
+       logxfer("mkdir", -1, name, NULL, NULL, p);
 }
 
 void
@@ -412,7 +412,7 @@
                perror_reply(550, name);
        } else
                ack("RMD");
-       logcmd("rmdir", -1, name, NULL, NULL, p);
+       logxfer("rmdir", -1, name, NULL, NULL, p);
 }
 
 char *
@@ -438,7 +438,7 @@
                perror_reply(550, "rename");
        } else
                ack("RNTO");
-       logcmd("rename", -1, from, to, NULL, p);
+       logxfer("rename", -1, from, to, NULL, p);
 }
 
 void
@@ -446,14 +446,17 @@
 {
        switch (type) {
        case TYPE_L:
-       case TYPE_I: {
+       case TYPE_I:
+           {
                struct stat stbuf;
                if (stat(filename, &stbuf) < 0 || !S_ISREG(stbuf.st_mode))
                        reply(550, "%s: not a plain file.", filename);
                else
                        reply(213, ULLF, (ULLT)stbuf.st_size);
-               break; }
-       case TYPE_A: {
+               break;
+           }
+       case TYPE_A:
+           {
                FILE *fin;
                int c;
                off_t count;
@@ -478,7 +481,8 @@
                (void) fclose(fin);
 
                reply(213, LLF, (LLT)count);
-               break; }
+               break;
+           }
        default:
                reply(504, "SIZE not implemented for Type %c.", "?AEIL"[type]);
        }
diff -r b7bd7a2a8f20 -r 72a9843dc03e libexec/ftpd/conf.c
--- a/libexec/ftpd/conf.c       Mon Dec 18 00:46:47 2000 +0000
+++ b/libexec/ftpd/conf.c       Mon Dec 18 02:32:50 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: conf.c,v 1.36 2000/11/16 13:15:13 lukem Exp $  */
+/*     $NetBSD: conf.c,v 1.37 2000/12/18 02:32:50 lukem Exp $  */
 
 /*-
  * Copyright (c) 1997-2000 The NetBSD Foundation, Inc.
@@ -38,17 +38,19 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: conf.c,v 1.36 2000/11/16 13:15:13 lukem Exp $");
+__RCSID("$NetBSD: conf.c,v 1.37 2000/12/18 02:32:50 lukem Exp $");
 #endif /* not lint */
 
 #include <sys/types.h>
 #include <sys/param.h>
+#include <sys/socket.h>
 #include <sys/stat.h>
 
 #include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <glob.h>
+#include <netdb.h>
 #include <setjmp.h>
 #include <signal.h>
 #include <stdio.h>
@@ -71,6 +73,13 @@
 static int filetypematch(char *, int);
 
 
+               /* class defaults */
+#define DEFAULT_LIMIT          -1              /* unlimited connections */
+#define DEFAULT_MAXFILESIZE    -1              /* unlimited file size */
+#define DEFAULT_MAXTIMEOUT     7200            /* 2 hours */
+#define DEFAULT_TIMEOUT                900             /* 15 minutes */
+#define DEFAULT_UMASK          027             /* 15 minutes */
+
 /*
  * Initialise curclass to an `empty' state
  */
@@ -88,26 +97,28 @@
                free(conv);
        }
 
+       memset((char *)&curclass.advertise, 0, sizeof(curclass.advertise));
+       curclass.advertise.su_len = 0;          /* `not used' */
        REASSIGN(curclass.chroot, NULL);
        REASSIGN(curclass.classname, NULL);
        curclass.conversions =  NULL;
        REASSIGN(curclass.display, NULL);
        REASSIGN(curclass.homedir, NULL);
-       curclass.limit =        -1;             /* unlimited connections */
+       curclass.limit =        DEFAULT_LIMIT;  
        REASSIGN(curclass.limitfile, NULL);
-       curclass.maxfilesize =  -1;             /* unlimited file size */
+       curclass.maxfilesize =  DEFAULT_MAXFILESIZE;
        curclass.maxrateget =   0;
        curclass.maxrateput =   0;
-       curclass.maxtimeout =   7200;           /* 2 hours */
+       curclass.maxtimeout =   DEFAULT_MAXTIMEOUT;
        REASSIGN(curclass.motd, xstrdup(_PATH_FTPLOGINMESG));
        REASSIGN(curclass.notify, NULL);
        curclass.portmin =      0;
        curclass.portmax =      0;
        curclass.rateget =      0;
        curclass.rateput =      0;
-       curclass.timeout =      900;            /* 15 minutes */
+       curclass.timeout =      DEFAULT_TIMEOUT;
            /* curclass.type is set elsewhere */
-       curclass.umask =        027;
+       curclass.umask =        DEFAULT_UMASK;
 
        CURCLASS_FLAGS_SET(checkportcmd);
        CURCLASS_FLAGS_SET(modify);
@@ -137,6 +148,7 @@
 
        init_curclass();
        REASSIGN(curclass.classname, xstrdup(findclass));
+                       /* set more guest defaults */
        if (strcasecmp(findclass, "guest") == 0) {
                CURCLASS_FLAGS_CLR(modify);
                curclass.umask = 0707;
@@ -192,7 +204,58 @@
                REASSIGN(curclass.x, arg); \
        } while (0)
 
-               if (strcasecmp(word, "checkportcmd") == 0) {
+
+               if (0)  {
+                       /* no-op */
+
+               } else if (strcasecmp(word, "advertise") == 0) {
+                       struct addrinfo hints, *res;
+                       int             error;
+
+                       memset((char *)&curclass.advertise, 0,
+                           sizeof(curclass.advertise));
+                       curclass.advertise.su_len = 0;
+                       if (none || EMPTYSTR(arg))
+                               continue;
+                       res = NULL;
+                       memset(&hints, 0, sizeof(hints));
+                                       /*
+                                        * only get addresses of the family
+                                        * that we're listening on
+                                        */
+                       hints.ai_family = ctrl_addr.su_family;
+                       hints.ai_socktype = SOCK_STREAM;
+                       error = getaddrinfo(arg, "0", &hints, &res);
+                       if (error) {
+                               syslog(LOG_WARNING, "%s line %d: %s",
+                                   infile, (int)line, gai_strerror(error));
+ advertiseparsefail:
+                               if (res)
+                                       freeaddrinfo(res);
+                               continue;
+                       }
+                       if (res->ai_next) {
+                               syslog(LOG_WARNING,
+    "%s line %d: multiple addresses returned for `%s'; please be more specific",
+                                   infile, (int)line, arg);
+                               goto advertiseparsefail;
+                       }
+                       if (sizeof(curclass.advertise) < res->ai_addrlen || (
+#ifdef INET6
+                           res->ai_family != AF_INET6 &&
+#endif
+                           res->ai_family != AF_INET)) {
+                               syslog(LOG_WARNING,
+    "%s line %d: unsupported protocol %d for `%s'",
+                                   infile, (int)line, res->ai_family, arg);
+                               goto advertiseparsefail;
+                       }
+                       memcpy(&curclass.advertise, res->ai_addr,
+                           res->ai_addrlen);
+                       curclass.advertise.su_len = res->ai_addrlen;
+                       freeaddrinfo(res);
+
+               } else if (strcasecmp(word, "checkportcmd") == 0) {
                        CONF_FLAG(checkportcmd);
 
                } else if (strcasecmp(word, "chroot") == 0) {
@@ -272,21 +335,11 @@
                } else if (strcasecmp(word, "homedir") == 0) {
                        CONF_STRING(homedir);
 
-               } else if (strcasecmp(word, "maxfilesize") == 0) {
-                       if (none || EMPTYSTR(arg))
-                               continue;
-                       llval = strsuftoll(arg);
-                       if (llval == -1) {
-                               syslog(LOG_WARNING,
-                                   "%s line %d: invalid maxfilesize %s",
-                                   infile, (int)line, arg);
-                               continue;
-                       }
-                       curclass.maxfilesize = llval;
-
                } else if (strcasecmp(word, "limit") == 0) {
                        int limit;
 
+                       curclass.limit = DEFAULT_LIMIT;
+                       REASSIGN(curclass.limitfile, NULL);
                        if (none || EMPTYSTR(arg))
                                continue;
                        limit = (int)strtol(arg, &endp, 10);
@@ -300,7 +353,21 @@
                        REASSIGN(curclass.limitfile,
                            EMPTYSTR(p) ? NULL : xstrdup(p));
 
+               } else if (strcasecmp(word, "maxfilesize") == 0) {
+                       curclass.maxfilesize = DEFAULT_MAXFILESIZE;
+                       if (none || EMPTYSTR(arg))
+                               continue;
+                       llval = strsuftoll(arg);
+                       if (llval == -1) {
+                               syslog(LOG_WARNING,
+                                   "%s line %d: invalid maxfilesize %s",
+                                   infile, (int)line, arg);
+                               continue;
+                       }
+                       curclass.maxfilesize = llval;
+
                } else if (strcasecmp(word, "maxtimeout") == 0) {
+                       curclass.maxtimeout = DEFAULT_MAXTIMEOUT;
                        if (none || EMPTYSTR(arg))
                                continue;
                        timeout = (unsigned int)strtoul(arg, &endp, 10);
@@ -341,12 +408,9 @@
                        int minport, maxport;
                        char *min, *max;
 
-                       if (none) {
-                               curclass.portmin = 0;
-                               curclass.portmax = 0;
-                               continue;
-                       }
-                       if (EMPTYSTR(arg))
+                       curclass.portmin = 0;
+                       curclass.portmax = 0;
+                       if (none || EMPTYSTR(arg))
                                continue;
                        min = arg;
                        NEXTWORD(p, max);
@@ -382,6 +446,8 @@
                        curclass.portmax = maxport;
 
                } else if (strcasecmp(word, "rateget") == 0) {
+                       curclass.maxrateget = 0;
+                       curclass.rateget = 0;
                        if (none || EMPTYSTR(arg))



Home | Main Index | Thread Index | Old Index