Two Methods for Enforcing Chroot(2) Environment

Two Methods for Enforcing Chroot(2) Environment

        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). Note that for FreeBSD 4.0 users and newer, ls(1) is
built into ftpd(8) by default, so you can skip this section.

	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

Leave a Reply

Your email address will not be published. Required fields are marked *