Index: dns/bind910/Makefile =================================================================== --- dns/bind910/Makefile +++ dns/bind910/Makefile @@ -220,6 +220,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 @@ -229,6 +230,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/bind910/files/BIND.chroot.dist =================================================================== --- /dev/null +++ dns/bind910/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/bind910/files/BIND.chroot.local.dist =================================================================== --- /dev/null +++ dns/bind910/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/bind910/files/named.in =================================================================== --- dns/bind910/files/named.in +++ dns/bind910/files/named.in @@ -8,12 +8,32 @@ # 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) +# Historically, was /var/named +# 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" +%%NATIVE_PKCS11%%# named_pkcs11_engine (str): Path to the PKCS#11 library to use. +# + . /etc/rc.subr name=named +desc="named BIND startup script" rcvar=named_enable -load_rc_config $name +load_rc_config ${name} extra_commands=reload @@ -21,24 +41,144 @@ 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"} +%%NATIVE_PKCS11%%named_pkcs11_engine=${named_pkcs11_engine:-""} + +# 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="%%LOCALBASE%%/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 -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" -%%NATIVE_PKCS11%%named_pkcs11_engine=${named_pkcs11_engine:-""} # Path to the PKCS#11 library to use. -named_confdir="${named_conf%/*}" # Not a configuration directive but makes rclint happy. + # 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 + + # 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 - echo " Waiting for nameserver to resolve $named_wait_host" + 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 fi @@ -46,15 +186,15 @@ 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() { - if get_pidfile_from_conf pid-file $named_conf; then - pidfile="$_pidfile_from_conf" + if get_pidfile_from_conf pid-file ${named_conf}; then + pidfile="${_pidfile_from_conf}" else pidfile="/var/run/named/pid" fi @@ -67,20 +207,38 @@ # This duplicates an undesirably large amount of code from the stop # routine in rc.subr in order to use rndc to shut down the process, # and to give it a second chance in case rndc fails. - rc_pid=$(check_pidfile $pidfile $command) - if [ -z "$rc_pid" ]; then - [ -n "$rc_fast" ] && return 0 + rc_pid=$(check_pidfile ${pidfile} ${command}) + if [ -z "${rc_pid}" ]; then + [ -n "${rc_fast}" ] && return 0 _run_rc_notrunning return 1 fi echo 'Stopping named.' - if ${command%/named}/rndc stop 2>/dev/null; then - wait_for_pids $rc_pid + 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 + kill -TERM ${rc_pid} + wait_for_pids ${rc_pid} + 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() @@ -95,7 +253,7 @@ { find_pidfile - if [ -n "$named_pidfile" ]; then + if [ -n "${named_pidfile}" ]; then warn 'named_pidfile: now determined from the conf file' fi @@ -104,37 +262,51 @@ install -d -o ${named_uid} -g ${named_uid} ${piddir} fi - command_args="-u ${named_uid:=root} -c $named_conf $command_args" + command_args="-u ${named_uid:=root} -c ${named_conf} ${command_args}" -%%NATIVE_PKCS11%% if [ -z "$named_pkcs11_engine"]; then -%%NATIVE_PKCS11%% err 3 "named_pkcs11_engine has to be set to the PKCS#11 engine's library you want to use" -%%NATIVE_PKCS11%% elif [ ! -f $named_pkcs11_engine ]; then -%%NATIVE_PKCS11%% err 3 "named_pkcs11_engine the PKCS#11 engine's library you want to use doesn't exist" +%%NATIVE_PKCS11%% if [ -z "${named_pkcs11_engine}"]; then +%%NATIVE_PKCS11%% err 3 "named_pkcs11_engine has to be set to the PKCS#11 engine's library you want to use" +%%NATIVE_PKCS11%% elif [ ! -f ${named_pkcs11_engine} ]; then +%%NATIVE_PKCS11%% err 3 "named_pkcs11_engine the PKCS#11 engine's library you want to use doesn't exist" %%NATIVE_PKCS11%% else -%%NATIVE_PKCS11%% command_args="-E $named_pkcs11_engine $command_args" +%%NATIVE_PKCS11%% mkdir -p ${named_chrootdir}${named_pkcs11_engine%/*} +%%NATIVE_PKCS11%% cp -p ${named_pkcs11_engine} ${named_chrootdir}${named_pkcs11_engine} +%%NATIVE_PKCS11%% command_args="-E ${named_pkcs11_engine} ${command_args}" %%NATIVE_PKCS11%% fi -%%NATIVE_PKCS11%% + 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 - root|$named_uid) ;; - *) $confgen_command ;; + if [ -s "${_named_confdir}/rndc.key" ]; then + case `stat -f%Su ${_named_confdir}/rndc.key` in + root|${named_uid}) ;; + *) ${confgen_command} ;; esac else - $confgen_command + ${confgen_command} fi 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 @@ -142,11 +314,11 @@ 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' + ${checkconf} ${named_conf} || + err 3 'named-checkconf for ${named_conf} failed' return fi @@ -156,25 +328,25 @@ echo ' forwarders {' > /var/run/auto_forward.conf while read line; do - case "$line" in + case "${line}" in 'nameserver '*|'nameserver '*) nsip=${line##nameserver[ ]} - if [ -z "$firstns" ]; then - if [ ! "$nsip" = '127.0.0.1' ]; then + if [ -z "${firstns}" ]; then + if [ ! "${nsip}" = '127.0.0.1' ]; then echo 'nameserver 127.0.0.1' echo " ${nsip};" >> /var/run/auto_forward.conf fi firstns=1 else - [ "$nsip" = '127.0.0.1' ] && continue + [ "${nsip}" = '127.0.0.1' ] && continue echo " ${nsip};" >> /var/run/auto_forward.conf fi ;; esac - echo $line + echo ${line} done < /etc/resolv.conf > /var/run/naf-resolv.conf echo ' };' >> /var/run/auto_forward.conf @@ -192,22 +364,22 @@ 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' + ${checkconf} ${named_conf} || err 3 "named-checkconf for ${named_conf} failed" } run_rc_command "$1" Index: dns/bind910/pkg-plist =================================================================== --- dns/bind910/pkg-plist +++ dns/bind910/pkg-plist @@ -410,12 +410,14 @@ sbin/tsig-keygen %%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 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,12 +8,31 @@ # 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) +# Historically, was /var/named +# 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 +load_rc_config ${name} extra_commands=reload @@ -21,23 +40,143 @@ 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="%%LOCALBASE%%/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 - echo " Waiting for nameserver to resolve $named_wait_host" + 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 fi @@ -45,15 +184,15 @@ 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() { - if get_pidfile_from_conf pid-file $named_conf; then - pidfile="$_pidfile_from_conf" + if get_pidfile_from_conf pid-file ${named_conf}; then + pidfile="${_pidfile_from_conf}" else pidfile="/var/run/named/pid" fi @@ -66,20 +205,38 @@ # This duplicates an undesirably large amount of code from the stop # routine in rc.subr in order to use rndc to shut down the process, # and to give it a second chance in case rndc fails. - rc_pid=$(check_pidfile $pidfile $command) - if [ -z "$rc_pid" ]; then - [ -n "$rc_fast" ] && return 0 + rc_pid=$(check_pidfile ${pidfile} ${command}) + if [ -z "${rc_pid}" ]; then + [ -n "${rc_fast}" ] && return 0 _run_rc_notrunning return 1 fi echo 'Stopping named.' - if ${command%/named}/rndc stop 2>/dev/null; then - wait_for_pids $rc_pid + 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 + kill -TERM ${rc_pid} + wait_for_pids ${rc_pid} + 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() @@ -94,7 +251,7 @@ { find_pidfile - if [ -n "$named_pidfile" ]; then + if [ -n "${named_pidfile}" ]; then warn 'named_pidfile: now determined from the conf file' fi @@ -103,29 +260,41 @@ install -d -o ${named_uid} -g ${named_uid} ${piddir} fi - command_args="-u ${named_uid:=root} -c $named_conf $command_args" + command_args="-u ${named_uid:=root} -c ${named_conf} ${command_args}" 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 - root|$named_uid) ;; - *) $confgen_command ;; + if [ -s "${_named_confdir}/rndc.key" ]; then + case `stat -f%Su ${_named_confdir}/rndc.key` in + root|${named_uid}) ;; + *) ${confgen_command} ;; esac else - $confgen_command + ${confgen_command} fi 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,11 +302,11 @@ 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' + ${checkconf} ${named_conf} || + err 3 'named-checkconf for ${named_conf} failed' return fi @@ -147,25 +316,25 @@ echo ' forwarders {' > /var/run/auto_forward.conf while read line; do - case "$line" in + case "${line}" in 'nameserver '*|'nameserver '*) nsip=${line##nameserver[ ]} - if [ -z "$firstns" ]; then - if [ ! "$nsip" = '127.0.0.1' ]; then + if [ -z "${firstns}" ]; then + if [ ! "${nsip}" = '127.0.0.1' ]; then echo 'nameserver 127.0.0.1' echo " ${nsip};" >> /var/run/auto_forward.conf fi firstns=1 else - [ "$nsip" = '127.0.0.1' ] && continue + [ "${nsip}" = '127.0.0.1' ] && continue echo " ${nsip};" >> /var/run/auto_forward.conf fi ;; esac - echo $line + echo ${line} done < /etc/resolv.conf > /var/run/naf-resolv.conf echo ' };' >> /var/run/auto_forward.conf @@ -183,22 +352,22 @@ 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' + ${checkconf} ${named_conf} || err 3 "named-checkconf for ${named_conf} failed" } run_rc_command "$1" 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