Hello community, here is the log from the commit of package dhcp for openSUSE:11.2 checked in at Wed Apr 6 10:53:14 CEST 2011.
-------- --- old-versions/11.2/UPDATES/all/dhcp/dhcp.changes 2009-12-16 15:19:51.000000000 +0100 +++ 11.2/dhcp/dhcp.changes 2011-04-06 10:31:25.000000000 +0200 @@ -1,0 +2,11 @@ +Wed Mar 30 10:16:31 UTC 2011 - [email protected] + +- Discard string options such as host and domain names containing + disallowed characters or beeing too long. This proctive patch + limits root-path to a-zA-Z0-9, #%+-_:.,@~/\[]= and a space + (bnc#675052, CVE-2011-0997). +- dhclient-script: fixed typo causing that only global settings + to set hostname and default route were applied for primary + and never per interface settings (bnc#673792). + +------------------------------------------------------------------- calling whatdependson for 11.2-i586 New: ---- dhcp-3.1.2p1-dhclient-option-checks.bnc675052.diff dhcp-3.1.2p1-dhclient-script.bnc673792.diff ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ dhcp.spec ++++++ --- /var/tmp/diff_new_pack.AyMBTa/_old 2011-04-06 10:53:00.000000000 +0200 +++ /var/tmp/diff_new_pack.AyMBTa/_new 2011-04-06 10:53:00.000000000 +0200 @@ -1,7 +1,7 @@ # -# spec file for package dhcp (Version 3.1.2p1) +# spec file for package dhcp # -# Copyright (c) 2009 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2011 SUSE LINUX Products GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -31,7 +31,7 @@ Group: Productivity/Networking/Boot/Servers AutoReqProv: on Version: 3.1.2p1 -Release: 4.<RELEASE6> +Release: 4.<RELEASE8> Summary: Common Files Used by ISC DHCP Software Url: http://www.isc.org/isc/dhcp.html Source0: http://ftp.isc.org/isc/dhcp/dhcp-%{version}.tar.gz @@ -81,6 +81,8 @@ ## Patch70: dhcp-3.1.1-CVE-2009-1892.bnc519413.dif Patch71: dhcp-3.1.2p1-dhclient-script.bnc555095.dif +Patch72: dhcp-3.1.2p1-dhclient-script.bnc673792.diff +Patch73: dhcp-3.1.2p1-dhclient-option-checks.bnc675052.diff Obsoletes: dhcp-base Provides: dhcp-base:/usr/bin/omshell PreReq: /bin/touch /sbin/chkconfig sysconfig @@ -207,6 +209,8 @@ %patch60 -p0 %patch70 -p0 %patch71 -p0 +%patch72 -p0 +%patch73 -p0 ## find . -type f -name \*.cat\* -exec rm -f {} \; cp -p %{S:2} %{S:3} %{S:11} %{S:12} %{S:14} %{S:32} %{S:33} . ++++++ dhcp-3.1.2p1-dhclient-option-checks.bnc675052.diff ++++++ --- client/dhclient.c +++ client/dhclient.c 2011/03/31 13:28:59 @@ -37,6 +37,8 @@ static char ocopyright[] = #include "dhcpd.h" #include "version.h" +#include <stddef.h> +#include <ctype.h> TIME default_lease_time = 43200; /* 12 hours... */ TIME max_lease_time = 86400; /* 24 hours... */ @@ -76,6 +78,10 @@ int quiet=0; int nowait=0; static void usage PROTO ((void)); +static int check_domain_name(const char *ptr, size_t len, int dots); +static int check_domain_name_list(const char *ptr, size_t len, int dots); +static int check_option_values(struct universe *universe, unsigned int opt, + const char *ptr, size_t len); int main (argc, argv, envp) int argc; @@ -197,8 +203,11 @@ int main (argc, argv, envp) log_error("-H option host-name string \"%s\" is too long:" "maximum length is %d characters", argv[i], HOST_NAME_MAX); exit(1); + } else if (check_domain_name(argv [i], strlen(argv [i]), 0) != 0) { + log_error("suspect hostname in -H option - discarded"); + } else { + dhclient_hostname = argv [i]; } - dhclient_hostname = argv [i]; } else if (!strcmp (argv [i], "-nw")) { nowait = 1; } else if (!strcmp (argv [i], "-n")) { @@ -2547,12 +2556,21 @@ void client_option_envadd (struct option char name [256]; if (dhcp_option_ev_name (name, sizeof name, oc -> option)) { - client_envadd (es -> client, es -> prefix, - name, "%s", - (pretty_print_option - (oc -> option, - data.data, data.len, - 0, 0))); + const char *value = pretty_print_option(oc -> option, + data.data, + data.len, 0, 0); + size_t length = strlen(value); + + if (check_option_values(oc->option->universe, + oc->option->code, + value, length) == 0) { + client_envadd (es -> client, es -> prefix, + name, "%s", value); + } else { + log_error ("suspect value in %s " + "option - discarded", + name); + } data_string_forget (&data, MDL); } } @@ -2632,12 +2650,31 @@ void script_write_params (client, prefix data_string_forget (&data, MDL); } - if (lease -> filename) - client_envadd (client, - prefix, "filename", "%s", lease -> filename); - if (lease -> server_name) - client_envadd (client, prefix, "server_name", - "%s", lease -> server_name); + if (lease -> filename) { + if (check_option_values(NULL, DHO_ROOT_PATH, + lease -> filename, + strlen(lease -> filename)) == 0) { + client_envadd (client, prefix, "filename", + "%s", lease -> filename); + } else { + log_error("suspect value in %s " + "option - discarded", + "filename"); + } + } + + if (lease -> server_name) { + if (check_option_values(NULL, DHO_HOST_NAME, + lease -> server_name, + strlen(lease -> server_name)) == 0) { + client_envadd (client, prefix, "server_name", + "%s", lease -> server_name); + } else { + log_error("suspect value in %s " + "option - discarded", + "server-name"); + } + } for (i = 0; i < lease -> options -> universe_count; i++) { option_space_foreach ((struct packet *)0, (struct lease *)0, @@ -3267,3 +3304,103 @@ isc_result_t client_dns_update (struct c data_string_forget (&ddns_dhcid, MDL); return rcode; } + +static int check_domain_name(const char *ptr, size_t len, int dots) +{ + const char *p; + + /* not empty or complete length not over 255 characters */ + if (len == 0 || len >= 256) + return -1; + + /* consists of [[:alnum:]-]+ labels separated by [.] */ + /* a [_] is against RFC but seems to be "widely used"... */ + for (p=ptr; *p && len-- > 0; p++) { + if ( *p == '-' || *p == '_') { + /* not allowed at begin or end of a label */ + if ((p - ptr) == 0 || len == 0 || p[1] == '.') + return -1; + } else + if ( *p == '.') { + /* each label has to be 1-63 characters; + we allow [.] at the end ('foo.bar.') */ + ptrdiff_t d = p - ptr; + if( d <= 0 || d >= 64) + return -1; + ptr = p + 1; /* jump to the next label */ + if(dots > 0 && len > 0) + dots--; + } else + if ( !isalnum((unsigned char)*p)) { + /* also numbers at the begin are fine */ + return -1; + } + } + return dots ? -1 : 0; +} + +static int check_domain_name_list(const char *ptr, size_t len, int dots) +{ + const char *p; + int ret = -1; /* at least one needed */ + + if (!ptr || !len) + return -1; + + for (p=ptr; *p && len > 0; p++, len--) { + if (*p != ' ') + continue; + if (p > ptr) { + if (check_domain_name(ptr, p - ptr, dots) != 0) + return -1; + ret = 0; + } + ptr = p + 1; + } + if (p > ptr) + return check_domain_name(ptr, p - ptr, dots); + else + return ret; +} + +static int check_option_values( struct universe *universe, + unsigned int opt, + const char *ptr, + size_t len) +{ + if( !ptr) + return -1; + + /* just reject options we want to protect, will be escaped anyway */ + if ((universe == NULL) || (universe == &dhcp_universe)) { + switch(opt) { + case DHO_HOST_NAME: + case DHO_DOMAIN_NAME: + case DHO_NIS_DOMAIN: + case DHO_NETBIOS_SCOPE: + return check_domain_name(ptr, len, 0); + break; + case DHO_DOMAIN_SEARCH: + return check_domain_name_list(ptr, len, 0); + break; + case DHO_ROOT_PATH: + if( len == 0) + return -1; + for (; *ptr && len-- > 0; ptr++) { + if( !(isalnum((unsigned char)*ptr) || + *ptr == '#' || *ptr == '%' || + *ptr == '+' || *ptr == '-' || + *ptr == '_' || *ptr == ':' || + *ptr == '.' || *ptr == ',' || + *ptr == '@' || *ptr == '~' || + *ptr == '\\' || *ptr == '/' || + *ptr == ' ')) + return -1; + } + return 0; + break; + } + } + return 0; +} + --- client/scripts/linux +++ client/scripts/linux 2011/03/31 13:31:47 @@ -284,22 +284,34 @@ if [ x$reason = xBOUND ] || [ x$reason = /etc/sysconfig/network/dhcp 2>/dev/null` fi if [ "$DHCLIENT_SET_HOSTNAME" = yes ] ; then + rx_host='^[[:alnum:]][[:alnum:]_-]{0,62}$' + + new_host_name="${new_host_name%%.*}" + [[ ${new_host_name} =~ ${rx_host} ]] || unset new_host_name + current_hostname=`hostname` - if [ "x${current_hostname%%.*}" = x ] || \ - [ "x${current_hostname%%.*}" != "x${new_host_name%%.*}" ]; then + current_hostname="${current_hostname%%.*}" + [[ ${current_hostname} =~ ${rx_host} ]] || unset current_hostname - if [ "x${new_host_name%%.*}" != x ]; then - hostname "${new_host_name%%.*}" + if [ "x${current_hostname}" = "x" ] || \ + [ "x${current_hostname}" = "xlocalhost" ] || \ + [ "x${current_hostname}" != "x${new_host_name}" ]; then + + if [ "x${new_host_name}" != "x" ]; then + hostname "${new_host_name}" else if [ -x /usr/bin/host ] ; then if out=`host -W 2 "$new_ip_address" 2>/dev/null` ; then - _hostname="`echo "$out" | sed 's:^.* ::; s:\..*::'`" - if [ "x${_hostname}" != x ]; then + _hostname="`echo "$out" | sed 's:^.* ::; s:\..*::; s:.*[)]::'`" + [[ ${_hostname} =~ ${rx_host} ]] || unset _hostname + if [ "x${_hostname}" != "x" -a \ + "x${_hostname}" != "x${current_hostname}" ]; then hostname "${_hostname}" fi fi fi fi + fi fi --- common/options.c +++ common/options.c 2011/03/31 13:28:59 @@ -2943,7 +2943,8 @@ pretty_escape(char **dst, char *dend, co count += 4; } } else if (**src == '"' || **src == '\'' || **src == '$' || - **src == '`' || **src == '\\') { + **src == '`' || **src == '\\' || **src == '|' || + **src == '&' || **src == ';') { if (*dst + 2 > dend) return -1; ++++++ dhcp-3.1.2p1-dhclient-script.bnc673792.diff ++++++ --- client/scripts/linux +++ client/scripts/linux 2011/03/31 13:22:58 @@ -221,7 +221,7 @@ if [ x$reason = xBOUND ] || [ x$reason = if grep -qs '^primary=yes' /dev/shm/sysconfig/if-${interface} 2>/dev/null ; then eval `grep --no-filename '^[[:space:]]*DHCLIENT_SET_DEFAULT_ROUTE=' \ - /etc/sysconfig/network/dhcp + /etc/sysconfig/network/dhcp \ /etc/sysconfig/network/ifcfg-${interface} 2>/dev/null` else eval `grep --no-filename '^[[:space:]]*DHCLIENT_SET_DEFAULT_ROUTE=' \ @@ -273,7 +273,7 @@ if [ x$reason = xBOUND ] || [ x$reason = if grep -qs '^primary=yes' /dev/shm/sysconfig/if-${interface} 2>/dev/null ; then eval `grep --no-filename "^[[:space:]]*DHCLIENT_SET_HOSTNAME=" \ - /etc/sysconfig/network/dhcp + /etc/sysconfig/network/dhcp \ /etc/sysconfig/network/ifcfg-${interface} 2>/dev/null` else eval `grep --no-filename "^[[:space:]]*DHCLIENT_SET_HOSTNAME=" \ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Remember to have fun... -- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
