svn commit: r216932 - head/libexec/ftpd

Christian S.J. Peron csjp at FreeBSD.org
Mon Jan 3 21:28:12 UTC 2011


Author: csjp
Date: Mon Jan  3 21:28:12 2011
New Revision: 216932
URL: http://svn.freebsd.org/changeset/base/216932

Log:
  expand checkuser() to support the propagation of error codes back to
  the caller.  Currently, checkuser() does not differentiate between the
  failure to open the file and the absence of a user in the file.  Check
  to see if there was an error opening the file.  If there are any errors,
  terminate the connection.  Currently, the only exception to this rule
  is ENOENT, since there is nothing that says the /etc/ftpuser
  and /etc/ftpchroot has to exist.
  
  MFC after:	3 weeks

Modified:
  head/libexec/ftpd/ftpd.c

Modified: head/libexec/ftpd/ftpd.c
==============================================================================
--- head/libexec/ftpd/ftpd.c	Mon Jan  3 20:37:31 2011	(r216931)
+++ head/libexec/ftpd/ftpd.c	Mon Jan  3 21:28:12 2011	(r216932)
@@ -244,7 +244,7 @@ static void	 sigurg(int);
 static void	 maskurg(int);
 static void	 flagxfer(int);
 static int	 myoob(void);
-static int	 checkuser(char *, char *, int, char **);
+static int	 checkuser(char *, char *, int, char **, int *);
 static FILE	*dataconn(char *, off_t, char *);
 static void	 dolog(struct sockaddr *);
 static void	 end_login(void);
@@ -996,6 +996,7 @@ static char curname[MAXLOGNAME];	/* curr
 void
 user(char *name)
 {
+	int ecode;
 	char *cp, *shell;
 
 	if (logged_in) {
@@ -1016,8 +1017,11 @@ user(char *name)
 	pw = sgetpwnam("ftp");
 #endif
 	if (strcmp(name, "ftp") == 0 || strcmp(name, "anonymous") == 0) {
-		if (checkuser(_PATH_FTPUSERS, "ftp", 0, NULL) ||
-		    checkuser(_PATH_FTPUSERS, "anonymous", 0, NULL))
+		if (checkuser(_PATH_FTPUSERS, "ftp", 0, NULL, &ecode) ||
+		    (ecode != 0 && ecode != ENOENT))
+			reply(530, "User %s access denied.", name);
+		else if (checkuser(_PATH_FTPUSERS, "anonymous", 0, NULL, &ecode) ||
+		    (ecode != 0 && ecode != ENOENT))
 			reply(530, "User %s access denied.", name);
 		else if (pw != NULL) {
 			guest = 1;
@@ -1045,7 +1049,9 @@ user(char *name)
 				break;
 		endusershell();
 
-		if (cp == NULL || checkuser(_PATH_FTPUSERS, name, 1, NULL)) {
+		if (cp == NULL || 
+		    (checkuser(_PATH_FTPUSERS, name, 1, NULL, &ecode) ||
+		    (ecode != 0 && ecode != ENOENT))) {
 			reply(530, "User %s access denied.", name);
 			if (logging)
 				syslog(LOG_NOTICE,
@@ -1087,13 +1093,15 @@ user(char *name)
  * of the matching line in "residue" if not NULL.
  */
 static int
-checkuser(char *fname, char *name, int pwset, char **residue)
+checkuser(char *fname, char *name, int pwset, char **residue, int *ecode)
 {
 	FILE *fd;
 	int found = 0;
 	size_t len;
 	char *line, *mp, *p;
 
+	if (ecode != NULL)
+		*ecode = 0;
 	if ((fd = fopen(fname, "r")) != NULL) {
 		while (!found && (line = fgetln(fd, &len)) != NULL) {
 			/* skip comments */
@@ -1162,7 +1170,8 @@ nextline:
 				free(mp);
 		}
 		(void) fclose(fd);
-	}
+	} else if (ecode != NULL)
+		*ecode = errno;
 	return (found);
 }
 
@@ -1359,7 +1368,7 @@ auth_pam(struct passwd **ppw, const char
 void
 pass(char *passwd)
 {
-	int rval;
+	int rval, ecode;
 	FILE *fd;
 #ifdef	LOGIN_CAP
 	login_cap_t *lc = NULL;
@@ -1475,11 +1484,21 @@ skip:
 #endif
 
 	dochroot =
-		checkuser(_PATH_FTPCHROOT, pw->pw_name, 1, &residue)
+		checkuser(_PATH_FTPCHROOT, pw->pw_name, 1, &residue, &ecode)
 #ifdef	LOGIN_CAP	/* Allow login.conf configuration as well */
 		|| login_getcapbool(lc, "ftp-chroot", 0)
 #endif
 	;
+	/*
+	 * It is possible that checkuser() failed to open the chroot file.
+	 * If this is the case, report that logins are un-available, since we
+	 * have no way of checking whether or not the user should be chrooted.
+	 * We ignore ENOENT since it is not required that this file be present.
+	 */
+	if (ecode != 0 && ecode != ENOENT) {
+		reply(530, "Login not available right now.");
+		return;
+	}
 	chrootdir = NULL;
 
 	/* Disable wtmp logging when chrooting. */


More information about the svn-src-all mailing list