BigAdmin System Administration Portal
Community-Submitted Article
Print-friendly VersionPrint-friendly Version
This content is submitted by a BigAdmin user. It has not been reviewed for technical accuracy by Sun Microsystems, though it may have been lightly edited to improve readability. If you find an error or would like to comment on the article, please contact the submitter or use the comment field at the bottom of the article. Community submissions may not follow Sun trademark guidelines. For information on Sun trademarks, please see http://www.sun.com/suntrademarks/.
 
 

Setting Up a Chroot Jail With rssh in the Solaris 8 OS

Russell Martin, May 2007


Introduction

The free rssh restricted shell written by Derek Martin seems to restrict users to using sftp or scp and prevents them from logging in to an interactive prompt. For me, this is like giving someone an FTP-only account in the day and age when unsecure utilities, such as telnet and ftp, have been replaced with secure utilities, such as ssh, sftp, and scp.

You can download and build rssh from source by going to http://pizzashack.org/rssh/. There is also a packaged version of rssh for the Solaris Operating System, which is available from blastwave.org. Setting up rssh will not be covered in this document.

The rssh shell comes with a helper program called rssh_chroot_helper, which allows you to edit your rssh.conf file to either place all users or a specific user in a chroot jail. Placing users in a chroot jail can be very useful if you have users who should be able to transfer files but shouldn't be able to browse the entire file system of the server to which they are connecting through sftp.

I'm certainly no expert when it comes to chroot environments. In fact, I hadn't ever set one up until I decided to try it with rssh. I read all the documentation that came with rssh and even read through the mkchroot.sh script that Derek provides with rssh. However, his script was written for Red Hat Linux, not the Solaris OS, so some of what the script is doing does not apply.

It took me about 16 hours of frustrating trial and error to get my first chroot jail set up with rssh, and so I'm providing the following information in the hope that it helps others who are attempting the same task.

Contents


Basic Steps

The basic steps are as follows:

  1. Install rssh on your system and ensure that it is working as a shell replacement that allows only sftp or scp. (This will not be covered in this document.)
  2. Create a chroot jail directory. (This directory will appear to users to be the root of the disk when they log in. I created mine in /export/home/chroot.)
  3. Copy the necessary executables (preserving permissions) inside the jail directory with a directory structure that mimics the one in the root file system.
  4. Copy any libraries that the executables need inside the jail (again preserving permissions), and, as in the previous step, use a directory structure that mimics the one in the root directory.
  5. Create home directories for your users inside of the jail.
  6. Modify the users' home directory path settings in /etc/passwd.
  7. Copy /etc/passwd inside the jail.
  8. Edit the rssh.conf file to place all users, or particular users, in a chroot environment when they log in.

Required Files

To my knowledge, the files that need to be copied into your jail are as follows. (However, I've done this only on the Solaris 8 OS.)

  • rssh
  • scp
  • sftp-server
  • rssh_chroot_helper
  • ldd
  • ksh
  • pwd

I feel like I can't say this too many times: The files need to be placed in the jail directory in directories that mimic their placement in the root file system.

For instance, on the root file system, ksh is in the /usr/bin directory.

So, if your jail was going to be in /export/home/chroot, then ksh would need to be copied to /export/home/chroot/usr/bin/ksh.


Library Files

The library files that any of these files need can be found by using the ldd command.

Running ldd against sftp-server produces output similar to this on my system:

  $ ldd /opt/csw/libexec/sftp-server
  libcrypto.so.0.9.8 =>   /opt/csw/lib//libcrypto.so.0.9.8
  librt.so.1 =>    /usr/lib/librt.so.1
  libsocket.so.1 =>        /usr/lib/libsocket.so.1
  libc.so.1 =>     /usr/lib/libc.so.1
  libnsl.so.1 =>   /usr/lib/libnsl.so.1
  libdl.so.1 =>    /usr/lib/libdl.so.1
  libaio.so.1 =>   /usr/lib/libaio.so.1
  libmp.so.2 =>    /usr/lib/libmp.so.2
  /usr/platform/SUNW,Sun-Blade-100/lib/libc_psr.so.1

All of those library files have to be copied inside of the directory that is going to be the jail directory, and they must be placed in directories that mimic the directory structure of the root file system.

For example, my chroot jail was set up in /export/home/chroot. So, /opt/csw/lib/libcrypto.so.0.9.8 was copied to /export/home/chroot/opt/csw/lib/libcrypto.so.0.9.8.

You could do all of this by hand, but I think it's easier to use a script, and I provide my script below.


The ldd Command Doesn't Tell the Whole Story

Unfortunately, ldd doesn't show all the files that sftp-server tries to open at startup. Upon launch, sftp-server tries to open an additional file, and I didn't discover this until I had run truss.

Here's the command I used to run truss against sftp-server and capture its output to a text file in my home directory:

  - $ truss -o /export/home/rmartin/truss_sftp-server.txt
/opt/csw/libexec/sftp-server

Running truss like this started the sftp-server and didn't return me to a command prompt. So, I waited a minute or so and then pressed Ctrl-C to stop sftp-server. I'm sure there is a more elegant way to do that, but I got the output that I needed.

Then, I used grep to find any lines that began with "open" to see which libraries and files sftp-server had opened when it started up:

- $ grep ^open /export/home/rmartin/truss_sftp-server.txt

This gave me the following:

  open("/var/ld/ld.config", O_RDONLY)             Err#2 ENOENT
  open("/opt/csw/lib//libcrypto.so.0.9.8", O_RDONLY) = 3
  open("/usr/lib/librt.so.1", O_RDONLY)           = 3
  open("/usr/lib/libsocket.so.1", O_RDONLY)       = 3
  open("/usr/lib/libc.so.1", O_RDONLY)            = 3
  open("/usr/lib/libnsl.so.1", O_RDONLY)          = 3
  open("/usr/lib/libdl.so.1", O_RDONLY)           = 3
  open("/usr/lib/libaio.so.1", O_RDONLY)          = 3
  open("/usr/lib/libmp.so.2", O_RDONLY)           = 3
  open("/usr/platform/SUNW,Sun-Blade-100/lib/libc_psr.so.1",
O_RDONLY) = 3
  open64("/dev/null", O_RDWR)                     = 3

Notice that in addition to the libraries that sftp-server is opening, it is also opening /dev/null. This output shows that in addition to copying the libraries inside the jail, /dev/null is also necessary.

(I also noticed that it is failing to open /var/ld/ld.config, but since this file didn't exist, and sftp works outside the jail, I assumed this was safe to ignore.)


What to Check When Things Aren't Working

Unfortunately, ldd and truss don't seem to tell the whole story either. When things still weren't working for me, I started checking /var/adm/messages and /var/spool/adm/syslog, and I discovered this:

  /var/adm/messages:Aug 23 18:41:14 slccon01 elfexec:
[ID 700856 kern.notice] ksh: Cannot find /usr/lib/ld.so.1
  /var/adm/messages:Aug 23 18:41:14 slccon01 elfexec:
[ID 700856 kern.notice] sftp-server: Cannot find /usr/lib/ld.so.1

In other words, both ksh and sftp-server are looking for /usr/lib/ld.so.1, a library that doesn't show up when you run ldd or truss against them. I copied this file into my jail as well.


Copy Preserving Permissions

The first time I got my jail working, I had suid root on the sftp-server inside of the jail. My rssh_chroot_helper outside the jail had not been suid root. (This was my error when I packaged rssh for blastwave.org. Yes, it's been corrected.) When it was pointed out to me that rssh_chroot_helper needed suid root and things still weren't working, I then deduced that maybe sftp-server needed a suid root.

This got things working, but it is a really bad idea, and once my initial elation from having the jail functioning wore off, I soon realized that the user would have free reign inside the jail and be able to break things or replace any files. I was wearing out my welcome on the rssh users mailing list when I decided to modify my script to use cp -p instead of cp.

I blew away my jail, re-ran my script, and suddenly things were working as they should be. I'm not sure why I had to use cp -p when none of the other scripts I've seen posted had done it this way, and it had not been mentioned on any discussions I'd read.


Make the User's Home Directory

Once you've created the user's home directory inside the jail, you need to either edit /etc/passwd or use usermod to change the user's home directory setting to the absolute path for the root file system, not the path inside of the jail.

Example:

  - testrssh:x:301:301:rssh test
account:/export/home/chroot/export/home/testrssh:/opt/csw/bin/rssh

Notice how the home directory is set to /export/home/chroot/export/home/testrssh, not to /export/home/testrssh.

Once the user is logged in, it will appear that their home directory is simply /export/home/testrssh.

Also, notice that their shell is set to rssh in the root file system, and not inside the jail.


Edit rssh.conf

The default rssh.conf file is very well documented and has very clear examples of what to do. Read it and you shouldn't have any problems configuring one user or all users to use your jail.


My Script for Creating Chroot Jails

This is the script I developed for creating chroot jails. I'm providing it without any guarantees of any kind. It works for me, but it may not work for you. You assume any and all responsibility for using this script on your systems.

This script does everything but edit the rssh.conf file and change the user's home directory setting. It does echo out a reminder about the home directory setting.

The script does not take command line arguments. Instead, you need to edit the lines that set environment variables within the script.

[Begin Script]
CHROOTPATH=/export/home/chroot
USER_HOME_DIR=export/home/testrssh
USER_NAME=testrssh
GROUP_NAME=testrssh
SFTP_PATH=/opt/csw/libexec/sftp-server
SCP_PATH=/opt/csw/bin/scp
RSSH_PATH=/opt/csw/bin/rssh
CHROOT_HELPER_PATH=/opt/csw/libexec/rssh_chroot_helper
LDD_PATH=/usr/bin/ldd
KSH_PATH1=/bin/ksh
KSH_PATH2=/usr/bin/ksh
PWD_PATH1=/bin/pwd
PWD_PATH2=/usr/bin/pwd
>>
CopyLibFiles(){
  for aFile in `ldd ${currExecutable} | cut -d' ' -f3`; do
    if [ ! -d ${CHROOTPATH}/`dirname ${aFile}` ]; then
      mkdir -p ${CHROOTPATH}/`dirname ${aFile}`;
    fi
    cp -p ${aFile} ${CHROOTPATH}${aFile}
  done;
}
>>
CopyExecutable(){
  directoryPath=`dirname ${currExecutable}`
  mkdir -p ${CHROOTPATH}${directoryPath}
  cp -p ${currExecutable} ${CHROOTPATH}${directoryPath}
}
>>
# copy sftp-server and library files
# ==================================
currExecutable=${SFTP_PATH}
CopyExecutable
CopyLibFiles
>>
# copy scp and library files
# ==========================
currExecutable=${SCP_PATH}
CopyExecutable
CopyLibFiles
>>
# copy rssh and library files
# ===========================
currExecutable=${RSSH_PATH}
CopyExecutable
CopyLibFiles
>>
# copy rssh_chroot_helper and library files
# =========================================
currExecutable=${CHROOT_HELPER_PATH}
CopyExecutable
CopyLibFiles

# copy ldd and library files
# ==========================
currExecutable=${LDD_PATH}
CopyExecutable
CopyLibFiles
>>
# copy ksh and library files
# =========================
currExecutable=${KSH_PATH1}
CopyExecutable
CopyLibFiles
currExecutable=${KSH_PATH2}
CopyExecutable
CopyLibFiles

# copy pwd and library files
# =========================
currExecutable=${PWD_PATH1}
CopyExecutable
CopyLibFiles
currExecutable=${PWD_PATH2}
CopyExecutable
CopyLibFiles

>>
# copy file(s) from /etc
# ====================
mkdir -p ${CHROOTPATH}/etc
cp -p /etc/passwd ${CHROOTPATH}/etc

# create home directory in jail
# =============================
mkdir -p ${CHROOTPATH}/${USER_HOME_DIR}
chown ${USER_NAME}:${GROUP_NAME} ${CHROOTPATH}/${USER_HOME_DIR}
echo "Remember to edit /etc/passwd with absolute path to jailed /
  home dir: ${CHROOTPATH}/${USER_HOME_DIR}"

# copy ld.so.1
# ============
cp -p /usr/lib/ld.so.1 ${CHROOTPATH}/usr/lib/

# create /dev/null in jail
# ========================
mkdir -p ${CHROOTPATH}/dev
cp -p /dev/null ${CHROOTPATH}/dev
[End Script]

What the Script Creates

Surprisingly, very few files ended up in my working jail. Here's the directory output:

  /export/home/chroot/
  /export/home/chroot/opt
  /export/home/chroot/opt/csw
  /export/home/chroot/opt/csw/libexec
  /export/home/chroot/opt/csw/libexec/sftp-server
  /export/home/chroot/opt/csw/libexec/rssh_chroot_helper
  /export/home/chroot/opt/csw/lib
  /export/home/chroot/opt/csw/lib/libcrypto.so.0.9.8
  /export/home/chroot/opt/csw/bin
  /export/home/chroot/opt/csw/bin/scp
  /export/home/chroot/opt/csw/bin/rssh
  /export/home/chroot/usr
  /export/home/chroot/usr/lib
  /export/home/chroot/usr/lib/librt.so.1
  /export/home/chroot/usr/lib/libsocket.so.1
  /export/home/chroot/usr/lib/libc.so.1
  /export/home/chroot/usr/lib/libnsl.so.1
  /export/home/chroot/usr/lib/libdl.so.1
  /export/home/chroot/usr/lib/libaio.so.1
  /export/home/chroot/usr/lib/libmp.so.2
  /export/home/chroot/usr/lib/libelf.so.1
  /export/home/chroot/usr/lib/libsecdb.so.1
  /export/home/chroot/usr/lib/libcmd.so.1
  /export/home/chroot/usr/lib/ld.so.1
  /export/home/chroot/usr/platform
  /export/home/chroot/usr/platform/SUNW,Sun-Blade-100
  /export/home/chroot/usr/platform/SUNW,Sun-Blade-100/lib
  /export/home/chroot/usr/platform/SUNW,
Sun-Blade-100/lib/libc_psr.so.1
  /export/home/chroot/usr/bin
  /export/home/chroot/usr/bin/ldd
  /export/home/chroot/usr/bin/ksh
  /export/home/chroot/usr/bin/pwd
  /export/home/chroot/bin
  /export/home/chroot/bin/ksh
  /export/home/chroot/bin/pwd
  /export/home/chroot/etc
  /export/home/chroot/etc/passwd
  /export/home/chroot/export
  /export/home/chroot/export/home
  /export/home/chroot/export/home/testrssh
  /export/home/chroot/dev
  /export/home/chroot/dev/null

I had seen some advice to create a single jail for all your jailed users; however, after looking at that list of files, I don't think it would be unreasonable to isolate each user in a separate jail.


Conclusion

Setting up a chroot jail for rssh is not a trivial task. Yet, with a little knowledge about what you're trying to accomplish and where to look when things aren't working, it's not impossible either. I hope the information here will save someone else the time I spent in figuring this out the first time, or maybe it will just help me in six months time when I try this again.

If all else fails, you may want to try posting to the rssh user mailing list.

Good luck and happy chroot'ing!


About the Author

Russell Martin has worked for EDS, the Salt Lake City School District, and Packard Bell. Oh, yeah, he also received a computer science degree with an emphasis on software engineering from Weber State University. One more thing: He is the creator of nCalc, a calculator for notebook computers running Mac OS.


Unless otherwise licensed, code in all technical manuals herein (including articles, FAQs, samples) is provided under this License.


BigAdmin
  
 
BigAdmin Upgrade Hub