svn commit: r202209 - head/libexec/ftpd

Ed Schouten ed at FreeBSD.org
Wed Jan 13 18:28:41 UTC 2010


Author: ed
Date: Wed Jan 13 18:28:41 2010
New Revision: 202209
URL: http://svn.freebsd.org/changeset/base/202209

Log:
  Port ftpd to utmpx.
  
  Unfortunately I have to partially wreck its functionality, though. ftpd
  used to keep a file descriptor to the wtmp, which allowed it to work
  from within a chroot. The current utmpx implementation doesn't offer a
  way to do this. Maybe we can address this in the future, if it turns out
  to be a real issue.

Modified:
  head/libexec/ftpd/ftpd.c
  head/libexec/ftpd/logwtmp.c

Modified: head/libexec/ftpd/ftpd.c
==============================================================================
--- head/libexec/ftpd/ftpd.c	Wed Jan 13 18:25:43 2010	(r202208)
+++ head/libexec/ftpd/ftpd.c	Wed Jan 13 18:28:41 2010	(r202209)
@@ -173,8 +173,7 @@ static struct ftphost {
 char	remotehost[NI_MAXHOST];
 char	*ident = NULL;
 
-static char	ttyline[20];
-char		*tty = ttyline;		/* for klogin */
+static char	wtmpid[20];
 
 #ifdef USE_PAM
 static int	auth_pam(struct passwd**, const char*);
@@ -584,8 +583,7 @@ gotchild:
 
 	data_source.su_port = htons(ntohs(ctrl_addr.su_port) - 1);
 
-	/* set this here so klogin can use it... */
-	(void)snprintf(ttyline, sizeof(ttyline), "ftp%d", getpid());
+	(void)snprintf(wtmpid, sizeof(wtmpid), "%xftpd", getpid());
 
 	/* Try to handle urgent data inline */
 #ifdef SO_OOBINLINE
@@ -1180,8 +1178,8 @@ end_login(void)
 #endif
 
 	(void) seteuid(0);
-	if (logged_in && dowtmp)
-		ftpd_logwtmp(ttyline, "", NULL);
+	if (logged_in && dowtmp && !dochroot)
+		ftpd_logwtmp(wtmpid, "", NULL);
 	pw = NULL;
 #ifdef	LOGIN_CAP
 	setusercontext(NULL, getpwuid(0), 0,
@@ -1476,9 +1474,16 @@ skip:
 	}
 #endif
 
-	/* open wtmp before chroot */
-	if (dowtmp)
-		ftpd_logwtmp(ttyline, pw->pw_name,
+	dochroot =
+		checkuser(_PATH_FTPCHROOT, pw->pw_name, 1, &residue)
+#ifdef	LOGIN_CAP	/* Allow login.conf configuration as well */
+		|| login_getcapbool(lc, "ftp-chroot", 0)
+#endif
+	;
+	chrootdir = NULL;
+
+	if (dowtmp && !dochroot)
+		ftpd_logwtmp(wtmpid, pw->pw_name,
 		    (struct sockaddr *)&his_addr);
 	logged_in = 1;
 
@@ -1491,13 +1496,6 @@ skip:
 		if (statfd < 0)
 			stats = 0;
 
-	dochroot =
-		checkuser(_PATH_FTPCHROOT, pw->pw_name, 1, &residue)
-#ifdef	LOGIN_CAP	/* Allow login.conf configuration as well */
-		|| login_getcapbool(lc, "ftp-chroot", 0)
-#endif
-	;
-	chrootdir = NULL;
 	/*
 	 * For a chrooted local user,
 	 * a) see whether ftpchroot(5) specifies a chroot directory,
@@ -2732,9 +2730,9 @@ void
 dologout(int status)
 {
 
-	if (logged_in && dowtmp) {
+	if (logged_in && dowtmp && !dochroot) {
 		(void) seteuid(0);
-		ftpd_logwtmp(ttyline, "", NULL);
+		ftpd_logwtmp(wtmpid, "", NULL);
 	}
 	/* beware of flushing buffers after a SIGPIPE */
 	_exit(status);

Modified: head/libexec/ftpd/logwtmp.c
==============================================================================
--- head/libexec/ftpd/logwtmp.c	Wed Jan 13 18:25:43 2010	(r202208)
+++ head/libexec/ftpd/logwtmp.c	Wed Jan 13 18:28:41 2010	(r202209)
@@ -46,47 +46,35 @@ __FBSDID("$FreeBSD$");
 #include <arpa/inet.h>
 #include <sys/socket.h>
 
-#include <fcntl.h>
-#include <time.h>
-#include <timeconv.h>
-#include <netdb.h>
-#include <utmp.h>
-#include <unistd.h>
+#include <libutil.h>
 #include <stdio.h>
 #include <string.h>
-#include <libutil.h>
+#include <unistd.h>
+#include <utmpx.h>
 #include "extern.h"
 
-static int fd = -1;
-
-/*
- * Modified version of logwtmp that holds wtmp file open
- * after first call, for use with ftp (which may chroot
- * after login, but before logout).
- */
 void
-ftpd_logwtmp(line, name, addr)
-	char *line, *name;
-	struct sockaddr *addr;
+ftpd_logwtmp(char *id, char *user, struct sockaddr *addr)
 {
-	struct utmp ut;
-	struct stat buf;
-	char host[UT_HOSTSIZE];
-
-	if (addr == NULL)
-		host[0] = '\0';
-	else
-		realhostname_sa(host, sizeof(host), addr, addr->sa_len);
-
-	if (fd < 0 && (fd = open(_PATH_WTMP, O_WRONLY|O_APPEND, 0)) < 0)
-		return;
-	if (fstat(fd, &buf) == 0) {
-		(void)strncpy(ut.ut_line, line, sizeof(ut.ut_line));
-		(void)strncpy(ut.ut_name, name, sizeof(ut.ut_name));
-		(void)strncpy(ut.ut_host, host, sizeof(ut.ut_host));
-		ut.ut_time = _time_to_time32(time(NULL));
-		if (write(fd, &ut, sizeof(struct utmp)) !=
-		    sizeof(struct utmp))
-			(void)ftruncate(fd, buf.st_size);
+	struct utmpx ut;
+
+	memset(&ut, 0, sizeof(ut));
+
+	if (*user != '\0') {
+		/* Log in. */
+		ut.ut_type = USER_PROCESS;
+		(void)strncpy(ut.ut_user, user, sizeof(ut.ut_user));
+		if (addr != NULL)
+			realhostname_sa(ut.ut_host, sizeof(ut.ut_host),
+			    addr, addr->sa_len);
+	} else {
+		/* Log out. */
+		ut.ut_type = DEAD_PROCESS;
 	}
+
+	ut.ut_pid = getpid();
+	gettimeofday(&ut.ut_tv, NULL);
+	(void)strncpy(ut.ut_id, id, sizeof(ut.ut_id));
+
+	pututxline(&ut);
 }


More information about the svn-src-all mailing list