From nobody@FreeBSD.ORG Tue Oct 17 15:59:18 2000 Return-Path: Received: by hub.freebsd.org (Postfix, from userid 32767) id 519C737B4C5; Tue, 17 Oct 2000 15:59:18 -0700 (PDT) Message-Id: <20001017225918.519C737B4C5@hub.freebsd.org> Date: Tue, 17 Oct 2000 15:59:18 -0700 (PDT) From: agifford@infowest.com Sender: nobody@FreeBSD.ORG To: freebsd-gnats-submit@FreeBSD.org Subject: Patch to add feature to FreeBSD's ftpd when used with chroot X-Send-Pr-Version: www-1.0 >Number: 22066 >Category: bin >Synopsis: Patch to add feature to FreeBSD's ftpd when used with chroot >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: closed >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Tue Oct 17 16:00:00 PDT 2000 >Closed-Date: Sun Jul 22 08:49:34 PDT 2001 >Last-Modified: Sun Jul 22 08:49:57 PDT 2001 >Originator: Aaron D. Gifford >Release: FreeBSD-4.1.1-STABLE >Organization: >Environment: FreeBSD my.freebsd.box 4.1.1-STABLE FreeBSD 4.1.1-STABLE #0: Thu Oct 12 11:58:29 MDT 2000 root@my.freebsd.box:/usr/src/sys/compile/LOCAL i386 >Description: Hello, When using the ftpd daemon with users who are chrooted (see the ftpd man page, authentication rule #5), if a user's home directory is /users/joe, ftpd behaves exactly as I expect and changes to that directory. However, in certain cases, the following feature would be preferable: If I use a set-up like this: /users/joe - directory in which I want user joe to be chrooted /users/joe/bin - where chroot-accessable binaries are kept /users/joe/etc - chroot-accesable system stuff (like group) so that ls and other tools behave normally in the chrooted environment /users/joe/web - this is the ONLY subdirectory that user joe owns (all others are root.wheel) and has write privileges to - it is where joe can upload web pages to With the above setup, it would be nice to be able to automatically AFTER the chroot to /users/joe do a cwd() to /web so that joe will begin his FTP session within his writable subdirectory. The wu-ftpd daemon has this ability by setting a user's home directory to: /users/joe/./web By adding a "/./" to the home directory, the wu-ftpd daemon knows where the chroot portion of the home directory ends and where the cwd() portion begins. Unfortunatly, wu-ftpd is not an option. FreeBSD's ftpd is far superior. The patch below adds this feature to FreeBSD's ftpd daemon. I hope that you seriously consider adding this to to FreeBSD. It is quite handy and I expect that there are many others who would enjoy this added ability. The only drawback that I can see to adding this feature (and I must mention it to be honest) is in cases where existing installations use a "/./" in home directories for some other purpose where changing the existing chroot behavior of the FTP daemon would require them to restructure. Installations where this would be a problem are very likely extremely rare or nonexistent. So while I mention it, I don't think it would really be a problem. I've been using these very same modifications to support this new chroot feature on a web server where users are chrooted to their own subdirectories for security purposes. It has been running without problems for months on a system with about 12,000 users. Sincerely, Aaron Gifford P.S. If the patch included doesn't quite come out right (I'm pasting it using a web browser), email me and I'll email a copy to you. >How-To-Repeat: This is a feature request. >Fix: Patch to ftpd follows: +++ libexec/ftpd/ftpd.c Tue Oct 3 10:18:24 2000 @@ -250,6 +250,63 @@ static void reapchild __P((int)); static void logxfer __P((char *, long, long)); +/* + * Two new subroutines to let ftpd chroot to a home directory in the + * format /home/dir/./here/or/there where the chroot will be done + * on chroot("/home/dir/") followed by a chdir ("/here/or/there") + * (Much like wu-ftpd's similar feature) and do it safely. + */ +static char * +chrootdir(dir) + char *dir; +{ + static char cdir[MAXPATHLEN+1]; + int len = 0; + + if (!dir) { + cdir[0] = '/'; + cdir[1] = '\0'; + return cdir; + } + while(*dir && len < MAXPATHLEN) { + if (*dir == '/' && *(dir+1) == '.' && *(dir+2) == '/') { + cdir[len++] = *dir; + cdir[len] = '\0'; + return cdir; + } + cdir[len++] = *dir++; + } + cdir[len] = '\0'; + return cdir; +} + +static char * +homedir(dir) + char *dir; +{ + static char hdir[MAXPATHLEN+1]; + int len = 0; + + if (!dir) { + hdir[0] = '/'; + hdir[1] = '\0'; + return hdir; + } + while (*dir && !(*dir == '/' && *(dir+1) == '.' && *(dir+2) == '/')) + dir++; + if (!*dir) { + hdir[0] = '/'; + hdir[1] = '\0'; + return hdir; + } + dir += 2; + while (*dir && len < MAXPATHLEN) + hdir[len++] = *dir++; + hdir[len] = '\0'; + return hdir; +} +/* End of chroot feature subroutine additions */ + static char * curdir() { @@ -260,7 +317,7 @@ if (path[1] != '\0') /* special case for root dir. */ strcat(path, "/"); /* For guest account, skip / since it's chrooted */ - return (guest ? path+1 : path); + return ((dochroot || guest) ? path+1 : path); } int @@ -1285,12 +1342,12 @@ * the old current directory will be accessible as "." * outside the new root! */ - if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) { + if (chroot(chrootdir(pw->pw_dir)) < 0 || chdir(homedir(pw->pw_dir)) < 0) { reply(550, "Can't set guest privileges."); goto bad; } } else if (dochroot) { - if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) { + if (chroot(chrootdir(pw->pw_dir)) < 0 || chdir(homedir(pw->pw_dir)) < 0) { reply(550, "Can't change root."); goto bad; } >Release-Note: >Audit-Trail: From: Daniel Hagan To: freebsd-gnats-submit@FreeBSD.org, agifford@infowest.com Cc: Subject: Re: bin/22066: Patch to add feature to FreeBSD's ftpd when used with chroot Date: Thu, 04 Jan 2001 16:52:54 -0500 This should probably be closed in preference to bin/23944. State-Changed-From-To: open->closed State-Changed-By: dd State-Changed-When: Sun Jul 22 08:49:34 PDT 2001 State-Changed-Why: duplicate of 23944; thanks dhagan@colltech.com http://www.FreeBSD.org/cgi/query-pr.cgi?pr=22066 >Unformatted: