Date: Thu, 4 Jan 2001 08:10:02 -0800 (PST) From: Daniel Hagan <dhagan@colltech.com> To: freebsd-bugs@FreeBSD.org Subject: Re: bin/23944: Proposed modification to ftpd Message-ID: <200101041610.f04GA2276727@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
The following reply was made to PR bin/23944; it has been noted by GNATS.
From: Daniel Hagan <dhagan@colltech.com>
To: freebsd-audit@freebsd.org
Cc: freebsd-gnats-submit@freebsd.org,
fschapachnik@vianetworks.com.ar, greid@dogma.freebsd-uk.eu.org
Subject: Re: bin/23944: Proposed modification to ftpd
Date: Thu, 4 Jan 2001 11:05:58 -0500 (EST)
I've rewritten some of your patch to not use dangling pointers. I also
added the cd_dir functionality to the ftp guest account, not because I
think it's a great idea, but because it will be consistent behavior.
(If someone had specified /info/ftp/./pub as HOME for ftp, your patch would
have chroot'd ftp into /info/ftp/pub, instead of /info/ftp. And this 'bug'
would only appear for the ftp account. ;-))
In the event that this mail doesn't get munged the way I'd like, please
respond to dhagan@colltech.com
Thanks,
Daniel
Index: ftpcmd.y
===================================================================
RCS file: /raid/ncvs/src/libexec/ftpd/ftpcmd.y,v
retrieving revision 1.19
diff -u -r1.19 ftpcmd.y
--- ftpcmd.y 2000/12/16 19:19:19 1.19
+++ ftpcmd.y 2001/01/04 15:55:42
@@ -92,6 +92,8 @@
extern char tmpline[];
extern int readonly;
extern int noepsv;
+extern int dochroot;
+extern char *cd_dir, *chroot_dir;
off_t restart_point;
@@ -505,8 +507,11 @@
| CWD check_login CRLF
{
if ($2) {
- if (guest)
- cwd("/");
+ if (guest || dochroot)
+ if (cd_dir != NULL)
+ cwd(cd_dir);
+ else
+ cwd("/");
else
cwd(pw->pw_dir);
}
Index: ftpd.8
===================================================================
RCS file: /raid/ncvs/src/libexec/ftpd/ftpd.8,v
retrieving revision 1.36
diff -u -r1.36 ftpd.8
--- ftpd.8 2000/12/18 08:33:25 1.36
+++ ftpd.8 2001/01/04 15:46:24
@@ -311,13 +311,14 @@
or the user is a member of a group with a group entry in this file,
i.e. one prefixed with
.Ql \&@ ,
-the session's root will be changed to the user's login directory by
+the session's root will be changed to the user's login directory (up to the first /./) by
.Xr chroot 2
as for an
.Dq anonymous
or
.Dq ftp
account (see next item).
+The user is placed into the directory that remainds after stripping the former from the user's login directory.
This facility may also be triggered by enabling the boolean "ftp-chroot"
capability in
.Xr login.conf 5 .
Index: ftpd.c
===================================================================
RCS file: /raid/ncvs/src/libexec/ftpd/ftpd.c,v
retrieving revision 1.72
diff -u -r1.72 ftpd.c
--- ftpd.c 2000/12/20 03:34:54 1.72
+++ ftpd.c 2001/01/04 15:56:59
@@ -140,6 +140,7 @@
int anon_only = 0; /* Only anonymous ftp allowed */
int guest;
int dochroot;
+char *cd_dir = NULL, *chroot_dir = NULL;
int stats;
int statfd = -1;
int type;
@@ -188,6 +189,9 @@
char *pid_file = NULL;
+/* WARNING: FTP_CHROOT_SEPARATOR *MUST* end in / */
+#define FTP_CHROOT_SEPARATOR "/./"
+
/*
* Timeout intervals for retrying connections
* to hosts that don't accept PORT cmds. This
@@ -251,6 +255,7 @@
static char *sgetsave __P((char *));
static void reapchild __P((int));
static void logxfer __P((char *, long, long));
+static void get_chroot_and_cd_dirs __P((char *, char **, char **));
static char *
curdir()
@@ -1038,6 +1043,8 @@
logged_in = 0;
guest = 0;
dochroot = 0;
+ free(chroot_dir);
+ free(cd_dir);
}
#if !defined(NOPAM)
@@ -1291,19 +1298,20 @@
login_getcapbool(lc, "ftp-chroot", 0) ||
#endif
checkuser(_PATH_FTPCHROOT, pw->pw_name, 1);
- if (guest) {
+ if (guest || dochroot) {
/*
* We MUST do a chdir() after the chroot. Otherwise
* the old current directory will be accessible as "."
* outside the new root!
*/
- if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) {
- reply(550, "Can't set guest privileges.");
- goto bad;
- }
- } else if (dochroot) {
- if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) {
- reply(550, "Can't change root.");
+ get_chroot_and_cd_dirs(pw->pw_dir, &chroot_dir, &cd_dir);
+ /*
+ * Do not free chroot_dir & cd_dir b/c they are used in
+ * processing CWD commands from client. They should be
+ * free'd during a user logout.
+ */
+ if (chroot(chroot_dir) < 0 || chdir(cd_dir) < 0) {
+ reply(550, guest ? "Can't set guest privileges." : "Can't change root.");
goto bad;
}
} else if (chdir(pw->pw_dir) < 0) {
@@ -2802,5 +2810,50 @@
ctime(&now)+4, ident, remotehost,
path, name, size, now - start + (now == start));
write(statfd, buf, strlen(buf));
+ }
+}
+
+/*
+ * Make a pointer to the chroot dir and another to the cd dir.
+ * The first is all the path up to the first FTP_CHROOT_SEPARATOR.
+ * The later is the remaining chars, not including the FTP_CHROOT_SEPARATOR,
+ * but prepending a '/', if FTP_CHROOT_SEPARATOR is found.
+ * Otherwise, return user_home_dir as chroot_dir and "/" as cd_dir.
+ */
+static void
+get_chroot_and_cd_dirs(user_home_dir, chroot_dir, cd_dir)
+ char *user_home_dir;
+ char **chroot_dir;
+ char **cd_dir;
+{
+ char *p;
+
+ /* Make a pointer to first character of string FTP_CHROOT_SEPARATOR
+ inside user_home_dir. */
+ p = (char *) strstr(user_home_dir, FTP_CHROOT_SEPARATOR);
+ if (p == NULL) {
+ /*
+ * There is not FTP_CHROOT_SEPARATOR string inside
+ * user_home_dir. Return user_home_dir as chroot_dir,
+ * and "/" as cd_dir.
+ */
+ if ((*chroot_dir = (char *) strdup(user_home_dir)) == NULL)
+ fatal("Ran out of memory.");
+ if ((*cd_dir = (char *) strdup("/")) == NULL)
+ fatal("Ran out of memory.");
+ } else {
+ /*
+ * Use strlen(user_home_dir) as maximun length for
+ * both cd_dir and chroot_dir, as both are substrings of
+ * user_home_dir.
+ */
+ if ((*chroot_dir = malloc(strlen(user_home_dir))) == NULL)
+ fatal("Ran out of memory.");
+ if ((*cd_dir = malloc(strlen(user_home_dir))) == NULL)
+ fatal("Ran out of memory.");
+ (void) strncpy(*chroot_dir, user_home_dir, p-user_home_dir);
+ /* Skip FTP_CHROOT_SEPARATOR (except the last /). */
+ p += strlen(FTP_CHROOT_SEPARATOR)-1;
+ (void) strncpy(*cd_dir, p, strlen(p));
}
}
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200101041610.f04GA2276727>
