#!/bin/sh # # (c) Copyright by Wolfgang Fuschlberger # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # ( http://www.fsf.org/licenses/gpl.txt ) # first Release: 2004-07-30 # latest update: 2006-07-17 # # The latest version of the script is available at # http://www.fuschlberger.net/programs/ssh-scp-chroot-jail/ # # Feedback is welcome! # # Thanks for Bugfixes / Enhancements to # Michael Prokop , # Randy K., Randy D. and Jonathan Hunter. # # Features: # - enable scp and sftp in the chroot-jail # - use one directory (default /home/jail/) as chroot for all users ################################################################################ # Check if we are called with username or update if [ -z "$1" ] ; then echo echo "Error: Parameter missing. Did you forget the username?" echo "-------------------------------------------------------------" echo "Creating new chrooted account:" echo "Usage: $0 username" echo echo "or specify \$SHELL and path where the jail should be located:" echo "Usage: $0 username [/path/to/chroot-shell [/path/to/jail]]" echo "Default shell = /bin/chroot-shell" echo "Default chroot-path = /home/jail" echo "-------------------------------------------------------------" echo "Updating files in the chroot-jail:" echo "Usage: $0 update [/path/to/chroot-shell [/path/to/jail]]" echo "-------------------------------------------------------------" echo "To uninstall: # userdel \$USER" echo " # rm -rf /home/jail" echo " # rm -f /bin/chroot-shell" echo " delete the User's line from /etc/sudoers" exit fi echo "Am I root? " if [ "$(whoami &2>/dev/null)" != "root" ] && [ "$(id -un &2>/dev/null)" != "root" ] ; then echo " NO! Error: You must be root to run this script." exit 1 fi echo " OK"; # Check existence of necessary files echo "Checking distribution... " if [ -f /etc/debian_version ]; then echo " Supported Distribution found" echo -e " System is running Debian Linux\n" DISTRO=DEBIAN; elif [ -f /etc/SuSE-release ]; then echo " Supported Distribution found" echo -e " System is running SuSE Linux\n" DISTRO=SUSE; elif [ -f /etc/fedora-release ]; then echo " Supported Distribution found" echo -e " System is running Fedora Linux\n" DISTRO=FEDORA; elif [ -f /etc/redhat-release ]; then echo " Supported Distribution found" echo -e " System is running Red Hat Linux\n" DISTRO=REDHAT; else echo -e " failed...........\nThis script works best on Debian, Red Hat and SuSE Linux!\nLet's try it nevertheless....\n" #exit 1 fi # Specify the apps you want to copy to the jail if [ "$DISTRO" = SUSE ]; then 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" elif [ "$DISTRO" = FEDORA ]; then 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" elif [ "$DISTRO" = REDHAT ]; then 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" elif [ "$DISTRO" = DEBIAN ]; then 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" else 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" fi # Check existence of necessary files echo "Checking for chroot..." if [ `which chroot` ]; then echo " OK"; else echo " failed Please install chroot-package/binary! " exit 1 fi echo "Checking for sudo..." if [ `which sudo` ]; then echo " OK "; else echo " failed Please install sudo-package/binary! " exit 1 fi # Get accountname to create CHROOT_USERNAME=$1 if ! [ -z "$2" ] ; then SHELL=$2 else SHELL=/bin/chroot-shell fi if ! [ -z "$3" ] ; then JAILPATH=$3 else JAILPATH=/home/jail fi # Exit if user already exists id $CHROOT_USERNAME > /dev/null 2>&1 && { echo "User exists."; echo "Exiting."; exit 1; } # Create $SHELL (shell for jailed accounts) if [ -f ${SHELL} ] ; then echo "$SHELL exists. Don't want to overwrite it. Please delete it before running the script." exit 1 else echo "Creating $SHELL" echo '#!/bin/sh' > $SHELL echo "`which sudo` `which chroot` $JAILPATH /bin/su - \$USER" \"\$@\" >> $SHELL chmod 755 $SHELL fi # make common jail for everybody if inexistent if [ ! -d $JAILPATH ] ; then mkdir -p $JAILPATH echo "Creating $JAILPATH" fi cd $JAILPATH # Create directories in jail that do not exist yet JAILDIRS="dev etc etc/pam.d bin home sbin usr usr/bin" for directory in $JAILDIRS ; do if [ ! -d "$JAILPATH/$directory" ] ; then mkdir $JAILPATH/"$directory" echo "Creating $JAILPATH/$directory" fi done echo # Comment in the following lines if your apache can't read the directories and # uses the security contexts # Fix security contexts so Apache can read files #CHCON=$(`which chcon`) #if [ -n "$CHCON" ] && [ -x $CHCON ]; then # $CHCON -t home_root_t $JAILPATH/home # $CHCON -t user_home_dir_t $JAILPATH/home/$CHROOT_USERNAME #fi # Creating necessary devices [ -r $JAILPATH/dev/urandom ] || mknod $JAILPATH/dev/urandom c 1 9 [ -r $JAILPATH/dev/null ] || mknod -m 666 $JAILPATH/dev/null c 1 3 [ -r $JAILPATH/dev/zero ] || mknod -m 666 $JAILPATH/dev/zero c 1 5 [ -r $JAILPATH/dev/tty ] || mknod -m 666 $JAILPATH/dev/tty c 5 0 # if we only want to update the files in the jail # skip the creation of the new account if [ "$1" != "update" ]; then # Modifiy /etc/sudoers to enable chroot-ing for users # must be removed by hand if account is deleted echo "Modifying /etc/sudoers" echo "$CHROOT_USERNAME ALL=NOPASSWD: `which chroot`, /bin/su - $CHROOT_USERNAME" >> /etc/sudoers # Define HomeDir for simple referencing HOMEDIR="$JAILPATH/home/$CHROOT_USERNAME" # Create new account, setting $SHELL to the above created script and # $HOME to $JAILPATH/home/* echo "Adding User \"$CHROOT_USERNAME\" to system" useradd -m -d "$HOMEDIR" -s "$SHELL" $CHROOT_USERNAME && chmod 700 "$HOMEDIR" # Enter password for new account passwd $CHROOT_USERNAME echo # Create /usr/bin/groups in the jail echo "#!/bin/bash" > usr/bin/groups echo "id -Gn" >> usr/bin/groups chmod 755 usr/bin/groups # Add users to etc/passwd # # check if file exists (ie we are not called for the first time) # if yes skip root's entry and do not overwrite the file if [ ! -f etc/passwd ] ; then grep /etc/passwd -e "^root" > etc/passwd fi if [ ! -f etc/group ] ; then grep /etc/group -e "^root" > etc/group # add the group for all users to etc/group (otherwise there is a nasty error # message and probably because of that changing directories doesn't work with # winSCP) grep /etc/group -e "^users" >> etc/group fi # grep the username which was given to us from /etc/passwd and add it # to ./etc/passwd replacing the $HOME with the directory as it will then # appear in the jail echo "Adding User $CHROOT_USERNAME to jail" grep -e "^$CHROOT_USERNAME:" /etc/passwd | \ sed -e "s#$JAILPATH##" \ -e "s#$SHELL#/bin/bash#" >> etc/passwd # if the system uses one account/one group we write the # account's group to etc/group grep -e "^$CHROOT_USERNAME:" /etc/group >> etc/group # write the user's line from /etc/shadow to /home/jail/etc/shadow grep -e "^$CHROOT_USERNAME:" /etc/shadow >> etc/shadow # endif for =! update fi # Copy the apps and the related libs echo "Copying necessary library-files to jail (may take some time)" # The original code worked fine on RedHat 7.3, but did not on FC3. # On FC3, when the 'ldd' is done, there is a 'linux-gate.so.1' that # points to nothing (or a 90xb.....), and it also does not pick up # some files that start with a '/'. To fix this, I am doing the ldd # to a file called ldlist, then going back into the file and pulling # out the libs that start with '/' # # Randy K. # # The original code worked fine on 2.4 kernel systems. Kernel 2.6 # introduced an internal library called 'linux-gate.so.1'. This # 'phantom' library caused non-critical errors to display during the # copy since the file does not actually exist on the file system. # To fix re-direct output of ldd to a file, parse the file and get # library files that start with / # if [ -x ${HOME}/ldlist ]; then mv ${HOME}/ldlist ${HOME}/ldlist.bak fi if [ -x ${HOME}/lddlist2 ]; then mv ${HOME}/lddlist2 ${HOME}/lddlist2.bak fi for app in $APPS; do # First of all, check that this application exists if [ -x $app ]; then # Check that the directory exists; create it if not. app_path=`echo $app | sed -e 's#\(.\+\)/[^/]\+#\1#'` if ! [ -d .$app_path ]; then mkdir -p .$app_path fi # If the files in the chroot are on the same file system as the # original files you should be able to use hard links instead of # copying the files, too. Symbolic links cannot be used, because the # original files are outside the chroot. cp -p $app .$app # get list of necessary libraries ldd $app >> ${HOME}/ldlist fi done # Clear out any old temporary file before we start if [ -e ${HOME}/ldlist2 ]; then rm ${HOME}/ldlist2 fi for libs in `cat /root/ldlist`; do frst_char="`echo $libs | cut -c1`" if [ "$frst_char" = "/" ]; then echo "$libs" >> /root/ldlist2 fi done for lib in `cat /root/ldlist2`; do mkdir -p .`dirname $lib` > /dev/null 2>&1 # If the files in the chroot are on the same file system as the original # files you should be able to use hard links instead of copying the files, # too. Symbolic links cannot be used, because the original files are # outside the chroot. cp $lib .$lib done # # Now, cleanup the 2 files we created for the library list # /bin/rm -f ${HOME}/ldlist /bin/rm -f ${HOME}/ldlist2 # Necessary files that are not listed by ldd if [ "$DISTRO" = SUSE ]; then cp /lib/libnss_compat.so.2 /lib/libnss_files.so.2 /lib/libnss_dns.so.2 /lib/libxcrypt.so.1 ${JAILPATH}/lib/ elif [ "$DISTRO" = FEDORA ]; then 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/ cp /lib/*.* ${JAILPATH}/lib/ elif [ "$DISTRO" = REDHAT ]; then 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/ # needed for scp on RHEL echo "export LD_LIBRARY_PATH=/usr/kerberos/lib" >> ${JAILPATH}/etc/profile elif [ "$DISTRO" = DEBIAN ]; then 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/ else 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/ fi # if you are using a 64 bit system and have strange problems with login comment # the following lines in, perhaps it works then (motto: if you can't find the # needed library just copy all of them) # #cp /lib/*.* ${JAILPATH}/lib/ #cp /lib/lib64/*.* ${JAILPATH}/lib/lib64/ # if you are using PAM you need stuff from /etc/pam.d/ in the jail, echo "Copying files from /etc/pam.d/ to jail" cp /etc/pam.d/* ${JAILPATH}/etc/pam.d/ # ...and of course the PAM-modules... echo "Copying PAM-Modules to jail" cp -r /lib/security ${JAILPATH}/lib/ # ...and something else useful for PAM cp -r /etc/security ${JAILPATH}/etc/ cp /etc/login.defs ${JAILPATH}/etc/ if [ -f /etc/DIR_COLORS ] ; then cp /etc/DIR_COLORS ${JAILPATH}/etc/ fi exit