changeset 1601:ed0524dd1004 draft

Escape | and & characters when passing to the shell. Add functions for hooks to check validity of domain names and paths. Ensure we set a valid hostname, DNS domain and NIS domain. Document the need for input validation in dhcpcd-run-hooks(8). Fixes CVE-2011-996. Based on patches to dhcpcd-3 by Marius Tomaschewski <mt@suse.de>.
author Roy Marples <roy@marples.name>
date Wed, 06 Apr 2011 08:16:32 +0000
parents 9c96a554b838
children a4828c7eceaf
files dhcp.c dhcpcd-hooks/20-resolv.conf dhcpcd-hooks/30-hostname dhcpcd-hooks/50-yp.conf dhcpcd-hooks/50-ypbind dhcpcd-run-hooks.8.in dhcpcd-run-hooks.in
diffstat 7 files changed, 84 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/dhcp.c	Tue Mar 29 10:36:17 2011 +0000
+++ b/dhcp.c	Wed Apr 06 08:16:32 2011 +0000
@@ -1143,7 +1143,9 @@
 		case '\'': /* FALLTHROUGH */
 		case '$':  /* FALLTHROUGH */
 		case '`':  /* FALLTHROUGH */
- 		case '\\':
+ 		case '\\': /* FALLTHROUGH */
+		case '|':  /* FALLTHROUGH */
+		case '&':
 			if (s) {
 				if (len < 3) {
 					errno = ENOBUFS;
--- a/dhcpcd-hooks/20-resolv.conf	Tue Mar 29 10:36:17 2011 +0000
+++ b/dhcpcd-hooks/20-resolv.conf	Wed Apr 06 08:16:32 2011 +0000
@@ -81,14 +81,22 @@
 	if [ -n "$new_domain_name" ]; then
 		set -- $new_domain_name
 		new_domain_name="$1"
-		conf="${conf}domain $new_domain_name\n"
+		if valid_domainname "$new_domain_name"; then
+			conf="${conf}domain $new_domain_name\n"
+		else
+			syslog err "Invalid domain name: $new_domain_name"
+		fi
 		# Support RFC violating search in domain
 		if [ -z "$new_domain_search" -a -n "$2" ]; then
 			new_domain_search="$@"
 		fi
 	fi
 	if [ -n "$new_domain_search" ]; then
-		conf="${conf}search $new_domain_search\n"
+		if valid_domainname_list; then
+			conf="${conf}search $new_domain_search\n"
+		else
+			syslog err "Invalid domain name in list: $new_domain_search"
+		fi
 	fi
 	for x in ${new_domain_name_servers}; do
 		conf="${conf}nameserver $x\n"
--- a/dhcpcd-hooks/30-hostname	Tue Mar 29 10:36:17 2011 +0000
+++ b/dhcpcd-hooks/30-hostname	Wed Apr 06 08:16:32 2011 +0000
@@ -18,13 +18,22 @@
 	esac
 }
 
+try_hostname()
+{
+	if valid_domainname "$1"; then
+		hostname "$1"
+	else
+		syslog err "Invalid hostname: $1"
+	fi
+}
+
 set_hostname()
 {
 	if need_hostname; then
 		if [ -n "$new_host_name" ]; then
-			hostname "$new_host_name"
+			try_hostname "$new_host_name"
 		elif [ -n "$new_fqdn_name" ]; then
-			hostname "$new_fqdn_name"
+			try_hostname "$new_fqdn_name"
 		fi
 	fi
 }
--- a/dhcpcd-hooks/50-yp.conf	Tue Mar 29 10:36:17 2011 +0000
+++ b/dhcpcd-hooks/50-yp.conf	Wed Apr 06 08:16:32 2011 +0000
@@ -13,6 +13,11 @@
 	rm -f "$cf"
 	echo "$signature" > "$cf"
 	if [ -n "$new_nis_domain" ]; then
+		if ! valid_domainname "$new_nis_domain"; then
+			syslog err "Invalid NIS domain name: $new_nis_domain"
+			rm -f "$cf"
+			return 1
+		fi
 		domainname "$new_nis_domain"
 		if [ -n "$new_nis_servers" ]; then
 			prefix="domain $new_nis_domain server "
--- a/dhcpcd-hooks/50-ypbind	Tue Mar 29 10:36:17 2011 +0000
+++ b/dhcpcd-hooks/50-ypbind	Wed Apr 06 08:16:32 2011 +0000
@@ -67,7 +67,11 @@
 	rm -f "$ypbind_dir/$interface"
 elif $if_up || $if_down; then
 	if [ -n "$new_nis_domain" ]; then
-		make_yp_binding
+		if valid_domainname "$new_nis_domain"; then
+			make_yp_binding
+		else
+			syslog err "Invalid NIS domain name: $new_nis_domain"
+		fi
 	elif [ -n "$old_nis_domain" ]; then
 		restore_yp_binding
 	fi
--- a/dhcpcd-run-hooks.8.in	Tue Mar 29 10:36:17 2011 +0000
+++ b/dhcpcd-run-hooks.8.in	Wed Apr 06 08:16:32 2011 +0000
@@ -1,4 +1,4 @@
-.\" Copyright (c) 2006-2010 Roy Marples
+.\" Copyright (c) 2006-2011 Roy Marples
 .\" All rights reserved
 .\"
 .\" Redistribution and use in source and binary forms, with or without
@@ -22,7 +22,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd August 24, 2010
+.Dd March 23, 2011
 .Dt DHCPCD-RUN-HOOKS 8 SMM
 .Os
 .Sh NAME
@@ -135,3 +135,11 @@
 .An Roy Marples Aq roy@marples.name
 .Sh BUGS
 Please report them to http://roy.marples.name/projects/dhcpcd
+.Sh SECURITY CONSIDERATIONS
+Little validation of DHCP options is done in dhcpcd itself.
+Instead, it is up to the hooks to handle any validation needed.
+To this end, some helper functions are provided, such as valid_domainname as
+used by the
+.Pa 20-resolv.conf
+hook to ensure that the hostname is not set to an invalid value.
+valid_path is also provided, but is currently unused by a stock hook script.
--- a/dhcpcd-run-hooks.in	Tue Mar 29 10:36:17 2011 +0000
+++ b/dhcpcd-run-hooks.in	Wed Apr 06 08:16:32 2011 +0000
@@ -147,6 +147,46 @@
 	fi
 }
 
+# Check for a valid domain name as per RFC1123 with the exception of
+# allowing - and _ as they seem to be widely used.
+valid_domainname()
+{
+	local name="$1" label
+
+	[ -z "$name" -o ${#name} -gt 255 ] && return 1
+	
+	while [ -n "$name" ]; do
+		label="${name%%.*}"
+		[ -z "$label" -o ${#label} -gt 63 ] && return 1
+		case "$label" in
+		-*|_*|*-|*_)		return 1;;
+		*[![:alnum:]-_]*)	return 1;;
+		esac
+		[ "$name" = "${name#*.}" ] && break
+		name="${name#*.}"
+	done
+	return 0	
+}
+
+valid_domainname_list()
+{
+	local name
+
+	for name in $@; do
+		valid_domainname "$name" || return $?
+	done
+	return 0
+}
+
+# Check for a valid path
+valid_path()
+{
+	case "$@" in
+	*[![:alnum:]#%+-_:\.,@~\\/\[\]=\ ]*) return 1;;
+	esac
+	return 0
+}
+
 # Check a system service exists 
 service_exists()
 {