From 9e69bcd277e34e54b11df4e39c4060972b4cb57a Mon Sep 17 00:00:00 2001 From: Robbie Harwood Date: Thu, 20 Dec 2018 18:15:55 -0500 Subject: [PATCH 1/5] Remove incorrect KDC assertion (CVE-2018-20217) --- Remove-incorrect-KDC-assertion.patch | 43 ++++++++++++++++++++++++++++ krb5.spec | 11 +++---- 2 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 Remove-incorrect-KDC-assertion.patch diff --git a/Remove-incorrect-KDC-assertion.patch b/Remove-incorrect-KDC-assertion.patch new file mode 100644 index 0000000..336476a --- /dev/null +++ b/Remove-incorrect-KDC-assertion.patch @@ -0,0 +1,43 @@ +From f08cf208c78d4a7e96c11a51ef2715a2718412db 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/krb5.spec b/krb5.spec index 9d0e2e7..0397d53 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: 22%{?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,8 @@ 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 +Patch87: Fix-bugs-with-concurrent-use-of-MEMORY-ccaches.patch +Patch88: Remove-incorrect-KDC-assertion.patch License: MIT URL: http://web.mit.edu/kerberos/www/ @@ -753,6 +751,9 @@ exit 0 %{_libdir}/libkadm5srv_mit.so.* %changelog +* 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 From 19b9dd17ffb523a91eb83d7b69cfe5e29494e03d Mon Sep 17 00:00:00 2001 From: Adam Williamson Date: Fri, 28 Dec 2018 09:29:34 -0800 Subject: [PATCH 2/5] Disable patch from -20 again rharwood re-enabled this patch in -22 (as well as adding the security fix that's mentioned in the changelog)...and FreeIPA immediately broke again, in all openQA update tests and also two people posted about it in Bugzilla. So it seems we still need this disabled. --- krb5.spec | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/krb5.spec b/krb5.spec index 0397d53..ccea469 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: 22%{?dist} +Release: 23%{?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,7 +103,10 @@ 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 -Patch87: Fix-bugs-with-concurrent-use-of-MEMORY-ccaches.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 License: MIT @@ -751,6 +754,10 @@ exit 0 %{_libdir}/libkadm5srv_mit.so.* %changelog +* 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) From 0b47ef89606ce7314f04976519c31d07f8c269a0 Mon Sep 17 00:00:00 2001 From: Robbie Harwood Date: Fri, 4 Jan 2019 10:53:37 -0500 Subject: [PATCH 3/5] Address some optimized-out memset() calls --- Address-some-optimized-out-memset-calls.patch | 95 +++++ ...ith-concurrent-use-of-MEMORY-ccaches.patch | 396 ------------------ Remove-incorrect-KDC-assertion.patch | 2 +- krb5.spec | 10 +- 4 files changed, 101 insertions(+), 402 deletions(-) create mode 100644 Address-some-optimized-out-memset-calls.patch delete mode 100644 Fix-bugs-with-concurrent-use-of-MEMORY-ccaches.patch 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/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/Remove-incorrect-KDC-assertion.patch b/Remove-incorrect-KDC-assertion.patch index 336476a..937ee02 100644 --- a/Remove-incorrect-KDC-assertion.patch +++ b/Remove-incorrect-KDC-assertion.patch @@ -1,4 +1,4 @@ -From f08cf208c78d4a7e96c11a51ef2715a2718412db Mon Sep 17 00:00:00 2001 +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 diff --git a/krb5.spec b/krb5.spec index ccea469..2b3136a 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: 23%{?dist} +Release: 24%{?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,11 +103,8 @@ 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 License: MIT URL: http://web.mit.edu/kerberos/www/ @@ -754,6 +751,9 @@ exit 0 %{_libdir}/libkadm5srv_mit.so.* %changelog +* 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) From dd7274809c083572af546345a9f76e9bdc087c16 Mon Sep 17 00:00:00 2001 From: Robbie Harwood Date: Thu, 17 Jan 2019 16:27:24 -0500 Subject: [PATCH 4/5] enctype logging and explicit_bzero() --- ...on-and-enctype-flag-for-deprecations.patch | 185 +++++++++++ ...llocating-a-register-in-zap-assembly.patch | 56 ++++ ...ebug-log-proper-ticket-enctype-names.patch | 29 ++ ...ec-always-log-non-permitted-enctypes.patch | 55 ++++ ...ype-names-in-KDC-logs-human-readable.patch | 297 ++++++++++++++++++ Mark-deprecated-enctypes-when-used.patch | 251 +++++++++++++++ krb5.spec | 11 +- 7 files changed, 883 insertions(+), 1 deletion(-) create mode 100644 Add-function-and-enctype-flag-for-deprecations.patch create mode 100644 Avoid-allocating-a-register-in-zap-assembly.patch create mode 100644 In-kpropd-debug-log-proper-ticket-enctype-names.patch create mode 100644 In-rd_req_dec-always-log-non-permitted-enctypes.patch create mode 100644 Make-etype-names-in-KDC-logs-human-readable.patch create mode 100644 Mark-deprecated-enctypes-when-used.patch 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/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/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..24f1b52 --- /dev/null +++ b/Make-etype-names-in-KDC-logs-human-readable.patch @@ -0,0 +1,297 @@ +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 | 131 +++++++++++++++++++++++---------------------- + src/kdc/kdc_util.h | 6 +-- + 3 files changed, 90 insertions(+), 89 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)) +- +-/* +- * 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) +- +-void +-ktypes2str(char *s, size_t len, int nktypes, krb5_enctype *ktype) ++/* 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) + { +- int i; +- char stmp[D_LEN(krb5_enctype) + 1]; +- char *p; ++ char *name; + +- if (nktypes < 0 +- || len < (sizeof(" etypes {...}") + D_LEN(int))) { +- *s = '\0'; +- return; +- } ++ if (buflen == 0) ++ return EINVAL; ++ *buf = '\0'; /* ensure these are always valid C-strings */ + +- snprintf(s, len, "%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); +- } +- strlcat(s, "}", len); +- return; ++ /* 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); ++ ++ if (strlcpy(name, buf, buflen) >= buflen) ++ return ENOMEM; ++ return 0; + } + +-void +-rep_etypes2str(char *s, size_t len, krb5_kdc_rep *rep) ++char * ++ktypes2str(krb5_enctype *ktype, int nktypes) + { +- char stmp[sizeof("ses=") + D_LEN(krb5_enctype)]; ++ struct k5buf buf; ++ int i; ++ char name[64]; + +- if (len < (3 * D_LEN(krb5_enctype) +- + sizeof("etypes {rep= tkt= ses=}"))) { +- *s = '\0'; +- return; ++ if (nktypes < 0) ++ return NULL; ++ ++ k5_buf_init_dynamic(&buf); ++ k5_buf_add_fmt(&buf, "%d etypes {", nktypes); ++ for (i = 0; i < nktypes; i++) { ++ enctype_name(ktype[i], name, sizeof(name)); ++ k5_buf_add_fmt(&buf, "%s%s(%ld)", i ? ", " : "", name, (long)ktype[i]); + } ++ k5_buf_add(&buf, "}"); ++ return buf.data; ++} + +- snprintf(s, len, "etypes {rep=%ld", (long)rep->enc_part.enctype); ++char * ++rep_etypes2str(krb5_kdc_rep *rep) ++{ ++ struct k5buf buf; ++ char name[64]; ++ krb5_enctype etype; ++ ++ 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/krb5.spec b/krb5.spec index 2b3136a..cce9746 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: 24%{?dist} +Release: 25%{?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 @@ -105,6 +105,12 @@ Patch85: Fix-k5test-prompts-for-Python-3.patch Patch86: In-FIPS-mode-add-plaintext-fallback-for-RC4-usages-a.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 License: MIT URL: http://web.mit.edu/kerberos/www/ @@ -751,6 +757,9 @@ exit 0 %{_libdir}/libkadm5srv_mit.so.* %changelog +* 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 From 59a5a08960ab42c0712657b93f090dee77cd0c71 Mon Sep 17 00:00:00 2001 From: Robbie Harwood Date: Wed, 25 Sep 2019 13:23:27 -0400 Subject: [PATCH 5/5] Fix KDC crash when logging PKINIT enctypes (CVE-2019-14844) --- ...ul-asking-for-AS-key-in-SPAKE-client.patch | 17 ++- ...nate-preprocessor-disabled-dead-code.patch | 4 +- ...C-crash-when-logging-PKINIT-enctypes.patch | 33 +++++ ...ype-names-in-KDC-logs-human-readable.patch | 115 +++++++++--------- ...r-KDC-krb5_pa_data-utility-functions.patch | 54 ++++---- Simplify-kdc_preauth.c-systems-table.patch | 48 ++++---- ...port-hex-functions-where-appropriate.patch | 51 ++++---- krb5.spec | 6 +- 8 files changed, 178 insertions(+), 150 deletions(-) create mode 100644 Fix-KDC-crash-when-logging-PKINIT-enctypes.patch 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/Make-etype-names-in-KDC-logs-human-readable.patch b/Make-etype-names-in-KDC-logs-human-readable.patch index 24f1b52..b3bd46d 100644 --- a/Make-etype-names-in-KDC-logs-human-readable.patch +++ b/Make-etype-names-in-KDC-logs-human-readable.patch @@ -13,9 +13,9 @@ ticket: 8772 (new) (cherry picked from commit b999ade3996817ccb9c9362e4c06dd236e4a854b) --- src/kdc/kdc_log.c | 42 +++++++-------- - src/kdc/kdc_util.c | 131 +++++++++++++++++++++++---------------------- + src/kdc/kdc_util.c | 125 +++++++++++++++++++++++---------------------- src/kdc/kdc_util.h | 6 +-- - 3 files changed, 90 insertions(+), 89 deletions(-) + 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 @@ -133,35 +133,68 @@ index 13111215d..6f83be9db 100644 - * 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) -+/* 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 * ++ktypes2str(krb5_enctype *ktype, int nktypes) { -- int i; ++ struct k5buf buf; + int i; - char stmp[D_LEN(krb5_enctype) + 1]; - char *p; -+ char *name; ++ char name[64]; - if (nktypes < 0 - || len < (sizeof(" etypes {...}") + D_LEN(int))) { - *s = '\0'; - return; - } -+ if (buflen == 0) -+ return EINVAL; -+ *buf = '\0'; /* ensure these are always valid C-strings */ ++ if (nktypes < 0) ++ return NULL; - snprintf(s, len, "%d etypes {", nktypes); -- for (i = 0; i < nktypes; i++) { ++ 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; @@ -181,68 +214,32 @@ index 13111215d..6f83be9db 100644 - } - } - 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; -+ /* 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); -+ -+ if (strlcpy(name, buf, buflen) >= buflen) -+ return ENOMEM; -+ return 0; ++ k5_buf_add(&buf, "}"); ++ return buf.data; } -void -rep_etypes2str(char *s, size_t len, krb5_kdc_rep *rep) +char * -+ktypes2str(krb5_enctype *ktype, int nktypes) ++rep_etypes2str(krb5_kdc_rep *rep) { - char stmp[sizeof("ses=") + D_LEN(krb5_enctype)]; -+ struct k5buf buf; -+ int i; -+ char name[64]; - +- - if (len < (3 * D_LEN(krb5_enctype) - + sizeof("etypes {rep= tkt= ses=}"))) { - *s = '\0'; - return; -+ if (nktypes < 0) -+ return NULL; -+ -+ k5_buf_init_dynamic(&buf); -+ k5_buf_add_fmt(&buf, "%d etypes {", nktypes); -+ for (i = 0; i < nktypes; i++) { -+ enctype_name(ktype[i], name, sizeof(name)); -+ k5_buf_add_fmt(&buf, "%s%s(%ld)", i ? ", " : "", name, (long)ktype[i]); - } -+ k5_buf_add(&buf, "}"); -+ return buf.data; -+} - -- snprintf(s, len, "etypes {rep=%ld", (long)rep->enc_part.enctype); -+char * -+rep_etypes2str(krb5_kdc_rep *rep) -+{ +- } + 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)); 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/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 cce9746..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: 25%{?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 @@ -111,6 +111,7 @@ 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/ @@ -757,6 +758,9 @@ 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()