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