Bug 20054 - ftpd(8) rotating _PATH_FTPDSTATFILE losts xferlog
Summary: ftpd(8) rotating _PATH_FTPDSTATFILE losts xferlog
Status: Open
Alias: None
Product: Base System
Classification: Unclassified
Component: bin (show other bugs)
Version: 5.0-CURRENT
Hardware: Any Any
: Normal Affects Only Me
Assignee: freebsd-bugs (Nobody)
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2000-07-20 10:50 UTC by Makoto Matsushita
Modified: 2018-01-03 05:16 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Makoto Matsushita 2000-07-20 10:50:01 UTC
	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.
Comment 1 Makoto Matsushita 2000-07-20 14:44:36 UTC
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
Comment 2 Makoto Matsushita 2000-07-25 02:26:37 UTC
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
Comment 3 Makoto Matsushita 2000-07-25 06:18:58 UTC
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);
  	}
  }
Comment 4 Peter Pentchev 2000-07-25 08:35:44 UTC
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.
Comment 5 Makoto Matsushita 2000-07-25 08:48:25 UTC
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
Comment 6 Makoto Matsushita 2000-09-27 05:37:35 UTC
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
Comment 7 Johan Karlsson freebsd_committer freebsd_triage 2002-08-21 20:50:21 UTC
Responsible Changed
From-To: freebsd-bugs->yar

Over to Yar.
Comment 8 Eitan Adler freebsd_committer freebsd_triage 2012-07-10 04:35:13 UTC
Responsible Changed
From-To: yar->freebsd-bugs

over to the pool (with bugmeister approval). I have not verified this 
still a problem
Comment 9 Eitan Adler freebsd_committer freebsd_triage 2017-12-31 08:00:13 UTC
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