Index: dns/bind99/Makefile =================================================================== --- dns/bind99/Makefile +++ dns/bind99/Makefile @@ -203,6 +203,7 @@ .endif .if ${OPSYS} == FreeBSD && ${OSVERSION} >= 1000100 + ${MKDIR} ${STAGEDIR}${PREFIX}/etc/mtree ${MKDIR} ${STAGEDIR}${ETCDIR} .for i in dynamic master slave working @${MKDIR} ${STAGEDIR}${ETCDIR}/$i @@ -212,6 +213,8 @@ ${INSTALL_DATA} ${FILESDIR}/empty.db ${STAGEDIR}${ETCDIR}/master ${INSTALL_DATA} ${FILESDIR}/localhost-forward.db ${STAGEDIR}${ETCDIR}/master ${INSTALL_DATA} ${FILESDIR}/localhost-reverse.db ${STAGEDIR}${ETCDIR}/master + ${INSTALL_DATA} ${FILESDIR}/BIND.chroot.dist ${STAGEDIR}${PREFIX}/etc/mtree + ${INSTALL_DATA} ${FILESDIR}/BIND.chroot.local.dist ${STAGEDIR}${PREFIX}/etc/mtree .endif ${INSTALL_DATA} ${WRKSRC}/bin/rndc/rndc.conf \ ${STAGEDIR}${ETCDIR}/rndc.conf.sample Index: dns/bind99/files/BIND.chroot.dist =================================================================== --- /dev/null +++ dns/bind99/files/BIND.chroot.dist @@ -0,0 +1,24 @@ +# $FreeBSD$ +# +# mtree -deU -f files/BIND.chroot.dist -p tmp +# mtree -cjnb -k uname,gname,mode -p tmp + +/set type=file uname=root gname=wheel mode=0755 +. type=dir + dev type=dir mode=0555 + .. + etc type=dir + .. +/set type=file uname=bind gname=bind mode=0755 + var type=dir uname=root gname=wheel + dump type=dir + .. + log type=dir + .. + run type=dir + named type=dir + .. + .. + stats type=dir + .. + .. Index: dns/bind99/files/BIND.chroot.local.dist =================================================================== --- /dev/null +++ dns/bind99/files/BIND.chroot.local.dist @@ -0,0 +1,20 @@ +# $FreeBSD$ +# +# mtree -deU -f files/BIND.etc.dist -p tmp +# mtree -cjnb -k uname,gname,mode -p tmp + +/set type=file uname=root gname=wheel mode=0755 +. type=dir + etc type=dir +/set type=file uname=bind gname=wheel mode=0755 + namedb type=dir uname=root + dynamic type=dir + .. + master type=dir uname=root + .. + slave type=dir + .. + working type=dir + .. + .. + .. Index: dns/bind99/files/named.in =================================================================== --- dns/bind99/files/named.in +++ dns/bind99/files/named.in @@ -8,9 +8,27 @@ # BEFORE: NETWORKING # KEYWORD: shutdown +# +# Add the following lines to /etc/rc.conf to enable BIND: +# named_enable (bool): Run named, the DNS server (or NO). +# named_program (str): Path to named, if you want a different one. +# named_conf (str): Path to the configuration file +# named_flags (str): Use this for flags OTHER than -u and -c +# named_uid (str): User to run named as +# named_chrootdir (str): Chroot directory (or "" not to auto-chroot it) +# named_chroot_autoupdate (bool): Automatically install/update chrooted +# components of named. +# named_symlink_enable (bool): Symlink the chrooted pid file +# named_wait (bool): Wait for working name service before exiting +# named_wait_host (str): Hostname to check if named_wait is enabled +# named_auto_forward (str): Set up forwarders from /etc/resolv.conf +# named_auto_forward_only (str): Do "forward only" instead of "forward first" +# + . /etc/rc.subr name=named +desc="named BIND startup script" rcvar=named_enable load_rc_config $name @@ -21,22 +39,142 @@ start_postcmd=named_poststart reload_cmd=named_reload stop_cmd=named_stop +stop_postcmd=named_poststop + +named_enable=${named_enable:-"NO"} +named_program=${named_program:-"%%PREFIX%%/sbin/named"} +named_conf=${named_conf:-"%%ETCDIR%%/named.conf"} +named_flags=${named_flags:-""} +named_uid=${named_uid:-"bind"} +named_chrootdir=${named_chrootdir:-""} +named_chroot_autoupdate=${named_chroot_autoupdate:-"YES"} +named_symlink_enable=${named_symlink_enable:-"YES"} +named_wait=${named_wait:-"NO"} +named_wait_host=${named_wait_host:-"localhost"} +named_auto_forward=${named_auto_forward:-"NO"} +named_auto_forward_only=${named_auto_forward_only:-"NO"} + +# Not configuration variables but having them here keeps rclint happy +required_dirs="$named_chrootdir" +_named_confdirroot="${named_conf%/*}" +_named_confdir="${named_chrootdir}${_named_confdirroot}" +_named_program_root="${named_program%/sbin/named}" +_openssl_engines="/usr/local/lib/engines" + +# If running in a chroot cage, ensure that the appropriate files +# exist inside the cage, as well as helper symlinks into the cage +# from outside. +# +# As this is called after the is_running and required_dir checks +# are made in run_rc_command(), we can safely assume ${named_chrootdir} +# exists and named isn't running at this point (unless forcestart +# is used). +# +chroot_autoupdate() +{ + local file + + # If it's the first time around, fiddle with things and move the + # current configuration to the chroot. + if [ -d ${_named_confdirroot} -a ! -d ${_named_confdir} ]; then + warn "named chroot: Moving current configuration in the chroot!" + install -d ${_named_confdir%/*} + mv ${_named_confdirroot} ${_named_confdir} + fi + + # Create (or update) the chroot directory structure + # + if [ -r %%PREFIX%%/etc/mtree/BIND.chroot.dist ]; then + mtree -deU -f %%PREFIX%%/etc/mtree/BIND.chroot.dist \ + -p ${named_chrootdir} + else + warn "%%PREFIX%%/etc/mtree/BIND.chroot.dist missing," + warn "${named_chrootdir} directory structure not updated" + fi + if [ -r %%PREFIX%%/etc/mtree/BIND.chroot.local.dist ]; then + mkdir -p ${named_chrootdir}%%PREFIX%% + mtree -deU -f %%PREFIX%%/etc/mtree/BIND.chroot.local.dist \ + -p ${named_chrootdir}%%PREFIX%% + else + warn "%%PREFIX%%/etc/mtree/BIND.chroot.local.dist missing," + warn "${named_chrootdir}%%PREFIX%% directory structure not updated" + fi + + # Create (or update) the configuration directory symlink + # + if [ ! -L "${_named_confdirroot}" ]; then + if [ -d "${_named_confdirroot}" ]; then + warn "named chroot: ${_named_confdirroot} is a directory!" + elif [ -e "${_named_confdirroot}" ]; then + warn "named chroot: ${_named_confdirroot} exists!" + else + ln -s ${_named_confdir} ${_named_confdirroot} + fi + else + # Make sure it points to the right place. + ln -shf ${_named_confdir} ${_named_confdirroot} + fi + + # Mount a devfs in the chroot directory if needed + # + if [ `${SYSCTL_N} security.jail.jailed` -eq 0 ]; then + umount ${named_chrootdir}/dev 2>/dev/null + devfs_domount ${named_chrootdir}/dev devfsrules_hide_all + devfs -m ${named_chrootdir}/dev rule apply path null unhide + devfs -m ${named_chrootdir}/dev rule apply path random unhide + else + if [ -c ${named_chrootdir}/dev/null -a \ + -c ${named_chrootdir}/dev/random ]; then + info "named chroot: using pre-mounted devfs." + else + err 1 "named chroot: devfs cannot be mounted from" \ + "within a jail. Thus a chrooted named cannot" \ + "be run from within a jail." \ + "To run named without chrooting it, set" \ + "named_chrootdir=\"\" in /etc/rc.conf." + fi + fi -named_enable=${named_enable:-"NO"} # Run named, the DNS server (or NO). -named_program=${named_program:-"%%PREFIX%%/sbin/named"} # Path to named, if you want a different one. -named_conf=${named_conf:-"%%ETCDIR%%/named.conf"} # Path to the configuration file -named_flags=${named_flags:-""} # Use this for flags OTHER than -u and -c -named_uid=${named_uid:-"bind"} # User to run named as -named_wait=${named_wait:-"NO"} # Wait for working name service before exiting -named_wait_host=${named_wait_host:-"localhost"} # Hostname to check if named_wait is enabled -named_auto_forward=${named_auto_forward:-"NO"} # Set up forwarders from /etc/resolv.conf -named_auto_forward_only=${named_auto_forward_only:-"NO"} # Do "forward only" instead of "forward first" -named_confdir="${named_conf%/*}" # Not a configuration directive but makes rclint happy. + # If OpenSSL from ports, then the engines should be present in the + # chroot, named loads them after chrooting. + if [ -d ${_openssl_engines} ]; then + # FIXME when 8.4 see if security.jail.param.allow.mount.nullfs can be used. + if [ `${SYSCTL_N} security.jail.jailed` -eq 0 -o `${SYSCTL_N} security.jail.mount_allowed` -eq 1 ]; then + mkdir -p ${named_chrootdir}${_openssl_engines} + mount -t nullfs ${_openssl_engines} ${named_chrootdir}${_openssl_engines} + else + warn "named chroot: cannot nullfs mount OpenSSL" \ + "engines into the chroot, will copy the shared" \ + "libraries instead." + mkdir -p ${named_chrootdir}${_openssl_engines} + cp -f ${_openssl_engines}/*.so ${named_chrootdir}${_openssl_engines} + fi + fi + + # Copy and/or update key files to the chroot /etc + # + for file in localtime protocols services; do + if [ -r /etc/$file ] && \ + ! cmp -s /etc/$file "${named_chrootdir}/etc/$file"; then + cp -p /etc/$file "${named_chrootdir}/etc/$file" + fi + done +} + +# Make symlinks to the correct pid file +# +make_symlinks() +{ + checkyesno named_symlink_enable && + ln -fs "${named_chrootdir}${pidfile}" ${pidfile} +} named_poststart() { + make_symlinks + if checkyesno named_wait; then - until ${command%/sbin/named}/bin/host $named_wait_host >/dev/null 2>&1; do + until ${_named_program_root}/bin/host $named_wait_host >/dev/null 2>&1; do echo " Waiting for nameserver to resolve $named_wait_host" sleep 1 done @@ -45,9 +183,9 @@ named_reload() { - # This is a one line function, but ${command} is not defined early + # This is a one line function, but ${named_program} is not defined early # enough to be there when the reload_cmd variable is defined up there. - ${command%/named}/rndc reload + ${_named_program_root}/sbin/rndc reload } find_pidfile() @@ -73,13 +211,31 @@ return 1 fi echo 'Stopping named.' - if ${command%/named}/rndc stop 2>/dev/null; then + if ${_named_program_root}/sbin/rndc stop 2>/dev/null; then wait_for_pids $rc_pid else echo -n 'rndc failed, trying kill: ' kill -TERM $rc_pid wait_for_pids $rc_pid - fi + fi +} + +named_poststop() +{ + if [ -n "${named_chrootdir}" -a -c ${named_chrootdir}/dev/null ]; then + # unmount OpenSSL engines, if they were not mounted but only + # copied, do nothing. + if [ `${SYSCTL_N} security.jail.jailed` -eq 0 -o `${SYSCTL_N} security.jail.mount_allowed` -eq 1 ]; then + umount ${named_chrootdir}${_openssl_engines} + fi + # unmount /dev + if [ `${SYSCTL_N} security.jail.jailed` -eq 0 ]; then + umount ${named_chrootdir}/dev 2>/dev/null || true + else + warn "named chroot:" \ + "cannot unmount devfs from inside jail!" + fi + fi } create_file() @@ -107,15 +263,24 @@ local line nsip firstns + # Is the user using a sandbox? + # + if [ -n "$named_chrootdir" ]; then + rc_flags="$rc_flags -t $named_chrootdir" + checkyesno named_chroot_autoupdate && chroot_autoupdate + else + named_symlink_enable=NO + fi + # Create an rndc.key file for the user if none exists # - confgen_command="${command%/named}/rndc-confgen -a -b256 -u $named_uid \ - -c ${named_confdir}/rndc.key" - if [ -s "${named_confdir}/rndc.conf" ]; then + confgen_command="${_named_program_root}/sbin/rndc-confgen -a -b256 -u $named_uid \ + -c ${_named_confdir}/rndc.key" + if [ -s "${_named_confdir}/rndc.conf" ]; then unset confgen_command fi - if [ -s "${named_confdir}/rndc.key" ]; then - case `stat -f%Su ${named_confdir}/rndc.key` in + if [ -s "${_named_confdir}/rndc.key" ]; then + case `stat -f%Su ${_named_confdir}/rndc.key` in root|$named_uid) ;; *) $confgen_command ;; esac @@ -125,7 +290,10 @@ local checkconf - checkconf="${command%/named}/named-checkconf" + checkconf="${_named_program_root}/sbin/named-checkconf" + if ! checkyesno named_chroot_autoupdate && [ -n "$named_chrootdir" ]; then + checkconf="$checkconf -t $named_chrootdir" + fi # Create a forwarder configuration based on /etc/resolv.conf if checkyesno named_auto_forward; then @@ -133,8 +301,8 @@ warn "named_auto_forward enabled, but no /etc/resolv.conf" # Empty the file in case it is included in named.conf - [ -s "${named_confdir}/auto_forward.conf" ] && - create_file ${named_confdir}/auto_forward.conf + [ -s "${_named_confdir}/auto_forward.conf" ] && + create_file ${_named_confdir}/auto_forward.conf $checkconf $named_conf || err 3 'named-checkconf for $named_conf failed' @@ -183,19 +351,19 @@ mv /var/run/naf-resolv.conf /etc/resolv.conf fi - if cmp -s ${named_confdir}/auto_forward.conf \ + if cmp -s ${_named_confdir}/auto_forward.conf \ /var/run/auto_forward.conf; then unlink /var/run/auto_forward.conf else - [ -e "${named_confdir}/auto_forward.conf" ] && - unlink ${named_confdir}/auto_forward.conf + [ -e "${_named_confdir}/auto_forward.conf" ] && + unlink ${_named_confdir}/auto_forward.conf mv /var/run/auto_forward.conf \ - ${named_confdir}/auto_forward.conf + ${_named_confdir}/auto_forward.conf fi else # Empty the file in case it is included in named.conf - [ -s "${named_confdir}/auto_forward.conf" ] && - create_file ${named_confdir}/auto_forward.conf + [ -s "${_named_confdir}/auto_forward.conf" ] && + create_file ${_named_confdir}/auto_forward.conf fi $checkconf $named_conf || err 3 'named-checkconf for $named_conf failed' Index: dns/bind99/pkg-plist =================================================================== --- dns/bind99/pkg-plist +++ dns/bind99/pkg-plist @@ -377,12 +377,14 @@ sbin/rndc-confgen %%ETCDIR%%/rndc.conf.sample %%ETCDIR%%/bind.keys +%%NOBASE%%etc/mtree/BIND.chroot.dist +%%NOBASE%%etc/mtree/BIND.chroot.local.dist %%NOBASE%%@sample %%ETCDIR%%/named.conf.sample %%NOBASE%%%%ETCDIR%%/named.root %%NOBASE%%%%ETCDIR%%/master/empty.db %%NOBASE%%%%ETCDIR%%/master/localhost-forward.db %%NOBASE%%%%ETCDIR%%/master/localhost-reverse.db %%NOBASE%%@dir(bind,bind,) %%ETCDIR%%/dynamic -%%NOBASE%%@dir(bind,bind,) %%ETCDIR%%/master +%%NOBASE%%@dir %%ETCDIR%%/master %%NOBASE%%@dir(bind,bind,) %%ETCDIR%%/slave %%NOBASE%%@dir(bind,bind,) %%ETCDIR%%/working