Adds anon ftp virtual host capability to ftpd, using /etc/ftphosts for
definition of a system's virtual hosts.
This commit is contained in:
parent
e9dff5569a
commit
ea4e54b942
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=25283
@ -1,11 +1,11 @@
|
||||
# @(#)Makefile 8.2 (Berkeley) 4/4/94
|
||||
# $Id: Makefile,v 1.20 1997/04/23 04:56:39 davidn Exp $
|
||||
# $Id: Makefile,v 1.21 1997/04/26 12:12:10 davidn Exp $
|
||||
|
||||
PROG= ftpd
|
||||
MAN8= ftpd.8
|
||||
SRCS= ftpd.c ftpcmd.c logwtmp.c popen.c skey-stuff.c
|
||||
|
||||
CFLAGS+=-DSETPROCTITLE -DSKEY -DLOGIN_CAP -Wall
|
||||
CFLAGS+=-DSETPROCTITLE -DSKEY -DLOGIN_CAP -DVIRTUAL_HOSTING -Wall
|
||||
|
||||
LDADD= -lskey -lmd -lcrypt -lutil
|
||||
DPADD= ${LIBSKEY} ${LIBMD} ${LIBCRYPT} ${LIBUTIL}
|
||||
|
@ -30,7 +30,7 @@
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)ftpd.8 8.2 (Berkeley) 4/19/94
|
||||
.\" $Id: ftpd.8,v 1.16 1997/04/26 12:23:51 davidn Exp $
|
||||
.\" $Id: ftpd.8,v 1.17 1997/04/27 08:29:21 davidn Exp $
|
||||
.\"
|
||||
.Dd April 19, 1994
|
||||
.Dt FTPD 8
|
||||
@ -286,8 +286,8 @@ This facility may also be triggered by enabling the boolean "ftp-chroot"
|
||||
capability in
|
||||
.Xr login.conf 5 .
|
||||
However, the user must still supply a password.
|
||||
This feature is intended as a compromise between a fully anonymous account
|
||||
and a fully privileged account.
|
||||
This feature is intended as a compromise between a fully anonymous
|
||||
account and a fully privileged account.
|
||||
The account should also be set up as for an anonymous account.
|
||||
.It
|
||||
If the user name is
|
||||
@ -357,6 +357,51 @@ can then place files which are to be accessible via the anonymous
|
||||
account in this directory.
|
||||
.El
|
||||
.Pp
|
||||
If the system has multiple IP addresses,
|
||||
.Nm ftpd
|
||||
supports the idea of virtual hosts, which provides the ability to
|
||||
define multiple anonymous ftp areas, each one allocated to a different
|
||||
internet address.
|
||||
The file
|
||||
.Pa /etc/ftphosts
|
||||
contains information pertaining to each of the virtual hosts.
|
||||
Each host is defined on its own line which contains a number of
|
||||
fields separated by whitespace:
|
||||
.Bl -tag -offset indent -width hostname
|
||||
.It hostname
|
||||
Contains the hostname or IP address of the virtual host.
|
||||
.It user
|
||||
Contains a user record in the system password file.
|
||||
As with normal anonymous ftp, this user's access uid, gid and group
|
||||
memberships determine file access to the anonymous ftp area.
|
||||
The anonymous ftp area (to which any user is chrooted on login)
|
||||
is determined by the home directory defined for the account.
|
||||
User id and group for any ftp account may be the same as for the
|
||||
standard ftp user.
|
||||
.It statfile
|
||||
File to which all file transfers are logged, which
|
||||
defaults to
|
||||
.Pa /var/log/ftpd .
|
||||
.It welcome
|
||||
This file is the welcome message displayed before the server ready
|
||||
prompt.
|
||||
It defaults to
|
||||
.Pa /etc/ftpwelcome .
|
||||
.It motd
|
||||
This file is displayed after the user logs in.
|
||||
It defaults to
|
||||
.Pa /etc/ftpmotd .
|
||||
.El
|
||||
.Pp
|
||||
Defining a virtual host for the primary IP address or hostname
|
||||
changes the default for ftp logins to that address.
|
||||
The 'user', 'statfile', 'welcome' and 'motd' fields may be left
|
||||
blank, or a single hypen '-' used to indicate that the default
|
||||
value is to be used.
|
||||
.Pp
|
||||
As with any anonymous login configuration, due care must be given
|
||||
to setup and maintenance to guard against security related problems.
|
||||
.Pp
|
||||
If compiled with the
|
||||
.Em INTERNAL_LS
|
||||
option,
|
||||
|
@ -30,7 +30,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ftpd.c,v 1.36 1997/04/26 12:12:10 davidn Exp $
|
||||
* $Id: ftpd.c,v 1.37 1997/04/27 08:29:21 davidn Exp $
|
||||
*/
|
||||
|
||||
#if 0
|
||||
@ -151,7 +151,23 @@ off_t byte_count;
|
||||
#endif
|
||||
int defumask = CMASK; /* default umask value */
|
||||
char tmpline[7];
|
||||
#ifdef VIRTUAL_HOSTING
|
||||
char *hostname;
|
||||
char *ftpuser;
|
||||
|
||||
static struct ftphost {
|
||||
struct ftphost *next;
|
||||
struct in_addr hostaddr;
|
||||
char *hostname;
|
||||
char *anonuser;
|
||||
char *statfile;
|
||||
char *welcome;
|
||||
char *loginmsg;
|
||||
} *thishost, *firsthost;
|
||||
|
||||
#else
|
||||
char hostname[MAXHOSTNAMELEN];
|
||||
#endif
|
||||
char remotehost[MAXHOSTNAMELEN];
|
||||
char *ident = NULL;
|
||||
|
||||
@ -214,6 +230,10 @@ char addr_string[20]; /* XXX */
|
||||
cmd, (*(file) == '/') ? "" : curdir(), file, cnt); \
|
||||
}
|
||||
|
||||
#ifdef VIRTUAL_HOSTING
|
||||
static void inithosts __P((void));
|
||||
static void selecthost __P((struct in_addr *));
|
||||
#endif
|
||||
static void ack __P((char *));
|
||||
static void myoob __P((int));
|
||||
static int checkuser __P((char *, char *));
|
||||
@ -341,6 +361,9 @@ main(argc, argv, envp)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef VIRTUAL_HOSTING
|
||||
inithosts();
|
||||
#endif
|
||||
(void) freopen(_PATH_DEVNULL, "w", stderr);
|
||||
|
||||
/*
|
||||
@ -450,6 +473,10 @@ main(argc, argv, envp)
|
||||
syslog(LOG_ERR, "getsockname (%s): %m",argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
#ifdef VIRTUAL_HOSTING
|
||||
/* select our identity from virtual host table */
|
||||
selecthost(&ctrl_addr.sin_addr);
|
||||
#endif
|
||||
#ifdef IP_TOS
|
||||
tos = IPTOS_LOWDELAY;
|
||||
if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
|
||||
@ -493,7 +520,11 @@ main(argc, argv, envp)
|
||||
reply(530, "System not available.");
|
||||
exit(0);
|
||||
}
|
||||
#ifdef VIRTUAL_HOSTING
|
||||
if ((fd = fopen(thishost->welcome, "r")) != NULL) {
|
||||
#else
|
||||
if ((fd = fopen(_PATH_FTPWELCOME, "r")) != NULL) {
|
||||
#endif
|
||||
while (fgets(line, sizeof(line), fd) != NULL) {
|
||||
if ((cp = strchr(line, '\n')) != NULL)
|
||||
*cp = '\0';
|
||||
@ -503,7 +534,9 @@ main(argc, argv, envp)
|
||||
(void) fclose(fd);
|
||||
/* reply(220,) must follow */
|
||||
}
|
||||
#ifndef VIRTUAL_HOSTING
|
||||
(void) gethostname(hostname, sizeof(hostname));
|
||||
#endif
|
||||
reply(220, "%s FTP server (%s) ready.", hostname, version);
|
||||
(void) setjmp(errcatch);
|
||||
for (;;)
|
||||
@ -521,6 +554,147 @@ lostconn(signo)
|
||||
dologout(-1);
|
||||
}
|
||||
|
||||
#ifdef VIRTUAL_HOSTING
|
||||
/*
|
||||
* read in virtual host tables (if they exist)
|
||||
*/
|
||||
|
||||
static void
|
||||
inithosts()
|
||||
{
|
||||
FILE *fp;
|
||||
char *cp;
|
||||
struct hostent *hp;
|
||||
struct ftphost *hrp, *lhrp;
|
||||
char line[1024];
|
||||
|
||||
/*
|
||||
* Fill in the default host information
|
||||
*/
|
||||
if (gethostname(line, sizeof(line)) < 0)
|
||||
line[0] = '\0';
|
||||
if ((hrp = malloc(sizeof(struct ftphost))) == NULL ||
|
||||
(hrp->hostname = strdup(line)) == NULL)
|
||||
fatal("Ran out of memory.");
|
||||
memset(&hrp->hostaddr, 0, sizeof hrp->hostaddr);
|
||||
if ((hp = gethostbyname(hrp->hostname)) != NULL)
|
||||
(void) memcpy(&hrp->hostaddr,
|
||||
hp->h_addr_list[0],
|
||||
sizeof(hrp->hostaddr));
|
||||
hrp->statfile = _PATH_FTPDSTATFILE;
|
||||
hrp->welcome = _PATH_FTPWELCOME;
|
||||
hrp->loginmsg = _PATH_FTPLOGINMESG;
|
||||
hrp->anonuser = "ftp";
|
||||
hrp->next = NULL;
|
||||
thishost = firsthost = lhrp = hrp;
|
||||
if ((fp = fopen(_PATH_FTPHOSTS, "r")) != NULL) {
|
||||
while (fgets(line, sizeof(line), fp) != NULL) {
|
||||
int i;
|
||||
|
||||
if ((cp = strchr(line, '\n')) == NULL) {
|
||||
/* ignore long lines */
|
||||
while (fgets(line, sizeof(line), fp) != NULL &&
|
||||
strchr(line, '\n') == NULL)
|
||||
;
|
||||
continue;
|
||||
}
|
||||
*cp = '\0';
|
||||
cp = strtok(line, " \t");
|
||||
/* skip comments and empty lines */
|
||||
if (cp == NULL || line[0] == '#')
|
||||
continue;
|
||||
/* first, try a standard gethostbyname() */
|
||||
if ((hp = gethostbyname(cp)) == NULL)
|
||||
continue;
|
||||
for (hrp = firsthost; hrp != NULL; hrp = hrp->next) {
|
||||
if (memcmp(&hrp->hostaddr,
|
||||
hp->h_addr_list[0],
|
||||
sizeof(hrp->hostaddr)) == 0)
|
||||
break;
|
||||
}
|
||||
if (hrp == NULL) {
|
||||
if ((hrp = malloc(sizeof(struct ftphost))) == NULL)
|
||||
continue;
|
||||
/* defaults */
|
||||
hrp->statfile = _PATH_FTPDSTATFILE;
|
||||
hrp->welcome = _PATH_FTPWELCOME;
|
||||
hrp->loginmsg = _PATH_FTPLOGINMESG;
|
||||
hrp->anonuser = "ftp";
|
||||
hrp->next = NULL;
|
||||
lhrp->next = hrp;
|
||||
lhrp = hrp;
|
||||
}
|
||||
(void) memcpy(&hrp->hostaddr,
|
||||
hp->h_addr_list[0],
|
||||
sizeof(hrp->hostaddr));
|
||||
/*
|
||||
* determine hostname to use.
|
||||
* force defined name if it is a valid alias
|
||||
* otherwise fallback to primary hostname
|
||||
*/
|
||||
if ((hp = gethostbyaddr((char*)&hrp->hostaddr,
|
||||
sizeof(hrp->hostaddr),
|
||||
AF_INET)) != NULL) {
|
||||
if (strcmp(cp, hp->h_name) != 0) {
|
||||
if (hp->h_aliases == NULL)
|
||||
cp = hp->h_name;
|
||||
else {
|
||||
i = 0;
|
||||
while (hp->h_aliases[i] &&
|
||||
strcmp(cp, hp->h_aliases[i]) != 0)
|
||||
++i;
|
||||
if (hp->h_aliases[i] == NULL)
|
||||
cp = hp->h_name;
|
||||
}
|
||||
}
|
||||
}
|
||||
hrp->hostname = strdup(cp);
|
||||
/* ok, now we now peel off the rest */
|
||||
i = 0;
|
||||
while (i < 4 && (cp = strtok(NULL, " \t")) != NULL) {
|
||||
if (*cp != '-' && (cp = strdup(cp)) != NULL) {
|
||||
switch (i) {
|
||||
case 0: /* anon user permissions */
|
||||
hrp->anonuser = cp;
|
||||
break;
|
||||
case 1: /* statistics file */
|
||||
hrp->statfile = cp;
|
||||
break;
|
||||
case 2: /* welcome message */
|
||||
hrp->welcome = cp;
|
||||
break;
|
||||
case 3: /* login message */
|
||||
hrp->loginmsg = cp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
(void) fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
selecthost(a)
|
||||
struct in_addr *a;
|
||||
{
|
||||
struct ftphost *hrp;
|
||||
|
||||
hrp = thishost = firsthost; /* default */
|
||||
while (hrp != NULL) {
|
||||
if (memcmp(a, &hrp->hostaddr, sizeof(hrp->hostaddr)) == 0) {
|
||||
thishost = hrp;
|
||||
break;
|
||||
}
|
||||
hrp = hrp->next;
|
||||
}
|
||||
/* setup static variables as appropriate */
|
||||
hostname = thishost->hostname;
|
||||
ftpuser = thishost->anonuser;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Helper function for sgetpwnam().
|
||||
*/
|
||||
@ -606,7 +780,11 @@ user(name)
|
||||
if (checkuser(_PATH_FTPUSERS, "ftp") ||
|
||||
checkuser(_PATH_FTPUSERS, "anonymous"))
|
||||
reply(530, "User %s access denied.", name);
|
||||
#ifdef VIRTUAL_HOSTING
|
||||
else if ((pw = sgetpwnam(thishost->anonuser)) != NULL) {
|
||||
#else
|
||||
else if ((pw = sgetpwnam("ftp")) != NULL) {
|
||||
#endif
|
||||
guest = 1;
|
||||
askpasswd = 1;
|
||||
reply(331,
|
||||
@ -820,7 +998,11 @@ pass(passwd)
|
||||
logged_in = 1;
|
||||
|
||||
if (guest && stats && statfd < 0)
|
||||
#ifdef VIRTUAL_HOSTING
|
||||
if ((statfd = open(thishost->statfile, O_WRONLY|O_APPEND)) < 0)
|
||||
#else
|
||||
if ((statfd = open(_PATH_FTPDSTATFILE, O_WRONLY|O_APPEND)) < 0)
|
||||
#endif
|
||||
stats = 0;
|
||||
|
||||
dochroot =
|
||||
@ -866,7 +1048,11 @@ pass(passwd)
|
||||
* Display a login message, if it exists.
|
||||
* N.B. reply(230,) must follow the message.
|
||||
*/
|
||||
#ifdef VIRTUAL_HOSTING
|
||||
if ((fd = fopen(thishost->loginmsg, "r")) != NULL) {
|
||||
#else
|
||||
if ((fd = fopen(_PATH_FTPLOGINMESG, "r")) != NULL) {
|
||||
#endif
|
||||
char *cp, line[LINE_MAX];
|
||||
|
||||
while (fgets(line, sizeof(line), fd) != NULL) {
|
||||
@ -886,10 +1072,18 @@ pass(passwd)
|
||||
|
||||
reply(230, "Guest login ok, access restrictions apply.");
|
||||
#ifdef SETPROCTITLE
|
||||
snprintf(proctitle, sizeof(proctitle),
|
||||
"%s: anonymous/%.*s", remotehost,
|
||||
sizeof(proctitle) - sizeof(remotehost) -
|
||||
sizeof(": anonymous/"), passwd);
|
||||
#ifdef VIRTUAL_HOSTING
|
||||
if (thishost != firsthost)
|
||||
snprintf(proctitle, sizeof(proctitle),
|
||||
"%s: anonymous(%s)/%.*s", remotehost, hostname,
|
||||
sizeof(proctitle) - sizeof(remotehost) -
|
||||
sizeof(": anonymous/"), passwd);
|
||||
else
|
||||
#endif
|
||||
snprintf(proctitle, sizeof(proctitle),
|
||||
"%s: anonymous/%.*s", remotehost,
|
||||
sizeof(proctitle) - sizeof(remotehost) -
|
||||
sizeof(": anonymous/"), passwd);
|
||||
setproctitle("%s", proctitle);
|
||||
#endif /* SETPROCTITLE */
|
||||
if (logging)
|
||||
@ -899,7 +1093,7 @@ pass(passwd)
|
||||
reply(230, "User %s logged in.", pw->pw_name);
|
||||
#ifdef SETPROCTITLE
|
||||
snprintf(proctitle, sizeof(proctitle),
|
||||
"%s: %s", remotehost, pw->pw_name);
|
||||
"%s: %s", remotehost, pw->pw_name);
|
||||
setproctitle("%s", proctitle);
|
||||
#endif /* SETPROCTITLE */
|
||||
if (logging)
|
||||
@ -1695,12 +1889,26 @@ dolog(sin)
|
||||
(void) strncpy(remotehost, inet_ntoa(sin->sin_addr),
|
||||
sizeof(remotehost));
|
||||
#ifdef SETPROCTITLE
|
||||
snprintf(proctitle, sizeof(proctitle), "%s: connected", remotehost);
|
||||
#ifdef VIRTUAL_HOSTING
|
||||
if (thishost != firsthost)
|
||||
snprintf(proctitle, sizeof(proctitle), "%s: connected (to %s)",
|
||||
remotehost, hostname);
|
||||
else
|
||||
#endif
|
||||
snprintf(proctitle, sizeof(proctitle), "%s: connected",
|
||||
remotehost);
|
||||
setproctitle("%s", proctitle);
|
||||
#endif /* SETPROCTITLE */
|
||||
|
||||
if (logging)
|
||||
syslog(LOG_INFO, "connection from %s", remotehost);
|
||||
if (logging) {
|
||||
#ifdef VIRTUAL_HOSTING
|
||||
if (thishost != firsthost)
|
||||
syslog(LOG_INFO, "connection from %s (to %s)",
|
||||
remotehost, hostname);
|
||||
else
|
||||
#endif
|
||||
syslog(LOG_INFO, "connection from %s", remotehost);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -31,7 +31,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)pathnames.h 8.1 (Berkeley) 6/4/93
|
||||
* $Id: pathnames.h,v 1.8 1997/02/22 14:21:29 peter Exp $
|
||||
* $Id: pathnames.h,v 1.9 1997/04/26 12:12:10 davidn Exp $
|
||||
*/
|
||||
|
||||
#include <paths.h>
|
||||
@ -39,5 +39,6 @@
|
||||
#define _PATH_FTPCHROOT "/etc/ftpchroot"
|
||||
#define _PATH_FTPWELCOME "/etc/ftpwelcome"
|
||||
#define _PATH_FTPLOGINMESG "/etc/ftpmotd"
|
||||
#define _PATH_FTPDSTATFILE "/var/log/ftpd"
|
||||
#define _PATH_LS "/bin/ls"
|
||||
#define _PATH_FTPHOSTS "/etc/ftphosts"
|
||||
#define _PATH_FTPDSTATFILE "/var/log/ftpd"
|
||||
#define _PATH_LS "/bin/ls"
|
||||
|
Loading…
Reference in New Issue
Block a user