--- Begin Message ---
Package: krb5
Version: 1.8.3+dfsg-4
Severity: normal
Tags: patch
User: ubuntu-de...@lists.ubuntu.com
Usertags: origin-ubuntu natty ubuntu-patch
Attached patches are taken from
http://web.mit.edu/Kerberos/advisories/MITKRB5-SA-2011-001.txt and
http://web.mit.edu/Kerberos/advisories/MITKRB5-SA-2011-002.txt which fix
CVE-2010-4022, CVE-2011-0281, and CVE-2011-0282. (CVE-2011-0283
only applies to krb5 1.9.x.)
Thanks!
*** /home/steve/tmp/tmpJ0rjIg
In Ubuntu, we've applied the attached patch to achieve the following:
* SECURITY UPDATE: kpropd denial of service via invalid network input
- src/slave/kpropd.c: don't return on kpropd child exit; applied
inline.
- CVE-2010-4022
- MITKRB5-SA-2011-001
* SECURITY UPDATE: kdc denial of service from unauthenticated remote
attackers
- src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h,
src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c,
src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c,
src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:
applied inline
- CVE-2011-0281
- CVE-2011-0282
- MITKRB5-SA-2011-002
We thought you might be interested in doing the same.
-- System Information:
Debian Release: squeeze/sid
APT prefers maverick-updates
APT policy: (500, 'maverick-updates'), (500, 'maverick-security'), (500,
'maverick-proposed'), (500, 'maverick')
Architecture: amd64 (x86_64)
Kernel: Linux 2.6.35-24-server (SMP w/4 CPU cores)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
diff -u krb5-1.8.3+dfsg/src/slave/kpropd.c krb5-1.8.3+dfsg/src/slave/kpropd.c
--- krb5-1.8.3+dfsg/src/slave/kpropd.c
+++ krb5-1.8.3+dfsg/src/slave/kpropd.c
@@ -398,11 +398,11 @@
}
close(s);
- if (iproprole == IPROP_SLAVE)
+ if (iproprole == IPROP_SLAVE) {
close(finet);
-
- if ((ret = WEXITSTATUS(status)) != 0)
- return (ret);
+ if ((ret = WEXITSTATUS(status)) != 0)
+ return (ret);
+ }
}
if (iproprole == IPROP_SLAVE)
break;
only in patch2:
unchanged:
--- krb5-1.8.3+dfsg.orig/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c
+++ krb5-1.8.3+dfsg/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c
@@ -103,10 +103,10 @@
unsigned int flags, krb5_db_entry *entries,
int *nentries, krb5_boolean *more)
{
- char *user=NULL, *filter=NULL, **subtree=NULL;
+ char *user=NULL, *filter=NULL, *filtuser=NULL;
unsigned int tree=0, ntrees=1, princlen=0;
krb5_error_code tempst=0, st=0;
- char **values=NULL, *cname=NULL;
+ char **values=NULL, **subtree=NULL, *cname=NULL;
LDAP *ld=NULL;
LDAPMessage *result=NULL, *ent=NULL;
krb5_ldap_context *ldap_context=NULL;
@@ -142,12 +142,18 @@
if ((st=krb5_ldap_unparse_principal_name(user)) != 0)
goto cleanup;
- princlen = strlen(FILTER) + strlen(user) + 2 + 1; /* 2 for closing brackets */
+ filtuser = ldap_filter_correct(user);
+ if (filtuser == NULL) {
+ st = ENOMEM;
+ goto cleanup;
+ }
+
+ princlen = strlen(FILTER) + strlen(filtuser) + 2 + 1; /* 2 for closing brackets */
if ((filter = malloc(princlen)) == NULL) {
st = ENOMEM;
goto cleanup;
}
- snprintf(filter, princlen, FILTER"%s))", user);
+ snprintf(filter, princlen, FILTER"%s))", filtuser);
if ((st = krb5_get_subtree_info(ldap_context, &subtree, &ntrees)) != 0)
goto cleanup;
@@ -231,6 +237,9 @@
if (user)
free(user);
+ if (filtuser)
+ free(filtuser);
+
if (cname)
free(cname);
only in patch2:
unchanged:
--- krb5-1.8.3+dfsg.orig/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h
+++ krb5-1.8.3+dfsg/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h
@@ -102,14 +102,18 @@
#define LDAP_SEARCH(base, scope, filter, attrs) LDAP_SEARCH_1(base, scope, filter, attrs, CHECK_STATUS)
#define LDAP_SEARCH_1(base, scope, filter, attrs, status_check) \
- do { \
- st = ldap_search_ext_s(ld, base, scope, filter, attrs, 0, NULL, NULL, &timelimit, LDAP_NO_LIMIT, &result); \
- if (translate_ldap_error(st, OP_SEARCH) == KRB5_KDB_ACCESS_ERROR) { \
- tempst = krb5_ldap_rebind(ldap_context, &ldap_server_handle); \
- if (ldap_server_handle) \
- ld = ldap_server_handle->ldap_handle; \
- } \
- }while (translate_ldap_error(st, OP_SEARCH) == KRB5_KDB_ACCESS_ERROR && tempst == 0); \
+ tempst = 0; \
+ st = ldap_search_ext_s(ld, base, scope, filter, attrs, 0, NULL, \
+ NULL, &timelimit, LDAP_NO_LIMIT, &result); \
+ if (translate_ldap_error(st, OP_SEARCH) == KRB5_KDB_ACCESS_ERROR) { \
+ tempst = krb5_ldap_rebind(ldap_context, &ldap_server_handle); \
+ if (ldap_server_handle) \
+ ld = ldap_server_handle->ldap_handle; \
+ if (tempst == 0) \
+ st = ldap_search_ext_s(ld, base, scope, filter, attrs, 0, \
+ NULL, NULL, &timelimit, \
+ LDAP_NO_LIMIT, &result); \
+ } \
\
if (status_check != IGNORE_STATUS) { \
if (tempst != 0) { \
only in patch2:
unchanged:
--- krb5-1.8.3+dfsg.orig/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c
+++ krb5-1.8.3+dfsg/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c
@@ -302,6 +302,7 @@
{
krb5_ldap_server_handle *handle = *ldap_server_handle;
+ ldap_unbind_ext_s(handle->ldap_handle, NULL, NULL);
if ((ldap_initialize(&handle->ldap_handle, handle->server_info->server_name) != LDAP_SUCCESS)
|| (krb5_ldap_bind(ldap_context, handle) != LDAP_SUCCESS))
return krb5_ldap_request_next_handle_from_pool(ldap_context, ldap_server_handle);
only in patch2:
unchanged:
--- krb5-1.8.3+dfsg.orig/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c
+++ krb5-1.8.3+dfsg/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c
@@ -446,12 +446,11 @@
* portion, then the first portion of the principal name SHOULD be
* "krbtgt". All this check is done in the immediate block.
*/
- if (searchfor->length == 2)
- if ((strncasecmp(searchfor->data[0].data, "krbtgt",
- FIND_MAX(searchfor->data[0].length, strlen("krbtgt"))) == 0) &&
- (strncasecmp(searchfor->data[1].data, defrealm,
- FIND_MAX(searchfor->data[1].length, defrealmlen)) == 0))
+ if (searchfor->length == 2) {
+ if (data_eq_string(searchfor->data[0], "krbtgt") &&
+ data_eq_string(searchfor->data[1], defrealm))
return 0;
+ }
/* first check the length, if they are not equal, then they are not same */
if (strlen(defrealm) != searchfor->realm.length)
only in patch2:
unchanged:
--- krb5-1.8.3+dfsg.orig/debian/patches/krb5-2011-001-patch
+++ krb5-1.8.3+dfsg/debian/patches/krb5-2011-001-patch
@@ -0,0 +1,31 @@
+Subject: kpropd denial of service
+Origin: upstream, http://web.mit.edu/Kerberos/advisories/MITKRB5-SA-2011-001.txt
+
+The MIT krb5 KDC database propagation daemon (kpropd) is vulnerable to
+a denial-of-service attack triggered by invalid network input. If a
+kpropd worker process receives invalid input that causes it to exit
+with an abnormal status, it can cause the termination of the listening
+process that spawned it, preventing the slave KDC it was running on
+from receiving database updates from the master KDC.
+
+CVE-2010-4022
+
+diff -up krb5/src/slave/kpropd.c krb5/src/slave/kpropd.c
+--- krb5/src/slave/kpropd.c 2010-12-17 11:14:26.000000000 -0500
++++ krb5/src/slave/kpropd.c 2010-12-17 11:41:19.000000000 -0500
+@@ -404,11 +404,11 @@ retry:
+ }
+
+ close(s);
+- if (iproprole == IPROP_SLAVE)
++ if (iproprole == IPROP_SLAVE) {
+ close(finet);
+-
+- if ((ret = WEXITSTATUS(status)) != 0)
+- return (ret);
++ if ((ret = WEXITSTATUS(status)) != 0)
++ return (ret);
++ }
+ }
+ if (iproprole == IPROP_SLAVE)
+ break;
only in patch2:
unchanged:
--- krb5-1.8.3+dfsg.orig/debian/patches/krb5-2011-002-r18-patch
+++ krb5-1.8.3+dfsg/debian/patches/krb5-2011-002-r18-patch
@@ -0,0 +1,127 @@
+Subject: krb5 Key Distribution Center (KDC) daemon DoS
+Origin: upstream, http://web.mit.edu/Kerberos/advisories/MITKRB5-SA-2011-002.txt
+
+The MIT krb5 Key Distribution Center (KDC) daemon is vulnerable to
+denial of service attacks from unauthenticated remote attackers.
+CVE-2011-0281 and CVE-2011-0282 occur only in KDCs using LDAP back
+ends, but CVE-2011-0283 occurs in all krb5-1.9 KDCs.
+
+Exploit code is not known to exist, but the vulnerabilities are easy
+to trigger manually. The trigger for CVE-2011-0281 has already been
+disclosed publicly, but that fact might not be obvious to casual
+readers of the message in which it was disclosed. The triggers for
+CVE-2011-0282 and CVE-2011-0283 have not yet been disclosed publicly,
+but they are also trivial.
+
+diff --git a/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h b/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h
+index 1ca09b4..60caf3d 100644
+--- a/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h
++++ b/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h
+@@ -102,14 +102,18 @@ extern void prepend_err_str (krb5_context ctx, const char *s, krb5_error_code er
+ #define LDAP_SEARCH(base, scope, filter, attrs) LDAP_SEARCH_1(base, scope, filter, attrs, CHECK_STATUS)
+
+ #define LDAP_SEARCH_1(base, scope, filter, attrs, status_check) \
+- do { \
+- st = ldap_search_ext_s(ld, base, scope, filter, attrs, 0, NULL, NULL, &timelimit, LDAP_NO_LIMIT, &result); \
+- if (translate_ldap_error(st, OP_SEARCH) == KRB5_KDB_ACCESS_ERROR) { \
+- tempst = krb5_ldap_rebind(ldap_context, &ldap_server_handle); \
+- if (ldap_server_handle) \
+- ld = ldap_server_handle->ldap_handle; \
+- } \
+- }while (translate_ldap_error(st, OP_SEARCH) == KRB5_KDB_ACCESS_ERROR && tempst == 0); \
++ tempst = 0; \
++ st = ldap_search_ext_s(ld, base, scope, filter, attrs, 0, NULL, \
++ NULL, &timelimit, LDAP_NO_LIMIT, &result); \
++ if (translate_ldap_error(st, OP_SEARCH) == KRB5_KDB_ACCESS_ERROR) { \
++ tempst = krb5_ldap_rebind(ldap_context, &ldap_server_handle); \
++ if (ldap_server_handle) \
++ ld = ldap_server_handle->ldap_handle; \
++ if (tempst == 0) \
++ st = ldap_search_ext_s(ld, base, scope, filter, attrs, 0, \
++ NULL, NULL, &timelimit, \
++ LDAP_NO_LIMIT, &result); \
++ } \
+ \
+ if (status_check != IGNORE_STATUS) { \
+ if (tempst != 0) { \
+diff --git a/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c b/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c
+index 82b0333..84e80ee 100644
+--- a/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c
++++ b/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c
+@@ -302,6 +302,7 @@ krb5_ldap_rebind(krb5_ldap_context *ldap_context,
+ {
+ krb5_ldap_server_handle *handle = *ldap_server_handle;
+
++ ldap_unbind_ext_s(handle->ldap_handle, NULL, NULL);
+ if ((ldap_initialize(&handle->ldap_handle, handle->server_info->server_name) != LDAP_SUCCESS)
+ || (krb5_ldap_bind(ldap_context, handle) != LDAP_SUCCESS))
+ return krb5_ldap_request_next_handle_from_pool(ldap_context, ldap_server_handle);
+diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c
+index f549e23..b70940f 100644
+--- a/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c
++++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c
+@@ -446,12 +446,11 @@ is_principal_in_realm(krb5_ldap_context *ldap_context,
+ * portion, then the first portion of the principal name SHOULD be
+ * "krbtgt". All this check is done in the immediate block.
+ */
+- if (searchfor->length == 2)
+- if ((strncasecmp(searchfor->data[0].data, "krbtgt",
+- FIND_MAX(searchfor->data[0].length, strlen("krbtgt"))) == 0) &&
+- (strncasecmp(searchfor->data[1].data, defrealm,
+- FIND_MAX(searchfor->data[1].length, defrealmlen)) == 0))
++ if (searchfor->length == 2) {
++ if (data_eq_string(searchfor->data[0], "krbtgt") &&
++ data_eq_string(searchfor->data[1], defrealm))
+ return 0;
++ }
+
+ /* first check the length, if they are not equal, then they are not same */
+ if (strlen(defrealm) != searchfor->realm.length)
+diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c
+index 7ad31da..626ed1f 100644
+--- a/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c
++++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c
+@@ -103,10 +103,10 @@ krb5_ldap_get_principal(krb5_context context, krb5_const_principal searchfor,
+ unsigned int flags, krb5_db_entry *entries,
+ int *nentries, krb5_boolean *more)
+ {
+- char *user=NULL, *filter=NULL, **subtree=NULL;
++ char *user=NULL, *filter=NULL, *filtuser=NULL;
+ unsigned int tree=0, ntrees=1, princlen=0;
+ krb5_error_code tempst=0, st=0;
+- char **values=NULL, *cname=NULL;
++ char **values=NULL, **subtree=NULL, *cname=NULL;
+ LDAP *ld=NULL;
+ LDAPMessage *result=NULL, *ent=NULL;
+ krb5_ldap_context *ldap_context=NULL;
+@@ -142,12 +142,18 @@ krb5_ldap_get_principal(krb5_context context, krb5_const_principal searchfor,
+ if ((st=krb5_ldap_unparse_principal_name(user)) != 0)
+ goto cleanup;
+
+- princlen = strlen(FILTER) + strlen(user) + 2 + 1; /* 2 for closing brackets */
++ filtuser = ldap_filter_correct(user);
++ if (filtuser == NULL) {
++ st = ENOMEM;
++ goto cleanup;
++ }
++
++ princlen = strlen(FILTER) + strlen(filtuser) + 2 + 1; /* 2 for closing brackets */
+ if ((filter = malloc(princlen)) == NULL) {
+ st = ENOMEM;
+ goto cleanup;
+ }
+- snprintf(filter, princlen, FILTER"%s))", user);
++ snprintf(filter, princlen, FILTER"%s))", filtuser);
+
+ if ((st = krb5_get_subtree_info(ldap_context, &subtree, &ntrees)) != 0)
+ goto cleanup;
+@@ -231,6 +237,9 @@ cleanup:
+ if (user)
+ free(user);
+
++ if (filtuser)
++ free(filtuser);
++
+ if (cname)
+ free(cname);
+
--- End Message ---