diff options
author | davidn <davidn@FreeBSD.org> | 1997-04-29 12:42:08 +0000 |
---|---|---|
committer | davidn <davidn@FreeBSD.org> | 1997-04-29 12:42:08 +0000 |
commit | 55c9dac45043b0c4199aaca4735cfa1d01b209e5 (patch) | |
tree | cc9b7f6114cd7e1018bffafa906e16f8eda8fb09 /libexec/ftpd/ftpd.c | |
parent | 559a468aae13aa79431fd99e4f039cabcaa507f4 (diff) | |
download | FreeBSD-src-55c9dac45043b0c4199aaca4735cfa1d01b209e5.zip FreeBSD-src-55c9dac45043b0c4199aaca4735cfa1d01b209e5.tar.gz |
Adds anon ftp virtual host capability to ftpd, using /etc/ftphosts for
definition of a system's virtual hosts.
Diffstat (limited to 'libexec/ftpd/ftpd.c')
-rw-r--r-- | libexec/ftpd/ftpd.c | 226 |
1 files changed, 217 insertions, 9 deletions
diff --git a/libexec/ftpd/ftpd.c b/libexec/ftpd/ftpd.c index 65e5b97..82c10dd 100644 --- a/libexec/ftpd/ftpd.c +++ b/libexec/ftpd/ftpd.c @@ -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 @@ skip: 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 @@ skip: * 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 @@ skip: 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 @@ skip: 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); + } } /* |