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