Release new version 2.13.0
[grml-scripts.git] / usr_sbin / make_chroot_jail
index 75cf12c..083c2d2 100755 (executable)
 #    ( http://www.fsf.org/licenses/gpl.txt )
 
 # first Release: 2004-07-30
-# latest update: 2006-07-17
+# latest update: 2007-02-24
 #
 # 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 
+# Thanks for Bugfixes / Enhancements to
 # Michael Prokop <http://www.michael-prokop.at/chroot/>,
 # Randy K., Randy D. and Jonathan Hunter.
 
@@ -29,6 +29,8 @@
 # Features:
 # - enable scp and sftp in the chroot-jail
 # - use one directory (default /home/jail/) as chroot for all users
+# - create new accounts
+# - move existing accounts to chroot
 ################################################################################
 
 # Check if we are called with username or update
@@ -55,10 +57,10 @@ if [ -z "$1" ] ; then
 fi
 
 echo "Am I root?  "
-if [ "$(whoami &2>/dev/null)" != "root" ] && [ "$(id -un &2>/dev/null)" != "root" ] ; then
+if [ "$(whoami 2>/dev/null)" != "root" ] && [ "$(id -un 2>/dev/null)" != "root" ] ; then
   echo "  NO!
 
-Error: You must be root to run this script."
+Error: You must be root to run this script." >&2
   exit 1
 fi
 echo "  OK";
@@ -67,60 +69,117 @@ echo "  OK";
 echo "Checking distribution... "
 if [ -f /etc/debian_version ];
   then echo "  Supported Distribution found"
-       echo -e "  System is running Debian Linux\n"
+       echo "  System is running Debian Linux"
        DISTRO=DEBIAN;
 elif [ -f /etc/SuSE-release ];
   then echo "  Supported Distribution found"
-       echo -e "  System is running SuSE Linux\n"
+       echo "  System is running SuSE Linux"
        DISTRO=SUSE;
 elif [ -f /etc/fedora-release ];
   then echo "  Supported Distribution found"
-       echo -e "  System is running Fedora Linux\n"
+       echo "  System is running Fedora Linux"
        DISTRO=FEDORA;
 elif [ -f /etc/redhat-release ];
   then echo "  Supported Distribution found"
-       echo -e "  System is running Red Hat Linux\n"
+       echo "  System is running Red Hat Linux"
        DISTRO=REDHAT;
-else echo -e "  failed...........\nThis script works best on Debian, Red Hat and SuSE Linux!\nLet's try it nevertheless....\n"
+else echo -e "  failed...........\nThis script works best on Debian, Red Hat, Fedora and SuSE Linux!\nLet's try it nevertheless....\nIf some program files cannot be found adjust the respective path in line 98\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"
+  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"
 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"
+  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"
 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"
+  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"
 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"
+  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"
 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"
+  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"
 fi
 
 # Check existence of necessary files
-echo "Checking for chroot..." 
+echo "Checking for which... "
+if ( test -f /usr/bin/which ) || ( test -f /bin/which ) || ( test -f /sbin/which ) || ( test -f /usr/sbin/which );
+  then echo "  OK";
+  else echo "  failed
+
+Please install which-binary!
+" >&2
+exit 1
+fi
+
+echo "Checking for chroot..."
 if [ `which chroot` ];
   then echo "  OK";
   else echo "  failed
 
+chroot not found!
 Please install chroot-package/binary!
-"
+" >&2
 exit 1
 fi
 
-echo "Checking for sudo..." 
+echo "Checking for sudo..."
 if [ `which sudo` ]; then
+  echo "  OK";
+else
+  echo "  failed
+
+sudo not found!
+Please install sudo-package/binary!
+" >&2
+exit 1
+fi
+
+echo "Checking for dirname..."
+if [ `which dirname` ]; then
+  echo "  OK";
+else
+  echo "  failed
+
+dirname not found!
+Please install dirname-binary (to be found eg in the package coreutils)!
+" >&2
+exit 1
+fi
+
+echo "Checking for awk..."
+if [ `which awk` ]; then
   echo "  OK
 ";
-else 
+else
   echo "  failed
 
-Please install sudo-package/binary!
-"
+awk not found!
+Please install (g)awk-package/binary!
+" >&2
 exit 1
 fi
 
+# get location of sftp-server binary from /etc/ssh/sshd_config
+# check for existence of /etc/ssh/sshd_config and for
+# (uncommented) line with sftp-server filename. If neither exists, just skip
+# this step and continue without sftp-server
+#
+if  (test ! -f /etc/ssh/sshd_config >/dev/null 2>&1); then
+  echo "
+File /etc/ssh/sshd_config not found.
+Not checking for path to sftp-server.
+  ";
+else
+  if !(grep -v "^#" /etc/ssh/sshd_config | grep -i sftp-server >/dev/null 2&1); then
+    echo "Obviously no sftp-server is running on this system.
+";
+  else SFTP_SERVER=$(grep -v "^#" /etc/ssh/sshd_config | grep -i sftp-server | awk  '{ print $3}')
+  fi
+fi
+
+#if !(grep -v "^#" /etc/ssh/sshd_config | grep -i sftp-server /etc/ssh/sshd_config | awk  '{ print $3}' >/dev/null 2&1); then
+APPS="$APPS $SFTP_SERVER"
+
 # Get accountname to create
 CHROOT_USERNAME=$1
 
@@ -137,13 +196,45 @@ else
 fi
 
 # Exit if user already exists
-id $CHROOT_USERNAME > /dev/null 2>&1 && { echo "User exists."; echo "Exiting."; exit 1; }
+#id $CHROOT_USERNAME > /dev/null 2>&1 && { echo "User exists."; echo "Exiting."; exit 1; }
+if ( id $CHROOT_USERNAME > /dev/null 2>&1 ) ; then {
+echo "
+-----------------------------
+User $CHROOT_USERNAME exists.
+
+Are you sure you want to modify the users home directory and lock him into the
+chroot directory?
+Are you REALLY sure?
+Say only yes if you absolutely know what you are doing!
+(yes/no) -> "
+  read MODIFYUSER
+  if [ "$MODIFYUSER" != "yes" ]; then
+    echo "
+Not entered yes. Exiting...." >&2
+    exit 1
+  fi
+}
+else
+  CREATEUSER="yes"
+fi
 
 # 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."
+  echo "
+-----------------------------
+The file $SHELL exists.
+Probably it was created by this script.
+
+Are you sure you want to overwrite it?
+(you want to say yes for example if you are running the script for the second
+time when adding more than one account to the jail)
+(yes/no) -> "
+read OVERWRITE
+if [ "$OVERWRITE" != "yes" ]; then
+  echo "
+Not entered yes. Exiting...." >&2
   exit 1
+fi
 else
   echo "Creating $SHELL"
   echo '#!/bin/sh' > $SHELL
@@ -152,14 +243,14 @@ else
 fi
 
 # make common jail for everybody if inexistent
-if [ ! -d $JAILPATH ] ; then
-  mkdir -p $JAILPATH
-  echo "Creating $JAILPATH"
+if [ ! -d ${JAILPATH} ] ; then
+  mkdir -p ${JAILPATH}
+  echo "Creating ${JAILPATH}"
 fi
-cd $JAILPATH
+cd ${JAILPATH}
 
 # Create directories in jail that do not exist yet
-JAILDIRS="dev etc etc/pam.d bin home sbin usr usr/bin"
+JAILDIRS="dev etc etc/pam.d bin home sbin usr usr/bin usr/lib"
 for directory in $JAILDIRS ; do
   if [ ! -d "$JAILPATH/$directory" ] ; then
     mkdir $JAILPATH/"$directory"
@@ -181,27 +272,49 @@ echo
 [ -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 
+[ -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
+# Modify sudo config 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
+SUDOERS="$CHROOT_USERNAME       ALL=NOPASSWD: $(which chroot), /bin/su - $CHROOT_USERNAME"
+if [ -d /etc/sudoers.d ]; then
+  echo "Installing sudoers configuration file /etc/sudoers.d/jail-$CHROOT_USERNAME"
+  echo "$SUDOERS" > "/etc/sudoers.d/jail-$CHROOT_USERNAME"
+  chmod 0440 "/etc/sudoers.d/jail-$CHROOT_USERNAME"
+else
+  echo "Modifying /etc/sudoers"
+  echo "$SUDOERS" >> /etc/sudoers
+fi
 
 # 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/*
+if [ "$CREATEUSER" != "yes" ] ; then echo "
+Not creating new User account
+Modifying User \"$CHROOT_USERNAME\"
+Copying files in $CHROOT_USERNAME's \$HOME to \"$HOMEDIR\"
+"
+usermod -d "$HOMEDIR" -m -s "$SHELL" $CHROOT_USERNAME && chmod 700 "$HOMEDIR"
+fi
+
+if [ "$CREATEUSER" = "yes" ] ; then {
 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
+if !(passwd $CHROOT_USERNAME);
+  then echo "Passwords are probably not the same, try again." >&2
+  exit 1;
+fi
 echo
+}
+fi
 
 # Create /usr/bin/groups in the jail
 echo "#!/bin/bash" > usr/bin/groups
@@ -213,30 +326,31 @@ chmod 755 usr/bin/groups
 # 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
+ grep /etc/passwd -e "^root" > ${JAILPATH}/etc/passwd
 fi
 if [ ! -f etc/group ] ; then
- grep /etc/group -e "^root" > etc/group
+ grep /etc/group -e "^root" > ${JAILPATH}/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
+ grep /etc/group -e "^users" >> ${JAILPATH}/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 
+# 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
+     -e "s#$SHELL#/bin/bash#"  >> ${JAILPATH}/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
+grep -e "^$CHROOT_USERNAME:" /etc/group >> ${JAILPATH}/etc/group
 
 # write the user's line from /etc/shadow to /home/jail/etc/shadow
-grep -e "^$CHROOT_USERNAME:" /etc/shadow >> etc/shadow
+grep -e "^$CHROOT_USERNAME:" /etc/shadow >> ${JAILPATH}/etc/shadow
+chmod 600 ${JAILPATH}/etc/shadow
 
 # endif for =! update
 fi
@@ -245,25 +359,25 @@ fi
 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 
+# 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 
+# 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 
+if [ -x ${HOME}/ldlist ]; then
    mv ${HOME}/ldlist ${HOME}/ldlist.bak
 fi
-if [ -x ${HOME}/lddlist2 ]; then 
+if [ -x ${HOME}/lddlist2 ]; then
    mv ${HOME}/lddlist2 ${HOME}/lddlist2.bak
 fi
 
@@ -292,13 +406,13 @@ done
 if [ -e ${HOME}/ldlist2 ]; then
     rm ${HOME}/ldlist2
 fi
-for libs in `cat /root/ldlist`; do
+for libs in `cat ${HOME}/ldlist`; do
    frst_char="`echo $libs | cut -c1`"
    if [ "$frst_char" = "/" ]; then
-     echo "$libs" >> /root/ldlist2
+     echo "$libs" >> ${HOME}/ldlist2
    fi
 done
-for lib in `cat /root/ldlist2`; do
+for lib in `cat ${HOME}/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
@@ -314,12 +428,18 @@ done
 /bin/rm -f ${HOME}/ldlist
 /bin/rm -f ${HOME}/ldlist2
 
-# Necessary files that are not listed by ldd
+# Necessary files that are not listed by ldd.
+#
+# There might be errors because of files that do not exist but in the end it
+# may work nevertheless (I added new file names at the end without deleting old
+# ones for reasons of backward compatibility).
+# So please test ssh/scp before reporting a bug.
 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/libnss_compat.so.2 /lib/libnsl.so.1 /lib/libnss_files.so.2 /lib/ld-linux.so.2 /lib/ld-ldb.so.3 /lib/ld-lsb.so.3 /lib/libnss_dns.so.2 /lib/libxcrypt.so.1 ${JAILPATH}/lib/
   cp /lib/*.* ${JAILPATH}/lib/
+  cp /usr/lib/libcrack.so.2 ${JAILPATH}/usr/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
@@ -335,7 +455,7 @@ fi
 # needed library just copy all of them)
 #
 #cp /lib/*.* ${JAILPATH}/lib/
-#cp /lib/lib64/*.* ${JAILPATH}/lib/lib64/ 
+#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"
@@ -351,7 +471,11 @@ cp /etc/login.defs ${JAILPATH}/etc/
 
 if [ -f /etc/DIR_COLORS ] ; then
   cp /etc/DIR_COLORS ${JAILPATH}/etc/
-fi 
+fi
+
+# Don't give more permissions than necessary
+chown root.root ${JAILPATH}/bin/su
+chmod 700 ${JAILPATH}/bin/su
 
 exit