I had to set up a chrooted user account with scp-Access to let people upload
files to a server in order not to let them browse the whole filesystem.
All the tutorials I found on the Internet described only the process of
patching either the openssh-sources or installing a separate program to be used
as a Shell.

So I wrote this Script which does all the work automatically to set up a working chroot-jail.

What this script does:

modify existing accounts
After explicit confirmation existing accounts can also be modified.
The files from the old Home-directory will be copied into the chroot

create a chrooted jail for these accounts

provide a chrooted shell (via ssh and telnet) for these accounts

provide scp functionality (works with WinSCP)

provide sftp functionality after detecting the location of the
sftp-server binary automatically (sftp-server is only needed if you
want to use sftp, for scp the ssh-daemon is sufficient)

update the files in the jail easily

What this script does not do:

create a special group for the new account
On some systems a group is created for each user (eg by the adduser-script
in debian). This would require the script to mess around with
/etc/group, which in this case is not necessary, since the new
account is automatically added to the group users (here: GID 100)
and the Users' $HOMEs are set to mode 700 so nobody from the
group can browse the directory.

Preparations

Download the script.
Set the eXecutable-bit:chmod 700 make_chroot_jail.sh

How the script works:

The script must be run by root:

To create a new chrooted account:

# make_chroot_jail.sh <Username> /path/to/chroot-shell /path/to/jail

Username is obligatory
filename of the chroot-shell and directory to be used as jail are optional (if one is specified, the other one also has to be specified).

If a user account with this name exists, the script exits with an error-message.

A user account with the name given is created, a chroot-jail is per default created in /home/jail/ which can be used by several chrooted accounts, and the Users' $HOME is per default set to /home/jail/home/<Username>

To update the files in the chroot-jail:

# make_chroot_jail.sh update

All necessary files that have been copied into the jail when running the script for the first time are being updated.
The selection of files can easily be changed by altering the line starting with APPS= at the beginning of the script.
If you want to add programs at a later time just add those to the
APPS= variable and run the script with the 'update' option.

RSA keys

I received a mail asking whether RSA keys could be used for the chrooted users
to avoid having to enter a password on each login (that this might be a
security risk is quite obvious so I won't explain it in detail). So I copied my
pub-key with scp into the chroot-ed $HOME, logged in as the
chrooted user, moved the file to .ssh/authorized_keys and could log in with ssh
without a password.
So it works perfectly well!

Important:

Do not add /bin/chroot-shell to /etc/shells. If you
do, a user can login with su -s /bin/sh - <username> and is
then not locked in the chroot.

On the other hand, if chroot'ed Users want to use FTP, you have to add
/bin/chroot-shell to /etc/shells. (Discovered by Leon
on FC5 with ProFTPd. Thanks!)
The better solution is to add the lineRequireValidShell off
to /etc/proftpd/proftpd.conf.

There is a possible exploit, as somebody told me some days ago. If a local user
outside the chroot knows the password of a chroot'ed user, he can get root.
This exploit needs only one little program in C.
For details have a look at the HTML-sources right below this.
The solution is to make sure that no non-chroot user knows the
username/password of a user in the chroot.

Troubleshooting:

If libxcrypt doesn't exist on your system uncomment the necessary lines near
the end of the script, then it should work.

If you cannot log in (for example on Debian Sarge) and see a warning like "su:
Module is unknown" then comment out the following line from
$JAIL/etc/pam.d/su:

#session required pam_limits.so

After that logging in will work, although I can't explain why the module in
$JAIL/lib/security/ is not found and used.

If you are running the system inside a virtual machine watch out if a different
architecture (32bit vs 64 bit) is emulated and copy the necessary libraries for
both into the chroot-directory (/lib and /lib64). A symptom of this may be the
error message /bin/su user xxx does not exist.