[net.unix-wizards] ftpd doesn't log anonymous logins

cak@Purdue.ARPA (01/13/84)

From:  Christopher A Kent <cak@Purdue.ARPA>

Description:
	The FTP daemon doesn't properly log anonymous logins in
/usr/adm/wtmp because the chroot to /usr/ftp is done before wtmp is
opened; thus the open always fails. My previous fix to this was not
wonderful, because while it correctly record logins, it never recorded
logouts. This version does both. I also changed logging to be done via
syslog(3), and now log the ident supplied by anonymous users as well as
all connections.

Repeat-By:
	ftp to localhost, log in as ftp, quit, and do a last. No record.
Fix:
	Apply the following diffs to ftpd.c; note that logging must be
explicitly enabled with -l in /etc/rc.local.

RCS file: RCS/ftpd.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -c -r1.1 -r1.2
*** /tmp/,RCSt1006490	Fri Jan 13 12:21:37 1984
--- /tmp/,RCSt2006490	Fri Jan 13 12:21:43 1984
***************
*** 1,5
  #ifndef lint
! static char rcsid[] = "$Header: /usr/src/etc/ftpd/RCS/ftpd.c,v 1.1 84/01/11 19:46:08 cak Rel $";
  static char sccsid[] = "@(#)ftpd.c	4.28 (Berkeley) 9/22/83";
  #endif
  

--- 1,5 -----
  #ifndef lint
! static char rcsid[] = "$Header: /usr/src/etc/ftpd/RCS/ftpd.c,v 1.2 84/01/13 11:55:30 cak Exp $";
  static char sccsid[] = "@(#)ftpd.c	4.28 (Berkeley) 9/22/83";
  #endif
  
***************
*** 55,60
  int	timeout;
  int	logging;
  int	guest;
  int	type;
  int	form;
  int	stru;			/* avoid C keyword */

--- 55,61 -----
  int	timeout;
  int	logging;
  int	guest;
+ int	wtmp;
  int	type;
  int	form;
  int	stru;			/* avoid C keyword */
***************
*** 235,240
  			pw->pw_name, pw->pw_dir);
  		goto bad;
  	}
  	if (guest && chroot(pw->pw_dir) < 0) {
  		reply(550, "Can't set guest privileges.");
  		goto bad;

--- 236,245 -----
  			pw->pw_name, pw->pw_dir);
  		goto bad;
  	}
+ 
+ 	if (guest)			/* grab wtmp before chroot */
+ 		wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND);
+ 
  	if (guest && chroot(pw->pw_dir) < 0) {
  		reply(550, "Can't set guest privileges.");
  		goto bad;
***************
*** 724,730
  dologin(pw)
  	struct passwd *pw;
  {
- 	int wtmp;
  	char line[32];
  
  	wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND);

--- 729,734 -----
  dologin(pw)
  	struct passwd *pw;
  {
  	char line[32];
  
  	if (guest && (wtmp >= 0))
***************
*** 727,733
  	int wtmp;
  	char line[32];
  
! 	wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND);
  	if (wtmp >= 0) {
  		/* hack, but must be unique and no tty line */
  		sprintf(line, "ftp%d", getpid());

--- 731,740 -----
  {
  	char line[32];
  
! 	if (guest && (wtmp >= 0))
! 		lseek(wtmp, 0, L_XTND);
! 	else
! 		wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND);
  	if (wtmp >= 0) {
  		/* hack, but must be unique and no tty line */
  		sprintf(line, "ftp%d", getpid());
***************
*** 736,742
  		SCPYN(utmp.ut_host, remotehost);
  		utmp.ut_time = time(0);
  		(void) write(wtmp, (char *)&utmp, sizeof (utmp));
! 		(void) close(wtmp);
  	}
  }
  

--- 743,750 -----
  		SCPYN(utmp.ut_host, remotehost);
  		utmp.ut_time = time(0);
  		(void) write(wtmp, (char *)&utmp, sizeof (utmp));
! 		if (!guest)
! 			(void) close(wtmp);
  	}
  }
  
***************
*** 747,754
  dologout(status)
  	int status;
  {
- 	int wtmp;
- 
  	if (!logged_in)
  		_exit(status);
  	seteuid(0);

--- 755,760 -----
  dologout(status)
  	int status;
  {
  	if (!logged_in)
  		_exit(status);
  	seteuid(0);
***************
*** 752,758
  	if (!logged_in)
  		_exit(status);
  	seteuid(0);
! 	wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND);
  	if (wtmp >= 0) {
  		SCPYN(utmp.ut_name, "");
  		SCPYN(utmp.ut_host, "");

--- 758,767 -----
  	if (!logged_in)
  		_exit(status);
  	seteuid(0);
! 	if (guest && (wtmp >= 0))
! 		lseek(wtmp, 0, L_XTND);
! 	else
! 		wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND);
  	if (wtmp >= 0) {
  		SCPYN(utmp.ut_name, "");
  		SCPYN(utmp.ut_host, "");

----------

jsq@ut-sally.UUCP (01/17/84)

Cak@Purdue's fix to logging of anonymous logins by ftpd in wtmp
had several problems.  The following is another fix for the same
but, which has been run by cak for criticism.  I will submit it to
Berkeley shortly.


*** ftpd.c.dist	Tue Jan 17 12:33:52 1984
--- ftpd.c	Tue Jan 17 12:41:11 1984
***************
*** 234,242
  			pw->pw_name, pw->pw_dir);
  		goto bad;
  	}
! 	if (guest && chroot(pw->pw_dir) < 0) {
! 		reply(550, "Can't set guest privileges.");
! 		goto bad;
  	}
  	if (!guest)
  		reply(230, "User %s logged in.", pw->pw_name);

--- 234,246 -----
  			pw->pw_name, pw->pw_dir);
  		goto bad;
  	}
! 	if (guest) {
! 		dologset(1);
!  		if (chroot(pw->pw_dir) < 0) {
! 			dologset(0);
! 			reply(550, "Can't set guest privileges.");
! 			goto bad;
! 		}
  	}
  	if (!guest)
  		reply(230, "User %s logged in.", pw->pw_name);
***************
*** 716,721
  
  #define	SCPYN(a, b)	strncpy(a, b, sizeof (a))
  struct	utmp utmp;
  
  /*
   * Record login in wtmp file.

--- 720,726 -----
  
  #define	SCPYN(a, b)	strncpy(a, b, sizeof (a))
  struct	utmp utmp;
+ int wtmp = -1;
  
  /*
   * Open or close wtmp.
***************
*** 718,723
  struct	utmp utmp;
  
  /*
   * Record login in wtmp file.
   */
  dologin(pw)

--- 723,745 -----
  int wtmp = -1;
  
  /*
+  * Open or close wtmp.
+  */
+ dologset(flag)
+ 	int flag;
+ {
+ 	if (flag) {
+ 		if (wtmp < 0)
+ 			wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND);
+ 		return;
+ 	}
+ 	if (wtmp < 0)
+ 		return;
+ 	(void) close (wtmp);
+ 	wtmp = -1;
+ }
+ 
+ /*
   * Record login in wtmp file.
   */
  dologin(pw)
***************
*** 723,729
  dologin(pw)
  	struct passwd *pw;
  {
- 	int wtmp;
  	char line[32];
  
  	wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND);

--- 745,750 -----
  dologin(pw)
  	struct passwd *pw;
  {
  	char line[32];
  
  	dologset(1);
***************
*** 726,732
  	int wtmp;
  	char line[32];
  
! 	wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND);
  	if (wtmp >= 0) {
  		/* hack, but must be unique and no tty line */
  		sprintf(line, "ftp%d", getpid());

--- 747,753 -----
  {
  	char line[32];
  
! 	dologset(1);
  	if (wtmp >= 0) {
  		/* hack, but must be unique and no tty line */
  		sprintf(line, "ftp%d", getpid());
***************
*** 735,741
  		SCPYN(utmp.ut_host, remotehost);
  		utmp.ut_time = time(0);
  		(void) write(wtmp, (char *)&utmp, sizeof (utmp));
! 		(void) close(wtmp);
  	}
  }
  

--- 756,763 -----
  		SCPYN(utmp.ut_host, remotehost);
  		utmp.ut_time = time(0);
  		(void) write(wtmp, (char *)&utmp, sizeof (utmp));
! 		if (!guest)
! 			dologset(0);
  	}
  }
  
***************
*** 746,753
  dologout(status)
  	int status;
  {
- 	int wtmp;
- 
  	if (!logged_in)
  		_exit(status);
  	seteuid(0);

--- 768,773 -----
  dologout(status)
  	int status;
  {
  	if (!logged_in)
  		_exit(status);
  	seteuid(0);
***************
*** 751,757
  	if (!logged_in)
  		_exit(status);
  	seteuid(0);
! 	wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND);
  	if (wtmp >= 0) {
  		SCPYN(utmp.ut_name, "");
  		SCPYN(utmp.ut_host, "");

--- 771,778 -----
  	if (!logged_in)
  		_exit(status);
  	seteuid(0);
! 	if (!guest)
! 		dologset(1);
  	if (wtmp >= 0) {
  		SCPYN(utmp.ut_name, "");
  		SCPYN(utmp.ut_host, "");
***************
*** 757,763
  		SCPYN(utmp.ut_host, "");
  		utmp.ut_time = time(0);
  		(void) write(wtmp, (char *)&utmp, sizeof (utmp));
! 		(void) close(wtmp);
  	}
  	/* beware of flushing buffers after a SIGPIPE */
  	_exit(status);

--- 778,784 -----
  		SCPYN(utmp.ut_host, "");
  		utmp.ut_time = time(0);
  		(void) write(wtmp, (char *)&utmp, sizeof (utmp));
! 		dologset(0);
  	}
  	/* beware of flushing buffers after a SIGPIPE */
  	_exit(status);
-- 
John Quarterman, CS Dept., University of Texas, Austin, Texas
{ihnp4,seismo,ctvax}!ut-sally!jsq, jsq@ut-sally.{ARPA,UUCP}