Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 24 Mar 2015 15:22:51 +0000 (UTC)
From:      Mathieu Arnold <mat@FreeBSD.org>
To:        ports-committers@freebsd.org, svn-ports-all@freebsd.org, svn-ports-head@freebsd.org
Subject:   svn commit: r382109 - in head: . dns/bind910 dns/bind910/files dns/bind99 dns/bind99/files
Message-ID:  <201503241522.t2OFMp0S027478@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mat
Date: Tue Mar 24 15:22:51 2015
New Revision: 382109
URL: https://svnweb.freebsd.org/changeset/ports/382109
QAT: https://qat.redports.org/buildarchive/r382109/

Log:
  Add chroot back to BIND's startup script.
  
  Differential Revision:	https://reviews.freebsd.org/D1952
  Sponsored by:	Absolight

Added:
  head/dns/bind910/files/BIND.chroot.dist   (contents, props changed)
  head/dns/bind910/files/BIND.chroot.local.dist   (contents, props changed)
  head/dns/bind99/files/BIND.chroot.dist   (contents, props changed)
  head/dns/bind99/files/BIND.chroot.local.dist   (contents, props changed)
Modified:
  head/UPDATING
  head/dns/bind910/Makefile
  head/dns/bind910/files/named.in
  head/dns/bind910/pkg-plist
  head/dns/bind99/Makefile
  head/dns/bind99/files/named.conf.in
  head/dns/bind99/files/named.in
  head/dns/bind99/pkg-plist

Modified: head/UPDATING
==============================================================================
--- head/UPDATING	Tue Mar 24 15:18:38 2015	(r382108)
+++ head/UPDATING	Tue Mar 24 15:22:51 2015	(r382109)
@@ -5,6 +5,24 @@ they are unavoidable.
 You should get into the habit of checking this file for changes each time
 you update your ports collection, before attempting any port upgrades.
 
+20150324:
+  AFFECTS: Users of dns/bind9*
+  AUTHOR: mat@FreeBSD.org
+
+  This is only for FreeBSD 10.0+.
+
+  BIND auto chroot has been added back to the named rc script.  As enabling it
+  by default would most certainly break people's setup, it is not.  To enable
+  it, and chroot it in /var/named, add the following line to your rc.conf file:
+
+  named_chrootdir="/var/named"
+
+  On first launch, the rc script will move the /usr/local/etc/namedb directory
+  into the chroot, and create a symlink to it.
+
+  Note that, if you're running from within a jail, you need to have a
+  /var/named/dev devfs created beforehand, with the null and random devices.
+
 20150323:
   AFFECTS: Users of net/asterisk* and net/pjsip ports
   AUTHOR: madpilot@FreeBSD.org

Modified: head/dns/bind910/Makefile
==============================================================================
--- head/dns/bind910/Makefile	Tue Mar 24 15:18:38 2015	(r382108)
+++ head/dns/bind910/Makefile	Tue Mar 24 15:22:51 2015	(r382109)
@@ -7,7 +7,7 @@ PORTVERSION=	${ISCVERSION:S/-P/P/}
 PORTREVISION=	0
 .else
 # dns/bind910 here
-PORTREVISION=	0
+PORTREVISION=	1
 .endif
 CATEGORIES=	dns net ipv6
 MASTER_SITES=	ISC/bind9/${ISCVERSION}
@@ -218,6 +218,7 @@ post-install:
 .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
@@ -227,6 +228,8 @@ post-install:
 	${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

Added: head/dns/bind910/files/BIND.chroot.dist
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/dns/bind910/files/BIND.chroot.dist	Tue Mar 24 15:22:51 2015	(r382109)
@@ -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
+        ..
+    ..

Added: head/dns/bind910/files/BIND.chroot.local.dist
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/dns/bind910/files/BIND.chroot.local.dist	Tue Mar 24 15:22:51 2015	(r382109)
@@ -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
+            ..
+        ..
+    ..

Modified: head/dns/bind910/files/named.in
==============================================================================
--- head/dns/bind910/files/named.in	Tue Mar 24 15:18:38 2015	(r382108)
+++ head/dns/bind910/files/named.in	Tue Mar 24 15:22:51 2015	(r382109)
@@ -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,145 @@ start_precmd=named_prestart
 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
+
+	# 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 is gone 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
+}
 
-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.
+# 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 +187,15 @@ named_poststart()
 
 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 +208,38 @@ named_stop()
 	# 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 +254,7 @@ named_prestart()
 {
 	find_pidfile
 
-	if [ -n "$named_pidfile" ]; then
+	if [ -n "${named_pidfile}" ]; then
 		warn 'named_pidfile: now determined from the conf file'
 	fi
 
@@ -104,37 +263,51 @@ named_prestart()
 		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 +315,11 @@ named_prestart()
 			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 +329,25 @@ named_prestart()
 		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 +365,22 @@ named_prestart()
 			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"

Modified: head/dns/bind910/pkg-plist
==============================================================================
--- head/dns/bind910/pkg-plist	Tue Mar 24 15:18:38 2015	(r382108)
+++ head/dns/bind910/pkg-plist	Tue Mar 24 15:22:51 2015	(r382109)
@@ -410,12 +410,14 @@ sbin/rndc-confgen
 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

Modified: head/dns/bind99/Makefile
==============================================================================
--- head/dns/bind99/Makefile	Tue Mar 24 15:18:38 2015	(r382108)
+++ head/dns/bind99/Makefile	Tue Mar 24 15:22:51 2015	(r382109)
@@ -2,7 +2,7 @@
 
 PORTNAME=	bind
 PORTVERSION=	${ISCVERSION:S/-P/P/}
-PORTREVISION=	0
+PORTREVISION=	1
 CATEGORIES=	dns net ipv6
 MASTER_SITES=	ISC/bind9/${ISCVERSION}
 PKGNAMESUFFIX=	99
@@ -200,6 +200,7 @@ post-install:
 .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
@@ -209,6 +210,8 @@ post-install:
 	${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

Added: head/dns/bind99/files/BIND.chroot.dist
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/dns/bind99/files/BIND.chroot.dist	Tue Mar 24 15:22:51 2015	(r382109)
@@ -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
+        ..
+    ..

Added: head/dns/bind99/files/BIND.chroot.local.dist
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/dns/bind99/files/BIND.chroot.local.dist	Tue Mar 24 15:22:51 2015	(r382109)
@@ -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
+            ..
+        ..
+    ..

Modified: head/dns/bind99/files/named.conf.in
==============================================================================
--- head/dns/bind99/files/named.conf.in	Tue Mar 24 15:18:38 2015	(r382108)
+++ head/dns/bind99/files/named.conf.in	Tue Mar 24 15:22:51 2015	(r382109)
@@ -1,7 +1,7 @@
 // $FreeBSD$
 //
 // Refer to the named.conf(5) and named(8) man pages, and the documentation
-// in /usr/share/doc/bind9 for more details.
+// in /usr/local/share/doc/bind for more details.
 //
 // If you are going to set up an authoritative server, make sure you
 // understand the hairy details of how DNS works.  Even with

Modified: head/dns/bind99/files/named.in
==============================================================================
--- head/dns/bind99/files/named.in	Tue Mar 24 15:18:38 2015	(r382108)
+++ head/dns/bind99/files/named.in	Tue Mar 24 15:22:51 2015	(r382109)
@@ -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,144 @@ start_precmd=named_prestart
 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
 
-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.
+	# 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 is gone 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 +185,15 @@ named_poststart()
 
 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 +206,38 @@ named_stop()
 	# 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 +252,7 @@ named_prestart()
 {
 	find_pidfile
 
-	if [ -n "$named_pidfile" ]; then
+	if [ -n "${named_pidfile}" ]; then
 		warn 'named_pidfile: now determined from the conf file'
 	fi
 
@@ -103,29 +261,41 @@ named_prestart()
 		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 +303,11 @@ named_prestart()
 			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 +317,25 @@ named_prestart()
 		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 +353,22 @@ named_prestart()
 			mv /var/run/naf-resolv.conf /etc/resolv.conf
 		fi
 
-		if cmp -s ${named_confdir}/auto_forward.conf \

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201503241522.t2OFMp0S027478>