From 48ae57efdbff9d38effbc1f0dfb939c0ed0e68a9 Mon Sep 17 00:00:00 2001 From: csjp Date: Mon, 3 Jan 2011 21:28:12 +0000 Subject: [PATCH] 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 --- libexec/ftpd/ftpd.c | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/libexec/ftpd/ftpd.c b/libexec/ftpd/ftpd.c index 119c5754310..78ebc7c737c 100644 --- a/libexec/ftpd/ftpd.c +++ b/libexec/ftpd/ftpd.c @@ -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]; /* current USER name */ 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 @@ checkuser(char *fname, char *name, int pwset, char **residue) free(mp); } (void) fclose(fd); - } + } else if (ecode != NULL) + *ecode = errno; return (found); } @@ -1359,7 +1368,7 @@ auth_pam(struct passwd **ppw, const char *pass) void pass(char *passwd) { - int rval; + int rval, ecode; FILE *fd; #ifdef LOGIN_CAP login_cap_t *lc = NULL; @@ -1475,11 +1484,21 @@ pass(char *passwd) #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. */ -- 2.45.0