#!/bin/bash # # Script to control the bind-chroot ISC BIND named(8) server runtime environment. # # Usage: # [ -e | --enable ] [ -d | --disable ] | [ -s --sync ] # # -e | --enable: enable the bind-chroot environment # -d | --disable: disable the bind-chroot environment # -s | --sync: sync files between the bind chroot and / environments, # so they are correct for the current state of the bind-chroot # (enabled / disabled) # $BIND_CHROOT_PREFIX, default /var/named/chroot, is the location of the chroot. # $BIND_DIR, default /var/named, is the default un-chrooted bind directory. # # Copyright(C) 2006 Jason Vas Dias , Red Hat, Inc. # # This software is provided under the terms of the GNU # General Public License (GPL), as published at: # http://www.gnu.org/licenses/gpl.html . # # BIND_CHROOT_PREFIX=${BIND_CHROOT_PREFIX:-@BIND_CHROOT_PREFIX@} if [ -e /etc/sysconfig/named ]; then BIND_CHROOT_PREFIX=`grep "ROOTDIR" /etc/sysconfig/named |grep \"` if [ `expr match "$BIND_CHROOT_PREFIX" '#'` -lt `expr match "$BIND_CHROOT_PREFIX" '"'` ]; then BIND_CHROOT_PREFIX=${BIND_CHROOT_PREFIX#*\"} BIND_CHROOT_PREFIX=${BIND_CHROOT_PREFIX%#*} BIND_CHROOT_PREFIX=${BIND_CHROOT_PREFIX%\"*} fi fi BIND_DIR=${BIND_DIR:-@BIND_DIR@} function usage() { echo 'Usage: -e | --enable: enable the bind-chroot environment -d | --disable: disable the bind-chroot environment -s | --sync: sync files between the bind chroot and / environments, so they are correct for the current state of the bind-chroot (enabled / disabled) $BIND_CHROOT_PREFIX, default /var/named/chroot, is the location of the chroot. $BIND_DIR, default /var/named, is the default un-chrooted bind directory. '; } function rootdir() { . /etc/sysconfig/named if [ -n "$ROOTDIR" ]; then BIND_CHROOT_PREFIX="$ROOTDIR"; BIND_CHROOT_PREFIX=`echo $BIND_CHROOT_PREFIX | sed 's#//*#/#g;s#/$##'`; if [ -L "$BIND_CHROOT_PREFIX" ]; then BIND_CHROOT_PREFIX=`/usr/bin/readlink "$BIND_CHROOT_PREFIX"`; fi return 0; fi; return 1; } function selinux_enabled() { while read d mp fs rest; do if [ "$fs" = "selinuxfs" ]; then return 0; fi; done < /proc/mounts return 1; } function check_dirs() { if [ -z "$BIND_CHROOT_PREFIX" ]; then rootdir; if [ -z "$BIND_CHROOT_PREFIX" ]; then usage; exit 1; fi; fi BIND_DIR=`echo $BIND_DIR | sed 's#//*#/#g;s#/$##'`; if [ -L "$BIND_DIR" ]; then BIND_DIR=`/usr/bin/readlink "$BIND_DIR"`; fi BIND_CHROOT_PREFIX=`echo $BIND_CHROOT_PREFIX | sed 's#//*#/#g;s#/$##'`; if [ -L "$BIND_CHROOT_PREFIX" ]; then BIND_CHROOT_PREFIX=`/usr/bin/readlink "$BIND_CHROOT_PREFIX"`; fi if [ -e /etc/sysconfig/named ]; then /bin/chown root:named /etc/sysconfig/named; /bin/chmod 0640 /etc/sysconfig/named; fi /bin/mkdir -p ${BIND_DIR}/{slaves,data}; /bin/chown --preserve-root root:named ${BIND_DIR}; /bin/chown --preserve-root named:named ${BIND_DIR}/{slaves,data}; /bin/chmod --preserve-root 750 ${BIND_DIR} /bin/chmod --preserve-root 770 ${BIND_DIR}/{slaves,data}; mkdir -p ${BIND_CHROOT_PREFIX}/{etc,dev,var/{run/named,named/{slaves,data}}}; /bin/chown --preserve-root root:named ${BIND_CHROOT_PREFIX}/{etc,dev,var/{run,named/}}; /bin/chown --preserve-root root:named ${BIND_CHROOT_PREFIX}/var; /bin/chmod --preserve-root 750 ${BIND_CHROOT_PREFIX}/{,etc,dev,var,var/{run,named/}}; /bin/chown --preserve-root named:named ${BIND_CHROOT_PREFIX}/var/{run/named,named/{data,slaves}}; /bin/chmod --preserve-root 770 ${BIND_CHROOT_PREFIX}/var/{run/named,named/{slaves,data}}; [ ! -e "${BIND_CHROOT_PREFIX}/dev/random" ] && /bin/mknod "${BIND_CHROOT_PREFIX}/dev/random" c 1 8 [ ! -e "${BIND_CHROOT_PREFIX}/dev/zero" ] && /bin/mknod "${BIND_CHROOT_PREFIX}/dev/zero" c 1 5 [ ! -e "${BIND_CHROOT_PREFIX}/dev/null" ] && /bin/mknod "${BIND_CHROOT_PREFIX}/dev/null" c 1 3 [ ! -e "${BIND_CHROOT_PREFIX}/etc/localtime" ] && [ -e /etc/localtime ] && /bin/cp -fp /etc/localtime "${BIND_CHROOT_PREFIX}/etc/localtime"; /bin/chown --preserve-root root:named "${BIND_CHROOT_PREFIX}"/dev/{random,null,zero}; /bin/chmod --preserve-root 660 "${BIND_CHROOT_PREFIX}"/dev/{random,null,zero}; if selinux_enabled && [ -x /usr/bin/chcon ]; then for dev in random zero null; do /usr/bin/chcon --reference=/dev/$dev ${BIND_CHROOT_PREFIX}/dev/$dev; done fi; } check_dirs; function replace_with_link() { # replaces $dst second arg file with link to $src first arg file if [ $# -lt 2 ]; then return 1; fi; src=$1 dst=$2 if [ -z "$src" ] || [ -z "$dst" ] || [ "$src" = "$dst" ]; then return 1; fi if [ ! -e "$src" ]; then if [ ! -e "$dst" ]; then return 1; else if [ -L "$dst" ]; then dstlnk=`/usr/bin/readlink "$dst"`; if [ ! -e "$dstlnk" ] ; then return 1; fi rm -f "$dst"; /bin/cp -fp "$dstlnk" "$dst"; fi; /bin/mv "$dst" "$src"; fi fi if [ -e "$dst" ]; then if [ ! -L "$dst" ]; then if [ ! -s "$dst" ] || /usr/bin/cmp "$dst" "$src" > /dev/null 2>&1; then /bin/rm -f "$dst"; else if [ "$src" -nt "$dst" ] || [ ! "$dst" -nt "$src" ] ; then /bin/mv "$dst" "$dst".`/bin/date +'%Y-%m-%d_%H-%M-%S.%N'`; else # [ "$dst" -nt "$src" ] /bin/mv "$src" "$src".`/bin/date +'%Y-%m-%d_%H-%M-%S.%N'`; /bin/mv "$dst" "$src"; fi; fi; else dstlnk=`/usr/bin/readlink "$dst"` if [ "$dstlnk" != $src ]; then /bin/rm -f $dst; if ! /usr/bin/cmp "$dstlnk" "$src" > /dev/null 2>&1; then if [ "$dstlnk" != "$dst" ] && [ -s $dstlnk ]; then if [ "$dstlnk" -nt "$src" ] || [ ! "$dstlnk" -nt "$src" ] ; then /bin/cp -fp "$dstlnk" "$dst".`/bin/date +'%Y-%m-%d_%H-%M-%S.%N'`; else /bin/mv "$src" "$src".`/bin/date +'%Y-%m-%d_%H-%M-%S.%N'`; /bin/cp -fp "$dstlnk" "$src"; fi; fi; fi; else return 0; fi; fi; fi; /bin/ln -sf "$src" "$dst"; return $?; } function replace_with_file() { if [ $# -lt 2 ]; then return 1; fi; src=$1; dst=$2; if [ -z "$src" ] || [ -z "$dst" ] || [ "$src" = "$dst" ]; then return 1; fi if [ ! -e "$src" ]; then if [ -e "$dst" ]; then /bin/rm -f $dst; fi; return 1; fi; if [ -e "$dst" ]; then if [ ! -L "$dst" ]; then /bin/mv "$dst" "$dst".`/bin/date +'%Y-%m-%d_%H-%M-%S.%N'`; else /bin/rm -f "$dst"; fi; fi; /bin/mv -f "$src" "$dst"; } function enable_bind_chroot() { if /bin/egrep -q '^ROOTDIR=' /etc/sysconfig/named; then /bin/sed -i -e 's#^ROOTDIR=.*$#ROOTDIR='${BIND_CHROOT_PREFIX}'#' /etc/sysconfig/named ; else echo 'ROOTDIR='${BIND_CHROOT_PREFIX} >> /etc/sysconfig/named; fi } function disable_bind_chroot() { /bin/sed -i -e '/^ROOTDIR=/d' /etc/sysconfig/named; } function sync_files() { shopt -q nullglob; ng=$? shopt -s nullglob; pfx='' changed=`/bin/mktemp /tmp/XXXXXX`; rm -f $changed if rootdir ; then # chroot is enabled /usr/bin/find /{etc/{named.*,rndc.*},${BIND_DIR#/}{/*,/data/*,/slaves/*}} -maxdepth 0 -type f | while read f; do replace_with_link ${BIND_CHROOT_PREFIX}/$f $f; [ ! -e $changed ] && touch $changed; done; /usr/bin/find /etc/{named.*,rndc.*}.rpmsave ${BIND_DIR}/*.rpmsave -maxdepth 0 -type l 2>/dev/null | while read f; do /bin/rm -f $f >/dev/null 2>&1; done pfx=${BIND_CHROOT_PREFIX} else # chroot is disabled /usr/bin/find /var/named/chroot/{etc/{named.*,rndc.*},var/named{/*,/data/*,/slaves/*}} -maxdepth 0 | while read f; do if [ ! -d "$f" ]; then replace_with_file $f ${f#$BIND_CHROOT_PREFIX}; [ ! -e $changed ] && touch $changed; fi; done fi; if [ ! -e ${pfx}/etc/rndc.key ]; then echo 'key "rndckey" { algorithm hmac-md5; secret "'`/usr/sbin/dns-keygen`'"; };' > /etc/rndc.key; elif /bin/egrep -q '@KEY@' /etc/rndc.key; then /bin/sed -i -e 's^@KEY@^'`/usr/sbin/dns-keygen`'^' /etc/rndc.key ; fi chown -h root:named /var/named/* >/dev/null 2>&1; chown -h root:named ${BIND_CHROOT_PREFIX}/var/named/* >/dev/null 2>&1; chown -h root:named /etc/{named,rndc}.* >/dev/null 2>&1; chown -h root:named ${BIND_CHROOT_PREFIX}/etc/{named,rndc}.* >/dev/null 2>&1; chmod 750 ${pfx}/var/named >/dev/null 2>&1; chmod 640 ${pfx}/var/named/* >/dev/null 2>&1; chmod 750 ${pfx}/var/named/*/. >/dev/null 2>&1; chown -h named:named /var/named/{data{,/*},slaves{,*/}} >/dev/null 2>&1; chown -h named:named ${BIND_CHROOT_PREFIX}/var/named/{data{,/*},slaves{,*/}} >/dev/null 2>&1; chmod 770 ${pfx}/var/named/{data,slaves} >/dev/null 2>&1; chmod 660 ${pfx}/var/named/{data/*,slaves/*} >/dev/null 2>&1; chmod 770 ${pfx}/var/named/{data/*/.,slaves/*/.} >/dev/null 2>&1; if [ -e $changed ]; then if selinux_enabled && [ -x /sbin/restorecon ]; then /sbin/restorecon -R ${BIND_CHROOT_PREFIX}/etc ${BIND_CHROOT_PREFIX}/var/named ${BIND_CHROOT_PREFIX}/var/run/named >/dev/null 2>&1; if [ -e ${BIND_CHROOT_PREFIX}/etc/localtime ] && [ -e /etc/localtime ] ; then /usr/bin/chcon --reference=/etc/localtime ${BIND_CHROOT_PREFIX}/etc/localtime >/dev/null 2>&1; fi; /usr/bin/chcon -h --reference=/etc/named.conf /etc/named.* >/dev/null 2>&1; /usr/bin/chcon -h --reference=/etc/rndc.key /etc/rndc.key >/dev/null 2>&1; /usr/bin/chcon -h --reference=/etc/rndc.conf /etc/rndc.conf >/dev/null 2>&1; /usr/bin/chcon -h --reference=/var/named /var/named{/,/*} >/dev/null 2>&1; /usr/bin/chcon -h --reference=${BIND_CHROOT_PREFIX}/var/named/slaves /var/named/{slaves,data}{/,/*} >/dev/null 2>&1; /sbin/restorecon /var/named/named.ca ${BIND_CHROOT_PREFIX}/var/named/named.ca >/dev/null 2>&1; /sbin/restorecon ${BIND_CHROOT_PREFIX} >/dev/null 2>&1; /usr/bin/chcon -h --reference=${BIND_CHROOT_PREFIX}/var/named/named.ca /var/named/named.ca >/dev/null 2>&1; fi; /sbin/service named condrestart rm -f $changed; fi; if [ $ng -eq 1 ]; then shopt -u nullglob; fi; } function clean_root() { if ! rootdir ; then # chroot is disabled, clean it up if [ -n "${BIND_CHROOT_PREFIX}" -a "x${BIND_CHROOT_PREFIX}" != "x/" ]; then rm -r ${BIND_CHROOT_PREFIX}/dev >/dev/null 2>&1 || :; rmdir ${BIND_CHROOT_PREFIX}/proc >/dev/null 2>&1 || :; rmdir ${BIND_CHROOT_PREFIX}/etc >/dev/null 2>&1 || :; rmdir ${BIND_CHROOT_PREFIX}/var/run/named >/dev/null 2>&1 || :; rmdir ${BIND_CHROOT_PREFIX}/var/run/dbus >/dev/null 2>&1 || :; rmdir ${BIND_CHROOT_PREFIX}/var/run >/dev/null 2>&1 || :; rmdir ${BIND_CHROOT_PREFIX}/var/named/slaves >/dev/null 2>&1 || :; rmdir ${BIND_CHROOT_PREFIX}/var/named/data >/dev/null 2>&1 || :; rmdir ${BIND_CHROOT_PREFIX}/var/named >/dev/null 2>&1 || :; rmdir ${BIND_CHROOT_PREFIX}/var/tmp >/dev/null 2>&1 || :; rmdir ${BIND_CHROOT_PREFIX}/var >/dev/null 2>&1 || :; fi; fi; } case $1 in -e|--enable) enable_bind_chroot; sync_files; exit $?; ;; -d|--disable) disable_bind_chroot; sync_files; /bin/umount ${BIND_CHROOT_PREFIX}/proc >/dev/null 2>&1 || :; /bin/umount ${BIND_CHROOT_PREFIX}/var/run/dbus >/dev/null 2>&1 || :; clean_root; exit $?; ;; -s|--sync) sync_files; exit $?; ;; -q) ;; *) usage; exit 1; esac