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); +