import krb5-1.18.2-14.el8
This commit is contained in:
		
							parent
							
								
									4ded906f6c
								
							
						
					
					
						commit
						ca46c1e298
					
				
							
								
								
									
										222
									
								
								SOURCES/Add-APIs-for-marshalling-credentials.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										222
									
								
								SOURCES/Add-APIs-for-marshalling-credentials.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,222 @@
 | 
			
		||||
From de01999b35773196749ba714f233649c9528aaad Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Robbie Harwood <rharwood@redhat.com>
 | 
			
		||||
Date: Thu, 14 Jan 2021 18:13:09 -0500
 | 
			
		||||
Subject: [PATCH] Add APIs for marshalling credentials
 | 
			
		||||
 | 
			
		||||
Faciliate KCM daemon implementations by providing functions to
 | 
			
		||||
deserialize and reserialize credentials in the FILE v4 format.
 | 
			
		||||
 | 
			
		||||
[ghudson@mit.edu: minor editorial changes]
 | 
			
		||||
 | 
			
		||||
ticket: 8980 (new)
 | 
			
		||||
(cherry picked from commit 18ea3bd2fca55b789b7de9c663624bc11d348fa6)
 | 
			
		||||
(cherry picked from commit 3d11179707923b033fa413387a33296b673ff52d)
 | 
			
		||||
[rharwood@redhat.com: function backport, so conflict in krb5_32.def]
 | 
			
		||||
---
 | 
			
		||||
 doc/appdev/refs/api/index.rst   |  2 ++
 | 
			
		||||
 src/include/krb5/krb5.hin       | 36 ++++++++++++++++++++++
 | 
			
		||||
 src/lib/krb5/ccache/ccmarshal.c | 53 +++++++++++++++++++++++++++++++++
 | 
			
		||||
 src/lib/krb5/ccache/t_marshal.c | 15 +++++++++-
 | 
			
		||||
 src/lib/krb5/libkrb5.exports    |  2 ++
 | 
			
		||||
 src/lib/krb5_32.def             |  4 +++
 | 
			
		||||
 6 files changed, 111 insertions(+), 1 deletion(-)
 | 
			
		||||
 | 
			
		||||
diff --git a/doc/appdev/refs/api/index.rst b/doc/appdev/refs/api/index.rst
 | 
			
		||||
index 727d9b492..9e03fd386 100644
 | 
			
		||||
--- a/doc/appdev/refs/api/index.rst
 | 
			
		||||
+++ b/doc/appdev/refs/api/index.rst
 | 
			
		||||
@@ -232,6 +232,7 @@ Rarely used public interfaces
 | 
			
		||||
    krb5_kt_remove_entry.rst
 | 
			
		||||
    krb5_kt_start_seq_get.rst
 | 
			
		||||
    krb5_make_authdata_kdc_issued.rst
 | 
			
		||||
+   krb5_marshal_credentials.rst
 | 
			
		||||
    krb5_merge_authdata.rst
 | 
			
		||||
    krb5_mk_1cred.rst
 | 
			
		||||
    krb5_mk_error.rst
 | 
			
		||||
@@ -285,6 +286,7 @@ Rarely used public interfaces
 | 
			
		||||
    krb5_tkt_creds_get_times.rst
 | 
			
		||||
    krb5_tkt_creds_init.rst
 | 
			
		||||
    krb5_tkt_creds_step.rst
 | 
			
		||||
+   krb5_unmarshal_credentials.rst
 | 
			
		||||
    krb5_verify_init_creds.rst
 | 
			
		||||
    krb5_verify_init_creds_opt_init.rst
 | 
			
		||||
    krb5_verify_init_creds_opt_set_ap_req_nofail.rst
 | 
			
		||||
diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin
 | 
			
		||||
index 9264bede1..d2cf1eba2 100644
 | 
			
		||||
--- a/src/include/krb5/krb5.hin
 | 
			
		||||
+++ b/src/include/krb5/krb5.hin
 | 
			
		||||
@@ -3125,6 +3125,42 @@ krb5_get_credentials(krb5_context context, krb5_flags options,
 | 
			
		||||
                      krb5_ccache ccache, krb5_creds *in_creds,
 | 
			
		||||
                      krb5_creds **out_creds);
 | 
			
		||||
 
 | 
			
		||||
+/**
 | 
			
		||||
+ * Serialize a @c krb5_creds object.
 | 
			
		||||
+ *
 | 
			
		||||
+ * @param [in]  context         Library context
 | 
			
		||||
+ * @param [in]  creds           The credentials object to serialize
 | 
			
		||||
+ * @param [out] data_out        The serialized credentials
 | 
			
		||||
+ *
 | 
			
		||||
+ * Serialize @a creds in the format used by the FILE ccache format (vesion 4)
 | 
			
		||||
+ * and KCM ccache protocol.
 | 
			
		||||
+ *
 | 
			
		||||
+ * Use krb5_free_data() to free @a data_out when it is no longer needed.
 | 
			
		||||
+ *
 | 
			
		||||
+ * @retval 0 Success; otherwise - Kerberos error codes
 | 
			
		||||
+ */
 | 
			
		||||
+krb5_error_code KRB5_CALLCONV
 | 
			
		||||
+krb5_marshal_credentials(krb5_context context, krb5_creds *in_creds,
 | 
			
		||||
+                         krb5_data **data_out);
 | 
			
		||||
+
 | 
			
		||||
+/**
 | 
			
		||||
+ * Deserialize a @c krb5_creds object.
 | 
			
		||||
+ *
 | 
			
		||||
+ * @param [in]  context         Library context
 | 
			
		||||
+ * @param [in]  data            The serialized credentials
 | 
			
		||||
+ * @param [out] creds_out       The resulting creds object
 | 
			
		||||
+ *
 | 
			
		||||
+ * Deserialize @a data to credentials in the format used by the FILE ccache
 | 
			
		||||
+ * format (vesion 4) and KCM ccache protocol.
 | 
			
		||||
+ *
 | 
			
		||||
+ * Use krb5_free_creds() to free @a creds_out when it is no longer needed.
 | 
			
		||||
+ *
 | 
			
		||||
+ * @retval 0 Success; otherwise - Kerberos error codes
 | 
			
		||||
+ */
 | 
			
		||||
+krb5_error_code KRB5_CALLCONV
 | 
			
		||||
+krb5_unmarshal_credentials(krb5_context context, const krb5_data *data,
 | 
			
		||||
+                           krb5_creds **creds_out);
 | 
			
		||||
+
 | 
			
		||||
 /** @deprecated Replaced by krb5_get_validated_creds. */
 | 
			
		||||
 krb5_error_code KRB5_CALLCONV
 | 
			
		||||
 krb5_get_credentials_validate(krb5_context context, krb5_flags options,
 | 
			
		||||
diff --git a/src/lib/krb5/ccache/ccmarshal.c b/src/lib/krb5/ccache/ccmarshal.c
 | 
			
		||||
index ae634ccab..ab284e721 100644
 | 
			
		||||
--- a/src/lib/krb5/ccache/ccmarshal.c
 | 
			
		||||
+++ b/src/lib/krb5/ccache/ccmarshal.c
 | 
			
		||||
@@ -515,3 +515,56 @@ k5_marshal_mcred(struct k5buf *buf, krb5_creds *mcred)
 | 
			
		||||
     if (mcred->second_ticket.length > 0)
 | 
			
		||||
         put_data(buf, version, &mcred->second_ticket);
 | 
			
		||||
 }
 | 
			
		||||
+
 | 
			
		||||
+krb5_error_code KRB5_CALLCONV
 | 
			
		||||
+krb5_marshal_credentials(krb5_context context, krb5_creds *in_creds,
 | 
			
		||||
+                         krb5_data **data_out)
 | 
			
		||||
+{
 | 
			
		||||
+    krb5_error_code ret;
 | 
			
		||||
+    krb5_data *data;
 | 
			
		||||
+    struct k5buf buf;
 | 
			
		||||
+
 | 
			
		||||
+    *data_out = NULL;
 | 
			
		||||
+
 | 
			
		||||
+    data = k5alloc(sizeof(krb5_data), &ret);
 | 
			
		||||
+    if (ret)
 | 
			
		||||
+        return ret;
 | 
			
		||||
+
 | 
			
		||||
+    k5_buf_init_dynamic(&buf);
 | 
			
		||||
+    k5_marshal_cred(&buf, 4, in_creds);
 | 
			
		||||
+
 | 
			
		||||
+    ret = k5_buf_status(&buf);
 | 
			
		||||
+    if (ret) {
 | 
			
		||||
+        free(data);
 | 
			
		||||
+        return ret;
 | 
			
		||||
+    }
 | 
			
		||||
+
 | 
			
		||||
+    /* Steal payload from buf. */
 | 
			
		||||
+    *data = make_data(buf.data, buf.len);
 | 
			
		||||
+    *data_out = data;
 | 
			
		||||
+    return 0;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+krb5_error_code KRB5_CALLCONV
 | 
			
		||||
+krb5_unmarshal_credentials(krb5_context context, const krb5_data *data,
 | 
			
		||||
+                           krb5_creds **creds_out)
 | 
			
		||||
+{
 | 
			
		||||
+    krb5_error_code ret;
 | 
			
		||||
+    krb5_creds *creds;
 | 
			
		||||
+
 | 
			
		||||
+    *creds_out = NULL;
 | 
			
		||||
+
 | 
			
		||||
+    creds = k5alloc(sizeof(krb5_creds), &ret);
 | 
			
		||||
+    if (ret)
 | 
			
		||||
+        return ret;
 | 
			
		||||
+
 | 
			
		||||
+    ret = k5_unmarshal_cred((unsigned char *)data->data, data->length, 4,
 | 
			
		||||
+                            creds);
 | 
			
		||||
+    if (ret) {
 | 
			
		||||
+        free(creds);
 | 
			
		||||
+        return ret;
 | 
			
		||||
+    }
 | 
			
		||||
+
 | 
			
		||||
+    *creds_out = creds;
 | 
			
		||||
+    return 0;
 | 
			
		||||
+}
 | 
			
		||||
diff --git a/src/lib/krb5/ccache/t_marshal.c b/src/lib/krb5/ccache/t_marshal.c
 | 
			
		||||
index 144554c30..47ec2e94d 100644
 | 
			
		||||
--- a/src/lib/krb5/ccache/t_marshal.c
 | 
			
		||||
+++ b/src/lib/krb5/ccache/t_marshal.c
 | 
			
		||||
@@ -268,13 +268,14 @@ main(int argc, char **argv)
 | 
			
		||||
     krb5_context context;
 | 
			
		||||
     krb5_ccache cache;
 | 
			
		||||
     krb5_principal princ;
 | 
			
		||||
-    krb5_creds cred1, cred2;
 | 
			
		||||
+    krb5_creds cred1, cred2, *alloc_cred;
 | 
			
		||||
     krb5_cc_cursor cursor;
 | 
			
		||||
     const char *filename;
 | 
			
		||||
     char *ccname, filebuf[256];
 | 
			
		||||
     int version, fd;
 | 
			
		||||
     const struct test *t;
 | 
			
		||||
     struct k5buf buf;
 | 
			
		||||
+    krb5_data ser_data, *alloc_data;
 | 
			
		||||
 
 | 
			
		||||
     if (argc != 2)
 | 
			
		||||
         abort();
 | 
			
		||||
@@ -285,6 +286,18 @@ main(int argc, char **argv)
 | 
			
		||||
     if (krb5_init_context(&context) != 0)
 | 
			
		||||
         abort();
 | 
			
		||||
 
 | 
			
		||||
+    /* Test public functions for unmarshalling and marshalling. */
 | 
			
		||||
+    ser_data = make_data((char *)tests[3].cred1, tests[3].cred1len);
 | 
			
		||||
+    if (krb5_unmarshal_credentials(context, &ser_data, &alloc_cred) != 0)
 | 
			
		||||
+        abort();
 | 
			
		||||
+    verify_cred1(alloc_cred);
 | 
			
		||||
+    if (krb5_marshal_credentials(context, alloc_cred, &alloc_data) != 0)
 | 
			
		||||
+        abort();
 | 
			
		||||
+    assert(alloc_data->length == tests[3].cred1len);
 | 
			
		||||
+    assert(memcmp(tests[3].cred1, alloc_data->data, alloc_data->length) == 0);
 | 
			
		||||
+    krb5_free_data(context, alloc_data);
 | 
			
		||||
+    krb5_free_creds(context, alloc_cred);
 | 
			
		||||
+
 | 
			
		||||
     for (version = FIRST_VERSION; version <= 4; version++) {
 | 
			
		||||
         t = &tests[version - 1];
 | 
			
		||||
 
 | 
			
		||||
diff --git a/src/lib/krb5/libkrb5.exports b/src/lib/krb5/libkrb5.exports
 | 
			
		||||
index cab5b3b17..48ae46f5c 100644
 | 
			
		||||
--- a/src/lib/krb5/libkrb5.exports
 | 
			
		||||
+++ b/src/lib/krb5/libkrb5.exports
 | 
			
		||||
@@ -488,6 +488,7 @@ krb5_lock_file
 | 
			
		||||
 krb5_make_authdata_kdc_issued
 | 
			
		||||
 krb5_make_full_ipaddr
 | 
			
		||||
 krb5_make_fulladdr
 | 
			
		||||
+krb5_marshal_credentials
 | 
			
		||||
 krb5_mcc_ops
 | 
			
		||||
 krb5_merge_authdata
 | 
			
		||||
 krb5_mk_1cred
 | 
			
		||||
@@ -592,6 +593,7 @@ krb5_timeofday
 | 
			
		||||
 krb5_timestamp_to_sfstring
 | 
			
		||||
 krb5_timestamp_to_string
 | 
			
		||||
 krb5_unlock_file
 | 
			
		||||
+krb5_unmarshal_credentials
 | 
			
		||||
 krb5_unpack_full_ipaddr
 | 
			
		||||
 krb5_unparse_name
 | 
			
		||||
 krb5_unparse_name_ext
 | 
			
		||||
diff --git a/src/lib/krb5_32.def b/src/lib/krb5_32.def
 | 
			
		||||
index de5823c17..209c6aaef 100644
 | 
			
		||||
--- a/src/lib/krb5_32.def
 | 
			
		||||
+++ b/src/lib/krb5_32.def
 | 
			
		||||
@@ -502,3 +502,7 @@ EXPORTS
 | 
			
		||||
 
 | 
			
		||||
 ; new in 1.19
 | 
			
		||||
 	k5_cc_store_primary_cred			@470 ; PRIVATE
 | 
			
		||||
+
 | 
			
		||||
+; new in 1.20
 | 
			
		||||
+	krb5_marshal_credentials			@472
 | 
			
		||||
+	krb5_unmarshal_credentials			@473
 | 
			
		||||
							
								
								
									
										360
									
								
								SOURCES/Add-KCM_OP_GET_CRED_LIST-for-faster-iteration.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										360
									
								
								SOURCES/Add-KCM_OP_GET_CRED_LIST-for-faster-iteration.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,360 @@
 | 
			
		||||
From d4a512e571a93318d37cbf7d18a120f317b87e97 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
 | 
			
		||||
Date: Thu, 11 Feb 2021 15:33:10 +0100
 | 
			
		||||
Subject: [PATCH] Add KCM_OP_GET_CRED_LIST for faster iteration
 | 
			
		||||
 | 
			
		||||
For large caches, one IPC operation per credential dominates the cost
 | 
			
		||||
of iteration.  Instead transfer the whole list of credentials to the
 | 
			
		||||
client in one IPC operation.
 | 
			
		||||
 | 
			
		||||
Add optional support for the new opcode to the test KCM server to
 | 
			
		||||
allow testing of the main and fallback code paths.
 | 
			
		||||
 | 
			
		||||
[ghudson@mit.edu: fixed memory leaks and potential memory errors;
 | 
			
		||||
adjusted code style and comments; rewrote commit message; added
 | 
			
		||||
kcmserver.py support and tests]
 | 
			
		||||
 | 
			
		||||
ticket: 8990 (new)
 | 
			
		||||
(cherry picked from commit 81bdb47d8ded390263d8ee48f71d5c312b4f1736)
 | 
			
		||||
(cherry picked from commit a0ee8b02e56c65e5dcd569caed0e151cef004ef4)
 | 
			
		||||
(cherry picked from commit baf60dbdeceb3cad35cad7d9930782f94b6c8221)
 | 
			
		||||
---
 | 
			
		||||
 src/include/kcm.h            |  12 ++-
 | 
			
		||||
 src/lib/krb5/ccache/cc_kcm.c | 144 ++++++++++++++++++++++++++++++++---
 | 
			
		||||
 src/tests/kcmserver.py       |  28 ++++++-
 | 
			
		||||
 src/tests/t_ccache.py        |  10 ++-
 | 
			
		||||
 4 files changed, 175 insertions(+), 19 deletions(-)
 | 
			
		||||
 | 
			
		||||
diff --git a/src/include/kcm.h b/src/include/kcm.h
 | 
			
		||||
index 5ea1447cd..e4140c3a0 100644
 | 
			
		||||
--- a/src/include/kcm.h
 | 
			
		||||
+++ b/src/include/kcm.h
 | 
			
		||||
@@ -51,9 +51,9 @@
 | 
			
		||||
  *
 | 
			
		||||
  * All replies begin with a 32-bit big-endian reply code.
 | 
			
		||||
  *
 | 
			
		||||
- * Parameters are appended to the request or reply with no delimiters.  Flags
 | 
			
		||||
- * and time offsets are stored as 32-bit big-endian integers.  Names are
 | 
			
		||||
- * marshalled as zero-terminated strings.  Principals and credentials are
 | 
			
		||||
+ * Parameters are appended to the request or reply with no delimiters.  Flags,
 | 
			
		||||
+ * time offsets, and lengths are stored as 32-bit big-endian integers.  Names
 | 
			
		||||
+ * 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.
 | 
			
		||||
  */
 | 
			
		||||
@@ -89,7 +89,11 @@ typedef enum kcm_opcode {
 | 
			
		||||
     KCM_OP_HAVE_NTLM_CRED,
 | 
			
		||||
     KCM_OP_DEL_NTLM_CRED,
 | 
			
		||||
     KCM_OP_DO_NTLM_AUTH,
 | 
			
		||||
-    KCM_OP_GET_NTLM_USER_LIST
 | 
			
		||||
+    KCM_OP_GET_NTLM_USER_LIST,
 | 
			
		||||
+
 | 
			
		||||
+    /* MIT extensions */
 | 
			
		||||
+    KCM_OP_MIT_EXTENSION_BASE = 13000,
 | 
			
		||||
+    KCM_OP_GET_CRED_LIST,       /* (name) -> (count, count*{len, cred}) */
 | 
			
		||||
 } kcm_opcode;
 | 
			
		||||
 
 | 
			
		||||
 #endif /* KCM_H */
 | 
			
		||||
diff --git a/src/lib/krb5/ccache/cc_kcm.c b/src/lib/krb5/ccache/cc_kcm.c
 | 
			
		||||
index a76a285d9..197a10fba 100644
 | 
			
		||||
--- a/src/lib/krb5/ccache/cc_kcm.c
 | 
			
		||||
+++ b/src/lib/krb5/ccache/cc_kcm.c
 | 
			
		||||
@@ -61,6 +61,17 @@ struct uuid_list {
 | 
			
		||||
     size_t pos;
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
+struct cred_list {
 | 
			
		||||
+    krb5_creds *creds;
 | 
			
		||||
+    size_t count;
 | 
			
		||||
+    size_t pos;
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+struct kcm_cursor {
 | 
			
		||||
+    struct uuid_list *uuids;
 | 
			
		||||
+    struct cred_list *creds;
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
 struct kcmio {
 | 
			
		||||
     SOCKET fd;
 | 
			
		||||
 #ifdef __APPLE__
 | 
			
		||||
@@ -489,6 +500,69 @@ free_uuid_list(struct uuid_list *uuids)
 | 
			
		||||
     free(uuids);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+static void
 | 
			
		||||
+free_cred_list(struct cred_list *list)
 | 
			
		||||
+{
 | 
			
		||||
+    size_t i;
 | 
			
		||||
+
 | 
			
		||||
+    if (list == NULL)
 | 
			
		||||
+        return;
 | 
			
		||||
+
 | 
			
		||||
+    /* Creds are transferred to the caller as list->pos is incremented, so we
 | 
			
		||||
+     * can start freeing there. */
 | 
			
		||||
+    for (i = list->pos; i < list->count; i++)
 | 
			
		||||
+        krb5_free_cred_contents(NULL, &list->creds[i]);
 | 
			
		||||
+    free(list->creds);
 | 
			
		||||
+    free(list);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+/* Fetch a cred list from req->reply. */
 | 
			
		||||
+static krb5_error_code
 | 
			
		||||
+kcmreq_get_cred_list(struct kcmreq *req, struct cred_list **creds_out)
 | 
			
		||||
+{
 | 
			
		||||
+    struct cred_list *list;
 | 
			
		||||
+    const unsigned char *data;
 | 
			
		||||
+    krb5_error_code ret = 0;
 | 
			
		||||
+    size_t count, len, i;
 | 
			
		||||
+
 | 
			
		||||
+    *creds_out = NULL;
 | 
			
		||||
+
 | 
			
		||||
+    /* Check a rough bound on the count to prevent very large allocations. */
 | 
			
		||||
+    count = k5_input_get_uint32_be(&req->reply);
 | 
			
		||||
+    if (count > req->reply.len / 4)
 | 
			
		||||
+        return KRB5_KCM_MALFORMED_REPLY;
 | 
			
		||||
+
 | 
			
		||||
+    list = malloc(sizeof(*list));
 | 
			
		||||
+    if (list == NULL)
 | 
			
		||||
+        return ENOMEM;
 | 
			
		||||
+
 | 
			
		||||
+    list->creds = NULL;
 | 
			
		||||
+    list->count = count;
 | 
			
		||||
+    list->pos = 0;
 | 
			
		||||
+    list->creds = k5calloc(count, sizeof(*list->creds), &ret);
 | 
			
		||||
+    if (list->creds == NULL) {
 | 
			
		||||
+        free(list);
 | 
			
		||||
+        return ret;
 | 
			
		||||
+    }
 | 
			
		||||
+
 | 
			
		||||
+    for (i = 0; i < count; i++) {
 | 
			
		||||
+        len = k5_input_get_uint32_be(&req->reply);
 | 
			
		||||
+        data = k5_input_get_bytes(&req->reply, len);
 | 
			
		||||
+        if (data == NULL)
 | 
			
		||||
+            break;
 | 
			
		||||
+        ret = k5_unmarshal_cred(data, len, 4, &list->creds[i]);
 | 
			
		||||
+        if (ret)
 | 
			
		||||
+            break;
 | 
			
		||||
+    }
 | 
			
		||||
+    if (i < count) {
 | 
			
		||||
+        free_cred_list(list);
 | 
			
		||||
+        return (ret == ENOMEM) ? ENOMEM : KRB5_KCM_MALFORMED_REPLY;
 | 
			
		||||
+    }
 | 
			
		||||
+
 | 
			
		||||
+    *creds_out = list;
 | 
			
		||||
+    return 0;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 static void
 | 
			
		||||
 kcmreq_free(struct kcmreq *req)
 | 
			
		||||
 {
 | 
			
		||||
@@ -753,33 +827,53 @@ kcm_start_seq_get(krb5_context context, krb5_ccache cache,
 | 
			
		||||
 {
 | 
			
		||||
     krb5_error_code ret;
 | 
			
		||||
     struct kcmreq req = EMPTY_KCMREQ;
 | 
			
		||||
-    struct uuid_list *uuids;
 | 
			
		||||
+    struct uuid_list *uuids = NULL;
 | 
			
		||||
+    struct cred_list *creds = NULL;
 | 
			
		||||
+    struct kcm_cursor *cursor;
 | 
			
		||||
 
 | 
			
		||||
     *cursor_out = NULL;
 | 
			
		||||
 
 | 
			
		||||
     get_kdc_offset(context, cache);
 | 
			
		||||
 
 | 
			
		||||
-    kcmreq_init(&req, KCM_OP_GET_CRED_UUID_LIST, cache);
 | 
			
		||||
+    kcmreq_init(&req, KCM_OP_GET_CRED_LIST, cache);
 | 
			
		||||
     ret = cache_call(context, cache, &req);
 | 
			
		||||
-    if (ret)
 | 
			
		||||
+    if (ret == 0) {
 | 
			
		||||
+        /* GET_CRED_LIST is available. */
 | 
			
		||||
+        ret = kcmreq_get_cred_list(&req, &creds);
 | 
			
		||||
+        if (ret)
 | 
			
		||||
+            goto cleanup;
 | 
			
		||||
+    } else if (ret == KRB5_FCC_INTERNAL) {
 | 
			
		||||
+        /* Fall back to GET_CRED_UUID_LIST. */
 | 
			
		||||
+        kcmreq_free(&req);
 | 
			
		||||
+        kcmreq_init(&req, KCM_OP_GET_CRED_UUID_LIST, cache);
 | 
			
		||||
+        ret = cache_call(context, cache, &req);
 | 
			
		||||
+        if (ret)
 | 
			
		||||
+            goto cleanup;
 | 
			
		||||
+        ret = kcmreq_get_uuid_list(&req, &uuids);
 | 
			
		||||
+        if (ret)
 | 
			
		||||
+            goto cleanup;
 | 
			
		||||
+    } else {
 | 
			
		||||
         goto cleanup;
 | 
			
		||||
-    ret = kcmreq_get_uuid_list(&req, &uuids);
 | 
			
		||||
-    if (ret)
 | 
			
		||||
+    }
 | 
			
		||||
+
 | 
			
		||||
+    cursor = k5alloc(sizeof(*cursor), &ret);
 | 
			
		||||
+    if (cursor == NULL)
 | 
			
		||||
         goto cleanup;
 | 
			
		||||
-    *cursor_out = (krb5_cc_cursor)uuids;
 | 
			
		||||
+    cursor->uuids = uuids;
 | 
			
		||||
+    cursor->creds = creds;
 | 
			
		||||
+    *cursor_out = (krb5_cc_cursor)cursor;
 | 
			
		||||
 
 | 
			
		||||
 cleanup:
 | 
			
		||||
     kcmreq_free(&req);
 | 
			
		||||
     return ret;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-static krb5_error_code KRB5_CALLCONV
 | 
			
		||||
-kcm_next_cred(krb5_context context, krb5_ccache cache, krb5_cc_cursor *cursor,
 | 
			
		||||
-              krb5_creds *cred_out)
 | 
			
		||||
+static krb5_error_code
 | 
			
		||||
+next_cred_by_uuid(krb5_context context, krb5_ccache cache,
 | 
			
		||||
+                  struct uuid_list *uuids, krb5_creds *cred_out)
 | 
			
		||||
 {
 | 
			
		||||
     krb5_error_code ret;
 | 
			
		||||
     struct kcmreq req;
 | 
			
		||||
-    struct uuid_list *uuids = (struct uuid_list *)*cursor;
 | 
			
		||||
 
 | 
			
		||||
     memset(cred_out, 0, sizeof(*cred_out));
 | 
			
		||||
 
 | 
			
		||||
@@ -797,11 +891,39 @@ kcm_next_cred(krb5_context context, krb5_ccache cache, krb5_cc_cursor *cursor,
 | 
			
		||||
     return map_invalid(ret);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+static krb5_error_code KRB5_CALLCONV
 | 
			
		||||
+kcm_next_cred(krb5_context context, krb5_ccache cache, krb5_cc_cursor *cursor,
 | 
			
		||||
+              krb5_creds *cred_out)
 | 
			
		||||
+{
 | 
			
		||||
+    struct kcm_cursor *c = (struct kcm_cursor *)*cursor;
 | 
			
		||||
+    struct cred_list *list;
 | 
			
		||||
+
 | 
			
		||||
+    if (c->uuids != NULL)
 | 
			
		||||
+        return next_cred_by_uuid(context, cache, c->uuids, cred_out);
 | 
			
		||||
+
 | 
			
		||||
+    list = c->creds;
 | 
			
		||||
+    if (list->pos >= list->count)
 | 
			
		||||
+        return KRB5_CC_END;
 | 
			
		||||
+
 | 
			
		||||
+    /* Transfer memory ownership of one cred to the caller. */
 | 
			
		||||
+    *cred_out = list->creds[list->pos];
 | 
			
		||||
+    memset(&list->creds[list->pos], 0, sizeof(*list->creds));
 | 
			
		||||
+    list->pos++;
 | 
			
		||||
+
 | 
			
		||||
+    return 0;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 static krb5_error_code KRB5_CALLCONV
 | 
			
		||||
 kcm_end_seq_get(krb5_context context, krb5_ccache cache,
 | 
			
		||||
                 krb5_cc_cursor *cursor)
 | 
			
		||||
 {
 | 
			
		||||
-    free_uuid_list((struct uuid_list *)*cursor);
 | 
			
		||||
+    struct kcm_cursor *c = *cursor;
 | 
			
		||||
+
 | 
			
		||||
+    if (c == NULL)
 | 
			
		||||
+        return 0;
 | 
			
		||||
+    free_uuid_list(c->uuids);
 | 
			
		||||
+    free_cred_list(c->creds);
 | 
			
		||||
+    free(c);
 | 
			
		||||
     *cursor = NULL;
 | 
			
		||||
     return 0;
 | 
			
		||||
 }
 | 
			
		||||
diff --git a/src/tests/kcmserver.py b/src/tests/kcmserver.py
 | 
			
		||||
index 57432e5a7..8c5e66ff1 100644
 | 
			
		||||
--- a/src/tests/kcmserver.py
 | 
			
		||||
+++ b/src/tests/kcmserver.py
 | 
			
		||||
@@ -23,6 +23,7 @@
 | 
			
		||||
 #         traceback.print_exception(etype, value, tb, file=f)
 | 
			
		||||
 # sys.excepthook = ehook
 | 
			
		||||
 
 | 
			
		||||
+import optparse
 | 
			
		||||
 import select
 | 
			
		||||
 import socket
 | 
			
		||||
 import struct
 | 
			
		||||
@@ -49,12 +50,14 @@ class KCMOpcodes(object):
 | 
			
		||||
     SET_DEFAULT_CACHE = 21
 | 
			
		||||
     GET_KDC_OFFSET = 22
 | 
			
		||||
     SET_KDC_OFFSET = 23
 | 
			
		||||
+    GET_CRED_LIST = 13001
 | 
			
		||||
 
 | 
			
		||||
 
 | 
			
		||||
 class KRB5Errors(object):
 | 
			
		||||
     KRB5_CC_END = -1765328242
 | 
			
		||||
     KRB5_CC_NOSUPP = -1765328137
 | 
			
		||||
     KRB5_FCC_NOFILE = -1765328189
 | 
			
		||||
+    KRB5_FCC_INTERNAL = -1765328188
 | 
			
		||||
 
 | 
			
		||||
 
 | 
			
		||||
 def make_uuid():
 | 
			
		||||
@@ -183,6 +186,14 @@ def op_set_kdc_offset(argbytes):
 | 
			
		||||
     return 0, b''
 | 
			
		||||
 
 | 
			
		||||
 
 | 
			
		||||
+def op_get_cred_list(argbytes):
 | 
			
		||||
+    name, rest = unmarshal_name(argbytes)
 | 
			
		||||
+    cache = get_cache(name)
 | 
			
		||||
+    creds = [cache.creds[u] for u in cache.cred_uuids]
 | 
			
		||||
+    return 0, (struct.pack('>L', len(creds)) +
 | 
			
		||||
+               b''.join(struct.pack('>L', len(c)) + c for c in creds))
 | 
			
		||||
+
 | 
			
		||||
+
 | 
			
		||||
 ophandlers = {
 | 
			
		||||
     KCMOpcodes.GEN_NEW : op_gen_new,
 | 
			
		||||
     KCMOpcodes.INITIALIZE : op_initialize,
 | 
			
		||||
@@ -197,7 +208,8 @@ ophandlers = {
 | 
			
		||||
     KCMOpcodes.GET_DEFAULT_CACHE : op_get_default_cache,
 | 
			
		||||
     KCMOpcodes.SET_DEFAULT_CACHE : op_set_default_cache,
 | 
			
		||||
     KCMOpcodes.GET_KDC_OFFSET : op_get_kdc_offset,
 | 
			
		||||
-    KCMOpcodes.SET_KDC_OFFSET : op_set_kdc_offset
 | 
			
		||||
+    KCMOpcodes.SET_KDC_OFFSET : op_set_kdc_offset,
 | 
			
		||||
+    KCMOpcodes.GET_CRED_LIST : op_get_cred_list
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 # Read and respond to a request from the socket s.
 | 
			
		||||
@@ -215,7 +227,11 @@ def service_request(s):
 | 
			
		||||
 
 | 
			
		||||
     majver, minver, op = struct.unpack('>BBH', req[:4])
 | 
			
		||||
     argbytes = req[4:]
 | 
			
		||||
-    code, payload = ophandlers[op](argbytes)
 | 
			
		||||
+
 | 
			
		||||
+    if op in ophandlers:
 | 
			
		||||
+        code, payload = ophandlers[op](argbytes)
 | 
			
		||||
+    else:
 | 
			
		||||
+        code, payload = KRB5Errors.KRB5_FCC_INTERNAL, b''
 | 
			
		||||
 
 | 
			
		||||
     # The KCM response is the code (4 bytes) and the response payload.
 | 
			
		||||
     # The Heimdal IPC response is the length of the KCM response (4
 | 
			
		||||
@@ -226,9 +242,15 @@ def service_request(s):
 | 
			
		||||
     s.sendall(hipc_response)
 | 
			
		||||
     return True
 | 
			
		||||
 
 | 
			
		||||
+parser = optparse.OptionParser()
 | 
			
		||||
+parser.add_option('-c', '--credlist', action='store_true', dest='credlist',
 | 
			
		||||
+                  default=False, help='Support KCM_OP_GET_CRED_LIST')
 | 
			
		||||
+(options, args) = parser.parse_args()
 | 
			
		||||
+if not options.credlist:
 | 
			
		||||
+    del ophandlers[KCMOpcodes.GET_CRED_LIST]
 | 
			
		||||
 
 | 
			
		||||
 server = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
 | 
			
		||||
-server.bind(sys.argv[1])
 | 
			
		||||
+server.bind(args[0])
 | 
			
		||||
 server.listen(5)
 | 
			
		||||
 select_input = [server,]
 | 
			
		||||
 sys.stderr.write('starting...\n')
 | 
			
		||||
diff --git a/src/tests/t_ccache.py b/src/tests/t_ccache.py
 | 
			
		||||
index 66804afa5..90040fb7b 100755
 | 
			
		||||
--- a/src/tests/t_ccache.py
 | 
			
		||||
+++ b/src/tests/t_ccache.py
 | 
			
		||||
@@ -125,10 +125,18 @@ def collection_test(realm, ccname):
 | 
			
		||||
 
 | 
			
		||||
 
 | 
			
		||||
 collection_test(realm, 'DIR:' + os.path.join(realm.testdir, 'cc'))
 | 
			
		||||
+
 | 
			
		||||
+# Test KCM without and with GET_CRED_LIST support.
 | 
			
		||||
 kcmserver_path = os.path.join(srctop, 'tests', 'kcmserver.py')
 | 
			
		||||
-realm.start_server([sys.executable, kcmserver_path, kcm_socket_path],
 | 
			
		||||
+kcmd = realm.start_server([sys.executable, kcmserver_path, kcm_socket_path],
 | 
			
		||||
+                          'starting...')
 | 
			
		||||
+collection_test(realm, 'KCM:')
 | 
			
		||||
+stop_daemon(kcmd)
 | 
			
		||||
+os.remove(kcm_socket_path)
 | 
			
		||||
+realm.start_server([sys.executable, kcmserver_path, '-c', kcm_socket_path],
 | 
			
		||||
                    'starting...')
 | 
			
		||||
 collection_test(realm, 'KCM:')
 | 
			
		||||
+
 | 
			
		||||
 if test_keyring:
 | 
			
		||||
     def cleanup_keyring(anchor, name):
 | 
			
		||||
         out = realm.run(['keyctl', 'list', anchor])
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
From 3a5576fab22ecd21bbf72cccec5be2096e0e05c4 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From 3c47e4adbed5e0a2e7f3993a24097889216a9d50 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Greg Hudson <ghudson@mit.edu>
 | 
			
		||||
Date: Sat, 31 Oct 2020 17:07:05 -0400
 | 
			
		||||
Subject: [PATCH] Add recursion limit for ASN.1 indefinite lengths
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										303
									
								
								SOURCES/Add-support-for-start_realm-cache-config.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										303
									
								
								SOURCES/Add-support-for-start_realm-cache-config.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,303 @@
 | 
			
		||||
From bb5552ece2a351dc3ccab52cceea1eaffeacd768 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Greg Hudson <ghudson@mit.edu>
 | 
			
		||||
Date: Mon, 14 Dec 2020 13:16:17 -0500
 | 
			
		||||
Subject: [PATCH] Add support for start_realm cache config
 | 
			
		||||
 | 
			
		||||
When making TGS requests, if start_realm is set in the cache, use the
 | 
			
		||||
named realm to look up the initial TGT for referral or cross-realm
 | 
			
		||||
requests.  (Also correct a comment in struct _tkt_creds_context: the
 | 
			
		||||
ccache field is an owner pointer, not an alias.)
 | 
			
		||||
 | 
			
		||||
Add an internal API k5_cc_store_primary_cred(), which sets start_realm
 | 
			
		||||
if the cred being stored is a TGT for a realm other than the client
 | 
			
		||||
realm.  Use this API when acquiring initial tickets with a
 | 
			
		||||
caller-specified output ccache, when renewing or validating tickets
 | 
			
		||||
with kinit, when accepting a delegated credential in a GSS context,
 | 
			
		||||
and when storing a single cred with kvno --out-cache.
 | 
			
		||||
 | 
			
		||||
ticket: 8332
 | 
			
		||||
tags: pullup
 | 
			
		||||
target_version: 1.19
 | 
			
		||||
 | 
			
		||||
(cherry picked from commit 0d56740ab9fcc40dc7f46c6fbebdf8f1214f9d96)
 | 
			
		||||
[rharwood@redhat.com: backport around spelling and canonicalization fallback]
 | 
			
		||||
---
 | 
			
		||||
 doc/formats/ccache_file_format.rst       |  6 +++++
 | 
			
		||||
 src/clients/kinit/kinit.c                |  2 +-
 | 
			
		||||
 src/clients/kvno/kvno.c                  |  5 ++++-
 | 
			
		||||
 src/include/k5-int.h                     |  4 ++++
 | 
			
		||||
 src/lib/gssapi/krb5/accept_sec_context.c |  2 +-
 | 
			
		||||
 src/lib/krb5/ccache/ccfns.c              | 20 +++++++++++++++++
 | 
			
		||||
 src/lib/krb5/krb/get_creds.c             | 28 ++++++++++++++++++------
 | 
			
		||||
 src/lib/krb5/krb/get_in_tkt.c            |  2 +-
 | 
			
		||||
 src/lib/krb5/libkrb5.exports             |  1 +
 | 
			
		||||
 src/lib/krb5_32.def                      |  3 +++
 | 
			
		||||
 src/tests/t_crossrealm.py                |  8 +++++++
 | 
			
		||||
 src/tests/t_pkinit.py                    |  3 +++
 | 
			
		||||
 12 files changed, 73 insertions(+), 11 deletions(-)
 | 
			
		||||
 | 
			
		||||
diff --git a/doc/formats/ccache_file_format.rst b/doc/formats/ccache_file_format.rst
 | 
			
		||||
index 6349e0d29..6138c1b58 100644
 | 
			
		||||
--- a/doc/formats/ccache_file_format.rst
 | 
			
		||||
+++ b/doc/formats/ccache_file_format.rst
 | 
			
		||||
@@ -174,3 +174,9 @@ refresh_time
 | 
			
		||||
     decimal representation of a timestamp at which the GSS mechanism
 | 
			
		||||
     should attempt to refresh the credential cache from the client
 | 
			
		||||
     keytab.
 | 
			
		||||
+
 | 
			
		||||
+start_realm
 | 
			
		||||
+    This key indicates the realm of the ticket-granting ticket to be
 | 
			
		||||
+    used for TGS requests, when making a referrals request or
 | 
			
		||||
+    beginning a cross-realm request.  If it is not present, the client
 | 
			
		||||
+    realm is used.
 | 
			
		||||
diff --git a/src/clients/kinit/kinit.c b/src/clients/kinit/kinit.c
 | 
			
		||||
index 3fdae2878..e5ebeb895 100644
 | 
			
		||||
--- a/src/clients/kinit/kinit.c
 | 
			
		||||
+++ b/src/clients/kinit/kinit.c
 | 
			
		||||
@@ -828,7 +828,7 @@ k5_kinit(struct k_opts *opts, struct k5_data *k5)
 | 
			
		||||
         if (opts->verbose)
 | 
			
		||||
             fprintf(stderr, _("Initialized cache\n"));
 | 
			
		||||
 
 | 
			
		||||
-        ret = krb5_cc_store_cred(k5->ctx, k5->out_cc, &my_creds);
 | 
			
		||||
+        ret = k5_cc_store_primary_cred(k5->ctx, k5->out_cc, &my_creds);
 | 
			
		||||
         if (ret) {
 | 
			
		||||
             com_err(progname, ret, _("while storing credentials"));
 | 
			
		||||
             goto cleanup;
 | 
			
		||||
diff --git a/src/clients/kvno/kvno.c b/src/clients/kvno/kvno.c
 | 
			
		||||
index c5f6bf700..f83c68a99 100644
 | 
			
		||||
--- a/src/clients/kvno/kvno.c
 | 
			
		||||
+++ b/src/clients/kvno/kvno.c
 | 
			
		||||
@@ -561,7 +561,10 @@ do_v5_kvno(int count, char *names[], char * ccachestr, char *etypestr,
 | 
			
		||||
                 }
 | 
			
		||||
                 initialized = 1;
 | 
			
		||||
             }
 | 
			
		||||
-            ret = krb5_cc_store_cred(context, out_ccache, creds);
 | 
			
		||||
+            if (count == 1)
 | 
			
		||||
+                ret = k5_cc_store_primary_cred(context, out_ccache, creds);
 | 
			
		||||
+            else
 | 
			
		||||
+                ret = krb5_cc_store_cred(context, out_ccache, creds);
 | 
			
		||||
             if (ret) {
 | 
			
		||||
                 com_err(prog, ret, _("while storing creds in output ccache"));
 | 
			
		||||
                 exit(1);
 | 
			
		||||
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
 | 
			
		||||
index eb18a4cd6..912aaedac 100644
 | 
			
		||||
--- a/src/include/k5-int.h
 | 
			
		||||
+++ b/src/include/k5-int.h
 | 
			
		||||
@@ -307,6 +307,7 @@ typedef unsigned char   u_char;
 | 
			
		||||
 #define KRB5_CC_CONF_PA_TYPE                   "pa_type"
 | 
			
		||||
 #define KRB5_CC_CONF_PROXY_IMPERSONATOR        "proxy_impersonator"
 | 
			
		||||
 #define KRB5_CC_CONF_REFRESH_TIME              "refresh_time"
 | 
			
		||||
+#define KRB5_CC_CONF_START_REALM               "start_realm"
 | 
			
		||||
 
 | 
			
		||||
 /* Error codes used in KRB_ERROR protocol messages.
 | 
			
		||||
    Return values of library routines are based on a different error table
 | 
			
		||||
@@ -1910,6 +1911,9 @@ krb5_ser_unpack_bytes(krb5_octet *, size_t, krb5_octet **, size_t *);
 | 
			
		||||
 krb5_error_code KRB5_CALLCONV
 | 
			
		||||
 krb5int_cc_default(krb5_context, krb5_ccache *);
 | 
			
		||||
 
 | 
			
		||||
+krb5_error_code
 | 
			
		||||
+k5_cc_store_primary_cred(krb5_context, krb5_ccache, krb5_creds *);
 | 
			
		||||
+
 | 
			
		||||
 /* Fill in the buffer with random alpha-numeric data. */
 | 
			
		||||
 krb5_error_code
 | 
			
		||||
 krb5int_random_string(krb5_context, char *string, unsigned int length);
 | 
			
		||||
diff --git a/src/lib/gssapi/krb5/accept_sec_context.c b/src/lib/gssapi/krb5/accept_sec_context.c
 | 
			
		||||
index 3d5b84b15..abccb5d11 100644
 | 
			
		||||
--- a/src/lib/gssapi/krb5/accept_sec_context.c
 | 
			
		||||
+++ b/src/lib/gssapi/krb5/accept_sec_context.c
 | 
			
		||||
@@ -216,7 +216,7 @@ rd_and_store_for_creds(context, auth_context, inbuf, out_cred)
 | 
			
		||||
     if ((retval = krb5_cc_initialize(context, ccache, creds[0]->client)))
 | 
			
		||||
         goto cleanup;
 | 
			
		||||
 
 | 
			
		||||
-    if ((retval = krb5_cc_store_cred(context, ccache, creds[0])))
 | 
			
		||||
+    if ((retval = k5_cc_store_primary_cred(context, ccache, creds[0])))
 | 
			
		||||
         goto cleanup;
 | 
			
		||||
 
 | 
			
		||||
     /* generate a delegated credential handle */
 | 
			
		||||
diff --git a/src/lib/krb5/ccache/ccfns.c b/src/lib/krb5/ccache/ccfns.c
 | 
			
		||||
index 62a6983d8..23edc2578 100644
 | 
			
		||||
--- a/src/lib/krb5/ccache/ccfns.c
 | 
			
		||||
+++ b/src/lib/krb5/ccache/ccfns.c
 | 
			
		||||
@@ -297,3 +297,23 @@ krb5_cc_switch(krb5_context context, krb5_ccache cache)
 | 
			
		||||
         return 0;
 | 
			
		||||
     return cache->ops->switch_to(context, cache);
 | 
			
		||||
 }
 | 
			
		||||
+
 | 
			
		||||
+krb5_error_code
 | 
			
		||||
+k5_cc_store_primary_cred(krb5_context context, krb5_ccache cache,
 | 
			
		||||
+                         krb5_creds *creds)
 | 
			
		||||
+{
 | 
			
		||||
+    krb5_error_code ret;
 | 
			
		||||
+
 | 
			
		||||
+    /* Write a start realm if we're writing a TGT and the client realm isn't
 | 
			
		||||
+     * the same as the TGS realm. */
 | 
			
		||||
+    if (IS_TGS_PRINC(creds->server) &&
 | 
			
		||||
+        !data_eq(creds->client->realm, creds->server->data[1])) {
 | 
			
		||||
+        ret = krb5_cc_set_config(context, cache, NULL,
 | 
			
		||||
+                                 KRB5_CC_CONF_START_REALM,
 | 
			
		||||
+                                 &creds->server->data[1]);
 | 
			
		||||
+        if (ret)
 | 
			
		||||
+            return ret;
 | 
			
		||||
+    }
 | 
			
		||||
+
 | 
			
		||||
+    return krb5_cc_store_cred(context, cache, creds);
 | 
			
		||||
+}
 | 
			
		||||
diff --git a/src/lib/krb5/krb/get_creds.c b/src/lib/krb5/krb/get_creds.c
 | 
			
		||||
index e0a3b5cd8..b40f705fc 100644
 | 
			
		||||
--- a/src/lib/krb5/krb/get_creds.c
 | 
			
		||||
+++ b/src/lib/krb5/krb/get_creds.c
 | 
			
		||||
@@ -149,7 +149,8 @@ struct _krb5_tkt_creds_context {
 | 
			
		||||
     krb5_principal client;      /* Caller-requested client principal (alias) */
 | 
			
		||||
     krb5_principal server;      /* Server principal (alias) */
 | 
			
		||||
     krb5_principal req_server;  /* Caller-requested server principal */
 | 
			
		||||
-    krb5_ccache ccache;         /* Caller-provided ccache (alias) */
 | 
			
		||||
+    krb5_ccache ccache;         /* Caller-provided ccache */
 | 
			
		||||
+    krb5_data start_realm;      /* Realm of starting TGT in ccache */
 | 
			
		||||
     krb5_flags req_options;     /* Caller-requested KRB5_GC_* options */
 | 
			
		||||
     krb5_flags req_kdcopt;      /* Caller-requested options as KDC options */
 | 
			
		||||
     krb5_authdata **authdata;   /* Caller-requested authdata */
 | 
			
		||||
@@ -783,7 +784,7 @@ get_cached_local_tgt(krb5_context context, krb5_tkt_creds_context ctx,
 | 
			
		||||
         return code;
 | 
			
		||||
 
 | 
			
		||||
     /* Construct the principal name. */
 | 
			
		||||
-    code = krb5int_tgtname(context, &ctx->client->realm, &ctx->client->realm,
 | 
			
		||||
+    code = krb5int_tgtname(context, &ctx->start_realm, &ctx->start_realm,
 | 
			
		||||
                            &tgtname);
 | 
			
		||||
     if (code != 0)
 | 
			
		||||
         return code;
 | 
			
		||||
@@ -821,7 +822,7 @@ init_realm_path(krb5_context context, krb5_tkt_creds_context ctx)
 | 
			
		||||
     size_t nrealms;
 | 
			
		||||
 
 | 
			
		||||
     /* Get the client realm path and count its length. */
 | 
			
		||||
-    code = k5_client_realm_path(context, &ctx->client->realm,
 | 
			
		||||
+    code = k5_client_realm_path(context, &ctx->start_realm,
 | 
			
		||||
                                 &ctx->server->realm, &realm_path);
 | 
			
		||||
     if (code != 0)
 | 
			
		||||
         return code;
 | 
			
		||||
@@ -933,7 +934,7 @@ step_get_tgt(krb5_context context, krb5_tkt_creds_context ctx)
 | 
			
		||||
                 ctx->cur_realm = path_realm;
 | 
			
		||||
                 ctx->next_realm = ctx->last_realm;
 | 
			
		||||
             }
 | 
			
		||||
-        } else if (data_eq(*tgt_realm, ctx->client->realm)) {
 | 
			
		||||
+        } else if (data_eq(*tgt_realm, ctx->start_realm)) {
 | 
			
		||||
             /* We were referred back to the local realm, which is bad. */
 | 
			
		||||
             return KRB5_KDCREP_MODIFIED;
 | 
			
		||||
         } else {
 | 
			
		||||
@@ -963,7 +964,7 @@ begin_get_tgt(krb5_context context, krb5_tkt_creds_context ctx)
 | 
			
		||||
 
 | 
			
		||||
     ctx->state = STATE_GET_TGT;
 | 
			
		||||
 
 | 
			
		||||
-    is_local_service = data_eq(ctx->client->realm, ctx->server->realm);
 | 
			
		||||
+    is_local_service = data_eq(ctx->start_realm, ctx->server->realm);
 | 
			
		||||
     if (!is_local_service) {
 | 
			
		||||
         /* See if we have a cached TGT for the server realm. */
 | 
			
		||||
         code = get_cached_tgt(context, ctx, &ctx->server->realm, &cached_tgt);
 | 
			
		||||
@@ -1048,10 +1049,10 @@ begin(krb5_context context, krb5_tkt_creds_context ctx)
 | 
			
		||||
     if (code != 0 || ctx->state == STATE_COMPLETE)
 | 
			
		||||
         return code;
 | 
			
		||||
 
 | 
			
		||||
-    /* If the server realm is unspecified, start with the client realm. */
 | 
			
		||||
+    /* If the server realm is unspecified, start with the TGT realm. */
 | 
			
		||||
     if (krb5_is_referral_realm(&ctx->server->realm)) {
 | 
			
		||||
         krb5_free_data_contents(context, &ctx->server->realm);
 | 
			
		||||
-        code = krb5int_copy_data_contents(context, &ctx->client->realm,
 | 
			
		||||
+        code = krb5int_copy_data_contents(context, &ctx->start_realm,
 | 
			
		||||
                                           &ctx->server->realm);
 | 
			
		||||
         TRACE_TKT_CREDS_REFERRAL_REALM(context, ctx->server);
 | 
			
		||||
         if (code != 0)
 | 
			
		||||
@@ -1100,6 +1101,18 @@ krb5_tkt_creds_init(krb5_context context, krb5_ccache ccache,
 | 
			
		||||
     code = krb5_cc_dup(context, ccache, &ctx->ccache);
 | 
			
		||||
     if (code != 0)
 | 
			
		||||
         goto cleanup;
 | 
			
		||||
+
 | 
			
		||||
+    /* Get the start realm from the cache config, defaulting to the client
 | 
			
		||||
+     * realm. */
 | 
			
		||||
+    code = krb5_cc_get_config(context, ccache, NULL, "start_realm",
 | 
			
		||||
+                              &ctx->start_realm);
 | 
			
		||||
+    if (code != 0) {
 | 
			
		||||
+        code = krb5int_copy_data_contents(context, &ctx->client->realm,
 | 
			
		||||
+                                          &ctx->start_realm);
 | 
			
		||||
+        if (code != 0)
 | 
			
		||||
+            goto cleanup;
 | 
			
		||||
+    }
 | 
			
		||||
+
 | 
			
		||||
     code = krb5_copy_authdata(context, in_creds->authdata, &ctx->authdata);
 | 
			
		||||
     if (code != 0)
 | 
			
		||||
         goto cleanup;
 | 
			
		||||
@@ -1139,6 +1152,7 @@ krb5_tkt_creds_free(krb5_context context, krb5_tkt_creds_context ctx)
 | 
			
		||||
     krb5int_fast_free_state(context, ctx->fast_state);
 | 
			
		||||
     krb5_free_creds(context, ctx->in_creds);
 | 
			
		||||
     krb5_cc_close(context, ctx->ccache);
 | 
			
		||||
+    krb5_free_data_contents(context, &ctx->start_realm);
 | 
			
		||||
     krb5_free_principal(context, ctx->req_server);
 | 
			
		||||
     krb5_free_authdata(context, ctx->authdata);
 | 
			
		||||
     krb5_free_creds(context, ctx->cur_tgt);
 | 
			
		||||
diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c
 | 
			
		||||
index cc0f70e83..f5dd7518b 100644
 | 
			
		||||
--- a/src/lib/krb5/krb/get_in_tkt.c
 | 
			
		||||
+++ b/src/lib/krb5/krb/get_in_tkt.c
 | 
			
		||||
@@ -1779,7 +1779,7 @@ init_creds_step_reply(krb5_context context,
 | 
			
		||||
         code = krb5_cc_initialize(context, out_ccache, ctx->cred.client);
 | 
			
		||||
         if (code != 0)
 | 
			
		||||
             goto cc_cleanup;
 | 
			
		||||
-        code = krb5_cc_store_cred(context, out_ccache, &ctx->cred);
 | 
			
		||||
+        code = k5_cc_store_primary_cred(context, out_ccache, &ctx->cred);
 | 
			
		||||
         if (code != 0)
 | 
			
		||||
             goto cc_cleanup;
 | 
			
		||||
         if (fast_avail) {
 | 
			
		||||
diff --git a/src/lib/krb5/libkrb5.exports b/src/lib/krb5/libkrb5.exports
 | 
			
		||||
index 5aba29ee4..cab5b3b17 100644
 | 
			
		||||
--- a/src/lib/krb5/libkrb5.exports
 | 
			
		||||
+++ b/src/lib/krb5/libkrb5.exports
 | 
			
		||||
@@ -125,6 +125,7 @@ k5_add_pa_data_from_data
 | 
			
		||||
 k5_alloc_pa_data
 | 
			
		||||
 k5_authind_decode
 | 
			
		||||
 k5_build_conf_principals
 | 
			
		||||
+k5_cc_store_primary_cred
 | 
			
		||||
 k5_ccselect_free_context
 | 
			
		||||
 k5_change_error_message_code
 | 
			
		||||
 k5_etypes_contains
 | 
			
		||||
diff --git a/src/lib/krb5_32.def b/src/lib/krb5_32.def
 | 
			
		||||
index a0734c729..de5823c17 100644
 | 
			
		||||
--- a/src/lib/krb5_32.def
 | 
			
		||||
+++ b/src/lib/krb5_32.def
 | 
			
		||||
@@ -499,3 +499,6 @@ EXPORTS
 | 
			
		||||
 	k5_size_context					@467 ; PRIVATE GSSAPI
 | 
			
		||||
 	k5_size_keyblock				@468 ; PRIVATE GSSAPI
 | 
			
		||||
 	k5_size_principal				@469 ; PRIVATE GSSAPI
 | 
			
		||||
+
 | 
			
		||||
+; new in 1.19
 | 
			
		||||
+	k5_cc_store_primary_cred			@470 ; PRIVATE
 | 
			
		||||
diff --git a/src/tests/t_crossrealm.py b/src/tests/t_crossrealm.py
 | 
			
		||||
index fa7fd2604..28b397cfb 100755
 | 
			
		||||
--- a/src/tests/t_crossrealm.py
 | 
			
		||||
+++ b/src/tests/t_crossrealm.py
 | 
			
		||||
@@ -77,6 +77,14 @@ r1, r2, r3 = cross_realms(3, xtgts=((0,1), (1,2)),
 | 
			
		||||
                                 {'realm': 'B.X'}))
 | 
			
		||||
 test_kvno(r1, r3.host_princ, 'KDC domain walk')
 | 
			
		||||
 check_klist(r1, (tgt(r1, r1), r3.host_princ))
 | 
			
		||||
+
 | 
			
		||||
+# Test start_realm in this setup.
 | 
			
		||||
+r1.run([kvno, '--out-cache', r1.ccache, r2.krbtgt_princ])
 | 
			
		||||
+r1.run([klist, '-C'], expected_msg='config: start_realm = X')
 | 
			
		||||
+msgs = ('Requesting TGT krbtgt/B.X@X using TGT krbtgt/X@X',
 | 
			
		||||
+        'Received TGT for service realm: krbtgt/B.X@X')
 | 
			
		||||
+r1.run([kvno, r3.host_princ], expected_trace=msgs)
 | 
			
		||||
+
 | 
			
		||||
 stop(r1, r2, r3)
 | 
			
		||||
 
 | 
			
		||||
 # Test client capaths.  The client in A will ask for a cross TGT to D,
 | 
			
		||||
diff --git a/src/tests/t_pkinit.py b/src/tests/t_pkinit.py
 | 
			
		||||
index ecd450e8a..f224383c8 100755
 | 
			
		||||
--- a/src/tests/t_pkinit.py
 | 
			
		||||
+++ b/src/tests/t_pkinit.py
 | 
			
		||||
@@ -130,6 +130,9 @@ realm.run([kvno, realm.host_princ])
 | 
			
		||||
 out = realm.run(['./adata', realm.host_princ])
 | 
			
		||||
 if '97:' in out:
 | 
			
		||||
     fail('auth indicators seen in anonymous PKINIT ticket')
 | 
			
		||||
+# Verify start_realm setting and test referrals TGS request.
 | 
			
		||||
+realm.run([klist, '-C'], expected_msg='start_realm = KRBTEST.COM')
 | 
			
		||||
+realm.run([kvno, '-S', 'host', hostname])
 | 
			
		||||
 
 | 
			
		||||
 # Test anonymous kadmin.
 | 
			
		||||
 mark('anonymous kadmin')
 | 
			
		||||
							
								
								
									
										403
									
								
								SOURCES/Add-three-kvno-options-from-Heimdal-kgetcred.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										403
									
								
								SOURCES/Add-three-kvno-options-from-Heimdal-kgetcred.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,403 @@
 | 
			
		||||
From a1f38973435b60c7f147abfca12b95c6a0a64406 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Greg Hudson <ghudson@mit.edu>
 | 
			
		||||
Date: Wed, 17 Jun 2020 20:48:38 -0400
 | 
			
		||||
Subject: [PATCH] Add three kvno options from Heimdal kgetcred
 | 
			
		||||
 | 
			
		||||
Add the flags --cached-only and --no-store, which pass the
 | 
			
		||||
corresponding options to krb5_get_credentials().  Add the option
 | 
			
		||||
--out-cache to write the retrieved credentials to a specified output
 | 
			
		||||
cache.
 | 
			
		||||
 | 
			
		||||
Add a Python test script for kvno command-line options, including
 | 
			
		||||
tests for the new options.
 | 
			
		||||
 | 
			
		||||
ticket: 8917 (new)
 | 
			
		||||
---
 | 
			
		||||
 doc/user/user_commands/kvno.rst |  13 ++++
 | 
			
		||||
 src/clients/kvno/Makefile.in    |   3 +
 | 
			
		||||
 src/clients/kvno/kvno.c         | 115 +++++++++++++++++++++++---------
 | 
			
		||||
 src/clients/kvno/t_kvno.py      |  75 +++++++++++++++++++++
 | 
			
		||||
 src/man/kvno.man                |  13 ++++
 | 
			
		||||
 5 files changed, 187 insertions(+), 32 deletions(-)
 | 
			
		||||
 create mode 100644 src/clients/kvno/t_kvno.py
 | 
			
		||||
 | 
			
		||||
diff --git a/doc/user/user_commands/kvno.rst b/doc/user/user_commands/kvno.rst
 | 
			
		||||
index 3892f0ca5..718313576 100644
 | 
			
		||||
--- a/doc/user/user_commands/kvno.rst
 | 
			
		||||
+++ b/doc/user/user_commands/kvno.rst
 | 
			
		||||
@@ -74,6 +74,19 @@ OPTIONS
 | 
			
		||||
     client principal with the X.509 certificate in *cert_file*.  The
 | 
			
		||||
     certificate file must be in PEM format.
 | 
			
		||||
 
 | 
			
		||||
+**--cached-only**
 | 
			
		||||
+    Only retrieve credentials already present in the cache, not from
 | 
			
		||||
+    the KDC.
 | 
			
		||||
+
 | 
			
		||||
+**--no-store**
 | 
			
		||||
+    Do not store retrieved credentials in the cache.  If
 | 
			
		||||
+    **--out-cache** is also specified, credentials will still be
 | 
			
		||||
+    stored into the output credential cache.
 | 
			
		||||
+
 | 
			
		||||
+**--out-cache** *ccache*
 | 
			
		||||
+    Initialize *ccache* and store all retrieved credentials into it.
 | 
			
		||||
+    Do not store acquired credentials in the input cache.
 | 
			
		||||
+
 | 
			
		||||
 **--u2u** *ccache*
 | 
			
		||||
     Requests a user-to-user ticket.  *ccache* must contain a local
 | 
			
		||||
     krbtgt ticket for the server principal.  The reported version
 | 
			
		||||
diff --git a/src/clients/kvno/Makefile.in b/src/clients/kvno/Makefile.in
 | 
			
		||||
index 1c3f79392..5ba877271 100644
 | 
			
		||||
--- a/src/clients/kvno/Makefile.in
 | 
			
		||||
+++ b/src/clients/kvno/Makefile.in
 | 
			
		||||
@@ -26,6 +26,9 @@ kvno: kvno.o $(KRB5_BASE_DEPLIBS)
 | 
			
		||||
 ##WIN32##	link $(EXE_LINKOPTS) /out:$@ $**
 | 
			
		||||
 ##WIN32##	$(_VC_MANIFEST_EMBED_EXE)
 | 
			
		||||
 
 | 
			
		||||
+check-pytests: kvno
 | 
			
		||||
+	$(RUNPYTEST) $(srcdir)/t_kvno.py $(PYTESTFLAGS)
 | 
			
		||||
+
 | 
			
		||||
 clean-unix::
 | 
			
		||||
 	$(RM) kvno.o kvno
 | 
			
		||||
 
 | 
			
		||||
diff --git a/src/clients/kvno/kvno.c b/src/clients/kvno/kvno.c
 | 
			
		||||
index 2472c0cfe..9d85864f6 100644
 | 
			
		||||
--- a/src/clients/kvno/kvno.c
 | 
			
		||||
+++ b/src/clients/kvno/kvno.c
 | 
			
		||||
@@ -44,14 +44,17 @@ xusage()
 | 
			
		||||
     fprintf(stderr, _("usage: %s [-C] [-u] [-c ccache] [-e etype]\n"), prog);
 | 
			
		||||
     fprintf(stderr, _("\t[-k keytab] [-S sname] [{-I | -U} for_user | "
 | 
			
		||||
                       "[-F cert_file] [-P]]\n"));
 | 
			
		||||
-    fprintf(stderr, _("\t[--u2u ccache] service1 service2 ...\n"));
 | 
			
		||||
+    fprintf(stderr, _("\t[--cached-only] [--no-store] [--out-cache ccache] "
 | 
			
		||||
+                      "[--u2u ccache]\n"));
 | 
			
		||||
+    fprintf(stderr, _("\tservice1 service2 ...\n"));
 | 
			
		||||
     exit(1);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static void do_v5_kvno(int argc, char *argv[], char *ccachestr, char *etypestr,
 | 
			
		||||
-                       char *keytab_name, char *sname, int canon, int unknown,
 | 
			
		||||
-                       char *for_user, int for_user_enterprise,
 | 
			
		||||
-                       char *for_user_cert_file, int proxy,
 | 
			
		||||
+                       char *keytab_name, char *sname, int cached_only,
 | 
			
		||||
+                       int canon, int no_store, int unknown, char *for_user,
 | 
			
		||||
+                       int for_user_enterprise, char *for_user_cert_file,
 | 
			
		||||
+                       int proxy, const char *out_ccname,
 | 
			
		||||
                        const char *u2u_ccname);
 | 
			
		||||
 
 | 
			
		||||
 #include <com_err.h>
 | 
			
		||||
@@ -61,18 +64,21 @@ static void extended_com_err_fn(const char *myprog, errcode_t code,
 | 
			
		||||
 int
 | 
			
		||||
 main(int argc, char *argv[])
 | 
			
		||||
 {
 | 
			
		||||
-    enum { OPTION_U2U = 256 };
 | 
			
		||||
-    struct option lopts[] = {
 | 
			
		||||
-        { "u2u", 1, NULL, OPTION_U2U },
 | 
			
		||||
-        { NULL, 0, NULL, 0 }
 | 
			
		||||
-    };
 | 
			
		||||
+    enum { OPTION_U2U = 256, OPTION_OUT_CACHE = 257 };
 | 
			
		||||
     const char *shopts = "uCc:e:hk:qPS:I:U:F:";
 | 
			
		||||
     int option;
 | 
			
		||||
     char *etypestr = NULL, *ccachestr = NULL, *keytab_name = NULL;
 | 
			
		||||
     char *sname = NULL, *for_user = NULL, *u2u_ccname = NULL;
 | 
			
		||||
-    char *for_user_cert_file = NULL;
 | 
			
		||||
+    char *for_user_cert_file = NULL, *out_ccname = NULL;
 | 
			
		||||
     int canon = 0, unknown = 0, proxy = 0, for_user_enterprise = 0;
 | 
			
		||||
-    int impersonate = 0;
 | 
			
		||||
+    int impersonate = 0, cached_only = 0, no_store = 0;
 | 
			
		||||
+    struct option lopts[] = {
 | 
			
		||||
+        { "cached-only", 0, &cached_only, 1 },
 | 
			
		||||
+        { "no-store", 0, &no_store, 1 },
 | 
			
		||||
+        { "out-cache", 1, NULL, OPTION_OUT_CACHE },
 | 
			
		||||
+        { "u2u", 1, NULL, OPTION_U2U },
 | 
			
		||||
+        { NULL, 0, NULL, 0 }
 | 
			
		||||
+    };
 | 
			
		||||
 
 | 
			
		||||
     setlocale(LC_ALL, "");
 | 
			
		||||
     set_com_err_hook(extended_com_err_fn);
 | 
			
		||||
@@ -135,6 +141,12 @@ main(int argc, char *argv[])
 | 
			
		||||
         case OPTION_U2U:
 | 
			
		||||
             u2u_ccname = optarg;
 | 
			
		||||
             break;
 | 
			
		||||
+        case OPTION_OUT_CACHE:
 | 
			
		||||
+            out_ccname = optarg;
 | 
			
		||||
+            break;
 | 
			
		||||
+        case 0:
 | 
			
		||||
+            /* If this option set a flag, do nothing else now. */
 | 
			
		||||
+            break;
 | 
			
		||||
         default:
 | 
			
		||||
             xusage();
 | 
			
		||||
             break;
 | 
			
		||||
@@ -159,8 +171,9 @@ main(int argc, char *argv[])
 | 
			
		||||
         xusage();
 | 
			
		||||
 
 | 
			
		||||
     do_v5_kvno(argc - optind, argv + optind, ccachestr, etypestr, keytab_name,
 | 
			
		||||
-               sname, canon, unknown, for_user, for_user_enterprise,
 | 
			
		||||
-               for_user_cert_file, proxy, u2u_ccname);
 | 
			
		||||
+               sname, cached_only, canon, no_store, unknown, for_user,
 | 
			
		||||
+               for_user_enterprise, for_user_cert_file, proxy, out_ccname,
 | 
			
		||||
+               u2u_ccname);
 | 
			
		||||
     return 0;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@@ -274,14 +287,16 @@ static krb5_error_code
 | 
			
		||||
 kvno(const char *name, krb5_ccache ccache, krb5_principal me,
 | 
			
		||||
      krb5_enctype etype, krb5_keytab keytab, const char *sname,
 | 
			
		||||
      krb5_flags options, int unknown, krb5_principal for_user_princ,
 | 
			
		||||
-     krb5_data *for_user_cert, int proxy, krb5_data *u2u_ticket)
 | 
			
		||||
+     krb5_data *for_user_cert, int proxy, krb5_data *u2u_ticket,
 | 
			
		||||
+     krb5_creds **creds_out)
 | 
			
		||||
 {
 | 
			
		||||
     krb5_error_code ret;
 | 
			
		||||
     krb5_principal server = NULL;
 | 
			
		||||
     krb5_ticket *ticket = NULL;
 | 
			
		||||
-    krb5_creds in_creds, *out_creds = NULL;
 | 
			
		||||
+    krb5_creds in_creds, *creds = NULL;
 | 
			
		||||
     char *princ = NULL;
 | 
			
		||||
 
 | 
			
		||||
+    *creds_out = NULL;
 | 
			
		||||
     memset(&in_creds, 0, sizeof(in_creds));
 | 
			
		||||
 
 | 
			
		||||
     if (sname != NULL) {
 | 
			
		||||
@@ -321,13 +336,12 @@ kvno(const char *name, krb5_ccache ccache, krb5_principal me,
 | 
			
		||||
         in_creds.client = for_user_princ;
 | 
			
		||||
         in_creds.server = me;
 | 
			
		||||
         ret = krb5_get_credentials_for_user(context, options, ccache,
 | 
			
		||||
-                                            &in_creds, for_user_cert,
 | 
			
		||||
-                                            &out_creds);
 | 
			
		||||
+                                            &in_creds, for_user_cert, &creds);
 | 
			
		||||
     } else {
 | 
			
		||||
         in_creds.client = me;
 | 
			
		||||
         in_creds.server = server;
 | 
			
		||||
         ret = krb5_get_credentials(context, options, ccache, &in_creds,
 | 
			
		||||
-                                   &out_creds);
 | 
			
		||||
+                                   &creds);
 | 
			
		||||
     }
 | 
			
		||||
 
 | 
			
		||||
     if (ret) {
 | 
			
		||||
@@ -336,7 +350,7 @@ kvno(const char *name, krb5_ccache ccache, krb5_principal me,
 | 
			
		||||
     }
 | 
			
		||||
 
 | 
			
		||||
     /* We need a native ticket. */
 | 
			
		||||
-    ret = krb5_decode_ticket(&out_creds->ticket, &ticket);
 | 
			
		||||
+    ret = krb5_decode_ticket(&creds->ticket, &ticket);
 | 
			
		||||
     if (ret) {
 | 
			
		||||
         com_err(prog, ret, _("while decoding ticket for %s"), princ);
 | 
			
		||||
         goto cleanup;
 | 
			
		||||
@@ -362,15 +376,15 @@ kvno(const char *name, krb5_ccache ccache, krb5_principal me,
 | 
			
		||||
     }
 | 
			
		||||
 
 | 
			
		||||
     if (proxy) {
 | 
			
		||||
-        in_creds.client = out_creds->client;
 | 
			
		||||
-        out_creds->client = NULL;
 | 
			
		||||
-        krb5_free_creds(context, out_creds);
 | 
			
		||||
-        out_creds = NULL;
 | 
			
		||||
+        in_creds.client = creds->client;
 | 
			
		||||
+        creds->client = NULL;
 | 
			
		||||
+        krb5_free_creds(context, creds);
 | 
			
		||||
+        creds = NULL;
 | 
			
		||||
         in_creds.server = server;
 | 
			
		||||
 
 | 
			
		||||
         ret = krb5_get_credentials_for_proxy(context, KRB5_GC_CANONICALIZE,
 | 
			
		||||
                                              ccache, &in_creds, ticket,
 | 
			
		||||
-                                             &out_creds);
 | 
			
		||||
+                                             &creds);
 | 
			
		||||
         krb5_free_principal(context, in_creds.client);
 | 
			
		||||
         if (ret) {
 | 
			
		||||
             com_err(prog, ret, _("%s: constrained delegation failed"),
 | 
			
		||||
@@ -379,10 +393,13 @@ kvno(const char *name, krb5_ccache ccache, krb5_principal me,
 | 
			
		||||
         }
 | 
			
		||||
     }
 | 
			
		||||
 
 | 
			
		||||
+    *creds_out = creds;
 | 
			
		||||
+    creds = NULL;
 | 
			
		||||
+
 | 
			
		||||
 cleanup:
 | 
			
		||||
     krb5_free_principal(context, server);
 | 
			
		||||
     krb5_free_ticket(context, ticket);
 | 
			
		||||
-    krb5_free_creds(context, out_creds);
 | 
			
		||||
+    krb5_free_creds(context, creds);
 | 
			
		||||
     krb5_free_unparsed_name(context, princ);
 | 
			
		||||
     return ret;
 | 
			
		||||
 }
 | 
			
		||||
@@ -428,19 +445,28 @@ cleanup:
 | 
			
		||||
 
 | 
			
		||||
 static void
 | 
			
		||||
 do_v5_kvno(int count, char *names[], char * ccachestr, char *etypestr,
 | 
			
		||||
-           char *keytab_name, char *sname, int canon, int unknown,
 | 
			
		||||
-           char *for_user, int for_user_enterprise,
 | 
			
		||||
-           char *for_user_cert_file, int proxy, const char *u2u_ccname)
 | 
			
		||||
+           char *keytab_name, char *sname, int cached_only, int canon,
 | 
			
		||||
+           int no_store, int unknown, char *for_user, int for_user_enterprise,
 | 
			
		||||
+           char *for_user_cert_file, int proxy, const char *out_ccname,
 | 
			
		||||
+           const char *u2u_ccname)
 | 
			
		||||
 {
 | 
			
		||||
     krb5_error_code ret;
 | 
			
		||||
-    int i, errors, flags;
 | 
			
		||||
+    int i, errors, flags, initialized = 0;
 | 
			
		||||
     krb5_enctype etype;
 | 
			
		||||
-    krb5_ccache ccache;
 | 
			
		||||
+    krb5_ccache ccache, out_ccache = NULL;
 | 
			
		||||
     krb5_principal me;
 | 
			
		||||
     krb5_keytab keytab = NULL;
 | 
			
		||||
     krb5_principal for_user_princ = NULL;
 | 
			
		||||
-    krb5_flags options = canon ? KRB5_GC_CANONICALIZE : 0;
 | 
			
		||||
+    krb5_flags options = 0;
 | 
			
		||||
     krb5_data cert_data = empty_data(), *user_cert = NULL, *u2u_ticket = NULL;
 | 
			
		||||
+    krb5_creds *creds;
 | 
			
		||||
+
 | 
			
		||||
+    if (canon)
 | 
			
		||||
+        options |= KRB5_GC_CANONICALIZE;
 | 
			
		||||
+    if (cached_only)
 | 
			
		||||
+        options |= KRB5_GC_CACHED;
 | 
			
		||||
+    if (no_store || out_ccname != NULL)
 | 
			
		||||
+        options |= KRB5_GC_NO_STORE;
 | 
			
		||||
 
 | 
			
		||||
     ret = krb5_init_context(&context);
 | 
			
		||||
     if (ret) {
 | 
			
		||||
@@ -467,6 +493,14 @@ do_v5_kvno(int count, char *names[], char * ccachestr, char *etypestr,
 | 
			
		||||
         exit(1);
 | 
			
		||||
     }
 | 
			
		||||
 
 | 
			
		||||
+    if (out_ccname != NULL) {
 | 
			
		||||
+        ret = krb5_cc_resolve(context, out_ccname, &out_ccache);
 | 
			
		||||
+        if (ret) {
 | 
			
		||||
+            com_err(prog, ret, _("while resolving output ccache"));
 | 
			
		||||
+            exit(1);
 | 
			
		||||
+        }
 | 
			
		||||
+    }
 | 
			
		||||
+
 | 
			
		||||
     if (keytab_name != NULL) {
 | 
			
		||||
         ret = krb5_kt_resolve(context, keytab_name, &keytab);
 | 
			
		||||
         if (ret) {
 | 
			
		||||
@@ -513,8 +547,25 @@ do_v5_kvno(int count, char *names[], char * ccachestr, char *etypestr,
 | 
			
		||||
     errors = 0;
 | 
			
		||||
     for (i = 0; i < count; i++) {
 | 
			
		||||
         if (kvno(names[i], ccache, me, etype, keytab, sname, options, unknown,
 | 
			
		||||
-                 for_user_princ, user_cert, proxy, u2u_ticket) != 0)
 | 
			
		||||
+                 for_user_princ, user_cert, proxy, u2u_ticket, &creds) != 0) {
 | 
			
		||||
             errors++;
 | 
			
		||||
+        } else if (out_ccache != NULL) {
 | 
			
		||||
+            if (!initialized) {
 | 
			
		||||
+                ret = krb5_cc_initialize(context, out_ccache, creds->client);
 | 
			
		||||
+                if (ret) {
 | 
			
		||||
+                    com_err(prog, ret, _("while initializing output ccache"));
 | 
			
		||||
+                    exit(1);
 | 
			
		||||
+                }
 | 
			
		||||
+                initialized = 1;
 | 
			
		||||
+            }
 | 
			
		||||
+            ret = krb5_cc_store_cred(context, out_ccache, creds);
 | 
			
		||||
+            if (ret) {
 | 
			
		||||
+                com_err(prog, ret, _("while storing creds in output ccache"));
 | 
			
		||||
+                exit(1);
 | 
			
		||||
+            }
 | 
			
		||||
+        }
 | 
			
		||||
+
 | 
			
		||||
+        krb5_free_creds(context, creds);
 | 
			
		||||
     }
 | 
			
		||||
 
 | 
			
		||||
     if (keytab != NULL)
 | 
			
		||||
diff --git a/src/clients/kvno/t_kvno.py b/src/clients/kvno/t_kvno.py
 | 
			
		||||
new file mode 100644
 | 
			
		||||
index 000000000..e98b90e8a
 | 
			
		||||
--- /dev/null
 | 
			
		||||
+++ b/src/clients/kvno/t_kvno.py
 | 
			
		||||
@@ -0,0 +1,75 @@
 | 
			
		||||
+from k5test import *
 | 
			
		||||
+
 | 
			
		||||
+realm = K5Realm()
 | 
			
		||||
+
 | 
			
		||||
+def check_cache(ccache, expected_services):
 | 
			
		||||
+    # Fetch the klist output and skip past the header.
 | 
			
		||||
+    lines = realm.run([klist, '-c', ccache]).splitlines()
 | 
			
		||||
+    lines = lines[4:]
 | 
			
		||||
+
 | 
			
		||||
+    # For each line not beginning with an indent, match against the
 | 
			
		||||
+    # expected service principals.
 | 
			
		||||
+    svcs = {x: True for x in expected_services}
 | 
			
		||||
+    for l in lines:
 | 
			
		||||
+        if not l.startswith('\t'):
 | 
			
		||||
+            svcprinc = l.split()[4]
 | 
			
		||||
+            if svcprinc in svcs:
 | 
			
		||||
+                del svcs[svcprinc]
 | 
			
		||||
+            else:
 | 
			
		||||
+                fail('unexpected service princ ' + svcprinc)
 | 
			
		||||
+
 | 
			
		||||
+    if svcs:
 | 
			
		||||
+        fail('services not found in klist output: ' + ' '.join(svcs.keys()))
 | 
			
		||||
+
 | 
			
		||||
+
 | 
			
		||||
+mark('no options')
 | 
			
		||||
+realm.run([kvno, realm.user_princ], expected_msg='user@KRBTEST.COM: kvno = 1')
 | 
			
		||||
+check_cache(realm.ccache, [realm.krbtgt_princ, realm.user_princ])
 | 
			
		||||
+
 | 
			
		||||
+mark('-e')
 | 
			
		||||
+msgs = ('etypes requested in TGS request: camellia128-cts',
 | 
			
		||||
+        '/KDC has no support for encryption type')
 | 
			
		||||
+realm.run([kvno, '-e', 'camellia128-cts', realm.host_princ],
 | 
			
		||||
+          expected_code=1, expected_trace=msgs)
 | 
			
		||||
+
 | 
			
		||||
+mark('--cached-only')
 | 
			
		||||
+realm.run([kvno, '--cached-only', realm.user_princ], expected_msg='kvno = 1')
 | 
			
		||||
+realm.run([kvno, '--cached-only', realm.host_princ],
 | 
			
		||||
+          expected_code=1, expected_msg='Matching credential not found')
 | 
			
		||||
+check_cache(realm.ccache, [realm.krbtgt_princ, realm.user_princ])
 | 
			
		||||
+
 | 
			
		||||
+mark('--no-store')
 | 
			
		||||
+realm.run([kvno, '--no-store', realm.host_princ], expected_msg='kvno = 1')
 | 
			
		||||
+check_cache(realm.ccache, [realm.krbtgt_princ, realm.user_princ])
 | 
			
		||||
+
 | 
			
		||||
+mark('--out-cache') # and multiple services
 | 
			
		||||
+out_ccache = os.path.join(realm.testdir, 'ccache.out')
 | 
			
		||||
+realm.run([kvno, '--out-cache', out_ccache,
 | 
			
		||||
+           realm.host_princ, realm.admin_princ])
 | 
			
		||||
+check_cache(realm.ccache, [realm.krbtgt_princ, realm.user_princ])
 | 
			
		||||
+check_cache(out_ccache, [realm.host_princ, realm.admin_princ])
 | 
			
		||||
+
 | 
			
		||||
+mark('--out-cache --cached-only') # tests out-cache overwriting, and -q
 | 
			
		||||
+realm.run([kvno, '--out-cache', out_ccache, '--cached-only', realm.host_princ],
 | 
			
		||||
+          expected_code=1, expected_msg='Matching credential not found')
 | 
			
		||||
+out = realm.run([kvno, '-q', '--out-cache', out_ccache, '--cached-only',
 | 
			
		||||
+                 realm.user_princ])
 | 
			
		||||
+if out:
 | 
			
		||||
+    fail('unexpected kvno output with -q')
 | 
			
		||||
+check_cache(out_ccache, [realm.user_princ])
 | 
			
		||||
+
 | 
			
		||||
+mark('-U') # and -c
 | 
			
		||||
+svc_ccache = os.path.join(realm.testdir, 'ccache.svc')
 | 
			
		||||
+realm.run([kinit, '-k', '-c', svc_ccache, realm.host_princ])
 | 
			
		||||
+realm.run([kvno, '-c', svc_ccache, '-U', 'user', realm.host_princ])
 | 
			
		||||
+realm.run([klist, '-c', svc_ccache], expected_msg='for client user@')
 | 
			
		||||
+realm.run([kvno, '-c', svc_ccache, '-U', 'user', '--out-cache', out_ccache,
 | 
			
		||||
+           realm.host_princ])
 | 
			
		||||
+out = realm.run([klist, '-c', out_ccache])
 | 
			
		||||
+if ('Default principal: user@KRBTEST.COM' not in out):
 | 
			
		||||
+    fail('wrong default principal in klist output')
 | 
			
		||||
+
 | 
			
		||||
+# More S4U options are tested in tests/gssapi/t_s4u.py.
 | 
			
		||||
+# --u2u is tested in tests/t_u2u.py.
 | 
			
		||||
+
 | 
			
		||||
+success('kvno tests')
 | 
			
		||||
diff --git a/src/man/kvno.man b/src/man/kvno.man
 | 
			
		||||
index 005a2ec97..b9f6739eb 100644
 | 
			
		||||
--- a/src/man/kvno.man
 | 
			
		||||
+++ b/src/man/kvno.man
 | 
			
		||||
@@ -95,6 +95,19 @@ Specifies that protocol transition is to be used, identifying the
 | 
			
		||||
 client principal with the X.509 certificate in \fIcert_file\fP\&.  The
 | 
			
		||||
 certificate file must be in PEM format.
 | 
			
		||||
 .TP
 | 
			
		||||
+\fB\-\-cached\-only\fP
 | 
			
		||||
+Only retrieve credentials already present in the cache, not from
 | 
			
		||||
+the KDC.
 | 
			
		||||
+.TP
 | 
			
		||||
+\fB\-\-no\-store\fP
 | 
			
		||||
+Do not store retrieved credentials in the cache.  If
 | 
			
		||||
+\fB\-\-out\-cache\fP is also specified, credentials will still be
 | 
			
		||||
+stored into the output credential cache.
 | 
			
		||||
+.TP
 | 
			
		||||
+\fB\-\-out\-cache\fP \fIccache\fP
 | 
			
		||||
+Initialize \fIccache\fP and store all retrieved credentials into it.
 | 
			
		||||
+Do not store acquired credentials in the input cache.
 | 
			
		||||
+.TP
 | 
			
		||||
 \fB\-\-u2u\fP \fIccache\fP
 | 
			
		||||
 Requests a user\-to\-user ticket.  \fIccache\fP must contain a local
 | 
			
		||||
 krbtgt ticket for the server principal.  The reported version
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
From e9200e874f33defec7193c11a093675b70e588b6 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From 5c1c391a80edd8ceb9e8bba9f7bdfb6639883ae6 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Robbie Harwood <rharwood@redhat.com>
 | 
			
		||||
Date: Tue, 24 Nov 2020 12:52:02 -0500
 | 
			
		||||
Subject: [PATCH] Document -k option in kvno(1) synopsis
 | 
			
		||||
@ -14,7 +14,7 @@ synopsis, option descriptions, and xusage(), but missed one option.
 | 
			
		||||
 2 files changed, 2 insertions(+)
 | 
			
		||||
 | 
			
		||||
diff --git a/doc/user/user_commands/kvno.rst b/doc/user/user_commands/kvno.rst
 | 
			
		||||
index 53e569651..00689ab4c 100644
 | 
			
		||||
index 65c44e1c0..93a5132b2 100644
 | 
			
		||||
--- a/doc/user/user_commands/kvno.rst
 | 
			
		||||
+++ b/doc/user/user_commands/kvno.rst
 | 
			
		||||
@@ -9,6 +9,7 @@ SYNOPSIS
 | 
			
		||||
@ -26,7 +26,7 @@ index 53e569651..00689ab4c 100644
 | 
			
		||||
 [**-u** | **-S** *sname*]
 | 
			
		||||
 [**-P**]
 | 
			
		||||
diff --git a/src/man/kvno.man b/src/man/kvno.man
 | 
			
		||||
index e156df723..3eeab41b2 100644
 | 
			
		||||
index 22318324d..4e5b43b3b 100644
 | 
			
		||||
--- a/src/man/kvno.man
 | 
			
		||||
+++ b/src/man/kvno.man
 | 
			
		||||
@@ -35,6 +35,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										105
									
								
								SOURCES/Fix-KCM-flag-transmission-for-remove_cred.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								SOURCES/Fix-KCM-flag-transmission-for-remove_cred.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,105 @@
 | 
			
		||||
From 261b0ed68fb83c34c70679ae8452cae2dba7e4e3 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Greg Hudson <ghudson@mit.edu>
 | 
			
		||||
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)
 | 
			
		||||
(cherry picked from commit 04f0de4420508161ce439f262f2761ff51a07ab0)
 | 
			
		||||
(cherry picked from commit ddbb295dee2adcc6cec26944974420bba188f191)
 | 
			
		||||
---
 | 
			
		||||
 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 197a10fba..4141140c3 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);
 | 
			
		||||
							
								
								
									
										64
									
								
								SOURCES/Fix-KCM-retrieval-support-for-sssd.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								SOURCES/Fix-KCM-retrieval-support-for-sssd.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,64 @@
 | 
			
		||||
From 0bfe0b2bc0a8ee0e9a8cee26528030c16d4fd15f Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Greg Hudson <ghudson@mit.edu>
 | 
			
		||||
Date: Tue, 11 May 2021 14:04:07 -0400
 | 
			
		||||
Subject: [PATCH] Fix KCM retrieval support for sssd
 | 
			
		||||
 | 
			
		||||
Commit 795ebba8c039be172ab93cd41105c73ffdba0fdb added a retrieval
 | 
			
		||||
handler using KCM_OP_RETRIEVE, falling back on the same error codes as
 | 
			
		||||
the previous KCM_OP_GET_CRED_LIST support.  But sssd (as of 2.4)
 | 
			
		||||
returns KRB5_CC_NOSUPP instead of KRB5_CC_IO if it recognizes an
 | 
			
		||||
opcode but does not implement it.  Add a helper function to recognize
 | 
			
		||||
all known unsupported-opcode error codes, and use it in kcm_retrieve()
 | 
			
		||||
and kcm_start_seq_get().
 | 
			
		||||
 | 
			
		||||
ticket: 8997
 | 
			
		||||
(cherry picked from commit da103e36e13f3c846bcddbe38dd518a21e5260a0)
 | 
			
		||||
(cherry picked from commit a5b2cff51808cd86fe8195e7ac074ecd25c3344d)
 | 
			
		||||
(cherry picked from commit 6a00fd149edd017ece894566771e2e9d4ba089f4)
 | 
			
		||||
---
 | 
			
		||||
 src/lib/krb5/ccache/cc_kcm.c | 18 ++++++++++++++++--
 | 
			
		||||
 1 file changed, 16 insertions(+), 2 deletions(-)
 | 
			
		||||
 | 
			
		||||
diff --git a/src/lib/krb5/ccache/cc_kcm.c b/src/lib/krb5/ccache/cc_kcm.c
 | 
			
		||||
index b600c6f15..6a36cfdce 100644
 | 
			
		||||
--- a/src/lib/krb5/ccache/cc_kcm.c
 | 
			
		||||
+++ b/src/lib/krb5/ccache/cc_kcm.c
 | 
			
		||||
@@ -144,6 +144,20 @@ map_tcflags(krb5_flags mitflags)
 | 
			
		||||
     return heimflags;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+/*
 | 
			
		||||
+ * Return true if code could indicate an unsupported operation.  Heimdal's KCM
 | 
			
		||||
+ * returns KRB5_FCC_INTERNAL.  sssd's KCM daemon (as of sssd 2.4) returns
 | 
			
		||||
+ * KRB5_CC_NO_SUPP if it recognizes the operation but does not implement it,
 | 
			
		||||
+ * and KRB5_CC_IO if it doesn't recognize the operation (which is unfortunate
 | 
			
		||||
+ * since it could also indicate a communication failure).
 | 
			
		||||
+ */
 | 
			
		||||
+static krb5_boolean
 | 
			
		||||
+unsupported_op_error(krb5_error_code code)
 | 
			
		||||
+{
 | 
			
		||||
+    return code == KRB5_FCC_INTERNAL || code == KRB5_CC_IO ||
 | 
			
		||||
+        code == KRB5_CC_NOSUPP;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 /* Begin a request for the given opcode.  If cache is non-null, supply the
 | 
			
		||||
  * cache name as a request parameter. */
 | 
			
		||||
 static void
 | 
			
		||||
@@ -841,7 +855,7 @@ kcm_retrieve(krb5_context context, krb5_ccache cache, krb5_flags flags,
 | 
			
		||||
     ret = cache_call(context, cache, &req);
 | 
			
		||||
 
 | 
			
		||||
     /* Fall back to iteration if the server does not support retrieval. */
 | 
			
		||||
-    if (ret == KRB5_FCC_INTERNAL || ret == KRB5_CC_IO) {
 | 
			
		||||
+    if (unsupported_op_error(ret)) {
 | 
			
		||||
         ret = k5_cc_retrieve_cred_default(context, cache, flags, mcred,
 | 
			
		||||
                                           cred_out);
 | 
			
		||||
         goto cleanup;
 | 
			
		||||
@@ -922,7 +936,7 @@ kcm_start_seq_get(krb5_context context, krb5_ccache cache,
 | 
			
		||||
         ret = kcmreq_get_cred_list(&req, &creds);
 | 
			
		||||
         if (ret)
 | 
			
		||||
             goto cleanup;
 | 
			
		||||
-    } else if (ret == KRB5_FCC_INTERNAL || ret == KRB5_CC_IO) {
 | 
			
		||||
+    } else if (unsupported_op_error(ret)) {
 | 
			
		||||
         /* Fall back to GET_CRED_UUID_LIST. */
 | 
			
		||||
         kcmreq_free(&req);
 | 
			
		||||
         kcmreq_init(&req, KCM_OP_GET_CRED_UUID_LIST, cache);
 | 
			
		||||
@ -0,0 +1,47 @@
 | 
			
		||||
From 0a8dfc380fe3b210662ba1b1d452fcec2f84841b Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Greg Hudson <ghudson@mit.edu>
 | 
			
		||||
Date: Tue, 3 Aug 2021 01:15:27 -0400
 | 
			
		||||
Subject: [PATCH] Fix KDC null deref on TGS inner body null server
 | 
			
		||||
 | 
			
		||||
After the KDC decodes a FAST inner body, it does not check for a null
 | 
			
		||||
server.  Prior to commit 39548a5b17bbda9eeb63625a201cfd19b9de1c5b this
 | 
			
		||||
would typically result in an error from krb5_unparse_name(), but with
 | 
			
		||||
the addition of get_local_tgt() it results in a null dereference.  Add
 | 
			
		||||
a null check.
 | 
			
		||||
 | 
			
		||||
Reported by Joseph Sutton of Catalyst.
 | 
			
		||||
 | 
			
		||||
CVE-2021-37750:
 | 
			
		||||
 | 
			
		||||
In MIT krb5 releases 1.14 and later, an authenticated attacker can
 | 
			
		||||
cause a null dereference in the KDC by sending a FAST TGS request with
 | 
			
		||||
no server field.
 | 
			
		||||
 | 
			
		||||
ticket: 9008 (new)
 | 
			
		||||
tags: pullup
 | 
			
		||||
target_version: 1.19-next
 | 
			
		||||
target_version: 1.18-next
 | 
			
		||||
 | 
			
		||||
(cherry picked from commit d775c95af7606a51bf79547a94fa52ddd1cb7f49)
 | 
			
		||||
(cherry picked from commit bb8fa495d00ccd931eec87a01b8920636cf7903e)
 | 
			
		||||
(cherry picked from commit dfe383f8251d0edc7e5e08ec5e4fdd9b7f902b2a)
 | 
			
		||||
---
 | 
			
		||||
 src/kdc/do_tgs_req.c | 5 +++++
 | 
			
		||||
 1 file changed, 5 insertions(+)
 | 
			
		||||
 | 
			
		||||
diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c
 | 
			
		||||
index 463a9c0dd..7c596a111 100644
 | 
			
		||||
--- a/src/kdc/do_tgs_req.c
 | 
			
		||||
+++ b/src/kdc/do_tgs_req.c
 | 
			
		||||
@@ -208,6 +208,11 @@ process_tgs_req(krb5_kdc_req *request, krb5_data *pkt,
 | 
			
		||||
         status = "FIND_FAST";
 | 
			
		||||
         goto cleanup;
 | 
			
		||||
     }
 | 
			
		||||
+    if (sprinc == NULL) {
 | 
			
		||||
+        status = "NULL_SERVER";
 | 
			
		||||
+        errcode = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
 | 
			
		||||
+        goto cleanup;
 | 
			
		||||
+    }
 | 
			
		||||
 
 | 
			
		||||
     errcode = get_local_tgt(kdc_context, &sprinc->realm, header_server,
 | 
			
		||||
                             &local_tgt, &local_tgt_storage, &local_tgt_key);
 | 
			
		||||
							
								
								
									
										113
									
								
								SOURCES/Fix-KDC-null-deref-on-bad-encrypted-challenge.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								SOURCES/Fix-KDC-null-deref-on-bad-encrypted-challenge.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,113 @@
 | 
			
		||||
From 4e8579f0a41b66ed8029f21a52082e1c27ab3996 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Joseph Sutton <josephsutton@catalyst.net.nz>
 | 
			
		||||
Date: Wed, 7 Jul 2021 11:47:44 +1200
 | 
			
		||||
Subject: [PATCH] Fix KDC null deref on bad encrypted challenge
 | 
			
		||||
 | 
			
		||||
The function ec_verify() in src/kdc/kdc_preauth_ec.c contains a check
 | 
			
		||||
to avoid further processing if the armor key is NULL.  However, this
 | 
			
		||||
check is bypassed by a call to k5memdup0() which overwrites retval
 | 
			
		||||
with 0 if the allocation succeeds.  If the armor key is NULL, a call
 | 
			
		||||
to krb5_c_fx_cf2_simple() will then dereference it, resulting in a
 | 
			
		||||
crash.  Add a check before the k5memdup0() call to avoid overwriting
 | 
			
		||||
retval.
 | 
			
		||||
 | 
			
		||||
CVE-2021-36222:
 | 
			
		||||
 | 
			
		||||
In MIT krb5 releases 1.16 and later, an unauthenticated attacker can
 | 
			
		||||
cause a null dereference in the KDC by sending a request containing a
 | 
			
		||||
PA-ENCRYPTED-CHALLENGE padata element without using FAST.
 | 
			
		||||
 | 
			
		||||
[ghudson@mit.edu: trimmed patch; added test case; edited commit
 | 
			
		||||
message]
 | 
			
		||||
 | 
			
		||||
(cherry picked from commit fc98f520caefff2e5ee9a0026fdf5109944b3562)
 | 
			
		||||
 | 
			
		||||
ticket: 9007
 | 
			
		||||
version_fixed: 1.18.4
 | 
			
		||||
 | 
			
		||||
(cherry picked from commit c4a406095b3ea4a67ae5b8ea586cbe9abdbae76f)
 | 
			
		||||
---
 | 
			
		||||
 src/kdc/kdc_preauth_ec.c      |  3 ++-
 | 
			
		||||
 src/tests/Makefile.in         |  1 +
 | 
			
		||||
 src/tests/t_cve-2021-36222.py | 46 +++++++++++++++++++++++++++++++++++
 | 
			
		||||
 3 files changed, 49 insertions(+), 1 deletion(-)
 | 
			
		||||
 create mode 100644 src/tests/t_cve-2021-36222.py
 | 
			
		||||
 | 
			
		||||
diff --git a/src/kdc/kdc_preauth_ec.c b/src/kdc/kdc_preauth_ec.c
 | 
			
		||||
index 7e636b3f9..43a9902cc 100644
 | 
			
		||||
--- a/src/kdc/kdc_preauth_ec.c
 | 
			
		||||
+++ b/src/kdc/kdc_preauth_ec.c
 | 
			
		||||
@@ -87,7 +87,8 @@ ec_verify(krb5_context context, krb5_data *req_pkt, krb5_kdc_req *request,
 | 
			
		||||
     }
 | 
			
		||||
 
 | 
			
		||||
     /* Check for a configured FAST ec auth indicator. */
 | 
			
		||||
-    realmstr = k5memdup0(realm.data, realm.length, &retval);
 | 
			
		||||
+    if (retval == 0)
 | 
			
		||||
+        realmstr = k5memdup0(realm.data, realm.length, &retval);
 | 
			
		||||
     if (realmstr != NULL)
 | 
			
		||||
         retval = profile_get_string(context->profile, KRB5_CONF_REALMS,
 | 
			
		||||
                                     realmstr,
 | 
			
		||||
diff --git a/src/tests/Makefile.in b/src/tests/Makefile.in
 | 
			
		||||
index 3f88f1713..0ffbebf56 100644
 | 
			
		||||
--- a/src/tests/Makefile.in
 | 
			
		||||
+++ b/src/tests/Makefile.in
 | 
			
		||||
@@ -158,6 +158,7 @@ check-pytests: unlockiter s4u2self
 | 
			
		||||
 	$(RUNPYTEST) $(srcdir)/t_cve-2012-1015.py $(PYTESTFLAGS)
 | 
			
		||||
 	$(RUNPYTEST) $(srcdir)/t_cve-2013-1416.py $(PYTESTFLAGS)
 | 
			
		||||
 	$(RUNPYTEST) $(srcdir)/t_cve-2013-1417.py $(PYTESTFLAGS)
 | 
			
		||||
+	$(RUNPYTEST) $(srcdir)/t_cve-2021-36222.py $(PYTESTFLAGS)
 | 
			
		||||
 	$(RM) au.log
 | 
			
		||||
 	$(RUNPYTEST) $(srcdir)/t_audit.py $(PYTESTFLAGS)
 | 
			
		||||
 	$(RUNPYTEST) $(srcdir)/jsonwalker.py -d $(srcdir)/au_dict.json \
 | 
			
		||||
diff --git a/src/tests/t_cve-2021-36222.py b/src/tests/t_cve-2021-36222.py
 | 
			
		||||
new file mode 100644
 | 
			
		||||
index 000000000..57e04993b
 | 
			
		||||
--- /dev/null
 | 
			
		||||
+++ b/src/tests/t_cve-2021-36222.py
 | 
			
		||||
@@ -0,0 +1,46 @@
 | 
			
		||||
+import socket
 | 
			
		||||
+from k5test import *
 | 
			
		||||
+
 | 
			
		||||
+realm = K5Realm()
 | 
			
		||||
+
 | 
			
		||||
+# CVE-2021-36222 KDC null dereference on encrypted challenge preauth
 | 
			
		||||
+# without FAST
 | 
			
		||||
+
 | 
			
		||||
+s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
 | 
			
		||||
+a = (hostname, realm.portbase)
 | 
			
		||||
+
 | 
			
		||||
+m = ('6A81A0' '30819D'          # [APPLICATION 10] SEQUENCE
 | 
			
		||||
+     'A103' '0201' '05'         #  [1] pvno = 5
 | 
			
		||||
+     'A203' '0201' '0A'         #  [2] msg-type = 10
 | 
			
		||||
+     'A30E' '300C'              #  [3] padata = SEQUENCE OF
 | 
			
		||||
+     '300A'                     #   SEQUENCE
 | 
			
		||||
+     'A104' '0202' '008A'       #    [1] padata-type = PA-ENCRYPTED-CHALLENGE
 | 
			
		||||
+     'A202' '0400'              #    [2] padata-value = ""
 | 
			
		||||
+     'A48180' '307E'            #  [4] req-body = SEQUENCE
 | 
			
		||||
+     'A007' '0305' '0000000000' #   [0] kdc-options = 0
 | 
			
		||||
+     'A120' '301E'              #   [1] cname = SEQUENCE
 | 
			
		||||
+     'A003' '0201' '01'         #    [0] name-type = NT-PRINCIPAL
 | 
			
		||||
+     'A117' '3015'              #    [1] name-string = SEQUENCE-OF
 | 
			
		||||
+     '1B06' '6B7262746774'      #     krbtgt
 | 
			
		||||
+     '1B0B' '4B5242544553542E434F4D'
 | 
			
		||||
+                                #     KRBTEST.COM
 | 
			
		||||
+     'A20D' '1B0B' '4B5242544553542E434F4D'
 | 
			
		||||
+                                #   [2] realm = KRBTEST.COM
 | 
			
		||||
+     'A320' '301E'              #   [3] sname = SEQUENCE
 | 
			
		||||
+     'A003' '0201' '01'         #    [0] name-type = NT-PRINCIPAL
 | 
			
		||||
+     'A117' '3015'              #    [1] name-string = SEQUENCE-OF
 | 
			
		||||
+     '1B06' '6B7262746774'      #     krbtgt
 | 
			
		||||
+     '1B0B' '4B5242544553542E434F4D'
 | 
			
		||||
+                                #     KRBTEST.COM
 | 
			
		||||
+     'A511' '180F' '31393934303631303036303331375A'
 | 
			
		||||
+                                #   [5] till = 19940610060317Z
 | 
			
		||||
+     'A703' '0201' '00'         #   [7] nonce = 0
 | 
			
		||||
+     'A808' '3006'              #   [8] etype = SEQUENCE OF
 | 
			
		||||
+     '020112' '020111')         #    aes256-cts aes128-cts
 | 
			
		||||
+
 | 
			
		||||
+s.sendto(bytes.fromhex(m), a)
 | 
			
		||||
+
 | 
			
		||||
+# Make sure kinit still works.
 | 
			
		||||
+realm.kinit(realm.user_princ, password('user'))
 | 
			
		||||
+
 | 
			
		||||
+success('CVE-2021-36222 regression test')
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
From ce6defae3595fc3d9980bcf5ddc4f1a6ee90d391 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From 7a87189f7bdabc144e22d4caa6a0785a06416d8f Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Greg Hudson <ghudson@mit.edu>
 | 
			
		||||
Date: Fri, 24 Jul 2020 16:05:24 -0400
 | 
			
		||||
Subject: [PATCH] Fix leak in KERB_AP_OPTIONS_CBT server support
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
From 087794ce6a9a529f4e6b0474fbfe3b6be3bc01b2 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From 42e29f27ce64fece2839bcce910813e97ca31210 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Robbie Harwood <rharwood@redhat.com>
 | 
			
		||||
Date: Wed, 15 Jul 2020 15:42:20 -0400
 | 
			
		||||
Subject: [PATCH] Ignore bad enctypes in krb5_string_to_keysalts()
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										28
									
								
								SOURCES/Make-KCM-iteration-fallback-work-with-sssd-kcm.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								SOURCES/Make-KCM-iteration-fallback-work-with-sssd-kcm.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
			
		||||
From b96983de501f185a06e8b3d2909ef71033bd9e48 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
 | 
			
		||||
Date: Tue, 30 Mar 2021 14:35:28 +0200
 | 
			
		||||
Subject: [PATCH] Make KCM iteration fallback work with sssd-kcm
 | 
			
		||||
 | 
			
		||||
sssd-kcm returns KRB5_CC_IO if the operation code is not known.
 | 
			
		||||
 | 
			
		||||
ticket: 8990
 | 
			
		||||
(cherry picked from commit 06afae820a44c1dc96ad88a0b16c3e50bc938b2a)
 | 
			
		||||
(cherry picked from commit 2dbca7e14c945d6394e0e05f285a068dcd541295)
 | 
			
		||||
(cherry picked from commit f7702c5b11bdd186d03fed32568c9a252d049d44)
 | 
			
		||||
---
 | 
			
		||||
 src/lib/krb5/ccache/cc_kcm.c | 2 +-
 | 
			
		||||
 1 file changed, 1 insertion(+), 1 deletion(-)
 | 
			
		||||
 | 
			
		||||
diff --git a/src/lib/krb5/ccache/cc_kcm.c b/src/lib/krb5/ccache/cc_kcm.c
 | 
			
		||||
index 4141140c3..dae622feb 100644
 | 
			
		||||
--- a/src/lib/krb5/ccache/cc_kcm.c
 | 
			
		||||
+++ b/src/lib/krb5/ccache/cc_kcm.c
 | 
			
		||||
@@ -876,7 +876,7 @@ kcm_start_seq_get(krb5_context context, krb5_ccache cache,
 | 
			
		||||
         ret = kcmreq_get_cred_list(&req, &creds);
 | 
			
		||||
         if (ret)
 | 
			
		||||
             goto cleanup;
 | 
			
		||||
-    } else if (ret == KRB5_FCC_INTERNAL) {
 | 
			
		||||
+    } else if (ret == KRB5_FCC_INTERNAL || ret == KRB5_CC_IO) {
 | 
			
		||||
         /* Fall back to GET_CRED_UUID_LIST. */
 | 
			
		||||
         kcmreq_free(&req);
 | 
			
		||||
         kcmreq_init(&req, KCM_OP_GET_CRED_UUID_LIST, cache);
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
From 54dade355262fafab54572384c4215cc6c63ecfb Mon Sep 17 00:00:00 2001
 | 
			
		||||
From 6858ecbb9c407ff6d2b22cac283ea2461af1757b Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Robbie Harwood <rharwood@redhat.com>
 | 
			
		||||
Date: Thu, 20 Aug 2020 17:49:29 -0400
 | 
			
		||||
Subject: [PATCH] Unify kvno option documentation
 | 
			
		||||
@ -25,15 +25,14 @@ target_version: 1.18-next
 | 
			
		||||
 | 
			
		||||
(cherry picked from commit becd1ad6830b526d08ddaf5b2b6f213154c6446c)
 | 
			
		||||
(cherry picked from commit 52e3695cc5ef00766e12adfe8ed276c2885e71bb)
 | 
			
		||||
[rharwood@redhat.com: backport around added kvno options]
 | 
			
		||||
---
 | 
			
		||||
 doc/user/user_commands/kvno.rst | 17 +++++++++--------
 | 
			
		||||
 src/clients/kvno/kvno.c         | 12 ++++++++----
 | 
			
		||||
 src/man/kvno.man                | 17 +++++++++--------
 | 
			
		||||
 3 files changed, 26 insertions(+), 20 deletions(-)
 | 
			
		||||
 doc/user/user_commands/kvno.rst | 24 +++++++++++++-----------
 | 
			
		||||
 src/clients/kvno/kvno.c         | 15 +++++++++------
 | 
			
		||||
 src/man/kvno.man                | 24 +++++++++++++-----------
 | 
			
		||||
 3 files changed, 35 insertions(+), 28 deletions(-)
 | 
			
		||||
 | 
			
		||||
diff --git a/doc/user/user_commands/kvno.rst b/doc/user/user_commands/kvno.rst
 | 
			
		||||
index 3892f0ca5..53e569651 100644
 | 
			
		||||
index 718313576..65c44e1c0 100644
 | 
			
		||||
--- a/doc/user/user_commands/kvno.rst
 | 
			
		||||
+++ b/doc/user/user_commands/kvno.rst
 | 
			
		||||
@@ -10,13 +10,9 @@ SYNOPSIS
 | 
			
		||||
@ -73,11 +72,32 @@ index 3892f0ca5..53e569651 100644
 | 
			
		||||
 
 | 
			
		||||
 **-P**
 | 
			
		||||
     Specifies that the *service1 service2* ...  arguments are to be
 | 
			
		||||
@@ -76,16 +77,17 @@ OPTIONS
 | 
			
		||||
 
 | 
			
		||||
 **--cached-only**
 | 
			
		||||
     Only retrieve credentials already present in the cache, not from
 | 
			
		||||
-    the KDC.
 | 
			
		||||
+    the KDC.  (Added in release 1.19.)
 | 
			
		||||
 
 | 
			
		||||
 **--no-store**
 | 
			
		||||
     Do not store retrieved credentials in the cache.  If
 | 
			
		||||
     **--out-cache** is also specified, credentials will still be
 | 
			
		||||
-    stored into the output credential cache.
 | 
			
		||||
+    stored into the output credential cache.  (Added in release 1.19.)
 | 
			
		||||
 
 | 
			
		||||
 **--out-cache** *ccache*
 | 
			
		||||
     Initialize *ccache* and store all retrieved credentials into it.
 | 
			
		||||
-    Do not store acquired credentials in the input cache.
 | 
			
		||||
+    Do not store acquired credentials in the input cache.  (Added in
 | 
			
		||||
+    release 1.19.)
 | 
			
		||||
 
 | 
			
		||||
 **--u2u** *ccache*
 | 
			
		||||
     Requests a user-to-user ticket.  *ccache* must contain a local
 | 
			
		||||
diff --git a/src/clients/kvno/kvno.c b/src/clients/kvno/kvno.c
 | 
			
		||||
index 2472c0cfe..8edd97361 100644
 | 
			
		||||
index 9d85864f6..c5f6bf700 100644
 | 
			
		||||
--- a/src/clients/kvno/kvno.c
 | 
			
		||||
+++ b/src/clients/kvno/kvno.c
 | 
			
		||||
@@ -38,13 +38,17 @@
 | 
			
		||||
@@ -38,15 +38,18 @@
 | 
			
		||||
 static char *prog;
 | 
			
		||||
 static int quiet = 0;
 | 
			
		||||
 
 | 
			
		||||
@ -89,18 +109,21 @@ index 2472c0cfe..8edd97361 100644
 | 
			
		||||
-    fprintf(stderr, _("usage: %s [-C] [-u] [-c ccache] [-e etype]\n"), prog);
 | 
			
		||||
-    fprintf(stderr, _("\t[-k keytab] [-S sname] [{-I | -U} for_user | "
 | 
			
		||||
-                      "[-F cert_file] [-P]]\n"));
 | 
			
		||||
-    fprintf(stderr, _("\t[--u2u ccache] service1 service2 ...\n"));
 | 
			
		||||
-    fprintf(stderr, _("\t[--cached-only] [--no-store] [--out-cache ccache] "
 | 
			
		||||
-                      "[--u2u ccache]\n"));
 | 
			
		||||
-    fprintf(stderr, _("\tservice1 service2 ...\n"));
 | 
			
		||||
+    fprintf(stderr, _("usage: %s [-c ccache] [-e etype] [-k keytab] [-q] "
 | 
			
		||||
+                      "[-u | -S sname]" XUSAGE_BREAK
 | 
			
		||||
+                      "[[{-F cert_file | {-I | -U} for_user} [-P]] | "
 | 
			
		||||
+                      "--u2u ccache]" XUSAGE_BREAK
 | 
			
		||||
+                      "[--cached-only] [--no-store] [--out-cache] "
 | 
			
		||||
+                      "service1 service2 ...\n"),
 | 
			
		||||
+            prog);
 | 
			
		||||
     exit(1);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
diff --git a/src/man/kvno.man b/src/man/kvno.man
 | 
			
		||||
index 005a2ec97..e156df723 100644
 | 
			
		||||
index b9f6739eb..22318324d 100644
 | 
			
		||||
--- a/src/man/kvno.man
 | 
			
		||||
+++ b/src/man/kvno.man
 | 
			
		||||
@@ -36,13 +36,9 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
 | 
			
		||||
@ -140,3 +163,24 @@ index 005a2ec97..e156df723 100644
 | 
			
		||||
 .TP
 | 
			
		||||
 \fB\-P\fP
 | 
			
		||||
 Specifies that the \fIservice1 service2\fP ...  arguments are to be
 | 
			
		||||
@@ -97,16 +98,17 @@ certificate file must be in PEM format.
 | 
			
		||||
 .TP
 | 
			
		||||
 \fB\-\-cached\-only\fP
 | 
			
		||||
 Only retrieve credentials already present in the cache, not from
 | 
			
		||||
-the KDC.
 | 
			
		||||
+the KDC.  (Added in release 1.19.)
 | 
			
		||||
 .TP
 | 
			
		||||
 \fB\-\-no\-store\fP
 | 
			
		||||
 Do not store retrieved credentials in the cache.  If
 | 
			
		||||
 \fB\-\-out\-cache\fP is also specified, credentials will still be
 | 
			
		||||
-stored into the output credential cache.
 | 
			
		||||
+stored into the output credential cache.  (Added in release 1.19.)
 | 
			
		||||
 .TP
 | 
			
		||||
 \fB\-\-out\-cache\fP \fIccache\fP
 | 
			
		||||
 Initialize \fIccache\fP and store all retrieved credentials into it.
 | 
			
		||||
-Do not store acquired credentials in the input cache.
 | 
			
		||||
+Do not store acquired credentials in the input cache.  (Added in
 | 
			
		||||
+release 1.19.)
 | 
			
		||||
 .TP
 | 
			
		||||
 \fB\-\-u2u\fP \fIccache\fP
 | 
			
		||||
 Requests a user\-to\-user ticket.  \fIccache\fP must contain a local
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										237
									
								
								SOURCES/Use-KCM_OP_RETRIEVE-in-KCM-client.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										237
									
								
								SOURCES/Use-KCM_OP_RETRIEVE-in-KCM-client.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,237 @@
 | 
			
		||||
From 00a2ccfeaeac7a0019a73a97cfe33063ba90c7f3 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Greg Hudson <ghudson@mit.edu>
 | 
			
		||||
Date: Fri, 26 Mar 2021 23:38:54 -0400
 | 
			
		||||
Subject: [PATCH] Use KCM_OP_RETRIEVE in KCM client
 | 
			
		||||
 | 
			
		||||
In kcm_retrieve(), try KCM_OP_RETRIEVE.  Fall back to iteration if the
 | 
			
		||||
server doesn't implement it, or if we can an answer incompatible with
 | 
			
		||||
KRB5_TC_SUPPORTED_KTYPES.
 | 
			
		||||
 | 
			
		||||
In kcmserver.py, implement partial decoding for creds and cred tags so
 | 
			
		||||
that we can do a basic principal name match.
 | 
			
		||||
 | 
			
		||||
ticket: 8997 (new)
 | 
			
		||||
(cherry picked from commit 795ebba8c039be172ab93cd41105c73ffdba0fdb)
 | 
			
		||||
(cherry picked from commit c56d4b87de0f30a38dc61d374ad225d02d581eb3)
 | 
			
		||||
(cherry picked from commit ac0a117096324fa73afae291ed467f2ea66e279b)
 | 
			
		||||
---
 | 
			
		||||
 src/include/kcm.h            |  2 +-
 | 
			
		||||
 src/lib/krb5/ccache/cc_kcm.c | 52 +++++++++++++++++++++++++++++++++---
 | 
			
		||||
 src/tests/kcmserver.py       | 44 +++++++++++++++++++++++++++---
 | 
			
		||||
 src/tests/t_ccache.py        | 11 +++++---
 | 
			
		||||
 4 files changed, 99 insertions(+), 10 deletions(-)
 | 
			
		||||
 | 
			
		||||
diff --git a/src/include/kcm.h b/src/include/kcm.h
 | 
			
		||||
index 9b66f1cbd..85c20d345 100644
 | 
			
		||||
--- a/src/include/kcm.h
 | 
			
		||||
+++ b/src/include/kcm.h
 | 
			
		||||
@@ -87,7 +87,7 @@ typedef enum kcm_opcode {
 | 
			
		||||
     KCM_OP_INITIALIZE,          /*          (name, princ) -> ()          */
 | 
			
		||||
     KCM_OP_DESTROY,             /*                 (name) -> ()          */
 | 
			
		||||
     KCM_OP_STORE,               /*           (name, cred) -> ()          */
 | 
			
		||||
-    KCM_OP_RETRIEVE,
 | 
			
		||||
+    KCM_OP_RETRIEVE,            /* (name, flags, credtag) -> (cred)      */
 | 
			
		||||
     KCM_OP_GET_PRINCIPAL,       /*                 (name) -> (princ)     */
 | 
			
		||||
     KCM_OP_GET_CRED_UUID_LIST,  /*                 (name) -> (uuid, ...) */
 | 
			
		||||
     KCM_OP_GET_CRED_BY_UUID,    /*           (name, uuid) -> (cred)      */
 | 
			
		||||
diff --git a/src/lib/krb5/ccache/cc_kcm.c b/src/lib/krb5/ccache/cc_kcm.c
 | 
			
		||||
index dae622feb..b600c6f15 100644
 | 
			
		||||
--- a/src/lib/krb5/ccache/cc_kcm.c
 | 
			
		||||
+++ b/src/lib/krb5/ccache/cc_kcm.c
 | 
			
		||||
@@ -826,9 +826,55 @@ static krb5_error_code KRB5_CALLCONV
 | 
			
		||||
 kcm_retrieve(krb5_context context, krb5_ccache cache, krb5_flags flags,
 | 
			
		||||
              krb5_creds *mcred, krb5_creds *cred_out)
 | 
			
		||||
 {
 | 
			
		||||
-    /* There is a KCM opcode for retrieving creds, but Heimdal's client doesn't
 | 
			
		||||
-     * use it.  It causes the KCM daemon to actually make a TGS request. */
 | 
			
		||||
-    return k5_cc_retrieve_cred_default(context, cache, flags, mcred, cred_out);
 | 
			
		||||
+    krb5_error_code ret;
 | 
			
		||||
+    struct kcmreq req = EMPTY_KCMREQ;
 | 
			
		||||
+    krb5_creds cred;
 | 
			
		||||
+    krb5_enctype *enctypes = NULL;
 | 
			
		||||
+
 | 
			
		||||
+    memset(&cred, 0, sizeof(cred));
 | 
			
		||||
+
 | 
			
		||||
+    /* Include KCM_GC_CACHED in flags to prevent Heimdal's sssd from making a
 | 
			
		||||
+     * TGS request itself. */
 | 
			
		||||
+    kcmreq_init(&req, KCM_OP_RETRIEVE, cache);
 | 
			
		||||
+    k5_buf_add_uint32_be(&req.reqbuf, map_tcflags(flags) | KCM_GC_CACHED);
 | 
			
		||||
+    k5_marshal_mcred(&req.reqbuf, mcred);
 | 
			
		||||
+    ret = cache_call(context, cache, &req);
 | 
			
		||||
+
 | 
			
		||||
+    /* Fall back to iteration if the server does not support retrieval. */
 | 
			
		||||
+    if (ret == KRB5_FCC_INTERNAL || ret == KRB5_CC_IO) {
 | 
			
		||||
+        ret = k5_cc_retrieve_cred_default(context, cache, flags, mcred,
 | 
			
		||||
+                                          cred_out);
 | 
			
		||||
+        goto cleanup;
 | 
			
		||||
+    }
 | 
			
		||||
+    if (ret)
 | 
			
		||||
+        goto cleanup;
 | 
			
		||||
+
 | 
			
		||||
+    ret = k5_unmarshal_cred(req.reply.ptr, req.reply.len, 4, &cred);
 | 
			
		||||
+    if (ret)
 | 
			
		||||
+        goto cleanup;
 | 
			
		||||
+
 | 
			
		||||
+    /* In rare cases we might retrieve a credential with a session key this
 | 
			
		||||
+     * context can't support, in which case we must retry using iteration. */
 | 
			
		||||
+    if (flags & KRB5_TC_SUPPORTED_KTYPES) {
 | 
			
		||||
+        ret = krb5_get_tgs_ktypes(context, cred.server, &enctypes);
 | 
			
		||||
+        if (ret)
 | 
			
		||||
+            goto cleanup;
 | 
			
		||||
+        if (!k5_etypes_contains(enctypes, cred.keyblock.enctype)) {
 | 
			
		||||
+            ret = k5_cc_retrieve_cred_default(context, cache, flags, mcred,
 | 
			
		||||
+                                              cred_out);
 | 
			
		||||
+            goto cleanup;
 | 
			
		||||
+        }
 | 
			
		||||
+    }
 | 
			
		||||
+
 | 
			
		||||
+    *cred_out = cred;
 | 
			
		||||
+    memset(&cred, 0, sizeof(cred));
 | 
			
		||||
+
 | 
			
		||||
+cleanup:
 | 
			
		||||
+    kcmreq_free(&req);
 | 
			
		||||
+    krb5_free_cred_contents(context, &cred);
 | 
			
		||||
+    free(enctypes);
 | 
			
		||||
+    /* Heimdal's KCM returns KRB5_CC_END if no cred is found. */
 | 
			
		||||
+    return (ret == KRB5_CC_END) ? KRB5_CC_NOTFOUND : map_invalid(ret);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static krb5_error_code KRB5_CALLCONV
 | 
			
		||||
diff --git a/src/tests/kcmserver.py b/src/tests/kcmserver.py
 | 
			
		||||
index 8c5e66ff1..25e6f2bbe 100644
 | 
			
		||||
--- a/src/tests/kcmserver.py
 | 
			
		||||
+++ b/src/tests/kcmserver.py
 | 
			
		||||
@@ -40,6 +40,7 @@ class KCMOpcodes(object):
 | 
			
		||||
     INITIALIZE = 4
 | 
			
		||||
     DESTROY = 5
 | 
			
		||||
     STORE = 6
 | 
			
		||||
+    RETRIEVE = 7
 | 
			
		||||
     GET_PRINCIPAL = 8
 | 
			
		||||
     GET_CRED_UUID_LIST = 9
 | 
			
		||||
     GET_CRED_BY_UUID = 10
 | 
			
		||||
@@ -54,6 +55,7 @@ class KCMOpcodes(object):
 | 
			
		||||
 
 | 
			
		||||
 
 | 
			
		||||
 class KRB5Errors(object):
 | 
			
		||||
+    KRB5_CC_NOTFOUND = -1765328243
 | 
			
		||||
     KRB5_CC_END = -1765328242
 | 
			
		||||
     KRB5_CC_NOSUPP = -1765328137
 | 
			
		||||
     KRB5_FCC_NOFILE = -1765328189
 | 
			
		||||
@@ -86,11 +88,29 @@ def get_cache(name):
 | 
			
		||||
     return cache
 | 
			
		||||
 
 | 
			
		||||
 
 | 
			
		||||
+def unpack_data(argbytes):
 | 
			
		||||
+    dlen, = struct.unpack('>L', argbytes[:4])
 | 
			
		||||
+    return argbytes[4:dlen+4], argbytes[dlen+4:]
 | 
			
		||||
+
 | 
			
		||||
+
 | 
			
		||||
 def unmarshal_name(argbytes):
 | 
			
		||||
     offset = argbytes.find(b'\0')
 | 
			
		||||
     return argbytes[0:offset], argbytes[offset+1:]
 | 
			
		||||
 
 | 
			
		||||
 
 | 
			
		||||
+def unmarshal_princ(argbytes):
 | 
			
		||||
+    # Ignore the type at argbytes[0:4].
 | 
			
		||||
+    ncomps, = struct.unpack('>L', argbytes[4:8])
 | 
			
		||||
+    realm, rest = unpack_data(argbytes[8:])
 | 
			
		||||
+    comps = []
 | 
			
		||||
+    for i in range(ncomps):
 | 
			
		||||
+        comp, rest = unpack_data(rest)
 | 
			
		||||
+        comps.append(comp)
 | 
			
		||||
+    # Asssume no quoting is needed.
 | 
			
		||||
+    princ = b'/'.join(comps) + b'@' + realm
 | 
			
		||||
+    return princ, rest
 | 
			
		||||
+
 | 
			
		||||
+
 | 
			
		||||
 def op_gen_new(argbytes):
 | 
			
		||||
     # Does not actually check for uniqueness.
 | 
			
		||||
     global next_unique
 | 
			
		||||
@@ -126,6 +146,22 @@ def op_store(argbytes):
 | 
			
		||||
     return 0, b''
 | 
			
		||||
 
 | 
			
		||||
 
 | 
			
		||||
+def op_retrieve(argbytes):
 | 
			
		||||
+    name, rest = unmarshal_name(argbytes)
 | 
			
		||||
+    # Ignore the flags at rest[0:4] and the header at rest[4:8].
 | 
			
		||||
+    # Assume there are client and server creds in the tag and match
 | 
			
		||||
+    # only against them.
 | 
			
		||||
+    cprinc, rest = unmarshal_princ(rest[8:])
 | 
			
		||||
+    sprinc, rest = unmarshal_princ(rest)
 | 
			
		||||
+    cache = get_cache(name)
 | 
			
		||||
+    for cred in (cache.creds[u] for u in cache.cred_uuids):
 | 
			
		||||
+        cred_cprinc, rest = unmarshal_princ(cred)
 | 
			
		||||
+        cred_sprinc, rest = unmarshal_princ(rest)
 | 
			
		||||
+        if cred_cprinc == cprinc and cred_sprinc == sprinc:
 | 
			
		||||
+            return 0, cred
 | 
			
		||||
+    return KRB5Errors.KRB5_CC_NOTFOUND, b''
 | 
			
		||||
+
 | 
			
		||||
+
 | 
			
		||||
 def op_get_principal(argbytes):
 | 
			
		||||
     name, rest = unmarshal_name(argbytes)
 | 
			
		||||
     cache = get_cache(name)
 | 
			
		||||
@@ -199,6 +235,7 @@ ophandlers = {
 | 
			
		||||
     KCMOpcodes.INITIALIZE : op_initialize,
 | 
			
		||||
     KCMOpcodes.DESTROY : op_destroy,
 | 
			
		||||
     KCMOpcodes.STORE : op_store,
 | 
			
		||||
+    KCMOpcodes.RETRIEVE : op_retrieve,
 | 
			
		||||
     KCMOpcodes.GET_PRINCIPAL : op_get_principal,
 | 
			
		||||
     KCMOpcodes.GET_CRED_UUID_LIST : op_get_cred_uuid_list,
 | 
			
		||||
     KCMOpcodes.GET_CRED_BY_UUID : op_get_cred_by_uuid,
 | 
			
		||||
@@ -243,10 +280,11 @@ def service_request(s):
 | 
			
		||||
     return True
 | 
			
		||||
 
 | 
			
		||||
 parser = optparse.OptionParser()
 | 
			
		||||
-parser.add_option('-c', '--credlist', action='store_true', dest='credlist',
 | 
			
		||||
-                  default=False, help='Support KCM_OP_GET_CRED_LIST')
 | 
			
		||||
+parser.add_option('-f', '--fallback', action='store_true', dest='fallback',
 | 
			
		||||
+                  default=False, help='Do not support RETRIEVE/GET_CRED_LIST')
 | 
			
		||||
 (options, args) = parser.parse_args()
 | 
			
		||||
-if not options.credlist:
 | 
			
		||||
+if options.fallback:
 | 
			
		||||
+    del ophandlers[KCMOpcodes.RETRIEVE]
 | 
			
		||||
     del ophandlers[KCMOpcodes.GET_CRED_LIST]
 | 
			
		||||
 
 | 
			
		||||
 server = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
 | 
			
		||||
diff --git a/src/tests/t_ccache.py b/src/tests/t_ccache.py
 | 
			
		||||
index 90040fb7b..6ea9fb969 100755
 | 
			
		||||
--- a/src/tests/t_ccache.py
 | 
			
		||||
+++ b/src/tests/t_ccache.py
 | 
			
		||||
@@ -25,7 +25,7 @@ from k5test import *
 | 
			
		||||
 kcm_socket_path = os.path.join(os.getcwd(), 'testdir', 'kcm')
 | 
			
		||||
 conf = {'libdefaults': {'kcm_socket': kcm_socket_path,
 | 
			
		||||
                         'kcm_mach_service': '-'}}
 | 
			
		||||
-realm = K5Realm(create_host=False, krb5_conf=conf)
 | 
			
		||||
+realm = K5Realm(krb5_conf=conf)
 | 
			
		||||
 
 | 
			
		||||
 keyctl = which('keyctl')
 | 
			
		||||
 out = realm.run([klist, '-c', 'KEYRING:process:abcd'], expected_code=1)
 | 
			
		||||
@@ -71,6 +71,11 @@ def collection_test(realm, ccname):
 | 
			
		||||
     realm.kinit('alice', password('alice'))
 | 
			
		||||
     realm.run([klist], expected_msg='Default principal: alice@')
 | 
			
		||||
     realm.run([klist, '-A', '-s'])
 | 
			
		||||
+    realm.run([kvno, realm.host_princ], expected_msg = 'kvno = 1')
 | 
			
		||||
+    realm.run([kvno, realm.host_princ], expected_msg = 'kvno = 1')
 | 
			
		||||
+    out = realm.run([klist])
 | 
			
		||||
+    if out.count(realm.host_princ) != 1:
 | 
			
		||||
+        fail('Wrong number of service tickets in cache')
 | 
			
		||||
     realm.run([kdestroy])
 | 
			
		||||
     output = realm.run([klist], expected_code=1)
 | 
			
		||||
     if 'No credentials cache' not in output and 'not found' not in output:
 | 
			
		||||
@@ -126,14 +131,14 @@ def collection_test(realm, ccname):
 | 
			
		||||
 
 | 
			
		||||
 collection_test(realm, 'DIR:' + os.path.join(realm.testdir, 'cc'))
 | 
			
		||||
 
 | 
			
		||||
-# Test KCM without and with GET_CRED_LIST support.
 | 
			
		||||
+# Test KCM with and without RETRIEVE and GET_CRED_LIST support.
 | 
			
		||||
 kcmserver_path = os.path.join(srctop, 'tests', 'kcmserver.py')
 | 
			
		||||
 kcmd = realm.start_server([sys.executable, kcmserver_path, kcm_socket_path],
 | 
			
		||||
                           'starting...')
 | 
			
		||||
 collection_test(realm, 'KCM:')
 | 
			
		||||
 stop_daemon(kcmd)
 | 
			
		||||
 os.remove(kcm_socket_path)
 | 
			
		||||
-realm.start_server([sys.executable, kcmserver_path, '-c', kcm_socket_path],
 | 
			
		||||
+realm.start_server([sys.executable, kcmserver_path, '-f', kcm_socket_path],
 | 
			
		||||
                    'starting...')
 | 
			
		||||
 collection_test(realm, 'KCM:')
 | 
			
		||||
 
 | 
			
		||||
@ -1 +1 @@
 | 
			
		||||
d /var/run/krb5kdc 0755 root root
 | 
			
		||||
d /run/krb5kdc 0755 root root
 | 
			
		||||
 | 
			
		||||
@ -18,7 +18,7 @@ Summary: The Kerberos network authentication system
 | 
			
		||||
Name: krb5
 | 
			
		||||
Version: 1.18.2
 | 
			
		||||
# for prerelease, should be e.g., 0.% {prerelease}.1% { ?dist } (without spaces)
 | 
			
		||||
Release: 8%{?dist}
 | 
			
		||||
Release: 14%{?dist}
 | 
			
		||||
 | 
			
		||||
# lookaside-cached sources; two downloads and a build artifact
 | 
			
		||||
Source0: https://web.mit.edu/kerberos/dist/krb5/1.18/krb5-%{version}%{prerelease}.tar.gz
 | 
			
		||||
@ -71,11 +71,21 @@ Patch125: Implement-KERB_AP_OPTIONS_CBT-server-side.patch
 | 
			
		||||
Patch126: Add-client_aware_channel_bindings-option.patch
 | 
			
		||||
Patch127: Pass-channel-bindings-through-SPNEGO.patch
 | 
			
		||||
Patch128: Add-channel-bindings-tests.patch
 | 
			
		||||
Patch129: Ignore-bad-enctypes-in-krb5_string_to_keysalts.patch
 | 
			
		||||
Patch130: Fix-leak-in-KERB_AP_OPTIONS_CBT-server-support.patch
 | 
			
		||||
Patch131: Unify-kvno-option-documentation.patch
 | 
			
		||||
Patch132: Document-k-option-in-kvno-1-synopsis.patch
 | 
			
		||||
Patch133: Add-recursion-limit-for-ASN.1-indefinite-lengths.patch
 | 
			
		||||
Patch129: Add-three-kvno-options-from-Heimdal-kgetcred.patch
 | 
			
		||||
Patch130: Ignore-bad-enctypes-in-krb5_string_to_keysalts.patch
 | 
			
		||||
Patch131: Fix-leak-in-KERB_AP_OPTIONS_CBT-server-support.patch
 | 
			
		||||
Patch132: Unify-kvno-option-documentation.patch
 | 
			
		||||
Patch133: Document-k-option-in-kvno-1-synopsis.patch
 | 
			
		||||
Patch134: Add-recursion-limit-for-ASN.1-indefinite-lengths.patch
 | 
			
		||||
Patch135: Add-support-for-start_realm-cache-config.patch
 | 
			
		||||
Patch136: Add-APIs-for-marshalling-credentials.patch
 | 
			
		||||
Patch137: Add-KCM_OP_GET_CRED_LIST-for-faster-iteration.patch
 | 
			
		||||
Patch138: Fix-KCM-flag-transmission-for-remove_cred.patch
 | 
			
		||||
Patch139: Make-KCM-iteration-fallback-work-with-sssd-kcm.patch
 | 
			
		||||
Patch140: Use-KCM_OP_RETRIEVE-in-KCM-client.patch
 | 
			
		||||
Patch141: Fix-KCM-retrieval-support-for-sssd.patch
 | 
			
		||||
Patch142: Fix-KDC-null-deref-on-bad-encrypted-challenge.patch
 | 
			
		||||
Patch143: Fix-KDC-null-deref-on-TGS-inner-body-null-server.patch
 | 
			
		||||
 | 
			
		||||
License: MIT
 | 
			
		||||
URL: http://web.mit.edu/kerberos/www/
 | 
			
		||||
@ -686,6 +696,30 @@ exit 0
 | 
			
		||||
%{_libdir}/libkadm5srv_mit.so.*
 | 
			
		||||
 | 
			
		||||
%changelog
 | 
			
		||||
* Wed Aug 25 2021 Robbie Harwood <rharwood@redhat.com> - 1.18.2-14
 | 
			
		||||
- Fix KDC null deref on TGS inner body null server (CVE-2021-37750)
 | 
			
		||||
- Resolves: #1997601
 | 
			
		||||
 | 
			
		||||
* Tue Jul 20 2021 Robbie Harwood <rharwood@redhat.com> - 1.18.2-13
 | 
			
		||||
- Fix KDC null deref on bad encrypted challenge (CVE-2021-36222)
 | 
			
		||||
- Resolves: #1983729
 | 
			
		||||
 | 
			
		||||
* Thu Jun 10 2021 Robbie Harwood <rharwood@redhat.com> - 1.18.2-12
 | 
			
		||||
- Backport KCM performance enablements
 | 
			
		||||
- Resolves: #1956388
 | 
			
		||||
 | 
			
		||||
* Thu Jun 10 2021 Robbie Harwood <rharwood@redhat.com> - 1.18.2-11
 | 
			
		||||
- Add APIs for marshalling credentials
 | 
			
		||||
- Resolves: #1964619
 | 
			
		||||
 | 
			
		||||
* Mon May 03 2021 Robbie Harwood <rharwood@redhat.com> - 1.18.2-10
 | 
			
		||||
- Update tmpfiles dropin to use /run instead of /var/run
 | 
			
		||||
- Resolves: #1945679
 | 
			
		||||
 | 
			
		||||
* Tue Apr 20 2021 Robbie Harwood <rharwood@redhat.com> - 1.18.2-9
 | 
			
		||||
- Add support for start_realm cache config
 | 
			
		||||
- Resolves: #1901195
 | 
			
		||||
 | 
			
		||||
* Wed Dec 16 2020 Robbie Harwood <rharwood@redhat.com> - 1.18.2-8
 | 
			
		||||
- Add recursion limit for ASN.1 indefinite lengths (CVE-2020-28196)
 | 
			
		||||
- Resolves: #1906492
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user