#!/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 <jvdias@redhat.com>, 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@}
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
ENABLED=0;
else
ENABLED=1;
fi;
}
function selinux_enabled()
{
if [ -x /usr/sbin/selinuxenabled ]; then
/usr/sbin/selinuxenabled;
return $?;
fi;
return 1;
}
function check_dirs()
{
if [ -z "$BIND_CHROOT_PREFIX" ]; then
usage;
exit 1;
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,dynamic};
/bin/chown --preserve-root root:named ${BIND_DIR};
/bin/chown --preserve-root named:named ${BIND_DIR}/{slaves,data,dynamic};
/bin/chmod --preserve-root 750 ${BIND_DIR}
/bin/chmod --preserve-root 770 ${BIND_DIR}/{slaves,data,dynamic};
mkdir -p ${BIND_CHROOT_PREFIX}/{etc,dev,var/{run/named,named/{slaves,data,dynamic}}};
/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,dynamic}};
/bin/chmod --preserve-root 770 ${BIND_CHROOT_PREFIX}/var/{run/named,named/{slaves,data,dynamic}};
[ ! -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 /sbin/restorecon ]; then
for dev in random zero null; do
/sbin/restorecon ${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()
{
rootdir;
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()
{
rootdir;
shopt -q nullglob;
ng=$?
shopt -s nullglob;
pfx=''
changed=`/bin/mktemp /tmp/XXXXXX`;
rm -f $changed
if [ $ENABLED -eq 0 ] ; then # chroot is enabled
/usr/bin/find /{etc/{named.*,rndc.*},${BIND_DIR#/}{/*,/data/*,/slaves/*,/dynamic/*}} -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
ln -sf ${BIND_CHROOT_PREFIX}/var/log/named.log /var/log/named.log
pfx=${BIND_CHROOT_PREFIX}
else # chroot is disabled
/usr/bin/find /var/named/chroot/{etc/{named.*,rndc.*},var/named{/*,/data/*,/slaves/*,/dynamic/*}} -maxdepth 0 |
while read f;
do
if [ ! -d "$f" ]; then
replace_with_file $f ${f#$BIND_CHROOT_PREFIX};
[ ! -e $changed ] && touch $changed;
fi;
done
[ -L /var/log/named.log ] && rm -f /var/log/named.log
[ -e ${BIND_CHROOT_PREFIX}/var/log/named.log ] && mv -f ${BIND_CHROOT_PREFIX}/var/log/named.log /var/log/named.log
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{,/*},dynamic{,/*}} >/dev/null 2>&1;
chown -h named:named ${BIND_CHROOT_PREFIX}/var/named/{data{,/*},slaves{,/*},dynamic{,/*}} >/dev/null 2>&1;
chmod 770 ${pfx}/var/named/{data,slaves,dynamic} >/dev/null 2>&1;
chmod 660 ${pfx}/var/named/{data/*,slaves/*,dynamic/*} >/dev/null 2>&1;
chmod 770 ${pfx}/var/named/{data/*/.,slaves/*/.,dynamic/*/.} >/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/restorecon ${BIND_CHROOT_PREFIX}/etc/localtime >/dev/null 2>&1;
fi;
/sbin/restorecon /etc/named.* >/dev/null 2>&1;
/sbin/restorecon /etc/rndc.key >/dev/null 2>&1;
/sbin/restorecon /etc/rndc.conf >/dev/null 2>&1;
/sbin/restorecon /var/named{/,/*} >/dev/null 2>&1;
/sbin/restorecon /var/named/{slaves,data,dynamic}{/,/*} >/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;
/sbin/restorecon /var/named/named.ca >/dev/null 2>&1;
fi;
/sbin/service named try-restart
rm -f $changed;
fi;
if [ $ng -eq 1 ]; then
shopt -u nullglob;
fi;
}
function clean_root()
{
if [ $ENABLED -eq 0 ] ; 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/dynamic >/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