#!/usr/bin/env bash ## Bash strict mode #################################### set -o errexit # abort on nonzero exitstatus set -o pipefail # don't hide errors within pipes set -o nounset # abort on unbound variable ## Bash color ########################################## # Set colors RED='\033[0;31m' GREEN='\033[00;32m' YELLOW='\033[00;33m' LRED='\033[01;31m' LBLUE='\033[01;34m' NC='\033[0m' # No Color ## Logs ################################################ readonly SCRIPTNAME="$(basename "$0")" success() { echo -e "${GREEN}[SUCCESS] $* ${NC}" | logger --tag "${SCRIPTNAME}" --stderr; } info() { echo -e "${LBLUE}[INFO] $* ${NC}" | logger --tag "${SCRIPTNAME}" --stderr ; } warning() { echo -e "${YELLOW}[WARNING] $* ${NC}" | logger --tag "${SCRIPTNAME}" --stderr ; } error() { echo -e "${LRED}[ERROR] $* ${NC}" | logger --tag "${SCRIPTNAME}" --stderr ; } fatal() { echo -e "${RED}[FATAL] $* ${NC}" | logger --tag "${SCRIPTNAME}" --stderr ; exit 1 ; } ######################################################## ## Define variables ################################### LOCK="/var/lock/${SCRIPTNAME}.lock" CHROOTPATH="/var/chroot" ZONEINFO="/usr/share/zoneinfo" LISTCHROOTFILE="/var/chroot/list" function _USAGE { cat << EOF Usage : ${SCRIPTNAME} [OPTIONS] Options : --install Install chroot on ${WEBCHROOT} --update Update configuration and binary on chroot --configure Configure chroot for specific path --help Display this help EOF exit 1 } function _GET_OPTS { _SHORT_OPTS="i:u:c:h"; _LONG_OPTS="install,update,configure,help"; _OPTS=$(getopt \ -o "${_SHORT_OPTS}" \ -l "${_LONG_OPTS}" \ -n "${SCRIPTNAME}" -- "${@}") if [ "${?}" -ne 0 ] then _USAGE fi eval set -- "${_OPTS}" while true ; do case "${1}" in --install) _INSTALL shift ;; --update) _UPDATE shift ;; --configure) _CONFIGURE "${3}" shift 2 ;; --help) _USAGE shift ;; *) echo "getopt Internal error!" ; exit 1 ;; esac done } function cpDep { if [[ -f "${CHROOTPATH}/${1}" ]] then error "$1 already exist in chroot" return 1 fi if [[ ! -d "${CHROOTPATH}/$(dirname "${1}")" ]] then mkdir -p "${CHROOTPATH}/$(dirname "${1}")" fi cp "${1}" "${CHROOTPATH}/${1}" # Linked libraries for DEP in $(ldd "${1}" | grep '=>' |cut -d'>' -f2 | awk '{print $1}') do mkdir -p "${CHROOTPATH}/$(dirname "${DEP}")" cp "${DEP}" "${CHROOTPATH}/${DEP}" done # And lib64 for DEP in $(ldd bin/bash |grep lib64 | awk '{print $1}') do if [[ ! -d "${CHROOTPATH}/$(dirname "${DEP}")" ]] then mkdir -p "${CHROOTPATH}/$(dirname "${DEP}")" fi cp "${DEP}" "${CHROOTPATH}/${DEP}" done } function _TIMEZONE { info "Clone Timezone" if [[ ! -d "${CHROOTPATH}/${ZONEINFO}" ]] then mkdir -p "${CHROOTPATH}${ZONEINFO}" rsync -azP "${ZONEINFO}/Europe" "${CHROOTPATH}${ZONEINFO}" rsync -azP "${ZONEINFO}/UTC" "${CHROOTPATH}${ZONEINFO}" rsync -azP "${ZONEINFO}/Etc" "${CHROOTPATH}${ZONEINFO}" else warning "Timezone already exist" fi } function _ETC { info "Copy /etc" if [[ ! -d "${CHROOTPATH}/etc" ]] then mkdir "${CHROOTPATH}/etc" for conf in {ld.so.cache,resolv.conf,nsswitch.conf,passwd,group,hosts,networks,protocols,services,localtime} do cp "/etc/${conf}" "${CHROOTPATH}/etc/" done fi info "Create ssl" mkdir -p "${CHROOTPATH}/etc/ssl" cp -rf /etc/ssl/certs ${CHROOTPATH}/etc/ssl } function _DEV { info "Copy /dev" if [[ ! -d "${CHROOTPATH}/dev" ]] then mkdir ${CHROOTPATH}/dev mknod -m 666 "${CHROOTPATH}/dev/null" c 1 3 mknod -m 666 "${CHROOTPATH}/dev/zero" c 1 5 mknod -m 444 "${CHROOTPATH}/dev/random" c 1 8 mknod -m 444 "${CHROOTPATH}/dev/urandom" c 1 9 fi } function _LIB { for lib_name in {libnss,libnss_dns,libxml,libcurl,libsqlite3} do info "Copy ${lib_name}" for lib in $(whereis ${lib_name}) do if echo "${lib}" | grep -q "/usr/lib" then mkdir -p "${CHROOTPATH}/$(dirname ${lib})" cp -f "${lib}" "${CHROOTPATH}/$(dirname ${lib})" fi done done for lib in $(ls /lib/x86_64-linux-gnu/*dns.* /lib/x86_64-linux-gnu/*dns-*) do info "Copy ${lib}" mkdir -p "${CHROOTPATH}/$(dirname ${lib})" cp -f "${lib}" "${CHROOTPATH}/$(dirname ${lib})" done } function _BIN { for binary in {/bin/bash,/bin/ls,/usr/bin/dig} do info "Copy ${binary} and dependencies" cpDep "${binary}" done } function _INSTALL { _TIMEZONE _ETC _DEV _LIB _BIN } function _UPGRADE { _LIBNSS _BIN } function _CONFIGURE { WEBCHROOT=${1} info "Create /etc and /tmp" mkdir -p "${WEBCHROOT}/etc" mkdir -p "${WEBCHROOT}/tmp" chmod 777 "${WEBCHROOT}/tmp" info "Link system folder" for chrooter in {dev,bin,lib/x86_64-linux-gnu,lib64,usr/bin,usr/lib/x86_64-linux-gnu/,usr/share/zoneinfo/Etc,usr/share/zoneinfo/Europe} do mkdir -p "${WEBCHROOT}/${chrooter}" for binary in $(ls "${CHROOTPATH}/${chrooter}") do #info "hardlink ${chrooter}/${binary}" ln "${CHROOTPATH}/${chrooter}/${binary}" "${WEBCHROOT}/${chrooter}/${binary}" done done info "hardlink libnss" ln "${CHROOTPATH}/usr/share/zoneinfo/UTC" "${WEBCHROOT}/usr/share/zoneinfo/UTC" info "hardlink some config" for chrooter in {ld.so.cache,localtime,networks,nsswitch.conf,protocols,resolv.conf,services} do info "hardlink ${chrooter}" ln "${CHROOTPATH}/etc/${chrooter}" "${WEBCHROOT}/etc/${chrooter}" done info "Copy some configurations" for chrooter in {group,hosts,passwd} do info "Copy ${chrooter}" cp "${CHROOTPATH}/etc/${chrooter}" "${WEBCHROOT}/etc/${chrooter}" done info "Create certs path" mkdir -p "${WEBCHROOT}/etc/ssl/certs" info "Mount RO certs path" mount --bind -o ro /etc/ssl/certs "${WEBCHROOT}/etc/ssl/certs" info "Create session folder" mkdir -p ${WEBCHROOT}/var/lib/php/sessions info "Chmod 755 all var" chmod 755 "${WEBCHROOT}/var/" info "Add sticky bit" chmod 1757 "${WEBCHROOT}/var/lib/php/sessions" echo ${WEBCHROOT} >> ${LISTCHROOTFILE} } function _CLEAN { rm -f "${LOCK}" } if [[ ! -f "${LOCK}" ]] then trap _CLEAN EXIT touch "${LOCK}" _GET_OPTS "${@}" _CLEAN success "Account was successfull chrooted" else fatal "Lock already exist" fi