- new ftpd.conf directives:
maxfilesize set the maximum size of uploaded files sanenames if set, only permit uploaded filenames that contain characters from the set "-+,._A-Za-z0-9" and that don't start with `.' - new/changed command line options: -e emailaddr define email address for %E (see below) -P dataport use dataport as the dataport (instead of ctrlport-1) -q use pid files to count users [default] -Q don't use pid files to count users -u write entries to utmp -U don't write entries to utmp [default] -w write entries to wtmp [default] -W don't write entries to wtmp NOTE: -U used to mean `write utmp entries'. Its meaning has changed so that it's orthogonal with -q/-Q and -w/-W. This isn't considered a major problem, because using -U isn't going to enable something you don't want, but will disable something you did want (which is safer). - new display file escape sequences: %E email address %s literal `s' if the previous %M or %N wasn't ``1''. %S literal `S' if the previous %M or %N wasn't ``1''. - expand the description of building ~ftp/incoming to cover the appropriate ftpd.conf(5) directives (which are defaults, but it pays to explicitly explain them) - replace strsuftoi() with strsuftoll(), which returns a long long if supported, otherwise a long - rework the way that check_modify and check_upload are done in the yacc parser; they're merged into a common check_write() function which is called explicitly - merge all ftpclass `flag variables' into a single bitfield-based flag element - move various common bits of parse_conf() into a couple of macros - clean up some comments
This commit is contained in:
parent
3f648dea6e
commit
999fd3d617
@ -1,4 +1,4 @@
|
|||||||
/* $NetBSD: cmds.c,v 1.7 2000/11/15 02:32:30 lukem Exp $ */
|
/* $NetBSD: cmds.c,v 1.8 2000/11/16 13:15:13 lukem Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999-2000 The NetBSD Foundation, Inc.
|
* Copyright (c) 1999-2000 The NetBSD Foundation, Inc.
|
||||||
@ -101,7 +101,7 @@
|
|||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
__RCSID("$NetBSD: cmds.c,v 1.7 2000/11/15 02:32:30 lukem Exp $");
|
__RCSID("$NetBSD: cmds.c,v 1.8 2000/11/16 13:15:13 lukem Exp $");
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
@ -602,7 +602,7 @@ fact_perm(const char *fact, FILE *fd, factelem *fe)
|
|||||||
* since we only need this info in such a case.
|
* since we only need this info in such a case.
|
||||||
*/
|
*/
|
||||||
pdir = fe->pdirstat;
|
pdir = fe->pdirstat;
|
||||||
if (pdir == NULL && curclass.modify) {
|
if (pdir == NULL && CURCLASS_FLAGS_ISSET(modify)) {
|
||||||
size_t len;
|
size_t len;
|
||||||
char realdir[MAXPATHLEN], *p;
|
char realdir[MAXPATHLEN], *p;
|
||||||
struct stat dir;
|
struct stat dir;
|
||||||
@ -636,15 +636,15 @@ fact_perm(const char *fact, FILE *fd, factelem *fe)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 'a': can APPE to file */
|
/* 'a': can APPE to file */
|
||||||
if (wok && curclass.upload && S_ISREG(fe->stat->st_mode))
|
if (wok && CURCLASS_FLAGS_ISSET(upload) && S_ISREG(fe->stat->st_mode))
|
||||||
CPUTC('a', fd);
|
CPUTC('a', fd);
|
||||||
|
|
||||||
/* 'c': can create or append to files in directory */
|
/* 'c': can create or append to files in directory */
|
||||||
if (wok && curclass.modify && S_ISDIR(fe->stat->st_mode))
|
if (wok && CURCLASS_FLAGS_ISSET(modify) && S_ISDIR(fe->stat->st_mode))
|
||||||
CPUTC('c', fd);
|
CPUTC('c', fd);
|
||||||
|
|
||||||
/* 'd': can delete file or directory */
|
/* 'd': can delete file or directory */
|
||||||
if (pdirwok && curclass.modify) {
|
if (pdirwok && CURCLASS_FLAGS_ISSET(modify)) {
|
||||||
int candel;
|
int candel;
|
||||||
|
|
||||||
candel = 1;
|
candel = 1;
|
||||||
@ -674,7 +674,7 @@ fact_perm(const char *fact, FILE *fd, factelem *fe)
|
|||||||
CPUTC('e', fd);
|
CPUTC('e', fd);
|
||||||
|
|
||||||
/* 'f': can rename file or directory */
|
/* 'f': can rename file or directory */
|
||||||
if (pdirwok && curclass.modify)
|
if (pdirwok && CURCLASS_FLAGS_ISSET(modify))
|
||||||
CPUTC('f', fd);
|
CPUTC('f', fd);
|
||||||
|
|
||||||
/* 'l': can list directory */
|
/* 'l': can list directory */
|
||||||
@ -682,11 +682,11 @@ fact_perm(const char *fact, FILE *fd, factelem *fe)
|
|||||||
CPUTC('l', fd);
|
CPUTC('l', fd);
|
||||||
|
|
||||||
/* 'm': can create directory */
|
/* 'm': can create directory */
|
||||||
if (wok && curclass.modify && S_ISDIR(fe->stat->st_mode))
|
if (wok && CURCLASS_FLAGS_ISSET(modify) && S_ISDIR(fe->stat->st_mode))
|
||||||
CPUTC('m', fd);
|
CPUTC('m', fd);
|
||||||
|
|
||||||
/* 'p': can remove files in directory */
|
/* 'p': can remove files in directory */
|
||||||
if (wok && curclass.modify && S_ISDIR(fe->stat->st_mode))
|
if (wok && CURCLASS_FLAGS_ISSET(modify) && S_ISDIR(fe->stat->st_mode))
|
||||||
CPUTC('p', fd);
|
CPUTC('p', fd);
|
||||||
|
|
||||||
/* 'r': can RETR file */
|
/* 'r': can RETR file */
|
||||||
@ -694,7 +694,7 @@ fact_perm(const char *fact, FILE *fd, factelem *fe)
|
|||||||
CPUTC('r', fd);
|
CPUTC('r', fd);
|
||||||
|
|
||||||
/* 'w': can STOR file */
|
/* 'w': can STOR file */
|
||||||
if (wok && curclass.upload && S_ISREG(fe->stat->st_mode))
|
if (wok && CURCLASS_FLAGS_ISSET(upload) && S_ISREG(fe->stat->st_mode))
|
||||||
CPUTC('w', fd);
|
CPUTC('w', fd);
|
||||||
|
|
||||||
CPUTC(';', fd);
|
CPUTC(';', fd);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $NetBSD: conf.c,v 1.35 2000/11/15 02:32:30 lukem Exp $ */
|
/* $NetBSD: conf.c,v 1.36 2000/11/16 13:15:13 lukem Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1997-2000 The NetBSD Foundation, Inc.
|
* Copyright (c) 1997-2000 The NetBSD Foundation, Inc.
|
||||||
@ -38,7 +38,7 @@
|
|||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
__RCSID("$NetBSD: conf.c,v 1.35 2000/11/15 02:32:30 lukem Exp $");
|
__RCSID("$NetBSD: conf.c,v 1.36 2000/11/16 13:15:13 lukem Exp $");
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
@ -88,7 +88,6 @@ init_curclass(void)
|
|||||||
free(conv);
|
free(conv);
|
||||||
}
|
}
|
||||||
|
|
||||||
curclass.checkportcmd = 1;
|
|
||||||
REASSIGN(curclass.chroot, NULL);
|
REASSIGN(curclass.chroot, NULL);
|
||||||
REASSIGN(curclass.classname, NULL);
|
REASSIGN(curclass.classname, NULL);
|
||||||
curclass.conversions = NULL;
|
curclass.conversions = NULL;
|
||||||
@ -96,13 +95,12 @@ init_curclass(void)
|
|||||||
REASSIGN(curclass.homedir, NULL);
|
REASSIGN(curclass.homedir, NULL);
|
||||||
curclass.limit = -1; /* unlimited connections */
|
curclass.limit = -1; /* unlimited connections */
|
||||||
REASSIGN(curclass.limitfile, NULL);
|
REASSIGN(curclass.limitfile, NULL);
|
||||||
|
curclass.maxfilesize = -1; /* unlimited file size */
|
||||||
curclass.maxrateget = 0;
|
curclass.maxrateget = 0;
|
||||||
curclass.maxrateput = 0;
|
curclass.maxrateput = 0;
|
||||||
curclass.maxtimeout = 7200; /* 2 hours */
|
curclass.maxtimeout = 7200; /* 2 hours */
|
||||||
curclass.modify = 1;
|
|
||||||
REASSIGN(curclass.motd, xstrdup(_PATH_FTPLOGINMESG));
|
REASSIGN(curclass.motd, xstrdup(_PATH_FTPLOGINMESG));
|
||||||
REASSIGN(curclass.notify, NULL);
|
REASSIGN(curclass.notify, NULL);
|
||||||
curclass.passive = 1;
|
|
||||||
curclass.portmin = 0;
|
curclass.portmin = 0;
|
||||||
curclass.portmax = 0;
|
curclass.portmax = 0;
|
||||||
curclass.rateget = 0;
|
curclass.rateget = 0;
|
||||||
@ -110,7 +108,12 @@ init_curclass(void)
|
|||||||
curclass.timeout = 900; /* 15 minutes */
|
curclass.timeout = 900; /* 15 minutes */
|
||||||
/* curclass.type is set elsewhere */
|
/* curclass.type is set elsewhere */
|
||||||
curclass.umask = 027;
|
curclass.umask = 027;
|
||||||
curclass.upload = 1;
|
|
||||||
|
CURCLASS_FLAGS_SET(checkportcmd);
|
||||||
|
CURCLASS_FLAGS_SET(modify);
|
||||||
|
CURCLASS_FLAGS_SET(passive);
|
||||||
|
CURCLASS_FLAGS_CLR(sanenames);
|
||||||
|
CURCLASS_FLAGS_SET(upload);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -123,7 +126,8 @@ parse_conf(const char *findclass)
|
|||||||
FILE *f;
|
FILE *f;
|
||||||
char *buf, *p;
|
char *buf, *p;
|
||||||
size_t len;
|
size_t len;
|
||||||
int none, match, rate;
|
LLT llval;
|
||||||
|
int none, match;
|
||||||
char *endp;
|
char *endp;
|
||||||
char *class, *word, *arg, *template;
|
char *class, *word, *arg, *template;
|
||||||
const char *infile;
|
const char *infile;
|
||||||
@ -134,7 +138,7 @@ parse_conf(const char *findclass)
|
|||||||
init_curclass();
|
init_curclass();
|
||||||
REASSIGN(curclass.classname, xstrdup(findclass));
|
REASSIGN(curclass.classname, xstrdup(findclass));
|
||||||
if (strcasecmp(findclass, "guest") == 0) {
|
if (strcasecmp(findclass, "guest") == 0) {
|
||||||
curclass.modify = 0;
|
CURCLASS_FLAGS_CLR(modify);
|
||||||
curclass.umask = 0707;
|
curclass.umask = 0707;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,19 +174,29 @@ parse_conf(const char *findclass)
|
|||||||
strcasecmp(class, "all") == 0) )
|
strcasecmp(class, "all") == 0) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
#define CONF_FLAG(x) \
|
||||||
|
do { \
|
||||||
|
if (none || \
|
||||||
|
(!EMPTYSTR(arg) && strcasecmp(arg, "off") == 0)) \
|
||||||
|
CURCLASS_FLAGS_CLR(x); \
|
||||||
|
else \
|
||||||
|
CURCLASS_FLAGS_SET(x); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define CONF_STRING(x) \
|
||||||
|
do { \
|
||||||
|
if (none || EMPTYSTR(arg)) \
|
||||||
|
arg = NULL; \
|
||||||
|
else \
|
||||||
|
arg = xstrdup(arg); \
|
||||||
|
REASSIGN(curclass.x, arg); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
if (strcasecmp(word, "checkportcmd") == 0) {
|
if (strcasecmp(word, "checkportcmd") == 0) {
|
||||||
if (none ||
|
CONF_FLAG(checkportcmd);
|
||||||
(!EMPTYSTR(arg) && strcasecmp(arg, "off") == 0))
|
|
||||||
curclass.checkportcmd = 0;
|
|
||||||
else
|
|
||||||
curclass.checkportcmd = 1;
|
|
||||||
|
|
||||||
} else if (strcasecmp(word, "chroot") == 0) {
|
} else if (strcasecmp(word, "chroot") == 0) {
|
||||||
if (none || EMPTYSTR(arg))
|
CONF_STRING(chroot);
|
||||||
arg = NULL;
|
|
||||||
else
|
|
||||||
arg = xstrdup(arg);
|
|
||||||
REASSIGN(curclass.chroot, arg);
|
|
||||||
|
|
||||||
} else if (strcasecmp(word, "classtype") == 0) {
|
} else if (strcasecmp(word, "classtype") == 0) {
|
||||||
if (!none && !EMPTYSTR(arg)) {
|
if (!none && !EMPTYSTR(arg)) {
|
||||||
@ -253,18 +267,22 @@ parse_conf(const char *findclass)
|
|||||||
REASSIGN(conv->command, convcmd);
|
REASSIGN(conv->command, convcmd);
|
||||||
|
|
||||||
} else if (strcasecmp(word, "display") == 0) {
|
} else if (strcasecmp(word, "display") == 0) {
|
||||||
if (none || EMPTYSTR(arg))
|
CONF_STRING(display);
|
||||||
arg = NULL;
|
|
||||||
else
|
|
||||||
arg = xstrdup(arg);
|
|
||||||
REASSIGN(curclass.display, arg);
|
|
||||||
|
|
||||||
} else if (strcasecmp(word, "homedir") == 0) {
|
} else if (strcasecmp(word, "homedir") == 0) {
|
||||||
|
CONF_STRING(homedir);
|
||||||
|
|
||||||
|
} else if (strcasecmp(word, "maxfilesize") == 0) {
|
||||||
if (none || EMPTYSTR(arg))
|
if (none || EMPTYSTR(arg))
|
||||||
arg = NULL;
|
continue;
|
||||||
else
|
llval = strsuftoll(arg);
|
||||||
arg = xstrdup(arg);
|
if (llval == -1) {
|
||||||
REASSIGN(curclass.homedir, arg);
|
syslog(LOG_WARNING,
|
||||||
|
"%s line %d: invalid maxfilesize %s",
|
||||||
|
infile, (int)line, arg);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
curclass.maxfilesize = llval;
|
||||||
|
|
||||||
} else if (strcasecmp(word, "limit") == 0) {
|
} else if (strcasecmp(word, "limit") == 0) {
|
||||||
int limit;
|
int limit;
|
||||||
@ -308,33 +326,16 @@ parse_conf(const char *findclass)
|
|||||||
curclass.maxtimeout = timeout;
|
curclass.maxtimeout = timeout;
|
||||||
|
|
||||||
} else if (strcasecmp(word, "modify") == 0) {
|
} else if (strcasecmp(word, "modify") == 0) {
|
||||||
if (none ||
|
CONF_FLAG(modify);
|
||||||
(!EMPTYSTR(arg) && strcasecmp(arg, "off") == 0))
|
|
||||||
curclass.modify = 0;
|
|
||||||
else
|
|
||||||
curclass.modify = 1;
|
|
||||||
|
|
||||||
} else if (strcasecmp(word, "motd") == 0) {
|
} else if (strcasecmp(word, "motd") == 0) {
|
||||||
if (none || EMPTYSTR(arg))
|
CONF_STRING(motd);
|
||||||
arg = NULL;
|
|
||||||
else
|
|
||||||
arg = xstrdup(arg);
|
|
||||||
REASSIGN(curclass.motd, arg);
|
|
||||||
|
|
||||||
|
|
||||||
} else if (strcasecmp(word, "notify") == 0) {
|
} else if (strcasecmp(word, "notify") == 0) {
|
||||||
if (none || EMPTYSTR(arg))
|
CONF_STRING(notify);
|
||||||
arg = NULL;
|
|
||||||
else
|
|
||||||
arg = xstrdup(arg);
|
|
||||||
REASSIGN(curclass.notify, arg);
|
|
||||||
|
|
||||||
} else if (strcasecmp(word, "passive") == 0) {
|
} else if (strcasecmp(word, "passive") == 0) {
|
||||||
if (none ||
|
CONF_FLAG(passive);
|
||||||
(!EMPTYSTR(arg) && strcasecmp(arg, "off") == 0))
|
|
||||||
curclass.passive = 0;
|
|
||||||
else
|
|
||||||
curclass.passive = 1;
|
|
||||||
|
|
||||||
} else if (strcasecmp(word, "portrange") == 0) {
|
} else if (strcasecmp(word, "portrange") == 0) {
|
||||||
int minport, maxport;
|
int minport, maxport;
|
||||||
@ -383,28 +384,31 @@ parse_conf(const char *findclass)
|
|||||||
} else if (strcasecmp(word, "rateget") == 0) {
|
} else if (strcasecmp(word, "rateget") == 0) {
|
||||||
if (none || EMPTYSTR(arg))
|
if (none || EMPTYSTR(arg))
|
||||||
continue;
|
continue;
|
||||||
rate = strsuftoi(arg);
|
llval = strsuftoll(arg);
|
||||||
if (rate == -1) {
|
if (llval == -1) {
|
||||||
syslog(LOG_WARNING,
|
syslog(LOG_WARNING,
|
||||||
"%s line %d: invalid rateget %s",
|
"%s line %d: invalid rateget %s",
|
||||||
infile, (int)line, arg);
|
infile, (int)line, arg);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
curclass.maxrateget = rate;
|
curclass.maxrateget = llval;
|
||||||
curclass.rateget = rate;
|
curclass.rateget = llval;
|
||||||
|
|
||||||
} else if (strcasecmp(word, "rateput") == 0) {
|
} else if (strcasecmp(word, "rateput") == 0) {
|
||||||
if (none || EMPTYSTR(arg))
|
if (none || EMPTYSTR(arg))
|
||||||
continue;
|
continue;
|
||||||
rate = strsuftoi(arg);
|
llval = strsuftoll(arg);
|
||||||
if (rate == -1) {
|
if (llval == -1) {
|
||||||
syslog(LOG_WARNING,
|
syslog(LOG_WARNING,
|
||||||
"%s line %d: invalid rateput %s",
|
"%s line %d: invalid rateput %s",
|
||||||
infile, (int)line, arg);
|
infile, (int)line, arg);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
curclass.maxrateput = rate;
|
curclass.maxrateput = llval;
|
||||||
curclass.rateput = rate;
|
curclass.rateput = llval;
|
||||||
|
|
||||||
|
} else if (strcasecmp(word, "sanenames") == 0) {
|
||||||
|
CONF_FLAG(sanenames);
|
||||||
|
|
||||||
} else if (strcasecmp(word, "timeout") == 0) {
|
} else if (strcasecmp(word, "timeout") == 0) {
|
||||||
if (none || EMPTYSTR(arg))
|
if (none || EMPTYSTR(arg))
|
||||||
@ -451,12 +455,9 @@ parse_conf(const char *findclass)
|
|||||||
curclass.umask = umask;
|
curclass.umask = umask;
|
||||||
|
|
||||||
} else if (strcasecmp(word, "upload") == 0) {
|
} else if (strcasecmp(word, "upload") == 0) {
|
||||||
if (none ||
|
CONF_FLAG(upload);
|
||||||
(!EMPTYSTR(arg) && strcasecmp(arg, "off") == 0)) {
|
if (! CURCLASS_FLAGS_ISSET(upload))
|
||||||
curclass.modify = 0;
|
CURCLASS_FLAGS_CLR(modify);
|
||||||
curclass.upload = 0;
|
|
||||||
} else
|
|
||||||
curclass.upload = 1;
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
syslog(LOG_WARNING,
|
syslog(LOG_WARNING,
|
||||||
@ -547,8 +548,10 @@ display_file(const char *file, int code)
|
|||||||
FILE *f;
|
FILE *f;
|
||||||
char *buf, *p, *cwd;
|
char *buf, *p, *cwd;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
off_t lastnum;
|
||||||
time_t now;
|
time_t now;
|
||||||
|
|
||||||
|
lastnum = 0;
|
||||||
if (quietmessages)
|
if (quietmessages)
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
@ -587,7 +590,9 @@ display_file(const char *file, int code)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'E':
|
case 'E':
|
||||||
/* XXXX email address */
|
if (! EMPTYSTR(emailaddr))
|
||||||
|
cprintf(stdout, "%s",
|
||||||
|
emailaddr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'L':
|
case 'L':
|
||||||
@ -595,23 +600,35 @@ display_file(const char *file, int code)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'M':
|
case 'M':
|
||||||
if (curclass.limit == -1)
|
if (curclass.limit == -1) {
|
||||||
cprintf(stdout, "unlimited");
|
cprintf(stdout, "unlimited");
|
||||||
else
|
lastnum = 0;
|
||||||
|
} else {
|
||||||
cprintf(stdout, "%d",
|
cprintf(stdout, "%d",
|
||||||
curclass.limit);
|
curclass.limit);
|
||||||
|
lastnum = curclass.limit;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'N':
|
case 'N':
|
||||||
if (connections > 0)
|
cprintf(stdout, "%d", connections);
|
||||||
cprintf(stdout, "%d",
|
lastnum = connections;
|
||||||
connections);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'R':
|
case 'R':
|
||||||
cprintf(stdout, "%s", remotehost);
|
cprintf(stdout, "%s", remotehost);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 's':
|
||||||
|
if (lastnum != 1)
|
||||||
|
cprintf(stdout, "s");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'S':
|
||||||
|
if (lastnum != 1)
|
||||||
|
cprintf(stdout, "S");
|
||||||
|
break;
|
||||||
|
|
||||||
case 'T':
|
case 'T':
|
||||||
now = time(NULL);
|
now = time(NULL);
|
||||||
cprintf(stdout, "%.24s", ctime(&now));
|
cprintf(stdout, "%.24s", ctime(&now));
|
||||||
@ -810,19 +827,19 @@ do_conversion(const char *fname)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert the string `arg' to an int, which may have an optional SI suffix
|
* Convert the string `arg' to a long long, which may have an optional SI suffix
|
||||||
* (`b', `k', `m', `g'). Returns the number for success, -1 otherwise.
|
* (`b', `k', `m', `g', `t'). Returns the number for success, -1 otherwise.
|
||||||
*/
|
*/
|
||||||
int
|
LLT
|
||||||
strsuftoi(const char *arg)
|
strsuftoll(const char *arg)
|
||||||
{
|
{
|
||||||
char *cp;
|
char *cp;
|
||||||
long val;
|
LLT val;
|
||||||
|
|
||||||
if (!isdigit((unsigned char)arg[0]))
|
if (!isdigit((unsigned char)arg[0]))
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
val = strtol(arg, &cp, 10);
|
val = STRTOLL(arg, &cp, 10);
|
||||||
if (cp != NULL) {
|
if (cp != NULL) {
|
||||||
if (cp[0] != '\0' && cp[1] != '\0')
|
if (cp[0] != '\0' && cp[1] != '\0')
|
||||||
return (-1);
|
return (-1);
|
||||||
@ -839,11 +856,14 @@ strsuftoi(const char *arg)
|
|||||||
case 'g':
|
case 'g':
|
||||||
val <<= 30;
|
val <<= 30;
|
||||||
break;
|
break;
|
||||||
|
case 't':
|
||||||
|
val <<= 40;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (val < 0 || val > INT_MAX)
|
if (val < 0)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
return (val);
|
return (val);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $NetBSD: extern.h,v 1.34 2000/11/15 02:32:30 lukem Exp $ */
|
/* $NetBSD: extern.h,v 1.35 2000/11/16 13:15:13 lukem Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1992, 1993
|
* Copyright (c) 1992, 1993
|
||||||
@ -100,6 +100,24 @@
|
|||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef NO_LONG_LONG
|
||||||
|
# define LLF "%ld"
|
||||||
|
# define LLFP(x) "%" x "ld"
|
||||||
|
# define LLT long
|
||||||
|
# define ULLF "%lu"
|
||||||
|
# define ULLFP(x) "%" x "lu"
|
||||||
|
# define ULLT unsigned long
|
||||||
|
# define STRTOLL(x,y,z) strtol(x,y,z)
|
||||||
|
#else
|
||||||
|
# define LLF "%lld"
|
||||||
|
# define LLFP(x) "%" x "lld"
|
||||||
|
# define LLT long long
|
||||||
|
# define ULLF "%llu"
|
||||||
|
# define ULLFP(x) "%" x "llu"
|
||||||
|
# define ULLT unsigned long long
|
||||||
|
# define STRTOLL(x,y,z) strtoll(x,y,z)
|
||||||
|
#endif
|
||||||
|
|
||||||
void blkfree(char **);
|
void blkfree(char **);
|
||||||
void closedataconn(FILE *);
|
void closedataconn(FILE *);
|
||||||
char *conffilename(const char *);
|
char *conffilename(const char *);
|
||||||
@ -152,17 +170,11 @@ void sizecmd(const char *);
|
|||||||
void statcmd(void);
|
void statcmd(void);
|
||||||
void statfilecmd(const char *);
|
void statfilecmd(const char *);
|
||||||
void store(const char *, const char *, int);
|
void store(const char *, const char *, int);
|
||||||
int strsuftoi(const char *);
|
LLT strsuftoll(const char *);
|
||||||
void user(const char *);
|
void user(const char *);
|
||||||
char *xstrdup(const char *);
|
char *xstrdup(const char *);
|
||||||
void yyerror(char *);
|
void yyerror(char *);
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
CLASS_GUEST,
|
|
||||||
CLASS_CHROOT,
|
|
||||||
CLASS_REAL
|
|
||||||
} class_ft;
|
|
||||||
|
|
||||||
struct tab {
|
struct tab {
|
||||||
char *name;
|
char *name;
|
||||||
short token;
|
short token;
|
||||||
@ -180,32 +192,48 @@ struct ftpconv {
|
|||||||
char *command; /* Command to do the conversion */
|
char *command; /* Command to do the conversion */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CLASS_GUEST,
|
||||||
|
CLASS_CHROOT,
|
||||||
|
CLASS_REAL
|
||||||
|
} class_ft;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FLAG_checkportcmd = 1<<0, /* Check port commands */
|
||||||
|
FLAG_modify = 1<<1, /* 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
|
||||||
|
APPE, STOR, STOU */
|
||||||
|
} classflag_t;
|
||||||
|
|
||||||
|
#define CURCLASS_FLAGS_SET(x) (curclass.flags |= (FLAG_ ## x))
|
||||||
|
#define CURCLASS_FLAGS_CLR(x) (curclass.flags &= ~(FLAG_ ## x))
|
||||||
|
#define CURCLASS_FLAGS_ISSET(x) (curclass.flags & (FLAG_ ## x))
|
||||||
|
|
||||||
struct ftpclass {
|
struct ftpclass {
|
||||||
int checkportcmd; /* Check PORT commands are valid */
|
|
||||||
char *chroot; /* Directory to chroot(2) to at login */
|
char *chroot; /* Directory to chroot(2) to at login */
|
||||||
char *classname; /* Current class */
|
char *classname; /* Current class */
|
||||||
struct ftpconv *conversions; /* List of conversions */
|
struct ftpconv *conversions; /* List of conversions */
|
||||||
char *display; /* Files to display upon chdir */
|
char *display; /* File to display upon chdir */
|
||||||
char *homedir; /* Directory to chdir(2) to at login */
|
char *homedir; /* Directory to chdir(2) to at login */
|
||||||
|
classflag_t flags; /* Flags; see classflag_t above */
|
||||||
int limit; /* Max connections (-1 = unlimited) */
|
int limit; /* Max connections (-1 = unlimited) */
|
||||||
char *limitfile; /* File to display if limit reached */
|
char *limitfile; /* File to display if limit reached */
|
||||||
int maxrateget; /* Maximum get transfer rate throttle */
|
LLT maxfilesize; /* Maximum file size of uploads */
|
||||||
int maxrateput; /* Maximum put transfer rate throttle */
|
LLT maxrateget; /* Maximum get transfer rate throttle */
|
||||||
|
LLT maxrateput; /* Maximum put transfer rate throttle */
|
||||||
unsigned int maxtimeout; /* Maximum permitted timeout */
|
unsigned int maxtimeout; /* Maximum permitted timeout */
|
||||||
int modify; /* Allow CHMOD, DELE, MKD, RMD, RNFR,
|
|
||||||
UMASK */
|
|
||||||
char *motd; /* MotD file to display after login */
|
char *motd; /* MotD file to display after login */
|
||||||
char *notify; /* Files to notify about upon chdir */
|
char *notify; /* Files to notify about upon chdir */
|
||||||
int passive; /* Allow PASV mode */
|
|
||||||
int portmin; /* Minumum port for passive mode */
|
int portmin; /* Minumum port for passive mode */
|
||||||
int portmax; /* Maximum port for passive mode */
|
int portmax; /* Maximum port for passive mode */
|
||||||
int rateget; /* Get (RETR) transfer rate throttle */
|
LLT rateget; /* Get (RETR) transfer rate throttle */
|
||||||
int rateput; /* Put (STOR) transfer rate throttle */
|
LLT rateput; /* Put (STOR) transfer rate throttle */
|
||||||
unsigned int timeout; /* Default timeout */
|
unsigned int timeout; /* Default timeout */
|
||||||
class_ft type; /* Class type */
|
class_ft type; /* Class type */
|
||||||
mode_t umask; /* Umask to use */
|
mode_t umask; /* Umask to use */
|
||||||
int upload; /* As per modify, but also allow
|
|
||||||
APPE, STOR, STOU */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
@ -255,6 +283,7 @@ GLOBAL int connections;
|
|||||||
GLOBAL struct ftpclass curclass;
|
GLOBAL struct ftpclass curclass;
|
||||||
GLOBAL int debug;
|
GLOBAL int debug;
|
||||||
GLOBAL jmp_buf errcatch;
|
GLOBAL jmp_buf errcatch;
|
||||||
|
GLOBAL char *emailaddr;
|
||||||
GLOBAL int form;
|
GLOBAL int form;
|
||||||
GLOBAL int gidcount; /* number of entries in gidlist[] */
|
GLOBAL int gidcount; /* number of entries in gidlist[] */
|
||||||
GLOBAL gid_t gidlist[NGROUPS_MAX];
|
GLOBAL gid_t gidlist[NGROUPS_MAX];
|
||||||
@ -319,21 +348,3 @@ extern struct tab cmdtab[];
|
|||||||
#ifndef IPPORT_ANONMAX
|
#ifndef IPPORT_ANONMAX
|
||||||
# define IPPORT_ANONMAX 65535
|
# define IPPORT_ANONMAX 65535
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef NO_LONG_LONG
|
|
||||||
# define LLF "%ld"
|
|
||||||
# define LLFP(x) "%" x "ld"
|
|
||||||
# define LLT long
|
|
||||||
# define ULLF "%lu"
|
|
||||||
# define ULLFP(x) "%" x "lu"
|
|
||||||
# define ULLT unsigned long
|
|
||||||
# define STRTOLL(x,y,z) strtol(x,y,z)
|
|
||||||
#else
|
|
||||||
# define LLF "%lld"
|
|
||||||
# define LLFP(x) "%" x "lld"
|
|
||||||
# define LLT long long
|
|
||||||
# define ULLF "%llu"
|
|
||||||
# define ULLFP(x) "%" x "llu"
|
|
||||||
# define ULLT unsigned long long
|
|
||||||
# define STRTOLL(x,y,z) strtoll(x,y,z)
|
|
||||||
#endif
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $NetBSD: ftpcmd.y,v 1.55 2000/11/15 02:32:30 lukem Exp $ */
|
/* $NetBSD: ftpcmd.y,v 1.56 2000/11/16 13:15:14 lukem Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1997-2000 The NetBSD Foundation, Inc.
|
* Copyright (c) 1997-2000 The NetBSD Foundation, Inc.
|
||||||
@ -83,7 +83,7 @@
|
|||||||
#if 0
|
#if 0
|
||||||
static char sccsid[] = "@(#)ftpcmd.y 8.3 (Berkeley) 4/6/94";
|
static char sccsid[] = "@(#)ftpcmd.y 8.3 (Berkeley) 4/6/94";
|
||||||
#else
|
#else
|
||||||
__RCSID("$NetBSD: ftpcmd.y,v 1.55 2000/11/15 02:32:30 lukem Exp $");
|
__RCSID("$NetBSD: ftpcmd.y,v 1.56 2000/11/16 13:15:14 lukem Exp $");
|
||||||
#endif
|
#endif
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
|
||||||
@ -165,7 +165,7 @@ char *fromname;
|
|||||||
%token <s> ALL
|
%token <s> ALL
|
||||||
%token <i> NUMBER
|
%token <i> NUMBER
|
||||||
|
|
||||||
%type <i> check_login check_modify check_upload octal_number byte_size
|
%type <i> check_login octal_number byte_size
|
||||||
%type <i> struct_code mode_code type_code form_code decimal_integer
|
%type <i> struct_code mode_code type_code form_code decimal_integer
|
||||||
%type <s> pathstring pathname password username
|
%type <s> pathstring pathname password username
|
||||||
%type <s> mechanism_name base64data prot_code
|
%type <s> mechanism_name base64data prot_code
|
||||||
@ -282,7 +282,7 @@ cmd
|
|||||||
| PASV check_login CRLF
|
| PASV check_login CRLF
|
||||||
{
|
{
|
||||||
if ($2) {
|
if ($2) {
|
||||||
if (curclass.passive)
|
if (CURCLASS_FLAGS_ISSET(passive))
|
||||||
passive();
|
passive();
|
||||||
else
|
else
|
||||||
reply(500, "PASV mode not available.");
|
reply(500, "PASV mode not available.");
|
||||||
@ -398,28 +398,28 @@ cmd
|
|||||||
free($4);
|
free($4);
|
||||||
}
|
}
|
||||||
|
|
||||||
| STOR check_upload SP pathname CRLF
|
| STOR SP pathname CRLF
|
||||||
{
|
{
|
||||||
if ($2 && $4 != NULL)
|
if (check_write($3, 1))
|
||||||
store($4, "w", 0);
|
store($3, "w", 0);
|
||||||
if ($4 != NULL)
|
if ($3 != NULL)
|
||||||
free($4);
|
free($3);
|
||||||
}
|
}
|
||||||
|
|
||||||
| STOU check_upload SP pathname CRLF
|
| STOU SP pathname CRLF
|
||||||
{
|
{
|
||||||
if ($2 && $4 != NULL)
|
if (check_write($3, 1))
|
||||||
store($4, "w", 1);
|
store($3, "w", 1);
|
||||||
if ($4 != NULL)
|
if ($3 != NULL)
|
||||||
free($4);
|
free($3);
|
||||||
}
|
}
|
||||||
|
|
||||||
| APPE check_upload SP pathname CRLF
|
| APPE SP pathname CRLF
|
||||||
{
|
{
|
||||||
if ($2 && $4 != NULL)
|
if (check_write($3, 1))
|
||||||
store($4, "a", 0);
|
store($3, "a", 0);
|
||||||
if ($4 != NULL)
|
if ($3 != NULL)
|
||||||
free($4);
|
free($3);
|
||||||
}
|
}
|
||||||
|
|
||||||
| ALLO check_login SP NUMBER CRLF
|
| ALLO check_login SP NUMBER CRLF
|
||||||
@ -434,18 +434,19 @@ cmd
|
|||||||
reply(202, "ALLO command ignored.");
|
reply(202, "ALLO command ignored.");
|
||||||
}
|
}
|
||||||
|
|
||||||
| RNTO check_login SP pathname CRLF
|
| RNTO SP pathname CRLF
|
||||||
{
|
{
|
||||||
if ($2) {
|
if (check_write($3, 0)) {
|
||||||
if (fromname) {
|
if (fromname) {
|
||||||
renamecmd(fromname, $4);
|
renamecmd(fromname, $3);
|
||||||
free(fromname);
|
free(fromname);
|
||||||
fromname = NULL;
|
fromname = NULL;
|
||||||
} else {
|
} else {
|
||||||
reply(503, "Bad sequence of commands.");
|
reply(503, "Bad sequence of commands.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free($4);
|
if ($3 != NULL)
|
||||||
|
free($3);
|
||||||
}
|
}
|
||||||
|
|
||||||
| ABOR check_login CRLF
|
| ABOR check_login CRLF
|
||||||
@ -454,28 +455,28 @@ cmd
|
|||||||
reply(225, "ABOR command successful.");
|
reply(225, "ABOR command successful.");
|
||||||
}
|
}
|
||||||
|
|
||||||
| DELE check_modify SP pathname CRLF
|
| DELE SP pathname CRLF
|
||||||
{
|
{
|
||||||
if ($2 && $4 != NULL)
|
if (check_write($3, 0))
|
||||||
delete($4);
|
delete($3);
|
||||||
if ($4 != NULL)
|
if ($3 != NULL)
|
||||||
free($4);
|
free($3);
|
||||||
}
|
}
|
||||||
|
|
||||||
| RMD check_modify SP pathname CRLF
|
| RMD SP pathname CRLF
|
||||||
{
|
{
|
||||||
if ($2 && $4 != NULL)
|
if (check_write($3, 0))
|
||||||
removedir($4);
|
removedir($3);
|
||||||
if ($4 != NULL)
|
if ($3 != NULL)
|
||||||
free($4);
|
free($3);
|
||||||
}
|
}
|
||||||
|
|
||||||
| MKD check_modify SP pathname CRLF
|
| MKD SP pathname CRLF
|
||||||
{
|
{
|
||||||
if ($2 && $4 != NULL)
|
if (check_write($3, 0))
|
||||||
makedir($4);
|
makedir($3);
|
||||||
if ($4 != NULL)
|
if ($3 != NULL)
|
||||||
free($4);
|
free($3);
|
||||||
}
|
}
|
||||||
|
|
||||||
| PWD check_login CRLF
|
| PWD check_login CRLF
|
||||||
@ -522,19 +523,19 @@ cmd
|
|||||||
help(sitetab, NULL);
|
help(sitetab, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
| SITE SP CHMOD check_modify SP octal_number SP pathname CRLF
|
| SITE SP CHMOD SP octal_number SP pathname CRLF
|
||||||
{
|
{
|
||||||
if ($4 && ($8 != NULL)) {
|
if (check_write($7, 0)) {
|
||||||
if ($6 > 0777)
|
if ($5 > 0777)
|
||||||
reply(501,
|
reply(501,
|
||||||
"CHMOD: Mode value must be between 0 and 0777");
|
"CHMOD: Mode value must be between 0 and 0777");
|
||||||
else if (chmod($8, $6) < 0)
|
else if (chmod($7, $5) < 0)
|
||||||
perror_reply(550, $8);
|
perror_reply(550, $7);
|
||||||
else
|
else
|
||||||
reply(200, "CHMOD command successful.");
|
reply(200, "CHMOD command successful.");
|
||||||
}
|
}
|
||||||
if ($8 != NULL)
|
if ($7 != NULL)
|
||||||
free($8);
|
free($7);
|
||||||
}
|
}
|
||||||
|
|
||||||
| SITE SP HELP SP STRING CRLF
|
| SITE SP HELP SP STRING CRLF
|
||||||
@ -572,30 +573,32 @@ cmd
|
|||||||
| SITE SP RATEGET check_login CRLF
|
| SITE SP RATEGET check_login CRLF
|
||||||
{
|
{
|
||||||
if ($4) {
|
if ($4) {
|
||||||
reply(200, "Current RATEGET is %d bytes/sec",
|
reply(200,
|
||||||
curclass.rateget);
|
"Current RATEGET is " LLF " bytes/sec",
|
||||||
|
(LLT)curclass.rateget);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
| SITE SP RATEGET check_login SP STRING CRLF
|
| SITE SP RATEGET check_login SP STRING CRLF
|
||||||
{
|
{
|
||||||
char *p = $6;
|
char *p = $6;
|
||||||
int rate;
|
LLT rate;
|
||||||
|
|
||||||
if ($4) {
|
if ($4) {
|
||||||
rate = strsuftoi(p);
|
rate = strsuftoll(p);
|
||||||
if (rate == -1)
|
if (rate == -1)
|
||||||
reply(501, "Invalid RATEGET %s", p);
|
reply(501, "Invalid RATEGET %s", p);
|
||||||
else if (curclass.maxrateget &&
|
else if (curclass.maxrateget &&
|
||||||
rate > curclass.maxrateget)
|
rate > curclass.maxrateget)
|
||||||
reply(501,
|
reply(501,
|
||||||
"RATEGET %d is larger than maximum RATEGET %d",
|
"RATEGET " LLF " is larger than maximum RATEGET " LLF,
|
||||||
rate, curclass.maxrateget);
|
(LLT)rate,
|
||||||
|
(LLT)curclass.maxrateget);
|
||||||
else {
|
else {
|
||||||
curclass.rateget = rate;
|
curclass.rateget = rate;
|
||||||
reply(200,
|
reply(200,
|
||||||
"RATEGET set to %d bytes/sec",
|
"RATEGET set to " LLF " bytes/sec",
|
||||||
curclass.rateget);
|
(LLT)curclass.rateget);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free($6);
|
free($6);
|
||||||
@ -604,30 +607,32 @@ cmd
|
|||||||
| SITE SP RATEPUT check_login CRLF
|
| SITE SP RATEPUT check_login CRLF
|
||||||
{
|
{
|
||||||
if ($4) {
|
if ($4) {
|
||||||
reply(200, "Current RATEPUT is %d bytes/sec",
|
reply(200,
|
||||||
curclass.rateput);
|
"Current RATEPUT is " LLF " bytes/sec",
|
||||||
|
(LLT)curclass.rateput);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
| SITE SP RATEPUT check_login SP STRING CRLF
|
| SITE SP RATEPUT check_login SP STRING CRLF
|
||||||
{
|
{
|
||||||
char *p = $6;
|
char *p = $6;
|
||||||
int rate;
|
LLT rate;
|
||||||
|
|
||||||
if ($4) {
|
if ($4) {
|
||||||
rate = strsuftoi(p);
|
rate = strsuftoll(p);
|
||||||
if (rate == -1)
|
if (rate == -1)
|
||||||
reply(501, "Invalid RATEPUT %s", p);
|
reply(501, "Invalid RATEPUT %s", p);
|
||||||
else if (curclass.maxrateput &&
|
else if (curclass.maxrateput &&
|
||||||
rate > curclass.maxrateput)
|
rate > curclass.maxrateput)
|
||||||
reply(501,
|
reply(501,
|
||||||
"RATEPUT %d is larger than maximum RATEPUT %d",
|
"RATEPUT " LLF " is larger than maximum RATEPUT " LLF,
|
||||||
rate, curclass.maxrateput);
|
(LLT)rate,
|
||||||
|
(LLT)curclass.maxrateput);
|
||||||
else {
|
else {
|
||||||
curclass.rateput = rate;
|
curclass.rateput = rate;
|
||||||
reply(200,
|
reply(200,
|
||||||
"RATEPUT set to %d bytes/sec",
|
"RATEPUT set to " LLF " bytes/sec",
|
||||||
curclass.rateput);
|
(LLT)curclass.rateput);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free($6);
|
free($6);
|
||||||
@ -644,11 +649,11 @@ cmd
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
| SITE SP UMASK check_modify SP octal_number CRLF
|
| SITE SP UMASK check_login SP octal_number CRLF
|
||||||
{
|
{
|
||||||
int oldmask;
|
int oldmask;
|
||||||
|
|
||||||
if ($4) {
|
if ($4 && CURCLASS_FLAGS_ISSET(modify)) {
|
||||||
if (($6 == -1) || ($6 > 0777)) {
|
if (($6 == -1) || ($6 > 0777)) {
|
||||||
reply(501, "Bad UMASK value");
|
reply(501, "Bad UMASK value");
|
||||||
} else {
|
} else {
|
||||||
@ -854,21 +859,20 @@ rcmd
|
|||||||
{
|
{
|
||||||
if ($2) {
|
if ($2) {
|
||||||
fromname = NULL;
|
fromname = NULL;
|
||||||
restart_point = $4; /* XXX $3 is only "int" */
|
restart_point = $4; /* XXX $4 is only "int" */
|
||||||
reply(350,
|
reply(350,
|
||||||
"Restarting at " LLF ". Send STORE or RETRIEVE to initiate transfer.",
|
"Restarting at " LLF ". Send STORE or RETRIEVE to initiate transfer.",
|
||||||
(LLT)restart_point);
|
(LLT)restart_point);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
| RNFR check_modify SP pathname CRLF
|
| RNFR SP pathname CRLF
|
||||||
{
|
{
|
||||||
restart_point = (off_t) 0;
|
restart_point = (off_t) 0;
|
||||||
if ($2 && $4) {
|
if (check_write($3, 0))
|
||||||
fromname = renamefrom($4);
|
fromname = renamefrom($3);
|
||||||
}
|
if ($3 != NULL)
|
||||||
if ($4)
|
free($3);
|
||||||
free($4);
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -1151,45 +1155,6 @@ check_login
|
|||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
check_modify
|
|
||||||
: /* empty */
|
|
||||||
{
|
|
||||||
if (logged_in) {
|
|
||||||
if (curclass.modify)
|
|
||||||
$$ = 1;
|
|
||||||
else {
|
|
||||||
reply(502,
|
|
||||||
"No permission to use this command.");
|
|
||||||
$$ = 0;
|
|
||||||
hasyyerrored = 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
reply(530, "Please login with USER and PASS.");
|
|
||||||
$$ = 0;
|
|
||||||
hasyyerrored = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
check_upload
|
|
||||||
: /* empty */
|
|
||||||
{
|
|
||||||
if (logged_in) {
|
|
||||||
if (curclass.upload)
|
|
||||||
$$ = 1;
|
|
||||||
else {
|
|
||||||
reply(502,
|
|
||||||
"No permission to use this command.");
|
|
||||||
$$ = 0;
|
|
||||||
hasyyerrored = 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
reply(530, "Please login with USER and PASS.");
|
|
||||||
$$ = 0;
|
|
||||||
hasyyerrored = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
#define CMD 0 /* beginning of command */
|
#define CMD 0 /* beginning of command */
|
||||||
@ -1290,13 +1255,55 @@ struct tab sitetab[] = {
|
|||||||
{ NULL, 0, 0, 0, NULL }
|
{ NULL, 0, 0, 0, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
static void help(struct tab *, const char *);
|
static int check_write(const char *, int);
|
||||||
static void port_check(const char *, int);
|
static void help(struct tab *, const char *);
|
||||||
static void toolong(int);
|
static void port_check(const char *, int);
|
||||||
static int yylex(void);
|
static void toolong(int);
|
||||||
|
static int yylex(void);
|
||||||
|
|
||||||
extern int epsvall;
|
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'.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
check_write(const char *file, int isupload)
|
||||||
|
{
|
||||||
|
if (file == NULL)
|
||||||
|
return (0);
|
||||||
|
if (! logged_in) {
|
||||||
|
reply(530, "Please login with USER and PASS.");
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
/* checking modify */
|
||||||
|
if (! isupload && ! CURCLASS_FLAGS_ISSET(modify)) {
|
||||||
|
reply(502, "No permission to use this command.");
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
/* checking upload */
|
||||||
|
if (isupload && ! CURCLASS_FLAGS_ISSET(upload)) {
|
||||||
|
reply(502, "No permission to use this command.");
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
/* checking sanenames */
|
||||||
|
if (CURCLASS_FLAGS_ISSET(sanenames)) {
|
||||||
|
const char *p;
|
||||||
|
|
||||||
|
if (file[0] == '.')
|
||||||
|
goto insane_name;
|
||||||
|
for (p = file; *p; p++) {
|
||||||
|
if (isalnum(*p) || *p == '-' || *p == '+' ||
|
||||||
|
*p == ',' || *p == '.' || *p == '_')
|
||||||
|
continue;
|
||||||
|
insane_name:
|
||||||
|
reply(553, "File name `%s' not allowed.", file);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
struct tab *
|
struct tab *
|
||||||
lookup(struct tab *p, const char *cmd)
|
lookup(struct tab *p, const char *cmd)
|
||||||
{
|
{
|
||||||
@ -1750,7 +1757,7 @@ port_check(const char *cmd, int family)
|
|||||||
goto port_check_fail;
|
goto port_check_fail;
|
||||||
|
|
||||||
/* be paranoid, if told so */
|
/* be paranoid, if told so */
|
||||||
if (curclass.checkportcmd) {
|
if (CURCLASS_FLAGS_ISSET(checkportcmd)) {
|
||||||
if ((ntohs(data_dest.su_port) < IPPORT_RESERVED) ||
|
if ((ntohs(data_dest.su_port) < IPPORT_RESERVED) ||
|
||||||
(data_dest.su_len != his_addr.su_len))
|
(data_dest.su_len != his_addr.su_len))
|
||||||
goto port_check_fail;
|
goto port_check_fail;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
.\" $NetBSD: ftpd.8,v 1.60 2000/07/28 12:54:01 lukem Exp $
|
.\" $NetBSD: ftpd.8,v 1.61 2000/11/16 13:15:14 lukem Exp $
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright (c) 1997-2000 The NetBSD Foundation, Inc.
|
.\" Copyright (c) 1997-2000 The NetBSD Foundation, Inc.
|
||||||
.\" All rights reserved.
|
.\" All rights reserved.
|
||||||
@ -67,7 +67,7 @@
|
|||||||
.\"
|
.\"
|
||||||
.\" @(#)ftpd.8 8.2 (Berkeley) 4/19/94
|
.\" @(#)ftpd.8 8.2 (Berkeley) 4/19/94
|
||||||
.\"
|
.\"
|
||||||
.Dd July 26, 2000
|
.Dd November 16, 2000
|
||||||
.Dt FTPD 8
|
.Dt FTPD 8
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -76,11 +76,13 @@
|
|||||||
Internet File Transfer Protocol server
|
Internet File Transfer Protocol server
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm
|
.Nm
|
||||||
.Op Fl dHlrsUW
|
.Op Fl dHlqQrsuUwW
|
||||||
.Op Fl a Ar anondir
|
.Op Fl a Ar anondir
|
||||||
.Op Fl c Ar confdir
|
.Op Fl c Ar confdir
|
||||||
.Op Fl C Ar user
|
.Op Fl C Ar user
|
||||||
|
.Op Fl e Ar emailaddr
|
||||||
.Op Fl h Ar hostname
|
.Op Fl h Ar hostname
|
||||||
|
.Op Fl P Ar dataport
|
||||||
.Op Fl V Ar version
|
.Op Fl V Ar version
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
.Nm
|
.Nm
|
||||||
@ -119,6 +121,13 @@ This can be useful for testing configurations.
|
|||||||
.It Fl d
|
.It Fl d
|
||||||
Debugging information is written to the syslog using
|
Debugging information is written to the syslog using
|
||||||
.Dv LOG_FTP .
|
.Dv LOG_FTP .
|
||||||
|
.It Fl e Ar emailaddr
|
||||||
|
Use
|
||||||
|
.Ar emailaddr
|
||||||
|
for the
|
||||||
|
.Dq "\&%E"
|
||||||
|
escape sequence (see
|
||||||
|
.Sx Display file escape sequences )
|
||||||
.It Fl h Ar hostname
|
.It Fl h Ar hostname
|
||||||
Explicitly set the hostname to advertise as to
|
Explicitly set the hostname to advertise as to
|
||||||
.Ar hostname .
|
.Ar hostname .
|
||||||
@ -149,7 +158,24 @@ session is logged using syslog with a facility of
|
|||||||
.Dv LOG_FTP .
|
.Dv LOG_FTP .
|
||||||
If this option is specified twice, the retrieve (get), store (put), append,
|
If this option is specified twice, the retrieve (get), store (put), append,
|
||||||
delete, make directory, remove directory and rename operations and
|
delete, make directory, remove directory and rename operations and
|
||||||
their filename arguments are also logged.
|
their file name arguments are also logged.
|
||||||
|
.It Fl P Ar dataport
|
||||||
|
Use
|
||||||
|
.Ar dataport
|
||||||
|
as the data port, overriding the default of using the port one less
|
||||||
|
that the port
|
||||||
|
.Nm
|
||||||
|
is listening on.
|
||||||
|
.It Fl q
|
||||||
|
Enable the use of pid files for keeping track of the number of logged-in
|
||||||
|
users per class.
|
||||||
|
This is the default.
|
||||||
|
.It Fl Q
|
||||||
|
Disable the use of pid files for keeping track of the number of logged-in
|
||||||
|
users per class.
|
||||||
|
This may reduce the load on heavily loaded
|
||||||
|
.Tn FTP
|
||||||
|
servers.
|
||||||
.It Fl r
|
.It Fl r
|
||||||
Permanently drop root privileges once the user is logged in.
|
Permanently drop root privileges once the user is logged in.
|
||||||
The use of this option may result in the server using a port other
|
The use of this option may result in the server using a port other
|
||||||
@ -163,13 +189,19 @@ See
|
|||||||
below for more details.
|
below for more details.
|
||||||
.It Fl s
|
.It Fl s
|
||||||
Require a secure authentication mechanism like Kerberos or S/Key to be used.
|
Require a secure authentication mechanism like Kerberos or S/Key to be used.
|
||||||
.It Fl U
|
.It Fl u
|
||||||
Each concurrent
|
Log each concurrent
|
||||||
.Tn FTP
|
.Tn FTP
|
||||||
session is logged to the file
|
session to
|
||||||
.Pa /var/run/utmp ,
|
.Pa /var/run/utmp ,
|
||||||
making them visible to commands such as
|
making them visible to commands such as
|
||||||
.Xr who 1 .
|
.Xr who 1 .
|
||||||
|
.It Fl U
|
||||||
|
Don't log each concurrent
|
||||||
|
.Tn FTP
|
||||||
|
session to
|
||||||
|
.Pa /var/run/utmp .
|
||||||
|
This is the default.
|
||||||
.It Fl V Ar version
|
.It Fl V Ar version
|
||||||
Use
|
Use
|
||||||
.Ar version
|
.Ar version
|
||||||
@ -183,14 +215,19 @@ If
|
|||||||
is empty or
|
is empty or
|
||||||
.Sq -
|
.Sq -
|
||||||
then don't display any version information.
|
then don't display any version information.
|
||||||
.It Fl W
|
.It Fl w
|
||||||
By default each
|
Log each
|
||||||
.Tn FTP
|
.Tn FTP
|
||||||
session is logged to
|
session to
|
||||||
.Pa /var/log/wtmp ,
|
.Pa /var/log/wtmp ,
|
||||||
making them visible to commands such as
|
making them visible to commands such as
|
||||||
.Xr last 1 .
|
.Xr last 1 .
|
||||||
This option prevents that from occurring.
|
This is the default.
|
||||||
|
.It Fl W
|
||||||
|
Don't log each
|
||||||
|
.Tn FTP
|
||||||
|
session to
|
||||||
|
.Pa /var/log/wtmp .
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
The file
|
The file
|
||||||
@ -443,6 +480,9 @@ The supported escape strings are:
|
|||||||
Class name.
|
Class name.
|
||||||
.It "\&%C"
|
.It "\&%C"
|
||||||
Current working directory.
|
Current working directory.
|
||||||
|
.It "\&%E"
|
||||||
|
Email address given with
|
||||||
|
.Fl e .
|
||||||
.It "\&%L"
|
.It "\&%L"
|
||||||
Local hostname.
|
Local hostname.
|
||||||
.It "\&%M"
|
.It "\&%M"
|
||||||
@ -454,6 +494,24 @@ if there's no limit.
|
|||||||
Current number of users for this class.
|
Current number of users for this class.
|
||||||
.It "\&%R"
|
.It "\&%R"
|
||||||
Remote hostname.
|
Remote hostname.
|
||||||
|
.It "\&%s"
|
||||||
|
If the result of the most recent
|
||||||
|
.Dq "\&%M"
|
||||||
|
or
|
||||||
|
.Dq "\&%N"
|
||||||
|
was not
|
||||||
|
.Dq Li 1 ,
|
||||||
|
print an
|
||||||
|
.Dq s .
|
||||||
|
.It "\&%S"
|
||||||
|
If the result of the most recent
|
||||||
|
.Dq "\&%M"
|
||||||
|
or
|
||||||
|
.Dq "\&%N"
|
||||||
|
was not
|
||||||
|
.Dq Li 1 ,
|
||||||
|
print an
|
||||||
|
.Dq S .
|
||||||
.It "\&%T"
|
.It "\&%T"
|
||||||
Current time.
|
Current time.
|
||||||
.It "\&%U"
|
.It "\&%U"
|
||||||
@ -532,9 +590,15 @@ users to be able to see the names of the
|
|||||||
files in this directory the permissions should be 770, otherwise
|
files in this directory the permissions should be 770, otherwise
|
||||||
they should be 370.
|
they should be 370.
|
||||||
.Pp
|
.Pp
|
||||||
Anonymous users will be able to upload files to this directory,
|
The following
|
||||||
but they will not be able to download them, delete them, or overwrite
|
.Xr ftpd.conf 5
|
||||||
them, due to the umask and disabling of the commands mentioned
|
directives should be used:
|
||||||
|
.Dl "modify guest off"
|
||||||
|
.Dl "umask guest 0707"
|
||||||
|
.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
|
||||||
|
overwrite them, due to the umask and disabling of the commands mentioned
|
||||||
above.
|
above.
|
||||||
.It Pa ~ftp/tmp
|
.It Pa ~ftp/tmp
|
||||||
This directory is used to create temporary files which contain
|
This directory is used to create temporary files which contain
|
||||||
@ -596,10 +660,10 @@ State file of logged-in processes for the
|
|||||||
.Nm
|
.Nm
|
||||||
class
|
class
|
||||||
.Sq CLASS .
|
.Sq CLASS .
|
||||||
.It Pa /var/log/wtmp
|
|
||||||
Login history database.
|
|
||||||
.It Pa /var/run/utmp
|
.It Pa /var/run/utmp
|
||||||
List of logged-in users on the system.
|
List of logged-in users on the system.
|
||||||
|
.It Pa /var/log/wtmp
|
||||||
|
Login history database.
|
||||||
.El
|
.El
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr ftp 1 ,
|
.Xr ftp 1 ,
|
||||||
@ -696,7 +760,8 @@ communicate back to the client for the
|
|||||||
.Sy LPTR ,
|
.Sy LPTR ,
|
||||||
and
|
and
|
||||||
.Sy PORT
|
.Sy PORT
|
||||||
commands.
|
commands, unless overridden with
|
||||||
|
.Fl P Ar dataport .
|
||||||
As the default port for
|
As the default port for
|
||||||
.Nm
|
.Nm
|
||||||
(21) is a privileged port below
|
(21) is a privileged port below
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $NetBSD: ftpd.c,v 1.110 2000/11/15 04:07:07 itojun Exp $ */
|
/* $NetBSD: ftpd.c,v 1.111 2000/11/16 13:15:14 lukem Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997-2000 The NetBSD Foundation, Inc.
|
* Copyright (c) 1997-2000 The NetBSD Foundation, Inc.
|
||||||
@ -109,7 +109,7 @@ __COPYRIGHT(
|
|||||||
#if 0
|
#if 0
|
||||||
static char sccsid[] = "@(#)ftpd.c 8.5 (Berkeley) 4/28/95";
|
static char sccsid[] = "@(#)ftpd.c 8.5 (Berkeley) 4/28/95";
|
||||||
#else
|
#else
|
||||||
__RCSID("$NetBSD: ftpd.c,v 1.110 2000/11/15 04:07:07 itojun Exp $");
|
__RCSID("$NetBSD: ftpd.c,v 1.111 2000/11/16 13:15:14 lukem Exp $");
|
||||||
#endif
|
#endif
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
|
||||||
@ -172,6 +172,8 @@ struct passwd *pw;
|
|||||||
int sflag;
|
int sflag;
|
||||||
int stru; /* avoid C keyword */
|
int stru; /* avoid C keyword */
|
||||||
int mode;
|
int mode;
|
||||||
|
int dataport; /* use specific data port */
|
||||||
|
int dopidfile; /* maintain pid file */
|
||||||
int doutmp; /* update utmp file */
|
int doutmp; /* update utmp file */
|
||||||
int dowtmp; /* update wtmp file */
|
int dowtmp; /* update wtmp file */
|
||||||
int dropprivs; /* if privileges should or have been dropped */
|
int dropprivs; /* if privileges should or have been dropped */
|
||||||
@ -181,8 +183,8 @@ off_t byte_count;
|
|||||||
static char ttyline[20];
|
static char ttyline[20];
|
||||||
static struct utmp utmp; /* for utmp */
|
static struct utmp utmp; /* for utmp */
|
||||||
|
|
||||||
static char *anondir = NULL;
|
static const char *anondir = NULL;
|
||||||
static char confdir[MAXPATHLEN];
|
static const char *confdir = NULL;
|
||||||
|
|
||||||
#if defined(KERBEROS) || defined(KERBEROS5)
|
#if defined(KERBEROS) || defined(KERBEROS5)
|
||||||
int has_ccache = 0;
|
int has_ccache = 0;
|
||||||
@ -236,31 +238,41 @@ main(int argc, char *argv[])
|
|||||||
#ifdef KERBEROS5
|
#ifdef KERBEROS5
|
||||||
krb5_error_code kerror;
|
krb5_error_code kerror;
|
||||||
#endif
|
#endif
|
||||||
|
char *p;
|
||||||
|
|
||||||
connections = 1;
|
connections = 1;
|
||||||
debug = 0;
|
debug = 0;
|
||||||
logging = 0;
|
logging = 0;
|
||||||
pdata = -1;
|
pdata = -1;
|
||||||
sflag = 0;
|
sflag = 0;
|
||||||
|
dataport = 0;
|
||||||
|
dopidfile = 1; /* default: DO use a pid file to count users */
|
||||||
doutmp = 0; /* default: don't log to utmp */
|
doutmp = 0; /* default: don't log to utmp */
|
||||||
dowtmp = 1; /* default: DO log to wtmp */
|
dowtmp = 1; /* default: DO log to wtmp */
|
||||||
dropprivs = 0;
|
dropprivs = 0;
|
||||||
mapped = 0;
|
mapped = 0;
|
||||||
usedefault = 1;
|
usedefault = 1;
|
||||||
(void)strcpy(confdir, _DEFAULT_CONFDIR);
|
emailaddr = NULL;
|
||||||
hostname[0] = '\0';
|
hostname[0] = '\0';
|
||||||
homedir[0] = '\0';
|
homedir[0] = '\0';
|
||||||
gidcount = 0;
|
gidcount = 0;
|
||||||
|
|
||||||
version = FTPD_VERSION;
|
version = FTPD_VERSION;
|
||||||
while ((ch = getopt(argc, argv, "a:c:C:dh:Hlrst:T:u:UvV:W")) != -1) {
|
|
||||||
|
/*
|
||||||
|
* 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, LOG_FTP);
|
||||||
|
|
||||||
|
while ((ch = getopt(argc, argv, "a:c:C:de:h:HlP:qQrst:T:uUvV:wW"))
|
||||||
|
!= -1) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 'a':
|
case 'a':
|
||||||
anondir = optarg;
|
anondir = optarg;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'c':
|
case 'c':
|
||||||
(void)strlcpy(confdir, optarg, sizeof(confdir));
|
confdir = optarg;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'C':
|
case 'C':
|
||||||
@ -273,6 +285,10 @@ main(int argc, char *argv[])
|
|||||||
debug = 1;
|
debug = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'e':
|
||||||
|
emailaddr = optarg;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'h':
|
case 'h':
|
||||||
strlcpy(hostname, optarg, sizeof(hostname));
|
strlcpy(hostname, optarg, sizeof(hostname));
|
||||||
break;
|
break;
|
||||||
@ -287,6 +303,24 @@ main(int argc, char *argv[])
|
|||||||
logging++; /* > 1 == extra logging */
|
logging++; /* > 1 == extra logging */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'P':
|
||||||
|
dataport = (int)strtol(optarg, &p, 10);
|
||||||
|
if (*p != '\0' || dataport < IPPORT_RESERVED ||
|
||||||
|
dataport > IPPORT_ANONMAX) {
|
||||||
|
syslog(LOG_WARNING, "Invalid dataport %s",
|
||||||
|
optarg);
|
||||||
|
dataport = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'q':
|
||||||
|
dopidfile = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'Q':
|
||||||
|
dopidfile = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'r':
|
case 'r':
|
||||||
dropprivs = 1;
|
dropprivs = 1;
|
||||||
break;
|
break;
|
||||||
@ -297,15 +331,19 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
case 't':
|
case 't':
|
||||||
case 'T':
|
case 'T':
|
||||||
case 'u':
|
syslog(LOG_ERR,
|
||||||
warnx("-%c has been deprecated in favour of ftpd.conf",
|
"-%c has been deprecated in favour of ftpd.conf",
|
||||||
ch);
|
ch);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'U':
|
case 'u':
|
||||||
doutmp = 1;
|
doutmp = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'U':
|
||||||
|
doutmp = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'V':
|
case 'V':
|
||||||
if (EMPTYSTR(optarg) || strcmp(optarg, "-") == 0)
|
if (EMPTYSTR(optarg) || strcmp(optarg, "-") == 0)
|
||||||
version = NULL;
|
version = NULL;
|
||||||
@ -313,6 +351,10 @@ main(int argc, char *argv[])
|
|||||||
version = xstrdup(optarg);
|
version = xstrdup(optarg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'w':
|
||||||
|
dowtmp = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'W':
|
case 'W':
|
||||||
dowtmp = 0;
|
dowtmp = 0;
|
||||||
break;
|
break;
|
||||||
@ -320,16 +362,13 @@ main(int argc, char *argv[])
|
|||||||
default:
|
default:
|
||||||
if (optopt == 'a' || optopt == 'C')
|
if (optopt == 'a' || optopt == 'C')
|
||||||
exit(1);
|
exit(1);
|
||||||
warnx("unknown flag -%c ignored", optopt);
|
syslog(LOG_ERR, "unknown flag -%c ignored", optopt);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (EMPTYSTR(confdir))
|
||||||
|
confdir = _DEFAULT_CONFDIR;
|
||||||
|
|
||||||
/*
|
|
||||||
* 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, LOG_FTP);
|
|
||||||
memset((char *)&his_addr, 0, sizeof (his_addr));
|
memset((char *)&his_addr, 0, sizeof (his_addr));
|
||||||
addrlen = sizeof(his_addr.si_su);
|
addrlen = sizeof(his_addr.si_su);
|
||||||
if (getpeername(0, (struct sockaddr *)&his_addr.si_su, &addrlen) < 0) {
|
if (getpeername(0, (struct sockaddr *)&his_addr.si_su, &addrlen) < 0) {
|
||||||
@ -938,7 +977,9 @@ pass(const char *passwd)
|
|||||||
|
|
||||||
/* parse ftpd.conf, setting up various parameters */
|
/* parse ftpd.conf, setting up various parameters */
|
||||||
parse_conf(class);
|
parse_conf(class);
|
||||||
count_users();
|
connections = 1;
|
||||||
|
if (dopidfile)
|
||||||
|
count_users();
|
||||||
if (curclass.limit != -1 && connections > curclass.limit) {
|
if (curclass.limit != -1 && connections > curclass.limit) {
|
||||||
if (! EMPTYSTR(curclass.limitfile))
|
if (! EMPTYSTR(curclass.limitfile))
|
||||||
(void)display_file(conffilename(curclass.limitfile),
|
(void)display_file(conffilename(curclass.limitfile),
|
||||||
@ -1090,9 +1131,11 @@ pass(const char *passwd)
|
|||||||
}
|
}
|
||||||
(void) umask(curclass.umask);
|
(void) umask(curclass.umask);
|
||||||
goto cleanuppass;
|
goto cleanuppass;
|
||||||
|
|
||||||
bad:
|
bad:
|
||||||
/* Forget all about it... */
|
/* Forget all about it... */
|
||||||
end_login();
|
end_login();
|
||||||
|
|
||||||
cleanuppass:
|
cleanuppass:
|
||||||
if (class)
|
if (class)
|
||||||
free(class);
|
free(class);
|
||||||
@ -1338,7 +1381,10 @@ getdatasock(const char *mode)
|
|||||||
* would be < IPPORT_RESERVED, use a random port
|
* would be < IPPORT_RESERVED, use a random port
|
||||||
* instead.
|
* instead.
|
||||||
*/
|
*/
|
||||||
port = ntohs(ctrl_addr.su_port) - 1;
|
if (dataport)
|
||||||
|
port = dataport;
|
||||||
|
else
|
||||||
|
port = ntohs(ctrl_addr.su_port) - 1;
|
||||||
if (dropprivs && port < IPPORT_RESERVED)
|
if (dropprivs && port < IPPORT_RESERVED)
|
||||||
port = 0; /* use random port */
|
port = 0; /* use random port */
|
||||||
data_source.su_port = htons(port);
|
data_source.su_port = htons(port);
|
||||||
@ -1632,6 +1678,7 @@ static int
|
|||||||
receive_data(FILE *instr, FILE *outstr)
|
receive_data(FILE *instr, FILE *outstr)
|
||||||
{
|
{
|
||||||
int c, bare_lfs, netfd, filefd, rval;
|
int c, bare_lfs, netfd, filefd, rval;
|
||||||
|
off_t byteswritten;
|
||||||
char buf[BUFSIZ];
|
char buf[BUFSIZ];
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
(void) &bare_lfs;
|
(void) &bare_lfs;
|
||||||
@ -1640,9 +1687,19 @@ receive_data(FILE *instr, FILE *outstr)
|
|||||||
bare_lfs = 0;
|
bare_lfs = 0;
|
||||||
transflag = 1;
|
transflag = 1;
|
||||||
rval = -1;
|
rval = -1;
|
||||||
|
byteswritten = 0;
|
||||||
if (setjmp(urgcatch))
|
if (setjmp(urgcatch))
|
||||||
goto cleanup_recv_data;
|
goto cleanup_recv_data;
|
||||||
|
|
||||||
|
#define FILESIZECHECK(x) \
|
||||||
|
do { \
|
||||||
|
if (curclass.maxfilesize != -1 && \
|
||||||
|
(x) > curclass.maxfilesize) { \
|
||||||
|
errno = EFBIG; \
|
||||||
|
goto file_err; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
|
||||||
case TYPE_I:
|
case TYPE_I:
|
||||||
@ -1662,8 +1719,9 @@ receive_data(FILE *instr, FILE *outstr)
|
|||||||
if ((c = read(netfd, buf,
|
if ((c = read(netfd, buf,
|
||||||
MIN(sizeof(buf), bufrem))) <= 0)
|
MIN(sizeof(buf), bufrem))) <= 0)
|
||||||
goto recvdone;
|
goto recvdone;
|
||||||
|
FILESIZECHECK(byte_count + c);
|
||||||
if ((d = write(filefd, buf, c)) != c)
|
if ((d = write(filefd, buf, c)) != c)
|
||||||
goto recvdone;
|
goto file_err;
|
||||||
(void) alarm(curclass.timeout);
|
(void) alarm(curclass.timeout);
|
||||||
bufrem -= c;
|
bufrem -= c;
|
||||||
byte_count += c;
|
byte_count += c;
|
||||||
@ -1679,6 +1737,7 @@ receive_data(FILE *instr, FILE *outstr)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
while ((c = read(netfd, buf, sizeof(buf))) > 0) {
|
while ((c = read(netfd, buf, sizeof(buf))) > 0) {
|
||||||
|
FILESIZECHECK(byte_count + c);
|
||||||
if (write(filefd, buf, c) != c)
|
if (write(filefd, buf, c) != c)
|
||||||
goto file_err;
|
goto file_err;
|
||||||
(void) alarm(curclass.timeout);
|
(void) alarm(curclass.timeout);
|
||||||
@ -1723,13 +1782,17 @@ receive_data(FILE *instr, FILE *outstr)
|
|||||||
total_bytes++;
|
total_bytes++;
|
||||||
if ((byte_count % 4096) == 0)
|
if ((byte_count % 4096) == 0)
|
||||||
(void) alarm(curclass.timeout);
|
(void) alarm(curclass.timeout);
|
||||||
|
byteswritten++;
|
||||||
|
FILESIZECHECK(byteswritten);
|
||||||
(void) putc ('\r', outstr);
|
(void) putc ('\r', outstr);
|
||||||
if (c == '\0' || c == EOF)
|
if (c == '\0' || c == EOF)
|
||||||
goto contin2;
|
goto contin2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
byteswritten++;
|
||||||
|
FILESIZECHECK(byteswritten);
|
||||||
(void) putc(c, outstr);
|
(void) putc(c, outstr);
|
||||||
contin2: ;
|
contin2: ;
|
||||||
}
|
}
|
||||||
(void) alarm(0);
|
(void) alarm(0);
|
||||||
fflush(outstr);
|
fflush(outstr);
|
||||||
@ -1750,6 +1813,7 @@ receive_data(FILE *instr, FILE *outstr)
|
|||||||
reply(550, "Unimplemented TYPE %d in receive_data", type);
|
reply(550, "Unimplemented TYPE %d in receive_data", type);
|
||||||
goto cleanup_recv_data;
|
goto cleanup_recv_data;
|
||||||
}
|
}
|
||||||
|
#undef FILESIZECHECK(x)
|
||||||
|
|
||||||
data_err:
|
data_err:
|
||||||
(void) alarm(0);
|
(void) alarm(0);
|
||||||
@ -1925,7 +1989,7 @@ statcmd(void)
|
|||||||
reply(0, "Class: %s, type: %s",
|
reply(0, "Class: %s, type: %s",
|
||||||
curclass.classname, CURCLASSTYPE);
|
curclass.classname, CURCLASSTYPE);
|
||||||
reply(0, "Check PORT/LPRT commands: %sabled",
|
reply(0, "Check PORT/LPRT commands: %sabled",
|
||||||
curclass.checkportcmd ? "en" : "dis");
|
CURCLASS_FLAGS_ISSET(checkportcmd) ? "en" : "dis");
|
||||||
if (! EMPTYSTR(curclass.display))
|
if (! EMPTYSTR(curclass.display))
|
||||||
reply(0, "Display file: %s", curclass.display);
|
reply(0, "Display file: %s", curclass.display);
|
||||||
if (! EMPTYSTR(curclass.notify))
|
if (! EMPTYSTR(curclass.notify))
|
||||||
@ -1938,30 +2002,39 @@ statcmd(void)
|
|||||||
else
|
else
|
||||||
reply(0, "Maximum connections: %d", curclass.limit);
|
reply(0, "Maximum connections: %d", curclass.limit);
|
||||||
if (curclass.limitfile)
|
if (curclass.limitfile)
|
||||||
reply(0, "Connection limit exceeded file: %s",
|
reply(0, "Connection limit exceeded message file: %s",
|
||||||
curclass.limitfile);
|
curclass.limitfile);
|
||||||
if (! EMPTYSTR(curclass.chroot))
|
if (! EMPTYSTR(curclass.chroot))
|
||||||
reply(0, "Chroot format: %s", curclass.chroot);
|
reply(0, "Chroot format: %s", curclass.chroot);
|
||||||
if (! EMPTYSTR(curclass.homedir))
|
if (! EMPTYSTR(curclass.homedir))
|
||||||
reply(0, "Homedir format: %s", curclass.homedir);
|
reply(0, "Homedir format: %s", curclass.homedir);
|
||||||
|
if (curclass.maxfilesize == -1)
|
||||||
|
reply(0, "Maximum file size: unlimited");
|
||||||
|
else
|
||||||
|
reply(0, "Maximum file size: " LLF,
|
||||||
|
(LLT)curclass.maxfilesize);
|
||||||
if (! EMPTYSTR(curclass.motd))
|
if (! EMPTYSTR(curclass.motd))
|
||||||
reply(0, "MotD file: %s", curclass.motd);
|
reply(0, "MotD file: %s", curclass.motd);
|
||||||
reply(0,
|
reply(0,
|
||||||
"Modify commands (CHMOD, DELE, MKD, RMD, RNFR, UMASK): %sabled",
|
"Modify commands (CHMOD, DELE, MKD, RMD, RNFR, UMASK): %sabled",
|
||||||
curclass.modify ? "en" : "dis");
|
CURCLASS_FLAGS_ISSET(modify) ? "en" : "dis");
|
||||||
reply(0, "Upload commands (APPE, STOR, STOU): %sabled",
|
reply(0, "Upload commands (APPE, STOR, STOU): %sabled",
|
||||||
curclass.upload ? "en" : "dis");
|
CURCLASS_FLAGS_ISSET(upload) ? "en" : "dis");
|
||||||
|
reply(0, "Sanitize file names: %sabled",
|
||||||
|
CURCLASS_FLAGS_ISSET(sanenames) ? "en" : "dis");
|
||||||
|
reply(0, "PASV/LPSV/EPSV connections: %sabled",
|
||||||
|
CURCLASS_FLAGS_ISSET(passive) ? "en" : "dis");
|
||||||
if (curclass.portmin && curclass.portmax)
|
if (curclass.portmin && curclass.portmax)
|
||||||
reply(0, "PASV port range: %d - %d",
|
reply(0, "PASV port range: %d - %d",
|
||||||
curclass.portmin, curclass.portmax);
|
curclass.portmin, curclass.portmax);
|
||||||
if (curclass.rateget)
|
if (curclass.rateget)
|
||||||
reply(0, "Rate get limit: %d bytes/sec",
|
reply(0, "Rate get limit: " LLF " bytes/sec",
|
||||||
curclass.rateget);
|
(LLT)curclass.rateget);
|
||||||
else
|
else
|
||||||
reply(0, "Rate get limit: disabled");
|
reply(0, "Rate get limit: disabled");
|
||||||
if (curclass.rateput)
|
if (curclass.rateput)
|
||||||
reply(0, "Rate put limit: %d bytes/sec",
|
reply(0, "Rate put limit: " LLF " bytes/sec",
|
||||||
curclass.rateput);
|
(LLT)curclass.rateput);
|
||||||
else
|
else
|
||||||
reply(0, "Rate put limit: disabled");
|
reply(0, "Rate put limit: disabled");
|
||||||
reply(0, "Umask: %.04o", curclass.umask);
|
reply(0, "Umask: %.04o", curclass.umask);
|
||||||
@ -2262,8 +2335,7 @@ long_passive(char *cmd, int pf)
|
|||||||
|
|
||||||
if (pf != PF_UNSPEC && ctrl_addr.su_family != pf) {
|
if (pf != PF_UNSPEC && ctrl_addr.su_family != pf) {
|
||||||
/*
|
/*
|
||||||
* XXX
|
* XXX: only EPRT/EPSV ready clients will understand this
|
||||||
* only EPRT/EPSV ready clients will understand this
|
|
||||||
*/
|
*/
|
||||||
if (strcmp(cmd, "EPSV") != 0)
|
if (strcmp(cmd, "EPSV") != 0)
|
||||||
reply(501, "Network protocol mismatch"); /*XXX*/
|
reply(501, "Network protocol mismatch"); /*XXX*/
|
||||||
@ -2364,7 +2436,7 @@ extended_port(const char *arg)
|
|||||||
p = q;
|
p = q;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* some more sanity check */
|
/* some more sanity checks */
|
||||||
p = NULL;
|
p = NULL;
|
||||||
(void)strtoul(result[2], &p, 10);
|
(void)strtoul(result[2], &p, 10);
|
||||||
if (!*result[2] || *p)
|
if (!*result[2] || *p)
|
||||||
@ -2389,7 +2461,7 @@ extended_port(const char *arg)
|
|||||||
memcpy(&data_dest, res->ai_addr, res->ai_addrlen);
|
memcpy(&data_dest, res->ai_addr, res->ai_addrlen);
|
||||||
if (his_addr.su_family == AF_INET6 &&
|
if (his_addr.su_family == AF_INET6 &&
|
||||||
data_dest.su_family == AF_INET6) {
|
data_dest.su_family == AF_INET6) {
|
||||||
/* XXX more sanity checks! */
|
/* XXX: more sanity checks! */
|
||||||
data_dest.su_scope_id = his_addr.su_scope_id;
|
data_dest.su_scope_id = his_addr.su_scope_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2431,7 +2503,7 @@ epsv_protounsupp(const char *message)
|
|||||||
|
|
||||||
proto = af2epsvproto(ctrl_addr.su_family);
|
proto = af2epsvproto(ctrl_addr.su_family);
|
||||||
if (proto < 0)
|
if (proto < 0)
|
||||||
reply(501, "%s", message); /*XXX*/
|
reply(501, "%s", message); /* XXX */
|
||||||
else
|
else
|
||||||
reply(522, "%s, use (%d)", message, proto);
|
reply(522, "%s, use (%d)", message, proto);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
.\" $NetBSD: ftpd.conf.5,v 1.13 2000/11/07 06:58:08 lukem Exp $
|
.\" $NetBSD: ftpd.conf.5,v 1.14 2000/11/16 13:15:14 lukem Exp $
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright (c) 1997-2000 The NetBSD Foundation, Inc.
|
.\" Copyright (c) 1997-2000 The NetBSD Foundation, Inc.
|
||||||
.\" All rights reserved.
|
.\" All rights reserved.
|
||||||
@ -34,7 +34,7 @@
|
|||||||
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
.\" POSSIBILITY OF SUCH DAMAGE.
|
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.Dd November 7, 2000
|
.Dd November 16, 2000
|
||||||
.Dt FTPD.CONF 5
|
.Dt FTPD.CONF 5
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -58,7 +58,7 @@ This allows
|
|||||||
.Sq wildcard
|
.Sq wildcard
|
||||||
entries to define defaults, and then have class-specific overrides.
|
entries to define defaults, and then have class-specific overrides.
|
||||||
.Pp
|
.Pp
|
||||||
A directive line has the format
|
A directive line has the format:
|
||||||
.Dl command class [arguments]
|
.Dl command class [arguments]
|
||||||
.Pp
|
.Pp
|
||||||
A
|
A
|
||||||
@ -211,7 +211,7 @@ Valid types are:
|
|||||||
(directory).
|
(directory).
|
||||||
.It Ar disable
|
.It Ar disable
|
||||||
The name of file that will prevent conversion if it exists.
|
The name of file that will prevent conversion if it exists.
|
||||||
A filename of
|
A file name of
|
||||||
.Dq Pa \&.
|
.Dq Pa \&.
|
||||||
will prevent this disabling action
|
will prevent this disabling action
|
||||||
(i.e., the conversion is always permitted.)
|
(i.e., the conversion is always permitted.)
|
||||||
@ -295,6 +295,9 @@ for
|
|||||||
and
|
and
|
||||||
.Sy CHROOT
|
.Sy CHROOT
|
||||||
users.
|
users.
|
||||||
|
.It Sy maxfilesize Ar class Ar size
|
||||||
|
Set the maximum size of an uploaded file to
|
||||||
|
.Ar size .
|
||||||
.It Sy maxtimeout Ar class Ar time
|
.It Sy maxtimeout Ar class Ar time
|
||||||
Set the maximum timeout period that a client may request,
|
Set the maximum timeout period that a client may request,
|
||||||
defaulting to two hours.
|
defaulting to two hours.
|
||||||
@ -392,6 +395,19 @@ to
|
|||||||
bytes per second,
|
bytes per second,
|
||||||
which is parsed as per
|
which is parsed as per
|
||||||
.Sy rateget Ar rate .
|
.Sy rateget Ar rate .
|
||||||
|
.It Sy sanenames Ar class Op Sy off
|
||||||
|
If
|
||||||
|
.Ar class
|
||||||
|
is
|
||||||
|
.Dq none
|
||||||
|
or
|
||||||
|
.Sy off
|
||||||
|
is given, 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 template Ar class Op Ar refclass
|
.It Sy template Ar class Op Ar refclass
|
||||||
Define
|
Define
|
||||||
.Ar refclass
|
.Ar refclass
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $NetBSD: version.h,v 1.21 2000/11/15 02:32:30 lukem Exp $ */
|
/* $NetBSD: version.h,v 1.22 2000/11/16 13:15:14 lukem Exp $ */
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
|
* Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
@ -36,5 +36,5 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef FTPD_VERSION
|
#ifndef FTPD_VERSION
|
||||||
#define FTPD_VERSION "NetBSD-ftpd 20001115"
|
#define FTPD_VERSION "NetBSD-ftpd 20001116"
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user