Defcon1-Header Defcon1-Header2
Tool-BarfreeBSD ArticlesSearch Our SiteHOMEfreeBSD LinksContribute to FreeBSD HelpFreeBSD FilesFreeBSD Script Corner Tool-Bar-2Defcon1  Webmail


How to enforce a chroot

If there are any questions or comments, please direct them to The newest copy of this HowTo can always be retrieved from All rights for the reproduction of this document are reserved.

 This mini HowTo will describe in quick and clear steps how to enforce a chroot(2) environment for regular user ftp sessions with the default ftp daemon that comes with the base system, and how to compile ftpd(8) with internal ls(1).

     1.   Two Methods for Enforcing Chroot(2) Environment
     1.1.  Method 1: Using /etc/ftpchroot
     1.2.  Method 2: Enabling 'ftp-chroot' Login Class Capability
     2.   Compiling ftpd(8) with Internal ls(1)
     3. Appendix

 1. Two Methods for Enforcing Chroot(2) Environment
 There are two methods for enforcing a chroot(2) environment for ftpd(8). The first entails the use of a file "ftpchroot" in /etc, and the second entails using a login class "capability" entry. For both methods, you must be logged in as or su(1)'ed to root.
 Note: anonymous ftp is always chroot(2)'ed and this HowTo only deals with ftp sessions where the user logs into his own directory to upload or download files.

 1.1. Method 1: Using /etc/ftpchroot
 The first method is simple. To enforce a chroot(2) environment for certain users' ftp sessions, enter the users' names into /etc/ftpchroot. For instance, if one wishes to enforce a chroot(2) environment for the ftp sessions of the users "boff" and "skip" then the following would accomplish this:
 (root@box)~># echo boff > /etc/ftpchroot
 (root@box)~># echo skip >> /etc/ftpchroot
 (root@box)~># cat /etc/ftpchroot

 If one wishes to enforce a chroot(8) environment for an entire user-group at once, then the group can be entered into the file as well, but must be prefixed with a '@'. For instance, to include the user group "basic_user" the following would accomplish this:
    (root@box)~># echo @basic_user >> /etc/ftpchroot
    (root@box)~># cat /etc/ftpchroot
 The above configuration would enforce an ftp chroot(2) environment for users "boff" and "skip" whether they are in the user-group "basic_user" or not. In addition, all users in the user-group "basic_user" would have their ftp sessions chroot(2)'ed.

 1.2. Method 2: Enabling 'ftp-chroot' Login Class Capability
 Firstly, one must note that the term "capability" is being used in a specialized fashion. The file /etc/login.conf as well as /etc/gettytab are in a database format know as a "Capabilities Database" and each entry is termed a "capability."
 If one is actively using login classes (see or for Login-Class-HOWTO if you are not familiar with login classes) to manage user accounts then this may be an ideal solution. To enable a chroot(2) ftp environment for all users within a particular login class simply ass the capability "ftp-chroot" within the corresponding login class. See getcap(3) or the previously mentioned Login-Class-HOWTO for in-depth information on login classes and the format of 'capabilities databases.' 

 2. Compiling ftpd(8) with Internal ls(1)
 Once one of the previous methods for enforcing a chroot(2)'ed ftp environment has been accomplished, it is recommended to recompile ftpd(8) such that ls(1) support is built right into the binary and ftpd(8) does not depend on a special /bin directory in the ftp root. This is important as the ftp root would be the user's home directory, and, as such, each user would require a ~/bin directory containing a statically compiled version of ls(1).
 To compile a copy of ftpd(8) with internal ls(1) support first requires that the user have the system source installed or that the user has downloaded the ftpd source code into a temporary directory. For those of you using system source in /usr/src, then the following steps will suffice in rebuilding the daemon properly:
 1) cd /usr/src/libexec/ftpd
 2) export FTPD_INTERNAL_LS=yes
 3) make clean; make; make install
 If you are using downloaded source, then cd into the source directory and do steps 1 and 2. 
 Note: you can also set the FTPD_INTERNAL_LS=yes value in /etc/make.conf for the same effect. For instance, the following line would accomplish this:
 (root@box)~># echo FTPD_INTERNAL_LS=yes >> /etc/make.conf
 Once the binary is rebuilt with "make" and install with "make install" you can easily check that ftpd(8) has indeed successfully compiled with internal ls(1) by ftp'ing to the daemon. One should see the version number of the ftp daemon suffixed by the letters "LS" such as in the following example:
 Connected to
 220 FTP server (Version 6.00LS) ready.
 Once this is verified, one has successfully compiled ftpd(8) with internal ls(1) support.
 3. Appendix
 Man page references:
  8 ftpd
  2 chroot
  3 getcap
 Other documents:
  Login-Class-HOWTO (from


© 1997 - 20013 Defcon1, , Copyrights for all materials on this web site are held by the individual authors, artists, photographers or creators. Materials may not be reproduced or otherwise distributed without permission of and the content's original author.