[comp.bugs.4bsd] More extensive logging for ftpd

ehrlich@psuvax1.psu.edu (Dan Ehrlich) (09/13/87)

Below are a set of patches to ftpd.c that result in most file
operations being logged if logging is enabled.  Modify the entry in
/etc/inetd.conf to pass "-l" to ftpd when it gets cranked up.  Here is
the entry from our inetd.conf:

ftp	stream	tcp	nowait	root	/etc/ftpd	ftpd -l


RCS file: RCS/ftpd.c,v
retrieving revision 1.1
retrieving revision 1.4
diff -c -r1.1 -r1.4
*** /tmp/,RCSt1028386	Sun Sep 13 09:23:58 1987
--- /tmp/,RCSt2028386	Sun Sep 13 09:24:01 1987
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   */
! 
  #ifndef lint
  char copyright[] =
  "@(#) Copyright (c) 1985 Regents of the University of California.\n\
--- 3,23 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   */
! /*
!  * $Header: ftpd.c,v 1.4 87/09/11 11:13:47 ehrlich Exp $
!  * $Source: /usr/src/etc/ftpd/RCS/ftpd.c,v $
!  * $Log:	ftpd.c,v $
!  * Revision 1.4  87/09/11  11:13:47  ehrlich
!  * Clean up log messages a bit.  --dre
!  * 
!  * Revision 1.3  87/09/11  10:15:37  ehrlich
!  * More extensive logging on file operations.  --dre
!  * 
!  * Revision 1.2  87/01/15  09:22:57  ehrlich
!  * Log anonymous ftp logins with remote host name and remote user ident.
!  * dre
!  * 
!  */
  #ifndef lint
  char copyright[] =
  "@(#) Copyright (c) 1985 Regents of the University of California.\n\
***************
*** 12,17 ****
--- 26,33 ----
  
  #ifndef lint
  static char sccsid[] = "@(#)ftpd.c	5.7 (Berkeley) 5/28/86";
+ static char *RCShdr = "$Header: ftpd.c,v 1.4 87/09/11 11:13:47 ehrlich Exp $";
+ static char *RCSsrc = "$Source: /usr/src/etc/ftpd/RCS/ftpd.c,v $";
  #endif not lint
  
  /*
***************
*** 54,59 ****
--- 70,76 ----
  extern	FILE *popen(), *fopen(), *freopen();
  extern	int  pclose(), fclose();
  extern	char *getline();
+ extern	char *ctime();
  extern	char cbuf[];
  
  struct	sockaddr_in ctrl_addr;
***************
*** 81,86 ****
--- 98,104 ----
  char	tmpline[7];
  char	hostname[32];
  char	remotehost[32];
+ char	password[32];
  
  /*
   * Timeout intervals for retrying connections
***************
*** 105,110 ****
--- 123,129 ----
  	long pgid;
  	char *cp;
  
+ 	openlog("ftpd", LOG_PID | LOG_CONS | LOG_NOWAIT, LOG_DAEMON);
  	addrlen = sizeof (his_addr);
  	if (getpeername(0, &his_addr, &addrlen) < 0) {
  		syslog(LOG_ERR, "getpeername (%s): %m",argv[0]);
***************
*** 117,123 ****
  	}
  	data_source.sin_port = htons(ntohs(ctrl_addr.sin_port) - 1);
  	debug = 0;
- 	openlog("ftpd", LOG_PID, LOG_DAEMON);
  	argc--, argv++;
  	while (argc > 0 && *argv[0] == '-') {
  		for (cp = &argv[0][1]; *cp; cp++) switch (*cp) {
--- 136,141 ----
***************
*** 177,182 ****
--- 195,202 ----
  	(void) gethostname(hostname, sizeof (hostname));
  	reply(220, "%s FTP server (%s) ready.",
  		hostname, version);
+ 	if (logging)
+ 	    syslog(LOG_INFO, "%s FTP server (%s) ready.", hostname, version);
  	for (;;) {
  		(void) setjmp(errcatch);
  		(void) yyparse();
***************
*** 187,193 ****
  {
  
  	if (debug)
! 		syslog(LOG_DEBUG, "lost connection");
  	dologout(-1);
  }
  
--- 207,213 ----
  {
  
  	if (debug)
! 		syslog(LOG_DEBUG, "lost connection with %s", remotehost);
  	dologout(-1);
  }
  
***************
*** 205,220 ****
  		xpasswd = crypt(passwd, pw->pw_passwd);
  		/* The strcmp does not catch null passwords! */
  		if (*pw->pw_passwd == '\0' || strcmp(xpasswd, pw->pw_passwd)) {
  			reply(530, "Login incorrect.");
  			pw = NULL;
  			return;
  		}
! 	}
  	setegid(pw->pw_gid);
  	initgroups(pw->pw_name, pw->pw_gid);
  	if (chdir(pw->pw_dir)) {
  		reply(530, "User %s: can't change directory to %s.",
  			pw->pw_name, pw->pw_dir);
  		goto bad;
  	}
  
--- 225,246 ----
  		xpasswd = crypt(passwd, pw->pw_passwd);
  		/* The strcmp does not catch null passwords! */
  		if (*pw->pw_passwd == '\0' || strcmp(xpasswd, pw->pw_passwd)) {
+ 			if(logging)
+ 			    syslog(LOG_INFO, "Login incorrect, user = %s.", pw->pw_name);
  			reply(530, "Login incorrect.");
  			pw = NULL;
  			return;
  		}
! 	} else	/* If guest, password is ident of remote user.  Tuck it away */
! 		strncpy(password, passwd, sizeof(password));
  	setegid(pw->pw_gid);
  	initgroups(pw->pw_name, pw->pw_gid);
  	if (chdir(pw->pw_dir)) {
  		reply(530, "User %s: can't change directory to %s.",
  			pw->pw_name, pw->pw_dir);
+ 		if(logging)
+ 		    syslog(LOG_INFO, "User %s: can't change directory to %s.",
+ 			pw->pw_name, pw->pw_dir);
  		goto bad;
  	}
  
***************
*** 222,227 ****
--- 248,255 ----
  	wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND);
  	if (guest && chroot(pw->pw_dir) < 0) {
  		reply(550, "Can't set guest privileges.");
+ 		if(logging)
+ 		    syslog(LOG_INFO, "Can't set guest privileges: %m");
  		if (wtmp >= 0) {
  			(void) close(wtmp);
  			wtmp = -1;
***************
*** 228,237 ****
  		}
  		goto bad;
  	}
! 	if (!guest)
  		reply(230, "User %s logged in.", pw->pw_name);
! 	else
  		reply(230, "Guest login ok, access restrictions apply.");
  	logged_in = 1;
  	dologin(pw);
  	seteuid(pw->pw_uid);
--- 256,269 ----
  		}
  		goto bad;
  	}
! 	if (!guest) {
  		reply(230, "User %s logged in.", pw->pw_name);
! 		if(logging)
! 		    syslog(LOG_INFO, "User %s logged in from %s", pw->pw_name,
! 			remotehost);
! 	} else {
  		reply(230, "Guest login ok, access restrictions apply.");
+ 	}
  	logged_in = 1;
  	dologin(pw);
  	seteuid(pw->pw_uid);
***************
*** 298,303 ****
--- 330,338 ----
  		reply(550, "%s: not a plain file.", name);
  		goto done;
  	}
+ 	if (logging)
+ 	    syslog(LOG_INFO, "%s at %s retrieving %s",
+ 		(guest ? password : pw->pw_name), remotehost, name);
  	dout = dataconn(name, st.st_size, "w");
  	if (dout == NULL)
  		goto done;
***************
*** 346,351 ****
--- 381,389 ----
  		reply(553, "%s: %s.", local, sys_errlist[errno]);
  		return;
  	}
+ 	if (logging)
+ 	    syslog(LOG_INFO, "%s at %s storing %s",
+ 		(guest ? password : pw->pw_name), remotehost, name);
  	din = dataconn(local, (off_t)-1, "r");
  	if (din == NULL)
  		goto done;
***************
*** 588,593 ****
--- 626,633 ----
  fatal(s)
  	char *s;
  {
+ 	if (logging)
+ 	    syslog(LOG_ERR, "Error in server: %s", s);
  	reply(451, "Error in server: %s\n", s);
  	reply(221, "Closing connection due to server error.");
  	dologout(0);
***************
*** 655,660 ****
--- 695,703 ----
  		reply(550, "%s: %s.", name, sys_errlist[errno]);
  		return;
  	}
+ 	if (logging)
+ 	    syslog(LOG_INFO, "%s at %s deleting %s",
+ 		(guest ? password : pw->pw_name), remotehost, name);
  	if ((st.st_mode&S_IFMT) == S_IFDIR) {
  		if (rmdir(name) < 0) {
  			reply(550, "%s: %s.", name, sys_errlist[errno]);
***************
*** 687,692 ****
--- 730,738 ----
  	struct stat st;
  	int dochown = stat(name, &st) < 0;
  	
+ 	if (logging)
+ 	    syslog(LOG_INFO, "%s at %s creating directory %s",
+ 		(guest ? password : pw->pw_name), remotehost, name);
  	if (mkdir(name, 0777) < 0) {
  		reply(550, "%s: %s.", name, sys_errlist[errno]);
  		return;
***************
*** 700,705 ****
--- 746,754 ----
  	char *name;
  {
  
+ 	if (logging)
+ 	    syslog(LOG_INFO, "%s at %s deleting directory %s",
+ 		(guest ? password : pw->pw_name), remotehost, name);
  	if (rmdir(name) < 0) {
  		reply(550, "%s: %s.", name, sys_errlist[errno]);
  		return;
***************
*** 736,741 ****
--- 785,793 ----
  	char *from, *to;
  {
  
+ 	if (logging)
+ 	    syslog(LOG_INFO, "%s at %s renaming %s to %s",
+ 		(guest ? password : pw->pw_name), remotehost, from, to);
  	if (rename(from, to) < 0) {
  		reply(550, "rename: %s.", sys_errlist[errno]);
  		return;
***************
*** 749,755 ****
  	struct hostent *hp = gethostbyaddr(&sin->sin_addr,
  		sizeof (struct in_addr), AF_INET);
  	time_t t;
- 	extern char *ctime();
  
  	if (hp) {
  		(void) strncpy(remotehost, hp->h_name, sizeof (remotehost));
--- 801,806 ----
***************
*** 760,766 ****
  	if (!logging)
  		return;
  	t = time((time_t *) 0);
! 	syslog(LOG_INFO,"FTPD: connection from %s at %s", remotehost, ctime(&t));
  }
  
  #include <utmp.h>
--- 811,817 ----
  	if (!logging)
  		return;
  	t = time((time_t *) 0);
! 	syslog(LOG_INFO,"connection from %s at %s", remotehost, ctime(&t));
  }
  
  #include <utmp.h>
***************
*** 789,794 ****
--- 840,849 ----
  			wtmp = -1;
  		}
  	}
+ 	if (guest) {
+ 		syslog(LOG_INFO, "Anonymous login from \"%s\" by \"%s\"",
+ 				remotehost, password);
+ 	}
  }
  
  /*
***************
*** 809,814 ****
--- 864,877 ----
  			utmp.ut_time = (long) time((time_t *) 0);
  			(void) write(wtmp, (char *)&utmp, sizeof (utmp));
  			(void) close(wtmp);
+ 		}
+ 		if(logging) {
+ 		    if(guest)
+ 			syslog(LOG_INFO, "Guest %s at %s logged out",
+ 			    password, remotehost);
+ 		    else
+ 			syslog(LOG_INFO, "%s@%s logged out", pw->pw_name,
+ 			    remotehost);
  		}
  	}
  	/* beware of flushing buffers after a SIGPIPE */