home *** CD-ROM | disk | FTP | other *** search
- #!/bin/sh
-
- ### This script can help create chrooted environment.
- ### It was tested ONLY WITH APACHE (with mod_ssl) AND PERL,
- ### but at the end of
- ### it you will find big section "apllication specific".
- ### So if you will chroot something else (proftpd, ldap,
- ### or what you want) you can add aplication specific
- ### part to the end of this script (if needed).
- ### In example apache needs /etc/mime.types to be copied
- ### but this is NOT a part of apache package. So at the
- ### end script just tests if package name is apache, and copies
- ### this file to new chroot.
- ###
- ### It works ONLY WITH DEBIAN (because of package system),
- ### and was tested ONLY WITH DEBIAN 3.0 (because I have no other :-).
- ### Use it on your own risk.
- ###
- ### What it does. It takes two arguments:
- ### debian package name;
- ### chroot directory.
- ### It makes some tests and asks you about configuration.
- ### Then it copies some files, libraries and devices to
- ### new chroot (you can add or remove if needed [lines 302-309]).
- ### When package files are copied, script looks what libraries are
- ### needed. After libraries are copied it goes to application
- ### specific section. For apache it can create startup script
- ### which you may copy to /etc/init.d/apache *(real path, not
- ### a chroot)*, so your chrooted apache can start at startup.
- ###
- ### USAGE NOTES
- ###
- ### Usage: this_script package_name chroot_dir
- ### I.e. if you need chrooted apache, do:
- ### dpkg -l | grep apache
- ### and look what packages you need.
- ### I took apache, apache-common, libapache-mod-ssl.
- ### (./mkchroot apache /var/chroot/apache
- ### ./mkchroot apache-common /var/chroot/apache
- ### ./mkchroot libapache-mod-ssl /var/chroot/apache )
- ###
- ### So you MUST run this scipt for EACH package once.
- ### For perl I took perl-base and perl.
- ###
- ### UPGRADES OF CHROOTED APPLICATIONS
- ###
- ### You can upgrade (apt-get upgrade package) package you need
- ### BUT BE SURE, YOU HAVE EXACT WORKING CONFIGURATION OUTSIDE
- ### THE JAIL. In other case, configuration, ssl-keys, etc. will
- ### be OVERWRITTEN!
- ###
- ### LICENCE. You can use, modify, distribute this script,
- ### but leave my name in authors section.
- ###
- ###
- ### Written by Martynas Domarkas (OTPABA) md@hansa.lt 2003 01 05.
- ###
- ### I DO NOT SUPPORT ANY SOFTWARE, so I'm not sure I'll answer
- ### your questions :-)
- ###
- ### Last note: this script does NOT check any package dependencies.
- ### The point is, that i.e. if you want a chrooted apache, debian package
- ### depends on perl. But if you find perl buggy or just hate it (like I do)
- ### you will not use cgi's written in perl, and no mod_perl of course.
- ### Then you need no perl package in your chroot! ;-)
-
- ### 2003 09 19 changed function file_list_for_tar(). There was a bug when copying
- ### targets of symlinks.
- ### Reported by Marc Lubarsky.
-
- ### 2003 09 19 added copying of /etc/hosts.
-
-
-
-
- CHRPACK=$1
- CHROOTD=$2
- clear
- ### Function "Print how to use" ###
- usage() {
- echo "
- Usage:
- $0 package_name chroot_dir
- "
- }
- #################################
-
- ### Check for command invocation syntax ###
- if [ "$CHRPACK" == "" ] || [ "$CHROOTD" == "" ]; then
- usage # Function from above
- exit 1
- fi
- ###########################################
-
-
- ### Ask some stupid questions, but it's better than README ;-)) ###
- echo "
- 1) Did you read what is written in head of this file?
-
- 2) Package you are chrooting is installed using debian tools
- and *CONFIGURED* ?
- (if you upgrade your system and try mkchroot
- again without actual configuration you currently have in chroot
- YOU WILL LOSE YOUR CONFIGURATION!)
-
- 3) Is this machine running Linux Debian 3.0 ?
- 4) Do you know what does it mean \"chroot\" at all?
- 5) Do you have dpkg, gawk (awk), tar, file, grep, egrep, ldd, mkdir in your PATH?
-
- If all 5 answers was \"YES!!!!\", then press ENTER. If not, better press ctrl-C
- and read beggining of this script.
- "
- read junk
- ##############################################################
-
- ### Check for user ###
- if [ `id -u` -ne 0 ]; then
- echo "
- You are not root.
- It is possible, that you will not be able access some files."
- echo -n "
- Do you want to continue? [y/n] : "
- read ANS
- if [ "$ANS" != "y" ]; then
- echo "OK, exiting..."
- exit 0
- fi
- fi
- #####################
-
-
- #################### FUNCTIONS ####################
-
- ### Function for checking of command existence ###
- ### It will be used to be sure that we can continue running this script ###
- cmd_exist() {
- which $1 > /dev/null
- if [ $? -ne 0 ]; then
- echo "Command \"$1\" not found"
- echo "Exiting..."
- exit 1
- fi
- }
-
- ### Function for getting needed libraries for package ###
- ### It uses list of files given by "dpkg -L $PACKAGE" looks for executables and prints out
- ### file names of needed libraries
- get_libs_for_pack() {
- dpkg -L $CHRPACK | while read GLFP
- do
- if [ ! -d $GLFP ]; then
- file $GLFP|egrep "(ELF.*executable|ELF.*shared obj)" > /dev/null
- if [ $? -eq 0 ]; then
- ldd $GLFP | $AWK '{ print $3 }'; fi; fi; done | sort -u
- }
- #########################################################
-
- ### Function for getting needed libraries for file
- ### (same as above but this takes as argument just one file
- get_libs_for_file() {
- file $1 | egrep "(ELF.*executable|ELF.*shared obj)" > /dev/null
- if [ $? -eq 0 ]; then
- ldd $1 | $AWK '{ print $3 }'; fi
- }
- ######################################################
-
- ### Function for checking if library does NOT exist in chroot ###
- check_lib_for_exsist() {
- while read CLFN
- do
- if [ ! -e $CHROOTD/$CLFN ]; then
- echo $CLFN
- fi
- done
- }
- #################################################################
-
- ### Function to prepare list of files for tar ###
- ### It checks for symlinks, targets and it's output is one single space separated line ###
-
- file_list_for_tar() {
- while read FLFT
- do
-
- # Check for accidental newline
- if [ ! -z $FLFT ]; then
-
- # You will ask me why I cycle again. It is because I like "break" more than "else" :-)
- file $FLFT | while read LO
- do
-
- # Check if the file exist
- if [ ! -f "$FLFT" ]; then
- break
- fi
-
- # Output filename to stdout (other functions will read this)
- echo -n "$FLFT "
-
- # Is it a symlink?
- echo $LO | grep "sym.*link" > /dev/null
- if [ $? -eq 0 ]; then
-
- # Symlinks often are made with realative path. So we need know WHERE the symlink is.
- prefdir=`dirname $FLFT`
- TG=`echo $LO | $AWK '{ print $NF }'`
- # Is the path absolute (absolute paths allways begisn with a "/")
- echo "$TG" | grep "^/" > /dev/null
- if [ $? -eq 0 ]; then
- TGF=$TG
- else
- # Path to target was realative - adding directory prefix.
- TGF=$prefdir/$TG
- fi
-
- # Shit happens... :-)
- if [ ! -f "$FLFT" ]; then
- break
- fi
-
- echo -n "$TGF "
- fi
- done
-
- fi
- done
- }
-
- ### Old one. Buggy.
- #file_list_for_tar() {
- #while read FLFT
- #do
- #file $FLFT | $AWK '{ gsub(/:$/, "", $1); print }' | while read LO
- # do
- # prefdir=`echo $LO | $AWK -F"/" '{ ORS=""; for(i=2; i<NF; i++) { print "/" $i } } END { print "/" }'`
- # echo $LO|grep "sym.*link" > /dev/null
- # if [ $? -eq 0 ]; then
- # echo $LO | $AWK '{ ORS=" "; print $1 }'
- # TG=`echo $LO | $AWK '{ print $NF }'`
- # TGF=`find "$prefdir" -name "$TG"`
- # echo -n "$TGF "
- # else
- # echo $LO | $AWK '{ ORS=" "; print $1 }'
- # fi
- # done
- #done
- #}
- ###################################################################################
-
- ### Function for copy given files to chroot ###
- cp_to_chroot() {
- read CTC
- if [ ! -z "$CTC" ]; then
- cd $CHROOTD
- tar cvf - $CTC | tar xf -
- fi
- }
- ##############################################
-
- ### Function to copy single commands (binaries) with libraries to chroot ###
- cp_cmd_to_chroot() {
- CMD=$1
- if [ ! -z "$CMD" ]; then
- if [ -f "$CMD" ]; then
- get_libs_for_file $CMD | check_lib_for_exsist | file_list_for_tar | cp_to_chroot
- if [ ! -f $CHROOTD/$CMD ]; then
- cd $CHROOTD
- tar cvf - "$CMD" | tar xf -
- fi
- else
- echo "$CMD does not exist"
- exit 1
- fi
- else
- echo "Error"
- exit 1
- fi
- }
-
- ############### END OF FUNCTIONS ####################
-
- ### OK lets begin! ###
-
- ### Looking for needed software ###
- ### GAWK: ###
- which gawk > /dev/null
- if [ $? -ne 0 ]; then
- which awk > /dev/null
- if [ $? -ne 0 ]; then
- echo "gawk or awk not found in your PATH"
- echo "Exiting..."
- exit 1
- else
- echo "Found awk instead of gawk. I'll try to use it..."
- AWK=`which awk`
- fi
- else
- #echo "gawk found. Excelent!"
- AWK=`which gawk`
- fi
-
- cmd_exist file
- cmd_exist ldd
- cmd_exist dpkg
- cmd_exist grep
- cmd_exist egrep
- cmd_exist mkdir
- cmd_exist tar
- cmd_exist dirname
-
- ### At this point we should be sure, that we found all software needed ###
-
- ### Looking for package beeing chrooted ###
- dpkg -L $CHRPACK > /dev/null 2>&1
- if [ $? -ne 0 ]; then
- echo "
- dpkg can not find package \"$CHRPACK\".
- If you mistyped command, start $0 again with correct arguments
- Be sure you installed it using usual Debian way (apt-get, dpkg -i, tasksel, dselect...)
- Exiting..."
- exit 1
- fi
- ###########################################
-
- ### Create new chroot or use an existing directory? ###
- if [ -e $CHROOTD ]; then
- if [ ! -d $CHROOTD ]; then
- echo "$CHROOTD exist and it is NOT a directory"
- echo "Exiting..."
- exit 1
- else
- echo -n "$CHROOTD exist. Should I use it? [y/n] : "
- read ANS
- if [ "$ANS" != "y" ]; then
- echo "Exiting..."
- exit 1
- fi
- fi
- else
- mkdir -p $CHROOTD
- fi
- ########################################################
-
-
- ### Minimal set of files so you can do 'chroot /your/dir' ###
- ### (ls, cat, tail, strace, less is also added for debuging) ###
-
- echo "
- Creating minimal chroot environment...
- "
- cp_cmd_to_chroot /bin/sh
- cp_cmd_to_chroot /bin/bash
- cp_cmd_to_chroot /bin/ls
- cp_cmd_to_chroot /bin/cat
- cp_cmd_to_chroot /usr/bin/strace
- cp_cmd_to_chroot /usr/bin/less
- cp_cmd_to_chroot /usr/bin/tail
-
- ### Little stupid hack. Without "libnss_files.so" apache can not read /etc/passwd for "User" directive
- ### but no binaries or modules ar linked with it...
- echo /lib/libnss_files.so.2 | check_lib_for_exsist | file_list_for_tar | cp_to_chroot
-
- ### Some directories and files that we will need ###
- mkdir -p $CHROOTD/var/run
- mkdir -p $CHROOTD/var/lock
- mkdir -p $CHROOTD/var/log
- mkdir -p $CHROOTD/proc
- mkdir -p $CHROOTD/dev
- mkdir -p $CHROOTD/etc
-
- cp -apR /dev/null $CHROOTD/dev
- cp -apR /dev/random $CHROOTD/dev
- cp -apR /dev/urandom $CHROOTD/dev
- cp -apR /dev/zero $CHROOTD/dev
- cp -ap /etc/hosts $CHROOTD/etc
-
- ############## END OF MINIMAL CHROOT ####################
-
- ### We also need an /etc/passwd and /etc/group ###
- ### At this moment we add user root to $CHROOTD/etc/passwd
- ### and group root to $CHROOTD/etc/group
- ### You will be asked later for application specific user and group
- if [ ! -f $CHROOTD/etc/passwd ]; then
- grep "^root:" /etc/passwd > $CHROOTD/etc/passwd
- else
- grep "^root:" $CHROOTD/etc/passwd > /dev/null
- if [ $? -ne 0 ]; then
- echo "No entry for user root found in your chrooted /etc/passwd"
- echo -n "Do you want me to add one? [y/n] : "
- read ANS
- if [ "$ANS" != "y" ]; then
- echo "OK, no root - no problems"
- else
- grep "^root:" /etc/passwd >> $CHROOTD/etc/passwd
- fi
- fi
- fi
-
- if [ ! -f $CHROOTD/etc/group ]; then
- grep "^root:" /etc/group > $CHROOTD/etc/group
- else
- grep "^root:" $CHROOTD/etc/group > /dev/null
- if [ $? -ne 0 ]; then
- echo "No entry for user root found in your chrooted /etc/group"
- echo -n "Do you want me to add one? [y/n] : "
- read ANS
- if [ "$ANS" != "y" ]; then
- echo "OK, no root - no problems"
- else
- grep "^root:" /etc/group >> $CHROOTD/etc/group
- fi
- fi
- fi
- ##################################################
-
- ### We have passwd and group files. Now we need copy some system users and groups to jail ###
- while [ true ]
- do
- sleep 1
- clear
-
- echo "
- You will need a part of /etc/passwd for your software to run.
- In most cases apache run under www-data, bind under bind. But I have no idea
- what is your setup. So, now you can enter username you need in chroot and
- press ENTER.
-
- If you DO NOT need any user enter NoMore.
- "
- echo -n "User to add to $CHROOTD/etc/passwd : "
-
- read USRN
- if [ ! -z "$USRN" ]; then
- if [ "$USRN" != "NoMore" ]; then
- grep "^$USRN:" /etc/passwd > /dev/null
- if [ $? -eq 0 ]; then
- grep "^$USRN:" $CHROOTD/etc/passwd 1>/dev/null 2>/dev/null
- if [ $? -ne 0 ]; then
- grep "^$USRN:" /etc/passwd >> $CHROOTD/etc/passwd
- echo ""
- echo -e "\tUser $USRN added"
- echo ""
- echo -e "\tPress ENTER to continue"
- read junk
- else
- echo ""
- echo -e "\t$USRN already is in your $CHROOTD/etc/passwd"
- echo ""
- echo -e "\tPress ENTER to continue"
- read junk
- fi
- else
- echo ""
- echo -e "\t$USRN does not exist in your system"
- echo ""
- echo -e "\tPress ENTER to continue"
- read junk
- fi
- else
- echo "OK... Continuing"
- break
- fi
- else
- echo -e "
- \tEnter an existing system user or NoMore if you wan't quit adding users to chroot"
- echo -e "
- \tPress ENTER to continue"
- read junk
- fi
- done
-
-
- while [ true ]
- do
- sleep 1
- clear
-
- echo "
- OK, for we have user file. Now repeat the same with groups.
-
- Now you can enter groupname you need in chroot and
- press ENTER.
-
- If you DO NOT need any group enter NoMore.
- "
- echo -n "Group to add to $CHROOTD/etc/group : "
-
- read GRPN
- if [ ! -z "$GRPN" ]; then
- if [ "$GRPN" != "NoMore" ]; then
- grep "^$GRPN:" /etc/group > /dev/null
- if [ $? -eq 0 ]; then
- grep "^$GRPN:" $CHROOTD/etc/group 1>/dev/null 2>/dev/null
- if [ $? -ne 0 ]; then
- grep "^$GRPN:" /etc/group >> $CHROOTD/etc/group
- echo ""
- echo -e "\tGroup $GRPN added"
- echo ""
- echo -e "\tPress ENTER to continue"
- read junk
- else
- echo ""
- echo -e "\t$GRPN already is in your $CHROOTD/etc/group"
- echo ""
- echo -e "\tPress ENTER to continue"
- read junk
- fi
- else
- echo ""
- echo -e "\t$GRPN does not exist in your system"
- echo ""
- echo -e "\tPress ENTER to continue"
- read junk
- fi
- else
- echo "OK... Continuing"
- break
- fi
- else
- echo -e "
- \tEnter an existing system group or NoMore if you wan't quit adding groups to chroot"
- echo -e "
- \tPress ENTER to continue"
- read junk
- fi
- done
-
- ##################################################################################
-
- ### Package files. Taken from dpkg -L $PACKAGE without doc's and manuals ###
- echo "
- Copying package files to $CHROOTD:
- "
- cd $CHROOTD
- LIST=`dpkg -L $CHRPACK | grep -v "share/[man|doc]" | while read F
- do
- if [ ! -d $F ]; then
- echo -n "$F "
- else
- if [ ! -d $CHROOTD/$F ]; then
- mkdir -p $CHROOTD/$F > /dev/null 2>&1
- fi
- fi
- done`
- tar cvf - $LIST| tar xf -
- #########################################
-
- echo "
- Copying libraries needed by $CHRPACK...
- "
- get_libs_for_pack | check_lib_for_exsist | file_list_for_tar | cp_to_chroot
-
-
- ### Package specific... APACHE ###
- if [ "$CHRPACK" = "apache" ]; then
- if [ ! -d $CHROOTD/etc/apache ]; then
- cd $CHROOTD
- tar cvf - /etc/apache | tar xf -
- else
- cp -apuRi /etc/apache/* $CHROOTD/etc/apache
- fi
-
- if [ ! -f $CHROOTD/etc/mime.types ]; then
- cp -ap /etc/mime.types $CHROOTD/etc
- fi
- echo "
- If you are running Debian 3.0, I can try provide startup script for you.
- It will be placed as /tmp/chrooted.apache.spartup.sh. You will need only
- chmod 750 /tmp/chrooted.apache.spartup.sh
- and
- /tmp/chrooted.apache.spartup.sh start
- "
- echo -n "Do you want try this script? [y/n] : "
- read ANS
- if [ "$ANS" = "y" ]; then
- STARTUPFILE=/tmp/chrooted.apache.spartup.sh
- rm $STARTUPFILE
- echo "#!/bin/bash" >> $STARTUPFILE
- echo "#" >> $STARTUPFILE
- echo "# apache Start the apache HTTP server." >> $STARTUPFILE
- echo "#" >> $STARTUPFILE
- echo "" >> $STARTUPFILE
- echo "CHRDIR=$CHROOTD" >> $STARTUPFILE
- echo "" >> $STARTUPFILE
- echo "NAME=apache" >> $STARTUPFILE
- echo "PATH=/bin:/usr/bin:/sbin:/usr/sbin" >> $STARTUPFILE
- echo "DAEMON=/usr/sbin/apache" >> $STARTUPFILE
- echo "SUEXEC=/usr/lib/apache/suexec" >> $STARTUPFILE
- echo "PIDFILE=/var/run/\$NAME.pid" >> $STARTUPFILE
- echo "CONF=/etc/apache/httpd.conf" >> $STARTUPFILE
- echo "APACHECTL=/usr/sbin/apachectl " >> $STARTUPFILE
- echo "" >> $STARTUPFILE
- echo "trap \"\" 1" >> $STARTUPFILE
- echo "export LANG=C" >> $STARTUPFILE
- echo "export PATH" >> $STARTUPFILE
- echo "" >> $STARTUPFILE
- echo "test -f \$DAEMON || exit 0" >> $STARTUPFILE
- echo "test -f \$APACHECTL || exit 0" >> $STARTUPFILE
- echo "" >> $STARTUPFILE
- echo "# ensure we don't leak environment vars into apachectl" >> $STARTUPFILE
- echo "APACHECTL=\"env -i LANG=\${LANG} PATH=\${PATH} \$APACHECTL\"" >> $STARTUPFILE
- echo "" >> $STARTUPFILE
- echo "if egrep -q -i \"^[[:space:]]*ServerType[[:space:]]+inet\" \$CONF" >> $STARTUPFILE
- echo "then" >> $STARTUPFILE
- echo " exit 0" >> $STARTUPFILE
- echo "fi" >> $STARTUPFILE
- echo "" >> $STARTUPFILE
- echo "case \"\$1\" in" >> $STARTUPFILE
- echo " start)" >> $STARTUPFILE
- echo " echo -n \"Starting web server: \$NAME\"" >> $STARTUPFILE
- echo " mount -t proc proc $CHROOTD/proc" >> $STARTUPFILE
- echo " start-stop-daemon --start --pidfile \$PIDFILE --exec \$DAEMON --chroot \$CHRDIR" >> $STARTUPFILE
- echo " ;;" >> $STARTUPFILE
- echo "" >> $STARTUPFILE
- echo " stop)" >> $STARTUPFILE
- echo " echo -n \"Stopping web server: \$NAME\"" >> $STARTUPFILE
- echo " start-stop-daemon --stop --pidfile \$CHRDIR/\$PIDFILE --oknodo" >> $STARTUPFILE
- echo " umount $CHROOTD/proc" >> $STARTUPFILE
- echo " ;;" >> $STARTUPFILE
- echo "" >> $STARTUPFILE
- echo " reload)" >> $STARTUPFILE
- echo " echo -n \"Reloading \$NAME configuration\"" >> $STARTUPFILE
- echo " start-stop-daemon --stop --pidfile \$CHRDIR/\$PIDFILE --signal USR1 --exec \$DAEMON --chroot \$CHRDIR" >> $STARTUPFILE
- echo " ;;" >> $STARTUPFILE
- echo "" >> $STARTUPFILE
- echo " reload-modules)" >> $STARTUPFILE
- echo " echo -n \"Reloading \$NAME modules\"" >> $STARTUPFILE
- echo " start-stop-daemon --stop --pidfile \$CHRDIR/\$PIDFILE --oknodo --retry 30" >> $STARTUPFILE
- echo " start-stop-daemon --start --pidfile \$PIDFILE --exec \$DAEMON --chroot \$CHRDIR" >> $STARTUPFILE
- echo " ;;" >> $STARTUPFILE
- echo "" >> $STARTUPFILE
- echo " restart)" >> $STARTUPFILE
- echo " \$0 reload-modules" >> $STARTUPFILE
- echo " exit \$?" >> $STARTUPFILE
- echo " ;;" >> $STARTUPFILE
- echo "" >> $STARTUPFILE
- echo " force-reload)" >> $STARTUPFILE
- echo " \$0 reload-modules" >> $STARTUPFILE
- echo " exit \$?" >> $STARTUPFILE
- echo " ;;" >> $STARTUPFILE
- echo "" >> $STARTUPFILE
- echo " *)" >> $STARTUPFILE
- echo " echo \"Usage: /etc/init.d/\$NAME {start|stop|reload|reload-modules|force-reload|restart}\"" >> $STARTUPFILE
- echo " exit 1" >> $STARTUPFILE
- echo " ;;" >> $STARTUPFILE
- echo "esac" >> $STARTUPFILE
- echo "" >> $STARTUPFILE
- echo "if [ \$? == 0 ]; then" >> $STARTUPFILE
- echo " echo ." >> $STARTUPFILE
- echo " exit 0" >> $STARTUPFILE
- echo "else" >> $STARTUPFILE
- echo " echo failed" >> $STARTUPFILE
- echo " exit 1" >> $STARTUPFILE
- echo "fi" >> $STARTUPFILE
- fi
- fi
-
-