3 # (c) Copyright by Wolfgang Fuschlberger
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
14 # ( http://www.fsf.org/licenses/gpl.txt )
16 # first Release: 2004-07-30
17 # latest update: 2006-07-17
19 # The latest version of the script is available at
20 # http://www.fuschlberger.net/programs/ssh-scp-chroot-jail/
22 # Feedback is welcome!
24 # Thanks for Bugfixes / Enhancements to
25 # Michael Prokop <http://www.michael-prokop.at/chroot/>,
26 # Randy K., Randy D. and Jonathan Hunter.
30 # - enable scp and sftp in the chroot-jail
31 # - use one directory (default /home/jail/) as chroot for all users
32 ################################################################################
34 # Check if we are called with username or update
37 echo "Error: Parameter missing. Did you forget the username?"
38 echo "-------------------------------------------------------------"
39 echo "Creating new chrooted account:"
40 echo "Usage: $0 username"
42 echo "or specify \$SHELL and path where the jail should be located:"
43 echo "Usage: $0 username [/path/to/chroot-shell [/path/to/jail]]"
44 echo "Default shell = /bin/chroot-shell"
45 echo "Default chroot-path = /home/jail"
46 echo "-------------------------------------------------------------"
47 echo "Updating files in the chroot-jail:"
48 echo "Usage: $0 update [/path/to/chroot-shell [/path/to/jail]]"
49 echo "-------------------------------------------------------------"
50 echo "To uninstall: # userdel \$USER"
51 echo " # rm -rf /home/jail"
52 echo " # rm -f /bin/chroot-shell"
53 echo " delete the User's line from /etc/sudoers"
58 if [ "$(whoami &2>/dev/null)" != "root" ] && [ "$(id -un &2>/dev/null)" != "root" ] ; then
61 Error: You must be root to run this script."
66 # Check existence of necessary files
67 echo "Checking distribution... "
68 if [ -f /etc/debian_version ];
69 then echo " Supported Distribution found"
70 echo -e " System is running Debian Linux\n"
72 elif [ -f /etc/SuSE-release ];
73 then echo " Supported Distribution found"
74 echo -e " System is running SuSE Linux\n"
76 elif [ -f /etc/fedora-release ];
77 then echo " Supported Distribution found"
78 echo -e " System is running Fedora Linux\n"
80 elif [ -f /etc/redhat-release ];
81 then echo " Supported Distribution found"
82 echo -e " System is running Red Hat Linux\n"
84 else echo -e " failed...........\nThis script works best on Debian, Red Hat and SuSE Linux!\nLet's try it nevertheless....\n"
88 # Specify the apps you want to copy to the jail
89 if [ "$DISTRO" = SUSE ]; then
90 APPS="/bin/bash /bin/cp /usr/bin/dircolors /bin/ls /bin/mkdir /bin/mv /bin/rm /bin/rmdir /bin/sh /bin/su /usr/bin/groups /usr/bin/id /usr/bin/netcat /usr/bin/rsync /usr/bin/ssh /usr/bin/scp /sbin/unix_chkpwd /usr/lib/ssh/sftp-server"
91 elif [ "$DISTRO" = FEDORA ]; then
92 APPS="/bin/bash /bin/cp /usr/bin/dircolors /bin/ls /bin/mkdir /bin/mv /bin/rm /bin/rmdir /bin/sh /bin/su /usr/bin/groups /usr/bin/id /usr/bin/nc /usr/bin/rsync /usr/bin/ssh /usr/bin/scp /sbin/unix_chkpwd /usr/libexec/openssh/sftp-server"
93 elif [ "$DISTRO" = REDHAT ]; then
94 APPS="/bin/bash /bin/cp /usr/bin/dircolors /bin/ls /bin/mkdir /bin/mv /bin/rm /bin/rmdir /bin/sh /bin/su /usr/bin/groups /usr/bin/id /usr/bin/nc /usr/bin/rsync /usr/bin/ssh /usr/bin/scp /sbin/unix_chkpwd /usr/libexec/openssh/sftp-server"
95 elif [ "$DISTRO" = DEBIAN ]; then
96 APPS="/bin/bash /bin/cp /usr/bin/dircolors /bin/ls /bin/mkdir /bin/mv /bin/rm /bin/rmdir /bin/sh /bin/su /usr/bin/groups /usr/bin/id /usr/bin/rsync /usr/bin/ssh /usr/bin/scp /sbin/unix_chkpwd /usr/lib/sftp-server"
98 APPS="/bin/bash /bin/cp /usr/bin/dircolors /bin/ls /bin/mkdir /bin/mv /bin/rm /bin/rmdir /bin/sh /bin/su /usr/bin/groups /usr/bin/id /usr/bin/rsync /usr/bin/ssh /usr/bin/scp /usr/sbin/unix_chkpwd /usr/lib/misc/sftp-server"
101 # Check existence of necessary files
102 echo "Checking for chroot..."
103 if [ `which chroot` ];
107 Please install chroot-package/binary!
112 echo "Checking for sudo..."
113 if [ `which sudo` ]; then
119 Please install sudo-package/binary!
124 # Get accountname to create
127 if ! [ -z "$2" ] ; then
130 SHELL=/bin/chroot-shell
133 if ! [ -z "$3" ] ; then
139 # Exit if user already exists
140 id $CHROOT_USERNAME > /dev/null 2>&1 && { echo "User exists."; echo "Exiting."; exit 1; }
142 # Create $SHELL (shell for jailed accounts)
143 if [ -f ${SHELL} ] ; then
144 echo "$SHELL exists. Don't want to overwrite it.
145 Please delete it before running the script."
148 echo "Creating $SHELL"
149 echo '#!/bin/sh' > $SHELL
150 echo "`which sudo` `which chroot` $JAILPATH /bin/su - \$USER" \"\$@\" >> $SHELL
154 # make common jail for everybody if inexistent
155 if [ ! -d $JAILPATH ] ; then
157 echo "Creating $JAILPATH"
161 # Create directories in jail that do not exist yet
162 JAILDIRS="dev etc etc/pam.d bin home sbin usr usr/bin"
163 for directory in $JAILDIRS ; do
164 if [ ! -d "$JAILPATH/$directory" ] ; then
165 mkdir $JAILPATH/"$directory"
166 echo "Creating $JAILPATH/$directory"
171 # Comment in the following lines if your apache can't read the directories and
172 # uses the security contexts
173 # Fix security contexts so Apache can read files
174 #CHCON=$(`which chcon`)
175 #if [ -n "$CHCON" ] && [ -x $CHCON ]; then
176 # $CHCON -t home_root_t $JAILPATH/home
177 # $CHCON -t user_home_dir_t $JAILPATH/home/$CHROOT_USERNAME
180 # Creating necessary devices
181 [ -r $JAILPATH/dev/urandom ] || mknod $JAILPATH/dev/urandom c 1 9
182 [ -r $JAILPATH/dev/null ] || mknod -m 666 $JAILPATH/dev/null c 1 3
183 [ -r $JAILPATH/dev/zero ] || mknod -m 666 $JAILPATH/dev/zero c 1 5
184 [ -r $JAILPATH/dev/tty ] || mknod -m 666 $JAILPATH/dev/tty c 5 0
186 # if we only want to update the files in the jail
187 # skip the creation of the new account
188 if [ "$1" != "update" ]; then
190 # Modifiy /etc/sudoers to enable chroot-ing for users
191 # must be removed by hand if account is deleted
192 echo "Modifying /etc/sudoers"
193 echo "$CHROOT_USERNAME ALL=NOPASSWD: `which chroot`, /bin/su - $CHROOT_USERNAME" >> /etc/sudoers
195 # Define HomeDir for simple referencing
196 HOMEDIR="$JAILPATH/home/$CHROOT_USERNAME"
198 # Create new account, setting $SHELL to the above created script and
199 # $HOME to $JAILPATH/home/*
200 echo "Adding User \"$CHROOT_USERNAME\" to system"
201 useradd -m -d "$HOMEDIR" -s "$SHELL" $CHROOT_USERNAME && chmod 700 "$HOMEDIR"
202 # Enter password for new account
203 passwd $CHROOT_USERNAME
206 # Create /usr/bin/groups in the jail
207 echo "#!/bin/bash" > usr/bin/groups
208 echo "id -Gn" >> usr/bin/groups
209 chmod 755 usr/bin/groups
211 # Add users to etc/passwd
213 # check if file exists (ie we are not called for the first time)
214 # if yes skip root's entry and do not overwrite the file
215 if [ ! -f etc/passwd ] ; then
216 grep /etc/passwd -e "^root" > etc/passwd
218 if [ ! -f etc/group ] ; then
219 grep /etc/group -e "^root" > etc/group
220 # add the group for all users to etc/group (otherwise there is a nasty error
221 # message and probably because of that changing directories doesn't work with
223 grep /etc/group -e "^users" >> etc/group
226 # grep the username which was given to us from /etc/passwd and add it
227 # to ./etc/passwd replacing the $HOME with the directory as it will then
229 echo "Adding User $CHROOT_USERNAME to jail"
230 grep -e "^$CHROOT_USERNAME:" /etc/passwd | \
231 sed -e "s#$JAILPATH##" \
232 -e "s#$SHELL#/bin/bash#" >> etc/passwd
234 # if the system uses one account/one group we write the
235 # account's group to etc/group
236 grep -e "^$CHROOT_USERNAME:" /etc/group >> etc/group
238 # write the user's line from /etc/shadow to /home/jail/etc/shadow
239 grep -e "^$CHROOT_USERNAME:" /etc/shadow >> etc/shadow
241 # endif for =! update
244 # Copy the apps and the related libs
245 echo "Copying necessary library-files to jail (may take some time)"
247 # The original code worked fine on RedHat 7.3, but did not on FC3.
248 # On FC3, when the 'ldd' is done, there is a 'linux-gate.so.1' that
249 # points to nothing (or a 90xb.....), and it also does not pick up
250 # some files that start with a '/'. To fix this, I am doing the ldd
251 # to a file called ldlist, then going back into the file and pulling
252 # out the libs that start with '/'
256 # The original code worked fine on 2.4 kernel systems. Kernel 2.6
257 # introduced an internal library called 'linux-gate.so.1'. This
258 # 'phantom' library caused non-critical errors to display during the
259 # copy since the file does not actually exist on the file system.
260 # To fix re-direct output of ldd to a file, parse the file and get
261 # library files that start with /
263 if [ -x ${HOME}/ldlist ]; then
264 mv ${HOME}/ldlist ${HOME}/ldlist.bak
266 if [ -x ${HOME}/lddlist2 ]; then
267 mv ${HOME}/lddlist2 ${HOME}/lddlist2.bak
272 # First of all, check that this application exists
274 # Check that the directory exists; create it if not.
275 app_path=`echo $app | sed -e 's#\(.\+\)/[^/]\+#\1#'`
276 if ! [ -d .$app_path ]; then
280 # If the files in the chroot are on the same file system as the
281 # original files you should be able to use hard links instead of
282 # copying the files, too. Symbolic links cannot be used, because the
283 # original files are outside the chroot.
286 # get list of necessary libraries
287 ldd $app >> ${HOME}/ldlist
291 # Clear out any old temporary file before we start
292 if [ -e ${HOME}/ldlist2 ]; then
295 for libs in `cat /root/ldlist`; do
296 frst_char="`echo $libs | cut -c1`"
297 if [ "$frst_char" = "/" ]; then
298 echo "$libs" >> /root/ldlist2
301 for lib in `cat /root/ldlist2`; do
302 mkdir -p .`dirname $lib` > /dev/null 2>&1
304 # If the files in the chroot are on the same file system as the original
305 # files you should be able to use hard links instead of copying the files,
306 # too. Symbolic links cannot be used, because the original files are
307 # outside the chroot.
312 # Now, cleanup the 2 files we created for the library list
314 /bin/rm -f ${HOME}/ldlist
315 /bin/rm -f ${HOME}/ldlist2
317 # Necessary files that are not listed by ldd
318 if [ "$DISTRO" = SUSE ]; then
319 cp /lib/libnss_compat.so.2 /lib/libnss_files.so.2 /lib/libnss_dns.so.2 /lib/libxcrypt.so.1 ${JAILPATH}/lib/
320 elif [ "$DISTRO" = FEDORA ]; then
321 cp /lib/libnss_compat.so.2 /lib/libnsl.so.1 /lib/libnss_files.so.2 /lib/ld-linux.so.2 /lib/ld-ldb.so.3 /lib/libnss_dns.so.2 /lib/libxcrypt.so.1 ${JAILPATH}/lib/
322 cp /lib/*.* ${JAILPATH}/lib/
323 elif [ "$DISTRO" = REDHAT ]; then
324 cp /lib/libnss_compat.so.2 /lib/libnsl.so.1 /lib/libnss_files.so.2 /lib/ld-linux.so.2 /lib/ld-lsb.so.1 /lib/libnss_dns.so.2 /lib/libxcrypt.so.1 ${JAILPATH}/lib/
325 # needed for scp on RHEL
326 echo "export LD_LIBRARY_PATH=/usr/kerberos/lib" >> ${JAILPATH}/etc/profile
327 elif [ "$DISTRO" = DEBIAN ]; then
328 cp /lib/libnss_compat.so.2 /lib/libnsl.so.1 /lib/libnss_files.so.2 /lib/libcap.so.1 /lib/libnss_dns.so.2 ${JAILPATH}/lib/
330 cp /lib/libnss_compat.so.2 /lib/libnsl.so.1 /lib/libnss_files.so.2 /lib/libcap.so.1 /lib/libnss_dns.so.2 ${JAILPATH}/lib/
333 # if you are using a 64 bit system and have strange problems with login comment
334 # the following lines in, perhaps it works then (motto: if you can't find the
335 # needed library just copy all of them)
337 #cp /lib/*.* ${JAILPATH}/lib/
338 #cp /lib/lib64/*.* ${JAILPATH}/lib/lib64/
340 # if you are using PAM you need stuff from /etc/pam.d/ in the jail,
341 echo "Copying files from /etc/pam.d/ to jail"
342 cp /etc/pam.d/* ${JAILPATH}/etc/pam.d/
344 # ...and of course the PAM-modules...
345 echo "Copying PAM-Modules to jail"
346 cp -r /lib/security ${JAILPATH}/lib/
348 # ...and something else useful for PAM
349 cp -r /etc/security ${JAILPATH}/etc/
350 cp /etc/login.defs ${JAILPATH}/etc/
352 if [ -f /etc/DIR_COLORS ] ; then
353 cp /etc/DIR_COLORS ${JAILPATH}/etc/