###############################################################################
##                                                                           ##
##       Setting up a Chroot Jail for use with a Slackware SSH Server        ##
##                                                                           ##
###############################################################################

Author:  elw
Date:    2012-08-27

-- Basic Concepts -------------------------------------------------------------

The basic concept of a chroot jail is to lock users inside of an environment
that emulates a true *nix system but is in fact a "sudo" system inside of the
true root filesystem. This type of system is particularly useful when you want
to limit the applications that are available to some of the users of your
system.

With some recently changes to the ssh daemon, it is now extremely easy to set
up a chroot environment for remote users. This document will attempt to explain
how to use the ssh chroot functionality on Slackware Linux. By the end of this
document you should have a basic understanding of how a chroot environment is
setup and have a basic chroot jail configured that users can access via ssh.

-- Setting up the Chroot Environment ------------------------------------------

Because a user in a chroot environment cannot see or access any files above the
chroot jails / directory, you must make sure that all binaries and libraries
the user will need are visible when in the chroot jail. We must first copy over
the minimum binaries for the chroot environment, in this case we will copy over
/bin/bash. In this example, we will use /chroot as our chroot jail directory.

       elw@sdf:~ $> mkdir /chroot
       elw@sdf:~ $> mkdir /chroot/bin
       elw@sdf:~ $> cp /bin/bash /chroot/bin/bash

/bin/bash, however, requires a few libraries. To find out what they
are we will use the "ldd" command. See the example below:

       elw@sdf:~ $> ldd /bin/bash
               linux-gate.so.1 =>  (0xffffe000)
               libtermcap.so.2 => /lib/libtermcap.so.2 (0xb77ee000)
               libdl.so.2 => /lib/libdl.so.2 (0xb77ea000)
               libc.so.6 => /lib/libc.so.6 (0xb7687000)
               /lib/ld-linux.so.2 (0xb7807000)

This is a list of the libraries which /bin/bash relies on. We must copy these
from the root file system to the chroot environment. First, however we must
create the necessary directories.

       elw@sdf:~ $> mkdir /chroot/lib
       elw@sdf:~ $> cp /lib/libtermcap.so.2 /chroot/lib
       elw@sdf:~ $> cp /lib/libdl.so.2 /chroot/lib
       elw@sdf:~ $> cp /lib/libc.so.6 /chroot/lib
       elw@sdf:~ $> cp /lib/ld-linux.so.2 /chroot/lib

Next, we will want to provide our users the ability to list files and folders.
We must bring the /bin/ls binary over to the chroot jail, as well as it's
libraries, as we did for /bin/bash.

       elw@sdf:~ $> cp /bin/ls /chroot/bin
       elw@sdf:~ $> ldd /bin/ls
               linux-gate.so.1 =>  (0xffffe000)
               librt.so.1 => /lib/librt.so.1 (0xb7868000)
               libcap.so.2 => /lib/libcap.so.2 (0xb7864000)
               libacl.so.1 => /lib/libacl.so.1 (0xb785c000)
               libc.so.6 => /lib/libc.so.6 (0xb76f9000)
               libpthread.so.0 => /lib/libpthread.so.0 (0xb76df000)
               /lib/ld-linux.so.2 (0xb7886000)
               libattr.so.1 => /lib/libattr.so.1 (0xb76da000)
       elw@sdf:~ $> cp /lib/librt.so.1 /chroot/lib
       elw@sdf:~ $> cp /lib/libcap.so.2 /chroot/lib
       elw@sdf:~ $> cp /lib/libacl.so.1 /chroot/lib
       elw@sdf:~ $> cp /lib/libpthread.so.0 /chroot/lib
       elw@sdf:~ $> cp /lib/libattr.so.1 /chroot/lib

You may have noticed that, in the above example, we did not copy over
/lib/libc.so.6. This is because it was already copied over with /bin/bash in
the previous example.

We will also need to provide the chroot user with some devices. The minimum
required for the chroot to work is /dev/null and /dev/zero. We will use the
mknod command to create these devices inside of the chroot.

       elw@sdf:~ $> mkdir /chroot/dev
       elw@sdf:~ $> mknod -m 0666 /chroot/dev/null c 1 3
       elw@sdf:~ $> mknod -m 0666 /chroot/dev/zero c 1 5

While we're creating the environment, let's also create a /tmp directory.

       elw@sdf:~ $> mkdir /chroot/tmp

I also like to mount /tmp as tmpfs so that any files a user writes to /tmp will
not be retained after a reboot. You should not do this if you are setting this
up on a low resource system.

       elw@sdf:~ $> echo "tmpfs    /chroot/tmp    tmpfs    defaults    0  0" >> \
                  /etc/fstab

While we're on the subject of mounting file systems, we will also need to
address /proc. You need to provide /proc inside the chroot environment or some
interesteing problems arise. We'll use a bind mount to get around this.

       elw@sdf:~ $> mkdir /chroot/proc
       elw@sdf:~ $> mount --bind /proc /chroot/proc

To make these changes permanent we need to add another entry into /etc/fstab.
Add the following line to the bottom of /etc/fstab to do this.

       /proc    /chroot/proc    bind    defaults,bind    0  0

-- Create the Chroot User -----------------------------------------------------

Next, lets create our first chroot shell user. This same pattern can be
followed for all subsequent users which you wish to chroot inside of our jail.

       elw@sdf:~ $> groupadd chroot_users
       elw@sdf:~ $> useradd -s /bin/bash -g chroot_users -d /home/chrootuser \
                  -mk /etc/skel chrootuser
       elw@sdf:~ $> passwd chrootuser

Again, because the user can't access anything outside of /chroot we either need
to copy or move /home/chrootuser to /chroot/home or move it all together. I
prefer to move the directory since the user has no use for it in it's current
location.

       elw@sdf:~ $> mkdir /chroot/home
       elw@sdf:~ $> mv /home/chrootuser /chroot/home

The next thing we need to copy over is /etc/passwd. The reason for this is that
when a user is logged in bash will reference /etc/profile and /etc/profile.d
which in turn will look up the users name in /etc/passwd and display it as the
\u value in $PS1. I generally do not, however, like to copy over the entire
/etc/passwd file because it is not necessary (I prefer to, in generally, use
the minimum required as to not provide more information about the system to
general system users as possible). The example below will show you how to
extract just "chrootuser" from /etc/passwd and extract just "chroot_users" from
/etc/group and place it in the cooresponding locations inside the chroot jail.

       elw@sdf:~ $> mkdir /chroot/etc
       elw@sdf:~ $> touch /chroot/etc/{passwd,group}
       elw@sdf:~ $> grep chrootuser /etc/passwd >> /chroot/etc/passwd
       elw@sdf:~ $> grep chroot_users /etc/group >> /chroot/etc/group

-- Configure SSH Daemon -------------------------------------------------------

The final step in getting our SSH users in a chroot jail is configuring sshd to
place users in a chroot jail instead of the root file system. We will use the
"Match" configuration option to accomplish this. Add the following lines to the
end of your /etc/ssh/sshd_config file.

       Match Group chroot_users
               ChrootDirectory /chroot

This option will check if the user is in group "chroot_users" and if they are,
it will place them inside of /chroot.

The final step is to restart sshd

       elw@sdf:~ $> /etc/rc.d/rc.sshd restart

At this point you should be able to ssh in to your system as chrootuser and be
placed in the newly created chroot jail. If you wish to take this a step
further, you can also copy /etc/profile and /etc/profile.d over to the /chroot.

       elw@sdf:~ $> cp /etc/profile /chroot/etc/profile
       elw@sdf:~ $> cp -R /etc/profile.d /chroot/etc/profile.d

If you choose to do this, however, there are some additional files which need
to be brought over to the chroot environment or you will get a bash prompt that
looks like the following example:

       I have no name!@sdf:~ $>

To resolve this issue you need to include some libraries which ldd did not
reveal. These are the two libnss_files libraries. Use the example below:

       elw@sdf:~ $> cp /lib/libnss_files* /chroot/lib

If you have included the default /etc/profile and /etc/profile.d in your
chroot, you will also want to include /bin/cat, /usr/bin/id, /bin/grep and
/bin/dircolors as they are required for the default /etc/profile to work 100%.
They do not require the addition of any more libraries, however so you can just
copy the binraries directly over to the chroot environment. See the example
below:

       elw@sdf:~ $> mkdir /chroot/usr/bin
       elw@sdf:~ $> cp /bin/cat /chroot/bin
       elw@sdf:~ $> cp /bin/grep /chroot/bin
       elw@sdf:~ $> cp /bin/dircolors /chroot/bin
       elw@sdf:~ $> cp /usr/bin/id /chroot/usr/bin

With that, you should pretty much have all you need to have a decently well
running chroot jail for your users to access via ssh. This will also have the
added benfit of chrooting the users that access the system with sftp as well.
Whenever you want to add another user, just reference the creating a user
section. If you need to copy over additional binaries, use the ldd examples and
keep in mind that more complicated binaries may have dependencies and
complicated dynamic libraries which may not appear when using ldd.