Compare commits

...
Sign in to create a new pull request.

5 commits

Author SHA1 Message Date
Robbie Harwood
59a5a08960 Fix KDC crash when logging PKINIT enctypes (CVE-2019-14844) 2019-09-25 13:23:27 -04:00
Robbie Harwood
dd7274809c enctype logging and explicit_bzero() 2019-01-17 16:27:24 -05:00
Robbie Harwood
0b47ef8960 Address some optimized-out memset() calls 2019-01-04 10:53:37 -05:00
Adam Williamson
19b9dd17ff 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.
2018-12-28 09:29:34 -08:00
Robbie Harwood
9e69bcd277 Remove incorrect KDC assertion (CVE-2018-20217) 2018-12-20 18:15:55 -05:00
16 changed files with 1151 additions and 491 deletions

View file

@ -0,0 +1,185 @@
From 7b4e3ebc438ec0263b4b7b45a0ad39809699bbec Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
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

View file

@ -0,0 +1,95 @@
From 772178a22bc43df83bfa74992d55f99a5153c03e Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
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;

View file

@ -0,0 +1,56 @@
From 0326bf3250ea674f424d72cdec3672bcc9918d8f Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@samba.org>
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
/*

View file

@ -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. */

View file

@ -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

View file

@ -0,0 +1,33 @@
From cf751906362c803aee6aa33ad1b3b9c3e3502acf Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
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;
}

View file

@ -1,396 +0,0 @@
From f61875dc7da3d5dadb935ebcce25fe66564f7d0f Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
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;
}

View file

@ -0,0 +1,29 @@
From 35fd91ee49ecba137a7f5b5da5f9c56ddef461af Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
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);

View file

@ -0,0 +1,55 @@
From 1bc74278b3393aeb559b0bcd3c7e2bd476f2754b Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
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.

View file

@ -0,0 +1,294 @@
From 3a17abda20fbb92ed20c1466a82fb2c7a656a6ab Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
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 : "<unknown client>";
const char *sname2 = sname ? sname : "<unknown server>";
@@ -74,26 +74,29 @@ log_as_req(krb5_context context,
fromstringbuf, sizeof(fromstringbuf));
if (!fromstring)
fromstring = "<unknown>";
- 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 = "<unknown>";
- 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 : "<unknown client>";
@@ -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

View file

@ -0,0 +1,251 @@
From 378f2ade14ec9bd2f5ab7b0e69d5437e51066584 Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
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), _("<Encryption type 0x%x>"),
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

View file

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

View file

@ -0,0 +1,43 @@
From ca75a685d19fec7c481fd3de9769ac3546e37a11 Mon Sep 17 00:00:00 2001
From: Isaac Boukris <iboukris@gmail.com>
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)

View file

@ -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;
}

View file

@ -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;

View file

@ -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 <rharwood@redhat.com> - 1.16.1-26
- Fix KDC crash when logging PKINIT enctypes (CVE-2019-14844)
* Thu Jan 17 2019 Robbie Harwood <rharwood@redhat.com> - 1.16.1-25
- enctype logging and explicit_bzero()
* Fri Jan 04 2019 Robbie Harwood <rharwood@redhat.com> - 1.16.1-24
- Address some optimized-out memset() calls
* Fri Dec 28 2018 Adam Williamson <awilliam@redhat.com> - 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 <rharwood@redhat.com> - 1.16.1-22
- Remove incorrect KDC assertion (CVE-2018-20217)
* Tue Oct 09 2018 Adam Williamson <awilliam@redhat.com> - 1.16.1-21
- Revert the patch from -20 for now as it seems to make FreeIPA worse