int logging;
int authenticate;
int guest;
+int restricted;
int type;
int clevel; /* control protection level */
int dlevel; /* data protection level */
* If account doesn't exist, ask for passwd anyway. Otherwise, check user
* requesting login privileges. Disallow anyone who does not have a standard
* shell as returned by getusershell(). Disallow anyone mentioned in the file
- * _PATH_FTPUSERS to allow people such as root and uucp to be avoided.
+ * _PATH_FTPUSERS to allow people such as root and uucp to be avoided, except
+ * for users whose names are followed by whitespace and then the keyword
+ * "restrict." Restricted users are allowed to login, but a chroot() is
+ * done to their home directory.
*/
user(name)
char *name;
guest = 0;
if (strcmp(name, "ftp") == 0 || strcmp(name, "anonymous") == 0) {
- if (checkuser("ftp") || checkuser("anonymous"))
+ if (disallowed_user("ftp") || disallowed_user("anonymous"))
reply(530, "User %s access denied.", name);
else if ((pw = sgetpwnam("ftp")) != NULL) {
guest = 1;
#else
cp = shell;
#endif
- if (cp == NULL || checkuser(name)) {
+ if (cp == NULL || disallowed_user(name)) {
reply(530, "User %s access denied.", name);
if (logging)
syslog(LOG_NOTICE,
pw = (struct passwd *) NULL;
return;
}
+ restricted = restricted_user(name);
}
#ifdef GSSAPI
if (auth_type && strcmp(auth_type, "GSSAPI") == 0) {
reply(331, "Password required for %s.", name);
askpasswd = 1;
+
/*
* Delay before reading passwd after first failed
* attempt to slow down passwd-guessing programs.
}
/*
- * Check if a user is in the file _PATH_FTPUSERS
+ * Check if a user is in the file _PATH_FTPUSERS.
+ * Return 1 if they are (a disallowed user), -1 if their username
+ * is followed by "restrict." (a restricted user). Otherwise return 0.
*/
checkuser(name)
char *name;
char line[FTP_BUFSIZ];
if ((fd = fopen(_PATH_FTPUSERS, "r")) != NULL) {
- while (fgets(line, sizeof(line), fd) != NULL)
- if ((p = strchr(line, '\n')) != NULL) {
- *p = '\0';
- if (line[0] == '#')
- continue;
- if (strcmp(line, name) == 0)
- return (1);
+ while (fgets(line, sizeof(line), fd) != NULL) {
+ if ((p = strchr(line, '\n')) != NULL) {
+ *p = '\0';
+ if (line[0] == '#')
+ continue;
+ if (strcmp(line, name) == 0)
+ return (1);
+ if (strncmp(line, name, strlen(name)) == 0) {
+ int i = strlen(name) + 1;
+
+ /* Make sure foo doesn't match foobar */
+ if (line[i] == '\0' || !isspace(line[i]))
+ continue;
+ /* Ignore whitespace */
+ while (isspace(line[++i]));
+
+ if (strcmp(&line[i], "restrict") == 0)
+ return (-1);
+ else
+ return (1);
}
- (void) fclose(fd);
+ }
+ }
}
+ (void) fclose(fd);
+
return (0);
}
+disallowed_user(name)
+ char *name;
+{
+ return(checkuser(name) == 1);
+}
+
+restricted_user(name)
+ char *name;
+{
+ return(checkuser(name) == -1);
+}
+
/*
* Terminate login as previous user, if any, resetting state;
* used when USER command is given or login fails.
ftp_logwtmp(ttyline, pw->pw_name, remotehost);
logged_in = 1;
- if (guest) {
- if (chroot(pw->pw_dir) < 0) {
- reply(550, "Can't set guest privileges.");
+ if (guest || restricted) {
+ if (chroot(pw->pw_dir) < 0) {
+ reply(550, "Can't set privileges.");
goto bad;
}
}
goto bad;
}
} else {
- if (chdir(pw->pw_dir) < 0) {
+ if (chdir(restricted ? "/" : pw->pw_dir) < 0) {
if (chdir("/") < 0) {
reply(530, "User %s: can't change directory to %s.",
pw->pw_name, pw->pw_dir);