diff --git a/Add-function-and-enctype-flag-for-deprecations.patch b/Add-function-and-enctype-flag-for-deprecations.patch new file mode 100644 index 0000000..9fee971 --- /dev/null +++ b/Add-function-and-enctype-flag-for-deprecations.patch @@ -0,0 +1,185 @@ +From 7b4e3ebc438ec0263b4b7b45a0ad39809699bbec Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Tue, 15 Jan 2019 16:16:57 -0500 +Subject: [PATCH] Add function and enctype flag for deprecations + +krb5int_c_deprecated_enctype() checks for the ETYPE_DEPRECATED flag on +enctypes. All ENCTYPE_WEAK enctypes are currently deprecated; not all +deprecated enctypes are considered weak. Deprecations follow RFC 6649 +and RFC 8429. + +(cherry picked from commit 484a6e7712f9b66e782b2520f07b0883889e116f) +(cherry picked from commit e0c8eb1bf93e0591e363e414378c70c255a6e6b6) +[rharwood@redhat.com: krb5_32.def conflict] +--- + src/include/k5-int.h | 1 + + src/lib/crypto/krb/crypto_int.h | 9 ++++++++- + src/lib/crypto/krb/enctype_util.c | 7 +++++++ + src/lib/crypto/krb/etypes.c | 19 ++++++++++--------- + src/lib/crypto/libk5crypto.exports | 1 + + src/lib/krb5_32.def | 3 +++ + 6 files changed, 30 insertions(+), 10 deletions(-) + +diff --git a/src/include/k5-int.h b/src/include/k5-int.h +index e4a9a1412..c597f3b8a 100644 +--- a/src/include/k5-int.h ++++ b/src/include/k5-int.h +@@ -2076,6 +2076,7 @@ krb5_get_tgs_ktypes(krb5_context, krb5_const_principal, krb5_enctype **); + krb5_boolean krb5_is_permitted_enctype(krb5_context, krb5_enctype); + + krb5_boolean KRB5_CALLCONV krb5int_c_weak_enctype(krb5_enctype); ++krb5_boolean KRB5_CALLCONV krb5int_c_deprecated_enctype(krb5_enctype); + krb5_error_code k5_enctype_to_ssf(krb5_enctype enctype, unsigned int *ssf_out); + + krb5_error_code krb5_kdc_rep_decrypt_proc(krb5_context, const krb5_keyblock *, +diff --git a/src/lib/crypto/krb/crypto_int.h b/src/lib/crypto/krb/crypto_int.h +index e5099291e..6c1c77cac 100644 +--- a/src/lib/crypto/krb/crypto_int.h ++++ b/src/lib/crypto/krb/crypto_int.h +@@ -114,7 +114,14 @@ struct krb5_keytypes { + unsigned int ssf; + }; + +-#define ETYPE_WEAK 1 ++/* ++ * "Weak" means the enctype is believed to be vulnerable to practical attacks, ++ * and will be disabled unless allow_weak_crypto is set to true. "Deprecated" ++ * means the enctype has been deprecated by the IETF, and affects display and ++ * logging. ++ */ ++#define ETYPE_WEAK (1 << 0) ++#define ETYPE_DEPRECATED (1 << 1) + + extern const struct krb5_keytypes krb5int_enctypes_list[]; + extern const int krb5int_enctypes_length; +diff --git a/src/lib/crypto/krb/enctype_util.c b/src/lib/crypto/krb/enctype_util.c +index b1b40e7ec..e394f4e19 100644 +--- a/src/lib/crypto/krb/enctype_util.c ++++ b/src/lib/crypto/krb/enctype_util.c +@@ -51,6 +51,13 @@ krb5int_c_weak_enctype(krb5_enctype etype) + return (ktp != NULL && (ktp->flags & ETYPE_WEAK) != 0); + } + ++krb5_boolean KRB5_CALLCONV ++krb5int_c_deprecated_enctype(krb5_enctype etype) ++{ ++ const struct krb5_keytypes *ktp = find_enctype(etype); ++ return ktp != NULL && (ktp->flags & ETYPE_DEPRECATED) != 0; ++} ++ + krb5_error_code KRB5_CALLCONV + krb5_c_enctype_compare(krb5_context context, krb5_enctype e1, krb5_enctype e2, + krb5_boolean *similar) +diff --git a/src/lib/crypto/krb/etypes.c b/src/lib/crypto/krb/etypes.c +index 53d4a5c79..8f44c37e7 100644 +--- a/src/lib/crypto/krb/etypes.c ++++ b/src/lib/crypto/krb/etypes.c +@@ -33,6 +33,7 @@ + that the keytypes are all near each other. I'd rather not make + that assumption. */ + ++/* Deprecations come from RFC 6649 and RFC 8249. */ + const struct krb5_keytypes krb5int_enctypes_list[] = { + { ENCTYPE_DES_CBC_CRC, + "des-cbc-crc", { 0 }, "DES cbc mode with CRC-32", +@@ -42,7 +43,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = { + krb5int_des_string_to_key, k5_rand2key_des, + krb5int_des_prf, + CKSUMTYPE_RSA_MD5_DES, +- ETYPE_WEAK, 56 }, ++ ETYPE_WEAK | ETYPE_DEPRECATED, 56 }, + { ENCTYPE_DES_CBC_MD4, + "des-cbc-md4", { 0 }, "DES cbc mode with RSA-MD4", + &krb5int_enc_des, &krb5int_hash_md4, +@@ -51,7 +52,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = { + krb5int_des_string_to_key, k5_rand2key_des, + krb5int_des_prf, + CKSUMTYPE_RSA_MD4_DES, +- ETYPE_WEAK, 56 }, ++ ETYPE_WEAK | ETYPE_DEPRECATED, 56 }, + { ENCTYPE_DES_CBC_MD5, + "des-cbc-md5", { "des" }, "DES cbc mode with RSA-MD5", + &krb5int_enc_des, &krb5int_hash_md5, +@@ -60,7 +61,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = { + krb5int_des_string_to_key, k5_rand2key_des, + krb5int_des_prf, + CKSUMTYPE_RSA_MD5_DES, +- ETYPE_WEAK, 56 }, ++ ETYPE_WEAK | ETYPE_DEPRECATED, 56 }, + { ENCTYPE_DES_CBC_RAW, + "des-cbc-raw", { 0 }, "DES cbc mode raw", + &krb5int_enc_des, NULL, +@@ -69,7 +70,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = { + krb5int_des_string_to_key, k5_rand2key_des, + krb5int_des_prf, + 0, +- ETYPE_WEAK, 56 }, ++ ETYPE_WEAK | ETYPE_DEPRECATED, 56 }, + { ENCTYPE_DES3_CBC_RAW, + "des3-cbc-raw", { 0 }, "Triple DES cbc mode raw", + &krb5int_enc_des3, NULL, +@@ -78,7 +79,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = { + krb5int_dk_string_to_key, k5_rand2key_des3, + NULL, /*PRF*/ + 0, +- ETYPE_WEAK, 112 }, ++ ETYPE_WEAK | ETYPE_DEPRECATED, 112 }, + + { ENCTYPE_DES3_CBC_SHA1, + "des3-cbc-sha1", { "des3-hmac-sha1", "des3-cbc-sha1-kd" }, +@@ -89,7 +90,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = { + krb5int_dk_string_to_key, k5_rand2key_des3, + krb5int_dk_prf, + CKSUMTYPE_HMAC_SHA1_DES3, +- 0 /*flags*/, 112 }, ++ ETYPE_DEPRECATED, 112 }, + + { ENCTYPE_DES_HMAC_SHA1, + "des-hmac-sha1", { 0 }, "DES with HMAC/sha1", +@@ -99,7 +100,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = { + krb5int_dk_string_to_key, k5_rand2key_des, + NULL, /*PRF*/ + 0, +- ETYPE_WEAK, 56 }, ++ ETYPE_WEAK | ETYPE_DEPRECATED, 56 }, + + /* rc4-hmac uses a 128-bit key, but due to weaknesses in the RC4 cipher, we + * consider its strength degraded and assign it an SSF value of 64. */ +@@ -113,7 +114,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = { + krb5int_arcfour_decrypt, krb5int_arcfour_string_to_key, + k5_rand2key_direct, krb5int_arcfour_prf, + CKSUMTYPE_HMAC_MD5_ARCFOUR, +- 0 /*flags*/, 64 }, ++ ETYPE_DEPRECATED, 64 }, + { ENCTYPE_ARCFOUR_HMAC_EXP, + "arcfour-hmac-exp", { "rc4-hmac-exp", "arcfour-hmac-md5-exp" }, + "Exportable ArcFour with HMAC/md5", +@@ -124,7 +125,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = { + krb5int_arcfour_decrypt, krb5int_arcfour_string_to_key, + k5_rand2key_direct, krb5int_arcfour_prf, + CKSUMTYPE_HMAC_MD5_ARCFOUR, +- ETYPE_WEAK, 40 ++ ETYPE_WEAK | ETYPE_DEPRECATED, 40 + }, + + { ENCTYPE_AES128_CTS_HMAC_SHA1_96, +diff --git a/src/lib/crypto/libk5crypto.exports b/src/lib/crypto/libk5crypto.exports +index 82eb5f30c..90afdf5f7 100644 +--- a/src/lib/crypto/libk5crypto.exports ++++ b/src/lib/crypto/libk5crypto.exports +@@ -109,3 +109,4 @@ k5_allow_weak_pbkdf2iter + krb5_c_prfplus + krb5_c_derive_prfplus + k5_enctype_to_ssf ++krb5int_c_deprecated_enctype +diff --git a/src/lib/krb5_32.def b/src/lib/krb5_32.def +index f7b428e16..53fdbd916 100644 +--- a/src/lib/krb5_32.def ++++ b/src/lib/krb5_32.def +@@ -473,3 +473,6 @@ EXPORTS + + ; new in 1.16 + k5_enctype_to_ssf @438 ; PRIVATE GSSAPI ++ ++; new in 1.18 ++ krb5int_c_deprecated_enctype @450 ; PRIVATE diff --git a/Address-some-optimized-out-memset-calls.patch b/Address-some-optimized-out-memset-calls.patch new file mode 100644 index 0000000..f14cebc --- /dev/null +++ b/Address-some-optimized-out-memset-calls.patch @@ -0,0 +1,95 @@ +From 772178a22bc43df83bfa74992d55f99a5153c03e Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Sun, 30 Dec 2018 16:40:28 -0500 +Subject: [PATCH] Address some optimized-out memset() calls + +Ilja Van Sprundel reported a list of memset() calls which gcc +optimizes out. In krb_auth_su.c, use zap() to clear the password, and +remove two memset() calls when there is no password to clear. In +iakerb.c, remove an unnecessary memset() before setting the only two +fields of the IAKERB header structure. In svr_principal.c, use +krb5_free_key_keyblock_contents() instead of hand-freeing key data. +In asn1_k_encode.c, remove an unnecessary memset() of the kdc_req_hack +shell before returning. + +(cherry picked from commit 1057b0befec1f1c0e9d4da5521a58496e2dc0997) +(cherry picked from commit 0d83197140d2040d47ca79f006126e503680f661) +--- + src/clients/ksu/krb_auth_su.c | 4 +--- + src/lib/gssapi/krb5/iakerb.c | 1 - + src/lib/kadm5/srv/svr_principal.c | 10 ++-------- + src/lib/krb5/asn.1/asn1_k_encode.c | 1 - + 4 files changed, 3 insertions(+), 13 deletions(-) + +diff --git a/src/clients/ksu/krb_auth_su.c b/src/clients/ksu/krb_auth_su.c +index 7af48195c..e39685fff 100644 +--- a/src/clients/ksu/krb_auth_su.c ++++ b/src/clients/ksu/krb_auth_su.c +@@ -183,21 +183,19 @@ krb5_boolean ksu_get_tgt_via_passwd(context, client, options, zero_password, + if (code ) { + com_err(prog_name, code, _("while reading password for '%s'\n"), + client_name); +- memset(password, 0, sizeof(password)); + return (FALSE); + } + + if ( pwsize == 0) { + fprintf(stderr, _("No password given\n")); + *zero_password = TRUE; +- memset(password, 0, sizeof(password)); + return (FALSE); + } + + code = krb5_get_init_creds_password(context, &creds, client, password, + krb5_prompter_posix, NULL, 0, NULL, + options); +- memset(password, 0, sizeof(password)); ++ zap(password, sizeof(password)); + + + if (code) { +diff --git a/src/lib/gssapi/krb5/iakerb.c b/src/lib/gssapi/krb5/iakerb.c +index bb1072fe4..47c161ec9 100644 +--- a/src/lib/gssapi/krb5/iakerb.c ++++ b/src/lib/gssapi/krb5/iakerb.c +@@ -262,7 +262,6 @@ iakerb_make_token(iakerb_ctx_id_t ctx, + /* + * Assemble the IAKERB-HEADER from the realm and cookie + */ +- memset(&iah, 0, sizeof(iah)); + iah.target_realm = *realm; + iah.cookie = cookie; + +diff --git a/src/lib/kadm5/srv/svr_principal.c b/src/lib/kadm5/srv/svr_principal.c +index a59a65e8f..61ce60da7 100644 +--- a/src/lib/kadm5/srv/svr_principal.c ++++ b/src/lib/kadm5/srv/svr_principal.c +@@ -2091,14 +2091,8 @@ static int decrypt_key_data(krb5_context context, + ret = krb5_dbe_decrypt_key_data(context, NULL, &key_data[i], &keys[i], + NULL); + if (ret) { +- for (; i >= 0; i--) { +- if (keys[i].contents) { +- memset (keys[i].contents, 0, keys[i].length); +- free( keys[i].contents ); +- } +- } +- +- memset(keys, 0, n_key_data*sizeof(krb5_keyblock)); ++ for (; i >= 0; i--) ++ krb5_free_keyblock_contents(context, &keys[i]); + free(keys); + return ret; + } +diff --git a/src/lib/krb5/asn.1/asn1_k_encode.c b/src/lib/krb5/asn.1/asn1_k_encode.c +index 29f6b903d..716ceee59 100644 +--- a/src/lib/krb5/asn.1/asn1_k_encode.c ++++ b/src/lib/krb5/asn.1/asn1_k_encode.c +@@ -532,7 +532,6 @@ decode_kdc_req_body(const taginfo *t, const unsigned char *asn1, size_t len, + if (ret) { + free_kdc_req_body(b); + free(h.server_realm.data); +- memset(&h, 0, sizeof(h)); + return ret; + } + b->server->realm = h.server_realm; diff --git a/Avoid-allocating-a-register-in-zap-assembly.patch b/Avoid-allocating-a-register-in-zap-assembly.patch new file mode 100644 index 0000000..dc08cb3 --- /dev/null +++ b/Avoid-allocating-a-register-in-zap-assembly.patch @@ -0,0 +1,56 @@ +From 0326bf3250ea674f424d72cdec3672bcc9918d8f Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Thu, 3 Jan 2019 17:19:32 +0100 +Subject: [PATCH] Avoid allocating a register in zap() assembly + +See https://bugs.llvm.org/show_bug.cgi?id=15495 + +Also add explicit_bzero() (glibc, FreeBSD) and explicit_memset() +(NetBSD) as alternatives. + +[ghudson@mit.edu: added explicit_bzero() and explicit_memset()] + +(cherry picked from commit 7391e8b541061d0f584193b4a53365b64364b0e8) +(cherry picked from commit 77b1ce65e7777395cee5a79e4068ff4340fcc680) +--- + src/configure.in | 2 +- + src/include/k5-platform.h | 6 +++++- + 2 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/src/configure.in b/src/configure.in +index 00cb297b8..b6b7b1f21 100644 +--- a/src/configure.in ++++ b/src/configure.in +@@ -419,7 +419,7 @@ AC_PROG_LEX + AC_C_CONST + AC_HEADER_DIRENT + AC_FUNC_STRERROR_R +-AC_CHECK_FUNCS(strdup setvbuf seteuid setresuid setreuid setegid setresgid setregid setsid flock fchmod chmod strftime strptime geteuid setenv unsetenv getenv gmtime_r localtime_r bswap16 bswap64 mkstemp getusershell access getcwd srand48 srand srandom stat strchr strerror timegm) ++AC_CHECK_FUNCS(strdup setvbuf seteuid setresuid setreuid setegid setresgid setregid setsid flock fchmod chmod strftime strptime geteuid setenv unsetenv getenv gmtime_r localtime_r bswap16 bswap64 mkstemp getusershell access getcwd srand48 srand srandom stat strchr strerror timegm explicit_bzero explicit_memset) + + AC_CHECK_FUNC(mkstemp, + [MKSTEMP_ST_OBJ= +diff --git a/src/include/k5-platform.h b/src/include/k5-platform.h +index 3368c7193..6e86129e8 100644 +--- a/src/include/k5-platform.h ++++ b/src/include/k5-platform.h +@@ -1023,6 +1023,10 @@ static inline void zap(void *ptr, size_t len) + if (len > 0) + memset_s(ptr, len, 0, len); + } ++#elif defined(HAVE_EXPLICIT_BZERO) ++# define zap(ptr, len) explicit_bzero(ptr, len) ++#elif defined(HAVE_EXPLICIT_MEMSET) ++# define zap(ptr, len) explicit_memset(ptr, 0, len) + #elif defined(__GNUC__) || defined(__clang__) + /* + * Use an asm statement which declares a memory clobber to force the memset to +@@ -1032,7 +1036,7 @@ static inline void zap(void *ptr, size_t len) + { + if (len > 0) + memset(ptr, 0, len); +- __asm__ __volatile__("" : : "r" (ptr) : "memory"); ++ __asm__ __volatile__("" : : "g" (ptr) : "memory"); + } + #else + /* diff --git a/Be-more-careful-asking-for-AS-key-in-SPAKE-client.patch b/Be-more-careful-asking-for-AS-key-in-SPAKE-client.patch index 692f4ad..4e329af 100644 --- a/Be-more-careful-asking-for-AS-key-in-SPAKE-client.patch +++ b/Be-more-careful-asking-for-AS-key-in-SPAKE-client.patch @@ -20,8 +20,8 @@ spake_prep_questions() without a prototype. ticket: 8659 (cherry picked from commit f240f1b0d324312be8aa59ead7cfbe0c329ed064) --- - src/plugins/preauth/spake/spake_client.c | 111 ++++++++++++++--------- - 1 file changed, 66 insertions(+), 45 deletions(-) + src/plugins/preauth/spake/spake_client.c | 109 ++++++++++++++--------- + 1 file changed, 65 insertions(+), 44 deletions(-) diff --git a/src/plugins/preauth/spake/spake_client.c b/src/plugins/preauth/spake/spake_client.c index d72bd64aa..47a6ba26c 100644 @@ -75,11 +75,14 @@ index d72bd64aa..47a6ba26c 100644 if (st == NULL) return ENOMEM; - if (st->initial_key == NULL && pa_data->length > 0) -+ +- cb->need_as_key(context, rock); + +- /* When second-factor is implemented, we should ask questions based on the +- * factors in the challenge. */ + /* We don't need to ask any questions to send a support message. */ + if (pa_data->length == 0) + return 0; -+ + + /* Decode the incoming message, replacing any previous one in the request + * state. If we can't decode it, we have no questions to ask. */ + k5_free_pa_spake(context, st->msg); @@ -98,11 +101,7 @@ index d72bd64aa..47a6ba26c 100644 + if (!contains_sf_none(ch->factors)) + return 0; + /* We will need the AS key to respond to the challenge. */ - cb->need_as_key(context, rock); -- -- /* When second-factor is implemented, we should ask questions based on the -- * factors in the challenge. */ -- ++ cb->need_as_key(context, rock); + } else if (st->msg->choice == SPAKE_MSGTYPE_ENCDATA) { + /* When second factor support is implemented, we should decrypt the + * encdata message and ask questions based on the factor data. */ diff --git a/Eliminate-preprocessor-disabled-dead-code.patch b/Eliminate-preprocessor-disabled-dead-code.patch index 9c55c67..3e2bbe8 100644 --- a/Eliminate-preprocessor-disabled-dead-code.patch +++ b/Eliminate-preprocessor-disabled-dead-code.patch @@ -1163,7 +1163,7 @@ index 1a35cfba5..8cd1d36cb 100644 - unsigned int i; - struct tms before, after; - unsigned long cksum; - +- - block = malloc(blksiz * nblk); - if (block == NULL) - exit(1); @@ -1187,7 +1187,7 @@ index 1a35cfba5..8cd1d36cb 100644 - free(block); -} -#endif -- + -static void -verify(void) +int diff --git a/Fix-KDC-crash-when-logging-PKINIT-enctypes.patch b/Fix-KDC-crash-when-logging-PKINIT-enctypes.patch new file mode 100644 index 0000000..092b203 --- /dev/null +++ b/Fix-KDC-crash-when-logging-PKINIT-enctypes.patch @@ -0,0 +1,33 @@ +From cf751906362c803aee6aa33ad1b3b9c3e3502acf Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Wed, 25 Sep 2019 12:57:56 -0400 +Subject: [PATCH] Fix KDC crash when logging PKINIT enctypes + +Commit a649279727490687d54becad91fde8cf7429d951 introduced a KDC crash +bug due to transposed strlcpy() arguments. Fix the argument order. + +This bug does not affect any MIT krb5 release, but affects the Fedora +krb5 packages due to backports. CVE-2019-14844 has been issued as a +result. + +ticket: 8772 +(cherry picked from commit 275c9a1aad36a1a7b56042f1a2c21c33e7d16eaf) +(cherry picked from commit 55353df13814c6d711a1d947dd6690b334269122) +(cherry picked from commit efbce403dcbcb4f76d6cbdbeb6a6bec2f4f533e3) +--- + src/kdc/kdc_util.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c +index e98efd3df..325729364 100644 +--- a/src/kdc/kdc_util.c ++++ b/src/kdc/kdc_util.c +@@ -1081,7 +1081,7 @@ enctype_name(krb5_enctype ktype, char *buf, size_t buflen) + else + return krb5_enctype_to_name(ktype, FALSE, buf, buflen); + +- if (strlcpy(name, buf, buflen) >= buflen) ++ if (strlcpy(buf, name, buflen) >= buflen) + return ENOMEM; + return 0; + } diff --git a/Fix-bugs-with-concurrent-use-of-MEMORY-ccaches.patch b/Fix-bugs-with-concurrent-use-of-MEMORY-ccaches.patch deleted file mode 100644 index 085030a..0000000 --- a/Fix-bugs-with-concurrent-use-of-MEMORY-ccaches.patch +++ /dev/null @@ -1,396 +0,0 @@ -From f61875dc7da3d5dadb935ebcce25fe66564f7d0f Mon Sep 17 00:00:00 2001 -From: Greg Hudson -Date: Sun, 1 Jul 2018 00:12:25 -0400 -Subject: [PATCH] Fix bugs with concurrent use of MEMORY ccaches - -A memory ccache iterator stores an alias into the cache object's -linked list of credentials. If the cache is reinitialized while the -iterator is active, the alias becomes invalid. Also, multiple handles -referencing the same memory ccache all use aliases to the same data -object; if one of the handles is destroyed, the other contains a -dangling pointer. - -Fix the first issue by adding a generation counter to the cache and to -cursors, incremented each time the cache is initialized or destroyed. -Check the generation on each cursor step and end the iteration if the -list was invalidated. Fix the second issue by adding a reference -count to the cache object, counting one reference for the table slot -and one for each open handle. Empty the cache object on each destroy -operation, but only release the object when the last handle to it is -destroyed or closed. - -Add regression tests for the two issues to t_cc.c. - -The first issue was reported by Sorin Manolache. - -ticket: 8202 -tags: pullup -target_version: 1.16-next -target_version: 1.15-next - -(cherry picked from commit 146dadec8fe7ccc4149eb2e3f577cc320aee6efb) ---- - src/lib/krb5/ccache/cc_memory.c | 164 ++++++++++++++++++++------------ - src/lib/krb5/ccache/t_cc.c | 51 ++++++++++ - 2 files changed, 154 insertions(+), 61 deletions(-) - -diff --git a/src/lib/krb5/ccache/cc_memory.c b/src/lib/krb5/ccache/cc_memory.c -index c5425eb3a..8cdaff7fb 100644 ---- a/src/lib/krb5/ccache/cc_memory.c -+++ b/src/lib/krb5/ccache/cc_memory.c -@@ -102,18 +102,20 @@ extern krb5_error_code krb5_change_cache (void); - typedef struct _krb5_mcc_link { - struct _krb5_mcc_link *next; - krb5_creds *creds; --} krb5_mcc_link, *krb5_mcc_cursor; -+} krb5_mcc_link; - - /* Per-cache data header. */ - typedef struct _krb5_mcc_data { - char *name; - k5_cc_mutex lock; - krb5_principal prin; -- krb5_mcc_cursor link; -+ krb5_mcc_link *link; - krb5_timestamp changetime; - /* Time offsets for clock-skewed clients. */ - krb5_int32 time_offset; - krb5_int32 usec_offset; -+ int refcount; /* One for the table slot, one per handle */ -+ int generation; /* Incremented at each initialize */ - } krb5_mcc_data; - - /* List of memory caches. */ -@@ -122,6 +124,12 @@ typedef struct krb5_mcc_list_node { - krb5_mcc_data *cache; - } krb5_mcc_list_node; - -+/* Iterator over credentials in a memory cache. */ -+struct mcc_cursor { -+ int generation; -+ krb5_mcc_link *next_link; -+}; -+ - /* Iterator over memory caches. */ - struct krb5_mcc_ptcursor_data { - struct krb5_mcc_list_node *cur; -@@ -132,7 +140,23 @@ static krb5_mcc_list_node *mcc_head = 0; - - static void update_mcc_change_time(krb5_mcc_data *); - --static void krb5_mcc_free (krb5_context context, krb5_ccache id); -+/* Remove creds from d, invalidate any existing cursors, and unset the client -+ * principal. The caller is responsible for locking. */ -+static void -+empty_mcc_cache(krb5_context context, krb5_mcc_data *d) -+{ -+ krb5_mcc_link *curr, *next; -+ -+ for (curr = d->link; curr != NULL; curr = next) { -+ next = curr->next; -+ krb5_free_creds(context, curr->creds); -+ free(curr); -+ } -+ d->link = NULL; -+ d->generation++; -+ krb5_free_principal(context, d->prin); -+ d->prin = NULL; -+} - - /* - * Modifies: -@@ -150,16 +174,12 @@ krb5_mcc_initialize(krb5_context context, krb5_ccache id, krb5_principal princ) - { - krb5_os_context os_ctx = &context->os_context; - krb5_error_code ret; -- krb5_mcc_data *d; -+ krb5_mcc_data *d = id->data; - -- d = (krb5_mcc_data *)id->data; - k5_cc_mutex_lock(context, &d->lock); -+ empty_mcc_cache(context, d); - -- krb5_mcc_free(context, id); -- -- d = (krb5_mcc_data *)id->data; -- ret = krb5_copy_principal(context, princ, -- &d->prin); -+ ret = krb5_copy_principal(context, princ, &d->prin); - update_mcc_change_time(d); - - if (os_ctx->os_flags & KRB5_OS_TOFFSET_VALID) { -@@ -185,61 +205,59 @@ krb5_mcc_initialize(krb5_context context, krb5_ccache id, krb5_principal princ) - krb5_error_code KRB5_CALLCONV - krb5_mcc_close(krb5_context context, krb5_ccache id) - { -+ krb5_mcc_data *d = id->data; -+ int count; -+ - free(id); -- return KRB5_OK; --} -- --static void --krb5_mcc_free(krb5_context context, krb5_ccache id) --{ -- krb5_mcc_cursor curr,next; -- krb5_mcc_data *d; -- -- d = (krb5_mcc_data *) id->data; -- for (curr = d->link; curr;) { -- krb5_free_creds(context, curr->creds); -- next = curr->next; -- free(curr); -- curr = next; -+ k5_cc_mutex_lock(context, &d->lock); -+ count = --d->refcount; -+ k5_cc_mutex_unlock(context, &d->lock); -+ if (count == 0) { -+ /* This is the last active handle referencing d and d has been removed -+ * from the table, so we can release it. */ -+ empty_mcc_cache(context, d); -+ free(d->name); -+ k5_cc_mutex_destroy(&d->lock); -+ free(d); - } -- d->link = NULL; -- krb5_free_principal(context, d->prin); -+ return KRB5_OK; - } - - /* - * Effects: - * Destroys the contents of id. id is invalid after call. -- * -- * Errors: -- * system errors (locks related) - */ - krb5_error_code KRB5_CALLCONV - krb5_mcc_destroy(krb5_context context, krb5_ccache id) - { - krb5_mcc_list_node **curr, *node; -- krb5_mcc_data *d; -+ krb5_mcc_data *d = id->data; -+ krb5_boolean removed_from_table = FALSE; - - k5_cc_mutex_lock(context, &krb5int_mcc_mutex); - -- d = (krb5_mcc_data *)id->data; - for (curr = &mcc_head; *curr; curr = &(*curr)->next) { - if ((*curr)->cache == d) { - node = *curr; - *curr = node->next; - free(node); -+ removed_from_table = TRUE; - break; - } - } - k5_cc_mutex_unlock(context, &krb5int_mcc_mutex); - -+ /* Empty the cache and remove the reference for the table slot. There will -+ * always be at least one reference left for the handle being destroyed. */ - k5_cc_mutex_lock(context, &d->lock); -- -- krb5_mcc_free(context, id); -- free(d->name); -+ empty_mcc_cache(context, d); -+ if (removed_from_table) -+ d->refcount--; - k5_cc_mutex_unlock(context, &d->lock); -- k5_cc_mutex_destroy(&d->lock); -- free(d); -- free(id); -+ -+ /* Invalidate the handle, possibly removing the last reference to d and -+ * freeing it. */ -+ krb5_mcc_close(context, id); - - krb5_change_cache (); - return KRB5_OK; -@@ -279,9 +297,12 @@ krb5_mcc_resolve (krb5_context context, krb5_ccache *id, const char *residual) - for (ptr = mcc_head; ptr; ptr=ptr->next) - if (!strcmp(ptr->cache->name, residual)) - break; -- if (ptr) -+ if (ptr != NULL) { - d = ptr->cache; -- else { -+ k5_cc_mutex_lock(context, &d->lock); -+ d->refcount++; -+ k5_cc_mutex_unlock(context, &d->lock); -+ } else { - err = new_mcc_data(residual, &d); - if (err) { - k5_cc_mutex_unlock(context, &krb5int_mcc_mutex); -@@ -326,14 +347,18 @@ krb5_error_code KRB5_CALLCONV - krb5_mcc_start_seq_get(krb5_context context, krb5_ccache id, - krb5_cc_cursor *cursor) - { -- krb5_mcc_cursor mcursor; -+ struct mcc_cursor *mcursor; - krb5_mcc_data *d; - -+ mcursor = malloc(sizeof(*mcursor)); -+ if (mcursor == NULL) -+ return KRB5_CC_NOMEM; - d = id->data; - k5_cc_mutex_lock(context, &d->lock); -- mcursor = d->link; -+ mcursor->generation = d->generation; -+ mcursor->next_link = d->link; - k5_cc_mutex_unlock(context, &d->lock); -- *cursor = (krb5_cc_cursor) mcursor; -+ *cursor = mcursor; - return KRB5_OK; - } - -@@ -361,23 +386,34 @@ krb5_error_code KRB5_CALLCONV - krb5_mcc_next_cred(krb5_context context, krb5_ccache id, - krb5_cc_cursor *cursor, krb5_creds *creds) - { -- krb5_mcc_cursor mcursor; -+ struct mcc_cursor *mcursor; - krb5_error_code retval; -+ krb5_mcc_data *d = id->data; - -- /* Once the node in the linked list is created, it's never -- modified, so we don't need to worry about locking here. (Note -- that we don't support _remove_cred.) */ -- mcursor = (krb5_mcc_cursor) *cursor; -- if (mcursor == NULL) -- return KRB5_CC_END; - memset(creds, 0, sizeof(krb5_creds)); -- if (mcursor->creds) { -- retval = k5_copy_creds_contents(context, mcursor->creds, creds); -- if (retval) -- return retval; -+ mcursor = *cursor; -+ if (mcursor->next_link == NULL) -+ return KRB5_CC_END; -+ -+ /* -+ * Check the cursor generation against the cache generation in case the -+ * cache has been reinitialized or destroyed, freeing the pointer in the -+ * cursor. Keep the cache locked while we copy the creds and advance the -+ * pointer, in case another thread reinitializes the cache after we check -+ * the generation. -+ */ -+ k5_cc_mutex_lock(context, &d->lock); -+ if (mcursor->generation != d->generation) { -+ k5_cc_mutex_unlock(context, &d->lock); -+ return KRB5_CC_END; - } -- *cursor = (krb5_cc_cursor)mcursor->next; -- return KRB5_OK; -+ -+ retval = k5_copy_creds_contents(context, mcursor->next_link->creds, creds); -+ if (retval == 0) -+ mcursor->next_link = mcursor->next_link->next; -+ -+ k5_cc_mutex_unlock(context, &d->lock); -+ return retval; - } - - /* -@@ -396,14 +432,18 @@ krb5_mcc_next_cred(krb5_context context, krb5_ccache id, - krb5_error_code KRB5_CALLCONV - krb5_mcc_end_seq_get(krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor) - { -- *cursor = 0L; -+ free(*cursor); -+ *cursor = NULL; - return KRB5_OK; - } - --/* Utility routine: Creates the back-end data for a memory cache, and -- threads it into the global linked list. -- -- Call with the global list lock held. */ -+/* -+ * Utility routine: Creates the back-end data for a memory cache, and threads -+ * it into the global linked list. Give the new object two references, one for -+ * the table slot and one for the caller's handle. -+ * -+ * Call with the global list lock held. -+ */ - static krb5_error_code - new_mcc_data (const char *name, krb5_mcc_data **dataptr) - { -@@ -432,6 +472,8 @@ new_mcc_data (const char *name, krb5_mcc_data **dataptr) - d->changetime = 0; - d->time_offset = 0; - d->usec_offset = 0; -+ d->refcount = 2; -+ d->generation = 0; - update_mcc_change_time(d); - - n = malloc(sizeof(krb5_mcc_list_node)); -diff --git a/src/lib/krb5/ccache/t_cc.c b/src/lib/krb5/ccache/t_cc.c -index 6069cabd3..cd4569c4c 100644 ---- a/src/lib/krb5/ccache/t_cc.c -+++ b/src/lib/krb5/ccache/t_cc.c -@@ -386,6 +386,55 @@ test_misc(krb5_context context) - krb5_cc_dfl_ops = ops_save; - - } -+ -+/* -+ * Regression tests for #8202. Because memory ccaches share objects between -+ * different handles to the same cache and between iterators and caches, -+ * historically there have been some bugs when those objects are released. -+ */ -+static void -+test_memory_concurrent(krb5_context context) -+{ -+ krb5_error_code kret; -+ krb5_ccache id1, id2; -+ krb5_cc_cursor cursor; -+ krb5_creds creds; -+ -+ /* Create two handles to the same memory ccache and destroy them. */ -+ kret = krb5_cc_resolve(context, "MEMORY:x", &id1); -+ CHECK(kret, "resolve 1"); -+ kret = krb5_cc_resolve(context, "MEMORY:x", &id2); -+ CHECK(kret, "resolve 2"); -+ kret = krb5_cc_destroy(context, id1); -+ CHECK(kret, "destroy 1"); -+ kret = krb5_cc_destroy(context, id2); -+ CHECK(kret, "destroy 2"); -+ -+ kret = init_test_cred(context); -+ CHECK(kret, "init_creds"); -+ -+ /* Reinitialize the cache after creating an iterator for it, and verify -+ * that the iterator ends gracefully. */ -+ kret = krb5_cc_resolve(context, "MEMORY:x", &id1); -+ CHECK(kret, "resolve"); -+ kret = krb5_cc_initialize(context, id1, test_creds.client); -+ CHECK(kret, "initialize"); -+ kret = krb5_cc_store_cred(context, id1, &test_creds); -+ CHECK(kret, "store"); -+ kret = krb5_cc_start_seq_get(context, id1, &cursor); -+ CHECK(kret, "start_seq_get"); -+ kret = krb5_cc_initialize(context, id1, test_creds.client); -+ CHECK(kret, "initialize again"); -+ kret = krb5_cc_next_cred(context, id1, &cursor, &creds); -+ CHECK_BOOL(kret != KRB5_CC_END, "iterator should end", "next_cred"); -+ kret = krb5_cc_end_seq_get(context, id1, &cursor); -+ CHECK(kret, "end_seq_get"); -+ kret = krb5_cc_destroy(context, id1); -+ CHECK(kret, "destroy"); -+ -+ free_test_cred(context); -+} -+ - extern const krb5_cc_ops krb5_mcc_ops; - extern const krb5_cc_ops krb5_fcc_ops; - -@@ -434,6 +483,8 @@ main(void) - do_test(context, "MEMORY:"); - do_test(context, "FILE:"); - -+ test_memory_concurrent(context); -+ - krb5_free_context(context); - return 0; - } diff --git a/In-kpropd-debug-log-proper-ticket-enctype-names.patch b/In-kpropd-debug-log-proper-ticket-enctype-names.patch new file mode 100644 index 0000000..4d484c4 --- /dev/null +++ b/In-kpropd-debug-log-proper-ticket-enctype-names.patch @@ -0,0 +1,29 @@ +From 35fd91ee49ecba137a7f5b5da5f9c56ddef461af Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Tue, 15 Jan 2019 13:41:16 -0500 +Subject: [PATCH] In kpropd, debug-log proper ticket enctype names + +This change replaces the last call of krb5_enctype_to_string() in our +sources with krb5_enctype_to_name(), ensuring that we log consistently +to users using readily discoverable strings. + +(cherry picked from commit 30e12a2ecdf7e2a034a91626a03b5c9909e4c68d) +(cherry picked from commit d2990ce023e000e1628007a5d24aad5a5abdb0a3) +--- + src/slave/kpropd.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/slave/kpropd.c b/src/slave/kpropd.c +index 99676cc97..e1e21f631 100644 +--- a/src/slave/kpropd.c ++++ b/src/slave/kpropd.c +@@ -1279,7 +1279,8 @@ kerberos_authenticate(krb5_context context, int fd, krb5_principal *clientp, + exit(1); + } + +- retval = krb5_enctype_to_string(*etype, etypebuf, sizeof(etypebuf)); ++ retval = krb5_enctype_to_name(*etype, FALSE, etypebuf, ++ sizeof(etypebuf)); + if (retval) { + com_err(progname, retval, _("while unparsing ticket etype")); + exit(1); diff --git a/In-rd_req_dec-always-log-non-permitted-enctypes.patch b/In-rd_req_dec-always-log-non-permitted-enctypes.patch new file mode 100644 index 0000000..8c821ce --- /dev/null +++ b/In-rd_req_dec-always-log-non-permitted-enctypes.patch @@ -0,0 +1,55 @@ +From 1bc74278b3393aeb559b0bcd3c7e2bd476f2754b Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Mon, 14 Jan 2019 17:14:42 -0500 +Subject: [PATCH] In rd_req_dec, always log non-permitted enctypes + +The buffer specified in negotiate_etype() is too small for use with +the AES enctypes when used with krb5_enctype_to_string(), so switch to +using krb5_enctype_to_name(). + +(cherry picked from commit bf75ebf583a51bf00005a96d17924818d19377be) +(cherry picked from commit e595f7a4c1c95aadcb1bc3ea2bb88fce66fb826b) +--- + src/lib/krb5/krb/rd_req_dec.c | 5 ++--- + src/tests/gssapi/t_enctypes.py | 5 +++-- + 2 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/src/lib/krb5/krb/rd_req_dec.c b/src/lib/krb5/krb/rd_req_dec.c +index 4cd429a11..e75192fee 100644 +--- a/src/lib/krb5/krb/rd_req_dec.c ++++ b/src/lib/krb5/krb/rd_req_dec.c +@@ -864,9 +864,8 @@ negotiate_etype(krb5_context context, + if (permitted == FALSE) { + char enctype_name[30]; + +- if (krb5_enctype_to_string(desired_etypes[i], +- enctype_name, +- sizeof(enctype_name)) == 0) ++ if (krb5_enctype_to_name(desired_etypes[i], FALSE, enctype_name, ++ sizeof(enctype_name)) == 0) + k5_setmsg(context, KRB5_NOPERM_ETYPE, + _("Encryption type %s not permitted"), enctype_name); + return KRB5_NOPERM_ETYPE; +diff --git a/src/tests/gssapi/t_enctypes.py b/src/tests/gssapi/t_enctypes.py +index ee43ff028..5d9f80e04 100755 +--- a/src/tests/gssapi/t_enctypes.py ++++ b/src/tests/gssapi/t_enctypes.py +@@ -85,7 +85,8 @@ test('both aes128', 'aes128-cts', 'aes128-cts', + # If only the acceptor constrains the permitted session enctypes to + # aes128, subkey negotiation fails because the acceptor considers the + # aes256 session key to be non-permitted. +-test_err('acc aes128', None, 'aes128-cts', 'Encryption type not permitted') ++test_err('acc aes128', None, 'aes128-cts', ++ 'Encryption type aes256-cts-hmac-sha1-96 not permitted') + + # If the initiator constrains the permitted session enctypes to des3, + # no acceptor subkey will be generated because we can't upgrade to a +@@ -128,7 +129,7 @@ test('upgrade init des3+rc4', 'des3 rc4', None, + # is only for the sake of the kernel, since we could upgrade to an + # aes128 subkey, but it's the current semantics.) + test_err('upgrade acc aes128', None, 'aes128-cts', +- 'Encryption type ArcFour with HMAC/md5 not permitted') ++ 'Encryption type arcfour-hmac not permitted') + + # If the acceptor permits rc4 but prefers aes128, it will negotiate an + # upgrade to aes128. diff --git a/Make-etype-names-in-KDC-logs-human-readable.patch b/Make-etype-names-in-KDC-logs-human-readable.patch new file mode 100644 index 0000000..b3bd46d --- /dev/null +++ b/Make-etype-names-in-KDC-logs-human-readable.patch @@ -0,0 +1,294 @@ +From 3a17abda20fbb92ed20c1466a82fb2c7a656a6ab Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Tue, 8 Jan 2019 17:42:35 -0500 +Subject: [PATCH] Make etype names in KDC logs human-readable + +Introduce enctype_name() as a wrapper over krb5_enctype_to_name for +converting between registered constants and names. Adjust signatures +and rewrite ktypes2str() and rep_etypes2str() to operate on dynamic +buffers. + +ticket: 8772 (new) +(cherry picked from commit a649279727490687d54becad91fde8cf7429d951) +(cherry picked from commit b999ade3996817ccb9c9362e4c06dd236e4a854b) +--- + src/kdc/kdc_log.c | 42 +++++++-------- + src/kdc/kdc_util.c | 125 +++++++++++++++++++++++---------------------- + src/kdc/kdc_util.h | 6 +-- + 3 files changed, 87 insertions(+), 86 deletions(-) + +diff --git a/src/kdc/kdc_log.c b/src/kdc/kdc_log.c +index 4eec50373..b160ba21a 100644 +--- a/src/kdc/kdc_log.c ++++ b/src/kdc/kdc_log.c +@@ -65,7 +65,7 @@ log_as_req(krb5_context context, + { + const char *fromstring = 0; + char fromstringbuf[70]; +- char ktypestr[128]; ++ char *ktypestr = NULL; + const char *cname2 = cname ? cname : ""; + const char *sname2 = sname ? sname : ""; + +@@ -74,26 +74,29 @@ log_as_req(krb5_context context, + fromstringbuf, sizeof(fromstringbuf)); + if (!fromstring) + fromstring = ""; +- ktypes2str(ktypestr, sizeof(ktypestr), +- request->nktypes, request->ktype); ++ ++ ktypestr = ktypes2str(request->ktype, request->nktypes); + + if (status == NULL) { + /* success */ +- char rep_etypestr[128]; +- rep_etypes2str(rep_etypestr, sizeof(rep_etypestr), reply); ++ char *rep_etypestr = rep_etypes2str(reply); + krb5_klog_syslog(LOG_INFO, _("AS_REQ (%s) %s: ISSUE: authtime %u, %s, " + "%s for %s"), +- ktypestr, fromstring, (unsigned int)authtime, +- rep_etypestr, cname2, sname2); ++ ktypestr ? ktypestr : "", fromstring, ++ (unsigned int)authtime, ++ rep_etypestr ? rep_etypestr : "", cname2, sname2); ++ free(rep_etypestr); + } else { + /* fail */ + krb5_klog_syslog(LOG_INFO, _("AS_REQ (%s) %s: %s: %s for %s%s%s"), +- ktypestr, fromstring, status, +- cname2, sname2, emsg ? ", " : "", emsg ? emsg : ""); ++ ktypestr ? ktypestr : "", fromstring, status, cname2, ++ sname2, emsg ? ", " : "", emsg ? emsg : ""); + } + krb5_db_audit_as_req(context, request, + local_addr->address, remote_addr->address, + client, server, authtime, errcode); ++ ++ free(ktypestr); + } + + /* +@@ -122,10 +125,9 @@ log_tgs_req(krb5_context ctx, const krb5_fulladdr *from, + unsigned int c_flags, + const char *status, krb5_error_code errcode, const char *emsg) + { +- char ktypestr[128]; ++ char *ktypestr = NULL, *rep_etypestr = NULL; + const char *fromstring = 0; + char fromstringbuf[70]; +- char rep_etypestr[128]; + char *cname = NULL, *sname = NULL, *altcname = NULL; + char *logcname = NULL, *logsname = NULL, *logaltcname = NULL; + +@@ -134,11 +136,6 @@ log_tgs_req(krb5_context ctx, const krb5_fulladdr *from, + fromstringbuf, sizeof(fromstringbuf)); + if (!fromstring) + fromstring = ""; +- ktypes2str(ktypestr, sizeof(ktypestr), request->nktypes, request->ktype); +- if (!errcode) +- rep_etypes2str(rep_etypestr, sizeof(rep_etypestr), reply); +- else +- rep_etypestr[0] = 0; + + unparse_and_limit(ctx, cprinc, &cname); + logcname = (cname != NULL) ? cname : ""; +@@ -151,10 +148,14 @@ log_tgs_req(krb5_context ctx, const krb5_fulladdr *from, + name (useful), and doesn't log ktypestr (probably not + important). */ + if (errcode != KRB5KDC_ERR_SERVER_NOMATCH) { ++ ktypestr = ktypes2str(request->ktype, request->nktypes); ++ rep_etypestr = rep_etypes2str(reply); + krb5_klog_syslog(LOG_INFO, _("TGS_REQ (%s) %s: %s: authtime %u, %s%s " + "%s for %s%s%s"), +- ktypestr, fromstring, status, (unsigned int)authtime, +- rep_etypestr, !errcode ? "," : "", logcname, logsname, ++ ktypestr ? ktypestr : "", fromstring, status, ++ (unsigned int)authtime, ++ rep_etypestr ? rep_etypestr : "", ++ !errcode ? "," : "", logcname, logsname, + errcode ? ", " : "", errcode ? emsg : ""); + if (isflagset(c_flags, KRB5_KDB_FLAG_PROTOCOL_TRANSITION)) + krb5_klog_syslog(LOG_INFO, +@@ -171,9 +172,8 @@ log_tgs_req(krb5_context ctx, const krb5_fulladdr *from, + fromstring, status, (unsigned int)authtime, + logcname, logsname, logaltcname); + +- /* OpenSolaris: audit_krb5kdc_tgs_req(...) or +- audit_krb5kdc_tgs_req_2ndtktmm(...) */ +- ++ free(rep_etypestr); ++ free(ktypestr); + krb5_free_unparsed_name(ctx, cname); + krb5_free_unparsed_name(ctx, sname); + krb5_free_unparsed_name(ctx, altcname); +diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c +index 13111215d..6f83be9db 100644 +--- a/src/kdc/kdc_util.c ++++ b/src/kdc/kdc_util.c +@@ -1043,84 +1043,87 @@ void limit_string(char *name) + return; + } + +-/* +- * L10_2 = log10(2**x), rounded up; log10(2) ~= 0.301. +- */ +-#define L10_2(x) ((int)(((x * 301) + 999) / 1000)) ++/* Wrapper of krb5_enctype_to_name() to include the PKINIT types. */ ++static krb5_error_code ++enctype_name(krb5_enctype ktype, char *buf, size_t buflen) ++{ ++ char *name; ++ ++ if (buflen == 0) ++ return EINVAL; ++ *buf = '\0'; /* ensure these are always valid C-strings */ ++ ++ /* rfc4556 recommends that clients wishing to indicate support for these ++ * pkinit algorithms include them in the etype field of the AS-REQ. */ ++ if (ktype == ENCTYPE_DSA_SHA1_CMS) ++ name = "id-dsa-with-sha1-CmsOID"; ++ else if (ktype == ENCTYPE_MD5_RSA_CMS) ++ name = "md5WithRSAEncryption-CmsOID"; ++ else if (ktype == ENCTYPE_SHA1_RSA_CMS) ++ name = "sha-1WithRSAEncryption-CmsOID"; ++ else if (ktype == ENCTYPE_RC2_CBC_ENV) ++ name = "rc2-cbc-EnvOID"; ++ else if (ktype == ENCTYPE_RSA_ENV) ++ name = "rsaEncryption-EnvOID"; ++ else if (ktype == ENCTYPE_RSA_ES_OAEP_ENV) ++ name = "id-RSAES-OAEP-EnvOID"; ++ else if (ktype == ENCTYPE_DES3_CBC_ENV) ++ name = "des-ede3-cbc-EnvOID"; ++ else ++ return krb5_enctype_to_name(ktype, FALSE, buf, buflen); + +-/* +- * Max length of sprintf("%ld") for an int of type T; includes leading +- * minus sign and terminating NUL. +- */ +-#define D_LEN(t) (L10_2(sizeof(t) * CHAR_BIT) + 2) ++ if (strlcpy(name, buf, buflen) >= buflen) ++ return ENOMEM; ++ return 0; ++} + +-void +-ktypes2str(char *s, size_t len, int nktypes, krb5_enctype *ktype) ++char * ++ktypes2str(krb5_enctype *ktype, int nktypes) + { ++ struct k5buf buf; + int i; +- char stmp[D_LEN(krb5_enctype) + 1]; +- char *p; ++ char name[64]; + +- if (nktypes < 0 +- || len < (sizeof(" etypes {...}") + D_LEN(int))) { +- *s = '\0'; +- return; +- } ++ if (nktypes < 0) ++ return NULL; + +- snprintf(s, len, "%d etypes {", nktypes); ++ k5_buf_init_dynamic(&buf); ++ k5_buf_add_fmt(&buf, "%d etypes {", nktypes); + for (i = 0; i < nktypes; i++) { +- snprintf(stmp, sizeof(stmp), "%s%ld", i ? " " : "", (long)ktype[i]); +- if (strlen(s) + strlen(stmp) + sizeof("}") > len) +- break; +- strlcat(s, stmp, len); +- } +- if (i < nktypes) { +- /* +- * We broke out of the loop. Try to truncate the list. +- */ +- p = s + strlen(s); +- while (p - s + sizeof("...}") > len) { +- while (p > s && *p != ' ' && *p != '{') +- *p-- = '\0'; +- if (p > s && *p == ' ') { +- *p-- = '\0'; +- continue; +- } +- } +- strlcat(s, "...", len); ++ enctype_name(ktype[i], name, sizeof(name)); ++ k5_buf_add_fmt(&buf, "%s%s(%ld)", i ? ", " : "", name, (long)ktype[i]); + } +- strlcat(s, "}", len); +- return; ++ k5_buf_add(&buf, "}"); ++ return buf.data; + } + +-void +-rep_etypes2str(char *s, size_t len, krb5_kdc_rep *rep) ++char * ++rep_etypes2str(krb5_kdc_rep *rep) + { +- char stmp[sizeof("ses=") + D_LEN(krb5_enctype)]; +- +- if (len < (3 * D_LEN(krb5_enctype) +- + sizeof("etypes {rep= tkt= ses=}"))) { +- *s = '\0'; +- return; +- } ++ struct k5buf buf; ++ char name[64]; ++ krb5_enctype etype; + +- snprintf(s, len, "etypes {rep=%ld", (long)rep->enc_part.enctype); ++ k5_buf_init_dynamic(&buf); ++ k5_buf_add(&buf, "etypes {rep="); ++ enctype_name(rep->enc_part.enctype, name, sizeof(name)); ++ k5_buf_add_fmt(&buf, "%s(%ld)", name, (long)rep->enc_part.enctype); + + if (rep->ticket != NULL) { +- snprintf(stmp, sizeof(stmp), +- " tkt=%ld", (long)rep->ticket->enc_part.enctype); +- strlcat(s, stmp, len); ++ etype = rep->ticket->enc_part.enctype; ++ enctype_name(etype, name, sizeof(name)); ++ k5_buf_add_fmt(&buf, ", tkt=%s(%ld)", name, (long)etype); + } + +- if (rep->ticket != NULL +- && rep->ticket->enc_part2 != NULL +- && rep->ticket->enc_part2->session != NULL) { +- snprintf(stmp, sizeof(stmp), " ses=%ld", +- (long)rep->ticket->enc_part2->session->enctype); +- strlcat(s, stmp, len); ++ if (rep->ticket != NULL && rep->ticket->enc_part2 != NULL && ++ rep->ticket->enc_part2->session != NULL) { ++ etype = rep->ticket->enc_part2->session->enctype; ++ enctype_name(etype, name, sizeof(name)); ++ k5_buf_add_fmt(&buf, ", ses=%s(%ld)", name, (long)etype); + } +- strlcat(s, "}", len); +- return; ++ ++ k5_buf_add(&buf, "}"); ++ return buf.data; + } + + static krb5_error_code +diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h +index 1885c9f80..8085e625a 100644 +--- a/src/kdc/kdc_util.h ++++ b/src/kdc/kdc_util.h +@@ -110,11 +110,9 @@ select_session_keytype (kdc_realm_t *kdc_active_realm, + + void limit_string (char *name); + +-void +-ktypes2str(char *s, size_t len, int nktypes, krb5_enctype *ktype); ++char *ktypes2str(krb5_enctype *ktype, int nktypes); + +-void +-rep_etypes2str(char *s, size_t len, krb5_kdc_rep *rep); ++char *rep_etypes2str(krb5_kdc_rep *rep); + + /* authind.c */ + krb5_boolean diff --git a/Mark-deprecated-enctypes-when-used.patch b/Mark-deprecated-enctypes-when-used.patch new file mode 100644 index 0000000..11eed47 --- /dev/null +++ b/Mark-deprecated-enctypes-when-used.patch @@ -0,0 +1,251 @@ +From 378f2ade14ec9bd2f5ab7b0e69d5437e51066584 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Thu, 10 Jan 2019 16:34:54 -0500 +Subject: [PATCH] Mark deprecated enctypes when used + +Preface ETYPE_DEPRECATED enctypes with "DEPRECATED:" in klist output, +KDC logs, and kadmin interactions. Also complain in krb5kdc when the +stash file has a deprecated enctype or a deprecated enctype is +requested with -k. + +ticket: 8773 (new) +(cherry picked from commit 8d8e68283b599e680f9fe45eff8af397e827bd6c) +(cherry picked from commit 1d1db003481768092410dc36a41e240c48a136e0) +--- + src/clients/klist/klist.c | 14 ++++++++++---- + src/kadmin/cli/kadmin.c | 6 +++++- + src/kdc/kdc_util.c | 9 +++++++++ + src/kdc/main.c | 19 +++++++++++++++++++ + src/tests/gssapi/t_enctypes.py | 15 +++++++++------ + src/tests/t_keyrollover.py | 8 +++++--- + src/tests/t_sesskeynego.py | 4 ++-- + 7 files changed, 59 insertions(+), 16 deletions(-) + +diff --git a/src/clients/klist/klist.c b/src/clients/klist/klist.c +index e9e76d8f3..8b24b30bc 100644 +--- a/src/clients/klist/klist.c ++++ b/src/clients/klist/klist.c +@@ -573,11 +573,17 @@ static char * + etype_string(krb5_enctype enctype) + { + static char buf[100]; +- krb5_error_code ret; ++ char *bp = buf; ++ size_t deplen, buflen = sizeof(buf); + +- ret = krb5_enctype_to_name(enctype, FALSE, buf, sizeof(buf)); +- if (ret) +- snprintf(buf, sizeof(buf), "etype %d", enctype); ++ if (krb5int_c_deprecated_enctype(enctype)) { ++ deplen = strlcpy(bp, "DEPRECATED:", buflen); ++ buflen -= deplen; ++ bp += deplen; ++ } ++ ++ if (krb5_enctype_to_name(enctype, FALSE, bp, buflen)) ++ snprintf(bp, buflen, "etype %d", enctype); + return buf; + } + +diff --git a/src/kadmin/cli/kadmin.c b/src/kadmin/cli/kadmin.c +index aee5c83b9..a1db55026 100644 +--- a/src/kadmin/cli/kadmin.c ++++ b/src/kadmin/cli/kadmin.c +@@ -1449,12 +1449,16 @@ kadmin_getprinc(int argc, char *argv[]) + for (i = 0; i < dprinc.n_key_data; i++) { + krb5_key_data *key_data = &dprinc.key_data[i]; + char enctype[BUFSIZ], salttype[BUFSIZ]; ++ char *deprecated = ""; + + if (krb5_enctype_to_name(key_data->key_data_type[0], FALSE, + enctype, sizeof(enctype))) + snprintf(enctype, sizeof(enctype), _(""), + key_data->key_data_type[0]); +- printf("Key: vno %d, %s", key_data->key_data_kvno, enctype); ++ if (krb5int_c_deprecated_enctype(key_data->key_data_type[0])) ++ deprecated = "DEPRECATED:"; ++ printf("Key: vno %d, %s%s", key_data->key_data_kvno, deprecated, ++ enctype); + if (key_data->key_data_ver > 1 && + key_data->key_data_type[1] != KRB5_KDB_SALTTYPE_NORMAL) { + if (krb5_salttype_to_string(key_data->key_data_type[1], +diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c +index 6f83be9db..e98efd3df 100644 +--- a/src/kdc/kdc_util.c ++++ b/src/kdc/kdc_util.c +@@ -1048,11 +1048,20 @@ static krb5_error_code + enctype_name(krb5_enctype ktype, char *buf, size_t buflen) + { + char *name; ++ size_t len; + + if (buflen == 0) + return EINVAL; + *buf = '\0'; /* ensure these are always valid C-strings */ + ++ if (krb5int_c_deprecated_enctype(ktype)) { ++ len = strlcpy(buf, "DEPRECATED:", buflen); ++ if (len >= buflen) ++ return ENOMEM; ++ buflen -= len; ++ buf += len; ++ } ++ + /* rfc4556 recommends that clients wishing to indicate support for these + * pkinit algorithms include them in the etype field of the AS-REQ. */ + if (ktype == ENCTYPE_DSA_SHA1_CMS) +diff --git a/src/kdc/main.c b/src/kdc/main.c +index 89dac23ae..78ddeed72 100644 +--- a/src/kdc/main.c ++++ b/src/kdc/main.c +@@ -214,12 +214,23 @@ init_realm(kdc_realm_t * rdp, krb5_pointer aprof, char *realm, + char *svalue = NULL; + const char *hierarchy[4]; + krb5_kvno mkvno = IGNORE_VNO; ++ char ename[32]; + + memset(rdp, 0, sizeof(kdc_realm_t)); + if (!realm) { + kret = EINVAL; + goto whoops; + } ++ ++ if (def_enctype != ENCTYPE_UNKNOWN && ++ krb5int_c_deprecated_enctype(def_enctype)) { ++ if (krb5_enctype_to_name(def_enctype, FALSE, ename, sizeof(ename))) ++ ename[0] = '\0'; ++ fprintf(stderr, ++ _("Requested master password enctype %s in %s is DEPRECATED!"), ++ ename, realm); ++ } ++ + hierarchy[0] = KRB5_CONF_REALMS; + hierarchy[1] = realm; + hierarchy[3] = NULL; +@@ -374,6 +385,14 @@ init_realm(kdc_realm_t * rdp, krb5_pointer aprof, char *realm, + goto whoops; + } + ++ if (krb5int_c_deprecated_enctype(rdp->realm_mkey.enctype)) { ++ if (krb5_enctype_to_name(rdp->realm_mkey.enctype, FALSE, ename, ++ sizeof(ename))) ++ ename[0] = '\0'; ++ fprintf(stderr, _("Stash file %s uses DEPRECATED enctype %s!"), ++ rdp->realm_stash, ename); ++ } ++ + if ((kret = krb5_db_fetch_mkey_list(rdp->realm_context, rdp->realm_mprinc, + &rdp->realm_mkey))) { + kdc_err(rdp->realm_context, kret, +diff --git a/src/tests/gssapi/t_enctypes.py b/src/tests/gssapi/t_enctypes.py +index 5d9f80e04..ca3d32d21 100755 +--- a/src/tests/gssapi/t_enctypes.py ++++ b/src/tests/gssapi/t_enctypes.py +@@ -9,8 +9,11 @@ from k5test import * + aes256 = 'aes256-cts-hmac-sha1-96' + aes128 = 'aes128-cts-hmac-sha1-96' + des3 = 'des3-cbc-sha1' ++d_des3 = 'DEPRECATED:des3-cbc-sha1' + des3raw = 'des3-cbc-raw' ++d_des3raw = 'DEPRECATED:des3-cbc-raw' + rc4 = 'arcfour-hmac' ++d_rc4 = 'DEPRECATED:arcfour-hmac' + + # These tests make assumptions about the default enctype lists, so set + # them explicitly rather than relying on the library defaults. +@@ -92,7 +95,7 @@ test_err('acc aes128', None, 'aes128-cts', + # no acceptor subkey will be generated because we can't upgrade to a + # CFX enctype. + test('init des3', 'des3', None, +- tktenc=aes256, tktsession=des3, ++ tktenc=aes256, tktsession=d_des3, + proto='rfc1964', isubkey=des3raw, asubkey=None) + + # Force the ticket session key to be rc4, so we can test some subkey +@@ -103,7 +106,7 @@ realm.run([kadminl, 'setstr', realm.host_princ, 'session_enctypes', 'rc4']) + # [aes256 aes128 des3] and the acceptor should upgrade to an aes256 + # subkey. + test('upgrade noargs', None, None, +- tktenc=aes256, tktsession=rc4, ++ tktenc=aes256, tktsession=d_rc4, + proto='cfx', isubkey=rc4, asubkey=aes256) + + # If the initiator won't permit rc4 as a session key, it won't be able +@@ -113,14 +116,14 @@ test_err('upgrade init aes', 'aes', None, 'no support for encryption type') + # If the initiator permits rc4 but prefers aes128, it will send an + # upgrade list of [aes128] and the acceptor will upgrade to aes128. + test('upgrade init aes128+rc4', 'aes128-cts rc4', None, +- tktenc=aes256, tktsession=rc4, ++ tktenc=aes256, tktsession=d_rc4, + proto='cfx', isubkey=rc4, asubkey=aes128) + + # If the initiator permits rc4 but prefers des3, it will send an + # upgrade list of [des3], but the acceptor won't generate a subkey + # because des3 isn't a CFX enctype. + test('upgrade init des3+rc4', 'des3 rc4', None, +- tktenc=aes256, tktsession=rc4, ++ tktenc=aes256, tktsession=d_rc4, + proto='rfc1964', isubkey=rc4, asubkey=None) + + # If the acceptor permits only aes128, subkey negotiation will fail +@@ -134,14 +137,14 @@ test_err('upgrade acc aes128', None, 'aes128-cts', + # If the acceptor permits rc4 but prefers aes128, it will negotiate an + # upgrade to aes128. + test('upgrade acc aes128 rc4', None, 'aes128-cts rc4', +- tktenc=aes256, tktsession=rc4, ++ tktenc=aes256, tktsession=d_rc4, + proto='cfx', isubkey=rc4, asubkey=aes128) + + # In this test, the initiator and acceptor each prefer an AES enctype + # to rc4, but they can't agree on which one, so no subkey is + # generated. + test('upgrade mismatch', 'aes128-cts rc4', 'aes256-cts rc4', +- tktenc=aes256, tktsession=rc4, ++ tktenc=aes256, tktsession=d_rc4, + proto='rfc1964', isubkey=rc4, asubkey=None) + + success('gss_krb5_set_allowable_enctypes tests') +diff --git a/src/tests/t_keyrollover.py b/src/tests/t_keyrollover.py +index 7c8d828f0..4af6804f2 100755 +--- a/src/tests/t_keyrollover.py ++++ b/src/tests/t_keyrollover.py +@@ -22,8 +22,9 @@ realm.run([kvno, princ1]) + realm.run([kadminl, 'purgekeys', realm.krbtgt_princ]) + # Make sure an old TGT fails after purging old TGS key. + realm.run([kvno, princ2], expected_code=1) +-msg = 'krbtgt/%s@%s\n\tEtype (skey, tkt): des-cbc-crc, des-cbc-crc' % \ +- (realm.realm, realm.realm) ++ddes = "DEPRECATED:des-cbc-crc" ++msg = 'krbtgt/%s@%s\n\tEtype (skey, tkt): %s, %s' % \ ++ (realm.realm, realm.realm, ddes, ddes) + realm.run([klist, '-e'], expected_msg=msg) + + # Check that new key actually works. +@@ -48,7 +49,8 @@ realm.run([kadminl, 'cpw', '-randkey', '-keepold', '-e', 'aes256-cts', + realm.krbtgt_princ]) + realm.run([kadminl, 'modprinc', '-kvno', '1', realm.krbtgt_princ]) + out = realm.run([kadminl, 'getprinc', realm.krbtgt_princ]) +-if 'vno 1, aes256' not in out or 'vno 1, des3' not in out: ++if 'vno 1, aes256-cts' not in out or \ ++ 'vno 1, DEPRECATED:des3-cbc-sha1' not in out: + fail('keyrollover: setup for TGS enctype test failed') + # Now present the DES3 ticket to the KDC and make sure it's rejected. + realm.run([kvno, realm.host_princ], expected_code=1) +diff --git a/src/tests/t_sesskeynego.py b/src/tests/t_sesskeynego.py +index 448092387..da02f224a 100755 +--- a/src/tests/t_sesskeynego.py ++++ b/src/tests/t_sesskeynego.py +@@ -62,11 +62,11 @@ test_kvno(realm, 'aes128-cts-hmac-sha1-96', 'aes256-cts-hmac-sha1-96') + # 3b: Negotiate rc4-hmac session key when principal only has aes256 long-term. + realm.run([kadminl, 'setstr', 'server', 'session_enctypes', + 'rc4-hmac,aes128-cts,aes256-cts']) +-test_kvno(realm, 'arcfour-hmac', 'aes256-cts-hmac-sha1-96') ++test_kvno(realm, 'DEPRECATED:arcfour-hmac', 'aes256-cts-hmac-sha1-96') + + # 3c: Test des-cbc-crc default assumption. + realm.run([kadminl, 'delstr', 'server', 'session_enctypes']) +-test_kvno(realm, 'des-cbc-crc', 'aes256-cts-hmac-sha1-96') ++test_kvno(realm, 'DEPRECATED:des-cbc-crc', 'aes256-cts-hmac-sha1-96') + realm.stop() + + # Last go: test that we can disable the des-cbc-crc assumption diff --git a/Refactor-KDC-krb5_pa_data-utility-functions.patch b/Refactor-KDC-krb5_pa_data-utility-functions.patch index 41e7cbe..264def1 100644 --- a/Refactor-KDC-krb5_pa_data-utility-functions.patch +++ b/Refactor-KDC-krb5_pa_data-utility-functions.patch @@ -19,9 +19,9 @@ where applicable. --- src/kdc/fast_util.c | 28 +------ src/kdc/kdc_preauth.c | 14 ++-- - src/kdc/kdc_util.c | 187 +++++++++++++++++++++--------------------- + src/kdc/kdc_util.c | 183 +++++++++++++++++++++--------------------- src/kdc/kdc_util.h | 8 +- - 4 files changed, 109 insertions(+), 128 deletions(-) + 4 files changed, 107 insertions(+), 126 deletions(-) diff --git a/src/kdc/fast_util.c b/src/kdc/fast_util.c index e05107ef3..6a3fc11b9 100644 @@ -250,29 +250,17 @@ index 754570c01..13111215d 100644 - - p[i] = (krb5_pa_data *)malloc(sizeof(krb5_pa_data)); - if (p[i] == NULL) -- return ENOMEM; -- *(p[i]) = *padata; -- -- p[i + 1] = NULL; -- -- if (copy) { -- p[i]->contents = (krb5_octet *)malloc(padata->length); -- if (p[i]->contents == NULL) { -- free(p[i]); -- p[i] = NULL; + *out = NULL; + if (len > 0) { + buf = malloc(len); + if (buf == NULL) - return ENOMEM; -- } -- -- memcpy(p[i]->contents, padata->contents, padata->length); - } ++ return ENOMEM; ++ } + pa = malloc(sizeof(*pa)); + if (pa == NULL) { + free(buf); -+ return ENOMEM; + return ENOMEM; +- *(p[i]) = *padata; + } + pa->magic = KV5M_PA_DATA; + pa->pa_type = pa_type; @@ -282,21 +270,31 @@ index 754570c01..13111215d 100644 + return 0; +} +- p[i + 1] = NULL; +/* Add pa to list, claiming its memory. Free pa on failure. */ +krb5_error_code +add_pa_data_element(krb5_pa_data ***list, krb5_pa_data *pa) +{ + size_t count; + krb5_pa_data **newlist; -+ + +- if (copy) { +- p[i]->contents = (krb5_octet *)malloc(padata->length); +- if (p[i]->contents == NULL) { +- free(p[i]); +- p[i] = NULL; +- return ENOMEM; +- } + for (count = 0; *list != NULL && (*list)[count] != NULL; count++); -+ + +- memcpy(p[i]->contents, padata->contents, padata->length); + newlist = realloc(*list, (count + 2) * sizeof(*newlist)); + if (newlist == NULL) { + free(pa->contents); + free(pa); + return ENOMEM; -+ } + } +- + newlist[count] = pa; + newlist[count + 1] = NULL; + *list = newlist; @@ -339,6 +337,13 @@ index 754570c01..13111215d 100644 + + /* Add a pa-data element to the list, stealing memory from der_cksum. */ + retval = alloc_pa_data(KRB5_ENCPADATA_REQ_ENC_PA_REP, 0, &pa); ++ if (retval) ++ goto cleanup; ++ pa->length = der_cksum->length; ++ pa->contents = (uint8_t *)der_cksum->data; ++ der_cksum->data = NULL; ++ /* add_pa_data_element() claims pa on success or failure. */ ++ retval = add_pa_data_element(out_enc_padata, pa); if (retval) goto cleanup; - out->data = NULL; @@ -347,13 +352,6 @@ index 754570c01..13111215d 100644 - pa.length = 0; - pa.contents = NULL; - retval = add_pa_data_element(context, &pa, out_enc_padata, FALSE); -+ pa->length = der_cksum->length; -+ pa->contents = (uint8_t *)der_cksum->data; -+ der_cksum->data = NULL; -+ /* add_pa_data_element() claims pa on success or failure. */ -+ retval = add_pa_data_element(out_enc_padata, pa); -+ if (retval) -+ goto cleanup; + + /* Add a zero-length PA-FX-FAST element to the list. */ + retval = alloc_pa_data(KRB5_PADATA_FX_FAST, 0, &pa); diff --git a/Remove-incorrect-KDC-assertion.patch b/Remove-incorrect-KDC-assertion.patch new file mode 100644 index 0000000..937ee02 --- /dev/null +++ b/Remove-incorrect-KDC-assertion.patch @@ -0,0 +1,43 @@ +From ca75a685d19fec7c481fd3de9769ac3546e37a11 Mon Sep 17 00:00:00 2001 +From: Isaac Boukris +Date: Sat, 15 Dec 2018 11:56:36 +0200 +Subject: [PATCH] Remove incorrect KDC assertion + +The assertion in return_enc_padata() is reachable because +kdc_make_s4u2self_rep() may have previously added encrypted padata. +It is no longer necessary because the code uses add_pa_data_element() +instead of allocating a new list. + +CVE-2018-20217: + +In MIT krb5 1.8 or later, an authenticated user who can obtain a TGT +using an older encryption type (DES, DES3, or RC4) can cause an +assertion failure in the KDC by sending an S4U2Self request. + +[ghudson@mit.edu: rewrote commit message with CVE description] + +ticket: 8767 (new) +tags: pullup +target_version: 1.17 +target_version: 1.16-next +target_version: 1.15-next + +(cherry picked from commit 94e5eda5bb94d1d44733a49c3d9b6d1e42c74def) +(cherry picked from commit 5ab44ff3ecdf362a792f193cf18df42866b70f80) +[rharwood@redhat.com: don't backport the tests] +--- + src/kdc/kdc_preauth.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c +index 811c16368..6f0cf68d9 100644 +--- a/src/kdc/kdc_preauth.c ++++ b/src/kdc/kdc_preauth.c +@@ -1666,7 +1666,6 @@ return_enc_padata(krb5_context context, krb5_data *req_pkt, + krb5_error_code code = 0; + /* This should be initialized and only used for Win2K compat and other + * specific standardized uses such as FAST negotiation. */ +- assert(reply_encpart->enc_padata == NULL); + if (is_referral) { + code = return_referral_enc_padata(context, reply_encpart, server); + if (code) diff --git a/Simplify-kdc_preauth.c-systems-table.patch b/Simplify-kdc_preauth.c-systems-table.patch index 08853d4..802258a 100644 --- a/Simplify-kdc_preauth.c-systems-table.patch +++ b/Simplify-kdc_preauth.c-systems-table.patch @@ -16,8 +16,8 @@ since it was first added. (cherry picked from commit fea1a488924faa3938ef723feaa1ff12d22a91ff) --- - src/kdc/kdc_preauth.c | 526 +++++++++++++++--------------------------- - 1 file changed, 184 insertions(+), 342 deletions(-) + src/kdc/kdc_preauth.c | 522 +++++++++++++++--------------------------- + 1 file changed, 182 insertions(+), 340 deletions(-) diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c index edc30bd83..6f34dc289 100644 @@ -344,18 +344,15 @@ index edc30bd83..6f34dc289 100644 state->rock = rock; state->realm = rock->rstate->realm_data; state->e_data_out = e_data_out; -- ++ state->pa_data = NULL; ++ state->ap = preauth_systems; + - state->pa_data = calloc(n_preauth_systems + 1, sizeof(krb5_pa_data *)); - if (!state->pa_data) { - free(state); - (*respond)(arg); - return; - } -- -- state->pa_cur = state->pa_data; -+ state->pa_data = NULL; - state->ap = preauth_systems; -+ + /* Add an empty PA-FX-FAST element to advertise FAST support. */ + if (alloc_pa_data(KRB5_PADATA_FX_FAST, 0, &pa) != 0) + goto error; @@ -365,7 +362,9 @@ index edc30bd83..6f34dc289 100644 + + if (add_etype_info(kdc_context, rock, &state->pa_data) != 0) + goto error; -+ + +- state->pa_cur = state->pa_data; +- state->ap = preauth_systems; hint_list_next(state); + return; + @@ -543,23 +542,16 @@ index edc30bd83..6f34dc289 100644 goto cleanup; - pa = k5alloc(sizeof(*pa), &retval); - if (pa == NULL) -+ -+ /* Steal the data from der_etype_info to create a pa-data element. */ -+ retval = alloc_pa_data(pa_type, 0, pa_out); -+ if (retval) - goto cleanup; +- goto cleanup; - pa->magic = KV5M_PA_DATA; - pa->pa_type = pa_type; - pa->contents = (unsigned char *)scratch->data; - pa->length = scratch->length; - scratch->data = NULL; - *pa_out = pa; -+ (*pa_out)->contents = (uint8_t *)der_etype_info->data; -+ (*pa_out)->length = der_etype_info->length; -+ der_etype_info->data = NULL; - - cleanup: - krb5_free_etype_info(context, entry); +- +-cleanup: +- krb5_free_etype_info(context, entry); - krb5_free_data(context, scratch); - return retval; -} @@ -576,7 +568,7 @@ index edc30bd83..6f34dc289 100644 - } - return FALSE; -} -- + -/* Generate hint list padata for PA-ETYPE-INFO or PA-ETYPE-INFO2. */ -static void -get_etype_info(krb5_context context, krb5_kdc_req *request, @@ -635,12 +627,14 @@ index edc30bd83..6f34dc289 100644 - - retval = krb5_dbe_compute_salt(context, client_key, request->client, - &salttype, &salt); -- if (retval) ++ /* Steal the data from der_etype_info to create a pa-data element. */ ++ retval = alloc_pa_data(pa_type, 0, pa_out); + if (retval) - return 0; - - padata = k5alloc(sizeof(*padata), &retval); - if (padata == NULL) -- goto cleanup; + goto cleanup; - padata->magic = KV5M_PA_DATA; - - if (salttype == KRB5_KDB_SALTTYPE_AFS3) { @@ -658,10 +652,14 @@ index edc30bd83..6f34dc289 100644 - - *send_pa = padata; - padata = NULL; -- --cleanup: ++ (*pa_out)->contents = (uint8_t *)der_etype_info->data; ++ (*pa_out)->length = der_etype_info->length; ++ der_etype_info->data = NULL; + + cleanup: - free(padata); - krb5_free_data(context, salt); ++ krb5_free_etype_info(context, entry); + krb5_free_data(context, der_etype_info); return retval; } diff --git a/Use-libkrb5support-hex-functions-where-appropriate.patch b/Use-libkrb5support-hex-functions-where-appropriate.patch index eab05bc..ea82592 100644 --- a/Use-libkrb5support-hex-functions-where-appropriate.patch +++ b/Use-libkrb5support-hex-functions-where-appropriate.patch @@ -8,7 +8,7 @@ Subject: [PATCH] Use libkrb5support hex functions where appropriate src/kadmin/dbutil/deps | 16 ++--- src/kadmin/dbutil/tabdump.c | 19 +++--- src/kadmin/ktutil/deps | 13 ++-- - src/kadmin/ktutil/ktutil_funcs.c | 30 ++++----- + src/kadmin/ktutil/ktutil_funcs.c | 28 ++++---- src/lib/crypto/crypto_tests/deps | 39 ++++++----- src/lib/crypto/crypto_tests/t_cksum.c | 35 +++------- src/lib/crypto/crypto_tests/t_crc.c | 28 ++------ @@ -24,7 +24,7 @@ Subject: [PATCH] Use libkrb5support hex functions where appropriate src/slave/kproplog.c | 11 ++-- src/tests/gssapi/deps | 14 ++-- src/tests/gssapi/t_prf.c | 13 ++-- - 19 files changed, 152 insertions(+), 255 deletions(-) + 19 files changed, 151 insertions(+), 254 deletions(-) diff --git a/src/kadmin/dbutil/deps b/src/kadmin/dbutil/deps index 4dcc33628..8b0965aac 100644 @@ -153,26 +153,25 @@ index 7a3aa0dca..5843e24b7 100644 - lp->entry->key.contents = (krb5_octet *) malloc((strlen(buf) + 1) / 2); - if (!lp->entry->key.contents) { - retval = ENOMEM; -+ retval = k5_hex_decode(buf, &keybytes, &keylen); -+ if (retval) { -+ if (retval == EINVAL) { -+ fprintf(stderr, _("addent: Illegal character in key.\n")); -+ retval = 0; -+ } - goto cleanup; - } - +- goto cleanup; +- } +- - i = 0; - for (cp = buf; *cp; cp += 2) { - if (!isxdigit((int) cp[0]) || !isxdigit((int) cp[1])) { -- fprintf(stderr, _("addent: Illegal character in key.\n")); -- retval = 0; ++ retval = k5_hex_decode(buf, &keybytes, &keylen); ++ if (retval) { ++ if (retval == EINVAL) { + fprintf(stderr, _("addent: Illegal character in key.\n")); + retval = 0; - goto cleanup; -- } + } - sscanf(cp, "%02x", &tmp); - lp->entry->key.contents[i++] = (krb5_octet) tmp; -- } ++ goto cleanup; + } - lp->entry->key.length = i; ++ + lp->entry->key.enctype = enctype; + lp->entry->key.contents = keybytes; + lp->entry->key.length = keylen; @@ -665,22 +664,17 @@ index 87a2118ff..cb30f4a7f 100644 return EINVAL; } - str += 5; - +- - len = strlen(str); - if (len % 2 != 0) { - k5_setmsg(context, EINVAL, _("Password corrupt")); - return EINVAL; -+ ret = k5_hex_decode(str + 5, &bytes, &len); -+ if (ret) { -+ if (ret == EINVAL) -+ k5_setmsg(context, ret, _("Password corrupt")); -+ return ret; - } - +- } +- - q = password = malloc(len / 2 + 1); - if (password == NULL) - return ENOMEM; -- + - for (p = (unsigned char *)str; *p != '\0'; p += 2) { - if (!isxdigit(*p) || !isxdigit(p[1])) { - free(password); @@ -689,9 +683,14 @@ index 87a2118ff..cb30f4a7f 100644 - } - sscanf((char *)p, "%2x", &k); - *q++ = k; -- } ++ ret = k5_hex_decode(str + 5, &bytes, &len); ++ if (ret) { ++ if (ret == EINVAL) ++ k5_setmsg(context, ret, _("Password corrupt")); ++ return ret; + } - *q = '\0'; -- + - *password_out = (char *)password; + *password_out = (char *)bytes; return 0; diff --git a/krb5.spec b/krb5.spec index 9d0e2e7..a74bc36 100644 --- a/krb5.spec +++ b/krb5.spec @@ -18,7 +18,7 @@ Summary: The Kerberos network authentication system Name: krb5 Version: 1.16.1 # for prerelease, should be e.g., 0.% {prerelease}.1% { ?dist } (without spaces) -Release: 21%{?dist} +Release: 26%{?dist} # lookaside-cached sources; two downloads and a build artifact Source0: https://web.mit.edu/kerberos/dist/krb5/1.16/krb5-%{version}%{prerelease}.tar.gz @@ -103,10 +103,15 @@ Patch83: Make-krb5kdc-p-affect-TCP-ports.patch Patch84: Remove-outdated-note-in-krb5kdc-man-page.patch Patch85: Fix-k5test-prompts-for-Python-3.patch Patch86: In-FIPS-mode-add-plaintext-fallback-for-RC4-usages-a.patch -# Disabled for now as it seems to make things worse for FreeIPA -# (consistent crashes during server deployment, not just a crash -# in a later test): https://bugzilla.redhat.com/show_bug.cgi?id=1633089#c26 -#Patch87: Fix-bugs-with-concurrent-use-of-MEMORY-ccaches.patch +Patch88: Remove-incorrect-KDC-assertion.patch +Patch89: Address-some-optimized-out-memset-calls.patch +Patch90: Avoid-allocating-a-register-in-zap-assembly.patch +Patch91: In-rd_req_dec-always-log-non-permitted-enctypes.patch +Patch92: In-kpropd-debug-log-proper-ticket-enctype-names.patch +Patch93: Add-function-and-enctype-flag-for-deprecations.patch +Patch94: Make-etype-names-in-KDC-logs-human-readable.patch +Patch95: Mark-deprecated-enctypes-when-used.patch +Patch96: Fix-KDC-crash-when-logging-PKINIT-enctypes.patch License: MIT URL: http://web.mit.edu/kerberos/www/ @@ -753,6 +758,22 @@ exit 0 %{_libdir}/libkadm5srv_mit.so.* %changelog +* Wed Sep 25 2019 Robbie Harwood - 1.16.1-26 +- Fix KDC crash when logging PKINIT enctypes (CVE-2019-14844) + +* Thu Jan 17 2019 Robbie Harwood - 1.16.1-25 +- enctype logging and explicit_bzero() + +* Fri Jan 04 2019 Robbie Harwood - 1.16.1-24 +- Address some optimized-out memset() calls + +* Fri Dec 28 2018 Adam Williamson - 1.16.1-23 +- Disable patch from -20 again (rharwood re-enabled it in -22, and + it immediately broke FreeIPA again) + +* Thu Dec 20 2018 Robbie Harwood - 1.16.1-22 +- Remove incorrect KDC assertion (CVE-2018-20217) + * Tue Oct 09 2018 Adam Williamson - 1.16.1-21 - Revert the patch from -20 for now as it seems to make FreeIPA worse