This commit was generated by cvs2svn to compensate for changes in r92282,

which included commits to RCS files with non-trunk default branches.
This commit is contained in:
David E. O'Brien 2002-03-14 19:25:32 +00:00
commit 1719980ed9
19 changed files with 420 additions and 239 deletions

View File

@ -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 ~

View File

@ -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.

View File

@ -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.

View File

@ -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

View File

@ -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>

View File

@ -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]

View File

@ -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, [\

View File

@ -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"

View File

@ -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

View File

@ -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));

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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));
/* check user in /etc/ftpusers, and setup class */
permitted = checkuser(_PATH_FTPUSERS, curname, 1, 0, &class);
/* 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(name) == 0) {
const char *myskey;
if (skey_haskey(curname) == 0) {
const char *myskey;
myskey = skey_keyinfo(name);
reply(331, "Password [%s] required for %s.",
myskey ? myskey : "error getting challenge", name);
} else
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;
}

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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