summaryrefslogtreecommitdiffstats
path: root/libexec/ftpd
diff options
context:
space:
mode:
authorcsjp <csjp@FreeBSD.org>2011-01-03 21:28:12 +0000
committercsjp <csjp@FreeBSD.org>2011-01-03 21:28:12 +0000
commit48ae57efdbff9d38effbc1f0dfb939c0ed0e68a9 (patch)
tree629ddbcda24e1842b7355bd4451398e70e42b6b1 /libexec/ftpd
parent53f27d6094f8d165bcafb24f7a049f6b3cf2a986 (diff)
downloadFreeBSD-src-48ae57efdbff9d38effbc1f0dfb939c0ed0e68a9.zip
FreeBSD-src-48ae57efdbff9d38effbc1f0dfb939c0ed0e68a9.tar.gz
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
Diffstat (limited to 'libexec/ftpd')
-rw-r--r--libexec/ftpd/ftpd.c35
1 files changed, 27 insertions, 8 deletions
diff --git a/libexec/ftpd/ftpd.c b/libexec/ftpd/ftpd.c
index 119c575..78ebc7c 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 @@ 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 *pass)
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. */
OpenPOWER on IntegriCloud