diff --git a/dhcp-4.2.1-P1-dhclient-option-checks.bnc675052.diff b/dhcp-4.2.1-P1-dhclient-option-checks.bnc675052.diff new file mode 100644 index 0000000..f4210ee --- /dev/null +++ b/dhcp-4.2.1-P1-dhclient-option-checks.bnc675052.diff @@ -0,0 +1,77 @@ +From 7c0b7ae289a0f25853bd4bb660f3dd34b5c1ce88 Mon Sep 17 00:00:00 2001 +From: Marius Tomaschewski +Date: Wed, 27 Apr 2011 13:56:47 +0200 +Subject: [PATCH] dhclient string option checks + +Merged dhclient pretty escape and string option checks. +Use relaxed domain-name option check causing a regression, when the +server is misusing it to provide a domain list and does not provide +it via the domain-search option; pretty escape semicolon as well +(bnc#675052, CVE-2011-0997). + +Signed-off-by: Marius Tomaschewski +--- + client/dhclient.c | 8 ++++---- + common/options.c | 2 +- + 2 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/client/dhclient.c b/client/dhclient.c +index 970b935..93db494 100644 +--- a/client/dhclient.c ++++ b/client/dhclient.c +@@ -3142,7 +3142,7 @@ void script_write_params (client, prefix, lease) + } else { + log_error("suspect value in %s " + "option - discarded", +- lease->filename); ++ "filename"); + } + } + +@@ -3155,7 +3155,7 @@ void script_write_params (client, prefix, lease) + } else { + log_error("suspect value in %s " + "option - discarded", +- lease->server_name); ++ "server-name"); + } + } + +@@ -4077,7 +4077,7 @@ 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)) ++ if ((len == 0) || (len >= 256)) + return(-1); + + /* consists of [[:alnum:]-]+ labels separated by [.] */ +@@ -4140,11 +4140,11 @@ static int check_option_values(struct universe *universe, + 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_NAME: /* accept a list for compatibiliy */ + case DHO_DOMAIN_SEARCH: + return check_domain_name_list(ptr, len, 0); + break; +diff --git a/common/options.c b/common/options.c +index c26f88c..8b4be65 100644 +--- a/common/options.c ++++ b/common/options.c +@@ -3916,7 +3916,7 @@ pretty_escape(char **dst, char *dend, const unsigned char **src, + } + } else if (**src == '"' || **src == '\'' || **src == '$' || + **src == '`' || **src == '\\' || **src == '|' || +- **src == '&') { ++ **src == '&' || **src == ';') { + if (*dst + 2 > dend) + return -1; + +-- +1.7.3.4 + diff --git a/dhcp-4.2.1-P1-ldap-patch-mt01.diff.bz2 b/dhcp-4.2.1-P1-ldap-patch-mt01.diff.bz2 new file mode 100644 index 0000000..d7cb6ba --- /dev/null +++ b/dhcp-4.2.1-P1-ldap-patch-mt01.diff.bz2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6f1458dc06686ad2c80111f09d1ffc61f0f7feecbd9e693bdc55904a35708608 +size 11461 diff --git a/dhcp-4.2.1-P1.tar.bz2 b/dhcp-4.2.1-P1.tar.bz2 new file mode 100644 index 0000000..b0e4b27 --- /dev/null +++ b/dhcp-4.2.1-P1.tar.bz2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cb8e19d01c5ab5de1da759c3fb34e4967e863e78c8d6106d2cbb0ffeaa80df76 +size 8659247 diff --git a/dhcp-4.2.1-dhclient-option-checks.bnc675052.diff b/dhcp-4.2.1-dhclient-option-checks.bnc675052.diff deleted file mode 100644 index 99d948b..0000000 --- a/dhcp-4.2.1-dhclient-option-checks.bnc675052.diff +++ /dev/null @@ -1,248 +0,0 @@ -From 632c8ceeff26a7663f939895f77aecb8377773f2 Mon Sep 17 00:00:00 2001 -From: Marius Tomaschewski -Date: Sun, 27 Mar 2011 13:15:58 +0200 -Subject: [PATCH] dhclient: discard incorrect string options - -Discard string options such as host and domain names -containing disallowed characters or beeing too long. -This proctive patch limits root-path to the a-zA-Z0-9, -space and the #%+-_:.,@~/\[]= characters. - -Signed-off-by: Marius Tomaschewski ---- - client/dhclient.c | 186 +++++++++++++++++++++++++++++++++++++++++++++++++---- - common/options.c | 3 +- - 2 files changed, 175 insertions(+), 14 deletions(-) - -diff --git a/client/dhclient.c b/client/dhclient.c -index dc19e8b..5d96c72 100644 ---- a/client/dhclient.c -+++ b/client/dhclient.c -@@ -91,6 +91,11 @@ static void usage(void); - - static isc_result_t write_duid(struct data_string *duid); - -+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(int argc, char **argv) { - int fd; -@@ -3034,13 +3039,23 @@ void client_option_envadd (struct option_cache *oc, - if (data.len) { - 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))); -+ oc->option)) { -+ const char *value; -+ 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); - } - } -@@ -3118,12 +3133,32 @@ void script_write_params (client, prefix, lease) - 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, -@@ -4026,3 +4061,128 @@ dhcpv4_client_assignments(void) - } else - remote_port = htons (ntohs (local_port) - 1); /* XXX */ - } -+ -+/* -+ * The following routines are used to check that certain -+ * strings are reasonable before we pass them to the scripts. -+ * This avoids some problems with scripts treating the strings -+ * as commands - see ticket 23722 -+ * The domain checking code should be done as part of assembling -+ * the string but we are doing it here for now due to time -+ * constraints. -+ */ -+ -+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 != 0) && (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.') */ -+ size_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) == 0) { -+ /* 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 == NULL) || (len == 0)) -+ return(-1); -+ -+ for (p=ptr; (*p != 0) && (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 == NULL) -+ 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 != 0) && (len-- > 0); ptr++) { -+ if(!(isalnum((unsigned char)*ptr) || -+ *ptr == '#' || *ptr == '%' || -+ *ptr == '+' || *ptr == '-' || -+ *ptr == '_' || *ptr == ':' || -+ *ptr == '.' || *ptr == ',' || -+ *ptr == '@' || *ptr == '~' || -+ *ptr == '\\' || *ptr == '/' || -+ *ptr == '[' || *ptr == ']' || -+ *ptr == '=' || *ptr == ' ')) -+ return(-1); -+ } -+ return(0); -+ break; -+ } -+ } -+ -+#ifdef DHCPv6 -+ if (universe == &dhcpv6_universe) { -+ switch(opt) { -+ case D6O_SIP_SERVERS_DNS: -+ case D6O_DOMAIN_SEARCH: -+ case D6O_NIS_DOMAIN_NAME: -+ case D6O_NISP_DOMAIN_NAME: -+ return check_domain_name_list(ptr, len, 0); -+ break; -+ } -+ } -+#endif -+ -+ return(0); -+} -+ -+ -+ -diff --git a/common/options.c b/common/options.c -index 28c36e6..3a6cb33 100644 ---- a/common/options.c -+++ b/common/options.c -@@ -3915,7 +3915,8 @@ pretty_escape(char **dst, char *dend, const unsigned char **src, - count += 4; - } - } else if (**src == '"' || **src == '\'' || **src == '$' || -- **src == '`' || **src == '\\') { -+ **src == '`' || **src == '\\' || **src == '|' || -+ **src == '&' || **src == ';') { - if (*dst + 2 > dend) - return -1; - --- -1.7.3.4 - diff --git a/dhcp-4.2.1-ldap-patch-mt01.diff.bz2 b/dhcp-4.2.1-ldap-patch-mt01.diff.bz2 deleted file mode 100644 index c4e4828..0000000 --- a/dhcp-4.2.1-ldap-patch-mt01.diff.bz2 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5d5a0f6d8570eda14268c48207f6df9c0360ddf2e91de50676e6e6d9a8df3d82 -size 10234 diff --git a/dhcp-4.2.1.tar.bz2 b/dhcp-4.2.1.tar.bz2 deleted file mode 100644 index 09becf6..0000000 --- a/dhcp-4.2.1.tar.bz2 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:172851e0eedbbb009142b143a5f1ed9d6d370d909475a356ac9a753c15c354e9 -size 8656089 diff --git a/dhcp.changes b/dhcp.changes index 0423d76..913940a 100644 --- a/dhcp.changes +++ b/dhcp.changes @@ -1,3 +1,22 @@ +------------------------------------------------------------------- +Fri Apr 29 13:31:57 UTC 2011 - mt@suse.de + +- Implemented optional ldap connect retry loop during the initial + startup of the dhcp server in cases where the ldap server is not + yet started. Set the ldap-init-retry option in dhcpd.conf + to enable it (bnc#627617). Merged in the actual ldap patch. +- Cleaned up init script error reporting, no -TERM for killproc. + +------------------------------------------------------------------- +Wed Apr 27 12:31:25 UTC 2011 - mt@suse.de + +- Updated to ISC dhcp-4.2.1-P1 release, that provides most of the + dhclient pretty escape and string option checks. Merged to use + relaxed domain-name option check causing a regression, when the + server is misusing it to provide a domain list (compatibility to + attic clients) and does not provide it via domain-search option; + pretty escape semicolon as well (bnc#675052, CVE-2011-0997). + ------------------------------------------------------------------- Thu Mar 31 09:56:02 UTC 2011 - mt@suse.de diff --git a/dhcp.spec b/dhcp.spec index 47693d3..5099e95 100644 --- a/dhcp.spec +++ b/dhcp.spec @@ -17,7 +17,7 @@ # norootforbuild -%define isc_version 4.2.1 +%define isc_version 4.2.1-P1 %define susefw2dir %{_sysconfdir}/sysconfig/SuSEfirewall2.d/services %define omc_prefix /usr/share/omc %define omc_svcdir %{omc_prefix}/svcinfo.d @@ -35,8 +35,8 @@ BuildRequires: dos2unix License: BSD3c(or similar) Group: Productivity/Networking/Boot/Servers AutoReqProv: on -Version: 4.2.1 -Release: 1 +Version: 4.2.1.P1 +Release: 0 Summary: Common Files Used by ISC DHCP Software Url: http://www.isc.org/software/dhcp Source0: dhcp-%{isc_version}.tar.bz2 @@ -78,11 +78,11 @@ Patch15: contrib-lease-path.diff Patch20: dhcp-4.1.1-dhclient-exec-filedes.diff Patch21: dhcp-4.2.1-dhclient-send-hostname-rml.diff ## patch lives here: http://www.suse.de/~mt/git/dhcp-ldap.git/ -Patch30: dhcp-4.2.1-ldap-patch-mt01.diff.bz2 +Patch30: dhcp-4.2.1-P1-ldap-patch-mt01.diff.bz2 Patch40: dhcp-4.1.1-P1-lpf-bind-msg-fix.diff Patch41: dhcp-4.1.1-P1-relay-no-ip-on-interface.diff Patch44: dhcp-4.2.0-xen-checksum.patch -Patch45: dhcp-4.2.1-dhclient-option-checks.bnc675052.diff +Patch45: dhcp-4.2.1-P1-dhclient-option-checks.bnc675052.diff ## PreReq: /bin/touch /sbin/chkconfig sysconfig BuildRoot: %{_tmppath}/%{name}-%{version}-build @@ -372,7 +372,6 @@ if [ ${FIRST_ARG:-0} -gt 1 ]; then rm -f $tmpfile fi fi -exit 0 %preun server %stop_on_removal dhcpd diff --git a/rc.dhcpd b/rc.dhcpd index 3e109e0..5cdb21a 100644 --- a/rc.dhcpd +++ b/rc.dhcpd @@ -280,8 +280,10 @@ case "$1" in ret=$? fi - if [ $error -gt 0 -o ${ret:-0} -gt 0 ]; then - cat $STARTPROC_LOGFILE + if [ $error -gt 0 -o ${ret:-0} -gt 0 ]; then + ## be verbose + echo "" + echo -n " please see $STARTPROC_LOGFILE for details "; ## set status to failed rc_failed else @@ -297,7 +299,7 @@ case "$1" in ## Stop daemon with killproc(8) and if this fails ## set echo the echo return value. - killproc -p $CHROOT_PREFIX/$DAEMON_PIDFILE -TERM $DAEMON_BIN + killproc -p $CHROOT_PREFIX/$DAEMON_PIDFILE $DAEMON_BIN ret=$? if test -s $CHROOT_PREFIX/$DAEMON_PIDFILE; then kill $(<$CHROOT_PREFIX/$DAEMON_PIDFILE) 2>/dev/null diff --git a/rc.dhcpd6 b/rc.dhcpd6 index a6ebd7a..9c7a34e 100644 --- a/rc.dhcpd6 +++ b/rc.dhcpd6 @@ -285,7 +285,9 @@ case "$1" in fi if [ $error -gt 0 -o ${ret:-0} -gt 0 ]; then - cat $STARTPROC_LOGFILE + ## be verbose + echo "" + echo -n " please see $STARTPROC_LOGFILE for details " ## set status to failed rc_failed else @@ -301,7 +303,7 @@ case "$1" in ## Stop daemon with killproc(8) and if this fails ## set echo the echo return value. - killproc -p $CHROOT_PREFIX/$DAEMON_PIDFILE -TERM $DAEMON_BIN + killproc -p $CHROOT_PREFIX/$DAEMON_PIDFILE $DAEMON_BIN ret=$? if test -s $CHROOT_PREFIX/$DAEMON_PIDFILE; then kill $(<$CHROOT_PREFIX/$DAEMON_PIDFILE) 2>/dev/null diff --git a/rc.dhcrelay b/rc.dhcrelay index 01f0100..56fea3a 100644 --- a/rc.dhcrelay +++ b/rc.dhcrelay @@ -105,16 +105,12 @@ case "$1" in # already running to match LSB spec. test "$2" = "-v" && echo -en \ "\nexecuting '$DAEMON_BIN $DHCPv_OPT $DHCRELAY_OPTIONS $DHCRELAY_INTERFACES_ARGS $DHCRELAY_SERVERS'" - startproc -q -l $STARTPROC_LOGFILE -p $DAEMON_PIDFILE $DAEMON_BIN $DHCPv_OPT $DHCRELAY_OPTIONS $DHCRELAY_INTERFACES_ARGS $DHCRELAY_SERVERS + startproc -q -l $STARTPROC_LOGFILE -p $DAEMON_PIDFILE $DAEMON_BIN $DHCPv_OPT $DHCRELAY_OPTIONS $DHCRELAY_INTERFACES_ARGS $DHCRELAY_SERVERS &>/dev/null rc=$? if ! [ $rc -eq 0 ]; then - if [ $link = $base ] ; then - ## be quiet - cat $STARTPROC_LOGFILE - else - ## be verbose - echo -e -n " please see $STARTPROC_LOGFILE for details "; - fi + ## be verbose + echo "" + echo -n " please see $STARTPROC_LOGFILE for details " ## set status to failed rc_failed fi @@ -127,7 +123,7 @@ case "$1" in ## Stop daemon with killproc(8) and if this fails ## set echo the echo return value. - killproc -p $DAEMON_PIDFILE -TERM $DAEMON_BIN + killproc -p $DAEMON_PIDFILE $DAEMON_BIN # Remember status and be verbose rc_status -v diff --git a/rc.dhcrelay6 b/rc.dhcrelay6 index 7d6964e..c5701ee 100644 --- a/rc.dhcrelay6 +++ b/rc.dhcrelay6 @@ -113,16 +113,12 @@ case "$1" in # already running to match LSB spec. test "$2" = "-v" && echo -en \ "\nexecuting '$DAEMON_BIN $DHCPv_OPT $DHCRELAY6_OPTIONS $DHCRELAY6_LOWER_INTERFACES_ARGS $DHCRELAY6_UPPER_INTERFACES_ARGS'" - startproc -q -l $STARTPROC_LOGFILE -p $DAEMON_PIDFILE $DAEMON_BIN $DHCPv_OPT $DHCRELAY6_OPTIONS $DHCRELAY6_LOWER_INTERFACES_ARGS $DHCRELAY6_UPPER_INTERFACES_ARGS + startproc -q -l $STARTPROC_LOGFILE -p $DAEMON_PIDFILE $DAEMON_BIN $DHCPv_OPT $DHCRELAY6_OPTIONS $DHCRELAY6_LOWER_INTERFACES_ARGS $DHCRELAY6_UPPER_INTERFACES_ARGS &>/dev/null rc=$? if ! [ $rc -eq 0 ]; then - if [ $link = $base ] ; then - ## be quiet - cat $STARTPROC_LOGFILE - else - ## be verbose - echo -e -n " please see $STARTPROC_LOGFILE for details "; - fi + ## be verbose + echo "" + echo -n " please see $STARTPROC_LOGFILE for details "; ## set status to failed rc_failed fi @@ -135,7 +131,7 @@ case "$1" in ## Stop daemon with killproc(8) and if this fails ## set echo the echo return value. - killproc -p $DAEMON_PIDFILE -TERM $DAEMON_BIN + killproc -p $DAEMON_PIDFILE $DAEMON_BIN # Remember status and be verbose rc_status -v