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:
commit
1719980ed9
@ -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 ~
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
6
contrib/lukemftpd/configure
vendored
6
contrib/lukemftpd/configure
vendored
@ -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]
|
||||
|
@ -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, [\
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user