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
This commit is contained in:
Christian S.J. Peron 2011-01-03 21:28:12 +00:00
parent 90305aa38b
commit cefb678553

View File

@ -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. */