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