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