Ftpd uses two logfile. The one is for ordinally operation, and is recorded via syslogd(8). Another one is for file transfer, and is recorded by ftpd itself. Default xferlog location is /var/log/ftpd (macro _PATH_FTPDSTATFILE defined in <pathnames.h>), however, you can change the localtion by /etc/ftphosts. There is no problem about logfile via syslogd. But if you want to record transfer history to /var/log/ftpd and want to do some aging by newsyslog(8), you found ftpd is too poor to handle this file. /var/log/ftpd is opened when you logged on (ftpd.c, pass()). If a file retrieve is successfully done (ftpd.c, retrieve()), ftpd records the results via logxfer(). Yes, ftpd does assume that "statfd (file descriptor for /var/log/ftpd) is *always* available while ftpd is running". Ftpd does not consider that logfile is moved away, gzipped, or whatever else. Logfile which does not have *all* log is not a logfile. I do not want to loss any messages from ftpd. Fix: Some approaches comes to me: 1) Use syslogd for xferlog also. pros: avoids (potentially) all problems about logfile. cons: difficult to separate xferlog and others. 2) logxfer() in ftpd.c does open(2)-write(2)-close(2) xferlog. pros: low impact to current implementation. cons: when newsyslog (or other aging tool) moves xferlog, and not yet touch(1)ed, ftpd will lost its logfile. 3) ftpd re-opens xferlog iff SIGHUP is catched up. pros: much smarter than 2). cons: you may want to run standalone ftpd (-D and -p option will help). daemon ftpd is maybe not welcomed to not-so-busy ftp servers. Any approaches are welcome for me. How about 1) + "enable feature of 1) with yet another option ?". How-To-Repeat: * prepare logfile by 'touch /var/log/ftpd'; ftpd does not record if file is not found. * Enable ftpd in /etc/inetd.conf, and run inetd (is default). * connect to ftpd. * get some files, then check /var/log/ftpd and you can see your transfer history. * do "mv /var/log/ftpd /var/log/ftpd.old; touch /var/log/ftpd". or use newsyslogd(8) to rotate current logfile. * get some files again. You cannot see any logs in /var/log/ftpd.
According to the suggestion by sheldonh@uunet.co.za, here is a summary of other BSDs approach about this issue. Short summary: We cannot pick some codes from other BSDs to fix :-) *** - NetBSD (fetched from anonymous CVS, ftpd.c revision 1.99) It seems that NetBSD does not implement -S option and its feature provided by the one of FreeBSD. - OpenBSD (fetched from anonymous ftp, ftpd.c revision 1.77) OpenBSD have the same feature (option -S) and similar implementation of the one of FreeBSD. Yes, it seems that the same problem exists. - BSD/OS (fetched from CD-ROM of BSD/OS 4.1, ftpd.c revision 1.13) BSD/OS also provides xferlog feature by a little bit different way (available by configulation file, not an option. -S option exists, but its means is different). However, it's implementation is similar to the one of FreeBSD; it seems that the same problem exists. -- - Makoto `MAR' MATSUSHITA
After some additional investigation, matusita> 1) Use syslogd for xferlog also. It is substitutable by 'ftpd -l -l'. Practically it is not the same of xferlog, however, it works *now*. matusita> 2) logxfer() in ftpd.c does open(2)-write(2)-close(2) xferlog. matusita> 3) ftpd re-opens xferlog iff SIGHUP is catched up. This requires ftpd can open xferlog *at any time*. What if ftpd runs for user 'anonymous' or whatever user who is listed on /etc/ftpchroot ? Anyway, matusita> How about 1) + "enable feature of 1) with yet another matusita> option ?". -- - Makoto `MAR' MATSUSHITA
matusita> How about 1) + "enable feature of 1) with yet another matusita> option ?". Here is an sample implementation. New option '-s', just like '-S' but uses syslog() to record. -- - Makoto `MAR' MATSUSHITA Index: ftpd.c =================================================================== RCS file: /pub/cvsup/FreeBSD.cvs/src/libexec/ftpd/ftpd.c,v retrieving revision 1.64 diff -c -r1.64 ftpd.c *** ftpd.c 2000/06/26 05:36:09 1.64 --- ftpd.c 2000/07/25 05:10:43 *************** *** 141,146 **** --- 141,147 ---- int dochroot; int stats; int statfd = -1; + int statssyslog; int type; int form; int stru; /* avoid C keyword */ *************** *** 290,296 **** #endif /* OLD_SETPROCTITLE */ ! while ((ch = getopt(argc, argv, "AdlDSURt:T:u:va:p:46")) != -1) { switch (ch) { case 'D': daemon_mode++; --- 291,297 ---- #endif /* OLD_SETPROCTITLE */ ! while ((ch = getopt(argc, argv, "AdlDSsURt:T:u:va:p:46")) != -1) { switch (ch) { case 'D': daemon_mode++; *************** *** 312,317 **** --- 313,322 ---- stats++; break; + case 's': + statssyslog++; + break; + case 'T': maxtimeout = atoi(optarg); if (timeout > maxtimeout) *************** *** 1435,1441 **** time(&start); send_data(fin, dout, st.st_blksize, st.st_size, restart_point == 0 && cmd == 0 && S_ISREG(st.st_mode)); ! if (cmd == 0 && guest && stats) logxfer(name, st.st_size, start); (void) fclose(dout); data = -1; --- 1440,1446 ---- time(&start); send_data(fin, dout, st.st_blksize, st.st_size, restart_point == 0 && cmd == 0 && S_ISREG(st.st_mode)); ! if (cmd == 0 && guest && (stats || statssyslog)) logxfer(name, st.st_size, start); (void) fclose(dout); data = -1; *************** *** 2777,2787 **** char path[MAXPATHLEN + 1]; time_t now; ! if (statfd >= 0 && getwd(path) != NULL) { time(&now); snprintf(buf, sizeof(buf), "%.20s!%s!%s!%s/%s!%ld!%ld\n", ctime(&now)+4, ident, remotehost, path, name, size, now - start + (now == start)); ! write(statfd, buf, strlen(buf)); } } --- 2782,2795 ---- char path[MAXPATHLEN + 1]; time_t now; ! if (getwd(path) != NULL) { time(&now); snprintf(buf, sizeof(buf), "%.20s!%s!%s!%s/%s!%ld!%ld\n", ctime(&now)+4, ident, remotehost, path, name, size, now - start + (now == start)); ! if (statfd >= 0) ! write(statfd, buf, strlen(buf)); ! if (statssyslog) ! syslog(LOG_INFO, buf); } }
On Mon, Jul 24, 2000 at 10:20:04PM -0700, Makoto MATSUSHITA wrote: [snip] > ! if (statssyslog) > ! syslog(LOG_INFO, buf); I'd suggest syslog(LOG_INFO, "%s", buf) - no need to create yet another potential format-string vulnerability ;) G'luck, Peter Pentchev -- If this sentence didn't exist, somebody would have invented it.
roam> I'd suggest syslog(LOG_INFO, "%s", buf) - no need to create yet roam> another potential format-string vulnerability ;) Oops, very sorry... -- - Makoto `MAR' MATSUSHITA
Here is a status of this PR. * Not assigned to a person. * NetBSD, OpenBSD, and BSD/OS does not consider about this situation. Maybe it is somewhat hard to solve... * Sample fix to add a new option '-S' (use syslog to record xfer history). I'm very happy if the patch is included (I'm using ftpd with this patch to provide anonymous ftp service). But if not, it is O.K. to close this PR; we can check this PR later to know what's the problem. -- - Makoto `MAR' MATSUSHITA
Responsible Changed From-To: freebsd-bugs->yar Over to Yar.
Responsible Changed From-To: yar->freebsd-bugs over to the pool (with bugmeister approval). I have not verified this still a problem
For bugs matching the following criteria: Status: In Progress Changed: (is less than) 2014-06-01 Reset to default assignee and clear in-progress tags. Mail being skipped