Import of LukeM's ftpd taken from the NetBSD CVS repo on 5-Jan-2003.
The "portable" release of this is just lagging way too far behind what is in NetBSD's base.
This commit is contained in:
parent
3d982f73f3
commit
33bc027019
46
contrib/lukemftpd/src/Makefile
Normal file
46
contrib/lukemftpd/src/Makefile
Normal file
@ -0,0 +1,46 @@
|
||||
# $NetBSD: Makefile,v 1.49 2002/08/22 00:09:38 christos Exp $
|
||||
# @(#)Makefile 8.2 (Berkeley) 4/4/94
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
PROG= ftpd
|
||||
SRCS= cmds.c conf.c ftpd.c ftpcmd.y logutmp.c logwtmp.c popen.c
|
||||
CPPFLAGS+=-I${.CURDIR} -DSUPPORT_UTMP -DSUPPORT_UTMPX
|
||||
DPADD+= ${LIBCRYPT} ${LIBUTIL}
|
||||
LDADD+= -lcrypt -lutil
|
||||
MAN= ftpd.conf.5 ftpusers.5 ftpd.8
|
||||
MLINKS= ftpusers.5 ftpchroot.5
|
||||
|
||||
# for `internal' ls
|
||||
SRCS+= ls.c cmp.c print.c stat_flags.c util.c
|
||||
.PATH: ${NETBSDSRCDIR}/bin/ls
|
||||
|
||||
CPPFLAGS+=-DINET6
|
||||
.include <bsd.own.mk>
|
||||
|
||||
WARNS=2
|
||||
|
||||
.if (${USE_SKEY} != "no")
|
||||
CPPFLAGS+=-DSKEY
|
||||
DPADD+= ${LIBSKEY}
|
||||
LDADD+= -lskey
|
||||
.endif
|
||||
|
||||
ftpd.o ftpcmd.o: version.h
|
||||
|
||||
# XXX Kerberos support is broken right now.
|
||||
#.PATH: ${NETBSDSRCDIR}/usr.bin/login
|
||||
|
||||
#.ifdef KERBEROS5
|
||||
#SRCS+= k5login.c
|
||||
#CPPFLAGS+=-DKERBEROS5
|
||||
#DPADD+= ${LIBKRB5} ${LIBK5CRYPTO} ${LIBCOM_ERR}
|
||||
#LDADD+= -lkrb5 -lk5crypto -lcom_err
|
||||
#.else
|
||||
#SRCS+= klogin.c
|
||||
#CPPFLAGS+=-DKERBEROS
|
||||
#DPADD+= ${LIBKRB} ${LIBDES} ${LIBCOM_ERR}
|
||||
#LDADD+= -lkrb -kdes -lcom_err
|
||||
#.endif
|
||||
|
||||
.include <bsd.prog.mk>
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: cmds.c,v 1.16 2002/02/13 15:15:23 lukem Exp $ */
|
||||
/* $NetBSD: cmds.c,v 1.18 2002/10/12 08:35:16 darrenr Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1999-2001 The NetBSD Foundation, Inc.
|
||||
@ -98,7 +98,30 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "lukemftpd.h"
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: cmds.c,v 1.18 2002/10/12 08:35:16 darrenr Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <arpa/ftp.h>
|
||||
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <setjmp.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <tzfile.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#ifdef KERBEROS5
|
||||
#include <krb5/krb5.h>
|
||||
#endif
|
||||
|
||||
#include "extern.h"
|
||||
|
||||
@ -307,11 +330,11 @@ opts(const char *command)
|
||||
*ep++ = '\0';
|
||||
c = lookup(cmdtab, command);
|
||||
if (c == NULL) {
|
||||
reply(502, "Unknown command %s.", command);
|
||||
reply(502, "Unknown command '%s'.", command);
|
||||
return;
|
||||
}
|
||||
if (! CMD_IMPLEMENTED(c)) {
|
||||
reply(501, "%s command not implemented.", c->name);
|
||||
reply(502, "%s command not implemented.", c->name);
|
||||
return;
|
||||
}
|
||||
if (! CMD_HAS_OPTIONS(c)) {
|
||||
@ -484,12 +507,14 @@ statfilecmd(const char *filename)
|
||||
{
|
||||
FILE *fin;
|
||||
int c;
|
||||
int atstart;
|
||||
char *argv[] = { INTERNAL_LS, "-lgA", "", NULL };
|
||||
|
||||
argv[2] = (char *)filename;
|
||||
fin = ftpd_popen(argv, "r", STDOUT_FILENO);
|
||||
reply(-211, "status of %s:", filename);
|
||||
/* XXX: use fgetln() or fparseln() here? */
|
||||
atstart = 1;
|
||||
while ((c = getc(fin)) != EOF) {
|
||||
if (c == '\n') {
|
||||
if (ferror(stdout)){
|
||||
@ -505,7 +530,10 @@ statfilecmd(const char *filename)
|
||||
}
|
||||
CPUTC('\r', stdout);
|
||||
}
|
||||
if (atstart && isdigit(c))
|
||||
CPUTC(' ', stdout);
|
||||
CPUTC(c, stdout);
|
||||
atstart = (c == '\n');
|
||||
}
|
||||
(void) ftpd_pclose(fin);
|
||||
reply(211, "End of Status");
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: conf.c,v 1.46 2001/12/04 13:54:12 lukem Exp $ */
|
||||
/* $NetBSD: conf.c,v 1.50 2002/11/16 03:10:34 itojun Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997-2001 The NetBSD Foundation, Inc.
|
||||
@ -36,7 +36,35 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "lukemftpd.h"
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: conf.c,v 1.50 2002/11/16 03:10:34 itojun Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <glob.h>
|
||||
#include <netdb.h>
|
||||
#include <setjmp.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stringlist.h>
|
||||
#include <syslog.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <util.h>
|
||||
|
||||
#ifdef KERBEROS5
|
||||
#include <krb5/krb5.h>
|
||||
#endif
|
||||
|
||||
#include "extern.h"
|
||||
#include "pathnames.h"
|
||||
@ -91,6 +119,11 @@ init_curclass(void)
|
||||
curclass.timeout = DEFAULT_TIMEOUT;
|
||||
/* curclass.type is set elsewhere */
|
||||
curclass.umask = DEFAULT_UMASK;
|
||||
curclass.mmapsize = 0;
|
||||
curclass.readsize = 0;
|
||||
curclass.writesize = 0;
|
||||
curclass.sendbufsize = 0;
|
||||
curclass.sendlowat = 0;
|
||||
|
||||
CURCLASS_FLAGS_SET(checkportcmd);
|
||||
CURCLASS_FLAGS_CLR(denyquick);
|
||||
@ -113,11 +146,10 @@ parse_conf(const char *findclass)
|
||||
size_t len;
|
||||
LLT llval;
|
||||
int none, match;
|
||||
char *endp;
|
||||
char *endp, errbuf[100];
|
||||
char *class, *word, *arg, *template;
|
||||
const char *infile;
|
||||
size_t line;
|
||||
unsigned int timeout;
|
||||
struct ftpconv *conv, *cnext;
|
||||
|
||||
init_curclass();
|
||||
@ -160,24 +192,37 @@ parse_conf(const char *findclass)
|
||||
strcasecmp(class, "all") == 0) )
|
||||
continue;
|
||||
|
||||
#define CONF_FLAG(x) \
|
||||
#define CONF_FLAG(Field) \
|
||||
do { \
|
||||
if (none || \
|
||||
(!EMPTYSTR(arg) && strcasecmp(arg, "off") == 0)) \
|
||||
CURCLASS_FLAGS_CLR(x); \
|
||||
CURCLASS_FLAGS_CLR(Field); \
|
||||
else \
|
||||
CURCLASS_FLAGS_SET(x); \
|
||||
CURCLASS_FLAGS_SET(Field); \
|
||||
} while (0)
|
||||
|
||||
#define CONF_STRING(x) \
|
||||
#define CONF_STRING(Field) \
|
||||
do { \
|
||||
if (none || EMPTYSTR(arg)) \
|
||||
arg = NULL; \
|
||||
else \
|
||||
arg = xstrdup(arg); \
|
||||
REASSIGN(curclass.x, arg); \
|
||||
REASSIGN(curclass.Field, arg); \
|
||||
} while (0)
|
||||
|
||||
#define CONF_LL(Field,Arg,Min,Max) \
|
||||
do { \
|
||||
if (none || EMPTYSTR(Arg)) \
|
||||
goto nextline; \
|
||||
llval = strsuftollx(#Field, Arg, Min, Max, \
|
||||
errbuf, sizeof(errbuf)); \
|
||||
if (errbuf[0]) { \
|
||||
syslog(LOG_WARNING, "%s line %d: %s", \
|
||||
infile, (int)line, errbuf); \
|
||||
goto nextline; \
|
||||
} \
|
||||
curclass.Field = llval; \
|
||||
} while(0)
|
||||
|
||||
if (0) {
|
||||
/* no-op */
|
||||
@ -314,61 +359,40 @@ parse_conf(const char *findclass)
|
||||
CONF_STRING(homedir);
|
||||
|
||||
} else if (strcasecmp(word, "limit") == 0) {
|
||||
int limit;
|
||||
|
||||
curclass.limit = DEFAULT_LIMIT;
|
||||
REASSIGN(curclass.limitfile, NULL);
|
||||
if (none || EMPTYSTR(arg))
|
||||
continue;
|
||||
limit = (int)strtol(arg, &endp, 10);
|
||||
if (*endp != 0) {
|
||||
syslog(LOG_WARNING,
|
||||
"%s line %d: invalid limit %s",
|
||||
infile, (int)line, arg);
|
||||
continue;
|
||||
}
|
||||
curclass.limit = limit;
|
||||
CONF_LL(limit, arg, -1, LLTMAX);
|
||||
REASSIGN(curclass.limitfile,
|
||||
EMPTYSTR(p) ? NULL : xstrdup(p));
|
||||
|
||||
} else if (strcasecmp(word, "maxfilesize") == 0) {
|
||||
curclass.maxfilesize = DEFAULT_MAXFILESIZE;
|
||||
if (none || EMPTYSTR(arg))
|
||||
continue;
|
||||
llval = strsuftoll(arg);
|
||||
if (llval == -1) {
|
||||
syslog(LOG_WARNING,
|
||||
"%s line %d: invalid maxfilesize %s",
|
||||
infile, (int)line, arg);
|
||||
continue;
|
||||
}
|
||||
curclass.maxfilesize = llval;
|
||||
CONF_LL(maxfilesize, arg, -1, LLTMAX);
|
||||
|
||||
} else if (strcasecmp(word, "maxtimeout") == 0) {
|
||||
curclass.maxtimeout = DEFAULT_MAXTIMEOUT;
|
||||
if (none || EMPTYSTR(arg))
|
||||
continue;
|
||||
timeout = (unsigned int)strtoul(arg, &endp, 10);
|
||||
if (*endp != 0) {
|
||||
syslog(LOG_WARNING,
|
||||
"%s line %d: invalid maxtimeout %s",
|
||||
infile, (int)line, arg);
|
||||
continue;
|
||||
}
|
||||
if (timeout < 30) {
|
||||
syslog(LOG_WARNING,
|
||||
"%s line %d: maxtimeout %d < 30 seconds",
|
||||
infile, (int)line, timeout);
|
||||
continue;
|
||||
}
|
||||
if (timeout < curclass.timeout) {
|
||||
syslog(LOG_WARNING,
|
||||
"%s line %d: maxtimeout %d < timeout (%d)",
|
||||
infile, (int)line, timeout,
|
||||
curclass.timeout);
|
||||
continue;
|
||||
}
|
||||
curclass.maxtimeout = timeout;
|
||||
CONF_LL(maxtimeout, arg,
|
||||
MIN(30, curclass.timeout), LLTMAX);
|
||||
|
||||
} else if (strcasecmp(word, "mmapsize") == 0) {
|
||||
curclass.mmapsize = 0;
|
||||
CONF_LL(mmapsize, arg, 0, LLTMAX);
|
||||
|
||||
} else if (strcasecmp(word, "readsize") == 0) {
|
||||
curclass.readsize = 0;
|
||||
CONF_LL(readsize, arg, 0, LLTMAX);
|
||||
|
||||
} else if (strcasecmp(word, "writesize") == 0) {
|
||||
curclass.writesize = 0;
|
||||
CONF_LL(writesize, arg, 0, LLTMAX);
|
||||
|
||||
} else if (strcasecmp(word, "sendbufsize") == 0) {
|
||||
curclass.sendbufsize = 0;
|
||||
CONF_LL(sendbufsize, arg, 0, LLTMAX);
|
||||
|
||||
} else if (strcasecmp(word, "sendlowat") == 0) {
|
||||
curclass.sendlowat = 0;
|
||||
CONF_LL(sendlowat, arg, 0, LLTMAX);
|
||||
|
||||
} else if (strcasecmp(word, "modify") == 0) {
|
||||
CONF_FLAG(modify);
|
||||
@ -383,107 +407,60 @@ parse_conf(const char *findclass)
|
||||
CONF_FLAG(passive);
|
||||
|
||||
} else if (strcasecmp(word, "portrange") == 0) {
|
||||
int minport, maxport;
|
||||
char *min, *max;
|
||||
long minport, maxport;
|
||||
|
||||
curclass.portmin = 0;
|
||||
curclass.portmax = 0;
|
||||
if (none || EMPTYSTR(arg))
|
||||
continue;
|
||||
min = arg;
|
||||
NEXTWORD(p, max);
|
||||
if (EMPTYSTR(max)) {
|
||||
if (EMPTYSTR(p)) {
|
||||
syslog(LOG_WARNING,
|
||||
"%s line %d: missing maxport argument",
|
||||
infile, (int)line);
|
||||
continue;
|
||||
}
|
||||
minport = (int)strtol(min, &endp, 10);
|
||||
if (*endp != 0 || minport < IPPORT_RESERVED ||
|
||||
minport > IPPORT_ANONMAX) {
|
||||
syslog(LOG_WARNING,
|
||||
"%s line %d: invalid minport %s",
|
||||
infile, (int)line, min);
|
||||
minport = strsuftollx("minport", arg, IPPORT_RESERVED,
|
||||
IPPORT_ANONMAX, errbuf, sizeof(errbuf));
|
||||
if (errbuf[0]) {
|
||||
syslog(LOG_WARNING, "%s line %d: %s",
|
||||
infile, (int)line, errbuf);
|
||||
continue;
|
||||
}
|
||||
maxport = (int)strtol(max, &endp, 10);
|
||||
if (*endp != 0 || maxport < IPPORT_RESERVED ||
|
||||
maxport > IPPORT_ANONMAX) {
|
||||
syslog(LOG_WARNING,
|
||||
"%s line %d: invalid maxport %s",
|
||||
infile, (int)line, max);
|
||||
maxport = strsuftollx("maxport", p, IPPORT_RESERVED,
|
||||
IPPORT_ANONMAX, errbuf, sizeof(errbuf));
|
||||
if (errbuf[0]) {
|
||||
syslog(LOG_WARNING, "%s line %d: %s",
|
||||
infile, (int)line, errbuf);
|
||||
continue;
|
||||
}
|
||||
if (minport >= maxport) {
|
||||
syslog(LOG_WARNING,
|
||||
"%s line %d: minport %d >= maxport %d",
|
||||
"%s line %d: minport %ld >= maxport %ld",
|
||||
infile, (int)line, minport, maxport);
|
||||
continue;
|
||||
}
|
||||
curclass.portmin = minport;
|
||||
curclass.portmax = maxport;
|
||||
curclass.portmin = (int)minport;
|
||||
curclass.portmax = (int)maxport;
|
||||
|
||||
} else if (strcasecmp(word, "private") == 0) {
|
||||
CONF_FLAG(private);
|
||||
|
||||
} else if (strcasecmp(word, "rateget") == 0) {
|
||||
curclass.maxrateget = 0;
|
||||
curclass.rateget = 0;
|
||||
if (none || EMPTYSTR(arg))
|
||||
continue;
|
||||
llval = strsuftoll(arg);
|
||||
if (llval == -1) {
|
||||
syslog(LOG_WARNING,
|
||||
"%s line %d: invalid rateget %s",
|
||||
infile, (int)line, arg);
|
||||
continue;
|
||||
}
|
||||
curclass.maxrateget = llval;
|
||||
curclass.rateget = llval;
|
||||
curclass.maxrateget = curclass.rateget = 0;
|
||||
CONF_LL(rateget, arg, 0, LLTMAX);
|
||||
curclass.maxrateget = curclass.rateget;
|
||||
|
||||
} else if (strcasecmp(word, "rateput") == 0) {
|
||||
curclass.maxrateput = 0;
|
||||
curclass.rateput = 0;
|
||||
if (none || EMPTYSTR(arg))
|
||||
continue;
|
||||
llval = strsuftoll(arg);
|
||||
if (llval == -1) {
|
||||
syslog(LOG_WARNING,
|
||||
"%s line %d: invalid rateput %s",
|
||||
infile, (int)line, arg);
|
||||
continue;
|
||||
}
|
||||
curclass.maxrateput = llval;
|
||||
curclass.rateput = llval;
|
||||
curclass.maxrateput = curclass.rateput = 0;
|
||||
CONF_LL(rateput, arg, 0, LLTMAX);
|
||||
curclass.maxrateput = curclass.rateput;
|
||||
|
||||
} else if (strcasecmp(word, "sanenames") == 0) {
|
||||
CONF_FLAG(sanenames);
|
||||
|
||||
} else if (strcasecmp(word, "timeout") == 0) {
|
||||
curclass.timeout = DEFAULT_TIMEOUT;
|
||||
if (none || EMPTYSTR(arg))
|
||||
continue;
|
||||
timeout = (unsigned int)strtoul(arg, &endp, 10);
|
||||
if (*endp != 0) {
|
||||
syslog(LOG_WARNING,
|
||||
"%s line %d: invalid timeout %s",
|
||||
infile, (int)line, arg);
|
||||
continue;
|
||||
}
|
||||
if (timeout < 30) {
|
||||
syslog(LOG_WARNING,
|
||||
"%s line %d: timeout %d < 30 seconds",
|
||||
infile, (int)line, timeout);
|
||||
continue;
|
||||
}
|
||||
if (timeout > curclass.maxtimeout) {
|
||||
syslog(LOG_WARNING,
|
||||
"%s line %d: timeout %d > maxtimeout (%d)",
|
||||
infile, (int)line, timeout,
|
||||
curclass.maxtimeout);
|
||||
continue;
|
||||
}
|
||||
curclass.timeout = timeout;
|
||||
CONF_LL(timeout, arg, 30, curclass.maxtimeout);
|
||||
|
||||
} else if (strcasecmp(word, "template") == 0) {
|
||||
if (none)
|
||||
@ -491,19 +468,22 @@ parse_conf(const char *findclass)
|
||||
REASSIGN(template, EMPTYSTR(arg) ? NULL : xstrdup(arg));
|
||||
|
||||
} else if (strcasecmp(word, "umask") == 0) {
|
||||
mode_t fumask;
|
||||
u_long fumask;
|
||||
|
||||
curclass.umask = DEFAULT_UMASK;
|
||||
if (none || EMPTYSTR(arg))
|
||||
continue;
|
||||
fumask = (mode_t)strtoul(arg, &endp, 8);
|
||||
if (*endp != 0 || fumask > 0777) {
|
||||
errno = 0;
|
||||
endp = NULL;
|
||||
fumask = strtoul(arg, &endp, 8);
|
||||
if (errno || *arg == '\0' || *endp != '\0' ||
|
||||
fumask > 0777) {
|
||||
syslog(LOG_WARNING,
|
||||
"%s line %d: invalid umask %s",
|
||||
infile, (int)line, arg);
|
||||
continue;
|
||||
}
|
||||
curclass.umask = fumask;
|
||||
curclass.umask = (mode_t)fumask;
|
||||
|
||||
} else if (strcasecmp(word, "upload") == 0) {
|
||||
CONF_FLAG(upload);
|
||||
@ -516,6 +496,8 @@ parse_conf(const char *findclass)
|
||||
infile, (int)line, word);
|
||||
continue;
|
||||
}
|
||||
nextline:
|
||||
;
|
||||
}
|
||||
REASSIGN(template, NULL);
|
||||
fclose(f);
|
||||
@ -578,7 +560,7 @@ show_chdir_messages(int code)
|
||||
return;
|
||||
|
||||
memset(&gl, 0, sizeof(gl));
|
||||
if (glob(curclass.notify, GLOB_LIMIT, NULL, &gl) != 0
|
||||
if (glob(curclass.notify, GLOB_BRACE|GLOB_LIMIT, NULL, &gl) != 0
|
||||
|| gl.gl_matchc == 0) {
|
||||
globfree(&gl);
|
||||
return;
|
||||
@ -669,8 +651,8 @@ display_file(const char *file, int code)
|
||||
cprintf(stdout, "unlimited");
|
||||
lastnum = 0;
|
||||
} else {
|
||||
cprintf(stdout, "%d",
|
||||
curclass.limit);
|
||||
cprintf(stdout, LLF,
|
||||
(LLT)curclass.limit);
|
||||
lastnum = curclass.limit;
|
||||
}
|
||||
break;
|
||||
@ -890,51 +872,6 @@ do_conversion(const char *fname)
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert the string `arg' to a long long, which may have an optional SI suffix
|
||||
* (`b', `k', `m', `g', `t'). Returns the number for success, -1 otherwise.
|
||||
*/
|
||||
LLT
|
||||
strsuftoll(const char *arg)
|
||||
{
|
||||
char *cp;
|
||||
LLT val;
|
||||
|
||||
if (!isdigit((unsigned char)arg[0]))
|
||||
return (-1);
|
||||
|
||||
val = STRTOLL(arg, &cp, 10);
|
||||
if (cp != NULL) {
|
||||
if (cp[0] != '\0' && cp[1] != '\0')
|
||||
return (-1);
|
||||
switch (tolower((unsigned char)cp[0])) {
|
||||
case '\0':
|
||||
case 'b':
|
||||
break;
|
||||
case 'k':
|
||||
val <<= 10;
|
||||
break;
|
||||
case 'm':
|
||||
val <<= 20;
|
||||
break;
|
||||
case 'g':
|
||||
val <<= 30;
|
||||
break;
|
||||
#ifndef NO_LONG_LONG
|
||||
case 't':
|
||||
val <<= 40;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
if (val < 0)
|
||||
return (-1);
|
||||
|
||||
return (val);
|
||||
}
|
||||
|
||||
/*
|
||||
* Count the number of current connections, reading from
|
||||
* /var/run/ftpd.pids-<class>
|
||||
@ -959,15 +896,8 @@ count_users(void)
|
||||
|
||||
if ((fd = open(fn, O_RDWR | O_CREAT, 0600)) == -1)
|
||||
return;
|
||||
#if HAVE_LOCKF
|
||||
if (lockf(fd, F_TLOCK, 0) == -1)
|
||||
goto cleanup_count;
|
||||
#elif HAVE_FLOCK
|
||||
if (flock(fd, LOCK_EX | LOCK_NB) != 0)
|
||||
goto cleanup_count;
|
||||
#else
|
||||
/* XXX: use fcntl ? */
|
||||
#endif
|
||||
if (fstat(fd, &sb) == -1)
|
||||
goto cleanup_count;
|
||||
if ((pids = malloc(sb.st_size + sizeof(pid_t))) == NULL)
|
||||
@ -1005,14 +935,8 @@ count_users(void)
|
||||
(void)ftruncate(fd, count);
|
||||
|
||||
cleanup_count:
|
||||
#if HAVE_LOCKF
|
||||
if (lseek(fd, 0, SEEK_SET) != -1)
|
||||
(void)lockf(fd, F_ULOCK, 0);
|
||||
#elif HAVE_FLOCK
|
||||
(void)flock(fd, LOCK_UN);
|
||||
#else
|
||||
/* XXX: use fcntl ? */
|
||||
#endif
|
||||
close(fd);
|
||||
REASSIGN(pids, NULL);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: extern.h,v 1.43 2001/12/04 13:54:12 lukem Exp $ */
|
||||
/* $NetBSD: extern.h,v 1.44 2002/05/30 00:24:47 enami Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992, 1993
|
||||
@ -108,15 +108,8 @@
|
||||
# define ULLFP(x) "%" x "lu"
|
||||
# define ULLT unsigned long
|
||||
# define STRTOLL(x,y,z) strtol(x,y,z)
|
||||
#else
|
||||
#if HAVE_PRINTF_QD
|
||||
# define LLF "%qd"
|
||||
# define LLFP(x) "%" x "qd"
|
||||
# define LLT long long
|
||||
# define ULLF "%qu"
|
||||
# define ULLFP(x) "%" x "qu"
|
||||
# define ULLT unsigned long long
|
||||
# define STRTOLL(x,y,z) strtoll(x,y,z)
|
||||
# define LLTMIN LONG_MIN
|
||||
# define LLTMAX LONG_MAX
|
||||
#else
|
||||
# define LLF "%lld"
|
||||
# define LLFP(x) "%" x "lld"
|
||||
@ -125,7 +118,8 @@
|
||||
# define ULLFP(x) "%" x "llu"
|
||||
# define ULLT unsigned long long
|
||||
# define STRTOLL(x,y,z) strtoll(x,y,z)
|
||||
#endif
|
||||
# define LLTMIN LLONG_MIN
|
||||
# define LLTMAX LLONG_MAX
|
||||
#endif
|
||||
|
||||
#define FTP_BUFLEN 512
|
||||
@ -137,7 +131,7 @@ char *conffilename(const char *);
|
||||
char **copyblk(char **);
|
||||
void count_users(void);
|
||||
void cprintf(FILE *, const char *, ...)
|
||||
;
|
||||
__attribute__((__format__(__printf__, 2, 3)));
|
||||
void cwd(const char *);
|
||||
FILE *dataconn(const char *, off_t, const char *);
|
||||
void delete(const char *);
|
||||
@ -177,7 +171,7 @@ void removedir(const char *);
|
||||
void renamecmd(const char *, const char *);
|
||||
char *renamefrom(const char *);
|
||||
void reply(int, const char *, ...)
|
||||
;
|
||||
__attribute__((__format__(__printf__, 2, 3)));
|
||||
void retrieve(char *[], const char *);
|
||||
void send_file_list(const char *);
|
||||
void show_chdir_messages(int);
|
||||
@ -186,7 +180,6 @@ void statcmd(void);
|
||||
void statfilecmd(const char *);
|
||||
void statxfer(void);
|
||||
void store(const char *, const char *, int);
|
||||
LLT strsuftoll(const char *);
|
||||
void user(const char *);
|
||||
char *xstrdup(const char *);
|
||||
void yyerror(char *);
|
||||
@ -271,24 +264,29 @@ struct ftpclass {
|
||||
char *display; /* File to display upon chdir */
|
||||
char *homedir; /* Directory to chdir(2) to at login */
|
||||
classflag_t flags; /* Flags; see classflag_t above */
|
||||
int limit; /* Max connections (-1 = unlimited) */
|
||||
LLT limit; /* Max connections (-1 = unlimited) */
|
||||
char *limitfile; /* File to display if limit reached */
|
||||
LLT maxfilesize; /* Maximum file size of uploads */
|
||||
LLT maxrateget; /* Maximum get transfer rate throttle */
|
||||
LLT maxrateput; /* Maximum put transfer rate throttle */
|
||||
unsigned int maxtimeout; /* Maximum permitted timeout */
|
||||
LLT maxtimeout; /* Maximum permitted timeout */
|
||||
char *motd; /* MotD file to display after login */
|
||||
char *notify; /* Files to notify about upon chdir */
|
||||
int portmin; /* Minumum port for passive mode */
|
||||
int portmax; /* Maximum port for passive mode */
|
||||
LLT portmin; /* Minumum port for passive mode */
|
||||
LLT portmax; /* Maximum port for passive mode */
|
||||
LLT rateget; /* Get (RETR) transfer rate throttle */
|
||||
LLT rateput; /* Put (STOR) transfer rate throttle */
|
||||
unsigned int timeout; /* Default timeout */
|
||||
LLT timeout; /* Default timeout */
|
||||
class_ft type; /* Class type */
|
||||
mode_t umask; /* Umask to use */
|
||||
LLT mmapsize; /* mmap window size */
|
||||
LLT readsize; /* data read size */
|
||||
LLT writesize; /* data write size */
|
||||
LLT sendbufsize; /* SO_SNDBUF size */
|
||||
LLT sendlowat; /* SO_SNDLOWAT size */
|
||||
};
|
||||
|
||||
extern void ftp_loop(void);
|
||||
extern void ftp_loop(void) __attribute__ ((noreturn));
|
||||
extern void ftp_handle_line(char *);
|
||||
|
||||
#ifndef GLOBAL
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* $NetBSD: ftpcmd.y,v 1.66 2001/12/01 10:25:30 lukem Exp $ */
|
||||
/* $NetBSD: ftpcmd.y,v 1.71 2002/10/12 08:35:17 darrenr Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997-2001 The NetBSD Foundation, Inc.
|
||||
* Copyright (c) 1997-2002 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
@ -77,7 +77,41 @@
|
||||
*/
|
||||
|
||||
%{
|
||||
#include "lukemftpd.h"
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)ftpcmd.y 8.3 (Berkeley) 4/6/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: ftpcmd.y,v 1.71 2002/10/12 08:35:17 darrenr Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/ftp.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <pwd.h>
|
||||
#include <setjmp.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <time.h>
|
||||
#include <tzfile.h>
|
||||
#include <unistd.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#ifdef KERBEROS5
|
||||
#include <krb5/krb5.h>
|
||||
#endif
|
||||
|
||||
#include "extern.h"
|
||||
#include "version.h"
|
||||
@ -93,7 +127,10 @@ char *fromname;
|
||||
%}
|
||||
|
||||
%union {
|
||||
struct {
|
||||
off_t o;
|
||||
int i;
|
||||
} u;
|
||||
char *s;
|
||||
}
|
||||
|
||||
@ -128,10 +165,10 @@ char *fromname;
|
||||
|
||||
%token <s> STRING
|
||||
%token <s> ALL
|
||||
%token <i> NUMBER
|
||||
%token <u> NUMBER
|
||||
|
||||
%type <i> check_login octal_number byte_size
|
||||
%type <i> struct_code mode_code type_code form_code decimal_integer
|
||||
%type <u.i> check_login octal_number byte_size
|
||||
%type <u.i> struct_code mode_code type_code form_code decimal_integer
|
||||
%type <s> pathstring pathname password username
|
||||
%type <s> mechanism_name base64data prot_code
|
||||
|
||||
@ -259,32 +296,48 @@ cmd
|
||||
| LPSV check_login CRLF
|
||||
{
|
||||
if ($2) {
|
||||
if (CURCLASS_FLAGS_ISSET(passive)) {
|
||||
if (epsvall)
|
||||
reply(501,
|
||||
"LPSV disallowed after EPSV ALL");
|
||||
else
|
||||
long_passive("LPSV", PF_UNSPEC);
|
||||
} else
|
||||
reply(500, "LPSV mode not available.");
|
||||
}
|
||||
}
|
||||
|
||||
| EPSV check_login SP NUMBER CRLF
|
||||
{
|
||||
if ($2)
|
||||
long_passive("EPSV", epsvproto2af($4));
|
||||
if ($2) {
|
||||
if (CURCLASS_FLAGS_ISSET(passive))
|
||||
long_passive("EPSV",
|
||||
epsvproto2af($4.i));
|
||||
else
|
||||
reply(500, "EPSV mode not available.");
|
||||
}
|
||||
}
|
||||
|
||||
| EPSV check_login SP ALL CRLF
|
||||
{
|
||||
if ($2) {
|
||||
reply(200, "EPSV ALL command successful.");
|
||||
if (CURCLASS_FLAGS_ISSET(passive)) {
|
||||
reply(200,
|
||||
"EPSV ALL command successful.");
|
||||
epsvall++;
|
||||
} else
|
||||
reply(500, "EPSV mode not available.");
|
||||
}
|
||||
}
|
||||
|
||||
| EPSV check_login CRLF
|
||||
{
|
||||
if ($2)
|
||||
if ($2) {
|
||||
if (CURCLASS_FLAGS_ISSET(passive))
|
||||
long_passive("EPSV", PF_UNSPEC);
|
||||
else
|
||||
reply(500, "EPSV mode not available.");
|
||||
}
|
||||
}
|
||||
|
||||
| TYPE check_login SP type_code CRLF
|
||||
@ -517,24 +570,28 @@ cmd
|
||||
{
|
||||
if ($4) {
|
||||
reply(200,
|
||||
"Current IDLE time limit is %d seconds; max %d",
|
||||
curclass.timeout, curclass.maxtimeout);
|
||||
"Current IDLE time limit is " LLF
|
||||
" seconds; max " LLF,
|
||||
(LLT)curclass.timeout,
|
||||
(LLT)curclass.maxtimeout);
|
||||
}
|
||||
}
|
||||
|
||||
| SITE SP IDLE check_login SP NUMBER CRLF
|
||||
{
|
||||
if ($4) {
|
||||
if ($6 < 30 || $6 > curclass.maxtimeout) {
|
||||
if ($6.i < 30 || $6.i > curclass.maxtimeout) {
|
||||
reply(501,
|
||||
"IDLE time limit must be between 30 and %d seconds",
|
||||
curclass.maxtimeout);
|
||||
"IDLE time limit must be between 30 and "
|
||||
LLF " seconds",
|
||||
(LLT)curclass.maxtimeout);
|
||||
} else {
|
||||
curclass.timeout = $6;
|
||||
curclass.timeout = $6.i;
|
||||
(void) alarm(curclass.timeout);
|
||||
reply(200,
|
||||
"IDLE time limit set to %d seconds",
|
||||
curclass.timeout);
|
||||
"IDLE time limit set to "
|
||||
LLF " seconds",
|
||||
(LLT)curclass.timeout);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -550,19 +607,17 @@ cmd
|
||||
|
||||
| SITE SP RATEGET check_login SP STRING CRLF
|
||||
{
|
||||
char errbuf[100];
|
||||
char *p = $6;
|
||||
LLT rate;
|
||||
|
||||
if ($4) {
|
||||
rate = strsuftoll(p);
|
||||
if (rate == -1)
|
||||
reply(501, "Invalid RATEGET %s", p);
|
||||
else if (curclass.maxrateget &&
|
||||
rate > curclass.maxrateget)
|
||||
reply(501,
|
||||
"RATEGET " LLF " is larger than maximum RATEGET " LLF,
|
||||
(LLT)rate,
|
||||
(LLT)curclass.maxrateget);
|
||||
rate = strsuftollx("RATEGET", p, 0,
|
||||
curclass.maxrateget
|
||||
? curclass.maxrateget
|
||||
: LLTMAX, errbuf, sizeof(errbuf));
|
||||
if (errbuf[0])
|
||||
reply(501, "%s", errbuf);
|
||||
else {
|
||||
curclass.rateget = rate;
|
||||
reply(200,
|
||||
@ -584,19 +639,17 @@ cmd
|
||||
|
||||
| SITE SP RATEPUT check_login SP STRING CRLF
|
||||
{
|
||||
char errbuf[100];
|
||||
char *p = $6;
|
||||
LLT rate;
|
||||
|
||||
if ($4) {
|
||||
rate = strsuftoll(p);
|
||||
if (rate == -1)
|
||||
reply(501, "Invalid RATEPUT %s", p);
|
||||
else if (curclass.maxrateput &&
|
||||
rate > curclass.maxrateput)
|
||||
reply(501,
|
||||
"RATEPUT " LLF " is larger than maximum RATEPUT " LLF,
|
||||
(LLT)rate,
|
||||
(LLT)curclass.maxrateput);
|
||||
rate = strsuftollx("RATEPUT", p, 0,
|
||||
curclass.maxrateput
|
||||
? curclass.maxrateput
|
||||
: LLTMAX, errbuf, sizeof(errbuf));
|
||||
if (errbuf[0])
|
||||
reply(501, "%s", errbuf);
|
||||
else {
|
||||
curclass.rateput = rate;
|
||||
reply(200,
|
||||
@ -622,7 +675,7 @@ cmd
|
||||
{
|
||||
int oldmask;
|
||||
|
||||
if ($4 && CURCLASS_FLAGS_ISSET(modify)) {
|
||||
if ($4 && check_write("", 0)) {
|
||||
if (($6 == -1) || ($6 > 0777)) {
|
||||
reply(501, "Bad UMASK value");
|
||||
} else {
|
||||
@ -827,11 +880,11 @@ cmd
|
||||
;
|
||||
|
||||
rcmd
|
||||
: REST check_login SP byte_size CRLF
|
||||
: REST check_login SP NUMBER CRLF
|
||||
{
|
||||
if ($2) {
|
||||
fromname = NULL;
|
||||
restart_point = $4; /* XXX: $4 is only "int" */
|
||||
restart_point = $4.o;
|
||||
reply(350,
|
||||
"Restarting at " LLF ". Send STORE or RETRIEVE to initiate transfer.",
|
||||
(LLT)restart_point);
|
||||
@ -863,6 +916,9 @@ password
|
||||
|
||||
byte_size
|
||||
: NUMBER
|
||||
{
|
||||
$$ = $1.i;
|
||||
}
|
||||
;
|
||||
|
||||
host_port
|
||||
@ -875,9 +931,9 @@ host_port
|
||||
data_dest.su_len = sizeof(struct sockaddr_in);
|
||||
data_dest.su_family = AF_INET;
|
||||
p = (char *)&data_dest.su_port;
|
||||
p[0] = $9; p[1] = $11;
|
||||
p[0] = $9.i; p[1] = $11.i;
|
||||
a = (char *)&data_dest.su_addr;
|
||||
a[0] = $1; a[1] = $3; a[2] = $5; a[3] = $7;
|
||||
a[0] = $1.i; a[1] = $3.i; a[2] = $5.i; a[3] = $7.i;
|
||||
}
|
||||
;
|
||||
|
||||
@ -892,12 +948,12 @@ host_long_port4
|
||||
data_dest.su_len = sizeof(struct sockaddr_in);
|
||||
data_dest.su_family = AF_INET;
|
||||
p = (char *)&data_dest.su_port;
|
||||
p[0] = $15; p[1] = $17;
|
||||
p[0] = $15.i; p[1] = $17.i;
|
||||
a = (char *)&data_dest.su_addr;
|
||||
a[0] = $5; a[1] = $7; a[2] = $9; a[3] = $11;
|
||||
a[0] = $5.i; a[1] = $7.i; a[2] = $9.i; a[3] = $11.i;
|
||||
|
||||
/* reject invalid LPRT command */
|
||||
if ($1 != 4 || $3 != 4 || $13 != 2)
|
||||
if ($1.i != 4 || $3.i != 4 || $13.i != 2)
|
||||
memset(&data_dest, 0, sizeof(data_dest));
|
||||
}
|
||||
;
|
||||
@ -917,12 +973,12 @@ host_long_port6
|
||||
data_dest.su_len = sizeof(struct sockaddr_in6);
|
||||
data_dest.su_family = AF_INET6;
|
||||
p = (char *)&data_dest.su_port;
|
||||
p[0] = $39; p[1] = $41;
|
||||
p[0] = $39.i; p[1] = $41.i;
|
||||
a = (char *)&data_dest.si_su.su_sin6.sin6_addr;
|
||||
a[0] = $5; a[1] = $7; a[2] = $9; a[3] = $11;
|
||||
a[4] = $13; a[5] = $15; a[6] = $17; a[7] = $19;
|
||||
a[8] = $21; a[9] = $23; a[10] = $25; a[11] = $27;
|
||||
a[12] = $29; a[13] = $31; a[14] = $33; a[15] = $35;
|
||||
a[0] = $5.i; a[1] = $7.i; a[2] = $9.i; a[3] = $11.i;
|
||||
a[4] = $13.i; a[5] = $15.i; a[6] = $17.i; a[7] = $19.i;
|
||||
a[8] = $21.i; a[9] = $23.i; a[10] = $25.i; a[11] = $27.i;
|
||||
a[12] = $29.i; a[13] = $31.i; a[14] = $33.i; a[15] = $35.i;
|
||||
if (his_addr.su_family == AF_INET6) {
|
||||
/* XXX: more sanity checks! */
|
||||
data_dest.su_scope_id = his_addr.su_scope_id;
|
||||
@ -931,7 +987,7 @@ host_long_port6
|
||||
memset(&data_dest, 0, sizeof(data_dest));
|
||||
#endif /* INET6 */
|
||||
/* reject invalid LPRT command */
|
||||
if ($1 != 6 || $3 != 16 || $37 != 2)
|
||||
if ($1.i != 6.i || $3.i != 16.i || $37.i != 2)
|
||||
memset(&data_dest, 0, sizeof(data_dest));
|
||||
}
|
||||
;
|
||||
@ -1093,7 +1149,7 @@ octal_number
|
||||
* Convert a number that was read as decimal number
|
||||
* to what it would be if it had been read as octal.
|
||||
*/
|
||||
dec = $1;
|
||||
dec = $1.i;
|
||||
multby = 1;
|
||||
ret = 0;
|
||||
while (dec) {
|
||||
@ -1124,6 +1180,9 @@ prot_code
|
||||
|
||||
decimal_integer
|
||||
: NUMBER
|
||||
{
|
||||
$$ = $1.i;
|
||||
}
|
||||
;
|
||||
|
||||
check_login
|
||||
@ -1251,6 +1310,8 @@ extern int epsvall;
|
||||
/*
|
||||
* Check if a filename is allowed to be modified (isupload == 0) or
|
||||
* uploaded (isupload == 1), and if necessary, check the filename is `sane'.
|
||||
* If the filename is NULL, fail.
|
||||
* If the filename is "", don't do the sane name check.
|
||||
*/
|
||||
static int
|
||||
check_write(const char *file, int isupload)
|
||||
@ -1271,8 +1332,9 @@ check_write(const char *file, int isupload)
|
||||
reply(502, "No permission to use this command.");
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* checking sanenames */
|
||||
if (CURCLASS_FLAGS_ISSET(sanenames)) {
|
||||
if (file[0] != '\0' && CURCLASS_FLAGS_ISSET(sanenames)) {
|
||||
const char *p;
|
||||
|
||||
if (file[0] == '.')
|
||||
@ -1392,11 +1454,11 @@ toolong(int signo)
|
||||
{
|
||||
|
||||
reply(421,
|
||||
"Timeout (%d seconds): closing control connection.",
|
||||
curclass.timeout);
|
||||
"Timeout (" LLF " seconds): closing control connection.",
|
||||
(LLT)curclass.timeout);
|
||||
if (logging)
|
||||
syslog(LOG_INFO, "User %s timed out after %d seconds",
|
||||
(pw ? pw->pw_name : "unknown"), curclass.timeout);
|
||||
syslog(LOG_INFO, "User %s timed out after " LLF " seconds",
|
||||
(pw ? pw->pw_name : "unknown"), (LLT)curclass.timeout);
|
||||
dologout(1);
|
||||
}
|
||||
|
||||
@ -1548,7 +1610,7 @@ yylex(void)
|
||||
;
|
||||
c = cmdp[cpos];
|
||||
cmdp[cpos] = '\0';
|
||||
yylval.i = atoi(cp);
|
||||
yylval.u.i = atoi(cp);
|
||||
cmdp[cpos] = c;
|
||||
state = STR1;
|
||||
return (NUMBER);
|
||||
@ -1563,7 +1625,8 @@ yylex(void)
|
||||
;
|
||||
c = cmdp[cpos];
|
||||
cmdp[cpos] = '\0';
|
||||
yylval.i = atoi(cp);
|
||||
yylval.u.i = atoi(cp);
|
||||
yylval.u.o = strtoull(cp, (char **)NULL, 10);
|
||||
cmdp[cpos] = c;
|
||||
return (NUMBER);
|
||||
}
|
||||
@ -1736,13 +1799,13 @@ help(struct tab *ctab, const char *s)
|
||||
}
|
||||
c = lookup(ctab, s);
|
||||
if (c == (struct tab *)0) {
|
||||
reply(502, "Unknown command %s.", s);
|
||||
reply(502, "Unknown command '%s'.", s);
|
||||
return;
|
||||
}
|
||||
if (CMD_IMPLEMENTED(c))
|
||||
reply(214, "Syntax: %s%s %s", htype, c->name, c->help);
|
||||
else
|
||||
reply(214, "%s%-*s\t%s; not implemented.", htype, width,
|
||||
reply(504, "%s%-*s\t%s; not implemented.", htype, width,
|
||||
c->name, c->help);
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
.\" $NetBSD: ftpd.8,v 1.69 2002/02/08 01:30:07 ross Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1997-2001 The NetBSD Foundation, Inc.
|
||||
.\" Copyright (c) 1997-2002 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 October 13, 2001
|
||||
.Dd October 25, 2002
|
||||
.Dt FTPD 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -734,7 +734,7 @@ and
|
||||
.Cm draft-ietf-ftpext-mlst-11
|
||||
support was implemented in
|
||||
.Nx 1.3
|
||||
and later releases by Luke Mewburn \*[Lt]lukem@netbsd.org\*[Gt].
|
||||
and later releases by Luke Mewburn.
|
||||
.Sh BUGS
|
||||
The server must run as the super-user to create sockets with
|
||||
privileged port numbers (i.e, those less than
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ftpd.c,v 1.138 2002/02/11 11:45:07 lukem Exp $ */
|
||||
/* $NetBSD: ftpd.c,v 1.147 2002/11/29 14:40:00 lukem Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997-2001 The NetBSD Foundation, Inc.
|
||||
@ -98,20 +98,69 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__COPYRIGHT(
|
||||
"@(#) Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994\n\
|
||||
The Regents of the University of California. All rights reserved.\n");
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)ftpd.c 8.5 (Berkeley) 4/28/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: ftpd.c,v 1.147 2002/11/29 14:40:00 lukem Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* FTP server.
|
||||
*/
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
|
||||
#define FTP_NAMES
|
||||
|
||||
#include "lukemftpd.h"
|
||||
|
||||
#if HAVE_GETSPNAM
|
||||
#include <shadow.h>
|
||||
#endif
|
||||
|
||||
#include <arpa/ftp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <arpa/telnet.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <fnmatch.h>
|
||||
#include <glob.h>
|
||||
#include <grp.h>
|
||||
#include <limits.h>
|
||||
#include <netdb.h>
|
||||
#include <pwd.h>
|
||||
#include <setjmp.h>
|
||||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <time.h>
|
||||
#include <tzfile.h>
|
||||
#include <unistd.h>
|
||||
#include <util.h>
|
||||
#ifdef SUPPORT_UTMP
|
||||
#include <utmp.h>
|
||||
#endif
|
||||
#ifdef SUPPORT_UTMPX
|
||||
#include <utmpx.h>
|
||||
#endif
|
||||
#ifdef SKEY
|
||||
#include <skey.h>
|
||||
#endif
|
||||
@ -140,7 +189,12 @@ int mapped; /* IPv4 connection on AF_INET6 socket */
|
||||
off_t file_size;
|
||||
off_t byte_count;
|
||||
static char ttyline[20];
|
||||
#ifdef SUPPORT_UTMP
|
||||
static struct utmp utmp; /* for utmp */
|
||||
#endif
|
||||
#ifdef SUPPORT_UTMPX
|
||||
static struct utmpx utmpx; /* for utmpx */
|
||||
#endif
|
||||
|
||||
static const char *anondir = NULL;
|
||||
static const char *confdir = _DEFAULT_CONFDIR;
|
||||
@ -166,6 +220,13 @@ int epsvall = 0;
|
||||
int swaitmax = SWAITMAX;
|
||||
int swaitint = SWAITINT;
|
||||
|
||||
enum send_status {
|
||||
SS_SUCCESS,
|
||||
SS_NO_TRANSFER, /* no transfer made yet */
|
||||
SS_FILE_ERROR, /* file read error */
|
||||
SS_DATA_ERROR /* data send error */
|
||||
};
|
||||
|
||||
static int bind_pasv_addr(void);
|
||||
static int checkuser(const char *, const char *, int, int, char **);
|
||||
static int checkaccess(const char *);
|
||||
@ -173,12 +234,21 @@ static int checkpassword(const struct passwd *, const char *);
|
||||
static void end_login(void);
|
||||
static FILE *getdatasock(const char *);
|
||||
static char *gunique(const char *);
|
||||
static void login_utmp(const char *, const char *, const char *);
|
||||
static void logremotehost(struct sockinet *);
|
||||
static void lostconn(int);
|
||||
static void myoob(int);
|
||||
static int receive_data(FILE *, FILE *);
|
||||
static int send_data(FILE *, FILE *, off_t, int);
|
||||
static int send_data(FILE *, FILE *, const struct stat *, int);
|
||||
static struct passwd *sgetpwnam(const char *);
|
||||
static int write_data(int, char *, size_t, off_t *, struct timeval *,
|
||||
int);
|
||||
static enum send_status
|
||||
send_data_with_read(int, int, const struct stat *, int);
|
||||
static enum send_status
|
||||
send_data_with_mmap(int, int, const struct stat *, int);
|
||||
static void logrusage(const struct rusage *, const struct rusage *);
|
||||
static void logout_utmp(void);
|
||||
|
||||
int main(int, char *[]);
|
||||
|
||||
@ -191,8 +261,6 @@ int k5login(struct passwd *, char *, char *, char *);
|
||||
void k5destroy(void);
|
||||
#endif
|
||||
|
||||
char * __progname;
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
@ -201,12 +269,7 @@ main(int argc, char *argv[])
|
||||
krb5_error_code kerror;
|
||||
#endif
|
||||
char *p;
|
||||
|
||||
__progname = strrchr(argv[0], '/');
|
||||
if (__progname == NULL)
|
||||
__progname = argv[0];
|
||||
else
|
||||
__progname++;
|
||||
long l;
|
||||
|
||||
connections = 1;
|
||||
debug = 0;
|
||||
@ -232,7 +295,7 @@ main(int argc, char *argv[])
|
||||
* LOG_NDELAY sets up the logging connection immediately,
|
||||
* necessary for anonymous ftp's that chroot and can't do it later.
|
||||
*/
|
||||
openlog("ftpd", LOG_PID | LOG_NDELAY, FTPD_LOGTYPE);
|
||||
openlog("ftpd", LOG_PID | LOG_NDELAY, LOG_FTP);
|
||||
|
||||
while ((ch = getopt(argc, argv, "a:c:C:de:h:HlP:qQrst:T:uUvV:wWX"))
|
||||
!= -1) {
|
||||
@ -274,13 +337,17 @@ main(int argc, char *argv[])
|
||||
break;
|
||||
|
||||
case 'P':
|
||||
dataport = (int)strtol(optarg, &p, 10);
|
||||
if (*p != '\0' || dataport < IPPORT_RESERVED ||
|
||||
dataport > IPPORT_ANONMAX) {
|
||||
errno = 0;
|
||||
p = NULL;
|
||||
l = strtol(optarg, &p, 10);
|
||||
if (errno || *optarg == '\0' || *p != '\0' ||
|
||||
l < IPPORT_RESERVED ||
|
||||
l > IPPORT_ANONMAX) {
|
||||
syslog(LOG_WARNING, "Invalid dataport %s",
|
||||
optarg);
|
||||
dataport = 0;
|
||||
}
|
||||
dataport = (int)l;
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
@ -529,7 +596,7 @@ sgetpwnam(const char *name)
|
||||
static int login_attempts; /* number of failed login attempts */
|
||||
static int askpasswd; /* had USER command, ask for PASSwd */
|
||||
static int permitted; /* USER permitted */
|
||||
static char curname[10]; /* current USER name */
|
||||
static char curname[LOGIN_NAME_MAX]; /* current USER name */
|
||||
|
||||
/*
|
||||
* USER command.
|
||||
@ -850,6 +917,69 @@ checkaccess(const char *name)
|
||||
return (checkuser(_PATH_FTPUSERS, name, 1, 0, NULL));
|
||||
}
|
||||
|
||||
static void
|
||||
login_utmp(const char *line, const char *name, const char *host)
|
||||
{
|
||||
#if defined(SUPPORT_UTMPX) || defined(SUPPORT_UTMP)
|
||||
struct timeval tv;
|
||||
(void)gettimeofday(&tv, NULL);
|
||||
#endif
|
||||
#ifdef SUPPORT_UTMPX
|
||||
if (doutmp) {
|
||||
(void)memset(&utmpx, 0, sizeof(utmpx));
|
||||
utmpx.ut_tv = tv;
|
||||
utmpx.ut_pid = getpid();
|
||||
utmpx.ut_id[0] = 'f';
|
||||
utmpx.ut_id[1] = 't';
|
||||
utmpx.ut_id[2] = 'p';
|
||||
utmpx.ut_id[3] = '*';
|
||||
utmpx.ut_type = USER_PROCESS;
|
||||
(void)strncpy(utmpx.ut_name, name, sizeof(utmpx.ut_name));
|
||||
(void)strncpy(utmpx.ut_line, line, sizeof(utmpx.ut_line));
|
||||
(void)strncpy(utmpx.ut_host, host, sizeof(utmpx.ut_host));
|
||||
loginx(&utmpx);
|
||||
}
|
||||
if (dowtmp)
|
||||
logwtmpx(line, name, host, 0, USER_PROCESS);
|
||||
#endif
|
||||
#ifdef SUPPORT_UTMP
|
||||
if (doutmp) {
|
||||
(void)memset(&utmp, 0, sizeof(utmp));
|
||||
(void)time(&utmp.ut_time);
|
||||
(void)strncpy(utmp.ut_name, name, sizeof(utmp.ut_name));
|
||||
(void)strncpy(utmp.ut_line, line, sizeof(utmp.ut_line));
|
||||
(void)strncpy(utmp.ut_host, host, sizeof(utmp.ut_host));
|
||||
login(&utmp);
|
||||
}
|
||||
if (dowtmp)
|
||||
logwtmp(line, name, host);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
logout_utmp(void)
|
||||
{
|
||||
int okwtmp = dowtmp;
|
||||
if (logged_in) {
|
||||
if (doutmp) {
|
||||
#ifdef SUPPORT_UTMPX
|
||||
okwtmp = logoutx(ttyline, 0, DEAD_PROCESS) & dowtmp;
|
||||
#endif
|
||||
#ifdef SUPPORT_UTMP
|
||||
okwtmp = logout(ttyline) & dowtmp;
|
||||
#endif
|
||||
}
|
||||
if (okwtmp) {
|
||||
#ifdef SUPPORT_UTMPX
|
||||
logwtmpx(ttyline, "", "", 0, DEAD_PROCESS);
|
||||
#endif
|
||||
#ifdef SUPPORT_UTMP
|
||||
logwtmp(ttyline, "", "");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Terminate login as previous user (if any), resetting state;
|
||||
* used when USER command is given or login fails.
|
||||
@ -857,16 +987,7 @@ checkaccess(const char *name)
|
||||
static void
|
||||
end_login(void)
|
||||
{
|
||||
|
||||
if (logged_in) {
|
||||
#ifdef NO_UTMP
|
||||
if (dowtmp)
|
||||
logwtmp(ttyline, "", "");
|
||||
if (doutmp)
|
||||
logout(utmp.ut_line);
|
||||
#endif /* NO_UTMP */
|
||||
}
|
||||
/* reset login state */
|
||||
logout_utmp();
|
||||
show_chdir_messages(-1); /* flush chdir cache */
|
||||
if (pw != NULL && pw->pw_passwd != NULL)
|
||||
memset(pw->pw_passwd, 0, strlen(pw->pw_passwd));
|
||||
@ -885,8 +1006,6 @@ pass(const char *passwd)
|
||||
{
|
||||
int rval;
|
||||
char root[MAXPATHLEN];
|
||||
char *p;
|
||||
int len;
|
||||
|
||||
if (logged_in || askpasswd == 0) {
|
||||
reply(503, "Login with USER first.");
|
||||
@ -976,21 +1095,8 @@ pass(const char *passwd)
|
||||
/* cache groups for cmds.c::matchgroup() */
|
||||
gidcount = getgroups(sizeof(gidlist), gidlist);
|
||||
|
||||
/* open wtmp before chroot */
|
||||
#ifdef NO_UTMP
|
||||
if (dowtmp)
|
||||
logwtmp(ttyline, pw->pw_name, remotehost);
|
||||
|
||||
/* open utmp before chroot */
|
||||
if (doutmp) {
|
||||
memset((void *)&utmp, 0, sizeof(utmp));
|
||||
(void)time(&utmp.ut_time);
|
||||
(void)strncpy(utmp.ut_name, pw->pw_name, sizeof(utmp.ut_name));
|
||||
(void)strncpy(utmp.ut_host, remotehost, sizeof(utmp.ut_host));
|
||||
(void)strncpy(utmp.ut_line, ttyline, sizeof(utmp.ut_line));
|
||||
login(&utmp);
|
||||
}
|
||||
#endif /* NO_UTMP */
|
||||
/* open utmp/wtmp before chroot */
|
||||
login_utmp(ttyline, pw->pw_name, remotehost);
|
||||
|
||||
logged_in = 1;
|
||||
|
||||
@ -1002,11 +1108,13 @@ pass(const char *passwd)
|
||||
(void)display_file(conffilename(curclass.limitfile),
|
||||
530);
|
||||
reply(530,
|
||||
"User %s access denied, connection limit of %d reached.",
|
||||
pw->pw_name, curclass.limit);
|
||||
"User %s access denied, connection limit of " LLF
|
||||
" reached.",
|
||||
pw->pw_name, (LLT)curclass.limit);
|
||||
syslog(LOG_NOTICE,
|
||||
"Maximum connection limit of %d for class %s reached, login refused for %s",
|
||||
curclass.limit, curclass.classname, pw->pw_name);
|
||||
"Maximum connection limit of " LLF
|
||||
" for class %s reached, login refused for %s",
|
||||
(LLT)curclass.limit, curclass.classname, pw->pw_name);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
@ -1099,9 +1207,7 @@ pass(const char *passwd)
|
||||
}
|
||||
break;
|
||||
}
|
||||
#if HAVE_SETLOGIN
|
||||
setlogin(pw->pw_name);
|
||||
#endif
|
||||
if (dropprivs ||
|
||||
(curclass.type != CLASS_REAL &&
|
||||
ntohs(ctrl_addr.su_port) > IPPORT_RESERVED + 1)) {
|
||||
@ -1120,15 +1226,7 @@ pass(const char *passwd)
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
len = sizeof("HOME=") + strlen(homedir) + 1;;
|
||||
p = malloc(len);
|
||||
if (p == NULL) {
|
||||
reply(550, "Local resource failure: malloc");
|
||||
goto bad;
|
||||
}
|
||||
snprintf(p, len, "HOME=%s", homedir);
|
||||
putenv(p);
|
||||
free(p);
|
||||
setenv("HOME", homedir, 1);
|
||||
|
||||
if (curclass.type == CLASS_GUEST && passwd[0] == '-')
|
||||
quietmessages = 1;
|
||||
@ -1186,19 +1284,20 @@ retrieve(char *argv[], const char *name)
|
||||
FILE *fin, *dout;
|
||||
struct stat st;
|
||||
int (*closefunc)(FILE *) = NULL;
|
||||
int log, sendrv, closerv, stderrfd, isconversion, isdata, isls;
|
||||
int dolog, sendrv, closerv, stderrfd, isconversion, isdata, isls;
|
||||
struct timeval start, finish, td, *tdp;
|
||||
struct rusage rusage_before, rusage_after;
|
||||
const char *dispname;
|
||||
char *error;
|
||||
|
||||
sendrv = closerv = stderrfd = -1;
|
||||
isconversion = isdata = isls = log = 0;
|
||||
isconversion = isdata = isls = dolog = 0;
|
||||
tdp = NULL;
|
||||
dispname = name;
|
||||
fin = dout = NULL;
|
||||
error = NULL;
|
||||
if (argv == NULL) { /* if not running a command ... */
|
||||
log = 1;
|
||||
dolog = 1;
|
||||
isdata = 1;
|
||||
fin = fopen(name, "r");
|
||||
closefunc = fclose;
|
||||
@ -1231,7 +1330,7 @@ retrieve(char *argv[], const char *name)
|
||||
if (fin == NULL) {
|
||||
if (errno != 0) {
|
||||
perror_reply(550, dispname);
|
||||
if (log)
|
||||
if (dolog)
|
||||
logxfer("get", -1, name, NULL, NULL,
|
||||
strerror(errno));
|
||||
}
|
||||
@ -1268,15 +1367,20 @@ retrieve(char *argv[], const char *name)
|
||||
if (dout == NULL)
|
||||
goto done;
|
||||
|
||||
(void)getrusage(RUSAGE_SELF, &rusage_before);
|
||||
(void)gettimeofday(&start, NULL);
|
||||
sendrv = send_data(fin, dout, st.st_blksize, isdata);
|
||||
sendrv = send_data(fin, dout, &st, isdata);
|
||||
(void)gettimeofday(&finish, NULL);
|
||||
(void)getrusage(RUSAGE_SELF, &rusage_after);
|
||||
closedataconn(dout); /* close now to affect timing stats */
|
||||
timersub(&finish, &start, &td);
|
||||
tdp = &td;
|
||||
done:
|
||||
if (log)
|
||||
if (dolog) {
|
||||
logxfer("get", byte_count, name, NULL, tdp, error);
|
||||
if (tdp != NULL)
|
||||
logrusage(&rusage_before, &rusage_after);
|
||||
}
|
||||
closerv = (*closefunc)(fin);
|
||||
if (sendrv == 0) {
|
||||
FILE *errf;
|
||||
@ -1567,21 +1671,173 @@ closedataconn(FILE *fd)
|
||||
pdata = -1;
|
||||
}
|
||||
|
||||
int
|
||||
write_data(int fd, char *buf, size_t size, off_t *bufrem,
|
||||
struct timeval *then, int isdata)
|
||||
{
|
||||
struct timeval now, td;
|
||||
ssize_t c;
|
||||
|
||||
while (size > 0) {
|
||||
c = size;
|
||||
if (curclass.writesize) {
|
||||
if (curclass.writesize < c)
|
||||
c = curclass.writesize;
|
||||
}
|
||||
if (curclass.rateget) {
|
||||
if (*bufrem < c)
|
||||
c = *bufrem;
|
||||
}
|
||||
(void) alarm(curclass.timeout);
|
||||
c = write(fd, buf, c);
|
||||
if (c <= 0)
|
||||
return (1);
|
||||
buf += c;
|
||||
size -= c;
|
||||
byte_count += c;
|
||||
if (isdata) {
|
||||
total_data_out += c;
|
||||
total_data += c;
|
||||
}
|
||||
total_bytes_out += c;
|
||||
total_bytes += c;
|
||||
if (curclass.rateget) {
|
||||
*bufrem -= c;
|
||||
if (*bufrem == 0) {
|
||||
(void)gettimeofday(&now, NULL);
|
||||
timersub(&now, then, &td);
|
||||
if (td.tv_sec == 0) {
|
||||
usleep(1000000 - td.tv_usec);
|
||||
(void)gettimeofday(then, NULL);
|
||||
} else
|
||||
*then = now;
|
||||
*bufrem = curclass.rateget;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static enum send_status
|
||||
send_data_with_read(int filefd, int netfd, const struct stat *st, int isdata)
|
||||
{
|
||||
struct timeval then;
|
||||
off_t bufrem;
|
||||
size_t readsize;
|
||||
char *buf;
|
||||
int c, error;
|
||||
|
||||
if (curclass.readsize)
|
||||
readsize = curclass.readsize;
|
||||
else
|
||||
readsize = (size_t)st->st_blksize;
|
||||
if ((buf = malloc(readsize)) == NULL) {
|
||||
perror_reply(451, "Local resource failure: malloc");
|
||||
return (SS_NO_TRANSFER);
|
||||
}
|
||||
|
||||
if (curclass.rateget) {
|
||||
bufrem = curclass.rateget;
|
||||
(void)gettimeofday(&then, NULL);
|
||||
}
|
||||
while (1) {
|
||||
(void) alarm(curclass.timeout);
|
||||
c = read(filefd, buf, readsize);
|
||||
if (c == 0)
|
||||
error = SS_SUCCESS;
|
||||
else if (c < 0)
|
||||
error = SS_FILE_ERROR;
|
||||
else if (write_data(netfd, buf, c, &bufrem, &then, isdata))
|
||||
error = SS_DATA_ERROR;
|
||||
else
|
||||
continue;
|
||||
|
||||
free(buf);
|
||||
return (error);
|
||||
}
|
||||
}
|
||||
|
||||
static enum send_status
|
||||
send_data_with_mmap(int filefd, int netfd, const struct stat *st, int isdata)
|
||||
{
|
||||
struct timeval then;
|
||||
off_t bufrem, filesize, off, origoff;
|
||||
size_t mapsize, winsize;
|
||||
int error, sendbufsize, sendlowat;
|
||||
void *win;
|
||||
|
||||
if (curclass.sendbufsize) {
|
||||
sendbufsize = curclass.sendbufsize;
|
||||
if (setsockopt(netfd, SOL_SOCKET, SO_SNDBUF,
|
||||
&sendbufsize, sizeof(int)) == -1)
|
||||
syslog(LOG_WARNING, "setsockopt(SO_SNDBUF, %d): %m",
|
||||
sendbufsize);
|
||||
}
|
||||
|
||||
if (curclass.sendlowat) {
|
||||
sendlowat = curclass.sendlowat;
|
||||
if (setsockopt(netfd, SOL_SOCKET, SO_SNDLOWAT,
|
||||
&sendlowat, sizeof(int)) == -1)
|
||||
syslog(LOG_WARNING, "setsockopt(SO_SNDLOWAT, %d): %m",
|
||||
sendlowat);
|
||||
}
|
||||
|
||||
winsize = curclass.mmapsize;
|
||||
filesize = st->st_size;
|
||||
if (debug)
|
||||
syslog(LOG_INFO, "mmapsize = %ld, writesize = %ld",
|
||||
(long)winsize, (long)curclass.writesize);
|
||||
if (winsize == 0)
|
||||
goto try_read;
|
||||
|
||||
off = lseek(filefd, (off_t)0, SEEK_CUR);
|
||||
if (off == -1)
|
||||
goto try_read;
|
||||
|
||||
origoff = off;
|
||||
if (curclass.rateget) {
|
||||
bufrem = curclass.rateget;
|
||||
(void)gettimeofday(&then, NULL);
|
||||
}
|
||||
while (1) {
|
||||
mapsize = MIN(filesize - off, winsize);
|
||||
if (mapsize == 0)
|
||||
break;
|
||||
win = mmap(NULL, mapsize, PROT_READ,
|
||||
MAP_FILE|MAP_SHARED, filefd, off);
|
||||
if (win == MAP_FAILED) {
|
||||
if (off == origoff)
|
||||
goto try_read;
|
||||
return (SS_FILE_ERROR);
|
||||
}
|
||||
(void) madvise(win, mapsize, MADV_SEQUENTIAL);
|
||||
error = write_data(netfd, win, mapsize, &bufrem, &then,
|
||||
isdata);
|
||||
(void) madvise(win, mapsize, MADV_DONTNEED);
|
||||
munmap(win, mapsize);
|
||||
if (error)
|
||||
return (SS_DATA_ERROR);
|
||||
off += mapsize;
|
||||
}
|
||||
return (SS_SUCCESS);
|
||||
|
||||
try_read:
|
||||
return (send_data_with_read(filefd, netfd, st, isdata));
|
||||
}
|
||||
|
||||
/*
|
||||
* Tranfer the contents of "instr" to "outstr" peer using the appropriate
|
||||
* encapsulation of the data subject * to Mode, Structure, and Type.
|
||||
* encapsulation of the data subject to Mode, Structure, and Type.
|
||||
*
|
||||
* NB: Form isn't handled.
|
||||
*/
|
||||
static int
|
||||
send_data(FILE *instr, FILE *outstr, off_t blksize, int isdata)
|
||||
send_data(FILE *instr, FILE *outstr, const struct stat *st, int isdata)
|
||||
{
|
||||
int c, filefd, netfd, rval;
|
||||
char *buf;
|
||||
|
||||
transflag = 1;
|
||||
rval = -1;
|
||||
buf = NULL;
|
||||
if (setjmp(urgcatch))
|
||||
goto cleanup_send_data;
|
||||
|
||||
@ -1624,66 +1880,22 @@ send_data(FILE *instr, FILE *outstr, off_t blksize, int isdata)
|
||||
|
||||
case TYPE_I:
|
||||
case TYPE_L:
|
||||
if ((buf = malloc((size_t)blksize)) == NULL) {
|
||||
perror_reply(451, "Local resource failure: malloc");
|
||||
goto cleanup_send_data;
|
||||
}
|
||||
filefd = fileno(instr);
|
||||
netfd = fileno(outstr);
|
||||
(void) alarm(curclass.timeout);
|
||||
if (curclass.rateget) {
|
||||
while (1) {
|
||||
int d;
|
||||
struct timeval then, now, td;
|
||||
off_t bufrem;
|
||||
char *bufp;
|
||||
switch (send_data_with_mmap(filefd, netfd, st, isdata)) {
|
||||
|
||||
(void)gettimeofday(&then, NULL);
|
||||
errno = c = d = 0;
|
||||
bufrem = curclass.rateget;
|
||||
while (bufrem > 0) {
|
||||
if ((c = read(filefd, buf,
|
||||
MIN(blksize, bufrem))) <= 0)
|
||||
goto senddone;
|
||||
(void) alarm(curclass.timeout);
|
||||
bufrem -= c;
|
||||
byte_count += c;
|
||||
if (isdata) {
|
||||
total_data_out += c;
|
||||
total_data += c;
|
||||
}
|
||||
total_bytes_out += c;
|
||||
total_bytes += c;
|
||||
for (bufp = buf; c > 0;
|
||||
c -= d, bufp += d)
|
||||
if ((d =
|
||||
write(netfd, bufp, c)) <= 0)
|
||||
case SS_SUCCESS:
|
||||
break;
|
||||
if (d < 0)
|
||||
goto data_err;
|
||||
}
|
||||
(void)gettimeofday(&now, NULL);
|
||||
timersub(&now, &then, &td);
|
||||
if (td.tv_sec == 0)
|
||||
usleep(1000000 - td.tv_usec);
|
||||
}
|
||||
} else {
|
||||
while ((c = read(filefd, buf, (size_t)blksize)) > 0) {
|
||||
if (write(netfd, buf, c) != c)
|
||||
goto data_err;
|
||||
(void) alarm(curclass.timeout);
|
||||
byte_count += c;
|
||||
if (isdata) {
|
||||
total_data_out += c;
|
||||
total_data += c;
|
||||
}
|
||||
total_bytes_out += c;
|
||||
total_bytes += c;
|
||||
}
|
||||
}
|
||||
senddone:
|
||||
if (c < 0)
|
||||
|
||||
case SS_NO_TRANSFER:
|
||||
goto cleanup_send_data;
|
||||
|
||||
case SS_FILE_ERROR:
|
||||
goto file_err;
|
||||
|
||||
case SS_DATA_ERROR:
|
||||
goto data_err;
|
||||
}
|
||||
rval = 0;
|
||||
goto cleanup_send_data;
|
||||
|
||||
@ -1705,8 +1917,6 @@ send_data(FILE *instr, FILE *outstr, off_t blksize, int isdata)
|
||||
cleanup_send_data:
|
||||
(void) alarm(0);
|
||||
transflag = 0;
|
||||
if (buf)
|
||||
free(buf);
|
||||
if (isdata) {
|
||||
total_files_out++;
|
||||
total_files++;
|
||||
@ -2053,13 +2263,14 @@ statcmd(void)
|
||||
reply(0, "Display file: %s", curclass.display);
|
||||
if (! EMPTYSTR(curclass.notify))
|
||||
reply(0, "Notify fileglob: %s", curclass.notify);
|
||||
reply(0, "Idle timeout: %d, maximum timeout: %d",
|
||||
curclass.timeout, curclass.maxtimeout);
|
||||
reply(0, "Idle timeout: " LLF ", maximum timeout: " LLF,
|
||||
(LLT)curclass.timeout, (LLT)curclass.maxtimeout);
|
||||
reply(0, "Current connections: %d", connections);
|
||||
if (curclass.limit == -1)
|
||||
reply(0, "Maximum connections: unlimited");
|
||||
else
|
||||
reply(0, "Maximum connections: %d", curclass.limit);
|
||||
reply(0, "Maximum connections: " LLF,
|
||||
(LLT)curclass.limit);
|
||||
if (curclass.limitfile)
|
||||
reply(0, "Connection limit exceeded message file: %s",
|
||||
conffilename(curclass.limitfile));
|
||||
@ -2096,8 +2307,8 @@ statcmd(void)
|
||||
reply(0, "PASV advertise address: %s", bp);
|
||||
}
|
||||
if (curclass.portmin && curclass.portmax)
|
||||
reply(0, "PASV port range: %d - %d",
|
||||
curclass.portmin, curclass.portmax);
|
||||
reply(0, "PASV port range: " LLF " - " LLF,
|
||||
(LLT)curclass.portmin, (LLT)curclass.portmax);
|
||||
if (curclass.rateget)
|
||||
reply(0, "Rate get limit: " LLF " bytes/sec",
|
||||
(LLT)curclass.rateget);
|
||||
@ -2108,6 +2319,28 @@ statcmd(void)
|
||||
(LLT)curclass.rateput);
|
||||
else
|
||||
reply(0, "Rate put limit: disabled");
|
||||
if (curclass.mmapsize)
|
||||
reply(0, "Mmap size: " LLF, (LLT)curclass.mmapsize);
|
||||
else
|
||||
reply(0, "Mmap size: disabled");
|
||||
if (curclass.readsize)
|
||||
reply(0, "Read size: " LLF, (LLT)curclass.readsize);
|
||||
else
|
||||
reply(0, "Read size: default");
|
||||
if (curclass.writesize)
|
||||
reply(0, "Write size: " LLF, (LLT)curclass.writesize);
|
||||
else
|
||||
reply(0, "Write size: default");
|
||||
if (curclass.sendbufsize)
|
||||
reply(0, "Send buffer size: " LLF,
|
||||
(LLT)curclass.sendbufsize);
|
||||
else
|
||||
reply(0, "Send buffer size: default");
|
||||
if (curclass.sendlowat)
|
||||
reply(0, "Send low water mark: " LLF,
|
||||
(LLT)curclass.sendlowat);
|
||||
else
|
||||
reply(0, "Send low water mark: default");
|
||||
reply(0, "Umask: %.04o", curclass.umask);
|
||||
for (cp = curclass.conversions; cp != NULL; cp=cp->next) {
|
||||
if (cp->suffix == NULL || cp->types == NULL ||
|
||||
@ -2195,14 +2428,8 @@ dologout(int status)
|
||||
* back to the main program loop.
|
||||
*/
|
||||
transflag = 0;
|
||||
|
||||
logout_utmp();
|
||||
if (logged_in) {
|
||||
#ifdef NO_UTMP
|
||||
if (dowtmp)
|
||||
logwtmp(ttyline, "", "");
|
||||
if (doutmp)
|
||||
logout(utmp.ut_line);
|
||||
#endif /* NO_UTMP */
|
||||
#ifdef KERBEROS
|
||||
if (!notickets && krbtkfile_env)
|
||||
unlink(krbtkfile_env);
|
||||
@ -2535,13 +2762,15 @@ extended_port(const char *arg)
|
||||
}
|
||||
|
||||
/* some more sanity checks */
|
||||
errno = 0;
|
||||
p = NULL;
|
||||
(void)strtoul(result[2], &p, 10);
|
||||
if (!*result[2] || *p)
|
||||
if (errno || !*result[2] || *p)
|
||||
goto parsefail;
|
||||
errno = 0;
|
||||
p = NULL;
|
||||
proto = strtoul(result[0], &p, 10);
|
||||
if (!*result[0] || *p)
|
||||
if (errno || !*result[0] || *p)
|
||||
goto protounsupp;
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
@ -2921,6 +3150,31 @@ logxfer(const char *command, off_t bytes, const char *file1, const char *file2,
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Log the resource usage.
|
||||
*
|
||||
* XXX: more resource usage to logging?
|
||||
*/
|
||||
void
|
||||
logrusage(const struct rusage *rusage_before,
|
||||
const struct rusage *rusage_after)
|
||||
{
|
||||
struct timeval usrtime, systime;
|
||||
|
||||
if (logging <= 1)
|
||||
return;
|
||||
|
||||
timersub(&rusage_after->ru_utime, &rusage_before->ru_utime, &usrtime);
|
||||
timersub(&rusage_after->ru_stime, &rusage_before->ru_stime, &systime);
|
||||
syslog(LOG_INFO, "%ld.%.03du %ld.%.03ds %ld+%ldio %ldpf+%ldw",
|
||||
usrtime.tv_sec, (int)(usrtime.tv_usec / 1000),
|
||||
systime.tv_sec, (int)(systime.tv_usec / 1000),
|
||||
rusage_after->ru_inblock - rusage_before->ru_inblock,
|
||||
rusage_after->ru_oublock - rusage_before->ru_oublock,
|
||||
rusage_after->ru_majflt - rusage_before->ru_majflt,
|
||||
rusage_after->ru_nswap - rusage_before->ru_nswap);
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine if `password' is valid for user given in `pw'.
|
||||
* Returns 2 if password expired, 1 if otherwise failed, 0 if ok
|
||||
@ -2930,24 +3184,13 @@ checkpassword(const struct passwd *pwent, const char *password)
|
||||
{
|
||||
char *orig, *new;
|
||||
time_t expire;
|
||||
#if HAVE_GETSPNAM
|
||||
struct spwd *spw;
|
||||
#endif
|
||||
|
||||
expire = 0;
|
||||
if (pwent == NULL)
|
||||
return 1;
|
||||
|
||||
#if HAVE_GETSPNAM
|
||||
if ((spw = getspnam(pwent->pw_name)) == NULL)
|
||||
return 1;
|
||||
orig = spw->sp_pwdp;
|
||||
#else
|
||||
orig = pwent->pw_passwd; /* save existing password */
|
||||
#if HAVE_PW_EXPIRE
|
||||
expire = pwent->pw_expire;
|
||||
#endif
|
||||
#endif /* HAVE_GETSPNAM */
|
||||
|
||||
if (orig[0] == '\0') /* don't allow empty passwords */
|
||||
return 1;
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" $NetBSD: ftpd.conf.5,v 1.19 2002/01/15 02:20:50 wiz Exp $
|
||||
.\" $NetBSD: ftpd.conf.5,v 1.24 2002/11/29 14:40:00 lukem Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1997-2001 The NetBSD Foundation, Inc.
|
||||
.\" All rights reserved.
|
||||
@ -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 5, 2001
|
||||
.Dd November 30, 2002
|
||||
.Dt FTPD.CONF 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -121,8 +121,8 @@ 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
|
||||
.It Sy advertise Ar class Op Ar host
|
||||
.It Sy advertize Ar class Op Ar host
|
||||
Set the address to advertise in the response to the
|
||||
.Sy PASV
|
||||
and
|
||||
@ -137,7 +137,9 @@ If
|
||||
.Ar class
|
||||
is
|
||||
.Dq none
|
||||
or no argument is given, disable this.
|
||||
or
|
||||
.Ar host
|
||||
not is specified, disable this.
|
||||
.It Sy checkportcmd Ar class Op Sy off
|
||||
Check the
|
||||
.Sy PORT
|
||||
@ -150,7 +152,7 @@ command connection, or if the remote TCP port number is less than
|
||||
.Dv IPPORT_RESERVED .
|
||||
It is
|
||||
.Em strongly
|
||||
encouraged that this option be used, espcially for sites concerned
|
||||
encouraged that this option be used, especially for sites concerned
|
||||
with potential security problems with
|
||||
.Tn FTP
|
||||
bounce attacks.
|
||||
@ -160,11 +162,11 @@ is
|
||||
.Dq none
|
||||
or
|
||||
.Sy off
|
||||
is given, disable this feature, otherwise enable it.
|
||||
is specified, disable this feature, otherwise enable it.
|
||||
.It Sy chroot Ar class Op Sy pathformat
|
||||
If
|
||||
.Ar pathformat
|
||||
is not given or
|
||||
is not specified or
|
||||
.Ar class
|
||||
is
|
||||
.Dq none ,
|
||||
@ -199,7 +201,7 @@ The user's home directory.
|
||||
.It Sy GUEST
|
||||
If
|
||||
.Fl a Ar anondir
|
||||
is given, use
|
||||
is specified, use
|
||||
.Ar anondir ,
|
||||
otherwise the home directory of the
|
||||
.Sq ftp
|
||||
@ -285,11 +287,11 @@ is
|
||||
.Dq none
|
||||
or
|
||||
.Sy off
|
||||
is given, disable this feature, otherwise enable it.
|
||||
is specified, disable this feature, otherwise enable it.
|
||||
.It Sy display Ar class Op Ar file
|
||||
If
|
||||
.Ar file
|
||||
is not given or
|
||||
is not specified or
|
||||
.Ar class
|
||||
is
|
||||
.Dq none ,
|
||||
@ -305,7 +307,7 @@ for more information.
|
||||
.It Sy homedir Ar class Op Sy pathformat
|
||||
If
|
||||
.Ar pathformat
|
||||
is not given or
|
||||
is not specified or
|
||||
.Ar class
|
||||
is
|
||||
.Dq none ,
|
||||
@ -331,18 +333,18 @@ and
|
||||
.Sy CHROOT
|
||||
users.
|
||||
.It Xo Sy limit Ar class
|
||||
.Ar count Op Ar file
|
||||
.Op Ar count Op Ar file
|
||||
.Xc
|
||||
Limit the maximum number of concurrent connections for
|
||||
.Ar class
|
||||
to
|
||||
.Ar count ,
|
||||
with
|
||||
.Sq 0
|
||||
.Sq \-1
|
||||
meaning unlimited connections.
|
||||
If the limit is exceeded and
|
||||
.Ar file
|
||||
is given, display its contents to the user.
|
||||
is specified, display its contents to the user.
|
||||
If
|
||||
.Ar class
|
||||
is
|
||||
@ -356,15 +358,20 @@ is a relative path, it will be searched for in
|
||||
.Pa /etc
|
||||
(which can be overridden with
|
||||
.Fl c Ar confdir ) .
|
||||
.It Sy maxfilesize Ar class Ar size
|
||||
.It Sy maxfilesize Ar class Op Ar size
|
||||
Set the maximum size of an uploaded file to
|
||||
.Ar size .
|
||||
.Ar size ,
|
||||
with
|
||||
.Sq \-1
|
||||
meaning unlimited connections.
|
||||
If
|
||||
.Ar class
|
||||
is
|
||||
.Dq none
|
||||
or no argument is given, disable this.
|
||||
.It Sy maxtimeout Ar class Ar time
|
||||
or
|
||||
.Ar size
|
||||
is not specified, disable this.
|
||||
.It Sy maxtimeout Ar class Op Ar time
|
||||
Set the maximum timeout period that a client may request,
|
||||
defaulting to two hours.
|
||||
This cannot be less than 30 seconds, or the value for
|
||||
@ -375,7 +382,26 @@ is
|
||||
.Dq none
|
||||
or
|
||||
.Ar time
|
||||
is not specified, set to default of 2 hours.
|
||||
is not specified, use the default.
|
||||
.It Sy mmapsize Ar class Op Ar size
|
||||
Set the size of the sliding window to map a file using
|
||||
.Xr mmap 2 .
|
||||
If zero,
|
||||
.Xr ftpd 8
|
||||
will use
|
||||
.Xr read 2
|
||||
instead.
|
||||
The default is zero.
|
||||
An optional suffix may be provided as per
|
||||
.Sy rateget .
|
||||
This option affects only binary transfers.
|
||||
If
|
||||
.Ar class
|
||||
is
|
||||
.Dq none
|
||||
or
|
||||
.Ar size
|
||||
is not specified, use the default.
|
||||
.It Sy modify Ar class Op Sy off
|
||||
If
|
||||
.Ar class
|
||||
@ -383,7 +409,7 @@ is
|
||||
.Dq none
|
||||
or
|
||||
.Sy off
|
||||
is given, disable the following commands:
|
||||
is specified, disable the following commands:
|
||||
.Sy CHMOD ,
|
||||
.Sy DELE ,
|
||||
.Sy MKD ,
|
||||
@ -395,7 +421,7 @@ Otherwise, enable them.
|
||||
.It Sy motd Ar class Op Ar file
|
||||
If
|
||||
.Ar file
|
||||
is not given or
|
||||
is not specified or
|
||||
.Ar class
|
||||
is
|
||||
.Dq none ,
|
||||
@ -417,7 +443,7 @@ is a relative path, it will be searched for in
|
||||
.It Sy notify Ar class Op Ar fileglob
|
||||
If
|
||||
.Ar fileglob
|
||||
is not given or
|
||||
is not specified or
|
||||
.Ar class
|
||||
is
|
||||
.Dq none ,
|
||||
@ -432,14 +458,16 @@ is
|
||||
.Dq none
|
||||
or
|
||||
.Sy off
|
||||
is given, prevent passive
|
||||
is specified, prevent passive
|
||||
.Sy ( PASV ,
|
||||
.Sy LPSV ,
|
||||
and
|
||||
.Sy EPSV )
|
||||
connections.
|
||||
Otherwise, enable them.
|
||||
.It Sy portrange Ar class Ar min Ar max
|
||||
.It Sy portrange Ar class Oo
|
||||
.Ar min Ar max
|
||||
.Oc
|
||||
Set the range of port number which will be used for the passive data port.
|
||||
.Ar max
|
||||
must be greater than
|
||||
@ -451,7 +479,7 @@ If
|
||||
.Ar class
|
||||
is
|
||||
.Dq none
|
||||
or no arguments are given, disable this.
|
||||
or no arguments are specified, disable this.
|
||||
.It Sy private Ar class Op Sy off
|
||||
If
|
||||
.Ar class
|
||||
@ -459,11 +487,11 @@ is
|
||||
.Dq none
|
||||
or
|
||||
.Sy off
|
||||
is given, do not display class information in the output of the
|
||||
is specified, do not display class information in the output of the
|
||||
.Sy STAT
|
||||
command.
|
||||
Otherwise, display the information.
|
||||
.It Sy rateget Ar class Ar rate
|
||||
.It Sy rateget Ar class Op Ar rate
|
||||
Set the maximum get
|
||||
.Pq Sy RETR
|
||||
transfer rate throttle for
|
||||
@ -478,14 +506,17 @@ If
|
||||
.Ar class
|
||||
is
|
||||
.Dq none
|
||||
or no arguments are given, disable this.
|
||||
or
|
||||
.Ar rate
|
||||
is not specified, disable this.
|
||||
.Pp
|
||||
An optional suffix may be provided, which changes the intrepretation of
|
||||
An optional suffix may be provided, which changes the interpretation of
|
||||
.Ar rate
|
||||
as follows:
|
||||
.Bl -tag -width 3n -offset indent -compact
|
||||
.It b
|
||||
Causes no modification. (Default; optional)
|
||||
Causes no modification.
|
||||
(Default; optional)
|
||||
.It k
|
||||
Kilo; multiply the argument by 1024
|
||||
.It m
|
||||
@ -495,7 +526,7 @@ Giga; multiply the argument by 1073741824
|
||||
.It t
|
||||
Tera; multiply the argument by 1099511627776
|
||||
.El
|
||||
.It Sy rateput Ar class Ar rate
|
||||
.It Sy rateput Ar class Op Ar rate
|
||||
Set the maximum put
|
||||
.Pq Sy STOR
|
||||
transfer rate throttle for
|
||||
@ -509,7 +540,24 @@ If
|
||||
.Ar class
|
||||
is
|
||||
.Dq none
|
||||
or no arguments are given, disable this.
|
||||
or
|
||||
.Ar rate
|
||||
is not specified, disable this.
|
||||
.It Sy readsize Ar class Op Ar size
|
||||
Set the size of the read buffer to
|
||||
.Xr read 2
|
||||
a file.
|
||||
The default is the file system block size.
|
||||
An optional suffix may be provided as per
|
||||
.Sy rateget .
|
||||
This option affects only binary transfers.
|
||||
If
|
||||
.Ar class
|
||||
is
|
||||
.Dq none
|
||||
or
|
||||
.Ar size
|
||||
is not specified, use the default.
|
||||
.It Sy sanenames Ar class Op Sy off
|
||||
If
|
||||
.Ar class
|
||||
@ -517,12 +565,38 @@ is
|
||||
.Dq none
|
||||
or
|
||||
.Sy off
|
||||
is given, allow uploaded file names to contain any characters valid for a
|
||||
is specified, allow uploaded file names to contain any characters valid for a
|
||||
file name.
|
||||
Otherwise, only permit file names which don't start with a
|
||||
.Sq \&.
|
||||
and only comprise of characters from the set
|
||||
.Dq [-+,._A-Za-z0-9] .
|
||||
.It Sy sendbufsize Ar class Op Ar size
|
||||
Set the size of the socket send buffer.
|
||||
An optional suffix may be provided as per
|
||||
.Sy rateget .
|
||||
The default is zero and the system default value will be used.
|
||||
This option affects only binary transfers.
|
||||
If
|
||||
.Ar class
|
||||
is
|
||||
.Dq none
|
||||
or
|
||||
.Ar size
|
||||
is not specified, use the default.
|
||||
.It Sy sendlowat Ar class Op Ar size
|
||||
Set the low water mark of socket send buffer.
|
||||
An optional suffix may be provided as per
|
||||
.Sy rateget .
|
||||
The default is zero and system default value will be used.
|
||||
This option affects only for binary transfer.
|
||||
If
|
||||
.Ar class
|
||||
is
|
||||
.Dq none
|
||||
or
|
||||
.Ar size
|
||||
is not specified, use the default.
|
||||
.It Sy template Ar class Op Ar refclass
|
||||
Define
|
||||
.Ar refclass
|
||||
@ -540,9 +614,9 @@ duplication.
|
||||
There can be only one template defined at a time.
|
||||
If
|
||||
.Ar refclass
|
||||
is not given, disable the template for
|
||||
is not specified, disable the template for
|
||||
.Ar class .
|
||||
.It Sy timeout Ar class Ar time
|
||||
.It Sy timeout Ar class Op Ar time
|
||||
Set the inactivity timeout period.
|
||||
(the default is fifteen minutes).
|
||||
This cannot be less than 30 seconds, or greater than the value for
|
||||
@ -553,8 +627,8 @@ is
|
||||
.Dq none
|
||||
or
|
||||
.Ar time
|
||||
is not specified, set to the default of 15 minutes.
|
||||
.It Sy umask Ar class Ar umaskval
|
||||
is not specified, use the default.
|
||||
.It Sy umask Ar class Op Ar umaskval
|
||||
Set the umask to
|
||||
.Ar umaskval .
|
||||
If
|
||||
@ -572,7 +646,7 @@ is
|
||||
.Dq none
|
||||
or
|
||||
.Sy off
|
||||
is given, disable the following commands:
|
||||
is specified, disable the following commands:
|
||||
.Sy APPE ,
|
||||
.Sy STOR ,
|
||||
and
|
||||
@ -586,6 +660,25 @@ as well as the modify commands:
|
||||
and
|
||||
.Sy UMASK .
|
||||
Otherwise, enable them.
|
||||
.It Sy writesize Ar class Op Ar size
|
||||
Limit the number of bytes to
|
||||
.Xr write 2
|
||||
at a time.
|
||||
The default is zero, which means all the data available as a result of
|
||||
.Xr mmap 2
|
||||
or
|
||||
.Xr read 2
|
||||
will be written at a time.
|
||||
An optional suffix may be provided as per
|
||||
.Sy rateget .
|
||||
This option affects only binary transfers.
|
||||
If
|
||||
.Ar class
|
||||
is
|
||||
.Dq none
|
||||
or
|
||||
.Ar size
|
||||
is not specified, use the default.
|
||||
.El
|
||||
.Sh DEFAULTS
|
||||
The following defaults are used:
|
||||
@ -596,7 +689,7 @@ classtype chroot CHROOT
|
||||
classtype guest GUEST
|
||||
classtype real REAL
|
||||
display none
|
||||
limit all -1 # unlimited connections
|
||||
limit all \-1 # unlimited connections
|
||||
maxtimeout all 7200 # 2 hours
|
||||
modify all
|
||||
motd all motd
|
||||
@ -618,6 +711,7 @@ A sample
|
||||
file.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr strsuftoll 3 ,
|
||||
.Xr ftpchroot 5 ,
|
||||
.Xr ftpusers 5 ,
|
||||
.Xr ftpd 8
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" $NetBSD: ftpusers.5,v 1.13 2001/12/01 16:24:24 wiz Exp $
|
||||
.\" $NetBSD: ftpusers.5,v 1.12 2001/12/01 10:16:06 lukem Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1997-2001 The NetBSD Foundation, Inc.
|
||||
.\" All rights reserved.
|
||||
|
@ -32,7 +32,16 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "lukemftpd.h"
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ttyent.h>
|
||||
#include <unistd.h>
|
||||
#include <utmp.h>
|
||||
#include <util.h>
|
||||
|
||||
typedef struct utmp UTMP;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: logwtmp.c,v 1.16 2001/02/04 22:04:12 christos Exp $ */
|
||||
/* $NetBSD: logwtmp.c,v 1.17 2002/09/12 08:55:31 itojun Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1993
|
||||
@ -34,7 +34,34 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "lukemftpd.h"
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)logwtmp.c 8.1 (Berkeley) 6/4/93";
|
||||
#else
|
||||
__RCSID("$NetBSD: logwtmp.c,v 1.17 2002/09/12 08:55:31 itojun Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <setjmp.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <utmp.h>
|
||||
#include <util.h>
|
||||
|
||||
#ifdef KERBEROS5
|
||||
#include <krb5/krb5.h>
|
||||
#endif
|
||||
|
||||
#include "extern.h"
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: pathnames.h,v 1.10 2000/03/06 21:42:26 lukem Exp $ */
|
||||
/* $NetBSD: pathnames.h,v 1.9 2000/01/08 11:09:56 lukem Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
@ -35,6 +35,8 @@
|
||||
* @(#)pathnames.h 8.1 (Berkeley) 6/4/93
|
||||
*/
|
||||
|
||||
#include <paths.h>
|
||||
|
||||
#ifndef _DEFAULT_CONFDIR
|
||||
#define _DEFAULT_CONFDIR "/etc"
|
||||
#endif
|
||||
@ -42,7 +44,6 @@
|
||||
#define _PATH_FTPCHROOT "ftpchroot"
|
||||
#define _PATH_FTPDCONF "ftpd.conf"
|
||||
#define _PATH_FTPLOGINMESG "motd"
|
||||
#undef _PATH_FTPUSERS
|
||||
#define _PATH_FTPUSERS "ftpusers"
|
||||
#define _PATH_FTPWELCOME "ftpwelcome"
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: popen.c,v 1.27 2001/12/01 10:25:30 lukem Exp $ */
|
||||
/* $NetBSD: popen.c,v 1.26 2001/04/25 01:46:26 lukem Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999-2001 The NetBSD Foundation, Inc.
|
||||
@ -73,7 +73,33 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "lukemftpd.h"
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)popen.c 8.3 (Berkeley) 4/6/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: popen.c,v 1.26 2001/04/25 01:46:26 lukem Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <glob.h>
|
||||
#include <setjmp.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stringlist.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef KERBEROS5
|
||||
#include <krb5/krb5.h>
|
||||
#endif
|
||||
|
||||
#include "extern.h"
|
||||
|
||||
@ -146,11 +172,7 @@ ftpd_popen(char *argv[], const char *ptype, int stderrfd)
|
||||
isls = (strcmp(sl->sl_str[0], INTERNAL_LS) == 0);
|
||||
#endif
|
||||
|
||||
#if HAVE_VFORK
|
||||
pid = isls ? fork() : vfork();
|
||||
#else
|
||||
pid = fork();
|
||||
#endif
|
||||
switch (pid) {
|
||||
case -1: /* error */
|
||||
(void)close(pdes[0]);
|
||||
@ -177,10 +199,7 @@ ftpd_popen(char *argv[], const char *ptype, int stderrfd)
|
||||
}
|
||||
#ifndef NO_INTERNAL_LS
|
||||
if (isls) { /* use internal ls */
|
||||
#if HAVE_OPTRESET
|
||||
optreset = 1;
|
||||
#endif
|
||||
optind = optopt = 1;
|
||||
optreset = optind = optopt = 1;
|
||||
closelog();
|
||||
exit(ls_main(sl->sl_cur - 1, sl->sl_str));
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* $NetBSD: version.h,v 1.42 2002/02/13 15:15:23 lukem Exp $ */
|
||||
/* $NetBSD: version.h,v 1.48 2002/10/26 04:19:56 lukem Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 1999-2001 The NetBSD Foundation, Inc.
|
||||
* Copyright (c) 1999-2002 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
@ -36,5 +36,5 @@
|
||||
*/
|
||||
|
||||
#ifndef FTPD_VERSION
|
||||
#define FTPD_VERSION "NetBSD-ftpd 20020214"
|
||||
#define FTPD_VERSION "NetBSD-ftpd 20021130"
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user