From 1528c264d0e1eebff34132c01f4f770f01f1d1c2 Mon Sep 17 00:00:00 2001 From: Greg Hudson Date: Mon, 29 Mar 2021 14:32:56 -0400 Subject: [PATCH] Fix KCM flag transmission for remove_cred MIT krb5 uses low bits for KRB5_TC flags, while Heimdal uses high bits so that the same flag word can also hold KRB5_GC flags. Add a mapping function and send the Heimdal flag values when performing a remove_cred operation. ticket: 8995 (cherry picked from commit 11a82cf424f9c905bb73680c64524f087090d4ef) --- src/include/kcm.h | 19 +++++++++++++++++++ src/lib/krb5/ccache/cc_kcm.c | 36 +++++++++++++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/src/include/kcm.h b/src/include/kcm.h index e4140c3a0..9b66f1cbd 100644 --- a/src/include/kcm.h +++ b/src/include/kcm.h @@ -56,8 +56,27 @@ * are marshalled as zero-terminated strings. Principals and credentials are * marshalled in the v4 FILE ccache format. UUIDs are 16 bytes. UUID lists * are not delimited, so nothing can come after them. + * + * Flag words must use Heimdal flag values, which are not the same as MIT krb5 + * values for KRB5_GC and KRB5_TC constants. The same flag word may contain + * both kinds of flags in Heimdal, but not in MIT krb5. Defines for the + * applicable Heimdal flag values are given below using KCM_GC and KCM_TC + * prefixes. */ +#define KCM_GC_CACHED (1U << 0) + +#define KCM_TC_DONT_MATCH_REALM (1U << 31) +#define KCM_TC_MATCH_KEYTYPE (1U << 30) +#define KCM_TC_MATCH_SRV_NAMEONLY (1U << 29) +#define KCM_TC_MATCH_FLAGS_EXACT (1U << 28) +#define KCM_TC_MATCH_FLAGS (1U << 27) +#define KCM_TC_MATCH_TIMES_EXACT (1U << 26) +#define KCM_TC_MATCH_TIMES (1U << 25) +#define KCM_TC_MATCH_AUTHDATA (1U << 24) +#define KCM_TC_MATCH_2ND_TKT (1U << 23) +#define KCM_TC_MATCH_IS_SKEY (1U << 22) + /* Opcodes without comments are currently unused in the MIT client * implementation. */ typedef enum kcm_opcode { diff --git a/src/lib/krb5/ccache/cc_kcm.c b/src/lib/krb5/ccache/cc_kcm.c index 772928e4d..1f81a2190 100644 --- a/src/lib/krb5/ccache/cc_kcm.c +++ b/src/lib/krb5/ccache/cc_kcm.c @@ -110,6 +110,40 @@ map_invalid(krb5_error_code code) KRB5_KCM_MALFORMED_REPLY : code; } +/* + * Map an MIT krb5 KRB5_TC flag word to the equivalent Heimdal flag word. Note + * that there is no MIT krb5 equivalent for Heimdal's KRB5_TC_DONT_MATCH_REALM + * (which is like KRB5_TC_MATCH_SRV_NAMEONLY but also applies to the client + * principal) and no Heimdal equivalent for MIT krb5's KRB5_TC_SUPPORTED_KTYPES + * (which matches against enctypes from the krb5_context rather than the + * matching cred). + */ +static inline krb5_flags +map_tcflags(krb5_flags mitflags) +{ + krb5_flags heimflags = 0; + + if (mitflags & KRB5_TC_MATCH_TIMES) + heimflags |= KCM_TC_MATCH_TIMES; + if (mitflags & KRB5_TC_MATCH_IS_SKEY) + heimflags |= KCM_TC_MATCH_IS_SKEY; + if (mitflags & KRB5_TC_MATCH_FLAGS) + heimflags |= KCM_TC_MATCH_FLAGS; + if (mitflags & KRB5_TC_MATCH_TIMES_EXACT) + heimflags |= KCM_TC_MATCH_TIMES_EXACT; + if (mitflags & KRB5_TC_MATCH_FLAGS_EXACT) + heimflags |= KCM_TC_MATCH_FLAGS_EXACT; + if (mitflags & KRB5_TC_MATCH_AUTHDATA) + heimflags |= KCM_TC_MATCH_AUTHDATA; + if (mitflags & KRB5_TC_MATCH_SRV_NAMEONLY) + heimflags |= KCM_TC_MATCH_SRV_NAMEONLY; + if (mitflags & KRB5_TC_MATCH_2ND_TKT) + heimflags |= KCM_TC_MATCH_2ND_TKT; + if (mitflags & KRB5_TC_MATCH_KTYPE) + heimflags |= KCM_TC_MATCH_KEYTYPE; + return heimflags; +} + /* Begin a request for the given opcode. If cache is non-null, supply the * cache name as a request parameter. */ static void @@ -936,7 +970,7 @@ kcm_remove_cred(krb5_context context, krb5_ccache cache, krb5_flags flags, struct kcmreq req; kcmreq_init(&req, KCM_OP_REMOVE_CRED, cache); - k5_buf_add_uint32_be(&req.reqbuf, flags); + k5_buf_add_uint32_be(&req.reqbuf, map_tcflags(flags)); k5_marshal_mcred(&req.reqbuf, mcred); ret = cache_call(context, cache, &req); kcmreq_free(&req);