summaryrefslogtreecommitdiffstats
path: root/contrib/lukemftpd
diff options
context:
space:
mode:
authorobrien <obrien@FreeBSD.org>2002-03-14 19:25:32 +0000
committerobrien <obrien@FreeBSD.org>2002-03-14 19:25:32 +0000
commit1535c5d0a834af5a3f099e6a39081379116dd002 (patch)
treedf37c593893b3b5168ce2b423d495103c9d24c0f /contrib/lukemftpd
parente4751f9e00971d0c774736bb50344b7ea67d40b0 (diff)
downloadFreeBSD-src-1535c5d0a834af5a3f099e6a39081379116dd002.zip
FreeBSD-src-1535c5d0a834af5a3f099e6a39081379116dd002.tar.gz
Import of LukeM's ftpd version 1.2 Beta 1.
Diffstat (limited to 'contrib/lukemftpd')
-rw-r--r--contrib/lukemftpd/ChangeLog32
-rw-r--r--contrib/lukemftpd/INSTALL9
-rw-r--r--contrib/lukemftpd/NEWS10
-rw-r--r--contrib/lukemftpd/README4
-rw-r--r--contrib/lukemftpd/THANKS1
-rwxr-xr-xcontrib/lukemftpd/configure6
-rw-r--r--contrib/lukemftpd/configure.in8
-rw-r--r--contrib/lukemftpd/lukemftpd.h4
-rw-r--r--contrib/lukemftpd/src/cmds.c57
-rw-r--r--contrib/lukemftpd/src/conf.c41
-rw-r--r--contrib/lukemftpd/src/extern.h16
-rw-r--r--contrib/lukemftpd/src/ftpcmd.y20
-rw-r--r--contrib/lukemftpd/src/ftpd.848
-rw-r--r--contrib/lukemftpd/src/ftpd.c306
-rw-r--r--contrib/lukemftpd/src/ftpd.conf.560
-rw-r--r--contrib/lukemftpd/src/ftpusers.517
-rw-r--r--contrib/lukemftpd/src/popen.c14
-rw-r--r--contrib/lukemftpd/src/version.h4
-rw-r--r--contrib/lukemftpd/todo4
19 files changed, 421 insertions, 240 deletions
diff --git a/contrib/lukemftpd/ChangeLog b/contrib/lukemftpd/ChangeLog
index 76cb9da..82270df 100644
--- a/contrib/lukemftpd/ChangeLog
+++ b/contrib/lukemftpd/ChangeLog
@@ -1,3 +1,33 @@
+Thu Mar 14 06:02:31 UTC 2002 lukem
+
+ * released 1.2 beta 1
+
+Thu Mar 14 05:39:24 UTC 2002 lukem
+
+ * libukem/snprintf.c: fix compile errors with gcc 3.x
+
+Sat Mar 1 07:10:54 UTC 2002 lukem
+
+ * update to NetBSD-current 2002-03-01
+ User visible changes include:
+ - enable case insensitive fnmatch(3)ing for hostname globs
+ in ftpusers(5)
+ - add 'denyquick' ftpd.conf(5) keyword
+ - add 'private' ftpd.conf(5) keyword
+ - use "advertise" in docco
+ User visible fixes:
+ - reject SIZE requests for ASCII files > 10KB long
+ - fixes for mlsd/mlst standards conformance
+ - fix passive transfers for various web browsers
+ - various glob(3) fixes
+ - don't log xferlog-style entries if the transfer didn't start
+ - fix skey password challenge
+ - don't try and use the motd directive if it's not set
+
+Thu Feb 28 01:39:06 UTC 2002 lukem
+
+ * update libukem/glob.c from NetBSD's __glob13.c rev 1.22 and rev 1.23
+
Wed May 9 02:04:08 UTC 2001 lukem
* released 1.1
@@ -10,7 +40,7 @@ Sat Apr 28 07:13:57 UTC 2001 lukem
Wed Apr 25 06:27:08 UTC 2001 lukem
- * update to NetBSD-current 2001/04/25:
+ * update to NetBSD-current 2001-04-25:
- update copyrights
- remove superfluous byte_count update in send_file_list
- use own code instead of bothering with glob() to do ~
diff --git a/contrib/lukemftpd/INSTALL b/contrib/lukemftpd/INSTALL
index 80fa04b..b187aeb 100644
--- a/contrib/lukemftpd/INSTALL
+++ b/contrib/lukemftpd/INSTALL
@@ -40,9 +40,12 @@ script. `configure' supports the following options:
BSD or GNU make may be required for this to work.
* Specific options:
- --enable-ipv6 Enable IPv6 support (if your OS supports it)
- --disable-ipv6 Disable IPv6 support (even if your OS supports it.)
- [default: enabled].
+
+ --enable-ipv6 Enable IPv6 support (if your OS supports it).
+ --disable-ipv6 Disable IPv6 support (even if your OS supports it).
+ [default: enabled]
+ --enable-builtinls Enable built-in /bin/ls. [default: enabled]
+ --disable-builtinls Disable built-in /bin/ls.
--with-socks Compile with SOCKS firewall traversal support.
--with-socks5[=PATH] Compile with SOCKS5 firewall traversal support.
--with-socks4[=PATH] Compile with SOCKS4 firewall traversal support.
diff --git a/contrib/lukemftpd/NEWS b/contrib/lukemftpd/NEWS
index b1c0211..6dcc320 100644
--- a/contrib/lukemftpd/NEWS
+++ b/contrib/lukemftpd/NEWS
@@ -1,4 +1,14 @@
This is a brief description of the new features and fixes added to
+lukemftpd-1.2 since the release of lukemftpd-1.1.
+
+* "denyquick" keyword added to ftpd.conf(5).
+
+* "private" keyword added to ftpd.conf(5).
+
+* Hostnames in ftpusers(5) are now matched in a case-insensitive fashion.
+
+---
+This is a brief description of the new features and fixes added to
lukemftpd-1.1 since the release of lukemftpd-1.0.
* Fixed checkportcmd for the IPv4 case.
diff --git a/contrib/lukemftpd/README b/contrib/lukemftpd/README
index 60d645f..95b42a9 100644
--- a/contrib/lukemftpd/README
+++ b/contrib/lukemftpd/README
@@ -2,7 +2,7 @@ WHAT IS LUKEMFTPD?
------------------
`lukemftpd' is what many users affectionately call the enhanced ftp
-server in NetBSD (http://www.netbsd.org). The `lukem' comes from
+server in NetBSD ( http://www.netbsd.org/ ). The `lukem' comes from
the account name of the NetBSD developer who wrote most of the
enhancements: Luke Mewburn <lukem@netbsd.org>.
@@ -38,6 +38,8 @@ include:
+ specify the directory to chroot(2) to
+ automatic in-line conversions (e.g, `.tar.gz'
retrieval of directories)
+ + deny logins after the username is provided (rather
+ than after the password)
+ display a file the first time a directory is entered
+ specify the home directory of the session (for "cd ~")
+ limit the maximum number of concurrent sessions
diff --git a/contrib/lukemftpd/THANKS b/contrib/lukemftpd/THANKS
index b6ce509..5919880 100644
--- a/contrib/lukemftpd/THANKS
+++ b/contrib/lukemftpd/THANKS
@@ -6,4 +6,5 @@ Christos Zoulas <christos@netbsd.org>
Curt Sampson <cjs@netbsd.org>
Jun-ichiro itojun Hagino <itojun@netbsd.org>
Matthew R. Green <mrg@eterna.com.au>
+Simon Burge <simonb@netbsd.org>
Todd Vierling <tv@netbsd.org>
diff --git a/contrib/lukemftpd/configure b/contrib/lukemftpd/configure
index 2a7563d..4d72d32 100755
--- a/contrib/lukemftpd/configure
+++ b/contrib/lukemftpd/configure
@@ -1,6 +1,6 @@
#! /bin/sh
-# From configure.in Revision: 1.16
+# From configure.in Revision: 1.17
@@ -25,8 +25,8 @@ ac_default_prefix=/usr/local
ac_help="$ac_help
\
--enable-ipv6 Enable IPv6 support (if your OS supports it).
- --disable-ipv6 Disable IPv6 support (even if your OS supports it)
- [default: enabled]."
+ --disable-ipv6 Disable IPv6 support (even if your OS supports it).
+ [default: enabled]"
ac_help="$ac_help
\
--enable-builtinls Enable built-in /bin/ls. [default: enabled]
diff --git a/contrib/lukemftpd/configure.in b/contrib/lukemftpd/configure.in
index 87331d0..470056d 100644
--- a/contrib/lukemftpd/configure.in
+++ b/contrib/lukemftpd/configure.in
@@ -1,10 +1,10 @@
-dnl $Id: configure.in,v 1.16 2001/04/28 07:11:06 lukem Exp $
+dnl $Id: configure.in,v 1.17 2001/12/01 02:00:48 lukem Exp $
dnl
dnl configure.in --
dnl process this file with autoconf to produce a configure script.
dnl
-AC_REVISION($Revision: 1.16 $)dnl
+AC_REVISION($Revision: 1.17 $)dnl
AC_INIT(lukemftpd.h)
@@ -13,8 +13,8 @@ dnl Arguments for which features are included
dnl
AC_ARG_ENABLE(ipv6, [\
--enable-ipv6 Enable IPv6 support (if your OS supports it).
- --disable-ipv6 Disable IPv6 support (even if your OS supports it)
- [default: enabled].],
+ --disable-ipv6 Disable IPv6 support (even if your OS supports it).
+ [default: enabled]],
opt_ipv6=$enableval,
opt_ipv6=yes)
AC_ARG_ENABLE(builtinls, [\
diff --git a/contrib/lukemftpd/lukemftpd.h b/contrib/lukemftpd/lukemftpd.h
index c697701..1a3e4d1 100644
--- a/contrib/lukemftpd/lukemftpd.h
+++ b/contrib/lukemftpd/lukemftpd.h
@@ -1,6 +1,6 @@
-/* $Id: lukemftpd.h,v 1.16 2001/05/09 02:04:53 lukem Exp $ */
+/* $Id: lukemftpd.h,v 1.18 2002/03/14 06:02:24 lukem Exp $ */
-#define FTPD_VERSION "lukemftpd 1.1"
+#define FTPD_VERSION "lukemftpd 1.2 beta 1"
#include "config.h"
diff --git a/contrib/lukemftpd/src/cmds.c b/contrib/lukemftpd/src/cmds.c
index 51efbb8..5f5db9f 100644
--- a/contrib/lukemftpd/src/cmds.c
+++ b/contrib/lukemftpd/src/cmds.c
@@ -1,4 +1,4 @@
-/* $NetBSD: cmds.c,v 1.13 2001/04/25 01:46:25 lukem Exp $ */
+/* $NetBSD: cmds.c,v 1.16 2002/02/13 15:15:23 lukem Exp $ */
/*
* Copyright (c) 1999-2001 The NetBSD Foundation, Inc.
@@ -102,12 +102,17 @@
#include "extern.h"
+typedef enum {
+ FE_MLSD = 1<<0, /* if op is MLSD (MLST otherwise ) */
+ FE_ISCURDIR = 1<<1, /* if name is the current directory */
+} factflag_t;
+
typedef struct {
const char *path; /* full pathname */
const char *display; /* name to display */
struct stat *stat; /* stat of path */
struct stat *pdirstat; /* stat of path's parent dir */
- int iscurdir; /* nonzero if name is the current dir */
+ factflag_t flags; /* flags */
} factelem;
static void ack(const char *);
@@ -224,13 +229,16 @@ mlsd(const char *path)
perror_reply(501, path);
return;
}
+ if ((dirp = opendir(path)) == NULL)
+ goto mlsdperror;
+
dout = dataconn("MLSD", (off_t)-1, "w");
if (dout == NULL)
return;
- if ((dirp = opendir(path)) == NULL)
- goto mlsdperror;
+ memset(&f, 0, sizeof(f));
f.stat = &sb;
+ f.flags |= FE_MLSD;
while ((dp = readdir(dirp)) != NULL) {
snprintf(name, sizeof(name), "%s/%s", path, dp->d_name);
if (ISDOTDIR(dp->d_name)) { /* special case curdir: */
@@ -238,7 +246,7 @@ mlsd(const char *path)
continue;
f.pdirstat = NULL; /* require stat of parent */
f.display = path; /* set name to real name */
- f.iscurdir = 1; /* flag name is curdir */
+ f.flags |= FE_ISCURDIR; /* flag name is curdir */
} else {
if (ISDOTDOTDIR(dp->d_name)) {
if (! hastypefact)
@@ -247,7 +255,7 @@ mlsd(const char *path)
} else
f.pdirstat = &pdirstat; /* cache parent stat */
f.display = dp->d_name;
- f.iscurdir = 0;
+ f.flags &= ~FE_ISCURDIR;
}
if (stat(name, &sb) == -1)
continue;
@@ -278,11 +286,11 @@ mlst(const char *path)
return;
}
reply(-250, "MLST %s", path);
+ memset(&f, 0, sizeof(f));
f.path = path;
f.display = path;
f.stat = &sb;
f.pdirstat = NULL;
- f.iscurdir = 0;
CPUTC(' ', stdout);
mlsname(stdout, &f);
reply(250, "End");
@@ -449,9 +457,14 @@ sizecmd(const char *filename)
(void) fclose(fin);
return;
}
+ if (stbuf.st_size > 10240) {
+ reply(550, "%s: file too large for SIZE.", filename);
+ (void) fclose(fin);
+ return;
+ }
count = 0;
- while((c=getc(fin)) != EOF) {
+ while((c = getc(fin)) != EOF) {
if (c == '\n') /* will get expanded to \r\n */
count++;
count++;
@@ -697,12 +710,16 @@ fact_type(const char *fact, FILE *fd, factelem *fe)
cprintf(fd, "%s=", fact);
switch (fe->stat->st_mode & S_IFMT) {
case S_IFDIR:
- if (fe->iscurdir || ISDOTDIR(fe->display))
- cprintf(fd, "cdir");
- else if (ISDOTDOTDIR(fe->display))
- cprintf(fd, "pdir");
- else
+ if (fe->flags & FE_MLSD) {
+ if ((fe->flags & FE_ISCURDIR) || ISDOTDIR(fe->display))
+ cprintf(fd, "cdir");
+ else if (ISDOTDOTDIR(fe->display))
+ cprintf(fd, "pdir");
+ else
+ cprintf(fd, "dir");
+ } else {
cprintf(fd, "dir");
+ }
break;
case S_IFREG:
cprintf(fd, "file");
@@ -757,13 +774,23 @@ matchgroup(gid_t gid)
static void
mlsname(FILE *fp, factelem *fe)
{
- int i;
+ char realfile[MAXPATHLEN];
+ int i, userf;
for (i = 0; i < FACTTABSIZE; i++) {
if (facttab[i].enabled)
(facttab[i].display)(facttab[i].name, fp, fe);
}
- cprintf(fp, " %s\r\n", fe->display);
+ if ((fe->flags & FE_MLSD) &&
+ !(fe->flags & FE_ISCURDIR) && !ISDOTDIR(fe->display)) {
+ /* if MLSD and not "." entry, display as-is */
+ userf = 0;
+ } else {
+ /* if MLST, or MLSD and "." entry, realpath(3) it */
+ if (realpath(fe->display, realfile) != NULL)
+ userf = 1;
+ }
+ cprintf(fp, " %s\r\n", userf ? realfile : fe->display);
}
static void
diff --git a/contrib/lukemftpd/src/conf.c b/contrib/lukemftpd/src/conf.c
index 19b9283..8ec927f 100644
--- a/contrib/lukemftpd/src/conf.c
+++ b/contrib/lukemftpd/src/conf.c
@@ -1,4 +1,4 @@
-/* $NetBSD: conf.c,v 1.41 2001/04/25 01:46:25 lukem Exp $ */
+/* $NetBSD: conf.c,v 1.46 2001/12/04 13:54:12 lukem Exp $ */
/*-
* Copyright (c) 1997-2001 The NetBSD Foundation, Inc.
@@ -93,8 +93,10 @@ init_curclass(void)
curclass.umask = DEFAULT_UMASK;
CURCLASS_FLAGS_SET(checkportcmd);
+ CURCLASS_FLAGS_CLR(denyquick);
CURCLASS_FLAGS_SET(modify);
CURCLASS_FLAGS_SET(passive);
+ CURCLASS_FLAGS_CLR(private);
CURCLASS_FLAGS_CLR(sanenames);
CURCLASS_FLAGS_SET(upload);
}
@@ -180,7 +182,8 @@ parse_conf(const char *findclass)
if (0) {
/* no-op */
- } else if (strcasecmp(word, "advertise") == 0) {
+ } else if ((strcasecmp(word, "advertise") == 0)
+ || (strcasecmp(word, "advertize") == 0)) {
struct addrinfo hints, *res;
int error;
@@ -301,6 +304,9 @@ parse_conf(const char *findclass)
REASSIGN(conv->disable, disable);
REASSIGN(conv->command, convcmd);
+ } else if (strcasecmp(word, "denyquick") == 0) {
+ CONF_FLAG(denyquick);
+
} else if (strcasecmp(word, "display") == 0) {
CONF_STRING(display);
@@ -417,6 +423,9 @@ parse_conf(const char *findclass)
curclass.portmin = minport;
curclass.portmax = maxport;
+ } else if (strcasecmp(word, "private") == 0) {
+ CONF_FLAG(private);
+
} else if (strcasecmp(word, "rateget") == 0) {
curclass.maxrateget = 0;
curclass.rateget = 0;
@@ -482,19 +491,19 @@ parse_conf(const char *findclass)
REASSIGN(template, EMPTYSTR(arg) ? NULL : xstrdup(arg));
} else if (strcasecmp(word, "umask") == 0) {
- mode_t umask;
+ mode_t fumask;
curclass.umask = DEFAULT_UMASK;
if (none || EMPTYSTR(arg))
continue;
- umask = (mode_t)strtoul(arg, &endp, 8);
- if (*endp != 0 || umask > 0777) {
+ fumask = (mode_t)strtoul(arg, &endp, 8);
+ if (*endp != 0 || fumask > 0777) {
syslog(LOG_WARNING,
"%s line %d: invalid umask %s",
infile, (int)line, arg);
continue;
}
- curclass.umask = umask;
+ curclass.umask = fumask;
} else if (strcasecmp(word, "upload") == 0) {
CONF_FLAG(upload);
@@ -528,7 +537,7 @@ show_chdir_messages(int code)
glob_t gl;
time_t now, then;
int age;
- char cwd[MAXPATHLEN];
+ char curwd[MAXPATHLEN];
char *cp, **rlist;
if (code == -1) {
@@ -550,14 +559,14 @@ show_chdir_messages(int code)
}
/* Check if this directory has already been visited */
- if (getcwd(cwd, sizeof(cwd) - 1) == NULL) {
+ if (getcwd(curwd, sizeof(curwd) - 1) == NULL) {
syslog(LOG_WARNING, "can't getcwd: %s", strerror(errno));
return;
}
- if (sl_find(slist, cwd) != NULL)
+ if (sl_find(slist, curwd) != NULL)
return;
- cp = xstrdup(cwd);
+ cp = xstrdup(curwd);
if (sl_add(slist, cp) == -1)
syslog(LOG_WARNING, "can't add `%s' to stringlist", cp);
@@ -568,7 +577,7 @@ show_chdir_messages(int code)
if (EMPTYSTR(curclass.notify))
return;
- gl.gl_offs = 0;
+ memset(&gl, 0, sizeof(gl));
if (glob(curclass.notify, GLOB_LIMIT, NULL, &gl) != 0
|| gl.gl_matchc == 0) {
globfree(&gl);
@@ -600,7 +609,8 @@ int
display_file(const char *file, int code)
{
FILE *f;
- char *buf, *p, *cwd;
+ char *buf, *p;
+ char curwd[MAXPATHLEN];
size_t len;
off_t lastnum;
time_t now;
@@ -634,13 +644,14 @@ display_file(const char *file, int code)
break;
case 'C':
- if (getcwd(cwd, sizeof(cwd)-1) == NULL){
+ if (getcwd(curwd, sizeof(curwd)-1)
+ == NULL){
syslog(LOG_WARNING,
"can't getcwd: %s",
strerror(errno));
continue;
}
- cprintf(stdout, "%s", cwd);
+ cprintf(stdout, "%s", curwd);
break;
case 'E':
@@ -771,7 +782,7 @@ strend(const char *s1, char *s2)
l1 = strlen(s1);
l2 = strlen(s2);
- if (l2 >= l1)
+ if (l2 >= l1 || l1 >= sizeof(buf))
return(NULL);
strlcpy(buf, s1, sizeof(buf));
diff --git a/contrib/lukemftpd/src/extern.h b/contrib/lukemftpd/src/extern.h
index 15cf939..3ddb6bf 100644
--- a/contrib/lukemftpd/src/extern.h
+++ b/contrib/lukemftpd/src/extern.h
@@ -1,4 +1,4 @@
-/* $NetBSD: extern.h,v 1.41 2001/04/25 01:46:25 lukem Exp $ */
+/* $NetBSD: extern.h,v 1.43 2001/12/04 13:54:12 lukem Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -193,7 +193,7 @@ void yyerror(char *);
#include <netinet/in.h>
-#ifdef BSD4_4
+#if defined(__NetBSD__)
# define HAVE_SETPROCTITLE 1
# define HAVE_SOCKADDR_SA_LEN 1
#endif
@@ -249,11 +249,13 @@ typedef enum {
typedef enum {
FLAG_checkportcmd = 1<<0, /* Check port commands */
- FLAG_modify = 1<<1, /* Allow CHMOD, DELE, MKD, RMD, RNFR,
+ FLAG_denyquick = 1<<1, /* Check ftpusers(5) before PASS */
+ FLAG_modify = 1<<2, /* Allow CHMOD, DELE, MKD, RMD, RNFR,
UMASK */
- FLAG_passive = 1<<2, /* Allow PASV mode */
- FLAG_sanenames = 1<<3, /* Restrict names of uploaded files */
- FLAG_upload = 1<<4 /* As per modify, but also allow
+ FLAG_passive = 1<<3, /* Allow PASV mode */
+ FLAG_private = 1<<4, /* Don't publish class info in STAT */
+ FLAG_sanenames = 1<<5, /* Restrict names of uploaded files */
+ FLAG_upload = 1<<6, /* As per modify, but also allow
APPE, STOR, STOU */
} classflag_t;
@@ -286,7 +288,7 @@ struct ftpclass {
mode_t umask; /* Umask to use */
};
-extern void ftp_loop(void) __attribute__ ((noreturn));
+extern void ftp_loop(void);
extern void ftp_handle_line(char *);
#ifndef GLOBAL
diff --git a/contrib/lukemftpd/src/ftpcmd.y b/contrib/lukemftpd/src/ftpcmd.y
index aeea190..68a598b 100644
--- a/contrib/lukemftpd/src/ftpcmd.y
+++ b/contrib/lukemftpd/src/ftpcmd.y
@@ -1,4 +1,4 @@
-/* $NetBSD: ftpcmd.y,v 1.65 2001/04/25 01:46:25 lukem Exp $ */
+/* $NetBSD: ftpcmd.y,v 1.66 2001/12/01 10:25:30 lukem Exp $ */
/*-
* Copyright (c) 1997-2001 The NetBSD Foundation, Inc.
@@ -1056,10 +1056,10 @@ pathname
if ($1[1] == '\0')
home = homedir;
else {
- struct passwd *pw;
+ struct passwd *hpw;
- if ((pw = getpwnam($1 + 1)) != NULL)
- home = pw->pw_dir;
+ if ((hpw = getpwnam($1 + 1)) != NULL)
+ home = hpw->pw_dir;
else
home = $1;
}
@@ -1681,12 +1681,12 @@ help(struct tab *ctab, const char *s)
{
struct tab *c;
int width, NCMDS;
- char *type;
+ char *htype;
if (ctab == sitetab)
- type = "SITE ";
+ htype = "SITE ";
else
- type = "";
+ htype = "";
width = 0, NCMDS = 0;
for (c = ctab; c->name != NULL; c++) {
int len = strlen(c->name);
@@ -1701,7 +1701,7 @@ help(struct tab *ctab, const char *s)
int columns, lines;
reply(-214, "%s", "");
- reply(0, "The following %scommands are recognized.", type);
+ reply(0, "The following %scommands are recognized.", htype);
reply(0, "(`-' = not implemented, `+' = supports options)");
columns = 76 / width;
if (columns == 0)
@@ -1740,9 +1740,9 @@ help(struct tab *ctab, const char *s)
return;
}
if (CMD_IMPLEMENTED(c))
- reply(214, "Syntax: %s%s %s", type, c->name, c->help);
+ reply(214, "Syntax: %s%s %s", htype, c->name, c->help);
else
- reply(214, "%s%-*s\t%s; not implemented.", type, width,
+ reply(214, "%s%-*s\t%s; not implemented.", htype, width,
c->name, c->help);
}
diff --git a/contrib/lukemftpd/src/ftpd.8 b/contrib/lukemftpd/src/ftpd.8
index 65f993a..5aaadf0 100644
--- a/contrib/lukemftpd/src/ftpd.8
+++ b/contrib/lukemftpd/src/ftpd.8
@@ -1,6 +1,6 @@
-.\" $NetBSD: ftpd.8,v 1.63 2000/12/18 02:32:51 lukem Exp $
+.\" $NetBSD: ftpd.8,v 1.69 2002/02/08 01:30:07 ross Exp $
.\"
-.\" Copyright (c) 1997-2000 The NetBSD Foundation, Inc.
+.\" Copyright (c) 1997-2001 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\"
.\" This code is derived from software contributed to The NetBSD Foundation
@@ -67,7 +67,7 @@
.\"
.\" @(#)ftpd.8 8.2 (Berkeley) 4/19/94
.\"
-.Dd December 18, 2000
+.Dd October 13, 2001
.Dt FTPD 8
.Os
.Sh NAME
@@ -149,7 +149,7 @@ The default is the hostname associated with the IP address that
is listening on.
This ability (with or without
.Fl h ) ,
-in conjunction with
+in conjunction with
.Fl c Ar confdir ,
is useful when configuring
.Sq virtual
@@ -257,7 +257,7 @@ style
file suitable for input into a third-party log analysis tool with a command
similar to:
.Dl "grep 'xferlog: ' /var/log/xferlog | \e"
-.Dl "\ \ \ sed -e 's/^.*xferlog: //' > wuxferlog"
+.Dl "\ \ \ sed -e 's/^.*xferlog: //' \*[Gt] wuxferlog"
.El
.Pp
The file
@@ -394,8 +394,7 @@ conventions used by
.Xr csh 1 .
This allows users to utilize the metacharacters
.Dq Li \&*?[]{}~ .
-.Sh User authentication
-.Pp
+.Ss User authentication
.Nm
authenticates users according to five rules.
.Pp
@@ -428,6 +427,10 @@ The user must have a standard shell returned by
If the user's shell field in the password database is empty, the
shell is assumed to be
.Pa /bin/sh .
+As per
+.Xr shells 5 ,
+the user's shell must be listed with full path in
+.Pa /etc/shells .
.It
If directed by the file
.Xr ftpchroot 5
@@ -491,8 +494,7 @@ then the verbose messages displayed at login and upon a
.Sy CWD
command are suppressed.
.El
-.Sh Display file escape sequences
-.Pp
+.Ss Display file escape sequences
When
.Nm
displays various files back to the client (such as
@@ -551,8 +553,7 @@ A
.Dq \&%
character.
.El
-.Sh Setting up a restricted ftp subtree
-.Pp
+.Ss Setting up a restricted ftp subtree
In order that system security is not breached, it is recommended
that the
subtrees for the
@@ -625,6 +626,7 @@ The following
directives should be used:
.Dl "modify guest off"
.Dl "umask guest 0707"
+.Dl "upload guest on"
.Pp
This will result in anonymous users being able to upload files to this
directory, but they will not be able to download them, delete them, or
@@ -661,20 +663,20 @@ login, you can copy/link
.Pa /sbin/nologin
to
.Pa /sbin/ftplogin ,
-and enter
-.Pa /sbin/ftplogin
+and enter
+.Pa /sbin/ftplogin
to
.Pa /etc/shells
to allow logging-in via
.Tn FTP
into the accounts, which must have
-.Pa /sbin/ftplogin
+.Pa /sbin/ftplogin
as login shell.
.Sh FILES
.Bl -tag -width /etc/ftpwelcome -compact
.It Pa /etc/ftpchroot
-List of normal users who should be
-.Xr chroot 2 ed.
+List of normal users whose root directory should be changed via
+.Xr chroot 2 .
.It Pa /etc/ftpd.conf
Configure file conversions and other settings.
.It Pa /etc/ftpusers
@@ -700,17 +702,17 @@ Login history database.
.Xr skey 1 ,
.Xr who 1 ,
.Xr getusershell 3 ,
-.Xr ftpd.conf 5 ,
.Xr ftpchroot 5 ,
+.Xr ftpd.conf 5 ,
.Xr ftpusers 5 ,
.Xr syslogd 8
.Sh STANDARDS
.Nm
-recognizes all commands in
-.Cm RFC 959 ,
-follows the guidelines in
+recognizes all commands in
+.Cm RFC 959 ,
+follows the guidelines in
.Cm RFC 1123 ,
-recognizes all commands in
+recognizes all commands in
.Cm RFC 2228
(although they are not supported yet),
and supports the extensions from
@@ -732,7 +734,7 @@ and
.Cm draft-ietf-ftpext-mlst-11
support was implemented in
.Nx 1.3
-and later releases by Luke Mewburn <lukem@netbsd.org>.
+and later releases by Luke Mewburn \*[Lt]lukem@netbsd.org\*[Gt].
.Sh BUGS
The server must run as the super-user to create sockets with
privileged port numbers (i.e, those less than
@@ -811,7 +813,7 @@ is running on a port greater than
.Dv IPPORT_RESERVED
and the user has logged in as a
.Sq guest
-or
+or
.Sq chroot
user.
.It
diff --git a/contrib/lukemftpd/src/ftpd.c b/contrib/lukemftpd/src/ftpd.c
index c5c2f2e..7170536 100644
--- a/contrib/lukemftpd/src/ftpd.c
+++ b/contrib/lukemftpd/src/ftpd.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ftpd.c,v 1.125 2001/04/25 01:46:26 lukem Exp $ */
+/* $NetBSD: ftpd.c,v 1.138 2002/02/11 11:45:07 lukem Exp $ */
/*
* Copyright (c) 1997-2001 The NetBSD Foundation, Inc.
@@ -527,7 +527,8 @@ sgetpwnam(const char *name)
}
static int login_attempts; /* number of failed login attempts */
-static int askpasswd; /* had user command, ask for passwd */
+static int askpasswd; /* had USER command, ask for PASSwd */
+static int permitted; /* USER permitted */
static char curname[10]; /* current USER name */
/*
@@ -544,6 +545,9 @@ static char curname[10]; /* current USER name */
void
user(const char *name)
{
+ char *class;
+
+ class = NULL;
if (logged_in) {
switch (curclass.type) {
case CLASS_GUEST:
@@ -572,6 +576,9 @@ user(const char *name)
#endif
curclass.type = CLASS_REAL;
+ askpasswd = 0;
+ permitted = 0;
+
if (strcmp(name, "ftp") == 0 || strcmp(name, "anonymous") == 0) {
/* need `pw' setup for checkaccess() and checkuser () */
if ((pw = sgetpwnam("ftp")) == NULL)
@@ -584,34 +591,106 @@ user(const char *name)
reply(331,
"Guest login ok, type your name as password.");
}
- if (!askpasswd && logging)
- syslog(LOG_NOTICE,
- "ANONYMOUS FTP LOGIN REFUSED FROM %s", remotehost);
- return;
- }
+ if (!askpasswd) {
+ if (logging)
+ syslog(LOG_NOTICE,
+ "ANONYMOUS FTP LOGIN REFUSED FROM %s",
+ remotehost);
+ end_login();
+ goto cleanup_user;
+ }
+ name = "ftp";
+ } else
+ pw = sgetpwnam(name);
- pw = sgetpwnam(name);
if (logging)
strlcpy(curname, name, sizeof(curname));
-#ifdef SKEY
- if (skey_haskey(name) == 0) {
- const char *myskey;
+ /* check user in /etc/ftpusers, and setup class */
+ permitted = checkuser(_PATH_FTPUSERS, curname, 1, 0, &class);
- myskey = skey_keyinfo(name);
- reply(331, "Password [%s] required for %s.",
- myskey ? myskey : "error getting challenge", name);
- } else
+ /* check user in /etc/ftpchroot */
+ if (checkuser(_PATH_FTPCHROOT, curname, 0, 0, NULL)) {
+ if (curclass.type == CLASS_GUEST) {
+ syslog(LOG_NOTICE,
+ "Can't change guest user to chroot class; remove entry in %s",
+ _PATH_FTPCHROOT);
+ exit(1);
+ }
+ curclass.type = CLASS_CHROOT;
+ }
+ /* determine default class */
+ if (class == NULL) {
+ switch (curclass.type) {
+ case CLASS_GUEST:
+ class = xstrdup("guest");
+ break;
+ case CLASS_CHROOT:
+ class = xstrdup("chroot");
+ break;
+ case CLASS_REAL:
+ class = xstrdup("real");
+ break;
+ default:
+ syslog(LOG_ERR, "unknown curclass.type %d; aborting",
+ curclass.type);
+ abort();
+ }
+ }
+ /* parse ftpd.conf, setting up various parameters */
+ parse_conf(class);
+ /* if not guest user, check for valid shell */
+ if (pw == NULL)
+ permitted = 0;
+ else {
+ const char *cp, *shell;
+
+ if ((shell = pw->pw_shell) == NULL || *shell == 0)
+ shell = _PATH_BSHELL;
+ while ((cp = getusershell()) != NULL)
+ if (strcmp(cp, shell) == 0)
+ break;
+ endusershell();
+ if (cp == NULL && curclass.type != CLASS_GUEST)
+ permitted = 0;
+ }
+
+ /* deny quickly (after USER not PASS) if requested */
+ if (CURCLASS_FLAGS_ISSET(denyquick) && !permitted) {
+ reply(530, "User %s may not use FTP.", curname);
+ if (logging)
+ syslog(LOG_NOTICE, "FTP LOGIN REFUSED FROM %s, %s",
+ remotehost, curname);
+ end_login();
+ goto cleanup_user;
+ }
+
+ /* if haven't asked yet (i.e, not anon), ask now */
+ if (!askpasswd) {
+ askpasswd = 1;
+#ifdef SKEY
+ if (skey_haskey(curname) == 0) {
+ const char *myskey;
+
+ myskey = skey_keyinfo(curname);
+ reply(331, "Password [ %s ] required for %s.",
+ myskey ? myskey : "error getting challenge",
+ curname);
+ } else
#endif
- reply(331, "Password required for %s.", name);
+ reply(331, "Password required for %s.", curname);
+ }
- askpasswd = 1;
+ cleanup_user:
/*
* Delay before reading passwd after first failed
* attempt to slow down passwd-guessing programs.
*/
if (login_attempts)
sleep((unsigned) login_attempts);
+
+ if (class)
+ free(class);
}
/*
@@ -619,7 +698,7 @@ user(const char *name)
* for a user. Each line is a shell-style glob followed by
* `yes' or `no'.
*
- * For backward compatability, `allow' and `deny' are synonymns
+ * For backward compatibility, `allow' and `deny' are synonymns
* for `yes' and `no', respectively.
*
* Each glob is matched against the username in turn, and the first
@@ -642,7 +721,7 @@ checkuser(const char *fname, const char *name, int def, int nofile,
{
FILE *fd;
int retval;
- char *glob, *perm, *class, *buf, *p;
+ char *word, *perm, *class, *buf, *p;
size_t len, line;
retval = def;
@@ -656,7 +735,7 @@ checkuser(const char *fname, const char *name, int def, int nofile,
(buf = fparseln(fd, &len, &line, NULL, FPARSELN_UNESCCOMM |
FPARSELN_UNESCCONT | FPARSELN_UNESCESC)) != NULL;
free(buf), buf = NULL) {
- glob = perm = class = NULL;
+ word = perm = class = NULL;
p = buf;
if (len < 1)
continue;
@@ -665,10 +744,10 @@ checkuser(const char *fname, const char *name, int def, int nofile,
if (EMPTYSTR(p))
continue;
- NEXTWORD(p, glob);
+ NEXTWORD(p, word);
NEXTWORD(p, perm);
NEXTWORD(p, class);
- if (EMPTYSTR(glob))
+ if (EMPTYSTR(word))
continue;
if (!EMPTYSTR(class)) {
if (strcasecmp(class, "all") == 0 ||
@@ -681,7 +760,7 @@ checkuser(const char *fname, const char *name, int def, int nofile,
}
/* have a host specifier */
- if ((p = strchr(glob, '@')) != NULL) {
+ if ((p = strchr(word, '@')) != NULL) {
unsigned long net, mask, addr;
int bits;
@@ -697,15 +776,17 @@ checkuser(const char *fname, const char *name, int def, int nofile,
continue;
/* check against hostname glob */
- } else if (fnmatch(p, remotehost, 0) != 0)
+ } else if (fnmatch(p, remotehost, FNM_CASEFOLD) != 0)
continue;
}
/* have a group specifier */
- if ((p = strchr(glob, ':')) != NULL) {
+ if ((p = strchr(word, ':')) != NULL) {
gid_t *groups, *ng;
int gsize, i, found;
+ if (pw == NULL)
+ continue; /* no match for unknown user */
*p++ = '\0';
groups = NULL;
gsize = 16;
@@ -734,7 +815,7 @@ checkuser(const char *fname, const char *name, int def, int nofile,
}
/* check against username glob */
- if (fnmatch(glob, name, 0) != 0)
+ if (fnmatch(word, name, 0) != 0)
continue;
if (perm != NULL &&
@@ -791,6 +872,8 @@ end_login(void)
memset(pw->pw_passwd, 0, strlen(pw->pw_passwd));
pw = NULL;
logged_in = 0;
+ askpasswd = 0;
+ permitted = 0;
quietmessages = 0;
gidcount = 0;
curclass.type = CLASS_REAL;
@@ -801,12 +884,10 @@ void
pass(const char *passwd)
{
int rval;
- const char *cp, *shell;
- char *class, root[MAXPATHLEN];
+ char root[MAXPATHLEN];
char *p;
int len;
- class = NULL;
if (logged_in || askpasswd == 0) {
reply(503, "Login with USER first.");
return;
@@ -877,22 +958,8 @@ pass(const char *passwd)
}
}
- /* password ok; see if anything else prevents login */
- if (! checkuser(_PATH_FTPUSERS, pw->pw_name, 1, 0, &class)) {
- reply(530, "User %s may not use FTP.", pw->pw_name);
- if (logging)
- syslog(LOG_NOTICE, "FTP LOGIN REFUSED FROM %s, %s",
- remotehost, pw->pw_name);
- goto bad;
- }
- /* if not guest user, check for valid shell */
- if ((shell = pw->pw_shell) == NULL || *shell == 0)
- shell = _PATH_BSHELL;
- while ((cp = getusershell()) != NULL)
- if (strcmp(cp, shell) == 0)
- break;
- endusershell();
- if (cp == NULL && curclass.type != CLASS_GUEST) {
+ /* password ok; check if anything else prevents login */
+ if (! permitted) {
reply(530, "User %s may not use FTP.", pw->pw_name);
if (logging)
syslog(LOG_NOTICE, "FTP LOGIN REFUSED FROM %s, %s",
@@ -927,36 +994,6 @@ pass(const char *passwd)
logged_in = 1;
- /* check user in /etc/ftpchroot */
- if (checkuser(_PATH_FTPCHROOT, pw->pw_name, 0, 0, NULL)) {
- if (curclass.type == CLASS_GUEST) {
- syslog(LOG_NOTICE,
- "Can't change guest user to chroot class; remove entry in %s",
- _PATH_FTPCHROOT);
- exit(1);
- }
- curclass.type = CLASS_CHROOT;
- }
- if (class == NULL) {
- switch (curclass.type) {
- case CLASS_GUEST:
- class = xstrdup("guest");
- break;
- case CLASS_CHROOT:
- class = xstrdup("chroot");
- break;
- case CLASS_REAL:
- class = xstrdup("real");
- break;
- default:
- syslog(LOG_ERR, "unknown curclass.type %d; aborting",
- curclass.type);
- abort();
- }
- }
-
- /* parse ftpd.conf, setting up various parameters */
- parse_conf(class);
connections = 1;
if (dopidfile)
count_users();
@@ -1100,7 +1137,8 @@ pass(const char *passwd)
* Display a login message, if it exists.
* N.B. reply(230,) must follow the message.
*/
- (void)display_file(conffilename(curclass.motd), 230);
+ if (! EMPTYSTR(curclass.motd))
+ (void)display_file(conffilename(curclass.motd), 230);
show_chdir_messages(230);
if (curclass.type == CLASS_GUEST) {
char *p;
@@ -1108,9 +1146,7 @@ pass(const char *passwd)
reply(230, "Guest login ok, access restrictions apply.");
#if HAVE_SETPROCTITLE
snprintf(proctitle, sizeof(proctitle),
- "%s: anonymous/%.*s", remotehost,
- (int) (sizeof(proctitle) - sizeof(remotehost) -
- sizeof(": anonymous/")), passwd);
+ "%s: anonymous/%s", remotehost, passwd);
setproctitle("%s", proctitle);
#endif /* HAVE_SETPROCTITLE */
if (logging)
@@ -1137,15 +1173,11 @@ pass(const char *passwd)
curclass.classname, CURCLASSTYPE);
}
(void) umask(curclass.umask);
- goto cleanuppass;
+ return;
bad:
/* Forget all about it... */
end_login();
-
- cleanuppass:
- if (class)
- free(class);
}
void
@@ -1157,12 +1189,14 @@ retrieve(char *argv[], const char *name)
int log, sendrv, closerv, stderrfd, isconversion, isdata, isls;
struct timeval start, finish, td, *tdp;
const char *dispname;
+ char *error;
sendrv = closerv = stderrfd = -1;
isconversion = isdata = isls = log = 0;
tdp = NULL;
dispname = name;
fin = dout = NULL;
+ error = NULL;
if (argv == NULL) { /* if not running a command ... */
log = 1;
isdata = 1;
@@ -1206,7 +1240,8 @@ retrieve(char *argv[], const char *name)
byte_count = -1;
if (argv == NULL
&& (fstat(fileno(fin), &st) < 0 || !S_ISREG(st.st_mode))) {
- reply(550, "%s: not a plain file.", dispname);
+ error = "Not a plain file";
+ reply(550, "%s: %s.", dispname, error);
goto done;
}
if (restart_point) {
@@ -1216,6 +1251,7 @@ retrieve(char *argv[], const char *name)
for (i = 0; i < restart_point; i++) {
if ((c=getc(fin)) == EOF) {
+ error = strerror(errno);
perror_reply(550, dispname);
goto done;
}
@@ -1223,6 +1259,7 @@ retrieve(char *argv[], const char *name)
i++;
}
} else if (lseek(fileno(fin), restart_point, SEEK_SET) < 0) {
+ error = strerror(errno);
perror_reply(550, dispname);
goto done;
}
@@ -1234,16 +1271,15 @@ retrieve(char *argv[], const char *name)
(void)gettimeofday(&start, NULL);
sendrv = send_data(fin, dout, st.st_blksize, isdata);
(void)gettimeofday(&finish, NULL);
- (void) fclose(dout); /* close now to affect timing stats */
- dout = NULL;
+ closedataconn(dout); /* close now to affect timing stats */
timersub(&finish, &start, &td);
tdp = &td;
done:
if (log)
- logxfer("get", byte_count, name, NULL, tdp, NULL);
+ logxfer("get", byte_count, name, NULL, tdp, error);
closerv = (*closefunc)(fin);
if (sendrv == 0) {
- FILE *err;
+ FILE *errf;
struct stat sb;
if (!isls && argv != NULL && closerv != 0) {
@@ -1257,24 +1293,23 @@ retrieve(char *argv[], const char *name)
}
if (!isls && argv != NULL && stderrfd != -1 &&
(fstat(stderrfd, &sb) == 0) && sb.st_size > 0 &&
- ((err = fdopen(stderrfd, "r")) != NULL)) {
+ ((errf = fdopen(stderrfd, "r")) != NULL)) {
char *cp, line[LINE_MAX];
reply(-226, "Command error messages:");
- rewind(err);
- while (fgets(line, sizeof(line), err) != NULL) {
+ rewind(errf);
+ while (fgets(line, sizeof(line), errf) != NULL) {
if ((cp = strchr(line, '\n')) != NULL)
*cp = '\0';
reply(0, " %s", line);
}
(void) fflush(stdout);
- (void) fclose(err);
+ (void) fclose(errf);
/* a reply(226,) must follow */
}
reply(226, "Transfer complete.");
}
cleanupretrieve:
- closedataconn(dout);
if (stderrfd != -1)
(void)close(stderrfd);
if (isconversion)
@@ -1282,16 +1317,17 @@ retrieve(char *argv[], const char *name)
}
void
-store(const char *name, const char *mode, int unique)
+store(const char *name, const char *fmode, int unique)
{
FILE *fout, *din;
struct stat st;
int (*closefunc)(FILE *);
struct timeval start, finish, td, *tdp;
- char *desc;
+ char *desc, *error;
din = NULL;
- desc = (*mode == 'w') ? "put" : "append";
+ desc = (*fmode == 'w') ? "put" : "append";
+ error = NULL;
if (unique && stat(name, &st) == 0 &&
(name = gunique(name)) == NULL) {
logxfer(desc, -1, name, NULL, NULL,
@@ -1300,8 +1336,8 @@ store(const char *name, const char *mode, int unique)
}
if (restart_point)
- mode = "r+";
- fout = fopen(name, mode);
+ fmode = "r+";
+ fout = fopen(name, fmode);
closefunc = fclose;
tdp = NULL;
if (fout == NULL) {
@@ -1317,6 +1353,7 @@ store(const char *name, const char *mode, int unique)
for (i = 0; i < restart_point; i++) {
if ((c=getc(fout)) == EOF) {
+ error = strerror(errno);
perror_reply(550, name);
goto done;
}
@@ -1329,10 +1366,12 @@ store(const char *name, const char *mode, int unique)
* writing.
*/
if (fseek(fout, 0L, SEEK_CUR) < 0) {
+ error = strerror(errno);
perror_reply(550, name);
goto done;
}
} else if (lseek(fileno(fout), restart_point, SEEK_SET) < 0) {
+ error = strerror(errno);
perror_reply(550, name);
goto done;
}
@@ -1349,26 +1388,25 @@ store(const char *name, const char *mode, int unique)
reply(226, "Transfer complete.");
}
(void)gettimeofday(&finish, NULL);
- (void) fclose(din); /* close now to affect timing stats */
- din = NULL;
+ closedataconn(din); /* close now to affect timing stats */
timersub(&finish, &start, &td);
tdp = &td;
done:
- logxfer(desc, byte_count, name, NULL, tdp, NULL);
+ logxfer(desc, byte_count, name, NULL, tdp, error);
(*closefunc)(fout);
cleanupstore:
- closedataconn(din);
+ ;
}
static FILE *
-getdatasock(const char *mode)
+getdatasock(const char *fmode)
{
int on, s, t, tries;
in_port_t port;
on = 1;
if (data >= 0)
- return (fdopen(data, mode));
+ return (fdopen(data, fmode));
if (! dropprivs)
(void) seteuid((uid_t)0);
s = socket(ctrl_addr.su_family, SOCK_STREAM, 0);
@@ -1415,7 +1453,7 @@ getdatasock(const char *mode)
syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
}
#endif
- return (fdopen(s, mode));
+ return (fdopen(s, fmode));
bad:
/* Return the real value of errno (close may change it) */
t = errno;
@@ -1427,7 +1465,7 @@ getdatasock(const char *mode)
}
FILE *
-dataconn(const char *name, off_t size, const char *mode)
+dataconn(const char *name, off_t size, const char *fmode)
{
char sizebuf[32];
FILE *file;
@@ -1474,18 +1512,18 @@ dataconn(const char *name, off_t size, const char *mode)
#endif
reply(150, "Opening %s mode data connection for '%s'%s.",
type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
- return (fdopen(pdata, mode));
+ return (fdopen(pdata, fmode));
}
if (data >= 0) {
reply(125, "Using existing data connection for '%s'%s.",
name, sizebuf);
usedefault = 1;
- return (fdopen(data, mode));
+ return (fdopen(data, fmode));
}
if (usedefault)
data_dest = his_addr;
usedefault = 1;
- file = getdatasock(mode);
+ file = getdatasock(fmode);
if (file == NULL) {
char hbuf[NI_MAXHOST];
char pbuf[NI_MAXSERV];
@@ -1520,8 +1558,9 @@ void
closedataconn(FILE *fd)
{
- if (fd != NULL)
- (void)fclose(fd);
+ if (fd == NULL)
+ return;
+ (void)fclose(fd);
data = -1;
if (pdata >= 0)
(void)close(pdata);
@@ -1920,7 +1959,7 @@ statcmd(void)
/* LPSV/LPRT */
{
- int alen, af, i;
+ int alen, i;
alen = 0;
switch (su->su_family) {
@@ -2002,7 +2041,7 @@ statcmd(void)
(LLT)otb, PLURAL(otb),
(LLT)total_xfers, PLURAL(total_xfers));
- if (logged_in) {
+ if (logged_in && !CURCLASS_FLAGS_ISSET(private)) {
struct ftpconv *cp;
reply(0, "%s", "");
@@ -2023,9 +2062,11 @@ statcmd(void)
reply(0, "Maximum connections: %d", curclass.limit);
if (curclass.limitfile)
reply(0, "Connection limit exceeded message file: %s",
- curclass.limitfile);
+ conffilename(curclass.limitfile));
if (! EMPTYSTR(curclass.chroot))
reply(0, "Chroot format: %s", curclass.chroot);
+ reply(0, "Deny bad ftpusers(5) quickly: %sabled",
+ CURCLASS_FLAGS_ISSET(denyquick) ? "en" : "dis");
if (! EMPTYSTR(curclass.homedir))
reply(0, "Homedir format: %s", curclass.homedir);
if (curclass.maxfilesize == -1)
@@ -2034,7 +2075,7 @@ statcmd(void)
reply(0, "Maximum file size: " LLF,
(LLT)curclass.maxfilesize);
if (! EMPTYSTR(curclass.motd))
- reply(0, "MotD file: %s", curclass.motd);
+ reply(0, "MotD file: %s", conffilename(curclass.motd));
reply(0,
"Modify commands (CHMOD, DELE, MKD, RMD, RNFR, UMASK): %sabled",
CURCLASS_FLAGS_ISSET(modify) ? "en" : "dis");
@@ -2113,13 +2154,16 @@ reply(int n, const char *fmt, ...)
else
cprintf(stdout, "%d ", n);
b = vprintf(fmt, ap);
+ va_end(ap);
total_bytes += b;
total_bytes_out += b;
cprintf(stdout, "\r\n");
(void)fflush(stdout);
if (debug) {
syslog(LOG_DEBUG, "<--- %d%c", abs(n), (n < 0) ? '-' : ' ');
+ va_start(ap, fmt);
vsyslog(LOG_DEBUG, fmt, ap);
+ va_end(ap);
}
}
@@ -2624,7 +2668,7 @@ send_file_list(const char *whichf)
DIR *dirp = NULL;
struct dirent *dir;
FILE *dout = NULL;
- char **dirlist, *dirname, *p;
+ char **dirlist, *dirname, *notglob, *p;
int simple = 0;
int freeglob = 0;
glob_t gl;
@@ -2652,8 +2696,8 @@ send_file_list(const char *whichf)
}
dirlist = gl.gl_pathv;
} else {
- p = xstrdup(whichf);
- onefile[0] = p;
+ notglob = xstrdup(whichf);
+ onefile[0] = notglob;
dirlist = onefile;
simple = 1;
}
@@ -2729,8 +2773,6 @@ send_file_list(const char *whichf)
*/
if (simple || (stat(nbuf, &st) == 0 &&
S_ISREG(st.st_mode))) {
- char *p;
-
if (dout == NULL) {
dout = dataconn("file list", (off_t)-1,
"w");
@@ -2761,8 +2803,8 @@ send_file_list(const char *whichf)
out:
total_xfers++;
total_xfers_out++;
- if (p)
- free(p);
+ if (notglob)
+ free(notglob);
if (freeglob)
globfree(&gl);
}
@@ -2788,7 +2830,8 @@ conffilename(const char *s)
* if elapsed != NULL, append "in xxx.yyy seconds"
* if error != NULL, append ": " + error
*
- * if doxferlog != 0, syslog a wu-ftpd style xferlog entry
+ * if doxferlog != 0, bytes != -1, and command is "get", "put",
+ * or "append", syslog a wu-ftpd style xferlog entry
*/
void
logxfer(const char *command, off_t bytes, const char *file1, const char *file2,
@@ -2835,7 +2878,7 @@ logxfer(const char *command, off_t bytes, const char *file1, const char *file2,
/*
* syslog wu-ftpd style log entry, prefixed with "xferlog: "
*/
- if (!doxferlog)
+ if (!doxferlog || bytes == -1)
return;
if (strcmp(command, "get") == 0)
@@ -2863,7 +2906,7 @@ logxfer(const char *command, off_t bytes, const char *file1, const char *file2,
#endif
elapsed == NULL ? 0 : elapsed->tv_sec + (elapsed->tv_usec > 0),
remotehost,
- bytes == (off_t)-1 ? 0 : (LLT) bytes,
+ (LLT) bytes,
r1,
type == TYPE_A ? 'a' : 'b',
"_", /* XXX: take conversions into account? */
@@ -2883,7 +2926,7 @@ logxfer(const char *command, off_t bytes, const char *file1, const char *file2,
* Returns 2 if password expired, 1 if otherwise failed, 0 if ok
*/
int
-checkpassword(const struct passwd *pw, const char *password)
+checkpassword(const struct passwd *pwent, const char *password)
{
char *orig, *new;
time_t expire;
@@ -2892,17 +2935,17 @@ checkpassword(const struct passwd *pw, const char *password)
#endif
expire = 0;
- if (pw == NULL)
+ if (pwent == NULL)
return 1;
#if HAVE_GETSPNAM
- if ((spw = getspnam(pw->pw_name)) == NULL)
+ if ((spw = getspnam(pwent->pw_name)) == NULL)
return 1;
orig = spw->sp_pwdp;
#else
- orig = pw->pw_passwd; /* save existing password */
+ orig = pwent->pw_passwd; /* save existing password */
#if HAVE_PW_EXPIRE
- expire = pw->pw_expire;
+ expire = pwent->pw_expire;
#endif
#endif /* HAVE_GETSPNAM */
@@ -2942,6 +2985,7 @@ cprintf(FILE *fd, const char *fmt, ...)
va_start(ap, fmt);
b = vfprintf(fd, fmt, ap);
+ va_end(ap);
total_bytes += b;
total_bytes_out += b;
}
diff --git a/contrib/lukemftpd/src/ftpd.conf.5 b/contrib/lukemftpd/src/ftpd.conf.5
index 0c7dc68..df3dbcb 100644
--- a/contrib/lukemftpd/src/ftpd.conf.5
+++ b/contrib/lukemftpd/src/ftpd.conf.5
@@ -1,6 +1,6 @@
-.\" $NetBSD: ftpd.conf.5,v 1.15 2000/12/18 02:32:51 lukem Exp $
+.\" $NetBSD: ftpd.conf.5,v 1.19 2002/01/15 02:20:50 wiz Exp $
.\"
-.\" Copyright (c) 1997-2000 The NetBSD Foundation, Inc.
+.\" Copyright (c) 1997-2001 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\"
.\" This code is derived from software contributed to The NetBSD Foundation
@@ -34,7 +34,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd December 18, 2000
+.Dd December 5, 2001
.Dt FTPD.CONF 5
.Os
.Sh NAME
@@ -114,11 +114,15 @@ The
.Xr ftpd 8
.Sy STAT
command will return the class settings for the current user as defined by
-.Nm "" .
+.Nm "" ,
+unless the
+.Sy private
+directive is set for the class.
.Pp
Each configuration line may be one of:
.Bl -tag -width 4n
.It Sy advertise Ar class Ar host
+.It Sy advertize Ar class Ar host
Set the address to advertise in the response to the
.Sy PASV
and
@@ -209,7 +213,7 @@ is performed.
Set the class type of
.Ar class
to
-.Ar type
+.Ar type
(see above).
.It Xo Sy conversion Ar class
.Ar suffix Op Ar "type disable command"
@@ -255,6 +259,33 @@ are replaced with the requested file (sans
.Pp
Conversion directives specified later in the file override earlier
conversions with the same suffix.
+.It Sy denyquick Ar class Op Sy off
+Enforce
+.Xr ftpusers 5
+rules after the
+.Sy USER
+command is received, rather than after the
+.Sy PASS
+command is received.
+Whilst enabling this feature may allow information leakage about
+available accounts (for example, if you allow some users of a
+.Sy REAL
+or
+.Sy CHROOT
+class but not others), it is useful in preventing a denied user
+(such as
+.Sq root )
+from entering their password across an insecure connection.
+This option is
+.Em strongly
+recommended for servers which run an anonymous-only service.
+If
+.Ar class
+is
+.Dq none
+or
+.Sy off
+is given, disable this feature, otherwise enable it.
.It Sy display Ar class Op Ar file
If
.Ar file
@@ -401,7 +432,7 @@ is
.Dq none
or
.Sy off
-is given, disallow passive
+is given, prevent passive
.Sy ( PASV ,
.Sy LPSV ,
and
@@ -414,13 +445,24 @@ Set the range of port number which will be used for the passive data port.
must be greater than
.Ar min ,
and both numbers must be be between
-.Dv IPPORT_RESERVED
+.Dv IPPORT_RESERVED
(1024) and 65535.
If
.Ar class
is
.Dq none
or no arguments are given, disable this.
+.It Sy private Ar class Op Sy off
+If
+.Ar class
+is
+.Dq none
+or
+.Sy off
+is given, do not display class information in the output of the
+.Sy STAT
+command.
+Otherwise, display the information.
.It Sy rateget Ar class Ar rate
Set the maximum get
.Pq Sy RETR
@@ -459,7 +501,7 @@ Set the maximum put
transfer rate throttle for
.Ar class
to
-.Ar rate
+.Ar rate
bytes per second,
which is parsed as per
.Sy rateget Ar rate .
@@ -521,7 +563,7 @@ is
.Dq none
or
.Ar umaskval
-is not specified, set to the default of
+is not specified, set to the default of
.Li 027 .
.It Sy upload Ar class Op Sy off
If
diff --git a/contrib/lukemftpd/src/ftpusers.5 b/contrib/lukemftpd/src/ftpusers.5
index 85f500f..3e87688 100644
--- a/contrib/lukemftpd/src/ftpusers.5
+++ b/contrib/lukemftpd/src/ftpusers.5
@@ -1,4 +1,4 @@
-.\" $NetBSD: ftpusers.5,v 1.10 2001/04/25 01:46:26 lukem Exp $
+.\" $NetBSD: ftpusers.5,v 1.13 2001/12/01 16:24:24 wiz Exp $
.\"
.\" Copyright (c) 1997-2001 The NetBSD Foundation, Inc.
.\" All rights reserved.
@@ -87,7 +87,9 @@ either a CIDR address (refer to
to match against the remote address
(e.g,
.Sq 1.2.3.4/24 ) ,
-or a glob to match against the remote hostname
+or an
+.Xr fnmatch 3
+glob to match against the remote hostname
(e.g,
.Sq *.netbsd.org ) .
.It Sy directive
@@ -127,7 +129,7 @@ If neither of the above is true.
.Pp
No further comparisons are attempted after the first successful match.
If no match is found, the user is granted access.
-This syntax is backward-compatable with the old syntax.
+This syntax is backward-compatible with the old syntax.
.Pp
If a user requests a guest login, the
.Xr ftpd 8
@@ -163,12 +165,13 @@ except that the
argument is ignored.
If there's a positive match, the session's root directory is changed.
No further comparisons are attempted after the first successful match.
-This syntax is backward-compatable with the old syntax.
+This syntax is backward-compatible with the old syntax.
.Sh FILES
-.Bl -tag -width /etc/ftpchroot -compact
+.Bl -tag -width /usr/share/examples/ftpd/ftpusers -compact
.It Pa /etc/ftpchroot
-List of normal users who should be
-.Xr chroot 2 ed.
+List of normal users who should have their ftp session's root directory
+changed by using
+.Xr chroot 2 .
.It Pa /etc/ftpusers
This file.
.It Pa /usr/share/examples/ftpd/ftpusers
diff --git a/contrib/lukemftpd/src/popen.c b/contrib/lukemftpd/src/popen.c
index 7e8d036..95123e7 100644
--- a/contrib/lukemftpd/src/popen.c
+++ b/contrib/lukemftpd/src/popen.c
@@ -1,4 +1,4 @@
-/* $NetBSD: popen.c,v 1.26 2001/04/25 01:46:26 lukem Exp $ */
+/* $NetBSD: popen.c,v 1.27 2001/12/01 10:25:30 lukem Exp $ */
/*-
* Copyright (c) 1999-2001 The NetBSD Foundation, Inc.
@@ -91,7 +91,7 @@ static int fds;
extern int ls_main(int, char *[]);
FILE *
-ftpd_popen(char *argv[], const char *type, int stderrfd)
+ftpd_popen(char *argv[], const char *ptype, int stderrfd)
{
FILE *iop;
int argc, pdes[2], pid, isls;
@@ -100,7 +100,7 @@ ftpd_popen(char *argv[], const char *type, int stderrfd)
iop = NULL;
isls = 0;
- if ((*type != 'r' && *type != 'w') || type[1])
+ if ((*ptype != 'r' && *ptype != 'w') || ptype[1])
return (NULL);
if (!pids) {
@@ -158,7 +158,7 @@ ftpd_popen(char *argv[], const char *type, int stderrfd)
goto pfree;
/* NOTREACHED */
case 0: /* child */
- if (*type == 'r') {
+ if (*ptype == 'r') {
if (pdes[1] != STDOUT_FILENO) {
dup2(pdes[1], STDOUT_FILENO);
(void)close(pdes[1]);
@@ -190,11 +190,11 @@ ftpd_popen(char *argv[], const char *type, int stderrfd)
_exit(1);
}
/* parent; assume fdopen can't fail... */
- if (*type == 'r') {
- iop = fdopen(pdes[0], type);
+ if (*ptype == 'r') {
+ iop = fdopen(pdes[0], ptype);
(void)close(pdes[1]);
} else {
- iop = fdopen(pdes[1], type);
+ iop = fdopen(pdes[1], ptype);
(void)close(pdes[0]);
}
pids[fileno(iop)] = pid;
diff --git a/contrib/lukemftpd/src/version.h b/contrib/lukemftpd/src/version.h
index 1a075c7..e741257 100644
--- a/contrib/lukemftpd/src/version.h
+++ b/contrib/lukemftpd/src/version.h
@@ -1,4 +1,4 @@
-/* $NetBSD: version.h,v 1.32 2001/04/25 01:46:26 lukem Exp $ */
+/* $NetBSD: version.h,v 1.42 2002/02/13 15:15:23 lukem Exp $ */
/*-
* Copyright (c) 1999-2001 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -36,5 +36,5 @@
*/
#ifndef FTPD_VERSION
-#define FTPD_VERSION "NetBSD-ftpd 20010425"
+#define FTPD_VERSION "NetBSD-ftpd 20020214"
#endif
diff --git a/contrib/lukemftpd/todo b/contrib/lukemftpd/todo
index 83ca631..7bb2012 100644
--- a/contrib/lukemftpd/todo
+++ b/contrib/lukemftpd/todo
@@ -3,6 +3,10 @@ autoconf checks:
- replace getopt() if optreset (BSD) or getoptreset() (irix)
is not available?
- IF_NAMESIZE not available on darwin
+ - inet_net_pton() ipv6 support
+ - FNM_CASEFOLD for fnmatch(3)
+
+support lfcompile(5) (large files) on solaris
fix internalls (actually fts) on IRIX
OpenPOWER on IntegriCloud