Subject: bin/4769: enhance ftpchroot like ftpusers
To: None <gnats-bugs@gnats.netbsd.org>
From: Ty Sarna <tsarna@endicor.com>
List: netbsd-bugs
Date: 01/03/1998 19:35:26
>Number: 4769
>Category: bin
>Synopsis: enhance ftpchroot like ftpusers
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: bin-bug-people (Utility Bug People)
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Sat Jan 3 17:50:01 1998
>Last-Modified:
>Originator: Ty Sarna
>Organization:
Endicor Technologies, Inc., San Antonio, Texas
>Release: 1.3_BETA-971217
>Environment:
1.3_BETA-971217, (on i386, but doesn't matter)
>Description:
Patches generalize checkaccess()'s functionality into checkuser(),
Which can then be used both for checkaccess() (/etc/ftpusers)
and /etc/ftpchroot (and possibly other things, in the future).
Upshot: /etc/ftpchroot then implements the wildcard matching and
other features of the new ftpusers syntax, in a backward
compatible manner.
>How-To-Repeat:
N/A
>Fix:
--- ftpd.c.orig Mon Dec 29 15:16:33 1997
+++ ftpd.c Sat Jan 3 18:34:15 1998
@@ -100,6 +100,11 @@
#include <varargs.h>
#endif
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
+
static char version[] = "Version 7.02";
extern off_t restart_point;
@@ -184,7 +189,7 @@
static void ack __P((char *));
static void myoob __P((int));
-static int checkuser __P((char *, char *));
+static int checkuser __P((char *, char *, int def, int nofile));
static int checkaccess __P((char *));
static FILE *dataconn __P((char *, off_t, char *));
static void dolog __P((struct sockaddr_in *));
@@ -500,66 +505,36 @@
sleep((unsigned) login_attempts);
}
-/*
- * Check if a user is in the file "fname"
- */
-static int
-checkuser(fname, name)
- char *fname;
- char *name;
-{
- FILE *fd;
- int found = 0;
- char *p, line[BUFSIZ];
-
- if ((fd = fopen(fname, "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) {
- found = 1;
- break;
- }
- }
- (void) fclose(fd);
- }
- return (found);
-}
-
-/*
- * Determine whether a user has access, based on information in
- * _PATH_FTPUSERS. Each line is a shell-style glob followed by
- * `allow' or `deny' (with deny being the default if anything but
- * `allow', or nothing at all, is specified).
+/* Determine wether something is to happen (allow access, chroot)
+ * for a user. Each line is a shell-style glob followed by
+ * `yes' or `no'.
*
- * Each glob is matched against the username in turn, and the first
- * match found is used. If no match is found, access is allowed.
+ * For backward compatability, `allow' and `deny' are synonymns
+ * for `yes' and `no', respectively.
*
- * Any line starting with `#' is considered a comment and ignored.
+ * Each glob is matched against the username in turn, and the first
+ * match found is used. If no match is found, the result is the
+ * argument `def'. If a match is found but without and explicit
+ * `yes'/`no', the result is the opposite of def.
*
- * This is probably not the best way to do this, but it preserves
- * the old semantics where if a user was listed in the file he was
- * denied, otherwise he was allowed.
+ * If the file doesn't exist at all, the result is the argument
+ * `nofile'
*
- * There is one change in the semantics, however; ftpd will now `fail
- * safe' and deny all access if there's no /etc/ftpusers file.
+ * Any line starting with `#' is considered a comment and ignored.
*
- * Return 1 if the user is denied, or 0 if he is allowed.
+ * Returns FALSE for no/deny, or TRUE for yes/allow.
*/
static int
-checkaccess(name)
- char *name;
+checkuser(fname, name, def, nofile)
+ char *fname, *name;
+ int def, nofile;
{
-#define ALLOWED 0
-#define NOT_ALLOWED 1
FILE *fd;
- int retval = ALLOWED;
+ int retval = def;
char *glob, *perm, line[BUFSIZ];
- if ((fd = fopen(conffilename(_PATH_FTPUSERS), "r")) == NULL)
- return NOT_ALLOWED;
+ if ((fd = fopen(conffilename(fname), "r")) == NULL)
+ return nofile;
while (fgets(line, sizeof(line), fd) != NULL) {
glob = strtok(line, " \t\n");
@@ -567,18 +542,33 @@
continue;
perm = strtok(NULL, " \t\n");
if (fnmatch(glob, name, 0) == 0) {
- if (perm != NULL && strcmp(perm, "allow") == 0)
- retval = ALLOWED;
+ if (perm != NULL &&
+ ( (strcmp(perm, "allow") == 0)
+ || (strcmp(perm, "yes") == 0)) )
+ retval = TRUE;
+ else if (perm != NULL &&
+ ( (strcmp(perm, "deny") == 0)
+ || (strcmp(perm, "no") == 0)) )
+ retval = FALSE;
else
- retval = NOT_ALLOWED;
+ retval = !def;
break;
}
}
(void) fclose(fd);
return (retval);
}
-#undef ALLOWED
-#undef NOT_ALLOWED
+
+/*
+ * Check if a user is allowed access. Default is no if /etc/ftpusers
+ * doesn't exist, yes if exists but user not listed.
+ */
+static int
+checkaccess(name)
+ char *name;
+{
+ return !checkuser(_PATH_FTPUSERS, name, TRUE, FALSE);
+}
/*
* Terminate login as previous user, if any, resetting state;
@@ -705,7 +695,7 @@
logwtmp(ttyline, pw->pw_name, remotehost);
logged_in = 1;
- dochroot = checkuser(conffilename(_PATH_FTPCHROOT), pw->pw_name);
+ dochroot = checkuser(_PATH_FTPCHROOT, pw->pw_name, FALSE, FALSE);
/* parse ftpd.conf, setting up various parameters */
if (guest)
--- ftpd.8.orig Sat Jan 3 18:53:15 1998
+++ ftpd.8 Sat Jan 3 19:03:18 1998
@@ -220,8 +220,9 @@
shell is assumed to be
.Pa /bin/sh . )
.It
-If the user name appears in the file
+If directed by the file
.Pa /etc/ftpchroot
+(see below)
the session's root will be changed to the user's login directory by
.Xr chroot 2
as for an
@@ -264,16 +265,24 @@
.Dq #
or a glob pattern that uses the same syntax as /bin/sh,
optionally followed by whitespace and
-.Dq allow
+.Dq allow ,
+.Dq yes ,
+.Dq deny ,
or
-.Dq deny .
+.Dq no .
Each glob pattern is compared in turn against the username
until a match is found. If the word following the matched glob
pattern is
.Dq allow
-the user is granted access; if the word is
-anything else, or nothing at all, the user is denied access.
-(No further comparisons are attempted after the first successful match.)
+or
+.Dq yes
+the user is granted access; if the word is
+.Dq deny
+or
+.Dq no ,
+or if the word is missing,
+the user is denied access.
+No further comparisons are attempted after the first successful match.
If no match is found, the user is granted access.
This syntax is backward-compatable with the old syntax.
.Pp
@@ -289,6 +298,29 @@
to
.Pa /etc/ftpusers
in order to allow guest logins.
+.Ss /etc/ftpchroot
+The file
+.Pa /etc/ftpchroot
+is used to determine which users will have their session's root changed
+to the user's home directory.
+If the file does not exist, the root change is not performed.
+If it does exist, each line is a a comment starting with
+.Dq #
+or a glob pattern that uses the same syntax as /bin/sh,
+optionally followed by whitespace and
+.Dq yes
+or
+.Dq no .
+Each glob pattern is compared in turn against the username
+until a match is found. If the word following the matched glob
+pattern is
+.Dq yes
+or there is no following word, the root is changed.
+If the word is
+.Dq no ,
+or if no match is found, the root is not changed.
+No further comparisons are attempted after the first successful match.
+This syntax is backward-compatable with the old syntax.
.Ss /etc/ftpd.conf
The file
.Pa /etc/ftpd.conf
>Audit-Trail:
>Unformatted: