Compare commits
11 Commits
imports/c8
...
c8
Author | SHA1 | Date | |
---|---|---|---|
fc51be7bd6 | |||
d29ac3a0b1 | |||
d760d9c2dc | |||
81bd838f78 | |||
|
72f8fad7b9 | ||
6d26dc1d96 | |||
|
b3034f73a2 | ||
|
978a4ade58 | ||
|
0314e20873 | ||
|
475028c8e9 | ||
|
8d2db90722 |
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])
|
673
SOURCES/Add-PAC-full-checksums.patch
Normal file
673
SOURCES/Add-PAC-full-checksums.patch
Normal file
@ -0,0 +1,673 @@
|
||||
From bf3e55bcd66c5d35fddadc94fd680bdd57508bce Mon Sep 17 00:00:00 2001
|
||||
From: Greg Hudson <ghudson@mit.edu>
|
||||
Date: Thu, 22 Dec 2022 03:05:23 -0500
|
||||
Subject: [PATCH] Add PAC full checksums
|
||||
|
||||
A paper by Tom Tervoort noted that computing the PAC privsvr checksum
|
||||
over only the server checksum is vulnerable to collision attacks
|
||||
(CVE-2022-37967). In response, Microsoft has added a second KDC
|
||||
checksum over the full contents of the PAC. Generate and verify full
|
||||
KDC checksums in PACs for service tickets. Update the t_pac.c ticket
|
||||
test case to use a ticket issued by a recent version of Active
|
||||
Directory (provided by Stefan Metzmacher).
|
||||
|
||||
ticket: 9084 (new)
|
||||
---
|
||||
doc/appdev/refs/macros/index.rst | 1 +
|
||||
src/include/krb5/krb5.hin | 1 +
|
||||
src/lib/krb5/krb/pac.c | 92 +++++++++--------
|
||||
src/lib/krb5/krb/pac_sign.c | 146 +++++++++++++++-----------
|
||||
src/lib/krb5/krb/t_pac.c | 171 ++++++++++++++++++-------------
|
||||
src/tests/t_authdata.py | 5 +-
|
||||
6 files changed, 242 insertions(+), 174 deletions(-)
|
||||
|
||||
diff --git a/doc/appdev/refs/macros/index.rst b/doc/appdev/refs/macros/index.rst
|
||||
index c6ea088742..22ef2b2f42 100644
|
||||
--- a/doc/appdev/refs/macros/index.rst
|
||||
+++ b/doc/appdev/refs/macros/index.rst
|
||||
@@ -247,6 +247,7 @@ Public
|
||||
KRB5_PAC_SERVER_CHECKSUM.rst
|
||||
KRB5_PAC_TICKET_CHECKSUM.rst
|
||||
KRB5_PAC_UPN_DNS_INFO.rst
|
||||
+ KRB5_PAC_FULL_CHECKSUM.rst
|
||||
KRB5_PADATA_AFS3_SALT.rst
|
||||
KRB5_PADATA_AP_REQ.rst
|
||||
KRB5_PADATA_AS_CHECKSUM.rst
|
||||
diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin
|
||||
index 8e59628bd9..12a1d441b8 100644
|
||||
--- a/src/include/krb5/krb5.hin
|
||||
+++ b/src/include/krb5/krb5.hin
|
||||
@@ -8187,6 +8187,7 @@ krb5_verify_authdata_kdc_issued(krb5_context context,
|
||||
#define KRB5_PAC_TICKET_CHECKSUM 16 /**< Ticket checksum */
|
||||
#define KRB5_PAC_ATTRIBUTES_INFO 17 /**< PAC attributes */
|
||||
#define KRB5_PAC_REQUESTOR 18 /**< PAC requestor SID */
|
||||
+#define KRB5_PAC_FULL_CHECKSUM 19 /**< KDC full checksum */
|
||||
|
||||
struct krb5_pac_data;
|
||||
/** PAC data structure to convey authorization information */
|
||||
diff --git a/src/lib/krb5/krb/pac.c b/src/lib/krb5/krb/pac.c
|
||||
index 2f6ad4e1df..9c00178a28 100644
|
||||
--- a/src/lib/krb5/krb/pac.c
|
||||
+++ b/src/lib/krb5/krb/pac.c
|
||||
@@ -500,7 +500,8 @@ zero_signature(krb5_context context, const krb5_pac pac, krb5_ui_4 type,
|
||||
size_t i;
|
||||
|
||||
assert(type == KRB5_PAC_SERVER_CHECKSUM ||
|
||||
- type == KRB5_PAC_PRIVSVR_CHECKSUM);
|
||||
+ type == KRB5_PAC_PRIVSVR_CHECKSUM ||
|
||||
+ type == KRB5_PAC_FULL_CHECKSUM);
|
||||
assert(data->length >= pac->data.length);
|
||||
|
||||
for (i = 0; i < pac->pac->cBuffers; i++) {
|
||||
@@ -567,17 +568,17 @@ verify_checksum(krb5_context context, const krb5_pac pac, uint32_t buffer_type,
|
||||
}
|
||||
|
||||
static krb5_error_code
|
||||
-verify_server_checksum(krb5_context context, const krb5_pac pac,
|
||||
- const krb5_keyblock *server)
|
||||
+verify_pac_checksums(krb5_context context, const krb5_pac pac,
|
||||
+ krb5_boolean expect_full_checksum,
|
||||
+ const krb5_keyblock *server, const krb5_keyblock *privsvr)
|
||||
{
|
||||
krb5_error_code ret;
|
||||
- krb5_data copy; /* PAC with zeroed checksums */
|
||||
+ krb5_data copy, server_checksum;
|
||||
|
||||
+ /* Make a copy of the PAC with zeroed out server and privsvr checksums. */
|
||||
ret = krb5int_copy_data_contents(context, &pac->data, ©);
|
||||
if (ret)
|
||||
return ret;
|
||||
-
|
||||
- /* Zero out both checksum buffers */
|
||||
ret = zero_signature(context, pac, KRB5_PAC_SERVER_CHECKSUM, ©);
|
||||
if (ret)
|
||||
goto cleanup;
|
||||
@@ -585,32 +586,46 @@ verify_server_checksum(krb5_context context, const krb5_pac pac,
|
||||
if (ret)
|
||||
goto cleanup;
|
||||
|
||||
- ret = verify_checksum(context, pac, KRB5_PAC_SERVER_CHECKSUM, server,
|
||||
- KRB5_KEYUSAGE_APP_DATA_CKSUM, ©);
|
||||
+ if (server != NULL) {
|
||||
+ /* Verify the server checksum over the PAC copy. */
|
||||
+ ret = verify_checksum(context, pac, KRB5_PAC_SERVER_CHECKSUM, server,
|
||||
+ KRB5_KEYUSAGE_APP_DATA_CKSUM, ©);
|
||||
+ }
|
||||
|
||||
-cleanup:
|
||||
- free(copy.data);
|
||||
- return ret;
|
||||
-}
|
||||
+ if (privsvr != NULL && expect_full_checksum) {
|
||||
+ /* Zero the full checksum buffer in the copy and verify the full
|
||||
+ * checksum over the copy with all three checksums zeroed. */
|
||||
+ ret = zero_signature(context, pac, KRB5_PAC_FULL_CHECKSUM, ©);
|
||||
+ if (ret)
|
||||
+ goto cleanup;
|
||||
+ ret = verify_checksum(context, pac, KRB5_PAC_FULL_CHECKSUM, privsvr,
|
||||
+ KRB5_KEYUSAGE_APP_DATA_CKSUM, ©);
|
||||
+ if (ret)
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
|
||||
-static krb5_error_code
|
||||
-verify_kdc_checksum(krb5_context context, const krb5_pac pac,
|
||||
- const krb5_keyblock *privsvr)
|
||||
-{
|
||||
- krb5_error_code ret;
|
||||
- krb5_data server_checksum;
|
||||
+ if (privsvr != NULL) {
|
||||
+ /* Verify the privsvr checksum over the server checksum. */
|
||||
+ ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_SERVER_CHECKSUM,
|
||||
+ &server_checksum);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ if (server_checksum.length < PAC_SIGNATURE_DATA_LENGTH)
|
||||
+ return KRB5_BAD_MSIZE;
|
||||
+ server_checksum.data += PAC_SIGNATURE_DATA_LENGTH;
|
||||
+ server_checksum.length -= PAC_SIGNATURE_DATA_LENGTH;
|
||||
|
||||
- ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_SERVER_CHECKSUM,
|
||||
- &server_checksum);
|
||||
- if (ret)
|
||||
- return ret;
|
||||
- if (server_checksum.length < PAC_SIGNATURE_DATA_LENGTH)
|
||||
- return KRB5_BAD_MSIZE;
|
||||
- server_checksum.data += PAC_SIGNATURE_DATA_LENGTH;
|
||||
- server_checksum.length -= PAC_SIGNATURE_DATA_LENGTH;
|
||||
+ ret = verify_checksum(context, pac, KRB5_PAC_PRIVSVR_CHECKSUM, privsvr,
|
||||
+ KRB5_KEYUSAGE_APP_DATA_CKSUM, &server_checksum);
|
||||
+ if (ret)
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
+ pac->verified = TRUE;
|
||||
|
||||
- return verify_checksum(context, pac, KRB5_PAC_PRIVSVR_CHECKSUM, privsvr,
|
||||
- KRB5_KEYUSAGE_APP_DATA_CKSUM, &server_checksum);
|
||||
+cleanup:
|
||||
+ free(copy.data);
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
/* Per MS-PAC 2.8.3, tickets encrypted to TGS and password change principals
|
||||
@@ -638,6 +653,7 @@ krb5_kdc_verify_ticket(krb5_context context, const krb5_enc_tkt_part *enc_tkt,
|
||||
krb5_authdata **authdata, *orig, **ifrel = NULL, **recoded_ifrel = NULL;
|
||||
uint8_t z = 0;
|
||||
krb5_authdata zpac = { KV5M_AUTHDATA, KRB5_AUTHDATA_WIN2K_PAC, 1, &z };
|
||||
+ krb5_boolean is_service_tkt;
|
||||
size_t i, j;
|
||||
|
||||
*pac_out = NULL;
|
||||
@@ -679,7 +695,8 @@ krb5_kdc_verify_ticket(krb5_context context, const krb5_enc_tkt_part *enc_tkt,
|
||||
if (ret)
|
||||
goto cleanup;
|
||||
|
||||
- if (privsvr != NULL && k5_pac_should_have_ticket_signature(server_princ)) {
|
||||
+ is_service_tkt = k5_pac_should_have_ticket_signature(server_princ);
|
||||
+ if (privsvr != NULL && is_service_tkt) {
|
||||
/* To check the PAC ticket signatures, re-encode the ticket with the
|
||||
* PAC contents replaced by a single zero. */
|
||||
orig = ifrel[j];
|
||||
@@ -703,8 +720,9 @@ krb5_kdc_verify_ticket(krb5_context context, const krb5_enc_tkt_part *enc_tkt,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
- ret = krb5_pac_verify_ext(context, pac, enc_tkt->times.authtime, NULL,
|
||||
- server, privsvr, FALSE);
|
||||
+ ret = verify_pac_checksums(context, pac, is_service_tkt, server, privsvr);
|
||||
+ if (ret)
|
||||
+ goto cleanup;
|
||||
|
||||
*pac_out = pac;
|
||||
pac = NULL;
|
||||
@@ -740,14 +758,8 @@ krb5_pac_verify_ext(krb5_context context,
|
||||
{
|
||||
krb5_error_code ret;
|
||||
|
||||
- if (server != NULL) {
|
||||
- ret = verify_server_checksum(context, pac, server);
|
||||
- if (ret != 0)
|
||||
- return ret;
|
||||
- }
|
||||
-
|
||||
- if (privsvr != NULL) {
|
||||
- ret = verify_kdc_checksum(context, pac, privsvr);
|
||||
+ if (server != NULL || privsvr != NULL) {
|
||||
+ ret = verify_pac_checksums(context, pac, FALSE, server, privsvr);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
@@ -759,8 +771,6 @@ krb5_pac_verify_ext(krb5_context context,
|
||||
return ret;
|
||||
}
|
||||
|
||||
- pac->verified = TRUE;
|
||||
-
|
||||
return 0;
|
||||
}
|
||||
|
||||
diff --git a/src/lib/krb5/krb/pac_sign.c b/src/lib/krb5/krb/pac_sign.c
|
||||
index 0f9581abbb..8ea61ac17b 100644
|
||||
--- a/src/lib/krb5/krb/pac_sign.c
|
||||
+++ b/src/lib/krb5/krb/pac_sign.c
|
||||
@@ -187,26 +187,41 @@ k5_pac_encode_header(krb5_context context, krb5_pac pac)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-krb5_error_code KRB5_CALLCONV
|
||||
-krb5_pac_sign(krb5_context context, krb5_pac pac, krb5_timestamp authtime,
|
||||
- krb5_const_principal principal, const krb5_keyblock *server_key,
|
||||
- const krb5_keyblock *privsvr_key, krb5_data *data)
|
||||
+/* Find the buffer of type buftype in pac and write within it a checksum of
|
||||
+ * type cksumtype over data. Set *cksum_out to the checksum. */
|
||||
+static krb5_error_code
|
||||
+compute_pac_checksum(krb5_context context, krb5_pac pac, uint32_t buftype,
|
||||
+ const krb5_keyblock *key, krb5_cksumtype cksumtype,
|
||||
+ const krb5_data *data, krb5_data *cksum_out)
|
||||
{
|
||||
- return krb5_pac_sign_ext(context, pac, authtime, principal, server_key,
|
||||
- privsvr_key, FALSE, data);
|
||||
+ krb5_error_code ret;
|
||||
+ krb5_data buf;
|
||||
+ krb5_crypto_iov iov[2];
|
||||
+
|
||||
+ ret = k5_pac_locate_buffer(context, pac, buftype, &buf);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ assert(buf.length > PAC_SIGNATURE_DATA_LENGTH);
|
||||
+ *cksum_out = make_data(buf.data + PAC_SIGNATURE_DATA_LENGTH,
|
||||
+ buf.length - PAC_SIGNATURE_DATA_LENGTH);
|
||||
+ iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
|
||||
+ iov[0].data = *data;
|
||||
+ iov[1].flags = KRB5_CRYPTO_TYPE_CHECKSUM;
|
||||
+ iov[1].data = *cksum_out;
|
||||
+ return krb5_c_make_checksum_iov(context, cksumtype, key,
|
||||
+ KRB5_KEYUSAGE_APP_DATA_CKSUM, iov, 2);
|
||||
}
|
||||
|
||||
-krb5_error_code KRB5_CALLCONV
|
||||
-krb5_pac_sign_ext(krb5_context context, krb5_pac pac, krb5_timestamp authtime,
|
||||
- krb5_const_principal principal,
|
||||
- const krb5_keyblock *server_key,
|
||||
- const krb5_keyblock *privsvr_key, krb5_boolean with_realm,
|
||||
- krb5_data *data)
|
||||
+static krb5_error_code
|
||||
+sign_pac(krb5_context context, krb5_pac pac, krb5_timestamp authtime,
|
||||
+ krb5_const_principal principal, const krb5_keyblock *server_key,
|
||||
+ const krb5_keyblock *privsvr_key, krb5_boolean with_realm,
|
||||
+ krb5_boolean is_service_tkt, krb5_data *data)
|
||||
{
|
||||
krb5_error_code ret;
|
||||
- krb5_data server_cksum, privsvr_cksum;
|
||||
+ krb5_data full_cksum, server_cksum, privsvr_cksum;
|
||||
krb5_cksumtype server_cksumtype, privsvr_cksumtype;
|
||||
- krb5_crypto_iov iov[2];
|
||||
|
||||
data->length = 0;
|
||||
data->data = NULL;
|
||||
@@ -214,67 +229,53 @@ krb5_pac_sign_ext(krb5_context context, krb5_pac pac, krb5_timestamp authtime,
|
||||
if (principal != NULL) {
|
||||
ret = k5_insert_client_info(context, pac, authtime, principal,
|
||||
with_realm);
|
||||
- if (ret != 0)
|
||||
+ if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
- /* Create zeroed buffers for both checksums */
|
||||
+ /* Create zeroed buffers for all checksums. */
|
||||
ret = k5_insert_checksum(context, pac, KRB5_PAC_SERVER_CHECKSUM,
|
||||
server_key, &server_cksumtype);
|
||||
- if (ret != 0)
|
||||
+ if (ret)
|
||||
return ret;
|
||||
-
|
||||
ret = k5_insert_checksum(context, pac, KRB5_PAC_PRIVSVR_CHECKSUM,
|
||||
privsvr_key, &privsvr_cksumtype);
|
||||
- if (ret != 0)
|
||||
+ if (ret)
|
||||
return ret;
|
||||
+ if (is_service_tkt) {
|
||||
+ ret = k5_insert_checksum(context, pac, KRB5_PAC_FULL_CHECKSUM,
|
||||
+ privsvr_key, &privsvr_cksumtype);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
|
||||
- /* Now, encode the PAC header so that the checksums will include it */
|
||||
+ /* Encode the PAC header so that the checksums will include it. */
|
||||
ret = k5_pac_encode_header(context, pac);
|
||||
- if (ret != 0)
|
||||
- return ret;
|
||||
-
|
||||
- /* Generate the server checksum over the entire PAC */
|
||||
- ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_SERVER_CHECKSUM,
|
||||
- &server_cksum);
|
||||
- if (ret != 0)
|
||||
+ if (ret)
|
||||
return ret;
|
||||
|
||||
- assert(server_cksum.length > PAC_SIGNATURE_DATA_LENGTH);
|
||||
-
|
||||
- iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
|
||||
- iov[0].data = pac->data;
|
||||
-
|
||||
- iov[1].flags = KRB5_CRYPTO_TYPE_CHECKSUM;
|
||||
- iov[1].data.data = server_cksum.data + PAC_SIGNATURE_DATA_LENGTH;
|
||||
- iov[1].data.length = server_cksum.length - PAC_SIGNATURE_DATA_LENGTH;
|
||||
+ if (is_service_tkt) {
|
||||
+ /* Generate a full KDC checksum over the whole PAC. */
|
||||
+ ret = compute_pac_checksum(context, pac, KRB5_PAC_FULL_CHECKSUM,
|
||||
+ privsvr_key, privsvr_cksumtype,
|
||||
+ &pac->data, &full_cksum);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
|
||||
- ret = krb5_c_make_checksum_iov(context, server_cksumtype,
|
||||
- server_key, KRB5_KEYUSAGE_APP_DATA_CKSUM,
|
||||
- iov, sizeof(iov)/sizeof(iov[0]));
|
||||
- if (ret != 0)
|
||||
+ /* Generate the server checksum over the whole PAC, including the full KDC
|
||||
+ * checksum if we added one. */
|
||||
+ ret = compute_pac_checksum(context, pac, KRB5_PAC_SERVER_CHECKSUM,
|
||||
+ server_key, server_cksumtype, &pac->data,
|
||||
+ &server_cksum);
|
||||
+ if (ret)
|
||||
return ret;
|
||||
|
||||
- /* Generate the privsvr checksum over the server checksum buffer */
|
||||
- ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_PRIVSVR_CHECKSUM,
|
||||
+ /* Generate the privsvr checksum over the server checksum buffer. */
|
||||
+ ret = compute_pac_checksum(context, pac, KRB5_PAC_PRIVSVR_CHECKSUM,
|
||||
+ privsvr_key, privsvr_cksumtype, &server_cksum,
|
||||
&privsvr_cksum);
|
||||
- if (ret != 0)
|
||||
- return ret;
|
||||
-
|
||||
- assert(privsvr_cksum.length > PAC_SIGNATURE_DATA_LENGTH);
|
||||
-
|
||||
- iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
|
||||
- iov[0].data.data = server_cksum.data + PAC_SIGNATURE_DATA_LENGTH;
|
||||
- iov[0].data.length = server_cksum.length - PAC_SIGNATURE_DATA_LENGTH;
|
||||
-
|
||||
- iov[1].flags = KRB5_CRYPTO_TYPE_CHECKSUM;
|
||||
- iov[1].data.data = privsvr_cksum.data + PAC_SIGNATURE_DATA_LENGTH;
|
||||
- iov[1].data.length = privsvr_cksum.length - PAC_SIGNATURE_DATA_LENGTH;
|
||||
-
|
||||
- ret = krb5_c_make_checksum_iov(context, privsvr_cksumtype,
|
||||
- privsvr_key, KRB5_KEYUSAGE_APP_DATA_CKSUM,
|
||||
- iov, sizeof(iov)/sizeof(iov[0]));
|
||||
- if (ret != 0)
|
||||
+ if (ret)
|
||||
return ret;
|
||||
|
||||
data->data = k5memdup(pac->data.data, pac->data.length, &ret);
|
||||
@@ -288,6 +289,26 @@ krb5_pac_sign_ext(krb5_context context, krb5_pac pac, krb5_timestamp authtime,
|
||||
return 0;
|
||||
}
|
||||
|
||||
+krb5_error_code KRB5_CALLCONV
|
||||
+krb5_pac_sign(krb5_context context, krb5_pac pac, krb5_timestamp authtime,
|
||||
+ krb5_const_principal principal, const krb5_keyblock *server_key,
|
||||
+ const krb5_keyblock *privsvr_key, krb5_data *data)
|
||||
+{
|
||||
+ return sign_pac(context, pac, authtime, principal, server_key,
|
||||
+ privsvr_key, FALSE, FALSE, data);
|
||||
+}
|
||||
+
|
||||
+krb5_error_code KRB5_CALLCONV
|
||||
+krb5_pac_sign_ext(krb5_context context, krb5_pac pac, krb5_timestamp authtime,
|
||||
+ krb5_const_principal principal,
|
||||
+ const krb5_keyblock *server_key,
|
||||
+ const krb5_keyblock *privsvr_key, krb5_boolean with_realm,
|
||||
+ krb5_data *data)
|
||||
+{
|
||||
+ return sign_pac(context, pac, authtime, principal, server_key, privsvr_key,
|
||||
+ with_realm, FALSE, data);
|
||||
+}
|
||||
+
|
||||
/* Add a signature over der_enc_tkt in privsvr to pac. der_enc_tkt should be
|
||||
* encoded with a dummy PAC authdata element containing a single zero byte. */
|
||||
static krb5_error_code
|
||||
@@ -359,6 +380,7 @@ krb5_kdc_sign_ticket(krb5_context context, krb5_enc_tkt_part *enc_tkt,
|
||||
krb5_error_code ret;
|
||||
krb5_data *der_enc_tkt = NULL, pac_data = empty_data();
|
||||
krb5_authdata **list, *pac_ad;
|
||||
+ krb5_boolean is_service_tkt;
|
||||
size_t count;
|
||||
|
||||
/* Reallocate space for another authdata element in enc_tkt. */
|
||||
@@ -377,7 +399,8 @@ krb5_kdc_sign_ticket(krb5_context context, krb5_enc_tkt_part *enc_tkt,
|
||||
memmove(list + 1, list, (count + 1) * sizeof(*list));
|
||||
list[0] = pac_ad;
|
||||
|
||||
- if (k5_pac_should_have_ticket_signature(server_princ)) {
|
||||
+ is_service_tkt = k5_pac_should_have_ticket_signature(server_princ);
|
||||
+ if (is_service_tkt) {
|
||||
ret = encode_krb5_enc_tkt_part(enc_tkt, &der_enc_tkt);
|
||||
if (ret)
|
||||
goto cleanup;
|
||||
@@ -388,9 +411,8 @@ krb5_kdc_sign_ticket(krb5_context context, krb5_enc_tkt_part *enc_tkt,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
- ret = krb5_pac_sign_ext(context, pac, enc_tkt->times.authtime,
|
||||
- client_princ, server, privsvr, with_realm,
|
||||
- &pac_data);
|
||||
+ ret = sign_pac(context, pac, enc_tkt->times.authtime, client_princ, server,
|
||||
+ privsvr, with_realm, is_service_tkt, &pac_data);
|
||||
if (ret)
|
||||
goto cleanup;
|
||||
|
||||
diff --git a/src/lib/krb5/krb/t_pac.c b/src/lib/krb5/krb/t_pac.c
|
||||
index 173bde7bab..81f1642ab0 100644
|
||||
--- a/src/lib/krb5/krb/t_pac.c
|
||||
+++ b/src/lib/krb5/krb/t_pac.c
|
||||
@@ -607,78 +607,102 @@ check_pac(krb5_context context, int index, const unsigned char *pdata,
|
||||
|
||||
static const krb5_keyblock ticket_sig_krbtgt_key = {
|
||||
0, ENCTYPE_AES256_CTS_HMAC_SHA1_96,
|
||||
- 32, U("\x7a\x58\x98\xd2\xaf\xa6\xaf\xc0\x6a\xce\x06\x04\x4b\xc2\x70\x84"
|
||||
- "\x9b\x8e\x0a\x6c\x4c\x07\xdc\x6f\xbb\x48\x43\xe1\xd2\xaa\x97\xf7")
|
||||
+ 32, U("\x03\x73\x81\xEC\x43\x96\x7B\xC2\xAC\x3D\xF5\x2A\xAE\x95\xA6\x8E"
|
||||
+ "\xBE\x24\x58\xDB\xCE\x52\x28\x20\xAF\x5E\xB7\x04\xA2\x22\x71\x4F")
|
||||
};
|
||||
|
||||
static const krb5_keyblock ticket_sig_server_key = {
|
||||
- 0, ENCTYPE_ARCFOUR_HMAC,
|
||||
- 16, U("\xed\x23\x11\x20\x7a\x21\x44\x20\xbf\xc0\x8d\x36\xf7\xf6\xb2\x3e")
|
||||
+ 0, ENCTYPE_AES256_CTS_HMAC_SHA1_96,
|
||||
+ 32, U("\x11\x4A\x84\xE3\x14\x8F\xAA\xB1\xFA\x7B\x53\x51\xB2\x8A\xC2\xF1"
|
||||
+ "\xFD\x19\x6D\x61\xE0\xF3\xF2\x3E\x1F\xDB\xD3\xC1\x79\x7D\xC1\xEE")
|
||||
};
|
||||
|
||||
+/* A ticket issued by an Active Directory KDC (Windows Server 2022), containing
|
||||
+ * a PAC with a full checksum. */
|
||||
static const krb5_data ticket_data = {
|
||||
- .length = 972, .data =
|
||||
- "\x61\x82\x03\xC8\x30\x82\x03\xC4\xA0\x03\x02\x01\x05\xA1\x0A\x1B"
|
||||
- "\x08\x43\x44\x4F\x4D\x2E\x43\x4F\x4D\xA2\x0F\x30\x0D\xA0\x03\x02"
|
||||
- "\x01\x01\xA1\x06\x30\x04\x1B\x02\x73\x31\xA3\x82\x03\x9E\x30\x82"
|
||||
- "\x03\x9A\xA0\x03\x02\x01\x17\xA1\x03\x02\x01\x03\xA2\x82\x03\x8C"
|
||||
- "\x04\x82\x03\x88\x44\x31\x61\x20\x17\xC9\xFE\xBC\xAC\x46\xB5\x77"
|
||||
- "\xE9\x68\x04\x4C\x9B\x31\x91\x0C\xC1\xD4\xDD\xEF\xC7\x34\x20\x08"
|
||||
- "\x90\x91\xE8\x79\xE0\xB5\x03\x26\xA4\x65\xDE\xEC\x47\x03\x2A\x8F"
|
||||
- "\x61\xE7\x4D\x38\x5A\x42\x95\x5A\xF9\x2F\x41\x2C\x2A\x6E\x60\xA1"
|
||||
- "\xEB\x51\xB3\xBD\x4C\x00\x41\x2A\x44\x76\x08\x37\x1A\x51\xFD\x65"
|
||||
- "\x67\x7E\xBF\x3D\x90\x86\xE3\x9A\x54\x6B\x67\xA8\x08\x7A\x73\xCC"
|
||||
- "\xC3\xB7\x4B\xD5\x5C\x3A\x14\x6C\xC1\x5F\x54\x4B\x92\x55\xB4\xB7"
|
||||
- "\x92\x23\x3F\x53\x89\x47\x8E\x1F\x8B\xB9\xDB\x3B\x93\xE8\x70\xE4"
|
||||
- "\x24\xB8\x9D\xF0\x0E\x35\x28\xF8\x7A\x27\x5D\xF7\x25\x97\x9C\xF5"
|
||||
- "\x9F\x9F\x64\x04\xF2\xA3\xAB\x11\x15\xB6\xDA\x18\xD6\x46\xD5\xE6"
|
||||
- "\xB8\x08\xDE\x0A\x62\xFD\xF8\xAA\x52\x90\xD9\x67\x29\xB2\xCD\x06"
|
||||
- "\xB6\xB0\x50\x2B\x3F\x0F\xA3\xA5\xBF\xAA\x6E\x40\x03\xD6\x5F\x02"
|
||||
- "\xBC\xD8\x18\x47\x97\x09\xD7\xE4\x96\x3B\xCB\xEB\x92\x2C\x3C\x49"
|
||||
- "\xFF\x1F\x71\xE0\x52\x94\x0F\x8B\x9F\xB8\x2A\xBB\x9C\xE2\xA3\xDD"
|
||||
- "\x38\x89\xE2\xB1\x0B\x9E\x1F\x7A\xB3\xE3\xD2\xB0\x94\xDC\x87\xBE"
|
||||
- "\x37\xA6\xD3\xB3\x29\x35\x9A\x72\xC3\x7A\xF1\xA9\xE6\xC5\xD1\x26"
|
||||
- "\x83\x65\x44\x17\xBA\x55\xA8\x5E\x94\x26\xED\xE9\x8A\x93\x11\x5D"
|
||||
- "\x7E\x20\x1B\x9C\x15\x9E\x13\x37\x03\x4D\xDD\x99\x51\xD8\x66\x29"
|
||||
- "\x6A\xB9\xFB\x49\xFE\x52\x78\xDA\x86\x85\xA9\xA3\xB9\xEF\xEC\xAD"
|
||||
- "\x35\xA6\x8D\xAC\x0F\x75\x22\xBB\x0B\x49\x1C\x13\x52\x40\xC9\x52"
|
||||
- "\x69\x09\x54\xD1\x0F\x94\x3F\x22\x48\x67\xB0\x96\x28\xAA\xE6\x28"
|
||||
- "\xD9\x0C\x08\xEF\x51\xED\x15\x5E\xA2\x53\x59\xA5\x03\xB4\x06\x20"
|
||||
- "\x3D\xCC\xB4\xC5\xF8\x8C\x73\x67\xA3\x21\x3D\x19\xCD\xD4\x12\x28"
|
||||
- "\xD2\x93\xDE\x0D\xF0\x71\x10\x50\xD6\x33\x35\x04\x11\x64\x43\x39"
|
||||
- "\xC3\xDF\x96\xE3\x66\xE3\x85\xCA\xE7\x67\x14\x3A\xF0\x43\xAA\xBB"
|
||||
- "\xD4\x1D\xB5\x24\xB5\x74\x90\x25\xA7\x87\x7E\xDB\xD3\x83\x8A\x3A"
|
||||
- "\x69\xA8\x2D\xAF\xB7\xB8\xF3\xDC\x13\xAF\x45\x61\x3F\x59\x39\x7E"
|
||||
- "\x69\xDE\x0C\x04\xF1\x10\x6B\xB4\x56\xFA\x21\x9F\x72\x2B\x60\x86"
|
||||
- "\xE3\x23\x0E\xC4\x51\xF6\xBE\xD8\xE1\x5F\xEE\x73\x4C\x17\x4C\x2C"
|
||||
- "\x1B\xFB\x9F\x1F\x7A\x3B\x07\x5B\x8E\xF1\x01\xAC\xD6\x30\x94\x8A"
|
||||
- "\x5D\x22\x6F\x08\xCE\xED\x5E\xB6\xDB\x86\x8C\x87\xEB\x8D\x91\xFF"
|
||||
- "\x0A\x86\x30\xBD\xC0\xF8\x25\xE7\xAE\x24\x35\xF2\xFC\xE5\xFD\x1B"
|
||||
- "\xB0\x05\x4A\xA3\xE5\xEB\x2E\x05\xAD\x99\x67\x49\x87\xE6\xB3\x87"
|
||||
- "\x82\xA4\x59\xA7\x6E\xDD\xF2\xB6\x66\xE8\xF7\x70\xF5\xBD\xC9\x0E"
|
||||
- "\xFA\x9C\x79\x84\xD4\x9B\x05\x0E\xBB\xF5\xDB\xEF\xFC\xCC\x26\xF2"
|
||||
- "\x93\xCF\xD2\x04\x3C\xA9\x2C\x65\x42\x97\x86\xD8\x38\x0A\x1E\xF6"
|
||||
- "\xD6\xCA\x30\xB5\x1A\xEC\xFB\xBA\x3B\x84\x57\xB0\xFD\xFB\xE6\xBC"
|
||||
- "\xF2\x76\xF6\x4C\xBB\xAB\xB1\x31\xA1\x27\x7C\xE6\xE6\x81\xB6\xCE"
|
||||
- "\x84\x86\x40\xB6\x40\x33\xC4\xF8\xB4\x15\xCF\xAA\xA5\x51\x78\xB9"
|
||||
- "\x8B\x50\x25\xB2\x88\x86\x96\x72\x8C\x71\x4D\xB5\x3A\x94\x86\x77"
|
||||
- "\x0E\x95\x9B\x16\x93\xEF\x3A\x11\x79\xBA\x83\xF7\x74\xD3\x8D\xBA"
|
||||
- "\x15\xE1\x2C\x04\x57\xA8\x92\x1E\x9D\x00\x8E\x20\xFD\x30\x70\xE7"
|
||||
- "\xF5\x65\x2F\x19\x0C\x94\xBA\x03\x71\x12\x96\xCD\xC8\xB4\x96\xDB"
|
||||
- "\xCE\x19\xC2\xDF\x3C\xC2\xF6\x3D\x53\xED\x98\xA5\x41\x72\x2A\x22"
|
||||
- "\x7B\xF3\x2B\x17\x6C\xE1\x39\x7D\xAE\x9B\x11\xF9\xC1\xA6\x9E\x9F"
|
||||
- "\x89\x3C\x12\xAA\x94\x74\xA7\x4F\x70\xE8\xB9\xDE\x04\xF0\x9D\x39"
|
||||
- "\x24\x2D\x92\xE8\x46\x2D\x2E\xF0\x40\x66\x1A\xD9\x27\xF9\x98\xF1"
|
||||
- "\x81\x1D\x70\x62\x63\x30\x6D\xCD\x84\x04\x5F\xFA\x83\xD3\xEC\x8D"
|
||||
- "\x86\xFB\x40\x61\xC1\x8A\x45\xFF\x7B\xD9\xD4\x18\x61\x7F\x51\xE3"
|
||||
- "\xFC\x1E\x18\xF0\xAF\xC6\x18\x2C\xE1\x6D\x5D\xF9\x62\xFC\x20\xA3"
|
||||
- "\xB2\x8A\x5F\xE5\xBB\x29\x0F\x99\x63\x07\x88\x38\x3A\x3B\x73\x2A"
|
||||
- "\x6D\xDA\x3D\xA8\x0D\x8F\x56\x41\x89\x82\xE5\xB8\x61\x00\x64\x7D"
|
||||
- "\x17\x0C\xCE\x03\x55\x8F\xF4\x5B\x0D\x50\xF2\xEB\x05\x67\xBE\xDB"
|
||||
- "\x7B\x75\xC5\xEA\xA1\xAB\x1D\xB0\x3C\x6D\x42\x08\x0B\x9A\x45\x20"
|
||||
- "\xA8\x8F\xE5\x67\x47\x30\xDE\x93\x5F\x43\x05\xEB\xA8\x2D\x80\xF5"
|
||||
- "\x1A\xB8\x4A\x4E\x42\x2D\x0B\x7A\xDC\x46\x20\x2D\x13\x17\xDD\x4B"
|
||||
- "\x94\x96\xAA\x1F\x06\x0C\x1F\x62\x07\x9C\x40\xA1"
|
||||
+ .length = 1307, .data =
|
||||
+ "\x61\x82\x05\x17\x30\x82\x05\x13\xA0\x03\x02\x01\x05\xA1\x0F\x1B"
|
||||
+ "\x0D\x57\x32\x30\x32\x32\x2D\x4C\x37\x2E\x42\x41\x53\x45\xA2\x2A"
|
||||
+ "\x30\x28\xA0\x03\x02\x01\x01\xA1\x21\x30\x1F\x1B\x04\x63\x69\x66"
|
||||
+ "\x73\x1B\x17\x77\x32\x30\x32\x32\x2D\x31\x31\x38\x2E\x77\x32\x30"
|
||||
+ "\x32\x32\x2D\x6C\x37\x2E\x62\x61\x73\x65\xA3\x82\x04\xCD\x30\x82"
|
||||
+ "\x04\xC9\xA0\x03\x02\x01\x12\xA1\x03\x02\x01\x05\xA2\x82\x04\xBB"
|
||||
+ "\x04\x82\x04\xB7\x44\x5C\x7B\x5A\x3F\x2E\xA3\x50\x34\xDE\xB0\x69"
|
||||
+ "\x23\x2D\x47\x89\x2C\xC0\xA3\xF9\xDD\x70\xAA\xA5\x1E\xFE\x74\xE5"
|
||||
+ "\x19\xA2\x4F\x65\x6C\x9E\x00\xB4\x60\x00\x7C\x0C\x29\x43\x31\x99"
|
||||
+ "\x77\x02\x73\xED\xB9\x40\xF5\xD2\xD1\xC9\x20\x0F\xE3\x38\xF9\xCC"
|
||||
+ "\x5E\x2A\xBD\x1F\x91\x66\x1A\xD8\x2A\x80\x3C\x2C\x00\x3C\x1E\xC9"
|
||||
+ "\x2A\x29\x19\x19\x96\x18\x54\x03\x97\x8F\x1D\x5F\xDB\xE9\x66\x68"
|
||||
+ "\xCD\xB1\xD5\x00\x35\x69\x49\x45\xF1\x6A\x78\x7B\x37\x71\x87\x14"
|
||||
+ "\x1C\x98\x4D\x69\xCB\x1B\xD8\xF5\xA3\xD8\x53\x4A\x75\x76\x62\xBA"
|
||||
+ "\x6C\x3F\xEA\x8B\x97\x21\xCA\x8A\x46\x4B\x38\xDA\x09\x9F\x5A\xC8"
|
||||
+ "\x38\xFF\x34\x97\x5B\xA2\xE5\xBA\xC9\x87\x17\xD8\x08\x05\x7A\x83"
|
||||
+ "\x04\xD6\x02\x8E\x9B\x18\xB6\x40\x1A\xF7\x47\x25\x24\x3E\x37\x1E"
|
||||
+ "\xF6\xC1\x3A\x1F\xCA\xB3\x43\x5A\xAE\x94\x83\x31\xAF\xFB\xEE\xED"
|
||||
+ "\x46\x71\xEF\xE2\x37\x37\x15\xFE\x1B\x0B\x9E\xF8\x3E\x0C\x43\x96"
|
||||
+ "\xB6\x0A\x04\x78\xF8\x5E\xAA\x33\x1F\xE2\x07\x5A\x8D\xC4\x4E\x32"
|
||||
+ "\x6D\xD6\xA0\xC5\xEA\x3D\x12\x59\xD4\x41\x40\x4E\xA1\xD8\xBE\xED"
|
||||
+ "\x17\xCB\x68\xCC\x59\xCB\x53\xB2\x0E\x58\x8A\xA9\x33\x7F\x6F\x2B"
|
||||
+ "\x37\x89\x08\x44\xBA\xC7\x67\x17\xBB\x91\xF7\xC3\x0F\x00\xF8\xAA"
|
||||
+ "\xA1\x33\xA6\x08\x47\xCA\xFA\xE8\x49\x27\x45\x46\xF1\xC1\xC3\x5F"
|
||||
+ "\xE2\x45\x0A\x7D\x64\x52\x8C\x2E\xE1\xDE\xFF\xB2\x64\xEC\x69\x98"
|
||||
+ "\x15\xDF\x9E\xB1\xEB\xD6\x9D\x08\x06\x4E\x73\xC1\x0B\x71\x21\x05"
|
||||
+ "\x9E\xBC\xA2\x17\xCF\xB3\x70\xF4\xEF\xB8\x69\xA9\x94\x27\xFD\x5E"
|
||||
+ "\x72\xB1\x2D\xD2\x20\x1B\x57\x80\xAB\x38\x97\xCF\x22\x68\x4F\xB8"
|
||||
+ "\xB7\x17\x53\x25\x67\x0B\xED\xD1\x58\x20\x0D\x45\xF9\x09\xFA\xE7"
|
||||
+ "\x61\x3E\xDB\xC2\x59\x7B\x3A\x3B\x59\x81\x51\xAA\xA4\x81\xF4\x96"
|
||||
+ "\x3B\xE1\x6F\x6F\xF4\x8E\x68\x9E\xBA\x1E\x0F\xF2\x44\x68\x11\xFC"
|
||||
+ "\x2B\x5F\xBE\xF2\xEA\x07\x80\xB9\xCA\x9E\x41\xBD\x2F\x81\xF5\x11"
|
||||
+ "\x2A\x12\xF3\x4F\xD6\x12\x16\x0F\x21\x90\xF1\xD3\x1E\xF1\xA4\x94"
|
||||
+ "\x46\xEA\x30\xF3\x84\x06\xC1\xA4\x51\xFC\x43\x35\xBD\xEF\x4D\x89"
|
||||
+ "\x1D\xA5\x44\xB2\x69\xC4\x0F\xBF\x86\x01\x08\x44\x77\xD5\xB4\xB7"
|
||||
+ "\x5C\x3F\xA7\xD4\x2F\x39\x73\x85\x88\xEE\xB1\x64\x1D\x80\x6C\xEE"
|
||||
+ "\x6E\x31\x90\x92\x0D\xA1\xB7\xC4\x5C\xCC\xEE\x91\xC8\xCB\x11\x2D"
|
||||
+ "\x4A\x1A\x7D\x43\x8F\xEB\x60\x09\xED\x1B\x07\x58\xBE\xBC\xBD\x29"
|
||||
+ "\xF3\xB3\xA3\x4F\xC5\x8A\x30\x33\xB9\xA9\x9F\x43\x08\x27\x15\xC4"
|
||||
+ "\x9C\x5D\x8E\xBD\x5C\x05\xC6\x05\x9C\x87\x60\x08\x1E\xE2\x52\xB8"
|
||||
+ "\x45\x8D\x28\xB6\x2C\x15\x46\x74\x9F\x0E\xAA\x6B\x70\x3A\x2A\x55"
|
||||
+ "\x45\x26\xB2\x58\x4D\x35\xA6\xF1\x96\xBE\x60\xB2\x71\x7B\xF8\x54"
|
||||
+ "\xB9\x90\x21\x8E\xB9\x0F\x35\x98\x5E\x88\xEB\x1A\x53\xB4\x59\x7F"
|
||||
+ "\xAF\x69\x1C\x61\x67\xF4\xF6\xBD\xAC\x24\xCD\xB7\xA9\x67\xE8\xA1"
|
||||
+ "\x83\x85\x5F\x11\x74\x1F\xF7\x4C\x78\x36\xEF\x50\x74\x88\x58\x4B"
|
||||
+ "\x1A\x9F\x84\x9A\x9A\x05\x92\xEC\x1D\xD5\xF3\xC4\x95\x51\x28\xE2"
|
||||
+ "\x3F\x32\x87\xB2\xFD\x21\x27\x66\xE4\x6B\x85\x2F\xDC\x7B\xC0\x22"
|
||||
+ "\xEB\x7A\x94\x20\x5A\x7B\xD3\x7A\xB9\x5B\xF8\x1A\x5A\x84\x4E\xA1"
|
||||
+ "\x73\x41\x53\xD2\x60\xF7\x7C\xEE\x68\x59\x85\x80\xFC\x3D\x70\x4B"
|
||||
+ "\x04\x32\xE7\xF2\xFD\xBD\xB3\xD9\x21\xE2\x37\x56\xA2\x16\xCC\xDE"
|
||||
+ "\x8A\xD3\xBC\x71\xEF\x58\x19\x0E\x45\x8A\x5B\x53\xD6\x77\x30\x6A"
|
||||
+ "\xA7\xF8\x68\x06\x4E\x07\xCA\xCE\x30\xD7\x35\xAB\x1A\xC7\x18\xD4"
|
||||
+ "\xC6\x2F\x1A\xFF\xE9\x7A\x94\x0B\x76\x5E\x7E\x29\x0C\xE6\xD3\x3B"
|
||||
+ "\x5B\x44\x96\xA8\xF1\x29\x23\x95\xD9\x79\xB3\x39\xFC\x76\xED\xE1"
|
||||
+ "\x1E\x67\x4E\xF7\xE8\x7B\x7A\x12\x9E\xD8\x4B\x35\x09\x0A\xF2\xC1"
|
||||
+ "\x63\x5B\xEE\xFD\x2A\xC2\xA6\x66\x30\x3C\x1F\x95\xAF\x65\x22\x95"
|
||||
+ "\x14\x1D\xF5\xD5\xDC\x38\x79\x35\x1C\xCD\x24\x47\xE0\xFD\x08\xC8"
|
||||
+ "\xF4\x15\x55\x9F\xD9\xC7\xAC\x3F\x67\xB3\x4F\xEB\x26\x7C\x8E\xD6"
|
||||
+ "\x74\xB3\x0A\xCD\xE7\xFA\xBE\x7E\xA3\x3E\xEC\x61\x50\x77\x52\x56"
|
||||
+ "\xCF\x90\x5D\x48\xFB\xD4\x2C\x6C\x61\x8B\xDD\x2B\xF5\x92\x1F\x30"
|
||||
+ "\xBF\x3F\x80\x0D\x31\xDB\xB2\x0B\x7D\x84\xE3\xA6\x42\x7F\x00\x38"
|
||||
+ "\x44\x02\xC5\xB8\xD9\x58\x29\x9D\x68\x5C\x32\x8B\x76\xAE\xED\x15"
|
||||
+ "\xF9\x7C\xAE\x7B\xB6\x8E\xD6\x54\x24\xFF\xFA\x87\x05\xEF\x15\x08"
|
||||
+ "\x5E\x4B\x21\xA2\x2F\x49\xE7\x0F\xC3\xD0\xB9\x49\x22\xEF\xD5\xCA"
|
||||
+ "\xB2\x11\xF2\x17\xB6\x77\x24\x68\x76\xB2\x07\xF8\x0A\x73\xDD\x65"
|
||||
+ "\x9C\x75\x64\xF7\xA1\xC6\x23\x08\x84\x72\x3E\x54\x2E\xEB\x9B\x40"
|
||||
+ "\xA6\x83\x87\xEB\xB5\x00\x40\x4F\xE1\x72\x2A\x59\x3A\x06\x60\x29"
|
||||
+ "\x7E\x25\x2F\xD8\x80\x40\x8C\x59\xCA\xCF\x8E\x44\xE4\x2D\x84\x7E"
|
||||
+ "\xCB\xFD\x1E\x3B\xD5\xFF\x9A\xB9\x66\x93\x6D\x5E\xC8\xB7\x13\x26"
|
||||
+ "\xD6\x38\x1B\x2B\xE1\x87\x96\x05\xD5\xF3\xAB\x68\xF7\x12\x62\x2C"
|
||||
+ "\x58\xC1\xC9\x85\x3C\x72\xF1\x26\xEE\xC0\x09\x5F\x1D\x4B\xAC\x01"
|
||||
+ "\x41\xC8\x12\xF8\xF3\x93\x43\x41\xFF\xEC\x0B\x80\xE2\xEE\x20\x85"
|
||||
+ "\x25\xCD\x6C\x30\x8C\x0D\x24\x2E\xBA\x19\xEA\x28\x7F\xCF\xD5\x10"
|
||||
+ "\x5C\xE9\xB2\x9D\x5F\x16\xE4\xC0\xF3\xCC\xD9\x68\x4A\x05\x08\x70"
|
||||
+ "\x17\x26\xC8\x5C\x4A\xBF\x94\x6A\x0E\xD5\xDA\x67\x47\x4B\xAF\x44"
|
||||
+ "\xE3\x94\xAA\x05\xDB\xA2\x49\x74\xFA\x5C\x69\xAB\x44\xB7\xF7\xBA"
|
||||
+ "\xAE\x7A\x23\x87\xEB\x54\x7E\x80\xF1\x5B\x60\xA5\x93\xE5\xD4\x24"
|
||||
+ "\x84\xF7\x0A\x16\x10\xBE\xE9\x4D\xD8\x6B\x15\x40\x5D\x74\xDA\x1B"
|
||||
+ "\xFF\x2E\x4D\x17\x9D\x35\xF7\x0D\xCF\x66\x38\x0D\x8A\xE4\xDD\x6B"
|
||||
+ "\xE1\x0F\x1F\xBD\xFD\x4F\x30\x37\x3F\x96\xB4\x92\x54\xD3\x9A\x7A"
|
||||
+ "\xD1\x5B\x5B\xA9\x54\x16\xE6\x24\xAB\xD4\x23\x39\x7D\xD2\xC7\x09"
|
||||
+ "\xFA\xD4\x86\x55\x4D\x60\xC2\x87\x67\x6B\xE6"
|
||||
};
|
||||
|
||||
static void
|
||||
@@ -686,7 +710,7 @@ test_pac_ticket_signature(krb5_context context)
|
||||
{
|
||||
krb5_error_code ret;
|
||||
krb5_ticket *ticket;
|
||||
- krb5_principal sprinc;
|
||||
+ krb5_principal cprinc, sprinc;
|
||||
krb5_authdata **authdata1, **authdata2;
|
||||
krb5_pac pac, pac2, pac3;
|
||||
uint32_t *list;
|
||||
@@ -701,7 +725,13 @@ test_pac_ticket_signature(krb5_context context)
|
||||
if (ret)
|
||||
err(context, ret, "while decrypting ticket");
|
||||
|
||||
- ret = krb5_parse_name(context, "s1@CDOM.COM", &sprinc);
|
||||
+ ret = krb5_parse_name(context, "administrator@W2022-L7.BASE", &cprinc);
|
||||
+ if (ret)
|
||||
+ err(context, ret, "krb5_parse_name");
|
||||
+
|
||||
+ ret = krb5_parse_name(context,
|
||||
+ "cifs/w2022-118.w2022-l7.base@W2022-L7.BASE",
|
||||
+ &sprinc);
|
||||
if (ret)
|
||||
err(context, ret, "krb5_parse_name");
|
||||
|
||||
@@ -713,7 +743,7 @@ test_pac_ticket_signature(krb5_context context)
|
||||
|
||||
/* In this test, the server is also the client. */
|
||||
ret = krb5_pac_verify(context, pac, ticket->enc_part2->times.authtime,
|
||||
- ticket->server, NULL, NULL);
|
||||
+ cprinc, NULL, NULL);
|
||||
if (ret)
|
||||
err(context, ret, "while verifying PAC client info");
|
||||
|
||||
@@ -722,7 +752,7 @@ test_pac_ticket_signature(krb5_context context)
|
||||
ticket->enc_part2->authorization_data = NULL;
|
||||
|
||||
ret = krb5_kdc_sign_ticket(context, ticket->enc_part2, pac, sprinc,
|
||||
- sprinc, &ticket_sig_server_key,
|
||||
+ cprinc, &ticket_sig_server_key,
|
||||
&ticket_sig_krbtgt_key, FALSE);
|
||||
if (ret)
|
||||
err(context, ret, "while signing ticket");
|
||||
@@ -781,6 +811,7 @@ test_pac_ticket_signature(krb5_context context)
|
||||
krb5_pac_free(context, pac);
|
||||
krb5_pac_free(context, pac2);
|
||||
krb5_pac_free(context, pac3);
|
||||
+ krb5_free_principal(context, cprinc);
|
||||
krb5_free_principal(context, sprinc);
|
||||
krb5_free_ticket(context, ticket);
|
||||
}
|
||||
diff --git a/src/tests/t_authdata.py b/src/tests/t_authdata.py
|
||||
index 4fbdbec052..b0666c3b81 100644
|
||||
--- a/src/tests/t_authdata.py
|
||||
+++ b/src/tests/t_authdata.py
|
||||
@@ -11,7 +11,7 @@ realm = K5Realm(krb5_conf=conf)
|
||||
# container.
|
||||
mark('baseline authdata')
|
||||
out = realm.run(['./adata', realm.host_princ])
|
||||
-if '?512: ' not in out or '^-42: Hello' not in out:
|
||||
+if '?128: [6, 7, 10, 16, 19]' not in out or '^-42: Hello' not in out:
|
||||
fail('expected authdata not seen for basic request')
|
||||
|
||||
# Requested authdata is copied into the ticket, with KDC-only types
|
||||
@@ -239,6 +239,9 @@ realm.run(['./s4u2proxy', usercache, 'service/2'])
|
||||
out = realm.run(['./adata', '-p', realm.user_princ, 'service/2'])
|
||||
if '+97: [indcl]' not in out or '[inds1]' in out:
|
||||
fail('correct auth-indicator not seen for S4U2Proxy req')
|
||||
+# Make sure a PAC with an S4U_DELEGATION_INFO(11) buffer is included.
|
||||
+if '?128: [1, 6, 7, 10, 11, 16, 19]' not in out:
|
||||
+ fail('PAC with delegation info not seen for S4U2Proxy req')
|
||||
|
||||
# Get another S4U2Proxy ticket including request-authdata.
|
||||
realm.run(['./s4u2proxy', usercache, 'service/2', '-2', 'proxy_ad'])
|
||||
--
|
||||
2.39.2
|
||||
|
840
SOURCES/Add-PAC-ticket-signature-APIs.patch
Normal file
840
SOURCES/Add-PAC-ticket-signature-APIs.patch
Normal file
@ -0,0 +1,840 @@
|
||||
From 48be25aaa27487fcbbba76044083de37211b30e7 Mon Sep 17 00:00:00 2001
|
||||
From: Isaac Boukris <iboukris@gmail.com>
|
||||
Date: Fri, 7 Jan 2022 13:46:24 -0500
|
||||
Subject: [PATCH] Add PAC ticket signature APIs
|
||||
|
||||
Microsoft added a third PAC signature over the ticket to prevent
|
||||
servers from setting the forwardable flag on evidence tickets. Add
|
||||
new APIs to generate and verify ticket signatures, as well as defines
|
||||
for this and other new PAC buffer types. Deprecate the old signing
|
||||
functions as they cannot generate ticket signatures. Modify several
|
||||
error returns to better match the protocol errors generated by Active
|
||||
Directory.
|
||||
|
||||
[ghudson@mit.edu: adjusted contracts for KDC requirements; simplified
|
||||
and commented code changes; wrote commit message. rharwood@redhat.com
|
||||
also did some work on this commit.]
|
||||
|
||||
ticket: 9043 (new)
|
||||
---
|
||||
doc/appdev/refs/api/index.rst | 2 +
|
||||
doc/appdev/refs/macros/index.rst | 6 +
|
||||
src/include/krb5/krb5.hin | 98 +++++++++++------
|
||||
src/lib/krb5/krb/deps | 5 +-
|
||||
src/lib/krb5/krb/int-proto.h | 12 ++
|
||||
src/lib/krb5/krb/pac.c | 148 ++++++++++++++++++++++++-
|
||||
src/lib/krb5/krb/pac_sign.c | 121 ++++++++++++++++++++
|
||||
src/lib/krb5/krb/t_pac.c | 182 +++++++++++++++++++++++++++++++
|
||||
src/lib/krb5/libkrb5.exports | 2 +
|
||||
src/lib/krb5_32.def | 3 +
|
||||
src/plugins/kdb/test/kdb_test.c | 6 +-
|
||||
11 files changed, 544 insertions(+), 41 deletions(-)
|
||||
|
||||
diff --git a/doc/appdev/refs/api/index.rst b/doc/appdev/refs/api/index.rst
|
||||
index 9e03fd386f..d12be47c3c 100644
|
||||
--- a/doc/appdev/refs/api/index.rst
|
||||
+++ b/doc/appdev/refs/api/index.rst
|
||||
@@ -223,6 +223,8 @@ Rarely used public interfaces
|
||||
krb5_init_creds_step.rst
|
||||
krb5_init_keyblock.rst
|
||||
krb5_is_referral_realm.rst
|
||||
+ krb5_kdc_sign_ticket.rst
|
||||
+ krb5_kdc_verify_ticket.rst
|
||||
krb5_kt_add_entry.rst
|
||||
krb5_kt_end_seq_get.rst
|
||||
krb5_kt_get_entry.rst
|
||||
diff --git a/doc/appdev/refs/macros/index.rst b/doc/appdev/refs/macros/index.rst
|
||||
index 001fb386a7..c6ea088742 100644
|
||||
--- a/doc/appdev/refs/macros/index.rst
|
||||
+++ b/doc/appdev/refs/macros/index.rst
|
||||
@@ -234,12 +234,18 @@ Public
|
||||
KRB5_NT_UNKNOWN.rst
|
||||
KRB5_NT_WELLKNOWN.rst
|
||||
KRB5_NT_X500_PRINCIPAL.rst
|
||||
+ KRB5_PAC_ATTRIBUTES_INFO.rst
|
||||
KRB5_PAC_CLIENT_INFO.rst
|
||||
+ KRB5_PAC_CLIENT_CLAIMS.rst
|
||||
KRB5_PAC_CREDENTIALS_INFO.rst
|
||||
KRB5_PAC_DELEGATION_INFO.rst
|
||||
+ KRB5_PAC_DEVICE_CLAIMS.rst
|
||||
+ KRB5_PAC_DEVICE_INFO.rst
|
||||
KRB5_PAC_LOGON_INFO.rst
|
||||
KRB5_PAC_PRIVSVR_CHECKSUM.rst
|
||||
+ KRB5_PAC_REQUESTOR.rst
|
||||
KRB5_PAC_SERVER_CHECKSUM.rst
|
||||
+ KRB5_PAC_TICKET_CHECKSUM.rst
|
||||
KRB5_PAC_UPN_DNS_INFO.rst
|
||||
KRB5_PADATA_AFS3_SALT.rst
|
||||
KRB5_PADATA_AP_REQ.rst
|
||||
diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin
|
||||
index a7060aa733..8e59628bd9 100644
|
||||
--- a/src/include/krb5/krb5.hin
|
||||
+++ b/src/include/krb5/krb5.hin
|
||||
@@ -1918,7 +1918,7 @@ krb5_verify_checksum(krb5_context context, krb5_cksumtype ctype,
|
||||
#define KRB5_AUTHDATA_CAMMAC 96
|
||||
#define KRB5_AUTHDATA_WIN2K_PAC 128
|
||||
#define KRB5_AUTHDATA_ETYPE_NEGOTIATION 129 /**< RFC 4537 */
|
||||
-#define KRB5_AUTHDATA_SIGNTICKET 512 /**< formerly 142 in krb5 1.8 */
|
||||
+#define KRB5_AUTHDATA_SIGNTICKET 512 /**< @deprecated use PAC */
|
||||
#define KRB5_AUTHDATA_FX_ARMOR 71
|
||||
#define KRB5_AUTHDATA_AUTH_INDICATOR 97
|
||||
#define KRB5_AUTHDATA_AP_OPTIONS 143
|
||||
@@ -8181,6 +8181,12 @@ krb5_verify_authdata_kdc_issued(krb5_context context,
|
||||
#define KRB5_PAC_CLIENT_INFO 10 /**< Client name and ticket info */
|
||||
#define KRB5_PAC_DELEGATION_INFO 11 /**< Constrained delegation info */
|
||||
#define KRB5_PAC_UPN_DNS_INFO 12 /**< User principal name and DNS info */
|
||||
+#define KRB5_PAC_CLIENT_CLAIMS 13 /**< Client claims information */
|
||||
+#define KRB5_PAC_DEVICE_INFO 14 /**< Device information */
|
||||
+#define KRB5_PAC_DEVICE_CLAIMS 15 /**< Device claims information */
|
||||
+#define KRB5_PAC_TICKET_CHECKSUM 16 /**< Ticket checksum */
|
||||
+#define KRB5_PAC_ATTRIBUTES_INFO 17 /**< PAC attributes */
|
||||
+#define KRB5_PAC_REQUESTOR 18 /**< PAC requestor SID */
|
||||
|
||||
struct krb5_pac_data;
|
||||
/** PAC data structure to convey authorization information */
|
||||
@@ -8338,56 +8344,84 @@ krb5_pac_verify_ext(krb5_context context, const krb5_pac pac,
|
||||
krb5_boolean with_realm);
|
||||
|
||||
/**
|
||||
- * Sign a PAC.
|
||||
+ * Verify a PAC, possibly including ticket signature
|
||||
*
|
||||
- * @param [in] context Library context
|
||||
- * @param [in] pac PAC handle
|
||||
- * @param [in] authtime Expected timestamp
|
||||
- * @param [in] principal Expected principal name (or NULL)
|
||||
- * @param [in] server_key Key for server checksum
|
||||
- * @param [in] privsvr_key Key for KDC checksum
|
||||
- * @param [out] data Signed PAC encoding
|
||||
+ * @param [in] context Library context
|
||||
+ * @param [in] enc_tkt Ticket enc-part, possibly containing a PAC
|
||||
+ * @param [in] server_princ Canonicalized name of ticket server
|
||||
+ * @param [in] server Key to validate server checksum (or NULL)
|
||||
+ * @param [in] privsvr Key to validate KDC checksum (or NULL)
|
||||
+ * @param [out] pac_out Verified PAC (NULL if no PAC included)
|
||||
*
|
||||
- * This function signs @a pac using the keys @a server_key and @a privsvr_key
|
||||
- * and returns the signed encoding in @a data. @a pac is modified to include
|
||||
- * the server and KDC checksum buffers. Use krb5_free_data_contents() to free
|
||||
- * @a data when it is no longer needed.
|
||||
+ * If a PAC is present in @a enc_tkt, verify its signatures. If @a privsvr is
|
||||
+ * not NULL and @a server_princ is not a krbtgt or kadmin/changepw service,
|
||||
+ * require a ticket signature over @a enc_tkt in addition to the KDC signature.
|
||||
+ * Place the verified PAC in @a pac_out. If an invalid PAC signature is found,
|
||||
+ * return an error matching the Windows KDC protocol code for that condition as
|
||||
+ * closely as possible.
|
||||
*
|
||||
- * @version New in 1.10
|
||||
+ * If no PAC is present in @a enc_tkt, set @a pac_out to NULL and return
|
||||
+ * successfully.
|
||||
+ *
|
||||
+ * @note This function does not validate the PAC_CLIENT_INFO buffer. If a
|
||||
+ * specific value is expected, the caller can make a separate call to
|
||||
+ * krb5_pac_verify_ext() with a principal but no keys.
|
||||
+ *
|
||||
+ * @retval 0 Success; otherwise - Kerberos error codes
|
||||
+ *
|
||||
+ * @version New in 1.20
|
||||
*/
|
||||
krb5_error_code KRB5_CALLCONV
|
||||
+krb5_kdc_verify_ticket(krb5_context context, const krb5_enc_tkt_part *enc_tkt,
|
||||
+ krb5_const_principal server_princ,
|
||||
+ const krb5_keyblock *server,
|
||||
+ const krb5_keyblock *privsvr, krb5_pac *pac_out);
|
||||
+
|
||||
+/** @deprecated Use krb5_kdc_sign_ticket() instead. */
|
||||
+krb5_error_code KRB5_CALLCONV
|
||||
krb5_pac_sign(krb5_context context, krb5_pac pac, krb5_timestamp authtime,
|
||||
krb5_const_principal principal, const krb5_keyblock *server_key,
|
||||
const krb5_keyblock *privsvr_key, krb5_data *data);
|
||||
|
||||
+/** @deprecated Use krb5_kdc_sign_ticket() instead. */
|
||||
+krb5_error_code KRB5_CALLCONV
|
||||
+krb5_pac_sign_ext(krb5_context context, krb5_pac pac, krb5_timestamp authtime,
|
||||
+ krb5_const_principal principal,
|
||||
+ const krb5_keyblock *server_key,
|
||||
+ const krb5_keyblock *privsvr_key, krb5_boolean with_realm,
|
||||
+ krb5_data *data);
|
||||
+
|
||||
/**
|
||||
- * Sign a PAC, possibly with a specified realm.
|
||||
+ * Sign a PAC, possibly including a ticket signature
|
||||
*
|
||||
* @param [in] context Library context
|
||||
+ * @param [in] enc_tkt The ticket for the signature
|
||||
* @param [in] pac PAC handle
|
||||
- * @param [in] authtime Expected timestamp
|
||||
- * @param [in] principal Principal name (or NULL)
|
||||
- * @param [in] server_key Key for server checksum
|
||||
- * @param [in] privsvr_key Key for KDC checksum
|
||||
+ * @param [in] server_princ Canonical ticket server name
|
||||
+ * @param [in] client_princ PAC_CLIENT_INFO principal (or NULL)
|
||||
+ * @param [in] server Key for server checksum
|
||||
+ * @param [in] privsvr Key for KDC and ticket checksum
|
||||
* @param [in] with_realm If true, include the realm of @a principal
|
||||
- * @param [out] data Signed PAC encoding
|
||||
*
|
||||
- * This function is similar to krb5_pac_sign(), but adds a parameter
|
||||
- * @a with_realm. If @a with_realm is true, the PAC_CLIENT_INFO field of the
|
||||
- * signed PAC will include the realm of @a principal as well as the name. This
|
||||
- * flag is necessary to generate PACs for cross-realm S4U2Self referrals.
|
||||
+ * Sign @a pac using the keys @a server and @a privsvr. Include a ticket
|
||||
+ * signature over @a enc_tkt if @a server_princ is not a TGS or kadmin/changepw
|
||||
+ * principal name. Add the signed PAC's encoding to the authorization data of
|
||||
+ * @a enc_tkt in the first slot, wrapped in an AD-IF-RELEVANT container. If @a
|
||||
+ * client_princ is non-null, add a PAC_CLIENT_INFO buffer, including the realm
|
||||
+ * if @a with_realm is true.
|
||||
*
|
||||
- * @version New in 1.17
|
||||
+ * @retval 0 on success, otherwise - Kerberos error codes
|
||||
+ *
|
||||
+ * @version New in 1.20
|
||||
*/
|
||||
krb5_error_code KRB5_CALLCONV
|
||||
-krb5_pac_sign_ext(krb5_context context, krb5_pac pac, krb5_timestamp authtime,
|
||||
- krb5_const_principal principal,
|
||||
- const krb5_keyblock *server_key,
|
||||
- const krb5_keyblock *privsvr_key, krb5_boolean with_realm,
|
||||
- krb5_data *data);
|
||||
+krb5_kdc_sign_ticket(krb5_context context, krb5_enc_tkt_part *enc_tkt,
|
||||
+ const krb5_pac pac, krb5_const_principal server_princ,
|
||||
+ krb5_const_principal client_princ,
|
||||
+ const krb5_keyblock *server, const krb5_keyblock *privsvr,
|
||||
+ krb5_boolean with_realm);
|
||||
|
||||
-
|
||||
-/*
|
||||
+/**
|
||||
* Read client information from a PAC.
|
||||
*
|
||||
* @param [in] context Library context
|
||||
diff --git a/src/lib/krb5/krb/deps b/src/lib/krb5/krb/deps
|
||||
index 439ca02725..cd842b03cd 100644
|
||||
--- a/src/lib/krb5/krb/deps
|
||||
+++ b/src/lib/krb5/krb/deps
|
||||
@@ -709,7 +709,7 @@ pac.so pac.po $(OUTPRE)pac.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
|
||||
$(top_srcdir)/include/k5-utf8.h $(top_srcdir)/include/krb5.h \
|
||||
$(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
|
||||
$(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
|
||||
- authdata.h pac.c
|
||||
+ authdata.h int-proto.h pac.c
|
||||
pac_sign.so pac_sign.po $(OUTPRE)pac_sign.$(OBJEXT): \
|
||||
$(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
|
||||
$(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
|
||||
@@ -720,7 +720,8 @@ pac_sign.so pac_sign.po $(OUTPRE)pac_sign.$(OBJEXT): \
|
||||
$(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/k5-utf8.h \
|
||||
$(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
|
||||
$(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
|
||||
- $(top_srcdir)/include/socket-utils.h authdata.h pac_sign.c
|
||||
+ $(top_srcdir)/include/socket-utils.h authdata.h int-proto.h \
|
||||
+ pac_sign.c
|
||||
padata.so padata.po $(OUTPRE)padata.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
|
||||
$(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
|
||||
$(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \
|
||||
diff --git a/src/lib/krb5/krb/int-proto.h b/src/lib/krb5/krb/int-proto.h
|
||||
index fe61bebf5b..453ed60c6c 100644
|
||||
--- a/src/lib/krb5/krb/int-proto.h
|
||||
+++ b/src/lib/krb5/krb/int-proto.h
|
||||
@@ -386,4 +386,16 @@ k5_get_proxy_cred_from_kdc(krb5_context context, krb5_flags options,
|
||||
krb5_ccache ccache, krb5_creds *in_creds,
|
||||
krb5_creds **out_creds);
|
||||
|
||||
+/* Return true if mprinc will match any hostname in a host-based principal name
|
||||
+ * (possibly due to ignore_acceptor_hostname) with krb5_sname_match(). */
|
||||
+krb5_boolean
|
||||
+k5_sname_wildcard_host(krb5_context context, krb5_const_principal mprinc);
|
||||
+
|
||||
+/* Guess the appropriate name-type for a principal based on the name. */
|
||||
+krb5_int32
|
||||
+k5_infer_principal_type(krb5_principal princ);
|
||||
+
|
||||
+krb5_boolean
|
||||
+k5_pac_should_have_ticket_signature(krb5_const_principal sprinc);
|
||||
+
|
||||
#endif /* KRB5_INT_FUNC_PROTO__ */
|
||||
diff --git a/src/lib/krb5/krb/pac.c b/src/lib/krb5/krb/pac.c
|
||||
index 1b9ef12276..6eb23d8090 100644
|
||||
--- a/src/lib/krb5/krb/pac.c
|
||||
+++ b/src/lib/krb5/krb/pac.c
|
||||
@@ -25,6 +25,7 @@
|
||||
*/
|
||||
|
||||
#include "k5-int.h"
|
||||
+#include "int-proto.h"
|
||||
#include "authdata.h"
|
||||
|
||||
#define MAX_BUFFERS 4096
|
||||
@@ -552,8 +553,10 @@ k5_pac_verify_server_checksum(krb5_context context,
|
||||
checksum.checksum_type = load_32_le(p);
|
||||
checksum.length = checksum_data.length - PAC_SIGNATURE_DATA_LENGTH;
|
||||
checksum.contents = p + PAC_SIGNATURE_DATA_LENGTH;
|
||||
+ if (checksum.checksum_type == CKSUMTYPE_SHA1)
|
||||
+ return KRB5KDC_ERR_SUMTYPE_NOSUPP;
|
||||
if (!krb5_c_is_keyed_cksum(checksum.checksum_type))
|
||||
- return KRB5KRB_AP_ERR_INAPP_CKSUM;
|
||||
+ return KRB5KRB_ERR_GENERIC;
|
||||
|
||||
pac_data.length = pac->data.length;
|
||||
pac_data.data = k5memdup(pac->data.data, pac->data.length, &ret);
|
||||
@@ -586,7 +589,7 @@ k5_pac_verify_server_checksum(krb5_context context,
|
||||
}
|
||||
|
||||
if (valid == FALSE)
|
||||
- ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
|
||||
+ ret = KRB5KRB_AP_ERR_MODIFIED;
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -623,7 +626,7 @@ k5_pac_verify_kdc_checksum(krb5_context context,
|
||||
checksum.length = privsvr_checksum.length - PAC_SIGNATURE_DATA_LENGTH;
|
||||
checksum.contents = p + PAC_SIGNATURE_DATA_LENGTH;
|
||||
if (!krb5_c_is_keyed_cksum(checksum.checksum_type))
|
||||
- return KRB5KRB_AP_ERR_INAPP_CKSUM;
|
||||
+ return KRB5KRB_ERR_GENERIC;
|
||||
|
||||
server_checksum.data += PAC_SIGNATURE_DATA_LENGTH;
|
||||
server_checksum.length -= PAC_SIGNATURE_DATA_LENGTH;
|
||||
@@ -635,11 +638,148 @@ k5_pac_verify_kdc_checksum(krb5_context context,
|
||||
return ret;
|
||||
|
||||
if (valid == FALSE)
|
||||
- ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
|
||||
+ ret = KRB5KRB_AP_ERR_MODIFIED;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static krb5_error_code
|
||||
+verify_ticket_checksum(krb5_context context, const krb5_pac pac,
|
||||
+ const krb5_data *ticket, const krb5_keyblock *privsvr)
|
||||
+{
|
||||
+ krb5_error_code ret;
|
||||
+ krb5_checksum checksum;
|
||||
+ krb5_data checksum_data;
|
||||
+ krb5_boolean valid;
|
||||
+ krb5_octet *p;
|
||||
+
|
||||
+ ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_TICKET_CHECKSUM,
|
||||
+ &checksum_data);
|
||||
+ if (ret != 0)
|
||||
+ return KRB5KRB_AP_ERR_MODIFIED;
|
||||
+
|
||||
+ if (checksum_data.length < PAC_SIGNATURE_DATA_LENGTH)
|
||||
+ return KRB5_BAD_MSIZE;
|
||||
+
|
||||
+ p = (krb5_octet *)checksum_data.data;
|
||||
+ checksum.checksum_type = load_32_le(p);
|
||||
+ checksum.length = checksum_data.length - PAC_SIGNATURE_DATA_LENGTH;
|
||||
+ checksum.contents = p + PAC_SIGNATURE_DATA_LENGTH;
|
||||
+ if (!krb5_c_is_keyed_cksum(checksum.checksum_type))
|
||||
+ return KRB5KRB_ERR_GENERIC;
|
||||
+
|
||||
+ ret = krb5_c_verify_checksum(context, privsvr,
|
||||
+ KRB5_KEYUSAGE_APP_DATA_CKSUM, ticket,
|
||||
+ &checksum, &valid);
|
||||
+ if (ret != 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ return valid ? 0 : KRB5KRB_AP_ERR_MODIFIED;
|
||||
+}
|
||||
+
|
||||
+/* Per MS-PAC 2.8.3, tickets encrypted to TGS and password change principals
|
||||
+ * should not have ticket signatures. */
|
||||
+krb5_boolean
|
||||
+k5_pac_should_have_ticket_signature(krb5_const_principal sprinc)
|
||||
+{
|
||||
+ if (IS_TGS_PRINC(sprinc))
|
||||
+ return FALSE;
|
||||
+ if (sprinc->length == 2 && data_eq_string(sprinc->data[0], "kadmin") &&
|
||||
+ data_eq_string(sprinc->data[1], "changepw"))
|
||||
+ return FALSE;
|
||||
+ return TRUE;
|
||||
+}
|
||||
+
|
||||
+krb5_error_code KRB5_CALLCONV
|
||||
+krb5_kdc_verify_ticket(krb5_context context, const krb5_enc_tkt_part *enc_tkt,
|
||||
+ krb5_const_principal server_princ,
|
||||
+ const krb5_keyblock *server,
|
||||
+ const krb5_keyblock *privsvr, krb5_pac *pac_out)
|
||||
+{
|
||||
+ krb5_error_code ret;
|
||||
+ krb5_pac pac = NULL;
|
||||
+ krb5_data *recoded_tkt = NULL;
|
||||
+ krb5_authdata **authdata, *orig, **ifrel = NULL, **recoded_ifrel = NULL;
|
||||
+ uint8_t z = 0;
|
||||
+ krb5_authdata zpac = { KV5M_AUTHDATA, KRB5_AUTHDATA_WIN2K_PAC, 1, &z };
|
||||
+ size_t i, j;
|
||||
+
|
||||
+ *pac_out = NULL;
|
||||
+
|
||||
+ /*
|
||||
+ * Find the position of the PAC in the ticket authdata. ifrel will be the
|
||||
+ * decoded AD-IF-RELEVANT container at position i containing a PAC, and j
|
||||
+ * will be the offset within the container.
|
||||
+ */
|
||||
+ authdata = enc_tkt->authorization_data;
|
||||
+ for (i = 0; authdata != NULL && authdata[i] != NULL; i++) {
|
||||
+ if (authdata[i]->ad_type != KRB5_AUTHDATA_IF_RELEVANT)
|
||||
+ continue;
|
||||
+
|
||||
+ ret = krb5_decode_authdata_container(context,
|
||||
+ KRB5_AUTHDATA_IF_RELEVANT,
|
||||
+ authdata[i], &ifrel);
|
||||
+ if (ret)
|
||||
+ goto cleanup;
|
||||
+
|
||||
+ for (j = 0; ifrel[j] != NULL; j++) {
|
||||
+ if (ifrel[j]->ad_type == KRB5_AUTHDATA_WIN2K_PAC)
|
||||
+ break;
|
||||
+ }
|
||||
+ if (ifrel[j] != NULL)
|
||||
+ break;
|
||||
+
|
||||
+ krb5_free_authdata(context, ifrel);
|
||||
+ ifrel = NULL;
|
||||
+ }
|
||||
+
|
||||
+ /* Stop and return successfully if we didn't find a PAC. */
|
||||
+ if (ifrel == NULL) {
|
||||
+ ret = 0;
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
+ ret = krb5_pac_parse(context, ifrel[j]->contents, ifrel[j]->length, &pac);
|
||||
+ if (ret)
|
||||
+ goto cleanup;
|
||||
+
|
||||
+ if (privsvr != NULL && k5_pac_should_have_ticket_signature(server_princ)) {
|
||||
+ /* To check the PAC ticket signatures, re-encode the ticket with the
|
||||
+ * PAC contents replaced by a single zero. */
|
||||
+ orig = ifrel[j];
|
||||
+ ifrel[j] = &zpac;
|
||||
+ ret = krb5_encode_authdata_container(context,
|
||||
+ KRB5_AUTHDATA_IF_RELEVANT,
|
||||
+ ifrel, &recoded_ifrel);
|
||||
+ ifrel[j] = orig;
|
||||
+ if (ret)
|
||||
+ goto cleanup;
|
||||
+ orig = authdata[i];
|
||||
+ authdata[i] = recoded_ifrel[0];
|
||||
+ ret = encode_krb5_enc_tkt_part(enc_tkt, &recoded_tkt);
|
||||
+ authdata[i] = orig;
|
||||
+ if (ret)
|
||||
+ goto cleanup;
|
||||
+
|
||||
+ ret = verify_ticket_checksum(context, pac, recoded_tkt, privsvr);
|
||||
+ if (ret)
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
+ ret = krb5_pac_verify_ext(context, pac, enc_tkt->times.authtime, NULL,
|
||||
+ server, privsvr, FALSE);
|
||||
+
|
||||
+ *pac_out = pac;
|
||||
+ pac = NULL;
|
||||
+
|
||||
+cleanup:
|
||||
+ krb5_pac_free(context, pac);
|
||||
+ krb5_free_data(context, recoded_tkt);
|
||||
+ krb5_free_authdata(context, ifrel);
|
||||
+ krb5_free_authdata(context, recoded_ifrel);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
krb5_error_code KRB5_CALLCONV
|
||||
krb5_pac_verify(krb5_context context,
|
||||
const krb5_pac pac,
|
||||
diff --git a/src/lib/krb5/krb/pac_sign.c b/src/lib/krb5/krb/pac_sign.c
|
||||
index 12f0259b4f..0f9581abbb 100644
|
||||
--- a/src/lib/krb5/krb/pac_sign.c
|
||||
+++ b/src/lib/krb5/krb/pac_sign.c
|
||||
@@ -25,6 +25,7 @@
|
||||
*/
|
||||
|
||||
#include "k5-int.h"
|
||||
+#include "int-proto.h"
|
||||
#include "authdata.h"
|
||||
|
||||
/* draft-brezak-win2k-krb-authz-00 */
|
||||
@@ -286,3 +287,123 @@ krb5_pac_sign_ext(krb5_context context, krb5_pac pac, krb5_timestamp authtime,
|
||||
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
+/* Add a signature over der_enc_tkt in privsvr to pac. der_enc_tkt should be
|
||||
+ * encoded with a dummy PAC authdata element containing a single zero byte. */
|
||||
+static krb5_error_code
|
||||
+add_ticket_signature(krb5_context context, const krb5_pac pac,
|
||||
+ krb5_data *der_enc_tkt, const krb5_keyblock *privsvr)
|
||||
+{
|
||||
+ krb5_error_code ret;
|
||||
+ krb5_data ticket_cksum;
|
||||
+ krb5_cksumtype ticket_cksumtype;
|
||||
+ krb5_crypto_iov iov[2];
|
||||
+
|
||||
+ /* Create zeroed buffer for checksum. */
|
||||
+ ret = k5_insert_checksum(context, pac, KRB5_PAC_TICKET_CHECKSUM,
|
||||
+ privsvr, &ticket_cksumtype);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_TICKET_CHECKSUM,
|
||||
+ &ticket_cksum);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
|
||||
+ iov[0].data = *der_enc_tkt;
|
||||
+ iov[1].flags = KRB5_CRYPTO_TYPE_CHECKSUM;
|
||||
+ iov[1].data = make_data(ticket_cksum.data + PAC_SIGNATURE_DATA_LENGTH,
|
||||
+ ticket_cksum.length - PAC_SIGNATURE_DATA_LENGTH);
|
||||
+ ret = krb5_c_make_checksum_iov(context, ticket_cksumtype, privsvr,
|
||||
+ KRB5_KEYUSAGE_APP_DATA_CKSUM, iov, 2);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ store_32_le(ticket_cksumtype, ticket_cksum.data);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* Set *out to an AD-IF-RELEVANT authdata element containing a PAC authdata
|
||||
+ * element with contents pac_data. */
|
||||
+static krb5_error_code
|
||||
+encode_pac_ad(krb5_context context, krb5_data *pac_data, krb5_authdata **out)
|
||||
+{
|
||||
+ krb5_error_code ret;
|
||||
+ krb5_authdata *container[2], **encoded_container = NULL;
|
||||
+ krb5_authdata pac_ad = { KV5M_AUTHDATA, KRB5_AUTHDATA_WIN2K_PAC };
|
||||
+ uint8_t z = 0;
|
||||
+
|
||||
+ pac_ad.contents = (pac_data != NULL) ? (uint8_t *)pac_data->data : &z;
|
||||
+ pac_ad.length = (pac_data != NULL) ? pac_data->length : 1;
|
||||
+ container[0] = &pac_ad;
|
||||
+ container[1] = NULL;
|
||||
+
|
||||
+ ret = krb5_encode_authdata_container(context, KRB5_AUTHDATA_IF_RELEVANT,
|
||||
+ container, &encoded_container);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ *out = encoded_container[0];
|
||||
+ free(encoded_container);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+krb5_error_code KRB5_CALLCONV
|
||||
+krb5_kdc_sign_ticket(krb5_context context, krb5_enc_tkt_part *enc_tkt,
|
||||
+ const krb5_pac pac, krb5_const_principal server_princ,
|
||||
+ krb5_const_principal client_princ,
|
||||
+ const krb5_keyblock *server, const krb5_keyblock *privsvr,
|
||||
+ krb5_boolean with_realm)
|
||||
+{
|
||||
+ krb5_error_code ret;
|
||||
+ krb5_data *der_enc_tkt = NULL, pac_data = empty_data();
|
||||
+ krb5_authdata **list, *pac_ad;
|
||||
+ size_t count;
|
||||
+
|
||||
+ /* Reallocate space for another authdata element in enc_tkt. */
|
||||
+ list = enc_tkt->authorization_data;
|
||||
+ for (count = 0; list != NULL && list[count] != NULL; count++);
|
||||
+ list = realloc(enc_tkt->authorization_data, (count + 2) * sizeof(*list));
|
||||
+ if (list == NULL)
|
||||
+ return ENOMEM;
|
||||
+ list[count] = NULL;
|
||||
+ enc_tkt->authorization_data = list;
|
||||
+
|
||||
+ /* Create a dummy PAC for ticket signing and make it the first element. */
|
||||
+ ret = encode_pac_ad(context, NULL, &pac_ad);
|
||||
+ if (ret)
|
||||
+ goto cleanup;
|
||||
+ memmove(list + 1, list, (count + 1) * sizeof(*list));
|
||||
+ list[0] = pac_ad;
|
||||
+
|
||||
+ if (k5_pac_should_have_ticket_signature(server_princ)) {
|
||||
+ ret = encode_krb5_enc_tkt_part(enc_tkt, &der_enc_tkt);
|
||||
+ if (ret)
|
||||
+ goto cleanup;
|
||||
+
|
||||
+ assert(privsvr != NULL);
|
||||
+ ret = add_ticket_signature(context, pac, der_enc_tkt, privsvr);
|
||||
+ if (ret)
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
+ ret = krb5_pac_sign_ext(context, pac, enc_tkt->times.authtime,
|
||||
+ client_princ, server, privsvr, with_realm,
|
||||
+ &pac_data);
|
||||
+ if (ret)
|
||||
+ goto cleanup;
|
||||
+
|
||||
+ /* Replace the dummy PAC with the signed real one. */
|
||||
+ ret = encode_pac_ad(context, &pac_data, &pac_ad);
|
||||
+ if (ret)
|
||||
+ goto cleanup;
|
||||
+ free(list[0]->contents);
|
||||
+ free(list[0]);
|
||||
+ list[0] = pac_ad;
|
||||
+
|
||||
+cleanup:
|
||||
+ krb5_free_data(context, der_enc_tkt);
|
||||
+ krb5_free_data_contents(context, &pac_data);
|
||||
+ return ret;
|
||||
+}
|
||||
diff --git a/src/lib/krb5/krb/t_pac.c b/src/lib/krb5/krb/t_pac.c
|
||||
index ccd165380d..173bde7bab 100644
|
||||
--- a/src/lib/krb5/krb/t_pac.c
|
||||
+++ b/src/lib/krb5/krb/t_pac.c
|
||||
@@ -605,6 +605,186 @@ check_pac(krb5_context context, int index, const unsigned char *pdata,
|
||||
krb5_pac_free(context, pac);
|
||||
}
|
||||
|
||||
+static const krb5_keyblock ticket_sig_krbtgt_key = {
|
||||
+ 0, ENCTYPE_AES256_CTS_HMAC_SHA1_96,
|
||||
+ 32, U("\x7a\x58\x98\xd2\xaf\xa6\xaf\xc0\x6a\xce\x06\x04\x4b\xc2\x70\x84"
|
||||
+ "\x9b\x8e\x0a\x6c\x4c\x07\xdc\x6f\xbb\x48\x43\xe1\xd2\xaa\x97\xf7")
|
||||
+};
|
||||
+
|
||||
+static const krb5_keyblock ticket_sig_server_key = {
|
||||
+ 0, ENCTYPE_ARCFOUR_HMAC,
|
||||
+ 16, U("\xed\x23\x11\x20\x7a\x21\x44\x20\xbf\xc0\x8d\x36\xf7\xf6\xb2\x3e")
|
||||
+};
|
||||
+
|
||||
+static const krb5_data ticket_data = {
|
||||
+ .length = 972, .data =
|
||||
+ "\x61\x82\x03\xC8\x30\x82\x03\xC4\xA0\x03\x02\x01\x05\xA1\x0A\x1B"
|
||||
+ "\x08\x43\x44\x4F\x4D\x2E\x43\x4F\x4D\xA2\x0F\x30\x0D\xA0\x03\x02"
|
||||
+ "\x01\x01\xA1\x06\x30\x04\x1B\x02\x73\x31\xA3\x82\x03\x9E\x30\x82"
|
||||
+ "\x03\x9A\xA0\x03\x02\x01\x17\xA1\x03\x02\x01\x03\xA2\x82\x03\x8C"
|
||||
+ "\x04\x82\x03\x88\x44\x31\x61\x20\x17\xC9\xFE\xBC\xAC\x46\xB5\x77"
|
||||
+ "\xE9\x68\x04\x4C\x9B\x31\x91\x0C\xC1\xD4\xDD\xEF\xC7\x34\x20\x08"
|
||||
+ "\x90\x91\xE8\x79\xE0\xB5\x03\x26\xA4\x65\xDE\xEC\x47\x03\x2A\x8F"
|
||||
+ "\x61\xE7\x4D\x38\x5A\x42\x95\x5A\xF9\x2F\x41\x2C\x2A\x6E\x60\xA1"
|
||||
+ "\xEB\x51\xB3\xBD\x4C\x00\x41\x2A\x44\x76\x08\x37\x1A\x51\xFD\x65"
|
||||
+ "\x67\x7E\xBF\x3D\x90\x86\xE3\x9A\x54\x6B\x67\xA8\x08\x7A\x73\xCC"
|
||||
+ "\xC3\xB7\x4B\xD5\x5C\x3A\x14\x6C\xC1\x5F\x54\x4B\x92\x55\xB4\xB7"
|
||||
+ "\x92\x23\x3F\x53\x89\x47\x8E\x1F\x8B\xB9\xDB\x3B\x93\xE8\x70\xE4"
|
||||
+ "\x24\xB8\x9D\xF0\x0E\x35\x28\xF8\x7A\x27\x5D\xF7\x25\x97\x9C\xF5"
|
||||
+ "\x9F\x9F\x64\x04\xF2\xA3\xAB\x11\x15\xB6\xDA\x18\xD6\x46\xD5\xE6"
|
||||
+ "\xB8\x08\xDE\x0A\x62\xFD\xF8\xAA\x52\x90\xD9\x67\x29\xB2\xCD\x06"
|
||||
+ "\xB6\xB0\x50\x2B\x3F\x0F\xA3\xA5\xBF\xAA\x6E\x40\x03\xD6\x5F\x02"
|
||||
+ "\xBC\xD8\x18\x47\x97\x09\xD7\xE4\x96\x3B\xCB\xEB\x92\x2C\x3C\x49"
|
||||
+ "\xFF\x1F\x71\xE0\x52\x94\x0F\x8B\x9F\xB8\x2A\xBB\x9C\xE2\xA3\xDD"
|
||||
+ "\x38\x89\xE2\xB1\x0B\x9E\x1F\x7A\xB3\xE3\xD2\xB0\x94\xDC\x87\xBE"
|
||||
+ "\x37\xA6\xD3\xB3\x29\x35\x9A\x72\xC3\x7A\xF1\xA9\xE6\xC5\xD1\x26"
|
||||
+ "\x83\x65\x44\x17\xBA\x55\xA8\x5E\x94\x26\xED\xE9\x8A\x93\x11\x5D"
|
||||
+ "\x7E\x20\x1B\x9C\x15\x9E\x13\x37\x03\x4D\xDD\x99\x51\xD8\x66\x29"
|
||||
+ "\x6A\xB9\xFB\x49\xFE\x52\x78\xDA\x86\x85\xA9\xA3\xB9\xEF\xEC\xAD"
|
||||
+ "\x35\xA6\x8D\xAC\x0F\x75\x22\xBB\x0B\x49\x1C\x13\x52\x40\xC9\x52"
|
||||
+ "\x69\x09\x54\xD1\x0F\x94\x3F\x22\x48\x67\xB0\x96\x28\xAA\xE6\x28"
|
||||
+ "\xD9\x0C\x08\xEF\x51\xED\x15\x5E\xA2\x53\x59\xA5\x03\xB4\x06\x20"
|
||||
+ "\x3D\xCC\xB4\xC5\xF8\x8C\x73\x67\xA3\x21\x3D\x19\xCD\xD4\x12\x28"
|
||||
+ "\xD2\x93\xDE\x0D\xF0\x71\x10\x50\xD6\x33\x35\x04\x11\x64\x43\x39"
|
||||
+ "\xC3\xDF\x96\xE3\x66\xE3\x85\xCA\xE7\x67\x14\x3A\xF0\x43\xAA\xBB"
|
||||
+ "\xD4\x1D\xB5\x24\xB5\x74\x90\x25\xA7\x87\x7E\xDB\xD3\x83\x8A\x3A"
|
||||
+ "\x69\xA8\x2D\xAF\xB7\xB8\xF3\xDC\x13\xAF\x45\x61\x3F\x59\x39\x7E"
|
||||
+ "\x69\xDE\x0C\x04\xF1\x10\x6B\xB4\x56\xFA\x21\x9F\x72\x2B\x60\x86"
|
||||
+ "\xE3\x23\x0E\xC4\x51\xF6\xBE\xD8\xE1\x5F\xEE\x73\x4C\x17\x4C\x2C"
|
||||
+ "\x1B\xFB\x9F\x1F\x7A\x3B\x07\x5B\x8E\xF1\x01\xAC\xD6\x30\x94\x8A"
|
||||
+ "\x5D\x22\x6F\x08\xCE\xED\x5E\xB6\xDB\x86\x8C\x87\xEB\x8D\x91\xFF"
|
||||
+ "\x0A\x86\x30\xBD\xC0\xF8\x25\xE7\xAE\x24\x35\xF2\xFC\xE5\xFD\x1B"
|
||||
+ "\xB0\x05\x4A\xA3\xE5\xEB\x2E\x05\xAD\x99\x67\x49\x87\xE6\xB3\x87"
|
||||
+ "\x82\xA4\x59\xA7\x6E\xDD\xF2\xB6\x66\xE8\xF7\x70\xF5\xBD\xC9\x0E"
|
||||
+ "\xFA\x9C\x79\x84\xD4\x9B\x05\x0E\xBB\xF5\xDB\xEF\xFC\xCC\x26\xF2"
|
||||
+ "\x93\xCF\xD2\x04\x3C\xA9\x2C\x65\x42\x97\x86\xD8\x38\x0A\x1E\xF6"
|
||||
+ "\xD6\xCA\x30\xB5\x1A\xEC\xFB\xBA\x3B\x84\x57\xB0\xFD\xFB\xE6\xBC"
|
||||
+ "\xF2\x76\xF6\x4C\xBB\xAB\xB1\x31\xA1\x27\x7C\xE6\xE6\x81\xB6\xCE"
|
||||
+ "\x84\x86\x40\xB6\x40\x33\xC4\xF8\xB4\x15\xCF\xAA\xA5\x51\x78\xB9"
|
||||
+ "\x8B\x50\x25\xB2\x88\x86\x96\x72\x8C\x71\x4D\xB5\x3A\x94\x86\x77"
|
||||
+ "\x0E\x95\x9B\x16\x93\xEF\x3A\x11\x79\xBA\x83\xF7\x74\xD3\x8D\xBA"
|
||||
+ "\x15\xE1\x2C\x04\x57\xA8\x92\x1E\x9D\x00\x8E\x20\xFD\x30\x70\xE7"
|
||||
+ "\xF5\x65\x2F\x19\x0C\x94\xBA\x03\x71\x12\x96\xCD\xC8\xB4\x96\xDB"
|
||||
+ "\xCE\x19\xC2\xDF\x3C\xC2\xF6\x3D\x53\xED\x98\xA5\x41\x72\x2A\x22"
|
||||
+ "\x7B\xF3\x2B\x17\x6C\xE1\x39\x7D\xAE\x9B\x11\xF9\xC1\xA6\x9E\x9F"
|
||||
+ "\x89\x3C\x12\xAA\x94\x74\xA7\x4F\x70\xE8\xB9\xDE\x04\xF0\x9D\x39"
|
||||
+ "\x24\x2D\x92\xE8\x46\x2D\x2E\xF0\x40\x66\x1A\xD9\x27\xF9\x98\xF1"
|
||||
+ "\x81\x1D\x70\x62\x63\x30\x6D\xCD\x84\x04\x5F\xFA\x83\xD3\xEC\x8D"
|
||||
+ "\x86\xFB\x40\x61\xC1\x8A\x45\xFF\x7B\xD9\xD4\x18\x61\x7F\x51\xE3"
|
||||
+ "\xFC\x1E\x18\xF0\xAF\xC6\x18\x2C\xE1\x6D\x5D\xF9\x62\xFC\x20\xA3"
|
||||
+ "\xB2\x8A\x5F\xE5\xBB\x29\x0F\x99\x63\x07\x88\x38\x3A\x3B\x73\x2A"
|
||||
+ "\x6D\xDA\x3D\xA8\x0D\x8F\x56\x41\x89\x82\xE5\xB8\x61\x00\x64\x7D"
|
||||
+ "\x17\x0C\xCE\x03\x55\x8F\xF4\x5B\x0D\x50\xF2\xEB\x05\x67\xBE\xDB"
|
||||
+ "\x7B\x75\xC5\xEA\xA1\xAB\x1D\xB0\x3C\x6D\x42\x08\x0B\x9A\x45\x20"
|
||||
+ "\xA8\x8F\xE5\x67\x47\x30\xDE\x93\x5F\x43\x05\xEB\xA8\x2D\x80\xF5"
|
||||
+ "\x1A\xB8\x4A\x4E\x42\x2D\x0B\x7A\xDC\x46\x20\x2D\x13\x17\xDD\x4B"
|
||||
+ "\x94\x96\xAA\x1F\x06\x0C\x1F\x62\x07\x9C\x40\xA1"
|
||||
+};
|
||||
+
|
||||
+static void
|
||||
+test_pac_ticket_signature(krb5_context context)
|
||||
+{
|
||||
+ krb5_error_code ret;
|
||||
+ krb5_ticket *ticket;
|
||||
+ krb5_principal sprinc;
|
||||
+ krb5_authdata **authdata1, **authdata2;
|
||||
+ krb5_pac pac, pac2, pac3;
|
||||
+ uint32_t *list;
|
||||
+ size_t len, i;
|
||||
+ krb5_data data;
|
||||
+
|
||||
+ ret = krb5_decode_ticket(&ticket_data, &ticket);
|
||||
+ if (ret)
|
||||
+ err(context, ret, "while decoding ticket");
|
||||
+
|
||||
+ ret = krb5_decrypt_tkt_part(context, &ticket_sig_server_key, ticket);
|
||||
+ if (ret)
|
||||
+ err(context, ret, "while decrypting ticket");
|
||||
+
|
||||
+ ret = krb5_parse_name(context, "s1@CDOM.COM", &sprinc);
|
||||
+ if (ret)
|
||||
+ err(context, ret, "krb5_parse_name");
|
||||
+
|
||||
+ ret = krb5_kdc_verify_ticket(context, ticket->enc_part2, sprinc,
|
||||
+ &ticket_sig_server_key,
|
||||
+ &ticket_sig_krbtgt_key, &pac);
|
||||
+ if (ret)
|
||||
+ err(context, ret, "while verifying ticket");
|
||||
+
|
||||
+ /* In this test, the server is also the client. */
|
||||
+ ret = krb5_pac_verify(context, pac, ticket->enc_part2->times.authtime,
|
||||
+ ticket->server, NULL, NULL);
|
||||
+ if (ret)
|
||||
+ err(context, ret, "while verifying PAC client info");
|
||||
+
|
||||
+ /* We know there is only a PAC in this test's ticket. */
|
||||
+ authdata1 = ticket->enc_part2->authorization_data;
|
||||
+ ticket->enc_part2->authorization_data = NULL;
|
||||
+
|
||||
+ ret = krb5_kdc_sign_ticket(context, ticket->enc_part2, pac, sprinc,
|
||||
+ sprinc, &ticket_sig_server_key,
|
||||
+ &ticket_sig_krbtgt_key, FALSE);
|
||||
+ if (ret)
|
||||
+ err(context, ret, "while signing ticket");
|
||||
+
|
||||
+ authdata2 = ticket->enc_part2->authorization_data;
|
||||
+ assert(authdata2 != NULL);
|
||||
+ assert(authdata2[1] == NULL);
|
||||
+
|
||||
+ assert(authdata1[0]->length == authdata2[0]->length);
|
||||
+ assert(memcmp(authdata1[0]->contents, authdata2[0]->contents,
|
||||
+ authdata1[0]->length) == 0);
|
||||
+
|
||||
+ /* Test adding signatures to a new PAC. */
|
||||
+ ret = krb5_pac_init(context, &pac2);
|
||||
+ if (ret)
|
||||
+ err(context, ret, "krb5_pac_init");
|
||||
+
|
||||
+ ret = krb5_pac_get_types(context, pac, &len, &list);
|
||||
+ if (ret)
|
||||
+ err(context, ret, "krb5_pac_get_types");
|
||||
+
|
||||
+ for (i = 0; i < len; i++) {
|
||||
+ /* Skip server_cksum, privsvr_cksum, and ticket_cksum. */
|
||||
+ if (list[i] == 6 || list[i] == 7 || list[i] == 16)
|
||||
+ continue;
|
||||
+
|
||||
+ ret = krb5_pac_get_buffer(context, pac, list[i], &data);
|
||||
+ if (ret)
|
||||
+ err(context, ret, "krb5_pac_get_buffer");
|
||||
+
|
||||
+ ret = krb5_pac_add_buffer(context, pac2, list[i], &data);
|
||||
+ if (ret)
|
||||
+ err(context, ret, "krb5_pac_add_buffer");
|
||||
+
|
||||
+ krb5_free_data_contents(context, &data);
|
||||
+ }
|
||||
+ free(list);
|
||||
+
|
||||
+ krb5_free_authdata(context, authdata1);
|
||||
+ krb5_free_authdata(context, ticket->enc_part2->authorization_data);
|
||||
+ ticket->enc_part2->authorization_data = NULL;
|
||||
+
|
||||
+ ret = krb5_kdc_sign_ticket(context, ticket->enc_part2, pac2, sprinc, NULL,
|
||||
+ &ticket_sig_server_key, &ticket_sig_krbtgt_key,
|
||||
+ FALSE);
|
||||
+ if (ret)
|
||||
+ err(context, ret, "while signing ticket");
|
||||
+
|
||||
+ /* We can't compare the data since the order of the buffers may differ. */
|
||||
+ ret = krb5_kdc_verify_ticket(context, ticket->enc_part2, sprinc,
|
||||
+ &ticket_sig_server_key,
|
||||
+ &ticket_sig_krbtgt_key, &pac3);
|
||||
+ if (ret)
|
||||
+ err(context, ret, "while verifying ticket");
|
||||
+
|
||||
+ krb5_pac_free(context, pac);
|
||||
+ krb5_pac_free(context, pac2);
|
||||
+ krb5_pac_free(context, pac3);
|
||||
+ krb5_free_principal(context, sprinc);
|
||||
+ krb5_free_ticket(context, ticket);
|
||||
+}
|
||||
+
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
@@ -618,6 +798,8 @@ main(int argc, char **argv)
|
||||
if (ret)
|
||||
err(NULL, 0, "krb5_init_contex");
|
||||
|
||||
+ test_pac_ticket_signature(context);
|
||||
+
|
||||
ret = krb5_set_default_realm(context, "WIN2K3.THINKER.LOCAL");
|
||||
if (ret)
|
||||
err(context, ret, "krb5_set_default_realm");
|
||||
diff --git a/src/lib/krb5/libkrb5.exports b/src/lib/krb5/libkrb5.exports
|
||||
index 48ae46f5c4..28784ec67c 100644
|
||||
--- a/src/lib/krb5/libkrb5.exports
|
||||
+++ b/src/lib/krb5/libkrb5.exports
|
||||
@@ -462,6 +462,8 @@ krb5_is_permitted_enctype
|
||||
krb5_is_referral_realm
|
||||
krb5_is_thread_safe
|
||||
krb5_kdc_rep_decrypt_proc
|
||||
+krb5_kdc_sign_ticket
|
||||
+krb5_kdc_verify_ticket
|
||||
krb5_kt_add_entry
|
||||
krb5_kt_client_default
|
||||
krb5_kt_close
|
||||
diff --git a/src/lib/krb5_32.def b/src/lib/krb5_32.def
|
||||
index 209c6aaef5..8c3469a96c 100644
|
||||
--- a/src/lib/krb5_32.def
|
||||
+++ b/src/lib/krb5_32.def
|
||||
@@ -506,3 +506,6 @@ EXPORTS
|
||||
; new in 1.20
|
||||
krb5_marshal_credentials @472
|
||||
krb5_unmarshal_credentials @473
|
||||
+ k5_sname_compare @474 ; PRIVATE GSSAPI
|
||||
+ krb5_kdc_sign_ticket @475 ;
|
||||
+ krb5_kdc_verify_ticket @476 ;
|
||||
diff --git a/src/plugins/kdb/test/kdb_test.c b/src/plugins/kdb/test/kdb_test.c
|
||||
index 38d371cb86..7d033acae4 100644
|
||||
--- a/src/plugins/kdb/test/kdb_test.c
|
||||
+++ b/src/plugins/kdb/test/kdb_test.c
|
||||
@@ -675,7 +675,7 @@ verify_kdc_signature(krb5_context context, krb5_pac pac,
|
||||
int tries;
|
||||
|
||||
ret = krb5_pac_verify(context, pac, 0, NULL, NULL, tgt_key);
|
||||
- if (ret != KRB5KRB_AP_ERR_BAD_INTEGRITY)
|
||||
+ if (ret != KRB5KRB_AP_ERR_MODIFIED)
|
||||
return ret;
|
||||
|
||||
kvno = tgt->key_data[0].key_data_kvno - 1;
|
||||
@@ -684,7 +684,7 @@ verify_kdc_signature(krb5_context context, krb5_pac pac,
|
||||
for (tries = 2; tries > 0 && kvno > 0; tries--, kvno--) {
|
||||
ret = krb5_dbe_find_enctype(context, tgt, -1, -1, kvno, &kd);
|
||||
if (ret)
|
||||
- return KRB5KRB_AP_ERR_BAD_INTEGRITY;
|
||||
+ return KRB5KRB_AP_ERR_MODIFIED;
|
||||
ret = krb5_dbe_decrypt_key_data(context, NULL, kd, &old_key, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -697,7 +697,7 @@ verify_kdc_signature(krb5_context context, krb5_pac pac,
|
||||
kvno = kd->key_data_kvno - 1;
|
||||
}
|
||||
|
||||
- return KRB5KRB_AP_ERR_BAD_INTEGRITY;
|
||||
+ return KRB5KRB_AP_ERR_MODIFIED;
|
||||
}
|
||||
|
||||
static krb5_error_code
|
||||
--
|
||||
2.39.2
|
||||
|
169
SOURCES/Add-a-simple-DER-support-header.patch
Normal file
169
SOURCES/Add-a-simple-DER-support-header.patch
Normal file
@ -0,0 +1,169 @@
|
||||
From 5c2f409c360560c8b99926d6cf1a80419e758b22 Mon Sep 17 00:00:00 2001
|
||||
From: Greg Hudson <ghudson@mit.edu>
|
||||
Date: Tue, 7 Mar 2023 00:19:33 -0500
|
||||
Subject: [PATCH] Add a simple DER support header
|
||||
|
||||
(cherry picked from commit 548da160b52b25a106e9f6077d6a42c2c049586c)
|
||||
---
|
||||
src/include/k5-der.h | 149 +++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 149 insertions(+)
|
||||
create mode 100644 src/include/k5-der.h
|
||||
|
||||
diff --git a/src/include/k5-der.h b/src/include/k5-der.h
|
||||
new file mode 100644
|
||||
index 0000000000..b8371d9b4d
|
||||
--- /dev/null
|
||||
+++ b/src/include/k5-der.h
|
||||
@@ -0,0 +1,149 @@
|
||||
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||
+/* include/k5-der.h - Distinguished Encoding Rules (DER) declarations */
|
||||
+/*
|
||||
+ * Copyright (C) 2023 by the Massachusetts Institute of Technology.
|
||||
+ * All rights reserved.
|
||||
+ *
|
||||
+ * Redistribution and use in source and binary forms, with or without
|
||||
+ * modification, are permitted provided that the following conditions
|
||||
+ * are met:
|
||||
+ *
|
||||
+ * * Redistributions of source code must retain the above copyright
|
||||
+ * notice, this list of conditions and the following disclaimer.
|
||||
+ *
|
||||
+ * * Redistributions in binary form must reproduce the above copyright
|
||||
+ * notice, this list of conditions and the following disclaimer in
|
||||
+ * the documentation and/or other materials provided with the
|
||||
+ * distribution.
|
||||
+ *
|
||||
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
+ */
|
||||
+
|
||||
+/*
|
||||
+ * Most ASN.1 encoding and decoding is done using the table-driven framework in
|
||||
+ * libkrb5. When that is not an option, these helpers can be used to encode
|
||||
+ * and decode simple types.
|
||||
+ */
|
||||
+
|
||||
+#ifndef K5_DER_H
|
||||
+#define K5_DER_H
|
||||
+
|
||||
+#include <stdint.h>
|
||||
+#include <stdbool.h>
|
||||
+#include "k5-buf.h"
|
||||
+#include "k5-input.h"
|
||||
+
|
||||
+/* Return the number of bytes needed to encode len as a DER encoding length. */
|
||||
+static inline size_t
|
||||
+k5_der_len_len(size_t len)
|
||||
+{
|
||||
+ size_t llen;
|
||||
+
|
||||
+ if (len < 128)
|
||||
+ return 1;
|
||||
+ llen = 1;
|
||||
+ while (len > 0) {
|
||||
+ len >>= 8;
|
||||
+ llen++;
|
||||
+ }
|
||||
+ return llen;
|
||||
+}
|
||||
+
|
||||
+/* Return the number of bytes needed to encode a DER value (with identifier
|
||||
+ * byte and length) for a given contents length. */
|
||||
+static inline size_t
|
||||
+k5_der_value_len(size_t contents_len)
|
||||
+{
|
||||
+ return 1 + k5_der_len_len(contents_len) + contents_len;
|
||||
+}
|
||||
+
|
||||
+/* Add a DER identifier byte (composed by the caller, including the ASN.1
|
||||
+ * class, tag, and constructed bit) and length. */
|
||||
+static inline void
|
||||
+k5_der_add_taglen(struct k5buf *buf, uint8_t idbyte, size_t len)
|
||||
+{
|
||||
+ uint8_t *p;
|
||||
+ size_t llen = k5_der_len_len(len);
|
||||
+
|
||||
+ p = k5_buf_get_space(buf, 1 + llen);
|
||||
+ if (p == NULL)
|
||||
+ return;
|
||||
+ *p++ = idbyte;
|
||||
+ if (len < 128) {
|
||||
+ *p = len;
|
||||
+ } else {
|
||||
+ *p = 0x80 | (llen - 1);
|
||||
+ /* Encode the length bytes backwards so the most significant byte is
|
||||
+ * first. */
|
||||
+ p += llen;
|
||||
+ while (len > 0) {
|
||||
+ *--p = len & 0xFF;
|
||||
+ len >>= 8;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* Add a DER value (identifier byte, length, and contents). */
|
||||
+static inline void
|
||||
+k5_der_add_value(struct k5buf *buf, uint8_t idbyte, const void *contents,
|
||||
+ size_t len)
|
||||
+{
|
||||
+ k5_der_add_taglen(buf, idbyte, len);
|
||||
+ k5_buf_add_len(buf, contents, len);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * If the next byte in in matches idbyte and the subsequent DER length is
|
||||
+ * valid, advance in past the value, set *contents_out to the value contents,
|
||||
+ * and return true. Otherwise return false. Only set an error on in if the
|
||||
+ * next bytes matches idbyte but the ensuing length is invalid. contents_out
|
||||
+ * may be aliased to in; it will only be written to on successful decoding of a
|
||||
+ * value.
|
||||
+ */
|
||||
+static inline bool
|
||||
+k5_der_get_value(struct k5input *in, uint8_t idbyte,
|
||||
+ struct k5input *contents_out)
|
||||
+{
|
||||
+ uint8_t lenbyte, i;
|
||||
+ size_t len;
|
||||
+ const void *bytes;
|
||||
+
|
||||
+ /* Do nothing if in is empty or the next byte doesn't match idbyte. */
|
||||
+ if (in->status || in->len == 0 || *in->ptr != idbyte)
|
||||
+ return false;
|
||||
+
|
||||
+ /* Advance past the identifier byte and decode the length. */
|
||||
+ (void)k5_input_get_byte(in);
|
||||
+ lenbyte = k5_input_get_byte(in);
|
||||
+ if (lenbyte < 128) {
|
||||
+ len = lenbyte;
|
||||
+ } else {
|
||||
+ len = 0;
|
||||
+ for (i = 0; i < (lenbyte & 0x7F); i++) {
|
||||
+ if (len > (SIZE_MAX >> 8)) {
|
||||
+ k5_input_set_status(in, EOVERFLOW);
|
||||
+ return false;
|
||||
+ }
|
||||
+ len = (len << 8) | k5_input_get_byte(in);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ bytes = k5_input_get_bytes(in, len);
|
||||
+ if (bytes == NULL)
|
||||
+ return false;
|
||||
+ k5_input_init(contents_out, bytes, len);
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+#endif /* K5_DER_H */
|
||||
--
|
||||
2.45.1
|
||||
|
@ -1,4 +1,4 @@
|
||||
From 6af3fd382e99a9724413929af7eee7c86326ffd9 Mon Sep 17 00:00:00 2001
|
||||
From 8182f9f08b2593ff8749078ffd3daef9bf39a7fe Mon Sep 17 00:00:00 2001
|
||||
From: Isaac Boukris <iboukris@gmail.com>
|
||||
Date: Fri, 20 Mar 2020 00:17:28 +0100
|
||||
Subject: [PATCH] Add channel bindings tests
|
||||
|
@ -1,4 +1,4 @@
|
||||
From fe50c57f6428d7512868663bd226bdc9007148a9 Mon Sep 17 00:00:00 2001
|
||||
From 64f643a7f798c5528182dc068f15dca7b3f2d8a1 Mon Sep 17 00:00:00 2001
|
||||
From: Isaac Boukris <iboukris@gmail.com>
|
||||
Date: Tue, 10 Mar 2020 13:13:17 +0100
|
||||
Subject: [PATCH] Add client_aware_channel_bindings option
|
||||
@ -21,10 +21,10 @@ ticket: 8900
|
||||
3 files changed, 98 insertions(+), 86 deletions(-)
|
||||
|
||||
diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst
|
||||
index 1d2aa7f68..1d8ffc1e4 100644
|
||||
index 3a8b9cf47..315253e37 100644
|
||||
--- a/doc/admin/conf_files/krb5_conf.rst
|
||||
+++ b/doc/admin/conf_files/krb5_conf.rst
|
||||
@@ -383,6 +383,12 @@ The libdefaults section may contain any of the following relations:
|
||||
@@ -389,6 +389,12 @@ The libdefaults section may contain any of the following relations:
|
||||
credentials will fail if the client machine does not have a
|
||||
keytab. The default value is false.
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
From 2ea85d8228663c9592705a13edecbd4d3c70aac1 Mon Sep 17 00:00:00 2001
|
||||
From 9a9ab4b2cad1597cbafbae756483aefa6e36f1eb Mon Sep 17 00:00:00 2001
|
||||
From: Jiri Sasek <Jiri.Sasek@Oracle.COM>
|
||||
Date: Fri, 13 Mar 2020 19:02:58 +0100
|
||||
Subject: [PATCH] Add finalization safety check to com_err
|
||||
|
@ -0,0 +1,97 @@
|
||||
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
|
||||
|
||||
The libkrb5 ASN.1 decoder supports BER indefinite lengths. It
|
||||
computes the tag length using recursion; the lack of a recursion limit
|
||||
allows an attacker to overrun the stack and cause the process to
|
||||
crash. Reported by Demi Obenour.
|
||||
|
||||
CVE-2020-28196:
|
||||
|
||||
In MIT krb5 releases 1.11 and later, an unauthenticated attacker can
|
||||
cause a denial of service for any client or server to which it can
|
||||
send an ASN.1-encoded Kerberos message of sufficient length.
|
||||
|
||||
(cherry picked from commit 57415dda6cf04e73ffc3723be518eddfae599bfd)
|
||||
|
||||
ticket: 8959
|
||||
version_fixed: 1.18.3
|
||||
|
||||
(cherry picked from commit 207ad69c87cf1b5c047d6c0c0165e5afe29700a6)
|
||||
---
|
||||
src/lib/krb5/asn.1/asn1_encode.c | 16 +++++++++-------
|
||||
1 file changed, 9 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/src/lib/krb5/asn.1/asn1_encode.c b/src/lib/krb5/asn.1/asn1_encode.c
|
||||
index a160cf4fe..cd6b879f7 100644
|
||||
--- a/src/lib/krb5/asn.1/asn1_encode.c
|
||||
+++ b/src/lib/krb5/asn.1/asn1_encode.c
|
||||
@@ -356,7 +356,7 @@ make_tag(asn1buf *buf, const taginfo *t, size_t len)
|
||||
static krb5_error_code
|
||||
get_tag(const uint8_t *asn1, size_t len, taginfo *tag_out,
|
||||
const uint8_t **contents_out, size_t *clen_out,
|
||||
- const uint8_t **remainder_out, size_t *rlen_out)
|
||||
+ const uint8_t **remainder_out, size_t *rlen_out, int recursion)
|
||||
{
|
||||
krb5_error_code ret;
|
||||
uint8_t o;
|
||||
@@ -394,9 +394,11 @@ get_tag(const uint8_t *asn1, size_t len, taginfo *tag_out,
|
||||
/* Indefinite form (should not be present in DER, but we accept it). */
|
||||
if (tag_out->construction != CONSTRUCTED)
|
||||
return ASN1_MISMATCH_INDEF;
|
||||
+ if (recursion >= 32)
|
||||
+ return ASN1_OVERFLOW;
|
||||
p = asn1;
|
||||
while (!(len >= 2 && p[0] == 0 && p[1] == 0)) {
|
||||
- ret = get_tag(p, len, &t, &c, &clen, &p, &len);
|
||||
+ ret = get_tag(p, len, &t, &c, &clen, &p, &len, recursion + 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
@@ -613,7 +615,7 @@ split_der(asn1buf *buf, uint8_t *const *der, size_t len, taginfo *tag_out)
|
||||
const uint8_t *contents, *remainder;
|
||||
size_t clen, rlen;
|
||||
|
||||
- ret = get_tag(*der, len, tag_out, &contents, &clen, &remainder, &rlen);
|
||||
+ ret = get_tag(*der, len, tag_out, &contents, &clen, &remainder, &rlen, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (rlen != 0)
|
||||
@@ -1199,7 +1201,7 @@ decode_atype(const taginfo *t, const uint8_t *asn1, size_t len,
|
||||
const uint8_t *rem;
|
||||
size_t rlen;
|
||||
if (!tag->implicit) {
|
||||
- ret = get_tag(asn1, len, &inner_tag, &asn1, &len, &rem, &rlen);
|
||||
+ ret = get_tag(asn1, len, &inner_tag, &asn1, &len, &rem, &rlen, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
/* Note: we don't check rlen (it should be 0). */
|
||||
@@ -1420,7 +1422,7 @@ decode_sequence(const uint8_t *asn1, size_t len, const struct seq_info *seq,
|
||||
for (i = 0; i < seq->n_fields; i++) {
|
||||
if (len == 0)
|
||||
break;
|
||||
- ret = get_tag(asn1, len, &t, &contents, &clen, &asn1, &len);
|
||||
+ ret = get_tag(asn1, len, &t, &contents, &clen, &asn1, &len, 0);
|
||||
if (ret)
|
||||
goto error;
|
||||
/*
|
||||
@@ -1478,7 +1480,7 @@ decode_sequence_of(const uint8_t *asn1, size_t len,
|
||||
*seq_out = NULL;
|
||||
*count_out = 0;
|
||||
while (len > 0) {
|
||||
- ret = get_tag(asn1, len, &t, &contents, &clen, &asn1, &len);
|
||||
+ ret = get_tag(asn1, len, &t, &contents, &clen, &asn1, &len, 0);
|
||||
if (ret)
|
||||
goto error;
|
||||
if (!check_atype_tag(elemtype, &t)) {
|
||||
@@ -1584,7 +1586,7 @@ k5_asn1_full_decode(const krb5_data *code, const struct atype_info *a,
|
||||
|
||||
*retrep = NULL;
|
||||
ret = get_tag((uint8_t *)code->data, code->length, &t, &contents,
|
||||
- &clen, &remainder, &rlen);
|
||||
+ &clen, &remainder, &rlen, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
/* rlen should be 0, but we don't check it (and due to padding in
|
226
SOURCES/Add-request_timeout-configuration-parameter.patch
Normal file
226
SOURCES/Add-request_timeout-configuration-parameter.patch
Normal file
@ -0,0 +1,226 @@
|
||||
From 433dd85aaf8d9ed0e923c873f107995232b94422 Mon Sep 17 00:00:00 2001
|
||||
From: Greg Hudson <ghudson@mit.edu>
|
||||
Date: Thu, 26 Oct 2023 14:20:34 -0400
|
||||
Subject: [PATCH] Add request_timeout configuration parameter
|
||||
|
||||
Add a parameter to limit the total amount of time taken for a KDC or
|
||||
password change request.
|
||||
|
||||
ticket: 9106 (new)
|
||||
(cherry picked from commit 802318cda963456b3ed7856c836e89da891483be)
|
||||
---
|
||||
doc/admin/conf_files/krb5_conf.rst | 9 ++++++
|
||||
src/include/k5-int.h | 2 ++
|
||||
src/lib/krb5/krb/init_ctx.c | 14 +++++++-
|
||||
src/lib/krb5/os/sendto_kdc.c | 51 ++++++++++++++++++++----------
|
||||
4 files changed, 58 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst
|
||||
index 315253e378..557094f6a2 100644
|
||||
--- a/doc/admin/conf_files/krb5_conf.rst
|
||||
+++ b/doc/admin/conf_files/krb5_conf.rst
|
||||
@@ -357,6 +357,15 @@ The libdefaults section may contain any of the following relations:
|
||||
(:ref:`duration` string.) Sets the default renewable lifetime
|
||||
for initial ticket requests. The default value is 0.
|
||||
|
||||
+**request_timeout**
|
||||
+ (:ref:`duration` string.) Sets the maximum total time for KDC or
|
||||
+ password change requests. This timeout does not affect the
|
||||
+ intervals between requests, so setting a low timeout may result in
|
||||
+ fewer requests being attempted and/or some servers not being
|
||||
+ contacted. A value of 0 indicates no specific maximum, in which
|
||||
+ case requests will time out if no server responds after several
|
||||
+ tries. The default value is 0. (New in release 1.22.)
|
||||
+
|
||||
**spake_preauth_groups**
|
||||
A whitespace or comma-separated list of words which specifies the
|
||||
groups allowed for SPAKE preauthentication. The possible values
|
||||
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
|
||||
index 912aaedac4..9d5e41ca2c 100644
|
||||
--- a/src/include/k5-int.h
|
||||
+++ b/src/include/k5-int.h
|
||||
@@ -293,6 +293,7 @@ typedef unsigned char u_char;
|
||||
#define KRB5_CONF_SPAKE_PREAUTH_INDICATOR "spake_preauth_indicator"
|
||||
#define KRB5_CONF_SPAKE_PREAUTH_KDC_CHALLENGE "spake_preauth_kdc_challenge"
|
||||
#define KRB5_CONF_SPAKE_PREAUTH_GROUPS "spake_preauth_groups"
|
||||
+#define KRB5_CONF_REQUEST_TIMEOUT "request_timeout"
|
||||
#define KRB5_CONF_TICKET_LIFETIME "ticket_lifetime"
|
||||
#define KRB5_CONF_UDP_PREFERENCE_LIMIT "udp_preference_limit"
|
||||
#define KRB5_CONF_UNLOCKITER "unlockiter"
|
||||
@@ -1218,6 +1219,7 @@ struct _krb5_context {
|
||||
kdb5_dal_handle *dal_handle;
|
||||
/* allowable clock skew */
|
||||
krb5_deltat clockskew;
|
||||
+ krb5_deltat req_timeout;
|
||||
krb5_flags kdc_default_options;
|
||||
krb5_flags library_options;
|
||||
krb5_boolean profile_secure;
|
||||
diff --git a/src/lib/krb5/krb/init_ctx.c b/src/lib/krb5/krb/init_ctx.c
|
||||
index 9a4741fa64..1a6e0bf672 100644
|
||||
--- a/src/lib/krb5/krb/init_ctx.c
|
||||
+++ b/src/lib/krb5/krb/init_ctx.c
|
||||
@@ -163,7 +163,7 @@ krb5_init_context_profile(profile_t profile, krb5_flags flags,
|
||||
} seed_data;
|
||||
krb5_data seed;
|
||||
int tmp;
|
||||
- char *plugin_dir = NULL;
|
||||
+ char *plugin_dir = NULL, *timeout_str = NULL;
|
||||
|
||||
/* Verify some assumptions. If the assumptions hold and the
|
||||
compiler is optimizing, this should result in no code being
|
||||
@@ -257,6 +257,17 @@ krb5_init_context_profile(profile_t profile, krb5_flags flags,
|
||||
get_integer(ctx, KRB5_CONF_CLOCKSKEW, DEFAULT_CLOCKSKEW, &tmp);
|
||||
ctx->clockskew = tmp;
|
||||
|
||||
+ retval = profile_get_string(ctx->profile, KRB5_CONF_LIBDEFAULTS,
|
||||
+ KRB5_CONF_REQUEST_TIMEOUT, NULL, NULL,
|
||||
+ &timeout_str);
|
||||
+ if (retval)
|
||||
+ goto cleanup;
|
||||
+ if (timeout_str != NULL) {
|
||||
+ retval = krb5_string_to_deltat(timeout_str, &ctx->req_timeout);
|
||||
+ if (retval)
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
get_integer(ctx, KRB5_CONF_KDC_DEFAULT_OPTIONS, KDC_OPT_RENEWABLE_OK,
|
||||
&tmp);
|
||||
ctx->kdc_default_options = tmp;
|
||||
@@ -298,6 +309,7 @@ krb5_init_context_profile(profile_t profile, krb5_flags flags,
|
||||
|
||||
cleanup:
|
||||
profile_release_string(plugin_dir);
|
||||
+ profile_release_string(timeout_str);
|
||||
krb5_free_context(ctx);
|
||||
return retval;
|
||||
}
|
||||
diff --git a/src/lib/krb5/os/sendto_kdc.c b/src/lib/krb5/os/sendto_kdc.c
|
||||
index 8e4fcd2a38..f57117126e 100644
|
||||
--- a/src/lib/krb5/os/sendto_kdc.c
|
||||
+++ b/src/lib/krb5/os/sendto_kdc.c
|
||||
@@ -1390,34 +1390,41 @@ get_endtime(time_ms endtime, struct conn_state *conns)
|
||||
|
||||
static krb5_boolean
|
||||
service_fds(krb5_context context, struct select_state *selstate,
|
||||
- time_ms interval, struct conn_state *conns,
|
||||
+ time_ms interval, time_ms timeout, struct conn_state *conns,
|
||||
struct select_state *seltemp, const krb5_data *realm,
|
||||
int (*msg_handler)(krb5_context, const krb5_data *, void *),
|
||||
void *msg_handler_data, struct conn_state **winner_out)
|
||||
{
|
||||
int e, selret = 0;
|
||||
- time_ms endtime;
|
||||
+ time_ms curtime, interval_end, endtime;
|
||||
struct conn_state *state;
|
||||
|
||||
*winner_out = NULL;
|
||||
|
||||
- e = get_curtime_ms(&endtime);
|
||||
+ e = get_curtime_ms(&curtime);
|
||||
if (e)
|
||||
return TRUE;
|
||||
- endtime += interval;
|
||||
+ interval_end = curtime + interval;
|
||||
|
||||
e = 0;
|
||||
while (selstate->nfds > 0) {
|
||||
- e = cm_select_or_poll(selstate, get_endtime(endtime, conns),
|
||||
- seltemp, &selret);
|
||||
+ endtime = get_endtime(interval_end, conns);
|
||||
+ /* Don't wait longer than the whole request should last. */
|
||||
+ if (timeout && endtime > timeout)
|
||||
+ endtime = timeout;
|
||||
+ e = cm_select_or_poll(selstate, endtime, seltemp, &selret);
|
||||
if (e == EINTR)
|
||||
continue;
|
||||
if (e != 0)
|
||||
break;
|
||||
|
||||
- if (selret == 0)
|
||||
- /* Timeout, return to caller. */
|
||||
+ if (selret == 0) {
|
||||
+ /* We timed out. Stop if we hit the overall request timeout. */
|
||||
+ if (timeout && (get_curtime_ms(&curtime) || curtime >= timeout))
|
||||
+ return TRUE;
|
||||
+ /* Otherwise return to the caller to send the next request. */
|
||||
return FALSE;
|
||||
+ }
|
||||
|
||||
/* Got something on a socket, process it. */
|
||||
for (state = conns; state != NULL; state = state->next) {
|
||||
@@ -1490,7 +1497,7 @@ k5_sendto(krb5_context context, const krb5_data *message,
|
||||
void *msg_handler_data)
|
||||
{
|
||||
int pass;
|
||||
- time_ms delay;
|
||||
+ time_ms delay, timeout = 0;
|
||||
krb5_error_code retval;
|
||||
struct conn_state *conns = NULL, *state, **tailptr, *next, *winner;
|
||||
size_t s;
|
||||
@@ -1500,6 +1507,13 @@ k5_sendto(krb5_context context, const krb5_data *message,
|
||||
|
||||
*reply = empty_data();
|
||||
|
||||
+ if (context->req_timeout) {
|
||||
+ retval = get_curtime_ms(&timeout);
|
||||
+ if (retval)
|
||||
+ return retval;
|
||||
+ timeout += 1000 * context->req_timeout;
|
||||
+ }
|
||||
+
|
||||
/* One for use here, listing all our fds in use, and one for
|
||||
* temporary use in service_fds, for the fds of interest. */
|
||||
sel_state = malloc(2 * sizeof(*sel_state));
|
||||
@@ -1527,8 +1541,9 @@ k5_sendto(krb5_context context, const krb5_data *message,
|
||||
if (maybe_send(context, state, message, sel_state, realm,
|
||||
callback_info))
|
||||
continue;
|
||||
- done = service_fds(context, sel_state, 1000, conns, seltemp,
|
||||
- realm, msg_handler, msg_handler_data, &winner);
|
||||
+ done = service_fds(context, sel_state, 1000, timeout, conns,
|
||||
+ seltemp, realm, msg_handler, msg_handler_data,
|
||||
+ &winner);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1540,13 +1555,13 @@ k5_sendto(krb5_context context, const krb5_data *message,
|
||||
if (maybe_send(context, state, message, sel_state, realm,
|
||||
callback_info))
|
||||
continue;
|
||||
- done = service_fds(context, sel_state, 1000, conns, seltemp,
|
||||
+ done = service_fds(context, sel_state, 1000, timeout, conns, seltemp,
|
||||
realm, msg_handler, msg_handler_data, &winner);
|
||||
}
|
||||
|
||||
/* Wait for two seconds at the end of the first pass. */
|
||||
if (!done) {
|
||||
- done = service_fds(context, sel_state, 2000, conns, seltemp,
|
||||
+ done = service_fds(context, sel_state, 2000, timeout, conns, seltemp,
|
||||
realm, msg_handler, msg_handler_data, &winner);
|
||||
}
|
||||
|
||||
@@ -1557,15 +1572,17 @@ k5_sendto(krb5_context context, const krb5_data *message,
|
||||
if (maybe_send(context, state, message, sel_state, realm,
|
||||
callback_info))
|
||||
continue;
|
||||
- done = service_fds(context, sel_state, 1000, conns, seltemp,
|
||||
- realm, msg_handler, msg_handler_data, &winner);
|
||||
+ done = service_fds(context, sel_state, 1000, timeout, conns,
|
||||
+ seltemp, realm, msg_handler, msg_handler_data,
|
||||
+ &winner);
|
||||
if (sel_state->nfds == 0)
|
||||
break;
|
||||
}
|
||||
/* Wait for the delay backoff at the end of this pass. */
|
||||
if (!done) {
|
||||
- done = service_fds(context, sel_state, delay, conns, seltemp,
|
||||
- realm, msg_handler, msg_handler_data, &winner);
|
||||
+ done = service_fds(context, sel_state, delay, timeout, conns,
|
||||
+ seltemp, realm, msg_handler, msg_handler_data,
|
||||
+ &winner);
|
||||
}
|
||||
if (sel_state->nfds == 0)
|
||||
break;
|
||||
--
|
||||
2.44.0
|
||||
|
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 b4dba5a4c16b2585c38445e3067b5e3399f38a10 Mon Sep 17 00:00:00 2001
|
||||
From ab814a990f109357fc4b505169792f9d4d5b5155 Mon Sep 17 00:00:00 2001
|
||||
From: Greg Hudson <ghudson@mit.edu>
|
||||
Date: Mon, 24 Feb 2020 15:58:59 -0500
|
||||
Subject: [PATCH] Allow certauth modules to set hw-authent flag
|
||||
|
@ -1,4 +1,4 @@
|
||||
From abcbd3d12b0c92aa37384627edb6e1e6fad9b47a Mon Sep 17 00:00:00 2001
|
||||
From cbdae9a9dc2a6af5551d26b32c8d473e1e0ce773 Mon Sep 17 00:00:00 2001
|
||||
From: Greg Hudson <ghudson@mit.edu>
|
||||
Date: Mon, 30 Mar 2020 15:26:02 -0400
|
||||
Subject: [PATCH] Correctly import "service@" GSS host-based name
|
||||
|
@ -1,4 +1,4 @@
|
||||
From 640ba4fe0c5d7423431d649f8e5e6ac72341f4ab Mon Sep 17 00:00:00 2001
|
||||
From ff6cf2a0545d12a020572dd137fd22d1edc726e4 Mon Sep 17 00:00:00 2001
|
||||
From: Sumit Bose <sbose@redhat.com>
|
||||
Date: Fri, 28 Feb 2020 10:11:49 +0100
|
||||
Subject: [PATCH] Do expiration warnings for all init_creds APIs
|
||||
|
39
SOURCES/Document-k-option-in-kvno-1-synopsis.patch
Normal file
39
SOURCES/Document-k-option-in-kvno-1-synopsis.patch
Normal file
@ -0,0 +1,39 @@
|
||||
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
|
||||
|
||||
becd1ad6830b526d08ddaf5b2b6f213154c6446c attempted to unify the
|
||||
synopsis, option descriptions, and xusage(), but missed one option.
|
||||
|
||||
(cherry picked from commit d81e76d9ddab9e880bcf54eabf07119af91d28c7)
|
||||
(cherry picked from commit 588d964f59356373353dfd31d4fdcba95e508385)
|
||||
---
|
||||
doc/user/user_commands/kvno.rst | 1 +
|
||||
src/man/kvno.man | 1 +
|
||||
2 files changed, 2 insertions(+)
|
||||
|
||||
diff --git a/doc/user/user_commands/kvno.rst b/doc/user/user_commands/kvno.rst
|
||||
index 65c44e1c0..93a5132b2 100644
|
||||
--- a/doc/user/user_commands/kvno.rst
|
||||
+++ b/doc/user/user_commands/kvno.rst
|
||||
@@ -9,6 +9,7 @@ SYNOPSIS
|
||||
**kvno**
|
||||
[**-c** *ccache*]
|
||||
[**-e** *etype*]
|
||||
+[**-k** *keytab*]
|
||||
[**-q**]
|
||||
[**-u** | **-S** *sname*]
|
||||
[**-P**]
|
||||
diff --git a/src/man/kvno.man b/src/man/kvno.man
|
||||
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]]
|
||||
\fBkvno\fP
|
||||
[\fB\-c\fP \fIccache\fP]
|
||||
[\fB\-e\fP \fIetype\fP]
|
||||
+[\fB\-k\fP \fIkeytab\fP]
|
||||
[\fB\-q\fP]
|
||||
[\fB\-u\fP | \fB\-S\fP \fIsname\fP]
|
||||
[\fB\-P\fP]
|
@ -1,4 +1,4 @@
|
||||
From fa5d09798a56960c34f28296726ed4525e6950d9 Mon Sep 17 00:00:00 2001
|
||||
From e2cc7a04f0dbfbf1a8bc6cd70f639c56a203af28 Mon Sep 17 00:00:00 2001
|
||||
From: Greg Hudson <ghudson@mit.edu>
|
||||
Date: Mon, 23 Mar 2020 19:10:03 -0400
|
||||
Subject: [PATCH] Eliminate redundant PKINIT responder invocation
|
||||
|
34
SOURCES/End-connection-on-KDC_ERR_SVC_UNAVAILABLE.patch
Normal file
34
SOURCES/End-connection-on-KDC_ERR_SVC_UNAVAILABLE.patch
Normal file
@ -0,0 +1,34 @@
|
||||
From a68fba22588cc21dcd1dc28550529187dca58331 Mon Sep 17 00:00:00 2001
|
||||
From: Greg Hudson <ghudson@mit.edu>
|
||||
Date: Fri, 27 Oct 2023 00:44:53 -0400
|
||||
Subject: [PATCH] End connection on KDC_ERR_SVC_UNAVAILABLE
|
||||
|
||||
In sendto_kdc.c:service_fds(), if a message handler indicates that a
|
||||
message should be discarded, kill the connection so we don't continue
|
||||
waiting on it for more data.
|
||||
|
||||
ticket: 7899
|
||||
(cherry picked from commit ca80f64c786341d5871ae1de18142e62af64f7b9)
|
||||
---
|
||||
src/lib/krb5/os/sendto_kdc.c | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/lib/krb5/os/sendto_kdc.c b/src/lib/krb5/os/sendto_kdc.c
|
||||
index d76e24ccf0..8e4fcd2a38 100644
|
||||
--- a/src/lib/krb5/os/sendto_kdc.c
|
||||
+++ b/src/lib/krb5/os/sendto_kdc.c
|
||||
@@ -1435,7 +1435,10 @@ service_fds(krb5_context context, struct select_state *selstate,
|
||||
if (msg_handler != NULL) {
|
||||
krb5_data reply = make_data(state->in.buf, state->in.pos);
|
||||
|
||||
- stop = (msg_handler(context, &reply, msg_handler_data) != 0);
|
||||
+ if (!msg_handler(context, &reply, msg_handler_data)) {
|
||||
+ kill_conn(context, state, selstate);
|
||||
+ stop = 0;
|
||||
+ }
|
||||
}
|
||||
|
||||
if (stop) {
|
||||
--
|
||||
2.44.0
|
||||
|
258
SOURCES/Factor-out-PAC-checksum-verification.patch
Normal file
258
SOURCES/Factor-out-PAC-checksum-verification.patch
Normal file
@ -0,0 +1,258 @@
|
||||
From b0372e31b81321a820204450a35c7633caf1b7dd Mon Sep 17 00:00:00 2001
|
||||
From: Greg Hudson <ghudson@mit.edu>
|
||||
Date: Fri, 14 Jan 2022 02:05:58 -0500
|
||||
Subject: [PATCH] Factor out PAC checksum verification
|
||||
|
||||
Reduce code repetition in PAC checksum handling by adding a helper
|
||||
function. Remove the unnecessary prefix on several function names.
|
||||
---
|
||||
src/lib/krb5/krb/pac.c | 173 +++++++++++++----------------------------
|
||||
1 file changed, 55 insertions(+), 118 deletions(-)
|
||||
|
||||
diff --git a/src/lib/krb5/krb/pac.c b/src/lib/krb5/krb/pac.c
|
||||
index 6eb23d8090..2f6ad4e1df 100644
|
||||
--- a/src/lib/krb5/krb/pac.c
|
||||
+++ b/src/lib/krb5/krb/pac.c
|
||||
@@ -493,10 +493,8 @@ k5_pac_validate_client(krb5_context context,
|
||||
}
|
||||
|
||||
static krb5_error_code
|
||||
-k5_pac_zero_signature(krb5_context context,
|
||||
- const krb5_pac pac,
|
||||
- krb5_ui_4 type,
|
||||
- krb5_data *data)
|
||||
+zero_signature(krb5_context context, const krb5_pac pac, krb5_ui_4 type,
|
||||
+ krb5_data *data)
|
||||
{
|
||||
PAC_INFO_BUFFER *buffer = NULL;
|
||||
size_t i;
|
||||
@@ -530,151 +528,89 @@ k5_pac_zero_signature(krb5_context context,
|
||||
}
|
||||
|
||||
static krb5_error_code
|
||||
-k5_pac_verify_server_checksum(krb5_context context,
|
||||
- const krb5_pac pac,
|
||||
- const krb5_keyblock *server)
|
||||
+verify_checksum(krb5_context context, const krb5_pac pac, uint32_t buffer_type,
|
||||
+ const krb5_keyblock *key, krb5_keyusage usage,
|
||||
+ const krb5_data *data)
|
||||
{
|
||||
krb5_error_code ret;
|
||||
- krb5_data pac_data; /* PAC with zeroed checksums */
|
||||
+ krb5_data buffer;
|
||||
+ krb5_cksumtype cksumtype;
|
||||
krb5_checksum checksum;
|
||||
- krb5_data checksum_data;
|
||||
krb5_boolean valid;
|
||||
- krb5_octet *p;
|
||||
+ size_t cksumlen;
|
||||
|
||||
- ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_SERVER_CHECKSUM,
|
||||
- &checksum_data);
|
||||
+ ret = k5_pac_locate_buffer(context, pac, buffer_type, &buffer);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
-
|
||||
- if (checksum_data.length < PAC_SIGNATURE_DATA_LENGTH)
|
||||
+ if (buffer.length < PAC_SIGNATURE_DATA_LENGTH)
|
||||
return KRB5_BAD_MSIZE;
|
||||
|
||||
- p = (krb5_octet *)checksum_data.data;
|
||||
- checksum.checksum_type = load_32_le(p);
|
||||
- checksum.length = checksum_data.length - PAC_SIGNATURE_DATA_LENGTH;
|
||||
- checksum.contents = p + PAC_SIGNATURE_DATA_LENGTH;
|
||||
- if (checksum.checksum_type == CKSUMTYPE_SHA1)
|
||||
+ cksumtype = load_32_le(buffer.data);
|
||||
+ if (buffer_type == KRB5_PAC_SERVER_CHECKSUM && cksumtype == CKSUMTYPE_SHA1)
|
||||
return KRB5KDC_ERR_SUMTYPE_NOSUPP;
|
||||
- if (!krb5_c_is_keyed_cksum(checksum.checksum_type))
|
||||
+ if (!krb5_c_is_keyed_cksum(cksumtype))
|
||||
return KRB5KRB_ERR_GENERIC;
|
||||
|
||||
- pac_data.length = pac->data.length;
|
||||
- pac_data.data = k5memdup(pac->data.data, pac->data.length, &ret);
|
||||
- if (pac_data.data == NULL)
|
||||
- return ret;
|
||||
-
|
||||
- /* Zero out both checksum buffers */
|
||||
- ret = k5_pac_zero_signature(context, pac, KRB5_PAC_SERVER_CHECKSUM,
|
||||
- &pac_data);
|
||||
- if (ret != 0) {
|
||||
- free(pac_data.data);
|
||||
- return ret;
|
||||
- }
|
||||
-
|
||||
- ret = k5_pac_zero_signature(context, pac, KRB5_PAC_PRIVSVR_CHECKSUM,
|
||||
- &pac_data);
|
||||
- if (ret != 0) {
|
||||
- free(pac_data.data);
|
||||
+ /* There may be an RODCIdentifier trailer (see [MS-PAC] 2.8), so look up
|
||||
+ * the length of the checksum by its type. */
|
||||
+ ret = krb5_c_checksum_length(context, cksumtype, &cksumlen);
|
||||
+ if (ret)
|
||||
return ret;
|
||||
- }
|
||||
+ if (cksumlen > buffer.length - PAC_SIGNATURE_DATA_LENGTH)
|
||||
+ return KRB5_BAD_MSIZE;
|
||||
+ checksum.checksum_type = cksumtype;
|
||||
+ checksum.length = cksumlen;
|
||||
+ checksum.contents = (uint8_t *)buffer.data + PAC_SIGNATURE_DATA_LENGTH;
|
||||
|
||||
- ret = krb5_c_verify_checksum(context, server,
|
||||
- KRB5_KEYUSAGE_APP_DATA_CKSUM,
|
||||
- &pac_data, &checksum, &valid);
|
||||
+ ret = krb5_c_verify_checksum(context, key, usage, data, &checksum, &valid);
|
||||
+ return ret ? ret : (valid ? 0 : KRB5KRB_AP_ERR_MODIFIED);
|
||||
+}
|
||||
|
||||
- free(pac_data.data);
|
||||
+static krb5_error_code
|
||||
+verify_server_checksum(krb5_context context, const krb5_pac pac,
|
||||
+ const krb5_keyblock *server)
|
||||
+{
|
||||
+ krb5_error_code ret;
|
||||
+ krb5_data copy; /* PAC with zeroed checksums */
|
||||
|
||||
- if (ret != 0) {
|
||||
+ ret = krb5int_copy_data_contents(context, &pac->data, ©);
|
||||
+ if (ret)
|
||||
return ret;
|
||||
- }
|
||||
|
||||
- if (valid == FALSE)
|
||||
- ret = KRB5KRB_AP_ERR_MODIFIED;
|
||||
+ /* Zero out both checksum buffers */
|
||||
+ ret = zero_signature(context, pac, KRB5_PAC_SERVER_CHECKSUM, ©);
|
||||
+ if (ret)
|
||||
+ goto cleanup;
|
||||
+ ret = zero_signature(context, pac, KRB5_PAC_PRIVSVR_CHECKSUM, ©);
|
||||
+ if (ret)
|
||||
+ goto cleanup;
|
||||
+
|
||||
+ ret = verify_checksum(context, pac, KRB5_PAC_SERVER_CHECKSUM, server,
|
||||
+ KRB5_KEYUSAGE_APP_DATA_CKSUM, ©);
|
||||
|
||||
+cleanup:
|
||||
+ free(copy.data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static krb5_error_code
|
||||
-k5_pac_verify_kdc_checksum(krb5_context context,
|
||||
- const krb5_pac pac,
|
||||
- const krb5_keyblock *privsvr)
|
||||
+verify_kdc_checksum(krb5_context context, const krb5_pac pac,
|
||||
+ const krb5_keyblock *privsvr)
|
||||
{
|
||||
krb5_error_code ret;
|
||||
- krb5_data server_checksum, privsvr_checksum;
|
||||
- krb5_checksum checksum;
|
||||
- krb5_boolean valid;
|
||||
- krb5_octet *p;
|
||||
-
|
||||
- ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_PRIVSVR_CHECKSUM,
|
||||
- &privsvr_checksum);
|
||||
- if (ret != 0)
|
||||
- return ret;
|
||||
-
|
||||
- if (privsvr_checksum.length < PAC_SIGNATURE_DATA_LENGTH)
|
||||
- return KRB5_BAD_MSIZE;
|
||||
+ krb5_data server_checksum;
|
||||
|
||||
ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_SERVER_CHECKSUM,
|
||||
&server_checksum);
|
||||
- if (ret != 0)
|
||||
+ if (ret)
|
||||
return ret;
|
||||
-
|
||||
if (server_checksum.length < PAC_SIGNATURE_DATA_LENGTH)
|
||||
return KRB5_BAD_MSIZE;
|
||||
-
|
||||
- p = (krb5_octet *)privsvr_checksum.data;
|
||||
- checksum.checksum_type = load_32_le(p);
|
||||
- checksum.length = privsvr_checksum.length - PAC_SIGNATURE_DATA_LENGTH;
|
||||
- checksum.contents = p + PAC_SIGNATURE_DATA_LENGTH;
|
||||
- if (!krb5_c_is_keyed_cksum(checksum.checksum_type))
|
||||
- return KRB5KRB_ERR_GENERIC;
|
||||
-
|
||||
server_checksum.data += PAC_SIGNATURE_DATA_LENGTH;
|
||||
server_checksum.length -= PAC_SIGNATURE_DATA_LENGTH;
|
||||
|
||||
- ret = krb5_c_verify_checksum(context, privsvr,
|
||||
- KRB5_KEYUSAGE_APP_DATA_CKSUM,
|
||||
- &server_checksum, &checksum, &valid);
|
||||
- if (ret != 0)
|
||||
- return ret;
|
||||
-
|
||||
- if (valid == FALSE)
|
||||
- ret = KRB5KRB_AP_ERR_MODIFIED;
|
||||
-
|
||||
- return ret;
|
||||
-}
|
||||
-
|
||||
-static krb5_error_code
|
||||
-verify_ticket_checksum(krb5_context context, const krb5_pac pac,
|
||||
- const krb5_data *ticket, const krb5_keyblock *privsvr)
|
||||
-{
|
||||
- krb5_error_code ret;
|
||||
- krb5_checksum checksum;
|
||||
- krb5_data checksum_data;
|
||||
- krb5_boolean valid;
|
||||
- krb5_octet *p;
|
||||
-
|
||||
- ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_TICKET_CHECKSUM,
|
||||
- &checksum_data);
|
||||
- if (ret != 0)
|
||||
- return KRB5KRB_AP_ERR_MODIFIED;
|
||||
-
|
||||
- if (checksum_data.length < PAC_SIGNATURE_DATA_LENGTH)
|
||||
- return KRB5_BAD_MSIZE;
|
||||
-
|
||||
- p = (krb5_octet *)checksum_data.data;
|
||||
- checksum.checksum_type = load_32_le(p);
|
||||
- checksum.length = checksum_data.length - PAC_SIGNATURE_DATA_LENGTH;
|
||||
- checksum.contents = p + PAC_SIGNATURE_DATA_LENGTH;
|
||||
- if (!krb5_c_is_keyed_cksum(checksum.checksum_type))
|
||||
- return KRB5KRB_ERR_GENERIC;
|
||||
-
|
||||
- ret = krb5_c_verify_checksum(context, privsvr,
|
||||
- KRB5_KEYUSAGE_APP_DATA_CKSUM, ticket,
|
||||
- &checksum, &valid);
|
||||
- if (ret != 0)
|
||||
- return ret;
|
||||
-
|
||||
- return valid ? 0 : KRB5KRB_AP_ERR_MODIFIED;
|
||||
+ return verify_checksum(context, pac, KRB5_PAC_PRIVSVR_CHECKSUM, privsvr,
|
||||
+ KRB5_KEYUSAGE_APP_DATA_CKSUM, &server_checksum);
|
||||
}
|
||||
|
||||
/* Per MS-PAC 2.8.3, tickets encrypted to TGS and password change principals
|
||||
@@ -761,7 +697,8 @@ krb5_kdc_verify_ticket(krb5_context context, const krb5_enc_tkt_part *enc_tkt,
|
||||
if (ret)
|
||||
goto cleanup;
|
||||
|
||||
- ret = verify_ticket_checksum(context, pac, recoded_tkt, privsvr);
|
||||
+ ret = verify_checksum(context, pac, KRB5_PAC_TICKET_CHECKSUM, privsvr,
|
||||
+ KRB5_KEYUSAGE_APP_DATA_CKSUM, recoded_tkt);
|
||||
if (ret)
|
||||
goto cleanup;
|
||||
}
|
||||
@@ -804,13 +741,13 @@ krb5_pac_verify_ext(krb5_context context,
|
||||
krb5_error_code ret;
|
||||
|
||||
if (server != NULL) {
|
||||
- ret = k5_pac_verify_server_checksum(context, pac, server);
|
||||
+ ret = verify_server_checksum(context, pac, server);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (privsvr != NULL) {
|
||||
- ret = k5_pac_verify_kdc_checksum(context, pac, privsvr);
|
||||
+ ret = verify_kdc_checksum(context, pac, privsvr);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
--
|
||||
2.39.2
|
||||
|
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')
|
45
SOURCES/Fix-defcred-leak-in-krb5-gss_inquire_cred.patch
Normal file
45
SOURCES/Fix-defcred-leak-in-krb5-gss_inquire_cred.patch
Normal file
@ -0,0 +1,45 @@
|
||||
From 058dfbaed97c8e09ac4f3f7a1655b64ab3cf0144 Mon Sep 17 00:00:00 2001
|
||||
From: Greg Hudson <ghudson@mit.edu>
|
||||
Date: Wed, 21 Jul 2021 13:44:30 -0400
|
||||
Subject: [PATCH] Fix defcred leak in krb5 gss_inquire_cred()
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Commit 1cd2821c19b2b95e39d5fc2f451a035585a40fa5 altered the memory
|
||||
management of krb5_gss_inquire_cred(), introducing defcred to act as
|
||||
an owner pointer when the function must acquire a default credential.
|
||||
The commit neglected to update the code to release the default cred
|
||||
along the successful path. The old code does not trigger because
|
||||
cred_handle is now reassigned, so the default credential is leaked.
|
||||
|
||||
Reported by Pavel Březina.
|
||||
|
||||
(a minimal alternative to commit 593e16448e1af23eef74689afe06a7bcc86e79c7)
|
||||
|
||||
ticket: 9016
|
||||
version_fixed: 1.18.4
|
||||
|
||||
(cherry picked from commit b92be484630b38e26f5ee4bd67973fbd7627009c)
|
||||
---
|
||||
src/lib/gssapi/krb5/inq_cred.c | 4 +---
|
||||
1 file changed, 1 insertion(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/lib/gssapi/krb5/inq_cred.c b/src/lib/gssapi/krb5/inq_cred.c
|
||||
index a8f2541102..cd8384d08c 100644
|
||||
--- a/src/lib/gssapi/krb5/inq_cred.c
|
||||
+++ b/src/lib/gssapi/krb5/inq_cred.c
|
||||
@@ -197,9 +197,7 @@ krb5_gss_inquire_cred(minor_status, cred_handle, name, lifetime_ret,
|
||||
mechs = GSS_C_NO_OID_SET;
|
||||
}
|
||||
|
||||
- if (cred_handle == GSS_C_NO_CREDENTIAL)
|
||||
- krb5_gss_release_cred(minor_status, (gss_cred_id_t *)&cred);
|
||||
-
|
||||
+ krb5_gss_release_cred(minor_status, &defcred);
|
||||
krb5_free_context(context);
|
||||
*minor_status = 0;
|
||||
return((lifetime == 0)?GSS_S_CREDENTIALS_EXPIRED:GSS_S_COMPLETE);
|
||||
--
|
||||
2.44.0
|
||||
|
106
SOURCES/Fix-integer-overflows-in-PAC-parsing.patch
Normal file
106
SOURCES/Fix-integer-overflows-in-PAC-parsing.patch
Normal file
@ -0,0 +1,106 @@
|
||||
From d2477aa606ad590ca4097941bb6c2e1955b2a8c8 Mon Sep 17 00:00:00 2001
|
||||
From: Greg Hudson <ghudson@mit.edu>
|
||||
Date: Mon, 17 Oct 2022 20:25:11 -0400
|
||||
Subject: [PATCH] Fix integer overflows in PAC parsing
|
||||
|
||||
In krb5_parse_pac(), check for buffer counts large enough to threaten
|
||||
integer overflow in the header length and memory length calculations.
|
||||
Avoid potential integer overflows when checking the length of each
|
||||
buffer.
|
||||
|
||||
CVE-2022-42898:
|
||||
|
||||
In MIT krb5 releases 1.8 and later, an authenticated attacker may be
|
||||
able to cause a KDC or kadmind process to crash by reading beyond the
|
||||
bounds of allocated memory, creating a denial of service. A
|
||||
privileged attacker may similarly be able to cause a Kerberos or GSS
|
||||
application service to crash. On 32-bit platforms, an attacker can
|
||||
also cause insufficient memory to be allocated for the result,
|
||||
potentially leading to remote code execution in a KDC, kadmind, or GSS
|
||||
or Kerberos application server process. An attacker with the
|
||||
privileges of a cross-realm KDC may be able to extract secrets from
|
||||
the KDC process's memory by having them copied into the PAC of a new
|
||||
ticket.
|
||||
|
||||
ticket: 9074 (new)
|
||||
tags: pullup
|
||||
target_version: 1.20-next
|
||||
target_version: 1.19-next
|
||||
---
|
||||
src/lib/krb5/krb/pac.c | 9 +++++++--
|
||||
src/lib/krb5/krb/t_pac.c | 18 ++++++++++++++++++
|
||||
2 files changed, 25 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/lib/krb5/krb/pac.c b/src/lib/krb5/krb/pac.c
|
||||
index 950beda657..1b9ef12276 100644
|
||||
--- a/src/lib/krb5/krb/pac.c
|
||||
+++ b/src/lib/krb5/krb/pac.c
|
||||
@@ -27,6 +27,8 @@
|
||||
#include "k5-int.h"
|
||||
#include "authdata.h"
|
||||
|
||||
+#define MAX_BUFFERS 4096
|
||||
+
|
||||
/* draft-brezak-win2k-krb-authz-00 */
|
||||
|
||||
/*
|
||||
@@ -316,6 +318,9 @@ krb5_pac_parse(krb5_context context,
|
||||
if (version != 0)
|
||||
return EINVAL;
|
||||
|
||||
+ if (cbuffers < 1 || cbuffers > MAX_BUFFERS)
|
||||
+ return ERANGE;
|
||||
+
|
||||
header_len = PACTYPE_LENGTH + (cbuffers * PAC_INFO_BUFFER_LENGTH);
|
||||
if (len < header_len)
|
||||
return ERANGE;
|
||||
@@ -348,8 +353,8 @@ krb5_pac_parse(krb5_context context,
|
||||
krb5_pac_free(context, pac);
|
||||
return EINVAL;
|
||||
}
|
||||
- if (buffer->Offset < header_len ||
|
||||
- buffer->Offset + buffer->cbBufferSize > len) {
|
||||
+ if (buffer->Offset < header_len || buffer->Offset > len ||
|
||||
+ buffer->cbBufferSize > len - buffer->Offset) {
|
||||
krb5_pac_free(context, pac);
|
||||
return ERANGE;
|
||||
}
|
||||
diff --git a/src/lib/krb5/krb/t_pac.c b/src/lib/krb5/krb/t_pac.c
|
||||
index ee47152ee4..ccd165380d 100644
|
||||
--- a/src/lib/krb5/krb/t_pac.c
|
||||
+++ b/src/lib/krb5/krb/t_pac.c
|
||||
@@ -431,6 +431,16 @@ static const unsigned char s4u_pac_ent_xrealm[] = {
|
||||
0x8a, 0x81, 0x9c, 0x9c, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
+static const unsigned char fuzz1[] = {
|
||||
+ 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
|
||||
+ 0x06, 0xff, 0xff, 0xff, 0x00, 0x00, 0xf5
|
||||
+};
|
||||
+
|
||||
+static const unsigned char fuzz2[] = {
|
||||
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
|
||||
+ 0x20, 0x20
|
||||
+};
|
||||
+
|
||||
static const char *s4u_principal = "w2k8u@ACME.COM";
|
||||
static const char *s4u_enterprise = "w2k8u@abc@ACME.COM";
|
||||
|
||||
@@ -646,6 +656,14 @@ main(int argc, char **argv)
|
||||
krb5_free_principal(context, sep);
|
||||
}
|
||||
|
||||
+ /* Check problematic PACs found by fuzzing. */
|
||||
+ ret = krb5_pac_parse(context, fuzz1, sizeof(fuzz1), &pac);
|
||||
+ if (!ret)
|
||||
+ err(context, ret, "krb5_pac_parse should have failed");
|
||||
+ ret = krb5_pac_parse(context, fuzz2, sizeof(fuzz2), &pac);
|
||||
+ if (!ret)
|
||||
+ err(context, ret, "krb5_pac_parse should have failed");
|
||||
+
|
||||
/*
|
||||
* Test empty free
|
||||
*/
|
||||
--
|
||||
2.37.3
|
||||
|
@ -1,4 +1,4 @@
|
||||
From 7b5ed3cffcfe2bc21f3157e883b078983947a113 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
|
||||
|
205
SOURCES/Fix-two-unlikely-memory-leaks.patch
Normal file
205
SOURCES/Fix-two-unlikely-memory-leaks.patch
Normal file
@ -0,0 +1,205 @@
|
||||
From efb3acd20cbe6330439635a9f297b9dae8a0a5d3 Mon Sep 17 00:00:00 2001
|
||||
From: Greg Hudson <ghudson@mit.edu>
|
||||
Date: Tue, 5 Mar 2024 19:53:07 -0500
|
||||
Subject: [PATCH] Fix two unlikely memory leaks
|
||||
|
||||
In gss_krb5int_make_seal_token_v3(), one of the bounds checks (which
|
||||
could probably never be triggered) leaks plain.data. Fix this leak
|
||||
and use current practices for cleanup throughout the function.
|
||||
|
||||
In xmt_rmtcallres() (unused within the tree and likely elsewhere),
|
||||
store port_ptr into crp->port_ptr as soon as it is allocated;
|
||||
otherwise it could leak if the subsequent xdr_u_int32() operation
|
||||
fails.
|
||||
|
||||
(cherry picked from commit c5f9c816107f70139de11b38aa02db2f1774ee0d)
|
||||
---
|
||||
src/lib/gssapi/krb5/k5sealv3.c | 56 +++++++++++++++-------------------
|
||||
src/lib/rpc/pmap_rmt.c | 9 +++---
|
||||
2 files changed, 29 insertions(+), 36 deletions(-)
|
||||
|
||||
diff --git a/src/lib/gssapi/krb5/k5sealv3.c b/src/lib/gssapi/krb5/k5sealv3.c
|
||||
index 3b4f8cb837..e881eee835 100644
|
||||
--- a/src/lib/gssapi/krb5/k5sealv3.c
|
||||
+++ b/src/lib/gssapi/krb5/k5sealv3.c
|
||||
@@ -65,7 +65,7 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
|
||||
int conf_req_flag, int toktype)
|
||||
{
|
||||
size_t bufsize = 16;
|
||||
- unsigned char *outbuf = 0;
|
||||
+ unsigned char *outbuf = NULL;
|
||||
krb5_error_code err;
|
||||
int key_usage;
|
||||
unsigned char acceptor_flag;
|
||||
@@ -75,9 +75,13 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
|
||||
#endif
|
||||
size_t ec;
|
||||
unsigned short tok_id;
|
||||
- krb5_checksum sum;
|
||||
+ krb5_checksum sum = { 0 };
|
||||
krb5_key key;
|
||||
krb5_cksumtype cksumtype;
|
||||
+ krb5_data plain = empty_data();
|
||||
+
|
||||
+ token->value = NULL;
|
||||
+ token->length = 0;
|
||||
|
||||
acceptor_flag = ctx->initiate ? 0 : FLAG_SENDER_IS_ACCEPTOR;
|
||||
key_usage = (toktype == KG_TOK_WRAP_MSG
|
||||
@@ -107,14 +111,15 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
|
||||
#endif
|
||||
|
||||
if (toktype == KG_TOK_WRAP_MSG && conf_req_flag) {
|
||||
- krb5_data plain;
|
||||
krb5_enc_data cipher;
|
||||
size_t ec_max;
|
||||
size_t encrypt_size;
|
||||
|
||||
/* 300: Adds some slop. */
|
||||
- if (SIZE_MAX - 300 < message->length)
|
||||
- return ENOMEM;
|
||||
+ if (SIZE_MAX - 300 < message->length) {
|
||||
+ err = ENOMEM;
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
ec_max = SIZE_MAX - message->length - 300;
|
||||
if (ec_max > 0xffff)
|
||||
ec_max = 0xffff;
|
||||
@@ -126,20 +131,20 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
|
||||
#endif
|
||||
err = alloc_data(&plain, message->length + 16 + ec);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto cleanup;
|
||||
|
||||
/* Get size of ciphertext. */
|
||||
encrypt_size = krb5_encrypt_size(plain.length, key->keyblock.enctype);
|
||||
if (encrypt_size > SIZE_MAX / 2) {
|
||||
err = ENOMEM;
|
||||
- goto error;
|
||||
+ goto cleanup;
|
||||
}
|
||||
bufsize = 16 + encrypt_size;
|
||||
/* Allocate space for header plus encrypted data. */
|
||||
outbuf = gssalloc_malloc(bufsize);
|
||||
if (outbuf == NULL) {
|
||||
- free(plain.data);
|
||||
- return ENOMEM;
|
||||
+ err = ENOMEM;
|
||||
+ goto cleanup;
|
||||
}
|
||||
|
||||
/* TOK_ID */
|
||||
@@ -164,11 +169,8 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
|
||||
cipher.ciphertext.length = bufsize - 16;
|
||||
cipher.enctype = key->keyblock.enctype;
|
||||
err = krb5_k_encrypt(context, key, key_usage, 0, &plain, &cipher);
|
||||
- zap(plain.data, plain.length);
|
||||
- free(plain.data);
|
||||
- plain.data = 0;
|
||||
if (err)
|
||||
- goto error;
|
||||
+ goto cleanup;
|
||||
|
||||
/* Now that we know we're returning a valid token.... */
|
||||
ctx->seq_send++;
|
||||
@@ -181,7 +183,6 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
|
||||
/* If the rotate fails, don't worry about it. */
|
||||
#endif
|
||||
} else if (toktype == KG_TOK_WRAP_MSG && !conf_req_flag) {
|
||||
- krb5_data plain;
|
||||
size_t cksumsize;
|
||||
|
||||
/* Here, message is the application-supplied data; message2 is
|
||||
@@ -193,21 +194,19 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
|
||||
wrap_with_checksum:
|
||||
err = alloc_data(&plain, message->length + 16);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto cleanup;
|
||||
|
||||
err = krb5_c_checksum_length(context, cksumtype, &cksumsize);
|
||||
if (err)
|
||||
- goto error;
|
||||
+ goto cleanup;
|
||||
|
||||
assert(cksumsize <= 0xffff);
|
||||
|
||||
bufsize = 16 + message2->length + cksumsize;
|
||||
outbuf = gssalloc_malloc(bufsize);
|
||||
if (outbuf == NULL) {
|
||||
- free(plain.data);
|
||||
- plain.data = 0;
|
||||
err = ENOMEM;
|
||||
- goto error;
|
||||
+ goto cleanup;
|
||||
}
|
||||
|
||||
/* TOK_ID */
|
||||
@@ -239,23 +238,15 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
|
||||
if (message2->length)
|
||||
memcpy(outbuf + 16, message2->value, message2->length);
|
||||
|
||||
- sum.contents = outbuf + 16 + message2->length;
|
||||
- sum.length = cksumsize;
|
||||
-
|
||||
err = krb5_k_make_checksum(context, cksumtype, key,
|
||||
key_usage, &plain, &sum);
|
||||
- zap(plain.data, plain.length);
|
||||
- free(plain.data);
|
||||
- plain.data = 0;
|
||||
if (err) {
|
||||
zap(outbuf,bufsize);
|
||||
- goto error;
|
||||
+ goto cleanup;
|
||||
}
|
||||
if (sum.length != cksumsize)
|
||||
abort();
|
||||
memcpy(outbuf + 16 + message2->length, sum.contents, cksumsize);
|
||||
- krb5_free_checksum_contents(context, &sum);
|
||||
- sum.contents = 0;
|
||||
/* Now that we know we're actually generating the token... */
|
||||
ctx->seq_send++;
|
||||
|
||||
@@ -285,12 +276,13 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
|
||||
|
||||
token->value = outbuf;
|
||||
token->length = bufsize;
|
||||
- return 0;
|
||||
+ outbuf = NULL;
|
||||
+ err = 0;
|
||||
|
||||
-error:
|
||||
+cleanup:
|
||||
+ krb5_free_checksum_contents(context, &sum);
|
||||
+ zapfree(plain.data, plain.length);
|
||||
gssalloc_free(outbuf);
|
||||
- token->value = NULL;
|
||||
- token->length = 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
diff --git a/src/lib/rpc/pmap_rmt.c b/src/lib/rpc/pmap_rmt.c
|
||||
index 8c7e30c21a..0748af34a7 100644
|
||||
--- a/src/lib/rpc/pmap_rmt.c
|
||||
+++ b/src/lib/rpc/pmap_rmt.c
|
||||
@@ -160,11 +160,12 @@ xdr_rmtcallres(
|
||||
caddr_t port_ptr;
|
||||
|
||||
port_ptr = (caddr_t)(void *)crp->port_ptr;
|
||||
- if (xdr_reference(xdrs, &port_ptr, sizeof (uint32_t),
|
||||
- xdr_u_int32) && xdr_u_int32(xdrs, &crp->resultslen)) {
|
||||
- crp->port_ptr = (uint32_t *)(void *)port_ptr;
|
||||
+ if (!xdr_reference(xdrs, &port_ptr, sizeof (uint32_t),
|
||||
+ (xdrproc_t)xdr_u_int32))
|
||||
+ return (FALSE);
|
||||
+ crp->port_ptr = (uint32_t *)(void *)port_ptr;
|
||||
+ if (xdr_u_int32(xdrs, &crp->resultslen))
|
||||
return ((*(crp->xdr_results))(xdrs, crp->results_ptr));
|
||||
- }
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
--
|
||||
2.44.0
|
||||
|
@ -1,4 +1,4 @@
|
||||
From 117681ff995f7a271ded83ff4615e7945c72a942 Mon Sep 17 00:00:00 2001
|
||||
From 5a0833a3f3b1c44edd08425d98f682b96ad7a01e Mon Sep 17 00:00:00 2001
|
||||
From: Robbie Harwood <rharwood@redhat.com>
|
||||
Date: Thu, 14 May 2020 15:01:18 -0400
|
||||
Subject: [PATCH] Fix typo ("in in") in the ksu man page
|
||||
|
535
SOURCES/Fix-vulnerabilities-in-GSS-message-token-handling.patch
Normal file
535
SOURCES/Fix-vulnerabilities-in-GSS-message-token-handling.patch
Normal file
@ -0,0 +1,535 @@
|
||||
From c73e8ed9f89fdc709d15656b6431492d43de94ce Mon Sep 17 00:00:00 2001
|
||||
From: Greg Hudson <ghudson@mit.edu>
|
||||
Date: Fri, 14 Jun 2024 10:56:12 -0400
|
||||
Subject: [PATCH] Fix vulnerabilities in GSS message token handling
|
||||
|
||||
In gss_krb5int_unseal_token_v3() and gss_krb5int_unseal_v3_iov(),
|
||||
verify the Extra Count field of CFX wrap tokens against the encrypted
|
||||
header. Reported by Jacob Champion.
|
||||
|
||||
In gss_krb5int_unseal_token_v3(), check for a decrypted plaintext
|
||||
length too short to contain the encrypted header and extra count
|
||||
bytes. Reported by Jacob Champion.
|
||||
|
||||
In kg_unseal_iov_token(), separately track the header IOV length and
|
||||
complete token length when parsing the token's ASN.1 wrapper. This
|
||||
fix contains modified versions of functions from k5-der.h and
|
||||
util_token.c; this duplication will be cleaned up in a future commit.
|
||||
|
||||
CVE-2024-37370:
|
||||
|
||||
In MIT krb5 release 1.3 and later, an attacker can modify the
|
||||
plaintext Extra Count field of a confidential GSS krb5 wrap token,
|
||||
causing the unwrapped token to appear truncated to the application.
|
||||
|
||||
CVE-2024-37371:
|
||||
|
||||
In MIT krb5 release 1.3 and later, an attacker can cause invalid
|
||||
memory reads by sending message tokens with invalid length fields.
|
||||
|
||||
ticket: 9128 (new)
|
||||
tags: pullup
|
||||
target_version: 1.21-next
|
||||
|
||||
(cherry picked from commit b0a2f8a5365f2eec3e27d78907de9f9d2c80505a)
|
||||
---
|
||||
src/lib/gssapi/krb5/k5sealv3.c | 5 +
|
||||
src/lib/gssapi/krb5/k5sealv3iov.c | 3 +-
|
||||
src/lib/gssapi/krb5/k5unsealiov.c | 80 +++++++++-
|
||||
src/tests/gssapi/t_invalid.c | 233 +++++++++++++++++++++++++-----
|
||||
4 files changed, 275 insertions(+), 46 deletions(-)
|
||||
|
||||
diff --git a/src/lib/gssapi/krb5/k5sealv3.c b/src/lib/gssapi/krb5/k5sealv3.c
|
||||
index e881eee835..d3210c1107 100644
|
||||
--- a/src/lib/gssapi/krb5/k5sealv3.c
|
||||
+++ b/src/lib/gssapi/krb5/k5sealv3.c
|
||||
@@ -400,10 +400,15 @@ gss_krb5int_unseal_token_v3(krb5_context *contextptr,
|
||||
/* Don't use bodysize here! Use the fact that
|
||||
cipher.ciphertext.length has been adjusted to the
|
||||
correct length. */
|
||||
+ if (plain.length < 16 + ec) {
|
||||
+ free(plain.data);
|
||||
+ goto defective;
|
||||
+ }
|
||||
althdr = (unsigned char *)plain.data + plain.length - 16;
|
||||
if (load_16_be(althdr) != KG2_TOK_WRAP_MSG
|
||||
|| althdr[2] != ptr[2]
|
||||
|| althdr[3] != ptr[3]
|
||||
+ || load_16_be(althdr+4) != ec
|
||||
|| memcmp(althdr+8, ptr+8, 8)) {
|
||||
free(plain.data);
|
||||
goto defective;
|
||||
diff --git a/src/lib/gssapi/krb5/k5sealv3iov.c b/src/lib/gssapi/krb5/k5sealv3iov.c
|
||||
index 333ee124dd..f8e90c35b4 100644
|
||||
--- a/src/lib/gssapi/krb5/k5sealv3iov.c
|
||||
+++ b/src/lib/gssapi/krb5/k5sealv3iov.c
|
||||
@@ -402,9 +402,10 @@ gss_krb5int_unseal_v3_iov(krb5_context context,
|
||||
if (load_16_be(althdr) != KG2_TOK_WRAP_MSG
|
||||
|| althdr[2] != ptr[2]
|
||||
|| althdr[3] != ptr[3]
|
||||
+ || load_16_be(althdr + 4) != ec
|
||||
|| memcmp(althdr + 8, ptr + 8, 8) != 0) {
|
||||
*minor_status = 0;
|
||||
- return GSS_S_BAD_SIG;
|
||||
+ return GSS_S_DEFECTIVE_TOKEN;
|
||||
}
|
||||
} else {
|
||||
/* Verify checksum: note EC is checksum size here, not padding */
|
||||
diff --git a/src/lib/gssapi/krb5/k5unsealiov.c b/src/lib/gssapi/krb5/k5unsealiov.c
|
||||
index 3ce2a90ce9..6a6585d9af 100644
|
||||
--- a/src/lib/gssapi/krb5/k5unsealiov.c
|
||||
+++ b/src/lib/gssapi/krb5/k5unsealiov.c
|
||||
@@ -25,6 +25,7 @@
|
||||
*/
|
||||
|
||||
#include "k5-int.h"
|
||||
+#include "k5-der.h"
|
||||
#include "gssapiP_krb5.h"
|
||||
|
||||
static OM_uint32
|
||||
@@ -247,6 +248,73 @@ cleanup:
|
||||
return retval;
|
||||
}
|
||||
|
||||
+/* Similar to k5_der_get_value(), but output an unchecked content length
|
||||
+ * instead of a k5input containing the contents. */
|
||||
+static inline bool
|
||||
+get_der_tag(struct k5input *in, uint8_t idbyte, size_t *len_out)
|
||||
+{
|
||||
+ uint8_t lenbyte, i;
|
||||
+ size_t len;
|
||||
+
|
||||
+ /* Do nothing if in is empty or the next byte doesn't match idbyte. */
|
||||
+ if (in->status || in->len == 0 || *in->ptr != idbyte)
|
||||
+ return false;
|
||||
+
|
||||
+ /* Advance past the identifier byte and decode the length. */
|
||||
+ (void)k5_input_get_byte(in);
|
||||
+ lenbyte = k5_input_get_byte(in);
|
||||
+ if (lenbyte < 128) {
|
||||
+ len = lenbyte;
|
||||
+ } else {
|
||||
+ len = 0;
|
||||
+ for (i = 0; i < (lenbyte & 0x7F); i++) {
|
||||
+ if (len > (SIZE_MAX >> 8)) {
|
||||
+ k5_input_set_status(in, EOVERFLOW);
|
||||
+ return false;
|
||||
+ }
|
||||
+ len = (len << 8) | k5_input_get_byte(in);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (in->status)
|
||||
+ return false;
|
||||
+
|
||||
+ *len_out = len;
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Similar to g_verify_token_header() without toktype or flags, but do not read
|
||||
+ * more than *header_len bytes of ASN.1 wrapper, and on output set *header_len
|
||||
+ * to the remaining number of header bytes. Verify the outer DER tag's length
|
||||
+ * against token_len, which may be larger (but not smaller) than *header_len.
|
||||
+ */
|
||||
+static gss_int32
|
||||
+verify_detached_wrapper(const gss_OID_desc *mech, size_t *header_len,
|
||||
+ uint8_t **header_in, size_t token_len)
|
||||
+{
|
||||
+ struct k5input in, mech_der;
|
||||
+ gss_OID_desc toid;
|
||||
+ size_t len;
|
||||
+
|
||||
+ k5_input_init(&in, *header_in, *header_len);
|
||||
+
|
||||
+ if (get_der_tag(&in, 0x60, &len)) {
|
||||
+ if (len != token_len - (in.ptr - *header_in))
|
||||
+ return G_BAD_TOK_HEADER;
|
||||
+ if (!k5_der_get_value(&in, 0x06, &mech_der))
|
||||
+ return G_BAD_TOK_HEADER;
|
||||
+ toid.elements = (uint8_t *)mech_der.ptr;
|
||||
+ toid.length = mech_der.len;
|
||||
+ if (!g_OID_equal(&toid, mech))
|
||||
+ return G_WRONG_MECH;
|
||||
+ }
|
||||
+
|
||||
+ *header_in = (uint8_t *)in.ptr;
|
||||
+ *header_len = in.len;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Caller must provide TOKEN | DATA | PADDING | TRAILER, except
|
||||
* for DCE in which case it can just provide TOKEN | DATA (must
|
||||
@@ -267,8 +335,7 @@ kg_unseal_iov_token(OM_uint32 *minor_status,
|
||||
gss_iov_buffer_t header;
|
||||
gss_iov_buffer_t padding;
|
||||
gss_iov_buffer_t trailer;
|
||||
- size_t input_length;
|
||||
- unsigned int bodysize;
|
||||
+ size_t input_length, hlen;
|
||||
int toktype2;
|
||||
|
||||
header = kg_locate_header_iov(iov, iov_count, toktype);
|
||||
@@ -298,15 +365,14 @@ kg_unseal_iov_token(OM_uint32 *minor_status,
|
||||
input_length += trailer->buffer.length;
|
||||
}
|
||||
|
||||
- code = g_verify_token_header(ctx->mech_used,
|
||||
- &bodysize, &ptr, -1,
|
||||
- input_length, 0);
|
||||
+ hlen = header->buffer.length;
|
||||
+ code = verify_detached_wrapper(ctx->mech_used, &hlen, &ptr, input_length);
|
||||
if (code != 0) {
|
||||
*minor_status = code;
|
||||
return GSS_S_DEFECTIVE_TOKEN;
|
||||
}
|
||||
|
||||
- if (bodysize < 2) {
|
||||
+ if (hlen < 2) {
|
||||
*minor_status = (OM_uint32)G_BAD_TOK_HEADER;
|
||||
return GSS_S_DEFECTIVE_TOKEN;
|
||||
}
|
||||
@@ -314,7 +380,7 @@ kg_unseal_iov_token(OM_uint32 *minor_status,
|
||||
toktype2 = load_16_be(ptr);
|
||||
|
||||
ptr += 2;
|
||||
- bodysize -= 2;
|
||||
+ hlen -= 2;
|
||||
|
||||
switch (toktype2) {
|
||||
case KG2_TOK_MIC_MSG:
|
||||
diff --git a/src/tests/gssapi/t_invalid.c b/src/tests/gssapi/t_invalid.c
|
||||
index fb8fe55111..8192935099 100644
|
||||
--- a/src/tests/gssapi/t_invalid.c
|
||||
+++ b/src/tests/gssapi/t_invalid.c
|
||||
@@ -36,31 +36,41 @@
|
||||
*
|
||||
* 1. A pre-CFX wrap or MIC token processed with a CFX-only context causes a
|
||||
* null pointer dereference. (The token must use SEAL_ALG_NONE or it will
|
||||
- * be rejected.)
|
||||
+ * be rejected.) This vulnerability also applies to IOV unwrap.
|
||||
*
|
||||
- * 2. A pre-CFX wrap or MIC token with fewer than 24 bytes after the ASN.1
|
||||
+ * 2. A CFX wrap token with a different value of EC between the plaintext and
|
||||
+ * encrypted copies will be erroneously accepted, which allows a message
|
||||
+ * truncation attack. This vulnerability also applies to IOV unwrap.
|
||||
+ *
|
||||
+ * 3. A CFX wrap token with a plaintext length fewer than 16 bytes causes an
|
||||
+ * access before the beginning of the input buffer, possibly leading to a
|
||||
+ * crash.
|
||||
+ *
|
||||
+ * 4. A CFX wrap token with a plaintext EC value greater than the plaintext
|
||||
+ * length - 16 causes an integer underflow when computing the result length,
|
||||
+ * likely causing a crash.
|
||||
+ *
|
||||
+ * 5. An IOV unwrap operation will overrun the header buffer if an ASN.1
|
||||
+ * wrapper longer than the header buffer is present.
|
||||
+ *
|
||||
+ * 6. A pre-CFX wrap or MIC token with fewer than 24 bytes after the ASN.1
|
||||
* header causes an input buffer overrun, usually leading to either a segv
|
||||
* or a GSS_S_DEFECTIVE_TOKEN error due to garbage algorithm, filler, or
|
||||
- * sequence number values.
|
||||
+ * sequence number values. This vulnerability also applies to IOV unwrap.
|
||||
*
|
||||
- * 3. A pre-CFX wrap token with fewer than 16 + cksumlen bytes after the ASN.1
|
||||
+ * 7. A pre-CFX wrap token with fewer than 16 + cksumlen bytes after the ASN.1
|
||||
* header causes an integer underflow when computing the ciphertext length,
|
||||
* leading to an allocation error on 32-bit platforms or a segv on 64-bit
|
||||
* platforms. A pre-CFX MIC token of this size causes an input buffer
|
||||
* overrun when comparing the checksum, perhaps leading to a segv.
|
||||
*
|
||||
- * 4. A pre-CFX wrap token with fewer than conflen + padlen bytes in the
|
||||
+ * 8. A pre-CFX wrap token with fewer than conflen + padlen bytes in the
|
||||
* ciphertext (where padlen is the last byte of the decrypted ciphertext)
|
||||
* causes an integer underflow when computing the original message length,
|
||||
* leading to an allocation error.
|
||||
*
|
||||
- * 5. In the mechglue, truncated encapsulation in the initial context token can
|
||||
+ * 9. In the mechglue, truncated encapsulation in the initial context token can
|
||||
* cause input buffer overruns in gss_accept_sec_context().
|
||||
- *
|
||||
- * Vulnerabilities #1 and #2 also apply to IOV unwrap, although tokens with
|
||||
- * fewer than 16 bytes after the ASN.1 header will be rejected.
|
||||
- * Vulnerabilities #2 and #5 can only be robustly detected using a
|
||||
- * memory-checking environment such as valgrind.
|
||||
*/
|
||||
|
||||
#include "k5-int.h"
|
||||
@@ -97,17 +107,25 @@ struct test {
|
||||
}
|
||||
};
|
||||
|
||||
-/* Fake up enough of a CFX GSS context for gss_unwrap, using an AES key. */
|
||||
+static void *
|
||||
+ealloc(size_t len)
|
||||
+{
|
||||
+ void *ptr = calloc(len, 1);
|
||||
+
|
||||
+ if (ptr == NULL)
|
||||
+ abort();
|
||||
+ return ptr;
|
||||
+}
|
||||
+
|
||||
+/* Fake up enough of a CFX GSS context for gss_unwrap, using an AES key.
|
||||
+ * The context takes ownership of subkey. */
|
||||
static gss_ctx_id_t
|
||||
-make_fake_cfx_context()
|
||||
+make_fake_cfx_context(krb5_key subkey)
|
||||
{
|
||||
gss_union_ctx_id_t uctx;
|
||||
krb5_gss_ctx_id_t kgctx;
|
||||
- krb5_keyblock kb;
|
||||
|
||||
- kgctx = calloc(1, sizeof(*kgctx));
|
||||
- if (kgctx == NULL)
|
||||
- abort();
|
||||
+ kgctx = ealloc(sizeof(*kgctx));
|
||||
kgctx->established = 1;
|
||||
kgctx->proto = 1;
|
||||
if (g_seqstate_init(&kgctx->seqstate, 0, 0, 0, 0) != 0)
|
||||
@@ -116,15 +134,10 @@ make_fake_cfx_context()
|
||||
kgctx->sealalg = -1;
|
||||
kgctx->signalg = -1;
|
||||
|
||||
- kb.enctype = ENCTYPE_AES128_CTS_HMAC_SHA1_96;
|
||||
- kb.length = 16;
|
||||
- kb.contents = (unsigned char *)"1234567887654321";
|
||||
- if (krb5_k_create_key(NULL, &kb, &kgctx->subkey) != 0)
|
||||
- abort();
|
||||
+ kgctx->subkey = subkey;
|
||||
+ kgctx->cksumtype = CKSUMTYPE_HMAC_SHA1_96_AES128;
|
||||
|
||||
- uctx = calloc(1, sizeof(*uctx));
|
||||
- if (uctx == NULL)
|
||||
- abort();
|
||||
+ uctx = ealloc(sizeof(*uctx));
|
||||
uctx->mech_type = &mech_krb5;
|
||||
uctx->internal_ctx_id = (gss_ctx_id_t)kgctx;
|
||||
return (gss_ctx_id_t)uctx;
|
||||
@@ -138,9 +151,7 @@ make_fake_context(const struct test *test)
|
||||
krb5_gss_ctx_id_t kgctx;
|
||||
krb5_keyblock kb;
|
||||
|
||||
- kgctx = calloc(1, sizeof(*kgctx));
|
||||
- if (kgctx == NULL)
|
||||
- abort();
|
||||
+ kgctx = ealloc(sizeof(*kgctx));
|
||||
kgctx->established = 1;
|
||||
if (g_seqstate_init(&kgctx->seqstate, 0, 0, 0, 0) != 0)
|
||||
abort();
|
||||
@@ -162,9 +173,7 @@ make_fake_context(const struct test *test)
|
||||
if (krb5_k_create_key(NULL, &kb, &kgctx->enc) != 0)
|
||||
abort();
|
||||
|
||||
- uctx = calloc(1, sizeof(*uctx));
|
||||
- if (uctx == NULL)
|
||||
- abort();
|
||||
+ uctx = ealloc(sizeof(*uctx));
|
||||
uctx->mech_type = &mech_krb5;
|
||||
uctx->internal_ctx_id = (gss_ctx_id_t)kgctx;
|
||||
return (gss_ctx_id_t)uctx;
|
||||
@@ -194,9 +203,7 @@ make_token(unsigned char *token, size_t len, gss_buffer_t out)
|
||||
|
||||
assert(mech_krb5.length == 9);
|
||||
assert(len + 11 < 128);
|
||||
- wrapped = malloc(len + 13);
|
||||
- if (wrapped == NULL)
|
||||
- abort();
|
||||
+ wrapped = ealloc(len + 13);
|
||||
wrapped[0] = 0x60;
|
||||
wrapped[1] = len + 11;
|
||||
wrapped[2] = 0x06;
|
||||
@@ -207,6 +214,18 @@ make_token(unsigned char *token, size_t len, gss_buffer_t out)
|
||||
out->value = wrapped;
|
||||
}
|
||||
|
||||
+/* Create a 16-byte header for a CFX confidential wrap token to be processed by
|
||||
+ * the fake CFX context. */
|
||||
+static void
|
||||
+write_cfx_header(uint16_t ec, uint8_t *out)
|
||||
+{
|
||||
+ memset(out, 0, 16);
|
||||
+ store_16_be(KG2_TOK_WRAP_MSG, out);
|
||||
+ out[2] = FLAG_WRAP_CONFIDENTIAL;
|
||||
+ out[3] = 0xFF;
|
||||
+ store_16_be(ec, out + 4);
|
||||
+}
|
||||
+
|
||||
/* Unwrap a superficially valid RFC 1964 token with a CFX-only context, with
|
||||
* regular and IOV unwrap. */
|
||||
static void
|
||||
@@ -238,6 +257,134 @@ test_bogus_1964_token(gss_ctx_id_t ctx)
|
||||
free(in.value);
|
||||
}
|
||||
|
||||
+static void
|
||||
+test_cfx_altered_ec(gss_ctx_id_t ctx, krb5_key subkey)
|
||||
+{
|
||||
+ OM_uint32 major, minor;
|
||||
+ uint8_t tokbuf[128], plainbuf[24];
|
||||
+ krb5_data plain;
|
||||
+ krb5_enc_data cipher;
|
||||
+ gss_buffer_desc in, out;
|
||||
+ gss_iov_buffer_desc iov[2];
|
||||
+
|
||||
+ /* Construct a header with a plaintext EC value of 3. */
|
||||
+ write_cfx_header(3, tokbuf);
|
||||
+
|
||||
+ /* Encrypt a plaintext and a copy of the header with the EC value 0. */
|
||||
+ memcpy(plainbuf, "truncate", 8);
|
||||
+ memcpy(plainbuf + 8, tokbuf, 16);
|
||||
+ store_16_be(0, plainbuf + 12);
|
||||
+ plain = make_data(plainbuf, 24);
|
||||
+ cipher.ciphertext.data = (char *)tokbuf + 16;
|
||||
+ cipher.ciphertext.length = sizeof(tokbuf) - 16;
|
||||
+ cipher.enctype = subkey->keyblock.enctype;
|
||||
+ if (krb5_k_encrypt(NULL, subkey, KG_USAGE_INITIATOR_SEAL, NULL,
|
||||
+ &plain, &cipher) != 0)
|
||||
+ abort();
|
||||
+
|
||||
+ /* Verify that the token is rejected by gss_unwrap(). */
|
||||
+ in.value = tokbuf;
|
||||
+ in.length = 16 + cipher.ciphertext.length;
|
||||
+ major = gss_unwrap(&minor, ctx, &in, &out, NULL, NULL);
|
||||
+ if (major != GSS_S_DEFECTIVE_TOKEN)
|
||||
+ abort();
|
||||
+ (void)gss_release_buffer(&minor, &out);
|
||||
+
|
||||
+ /* Verify that the token is rejected by gss_unwrap_iov(). */
|
||||
+ iov[0].type = GSS_IOV_BUFFER_TYPE_STREAM;
|
||||
+ iov[0].buffer = in;
|
||||
+ iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
|
||||
+ major = gss_unwrap_iov(&minor, ctx, NULL, NULL, iov, 2);
|
||||
+ if (major != GSS_S_DEFECTIVE_TOKEN)
|
||||
+ abort();
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+test_cfx_short_plaintext(gss_ctx_id_t ctx, krb5_key subkey)
|
||||
+{
|
||||
+ OM_uint32 major, minor;
|
||||
+ uint8_t tokbuf[128], zerobyte = 0;
|
||||
+ krb5_data plain;
|
||||
+ krb5_enc_data cipher;
|
||||
+ gss_buffer_desc in, out;
|
||||
+
|
||||
+ write_cfx_header(0, tokbuf);
|
||||
+
|
||||
+ /* Encrypt a single byte, with no copy of the header. */
|
||||
+ plain = make_data(&zerobyte, 1);
|
||||
+ cipher.ciphertext.data = (char *)tokbuf + 16;
|
||||
+ cipher.ciphertext.length = sizeof(tokbuf) - 16;
|
||||
+ cipher.enctype = subkey->keyblock.enctype;
|
||||
+ if (krb5_k_encrypt(NULL, subkey, KG_USAGE_INITIATOR_SEAL, NULL,
|
||||
+ &plain, &cipher) != 0)
|
||||
+ abort();
|
||||
+
|
||||
+ /* Verify that the token is rejected by gss_unwrap(). */
|
||||
+ in.value = tokbuf;
|
||||
+ in.length = 16 + cipher.ciphertext.length;
|
||||
+ major = gss_unwrap(&minor, ctx, &in, &out, NULL, NULL);
|
||||
+ if (major != GSS_S_DEFECTIVE_TOKEN)
|
||||
+ abort();
|
||||
+ (void)gss_release_buffer(&minor, &out);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+test_cfx_large_ec(gss_ctx_id_t ctx, krb5_key subkey)
|
||||
+{
|
||||
+ OM_uint32 major, minor;
|
||||
+ uint8_t tokbuf[128] = { 0 }, plainbuf[20];
|
||||
+ krb5_data plain;
|
||||
+ krb5_enc_data cipher;
|
||||
+ gss_buffer_desc in, out;
|
||||
+
|
||||
+ /* Construct a header with an EC value of 5. */
|
||||
+ write_cfx_header(5, tokbuf);
|
||||
+
|
||||
+ /* Encrypt a 4-byte plaintext plus the header. */
|
||||
+ memcpy(plainbuf, "abcd", 4);
|
||||
+ memcpy(plainbuf + 4, tokbuf, 16);
|
||||
+ plain = make_data(plainbuf, 20);
|
||||
+ cipher.ciphertext.data = (char *)tokbuf + 16;
|
||||
+ cipher.ciphertext.length = sizeof(tokbuf) - 16;
|
||||
+ cipher.enctype = subkey->keyblock.enctype;
|
||||
+ if (krb5_k_encrypt(NULL, subkey, KG_USAGE_INITIATOR_SEAL, NULL,
|
||||
+ &plain, &cipher) != 0)
|
||||
+ abort();
|
||||
+
|
||||
+ /* Verify that the token is rejected by gss_unwrap(). */
|
||||
+ in.value = tokbuf;
|
||||
+ in.length = 16 + cipher.ciphertext.length;
|
||||
+ major = gss_unwrap(&minor, ctx, &in, &out, NULL, NULL);
|
||||
+ if (major != GSS_S_DEFECTIVE_TOKEN)
|
||||
+ abort();
|
||||
+ (void)gss_release_buffer(&minor, &out);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+test_iov_large_asn1_wrapper(gss_ctx_id_t ctx)
|
||||
+{
|
||||
+ OM_uint32 minor, major;
|
||||
+ uint8_t databuf[10] = { 0 };
|
||||
+ gss_iov_buffer_desc iov[2];
|
||||
+
|
||||
+ /*
|
||||
+ * In this IOV array, the header contains a DER tag with a dangling eight
|
||||
+ * bytes of length field. The data IOV indicates a total token length
|
||||
+ * sufficient to contain the length bytes.
|
||||
+ */
|
||||
+ iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER;
|
||||
+ iov[0].buffer.value = ealloc(2);
|
||||
+ iov[0].buffer.length = 2;
|
||||
+ memcpy(iov[0].buffer.value, "\x60\x88", 2);
|
||||
+ iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
|
||||
+ iov[1].buffer.value = databuf;
|
||||
+ iov[1].buffer.length = 10;
|
||||
+ major = gss_unwrap_iov(&minor, ctx, NULL, NULL, iov, 2);
|
||||
+ if (major != GSS_S_DEFECTIVE_TOKEN)
|
||||
+ abort();
|
||||
+ free(iov[0].buffer.value);
|
||||
+}
|
||||
+
|
||||
/* Process wrap and MIC tokens with incomplete headers. */
|
||||
static void
|
||||
test_short_header(gss_ctx_id_t ctx)
|
||||
@@ -387,9 +534,7 @@ try_accept(void *value, size_t len)
|
||||
gss_ctx_id_t ctx = GSS_C_NO_CONTEXT;
|
||||
|
||||
/* Copy the provided value to make input overruns more obvious. */
|
||||
- in.value = malloc(len);
|
||||
- if (in.value == NULL)
|
||||
- abort();
|
||||
+ in.value = ealloc(len);
|
||||
memcpy(in.value, value, len);
|
||||
in.length = len;
|
||||
(void)gss_accept_sec_context(&minor, &ctx, GSS_C_NO_CREDENTIAL, &in,
|
||||
@@ -424,11 +569,23 @@ test_short_encapsulation()
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
+ krb5_keyblock kb;
|
||||
+ krb5_key cfx_subkey;
|
||||
gss_ctx_id_t ctx;
|
||||
size_t i;
|
||||
|
||||
- ctx = make_fake_cfx_context();
|
||||
+ kb.enctype = ENCTYPE_AES128_CTS_HMAC_SHA1_96;
|
||||
+ kb.length = 16;
|
||||
+ kb.contents = (unsigned char *)"1234567887654321";
|
||||
+ if (krb5_k_create_key(NULL, &kb, &cfx_subkey) != 0)
|
||||
+ abort();
|
||||
+
|
||||
+ ctx = make_fake_cfx_context(cfx_subkey);
|
||||
test_bogus_1964_token(ctx);
|
||||
+ test_cfx_altered_ec(ctx, cfx_subkey);
|
||||
+ test_cfx_short_plaintext(ctx, cfx_subkey);
|
||||
+ test_cfx_large_ec(ctx, cfx_subkey);
|
||||
+ test_iov_large_asn1_wrapper(ctx);
|
||||
free_fake_context(ctx);
|
||||
|
||||
for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) {
|
||||
--
|
||||
2.45.1
|
||||
|
629
SOURCES/Generate-and-verify-message-MACs-in-libkrad.patch
Normal file
629
SOURCES/Generate-and-verify-message-MACs-in-libkrad.patch
Normal file
@ -0,0 +1,629 @@
|
||||
From aad00d346e5c7923287fc0016a37b49c4618d78e Mon Sep 17 00:00:00 2001
|
||||
From: Julien Rische <jrische@redhat.com>
|
||||
Date: Thu, 22 Aug 2024 17:15:50 +0200
|
||||
Subject: [PATCH] Generate and verify message MACs in libkrad
|
||||
|
||||
Implement some of the measures specified in
|
||||
draft-ietf-radext-deprecating-radius-03 for mitigating the BlastRADIUS
|
||||
attack (CVE-2024-3596):
|
||||
|
||||
* Include a Message-Authenticator MAC as the first attribute when
|
||||
generating a packet of type Access-Request, Access-Reject,
|
||||
Access-Accept, or Access-Challenge (sections 5.2.1 and 5.2.4), if
|
||||
the secret is non-empty. (An empty secret indicates the use of Unix
|
||||
domain socket transport.)
|
||||
|
||||
* Validate the Message-Authenticator MAC in received packets, if
|
||||
present.
|
||||
|
||||
FreeRADIUS enforces Message-Authenticator as of versions 3.2.5 and
|
||||
3.0.27. libkrad must generate Message-Authenticator attributes in
|
||||
order to remain compatible with these implementations.
|
||||
|
||||
[ghudson@mit.edu: adjusted style and naming; simplified some
|
||||
functions; edited commit message]
|
||||
|
||||
ticket: 9142 (new)
|
||||
tags: pullup
|
||||
target_version: 1.21-next
|
||||
|
||||
(cherry picked from commit 871125fea8ce0370a972bf65f7d1de63f619b06c)
|
||||
---
|
||||
src/include/k5-int.h | 5 +
|
||||
src/lib/crypto/krb/checksum_hmac_md5.c | 28 ++++
|
||||
src/lib/crypto/libk5crypto.exports | 1 +
|
||||
src/lib/krad/attr.c | 17 ++
|
||||
src/lib/krad/attrset.c | 59 +++++--
|
||||
src/lib/krad/internal.h | 7 +-
|
||||
src/lib/krad/packet.c | 206 +++++++++++++++++++++++--
|
||||
src/lib/krad/t_attrset.c | 2 +-
|
||||
src/lib/krad/t_daemon.py | 3 +-
|
||||
src/lib/krad/t_packet.c | 11 ++
|
||||
src/tests/t_otp.py | 3 +
|
||||
11 files changed, 311 insertions(+), 31 deletions(-)
|
||||
|
||||
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
|
||||
index 9d5e41ca2c..d062617268 100644
|
||||
--- a/src/include/k5-int.h
|
||||
+++ b/src/include/k5-int.h
|
||||
@@ -2415,4 +2415,9 @@ void k5_change_error_message_code(krb5_context ctx, krb5_error_code oldcode,
|
||||
#define k5_prependmsg krb5_prepend_error_message
|
||||
#define k5_wrapmsg krb5_wrap_error_message
|
||||
|
||||
+/* Generate an HMAC-MD5 keyed checksum as specified by RFC 2104. */
|
||||
+krb5_error_code
|
||||
+k5_hmac_md5(const krb5_data *key, const krb5_crypto_iov *data, size_t num_data,
|
||||
+ krb5_data *output);
|
||||
+
|
||||
#endif /* _KRB5_INT_H */
|
||||
diff --git a/src/lib/crypto/krb/checksum_hmac_md5.c b/src/lib/crypto/krb/checksum_hmac_md5.c
|
||||
index ec024f3966..a809388549 100644
|
||||
--- a/src/lib/crypto/krb/checksum_hmac_md5.c
|
||||
+++ b/src/lib/crypto/krb/checksum_hmac_md5.c
|
||||
@@ -92,3 +92,31 @@ cleanup:
|
||||
free(hash_iov);
|
||||
return ret;
|
||||
}
|
||||
+
|
||||
+krb5_error_code
|
||||
+k5_hmac_md5(const krb5_data *key, const krb5_crypto_iov *data, size_t num_data,
|
||||
+ krb5_data *output)
|
||||
+{
|
||||
+ krb5_error_code ret;
|
||||
+ const struct krb5_hash_provider *hash = &krb5int_hash_md5;
|
||||
+ krb5_keyblock keyblock = { 0 };
|
||||
+ krb5_data hashed_key;
|
||||
+ uint8_t hkeybuf[16];
|
||||
+ krb5_crypto_iov iov;
|
||||
+
|
||||
+ /* Hash the key if it is longer than the block size. */
|
||||
+ if (key->length > hash->blocksize) {
|
||||
+ hashed_key = make_data(hkeybuf, sizeof(hkeybuf));
|
||||
+ iov.flags = KRB5_CRYPTO_TYPE_DATA;
|
||||
+ iov.data = *key;
|
||||
+ ret = hash->hash(&iov, 1, &hashed_key);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ key = &hashed_key;
|
||||
+ }
|
||||
+
|
||||
+ keyblock.magic = KV5M_KEYBLOCK;
|
||||
+ keyblock.length = key->length;
|
||||
+ keyblock.contents = (uint8_t *)key->data;
|
||||
+ return krb5int_hmac_keyblock(hash, &keyblock, data, num_data, output);
|
||||
+}
|
||||
diff --git a/src/lib/crypto/libk5crypto.exports b/src/lib/crypto/libk5crypto.exports
|
||||
index 9db1813810..b4dcd29937 100644
|
||||
--- a/src/lib/crypto/libk5crypto.exports
|
||||
+++ b/src/lib/crypto/libk5crypto.exports
|
||||
@@ -107,3 +107,4 @@ krb5_c_prfplus
|
||||
krb5_c_derive_prfplus
|
||||
k5_enctype_to_ssf
|
||||
krb5int_c_deprecated_enctype
|
||||
+k5_hmac_md5
|
||||
diff --git a/src/lib/krad/attr.c b/src/lib/krad/attr.c
|
||||
index 42d354a3b5..65ed1d35e7 100644
|
||||
--- a/src/lib/krad/attr.c
|
||||
+++ b/src/lib/krad/attr.c
|
||||
@@ -125,6 +125,23 @@ static const attribute_record attributes[UCHAR_MAX] = {
|
||||
{"NAS-Port-Type", 4, 4, NULL, NULL},
|
||||
{"Port-Limit", 4, 4, NULL, NULL},
|
||||
{"Login-LAT-Port", 1, MAX_ATTRSIZE, NULL, NULL},
|
||||
+ {NULL, 0, 0, NULL, NULL}, /* Reserved for tunnelling */
|
||||
+ {NULL, 0, 0, NULL, NULL}, /* Reserved for tunnelling */
|
||||
+ {NULL, 0, 0, NULL, NULL}, /* Reserved for tunnelling */
|
||||
+ {NULL, 0, 0, NULL, NULL}, /* Reserved for tunnelling */
|
||||
+ {NULL, 0, 0, NULL, NULL}, /* Reserved for tunnelling */
|
||||
+ {NULL, 0, 0, NULL, NULL}, /* Reserved for tunnelling */
|
||||
+ {NULL, 0, 0, NULL, NULL}, /* Reserved for Apple Remote Access Protocol */
|
||||
+ {NULL, 0, 0, NULL, NULL}, /* Reserved for Apple Remote Access Protocol */
|
||||
+ {NULL, 0, 0, NULL, NULL}, /* Reserved for Apple Remote Access Protocol */
|
||||
+ {NULL, 0, 0, NULL, NULL}, /* Reserved for Apple Remote Access Protocol */
|
||||
+ {NULL, 0, 0, NULL, NULL}, /* Reserved for Apple Remote Access Protocol */
|
||||
+ {NULL, 0, 0, NULL, NULL}, /* Password-Retry */
|
||||
+ {NULL, 0, 0, NULL, NULL}, /* Prompt */
|
||||
+ {NULL, 0, 0, NULL, NULL}, /* Connect-Info */
|
||||
+ {NULL, 0, 0, NULL, NULL}, /* Configuration-Token */
|
||||
+ {NULL, 0, 0, NULL, NULL}, /* EAP-Message */
|
||||
+ {"Message-Authenticator", MD5_DIGEST_SIZE, MD5_DIGEST_SIZE, NULL, NULL},
|
||||
};
|
||||
|
||||
/* Encode User-Password attribute. */
|
||||
diff --git a/src/lib/krad/attrset.c b/src/lib/krad/attrset.c
|
||||
index 6ec031e320..e5457ebfd7 100644
|
||||
--- a/src/lib/krad/attrset.c
|
||||
+++ b/src/lib/krad/attrset.c
|
||||
@@ -164,15 +164,44 @@ krad_attrset_copy(const krad_attrset *set, krad_attrset **copy)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+/* Place an encoded attributes into outbuf at position *i. Increment *i by the
|
||||
+ * length of the encoding. */
|
||||
+static krb5_error_code
|
||||
+append_attr(krb5_context ctx, const char *secret,
|
||||
+ const uint8_t *auth, krad_attr type, const krb5_data *data,
|
||||
+ uint8_t outbuf[MAX_ATTRSETSIZE], size_t *i, krb5_boolean *is_fips)
|
||||
+{
|
||||
+ uint8_t buffer[MAX_ATTRSIZE];
|
||||
+ size_t attrlen;
|
||||
+ krb5_error_code retval;
|
||||
+
|
||||
+ retval = kr_attr_encode(ctx, secret, auth, type, data, buffer, &attrlen,
|
||||
+ is_fips);
|
||||
+ if (retval)
|
||||
+ return retval;
|
||||
+
|
||||
+ if (attrlen > MAX_ATTRSETSIZE - *i - 2)
|
||||
+ return EMSGSIZE;
|
||||
+
|
||||
+ outbuf[(*i)++] = type;
|
||||
+ outbuf[(*i)++] = attrlen + 2;
|
||||
+ memcpy(outbuf + *i, buffer, attrlen);
|
||||
+ *i += attrlen;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
krb5_error_code
|
||||
kr_attrset_encode(const krad_attrset *set, const char *secret,
|
||||
- const unsigned char *auth,
|
||||
+ const uint8_t *auth, krb5_boolean add_msgauth,
|
||||
unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen,
|
||||
krb5_boolean *is_fips)
|
||||
{
|
||||
- unsigned char buffer[MAX_ATTRSIZE];
|
||||
krb5_error_code retval;
|
||||
- size_t i = 0, attrlen;
|
||||
+ krad_attr msgauth_type = krad_attr_name2num("Message-Authenticator");
|
||||
+ const uint8_t zeroes[MD5_DIGEST_SIZE] = { 0 };
|
||||
+ krb5_data zerodata;
|
||||
+ size_t i = 0;
|
||||
attr *a;
|
||||
|
||||
if (set == NULL) {
|
||||
@@ -180,19 +209,21 @@ kr_attrset_encode(const krad_attrset *set, const char *secret,
|
||||
return 0;
|
||||
}
|
||||
|
||||
- K5_TAILQ_FOREACH(a, &set->list, list) {
|
||||
- retval = kr_attr_encode(set->ctx, secret, auth, a->type, &a->attr,
|
||||
- buffer, &attrlen, is_fips);
|
||||
- if (retval != 0)
|
||||
+ if (add_msgauth) {
|
||||
+ /* Encode Message-Authenticator as the first attribute, per
|
||||
+ * draft-ietf-radext-deprecating-radius-03 section 5.2. */
|
||||
+ zerodata = make_data((uint8_t *)zeroes, MD5_DIGEST_SIZE);
|
||||
+ retval = append_attr(set->ctx, secret, auth, msgauth_type, &zerodata,
|
||||
+ outbuf, &i, is_fips);
|
||||
+ if (retval)
|
||||
return retval;
|
||||
+ }
|
||||
|
||||
- if (i + attrlen + 2 > MAX_ATTRSETSIZE)
|
||||
- return EMSGSIZE;
|
||||
-
|
||||
- outbuf[i++] = a->type;
|
||||
- outbuf[i++] = attrlen + 2;
|
||||
- memcpy(&outbuf[i], buffer, attrlen);
|
||||
- i += attrlen;
|
||||
+ K5_TAILQ_FOREACH(a, &set->list, list) {
|
||||
+ retval = append_attr(set->ctx, secret, auth, a->type, &a->attr,
|
||||
+ outbuf, &i, is_fips);
|
||||
+ if (retval)
|
||||
+ return retval;
|
||||
}
|
||||
|
||||
*outlen = i;
|
||||
diff --git a/src/lib/krad/internal.h b/src/lib/krad/internal.h
|
||||
index b086598fb2..f3e4a1d8d3 100644
|
||||
--- a/src/lib/krad/internal.h
|
||||
+++ b/src/lib/krad/internal.h
|
||||
@@ -45,6 +45,8 @@
|
||||
#define UCHAR_MAX 255
|
||||
#endif
|
||||
|
||||
+#define MD5_DIGEST_SIZE 16
|
||||
+
|
||||
/* RFC 2865 */
|
||||
#define MAX_ATTRSIZE (UCHAR_MAX - 2)
|
||||
#define MAX_ATTRSETSIZE (KRAD_PACKET_SIZE_MAX - 20)
|
||||
@@ -75,10 +77,11 @@ kr_attr_decode(krb5_context ctx, const char *secret, const unsigned char *auth,
|
||||
krad_attr type, const krb5_data *in,
|
||||
unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen);
|
||||
|
||||
-/* Encode the attributes into the buffer. */
|
||||
+/* Encode set into outbuf. If add_msgauth is true, include a zeroed
|
||||
+ * Message-Authenticator as the first attribute. */
|
||||
krb5_error_code
|
||||
kr_attrset_encode(const krad_attrset *set, const char *secret,
|
||||
- const unsigned char *auth,
|
||||
+ const uint8_t *auth, krb5_boolean add_msgauth,
|
||||
unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen,
|
||||
krb5_boolean *is_fips);
|
||||
|
||||
diff --git a/src/lib/krad/packet.c b/src/lib/krad/packet.c
|
||||
index fc2d248001..257bbc6345 100644
|
||||
--- a/src/lib/krad/packet.c
|
||||
+++ b/src/lib/krad/packet.c
|
||||
@@ -36,6 +36,7 @@
|
||||
typedef unsigned char uchar;
|
||||
|
||||
/* RFC 2865 */
|
||||
+#define MSGAUTH_SIZE (2 + MD5_DIGEST_SIZE)
|
||||
#define OFFSET_CODE 0
|
||||
#define OFFSET_ID 1
|
||||
#define OFFSET_LENGTH 2
|
||||
@@ -222,6 +223,106 @@ packet_set_attrset(krb5_context ctx, const char *secret, krad_packet *pkt)
|
||||
return kr_attrset_decode(ctx, &tmp, secret, pkt_auth(pkt), &pkt->attrset);
|
||||
}
|
||||
|
||||
+/* Determine if a packet requires a Message-Authenticator attribute. */
|
||||
+static inline krb5_boolean
|
||||
+requires_msgauth(const char *secret, krad_code code)
|
||||
+{
|
||||
+ /* If no secret is provided, assume that the transport is a UNIX socket.
|
||||
+ * Message-Authenticator is required only on UDP and TCP connections. */
|
||||
+ if (*secret == '\0')
|
||||
+ return FALSE;
|
||||
+
|
||||
+ /*
|
||||
+ * Per draft-ietf-radext-deprecating-radius-03 sections 5.2.1 and 5.2.4,
|
||||
+ * Message-Authenticator is required in Access-Request packets and all
|
||||
+ * potential responses when UDP or TCP transport is used.
|
||||
+ */
|
||||
+ return code == krad_code_name2num("Access-Request") ||
|
||||
+ code == krad_code_name2num("Access-Reject") ||
|
||||
+ code == krad_code_name2num("Access-Accept") ||
|
||||
+ code == krad_code_name2num("Access-Challenge");
|
||||
+}
|
||||
+
|
||||
+/* Check if the packet has a Message-Authenticator attribute. */
|
||||
+static inline krb5_boolean
|
||||
+has_pkt_msgauth(const krad_packet *pkt)
|
||||
+{
|
||||
+ krad_attr msgauth_type = krad_attr_name2num("Message-Authenticator");
|
||||
+
|
||||
+ return krad_attrset_get(pkt->attrset, msgauth_type, 0) != NULL;
|
||||
+}
|
||||
+
|
||||
+/* Return the beginning of the Message-Authenticator attribute in pkt, or NULL
|
||||
+ * if no such attribute is present. */
|
||||
+static const uint8_t *
|
||||
+lookup_msgauth_addr(const krad_packet *pkt)
|
||||
+{
|
||||
+ krad_attr msgauth_type = krad_attr_name2num("Message-Authenticator");
|
||||
+ size_t i;
|
||||
+ uint8_t *p;
|
||||
+
|
||||
+ i = OFFSET_ATTR;
|
||||
+ while (i + 2 < pkt->pkt.length) {
|
||||
+ p = (uint8_t *)offset(&pkt->pkt, i);
|
||||
+ if (msgauth_type == *p)
|
||||
+ return p;
|
||||
+ i += p[1];
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Calculate the message authenticator MAC for pkt as specified in RFC 2869
|
||||
+ * section 5.14, placing the result in mac_out. Use the provided authenticator
|
||||
+ * auth, which may be from pkt or from a corresponding request.
|
||||
+ */
|
||||
+static krb5_error_code
|
||||
+calculate_mac(const char *secret, const krad_packet *pkt,
|
||||
+ const uint8_t auth[AUTH_FIELD_SIZE],
|
||||
+ uint8_t mac_out[MD5_DIGEST_SIZE])
|
||||
+{
|
||||
+ uint8_t zeroed_msgauth[MSGAUTH_SIZE];
|
||||
+ krad_attr msgauth_type = krad_attr_name2num("Message-Authenticator");
|
||||
+ const uint8_t *msgauth_attr, *msgauth_end, *pkt_end;
|
||||
+ krb5_crypto_iov input[5];
|
||||
+ krb5_data ksecr, mac;
|
||||
+
|
||||
+ msgauth_attr = lookup_msgauth_addr(pkt);
|
||||
+ if (msgauth_attr == NULL)
|
||||
+ return EINVAL;
|
||||
+ msgauth_end = msgauth_attr + MSGAUTH_SIZE;
|
||||
+ pkt_end = (const uint8_t *)pkt->pkt.data + pkt->pkt.length;
|
||||
+
|
||||
+ /* Read code, id, and length from the packet. */
|
||||
+ input[0].flags = KRB5_CRYPTO_TYPE_DATA;
|
||||
+ input[0].data = make_data(pkt->pkt.data, OFFSET_AUTH);
|
||||
+
|
||||
+ /* Read the provided authenticator. */
|
||||
+ input[1].flags = KRB5_CRYPTO_TYPE_DATA;
|
||||
+ input[1].data = make_data((uint8_t *)auth, AUTH_FIELD_SIZE);
|
||||
+
|
||||
+ /* Read any attributes before Message-Authenticator. */
|
||||
+ input[2].flags = KRB5_CRYPTO_TYPE_DATA;
|
||||
+ input[2].data = make_data(pkt_attr(pkt), msgauth_attr - pkt_attr(pkt));
|
||||
+
|
||||
+ /* Read Message-Authenticator with the data bytes all set to zero, per RFC
|
||||
+ * 2869 section 5.14. */
|
||||
+ zeroed_msgauth[0] = msgauth_type;
|
||||
+ zeroed_msgauth[1] = MSGAUTH_SIZE;
|
||||
+ memset(zeroed_msgauth + 2, 0, MD5_DIGEST_SIZE);
|
||||
+ input[3].flags = KRB5_CRYPTO_TYPE_DATA;
|
||||
+ input[3].data = make_data(zeroed_msgauth, MSGAUTH_SIZE);
|
||||
+
|
||||
+ /* Read any attributes after Message-Authenticator. */
|
||||
+ input[4].flags = KRB5_CRYPTO_TYPE_DATA;
|
||||
+ input[4].data = make_data((uint8_t *)msgauth_end, pkt_end - msgauth_end);
|
||||
+
|
||||
+ mac = make_data(mac_out, MD5_DIGEST_SIZE);
|
||||
+ ksecr = string2data((char *)secret);
|
||||
+ return k5_hmac_md5(&ksecr, input, 5, &mac);
|
||||
+}
|
||||
+
|
||||
ssize_t
|
||||
krad_packet_bytes_needed(const krb5_data *buffer)
|
||||
{
|
||||
@@ -255,6 +356,7 @@ krad_packet_new_request(krb5_context ctx, const char *secret, krad_code code,
|
||||
krad_packet *pkt;
|
||||
uchar id;
|
||||
size_t attrset_len;
|
||||
+ krb5_boolean msgauth_required;
|
||||
|
||||
pkt = packet_new();
|
||||
if (pkt == NULL) {
|
||||
@@ -274,9 +376,13 @@ krad_packet_new_request(krb5_context ctx, const char *secret, krad_code code,
|
||||
if (retval != 0)
|
||||
goto error;
|
||||
|
||||
+ /* Determine if Message-Authenticator is required. */
|
||||
+ msgauth_required = (*secret != '\0' &&
|
||||
+ code == krad_code_name2num("Access-Request"));
|
||||
+
|
||||
/* Encode the attributes. */
|
||||
- retval = kr_attrset_encode(set, secret, pkt_auth(pkt), pkt_attr(pkt),
|
||||
- &attrset_len, &pkt->is_fips);
|
||||
+ retval = kr_attrset_encode(set, secret, pkt_auth(pkt), msgauth_required,
|
||||
+ pkt_attr(pkt), &attrset_len, &pkt->is_fips);
|
||||
if (retval != 0)
|
||||
goto error;
|
||||
|
||||
@@ -285,6 +391,13 @@ krad_packet_new_request(krb5_context ctx, const char *secret, krad_code code,
|
||||
pkt_code_set(pkt, code);
|
||||
pkt_len_set(pkt, pkt->pkt.length);
|
||||
|
||||
+ if (msgauth_required) {
|
||||
+ /* Calculate and set the Message-Authenticator MAC. */
|
||||
+ retval = calculate_mac(secret, pkt, pkt_auth(pkt), pkt_attr(pkt) + 2);
|
||||
+ if (retval != 0)
|
||||
+ goto error;
|
||||
+ }
|
||||
+
|
||||
/* Copy the attrset for future use. */
|
||||
retval = packet_set_attrset(ctx, secret, pkt);
|
||||
if (retval != 0)
|
||||
@@ -307,14 +420,19 @@ krad_packet_new_response(krb5_context ctx, const char *secret, krad_code code,
|
||||
krb5_error_code retval;
|
||||
krad_packet *pkt;
|
||||
size_t attrset_len;
|
||||
+ krb5_boolean msgauth_required;
|
||||
|
||||
pkt = packet_new();
|
||||
if (pkt == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
+ /* Determine if Message-Authenticator is required. */
|
||||
+ msgauth_required = requires_msgauth(secret, code);
|
||||
+
|
||||
/* Encode the attributes. */
|
||||
- retval = kr_attrset_encode(set, secret, pkt_auth(request), pkt_attr(pkt),
|
||||
- &attrset_len, &pkt->is_fips);
|
||||
+ retval = kr_attrset_encode(set, secret, pkt_auth(request),
|
||||
+ msgauth_required, pkt_attr(pkt), &attrset_len,
|
||||
+ &pkt->is_fips);
|
||||
if (retval != 0)
|
||||
goto error;
|
||||
|
||||
@@ -330,6 +448,18 @@ krad_packet_new_response(krb5_context ctx, const char *secret, krad_code code,
|
||||
if (retval != 0)
|
||||
goto error;
|
||||
|
||||
+ if (msgauth_required) {
|
||||
+ /*
|
||||
+ * Calculate and replace the Message-Authenticator MAC. Per RFC 2869
|
||||
+ * section 5.14, use the authenticator from the request, not from the
|
||||
+ * response.
|
||||
+ */
|
||||
+ retval = calculate_mac(secret, pkt, pkt_auth(request),
|
||||
+ pkt_attr(pkt) + 2);
|
||||
+ if (retval != 0)
|
||||
+ goto error;
|
||||
+ }
|
||||
+
|
||||
/* Copy the attrset for future use. */
|
||||
retval = packet_set_attrset(ctx, secret, pkt);
|
||||
if (retval != 0)
|
||||
@@ -343,6 +473,34 @@ error:
|
||||
return retval;
|
||||
}
|
||||
|
||||
+/* Verify the Message-Authenticator value in pkt, using the provided
|
||||
+ * authenticator (which may be from pkt or from a corresponding request). */
|
||||
+static krb5_error_code
|
||||
+verify_msgauth(const char *secret, const krad_packet *pkt,
|
||||
+ const uint8_t auth[AUTH_FIELD_SIZE])
|
||||
+{
|
||||
+ uint8_t mac[MD5_DIGEST_SIZE];
|
||||
+ krad_attr msgauth_type = krad_attr_name2num("Message-Authenticator");
|
||||
+ const krb5_data *msgauth;
|
||||
+ krb5_error_code retval;
|
||||
+
|
||||
+ msgauth = krad_packet_get_attr(pkt, msgauth_type, 0);
|
||||
+ if (msgauth == NULL)
|
||||
+ return ENODATA;
|
||||
+
|
||||
+ retval = calculate_mac(secret, pkt, auth, mac);
|
||||
+ if (retval)
|
||||
+ return retval;
|
||||
+
|
||||
+ if (msgauth->length != MD5_DIGEST_SIZE)
|
||||
+ return EMSGSIZE;
|
||||
+
|
||||
+ if (k5_bcmp(mac, msgauth->data, MD5_DIGEST_SIZE) != 0)
|
||||
+ return EBADMSG;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
/* Decode a packet. */
|
||||
static krb5_error_code
|
||||
decode_packet(krb5_context ctx, const char *secret, const krb5_data *buffer,
|
||||
@@ -394,21 +552,35 @@ krad_packet_decode_request(krb5_context ctx, const char *secret,
|
||||
krad_packet **reqpkt)
|
||||
{
|
||||
const krad_packet *tmp = NULL;
|
||||
+ krad_packet *req;
|
||||
krb5_error_code retval;
|
||||
|
||||
- retval = decode_packet(ctx, secret, buffer, reqpkt);
|
||||
- if (cb != NULL && retval == 0) {
|
||||
+ retval = decode_packet(ctx, secret, buffer, &req);
|
||||
+ if (retval)
|
||||
+ return retval;
|
||||
+
|
||||
+ /* Verify Message-Authenticator if present. */
|
||||
+ if (has_pkt_msgauth(req)) {
|
||||
+ retval = verify_msgauth(secret, req, pkt_auth(req));
|
||||
+ if (retval) {
|
||||
+ krad_packet_free(req);
|
||||
+ return retval;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (cb != NULL) {
|
||||
for (tmp = (*cb)(data, FALSE); tmp != NULL; tmp = (*cb)(data, FALSE)) {
|
||||
if (pkt_id_get(*reqpkt) == pkt_id_get(tmp))
|
||||
break;
|
||||
}
|
||||
- }
|
||||
|
||||
- if (cb != NULL && (retval != 0 || tmp != NULL))
|
||||
- (*cb)(data, TRUE);
|
||||
+ if (tmp != NULL)
|
||||
+ (*cb)(data, TRUE);
|
||||
+ }
|
||||
|
||||
+ *reqpkt = req;
|
||||
*duppkt = tmp;
|
||||
- return retval;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
krb5_error_code
|
||||
@@ -435,9 +607,17 @@ krad_packet_decode_response(krb5_context ctx, const char *secret,
|
||||
break;
|
||||
}
|
||||
|
||||
- /* If the authenticator matches, then the response is valid. */
|
||||
- if (memcmp(pkt_auth(*rsppkt), auth, sizeof(auth)) == 0)
|
||||
- break;
|
||||
+ /* Verify the response authenticator. */
|
||||
+ if (k5_bcmp(pkt_auth(*rsppkt), auth, sizeof(auth)) != 0)
|
||||
+ continue;
|
||||
+
|
||||
+ /* Verify Message-Authenticator if present. */
|
||||
+ if (has_pkt_msgauth(*rsppkt)) {
|
||||
+ if (verify_msgauth(secret, *rsppkt, pkt_auth(tmp)) != 0)
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ break;
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/lib/krad/t_attrset.c b/src/lib/krad/t_attrset.c
|
||||
index 0f95762534..9a70529dc5 100644
|
||||
--- a/src/lib/krad/t_attrset.c
|
||||
+++ b/src/lib/krad/t_attrset.c
|
||||
@@ -63,7 +63,7 @@ main()
|
||||
noerror(krad_attrset_add(set, krad_attr_name2num("User-Password"), &tmp));
|
||||
|
||||
/* Encode attrset. */
|
||||
- noerror(kr_attrset_encode(set, "foo", auth, buffer, &encode_len,
|
||||
+ noerror(kr_attrset_encode(set, "foo", auth, FALSE, buffer, &encode_len,
|
||||
&is_fips));
|
||||
krad_attrset_free(set);
|
||||
|
||||
diff --git a/src/lib/krad/t_daemon.py b/src/lib/krad/t_daemon.py
|
||||
index 7668cd7f87..7fa0449a3c 100755
|
||||
--- a/src/lib/krad/t_daemon.py
|
||||
+++ b/src/lib/krad/t_daemon.py
|
||||
@@ -40,6 +40,7 @@ DICTIONARY = """
|
||||
ATTRIBUTE\tUser-Name\t1\tstring
|
||||
ATTRIBUTE\tUser-Password\t2\toctets
|
||||
ATTRIBUTE\tNAS-Identifier\t32\tstring
|
||||
+ATTRIBUTE\tMessage-Authenticator\t80\toctets
|
||||
"""
|
||||
|
||||
class TestServer(server.Server):
|
||||
@@ -52,7 +53,7 @@ class TestServer(server.Server):
|
||||
if key == "User-Password":
|
||||
passwd = map(pkt.PwDecrypt, pkt[key])
|
||||
|
||||
- reply = self.CreateReplyPacket(pkt)
|
||||
+ reply = self.CreateReplyPacket(pkt, message_authenticator=True)
|
||||
if passwd == ['accept']:
|
||||
reply.code = packet.AccessAccept
|
||||
else:
|
||||
diff --git a/src/lib/krad/t_packet.c b/src/lib/krad/t_packet.c
|
||||
index c22489144f..104b6507a2 100644
|
||||
--- a/src/lib/krad/t_packet.c
|
||||
+++ b/src/lib/krad/t_packet.c
|
||||
@@ -172,6 +172,9 @@ main(int argc, const char **argv)
|
||||
krb5_data username, password;
|
||||
krb5_boolean auth = FALSE;
|
||||
krb5_context ctx;
|
||||
+ const krad_packet *dupreq;
|
||||
+ const krb5_data *encpkt;
|
||||
+ krad_packet *decreq;
|
||||
|
||||
username = string2data("testUser");
|
||||
|
||||
@@ -184,9 +187,17 @@ main(int argc, const char **argv)
|
||||
|
||||
password = string2data("accept");
|
||||
noerror(make_packet(ctx, &username, &password, &packets[ACCEPT_PACKET]));
|
||||
+ encpkt = krad_packet_encode(packets[ACCEPT_PACKET]);
|
||||
+ noerror(krad_packet_decode_request(ctx, "foo", encpkt, NULL, NULL,
|
||||
+ &dupreq, &decreq));
|
||||
+ krad_packet_free(decreq);
|
||||
|
||||
password = string2data("reject");
|
||||
noerror(make_packet(ctx, &username, &password, &packets[REJECT_PACKET]));
|
||||
+ encpkt = krad_packet_encode(packets[REJECT_PACKET]);
|
||||
+ noerror(krad_packet_decode_request(ctx, "foo", encpkt, NULL, NULL,
|
||||
+ &dupreq, &decreq));
|
||||
+ krad_packet_free(decreq);
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_INET;
|
||||
diff --git a/src/tests/t_otp.py b/src/tests/t_otp.py
|
||||
index cba871a0f2..1ec916598c 100755
|
||||
--- a/src/tests/t_otp.py
|
||||
+++ b/src/tests/t_otp.py
|
||||
@@ -49,6 +49,7 @@ ATTRIBUTE User-Name 1 string
|
||||
ATTRIBUTE User-Password 2 octets
|
||||
ATTRIBUTE Service-Type 6 integer
|
||||
ATTRIBUTE NAS-Identifier 32 string
|
||||
+ATTRIBUTE Message-Authenticator 80 octets
|
||||
'''
|
||||
|
||||
class RadiusDaemon(Process):
|
||||
@@ -97,6 +98,8 @@ class RadiusDaemon(Process):
|
||||
reply.code = packet.AccessReject
|
||||
replyq['reply'] = False
|
||||
|
||||
+ reply.add_message_authenticator()
|
||||
+
|
||||
outq.put(replyq)
|
||||
if addr is None:
|
||||
sock.send(reply.ReplyPacket())
|
||||
--
|
||||
2.46.0
|
||||
|
@ -1,4 +1,4 @@
|
||||
From e339ad300caafc2a98e86ab48a9ac278cfe3bb85 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()
|
||||
|
@ -1,4 +1,4 @@
|
||||
From 3c15e9724dae95a4bf0899a8b8efc3e9e3f486ab Mon Sep 17 00:00:00 2001
|
||||
From b8bff4973a6642af80cbbc1bc03a52cb0d4e6247 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Scheel <ascheel@redhat.com>
|
||||
Date: Wed, 5 Jul 2017 11:38:30 -0400
|
||||
Subject: [PATCH] Implement GSS_C_CHANNEL_BOUND_FLAG
|
||||
|
@ -1,4 +1,4 @@
|
||||
From 7aea9fc73fb508e3168581990eb2e2ff7a1aea31 Mon Sep 17 00:00:00 2001
|
||||
From b37714a1b9138c0258d357931215fbd5ca7fa72b Mon Sep 17 00:00:00 2001
|
||||
From: Isaac Boukris <iboukris@gmail.com>
|
||||
Date: Mon, 9 Mar 2020 16:04:21 +0100
|
||||
Subject: [PATCH] Implement KERB_AP_OPTIONS_CBT (server side)
|
||||
|
@ -1,4 +1,4 @@
|
||||
From ca72aa3a2e4ca8bc1b1c33e46ca59ed4b3f20393 Mon Sep 17 00:00:00 2001
|
||||
From 01b93a5522fd0e402401bf6ed3c1ebfde613965e Mon Sep 17 00:00:00 2001
|
||||
From: Robbie Harwood <rharwood@redhat.com>
|
||||
Date: Tue, 9 Jun 2020 16:23:37 -0400
|
||||
Subject: [PATCH] Improve negoex_parse_token() code hygiene
|
||||
|
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);
|
365
SOURCES/Make-kprop-work-for-dump-files-larger-than-4GB.patch
Normal file
365
SOURCES/Make-kprop-work-for-dump-files-larger-than-4GB.patch
Normal file
@ -0,0 +1,365 @@
|
||||
From 5d541f1f0b468b1c976acf8ec2359bd0c8c73be7 Mon Sep 17 00:00:00 2001
|
||||
From: Julien Rische <jrische@redhat.com>
|
||||
Date: Wed, 19 Jan 2022 19:46:08 +0100
|
||||
Subject: [PATCH] Make kprop work for dump files larger than 4GB
|
||||
|
||||
If the dump file size does not fit in 32 bits, encode four zero bytes
|
||||
(forcing an error for unmodified kpropd) followed by the size in the
|
||||
next 64 bits.
|
||||
|
||||
Add a functional test case, but only run it when an environment
|
||||
variable is set, as processing a 4GB dump file is too
|
||||
resource-intensive for make check.
|
||||
|
||||
[ghudson@mit.edu: edited comments and commit message; eliminated use
|
||||
of defined constant in some cases; added test case]
|
||||
|
||||
ticket: 9053 (new)
|
||||
---
|
||||
src/kprop/kprop.c | 37 +++++++++++++++++++++----------------
|
||||
src/kprop/kprop.h | 12 ++++++++++++
|
||||
src/kprop/kprop_util.c | 42 ++++++++++++++++++++++++++++++++++++++++++
|
||||
src/kprop/kpropd.c | 33 +++++++++++++++++++++------------
|
||||
src/tests/t_kprop.py | 34 ++++++++++++++++++++++++++++++++++
|
||||
5 files changed, 130 insertions(+), 28 deletions(-)
|
||||
|
||||
diff --git a/src/kprop/kprop.c b/src/kprop/kprop.c
|
||||
index 0b53aae7e..5adb4d31f 100644
|
||||
--- a/src/kprop/kprop.c
|
||||
+++ b/src/kprop/kprop.c
|
||||
@@ -25,6 +25,7 @@
|
||||
*/
|
||||
|
||||
#include "k5-int.h"
|
||||
+#include <inttypes.h>
|
||||
#include <locale.h>
|
||||
#include <sys/file.h>
|
||||
#include <signal.h>
|
||||
@@ -71,11 +72,11 @@ static void open_connection(krb5_context context, char *host, int *fd_out);
|
||||
static void kerberos_authenticate(krb5_context context,
|
||||
krb5_auth_context *auth_context, int fd,
|
||||
krb5_principal me, krb5_creds **new_creds);
|
||||
-static int open_database(krb5_context context, char *data_fn, int *size);
|
||||
+static int open_database(krb5_context context, char *data_fn, off_t *size);
|
||||
static void close_database(krb5_context context, int fd);
|
||||
static void xmit_database(krb5_context context,
|
||||
krb5_auth_context auth_context, krb5_creds *my_creds,
|
||||
- int fd, int database_fd, int in_database_size);
|
||||
+ int fd, int database_fd, off_t in_database_size);
|
||||
static void send_error(krb5_context context, krb5_creds *my_creds, int fd,
|
||||
char *err_text, krb5_error_code err_code);
|
||||
static void update_last_prop_file(char *hostname, char *file_name);
|
||||
@@ -90,7 +91,8 @@ static void usage()
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
- int fd, database_fd, database_size;
|
||||
+ int fd, database_fd;
|
||||
+ off_t database_size;
|
||||
krb5_error_code retval;
|
||||
krb5_context context;
|
||||
krb5_creds *my_creds;
|
||||
@@ -339,7 +341,7 @@ kerberos_authenticate(krb5_context context, krb5_auth_context *auth_context,
|
||||
* in the size of the database file.
|
||||
*/
|
||||
static int
|
||||
-open_database(krb5_context context, char *data_fn, int *size)
|
||||
+open_database(krb5_context context, char *data_fn, off_t *size)
|
||||
{
|
||||
struct stat stbuf, stbuf_ok;
|
||||
char *data_ok_fn;
|
||||
@@ -413,19 +415,18 @@ close_database(krb5_context context, int fd)
|
||||
static void
|
||||
xmit_database(krb5_context context, krb5_auth_context auth_context,
|
||||
krb5_creds *my_creds, int fd, int database_fd,
|
||||
- int in_database_size)
|
||||
+ off_t in_database_size)
|
||||
{
|
||||
krb5_int32 n;
|
||||
krb5_data inbuf, outbuf;
|
||||
- char buf[KPROP_BUFSIZ];
|
||||
+ char buf[KPROP_BUFSIZ], dbsize_buf[KPROP_DBSIZE_MAX_BUFSIZ];
|
||||
krb5_error_code retval;
|
||||
krb5_error *error;
|
||||
- krb5_ui_4 database_size = in_database_size, send_size, sent_size;
|
||||
+ uint64_t database_size = in_database_size, send_size, sent_size;
|
||||
|
||||
/* Send over the size. */
|
||||
- send_size = htonl(database_size);
|
||||
- inbuf.data = (char *)&send_size;
|
||||
- inbuf.length = sizeof(send_size); /* must be 4, really */
|
||||
+ inbuf = make_data(dbsize_buf, sizeof(dbsize_buf));
|
||||
+ encode_database_size(database_size, &inbuf);
|
||||
/* KPROP_CKSUMTYPE */
|
||||
retval = krb5_mk_safe(context, auth_context, &inbuf, &outbuf, NULL);
|
||||
if (retval) {
|
||||
@@ -460,7 +461,7 @@ xmit_database(krb5_context context, krb5_auth_context auth_context,
|
||||
retval = krb5_mk_priv(context, auth_context, &inbuf, &outbuf, NULL);
|
||||
if (retval) {
|
||||
snprintf(buf, sizeof(buf),
|
||||
- "while encoding database block starting at %d",
|
||||
+ "while encoding database block starting at %"PRIu64,
|
||||
sent_size);
|
||||
com_err(progname, retval, "%s", buf);
|
||||
send_error(context, my_creds, fd, buf, retval);
|
||||
@@ -471,14 +472,14 @@ xmit_database(krb5_context context, krb5_auth_context auth_context,
|
||||
if (retval) {
|
||||
krb5_free_data_contents(context, &outbuf);
|
||||
com_err(progname, retval,
|
||||
- _("while sending database block starting at %d"),
|
||||
+ _("while sending database block starting at %"PRIu64),
|
||||
sent_size);
|
||||
exit(1);
|
||||
}
|
||||
krb5_free_data_contents(context, &outbuf);
|
||||
sent_size += n;
|
||||
if (debug)
|
||||
- printf("%d bytes sent.\n", sent_size);
|
||||
+ printf("%"PRIu64" bytes sent.\n", sent_size);
|
||||
}
|
||||
if (sent_size != database_size) {
|
||||
com_err(progname, 0, _("Premature EOF found for database file!"));
|
||||
@@ -533,10 +534,14 @@ xmit_database(krb5_context context, krb5_auth_context auth_context,
|
||||
exit(1);
|
||||
}
|
||||
|
||||
- memcpy(&send_size, outbuf.data, sizeof(send_size));
|
||||
- send_size = ntohl(send_size);
|
||||
+ retval = decode_database_size(&outbuf, &send_size);
|
||||
+ if (retval) {
|
||||
+ com_err(progname, retval, _("malformed sent database size message"));
|
||||
+ exit(1);
|
||||
+ }
|
||||
if (send_size != database_size) {
|
||||
- com_err(progname, 0, _("Kpropd sent database size %d, expecting %d"),
|
||||
+ com_err(progname, 0, _("Kpropd sent database size %"PRIu64
|
||||
+ ", expecting %"PRIu64),
|
||||
send_size, database_size);
|
||||
exit(1);
|
||||
}
|
||||
diff --git a/src/kprop/kprop.h b/src/kprop/kprop.h
|
||||
index 75331cc8a..3a319b535 100644
|
||||
--- a/src/kprop/kprop.h
|
||||
+++ b/src/kprop/kprop.h
|
||||
@@ -32,6 +32,7 @@
|
||||
#define KPROP_PROT_VERSION "kprop5_01"
|
||||
|
||||
#define KPROP_BUFSIZ 32768
|
||||
+#define KPROP_DBSIZE_MAX_BUFSIZ 12 /* max length of an encoded DB size */
|
||||
|
||||
/* pathnames are in osconf.h, included via k5-int.h */
|
||||
|
||||
@@ -41,3 +42,14 @@ int sockaddr2krbaddr(krb5_context context, int family, struct sockaddr *sa,
|
||||
krb5_error_code
|
||||
sn2princ_realm(krb5_context context, const char *hostname, const char *sname,
|
||||
const char *realm, krb5_principal *princ_out);
|
||||
+
|
||||
+/*
|
||||
+ * Encode size in four bytes (for backward compatibility) if it fits; otherwise
|
||||
+ * use the larger encoding. buf must be allocated with at least
|
||||
+ * KPROP_DBSIZE_MAX_BUFSIZ bytes.
|
||||
+ */
|
||||
+void encode_database_size(uint64_t size, krb5_data *buf);
|
||||
+
|
||||
+/* Decode a database size. Return KRB5KRB_ERR_GENERIC if buf has an invalid
|
||||
+ * length or did not encode a 32-bit size compactly. */
|
||||
+krb5_error_code decode_database_size(const krb5_data *buf, uint64_t *size_out);
|
||||
diff --git a/src/kprop/kprop_util.c b/src/kprop/kprop_util.c
|
||||
index c32d174b9..9d6b25389 100644
|
||||
--- a/src/kprop/kprop_util.c
|
||||
+++ b/src/kprop/kprop_util.c
|
||||
@@ -96,3 +96,45 @@ sn2princ_realm(krb5_context context, const char *hostname, const char *sname,
|
||||
(*princ_out)->type = KRB5_NT_SRV_HST;
|
||||
return ret;
|
||||
}
|
||||
+
|
||||
+void
|
||||
+encode_database_size(uint64_t size, krb5_data *buf)
|
||||
+{
|
||||
+ assert(buf->length >= 12);
|
||||
+ if (size > 0 && size <= UINT32_MAX) {
|
||||
+ /* Encode in 32 bits for backward compatibility. */
|
||||
+ store_32_be(size, buf->data);
|
||||
+ buf->length = 4;
|
||||
+ } else {
|
||||
+ /* Set the first 32 bits to 0 and encode in the following 64 bits. */
|
||||
+ store_32_be(0, buf->data);
|
||||
+ store_64_be(size, buf->data + 4);
|
||||
+ buf->length = 12;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+krb5_error_code
|
||||
+decode_database_size(const krb5_data *buf, uint64_t *size_out)
|
||||
+{
|
||||
+ uint64_t size;
|
||||
+
|
||||
+ if (buf->length == 12) {
|
||||
+ /* A 12-byte buffer must have the first four bytes zeroed. */
|
||||
+ if (load_32_be(buf->data) != 0)
|
||||
+ return KRB5KRB_ERR_GENERIC;
|
||||
+
|
||||
+ /* The size is stored in the next 64 bits. Values from 1..2^32-1 must
|
||||
+ * be encoded in four bytes. */
|
||||
+ size = load_64_be(buf->data + 4);
|
||||
+ if (size > 0 && size <= UINT32_MAX)
|
||||
+ return KRB5KRB_ERR_GENERIC;
|
||||
+ } else if (buf->length == 4) {
|
||||
+ size = load_32_be(buf->data);
|
||||
+ } else {
|
||||
+ /* Invalid buffer size. */
|
||||
+ return KRB5KRB_ERR_GENERIC;
|
||||
+ }
|
||||
+
|
||||
+ *size_out = size;
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/src/kprop/kpropd.c b/src/kprop/kpropd.c
|
||||
index 356e3e0e6..a83a86866 100644
|
||||
--- a/src/kprop/kpropd.c
|
||||
+++ b/src/kprop/kpropd.c
|
||||
@@ -55,6 +55,7 @@
|
||||
#include "com_err.h"
|
||||
#include "fake-addrinfo.h"
|
||||
|
||||
+#include <inttypes.h>
|
||||
#include <locale.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/file.h>
|
||||
@@ -1354,9 +1355,10 @@ static void
|
||||
recv_database(krb5_context context, int fd, int database_fd,
|
||||
krb5_data *confmsg)
|
||||
{
|
||||
- krb5_ui_4 database_size, received_size;
|
||||
+ uint64_t database_size, received_size;
|
||||
int n;
|
||||
char buf[1024];
|
||||
+ char dbsize_buf[KPROP_DBSIZE_MAX_BUFSIZ];
|
||||
krb5_data inbuf, outbuf;
|
||||
krb5_error_code retval;
|
||||
|
||||
@@ -1378,10 +1380,17 @@ recv_database(krb5_context context, int fd, int database_fd,
|
||||
_("while decoding database size from client"));
|
||||
exit(1);
|
||||
}
|
||||
- memcpy(&database_size, outbuf.data, sizeof(database_size));
|
||||
+
|
||||
+ retval = decode_database_size(&outbuf, &database_size);
|
||||
+ if (retval) {
|
||||
+ send_error(context, fd, retval, "malformed database size message");
|
||||
+ com_err(progname, retval,
|
||||
+ _("malformed database size message from client"));
|
||||
+ exit(1);
|
||||
+ }
|
||||
+
|
||||
krb5_free_data_contents(context, &inbuf);
|
||||
krb5_free_data_contents(context, &outbuf);
|
||||
- database_size = ntohl(database_size);
|
||||
|
||||
/* Initialize the initial vector. */
|
||||
retval = krb5_auth_con_initivector(context, auth_context);
|
||||
@@ -1401,7 +1410,7 @@ recv_database(krb5_context context, int fd, int database_fd,
|
||||
retval = krb5_read_message(context, &fd, &inbuf);
|
||||
if (retval) {
|
||||
snprintf(buf, sizeof(buf),
|
||||
- "while reading database block starting at offset %d",
|
||||
+ "while reading database block starting at offset %"PRIu64,
|
||||
received_size);
|
||||
com_err(progname, retval, "%s", buf);
|
||||
send_error(context, fd, retval, buf);
|
||||
@@ -1412,8 +1421,8 @@ recv_database(krb5_context context, int fd, int database_fd,
|
||||
retval = krb5_rd_priv(context, auth_context, &inbuf, &outbuf, NULL);
|
||||
if (retval) {
|
||||
snprintf(buf, sizeof(buf),
|
||||
- "while decoding database block starting at offset %d",
|
||||
- received_size);
|
||||
+ "while decoding database block starting at offset %"
|
||||
+ PRIu64, received_size);
|
||||
com_err(progname, retval, "%s", buf);
|
||||
send_error(context, fd, retval, buf);
|
||||
krb5_free_data_contents(context, &inbuf);
|
||||
@@ -1424,13 +1433,13 @@ recv_database(krb5_context context, int fd, int database_fd,
|
||||
krb5_free_data_contents(context, &outbuf);
|
||||
if (n < 0) {
|
||||
snprintf(buf, sizeof(buf),
|
||||
- "while writing database block starting at offset %d",
|
||||
+ "while writing database block starting at offset %"PRIu64,
|
||||
received_size);
|
||||
send_error(context, fd, errno, buf);
|
||||
} else if ((unsigned int)n != outbuf.length) {
|
||||
snprintf(buf, sizeof(buf),
|
||||
"incomplete write while writing database block starting "
|
||||
- "at \noffset %d (%d written, %d expected)",
|
||||
+ "at \noffset %"PRIu64" (%d written, %d expected)",
|
||||
received_size, n, outbuf.length);
|
||||
send_error(context, fd, KRB5KRB_ERR_GENERIC, buf);
|
||||
}
|
||||
@@ -1440,7 +1449,8 @@ recv_database(krb5_context context, int fd, int database_fd,
|
||||
/* OK, we've seen the entire file. Did we get too many bytes? */
|
||||
if (received_size > database_size) {
|
||||
snprintf(buf, sizeof(buf),
|
||||
- "Received %d bytes, expected %d bytes for database file",
|
||||
+ "Received %"PRIu64" bytes, expected %"PRIu64
|
||||
+ " bytes for database file",
|
||||
received_size, database_size);
|
||||
send_error(context, fd, KRB5KRB_ERR_GENERIC, buf);
|
||||
}
|
||||
@@ -1450,9 +1460,8 @@ recv_database(krb5_context context, int fd, int database_fd,
|
||||
|
||||
/* Create message acknowledging number of bytes received, but
|
||||
* don't send it until kdb5_util returns successfully. */
|
||||
- database_size = htonl(database_size);
|
||||
- inbuf.data = (char *)&database_size;
|
||||
- inbuf.length = sizeof(database_size);
|
||||
+ inbuf = make_data(dbsize_buf, sizeof(dbsize_buf));
|
||||
+ encode_database_size(database_size, &inbuf);
|
||||
retval = krb5_mk_safe(context,auth_context,&inbuf,confmsg,NULL);
|
||||
if (retval) {
|
||||
com_err(progname, retval, "while encoding # of receieved bytes");
|
||||
diff --git a/src/tests/t_kprop.py b/src/tests/t_kprop.py
|
||||
index c33e4fea2..f8ffd653a 100755
|
||||
--- a/src/tests/t_kprop.py
|
||||
+++ b/src/tests/t_kprop.py
|
||||
@@ -87,5 +87,39 @@ realm.run([kdb5_util, 'dump', dumpfile])
|
||||
realm.run([kprop, '-f', dumpfile, '-P', str(realm.kprop_port()), hostname])
|
||||
check_output(kpropd)
|
||||
realm.run([kadminl, 'listprincs'], replica3, expected_msg='wakawaka')
|
||||
+stop_daemon(kpropd)
|
||||
+
|
||||
+# This test is too resource-intensive to be included in "make check"
|
||||
+# by default, but it can be enabled in the environment to test the
|
||||
+# propagation of databases large enough to require a 12-byte encoding
|
||||
+# of the database size.
|
||||
+if 'KPROP_LARGE_DB_TEST' in os.environ:
|
||||
+ output('Generating >4GB dumpfile\n')
|
||||
+ with open(dumpfile, 'w') as f:
|
||||
+ f.write('kdb5_util load_dump version 6\n')
|
||||
+ f.write('princ\t38\t15\t3\t1\t0\tK/M@KRBTEST.COM\t64\t86400\t0\t0\t0'
|
||||
+ '\t0\t0\t0\t8\t2\t0100\t9\t8\t0100010000000000\t2\t28'
|
||||
+ '\tb93e105164625f6372656174696f6e404b5242544553542e434f4d00'
|
||||
+ '\t1\t1\t18\t62\t2000408c027c250e8cc3b81476414f2214d57c1ce'
|
||||
+ '38891e29792e87258247c73547df4d5756266931dd6686b62270e6568'
|
||||
+ '95a31ec66bfe913b4f15226227\t-1;\n')
|
||||
+ for i in range(1, 20000000):
|
||||
+ f.write('princ\t38\t21\t1\t1\t0\tp%08d@KRBTEST.COM' % i)
|
||||
+ f.write('\t0\t86400\t0\t0\t0\t0\t0\t0\t2\t27'
|
||||
+ '\td73e1051757365722f61646d696e404b5242544553542e434f4d00'
|
||||
+ '\t1\t1\t17\t46'
|
||||
+ '\t10009c8ab7b3f89ccf3ca3ad98352a461b7f4f1b0c49'
|
||||
+ '5605117591d9ad52ba4da0adef7a902126973ed2bdc3ffbf\t-1;\n')
|
||||
+ assert os.path.getsize(dumpfile) > 4 * 1024 * 1024 * 1024
|
||||
+ with open(dumpfile + '.dump_ok', 'w') as f:
|
||||
+ f.write('\0')
|
||||
+ conf_large = {'dbmodules': {'db': {'database_name': '$testdir/db.large'}},
|
||||
+ 'realms': {'$realm': {'iprop_resync_timeout': '3600'}}}
|
||||
+ large = realm.special_env('large', True, kdc_conf=conf_large)
|
||||
+ kpropd = realm.start_kpropd(large, ['-d'])
|
||||
+ realm.run([kprop, '-f', dumpfile, '-P', str(realm.kprop_port()), hostname])
|
||||
+ check_output(kpropd)
|
||||
+ realm.run([kadminl, 'getprinc', 'p19999999'], env=large,
|
||||
+ expected_msg='Principal: p19999999')
|
||||
|
||||
success('kprop tests')
|
||||
--
|
||||
2.35.1
|
||||
|
@ -1,4 +1,4 @@
|
||||
From 61f3943f9fc237936ed9fd098edcd8dcc43b8da7 Mon Sep 17 00:00:00 2001
|
||||
From f7b6d43533d1d9ec3960e3d7f375995896768aef Mon Sep 17 00:00:00 2001
|
||||
From: Greg Hudson <ghudson@mit.edu>
|
||||
Date: Wed, 6 May 2020 16:03:13 -0400
|
||||
Subject: [PATCH] Omit KDC indicator check for S4U2Self requests
|
||||
|
@ -1,4 +1,4 @@
|
||||
From 4c4c22639eb2794e563370a2ee48a34dbdddc639 Mon Sep 17 00:00:00 2001
|
||||
From e1b2c967266b14bc37e5ed11e6c0525bd259e0bb Mon Sep 17 00:00:00 2001
|
||||
From: Isaac Boukris <iboukris@gmail.com>
|
||||
Date: Sat, 6 Jun 2020 11:03:37 +0200
|
||||
Subject: [PATCH] Omit PA_FOR_USER if we can't compute its checksum
|
||||
|
@ -1,4 +1,4 @@
|
||||
From d98f8867f8245b3c9dd506271897d0f03d69ae49 Mon Sep 17 00:00:00 2001
|
||||
From 6265b0fbc59e13756364b97a5e3e8672514f8302 Mon Sep 17 00:00:00 2001
|
||||
From: Isaac Boukris <iboukris@gmail.com>
|
||||
Date: Tue, 28 Apr 2020 18:15:55 +0200
|
||||
Subject: [PATCH] Pass channel bindings through SPNEGO
|
||||
|
@ -1,4 +1,4 @@
|
||||
From 64b1fdf0732b094e174b484fd9aac29f06e482bd Mon Sep 17 00:00:00 2001
|
||||
From e57cdf6610f0b7c8ac38f9b2342b74b8c9e5bc54 Mon Sep 17 00:00:00 2001
|
||||
From: Greg Hudson <ghudson@mit.edu>
|
||||
Date: Sun, 26 Apr 2020 19:55:54 -0400
|
||||
Subject: [PATCH] Pass gss_localname() through SPNEGO
|
||||
|
@ -1,4 +1,4 @@
|
||||
From c4a49f5b42916fdbb34c72a11adb42ff879c50c3 Mon Sep 17 00:00:00 2001
|
||||
From 4f14a2f48b52e59c472847a5522fd0cf52927755 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Scheel <ascheel@redhat.com>
|
||||
Date: Fri, 30 Jun 2017 16:03:01 -0400
|
||||
Subject: [PATCH] Refactor krb5 GSS checksum handling
|
||||
|
@ -1,4 +1,4 @@
|
||||
From fdd97fe6c9f0a3a6ff8d2580ca9f3c46826449b7 Mon Sep 17 00:00:00 2001
|
||||
From cb8c8af56d306267d6964da217c65e129fe83c82 Mon Sep 17 00:00:00 2001
|
||||
From: Robbie Harwood <rharwood@redhat.com>
|
||||
Date: Wed, 26 Feb 2020 18:27:17 -0500
|
||||
Subject: [PATCH] Refresh manually acquired creds from client keytab
|
||||
|
1299
SOURCES/Remove-PKINIT-RSA-support.patch
Normal file
1299
SOURCES/Remove-PKINIT-RSA-support.patch
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,91 @@
|
||||
From 6b4cdaac48e6b736b66ccc21f4eed7c6fc4c2e4a Mon Sep 17 00:00:00 2001
|
||||
From: Greg Hudson <ghudson@mit.edu>
|
||||
Date: Fri, 4 Mar 2022 00:45:00 -0500
|
||||
Subject: [PATCH] Try harder to avoid password change replay errors
|
||||
|
||||
Commit d7b3018d338fc9c989c3fa17505870f23c3759a8 (ticket 7905) changed
|
||||
change_set_password() to prefer TCP. However, because UDP_LAST falls
|
||||
back to UDP after one second, we can still get a replay error due to a
|
||||
dropped packet, before the TCP layer has a chance to retry.
|
||||
|
||||
Instead, try k5_sendto() with NO_UDP, and only fall back to UDP after
|
||||
TCP fails completely without reaching a server. In sendto_kdc.c,
|
||||
implement an ONLY_UDP transport strategy to allow the UDP fallback.
|
||||
|
||||
ticket: 9037
|
||||
---
|
||||
src/lib/krb5/os/changepw.c | 9 ++++++++-
|
||||
src/lib/krb5/os/os-proto.h | 1 +
|
||||
src/lib/krb5/os/sendto_kdc.c | 12 ++++++++----
|
||||
3 files changed, 17 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/src/lib/krb5/os/changepw.c b/src/lib/krb5/os/changepw.c
|
||||
index 9f968da7f..c59232586 100644
|
||||
--- a/src/lib/krb5/os/changepw.c
|
||||
+++ b/src/lib/krb5/os/changepw.c
|
||||
@@ -255,9 +255,16 @@ change_set_password(krb5_context context,
|
||||
callback_info.pfn_cleanup = kpasswd_sendto_msg_cleanup;
|
||||
krb5_free_data_contents(callback_ctx.context, &chpw_rep);
|
||||
|
||||
+ /* UDP retransmits may be seen as replays. Only try UDP after other
|
||||
+ * transports fail completely. */
|
||||
code = k5_sendto(callback_ctx.context, NULL, &creds->server->realm,
|
||||
- &sl, UDP_LAST, &callback_info, &chpw_rep,
|
||||
+ &sl, NO_UDP, &callback_info, &chpw_rep,
|
||||
ss2sa(&remote_addr), &addrlen, NULL, NULL, NULL);
|
||||
+ if (code == KRB5_KDC_UNREACH) {
|
||||
+ code = k5_sendto(callback_ctx.context, NULL, &creds->server->realm,
|
||||
+ &sl, ONLY_UDP, &callback_info, &chpw_rep,
|
||||
+ ss2sa(&remote_addr), &addrlen, NULL, NULL, NULL);
|
||||
+ }
|
||||
if (code)
|
||||
goto cleanup;
|
||||
|
||||
diff --git a/src/lib/krb5/os/os-proto.h b/src/lib/krb5/os/os-proto.h
|
||||
index a16a34b74..ad3839131 100644
|
||||
--- a/src/lib/krb5/os/os-proto.h
|
||||
+++ b/src/lib/krb5/os/os-proto.h
|
||||
@@ -49,6 +49,7 @@ typedef enum {
|
||||
UDP_FIRST = 0,
|
||||
UDP_LAST,
|
||||
NO_UDP,
|
||||
+ ONLY_UDP
|
||||
} k5_transport_strategy;
|
||||
|
||||
/* A single server hostname or address. */
|
||||
diff --git a/src/lib/krb5/os/sendto_kdc.c b/src/lib/krb5/os/sendto_kdc.c
|
||||
index 82523c561..d76e24ccf 100644
|
||||
--- a/src/lib/krb5/os/sendto_kdc.c
|
||||
+++ b/src/lib/krb5/os/sendto_kdc.c
|
||||
@@ -799,11 +799,14 @@ resolve_server(krb5_context context, const krb5_data *realm,
|
||||
int err, result;
|
||||
char portbuf[PORT_LENGTH];
|
||||
|
||||
- /* Skip UDP entries if we don't want UDP. */
|
||||
+ /* Skip entries excluded by the strategy. */
|
||||
if (strategy == NO_UDP && entry->transport == UDP)
|
||||
return 0;
|
||||
+ if (strategy == ONLY_UDP && entry->transport != UDP &&
|
||||
+ entry->transport != TCP_OR_UDP)
|
||||
+ return 0;
|
||||
|
||||
- transport = (strategy == UDP_FIRST) ? UDP : TCP;
|
||||
+ transport = (strategy == UDP_FIRST || strategy == ONLY_UDP) ? UDP : TCP;
|
||||
if (entry->hostname == NULL) {
|
||||
/* Added by a module, so transport is either TCP or UDP. */
|
||||
ai.ai_socktype = socktype_for_transport(entry->transport);
|
||||
@@ -847,8 +850,9 @@ resolve_server(krb5_context context, const krb5_data *realm,
|
||||
}
|
||||
|
||||
/* For TCP_OR_UDP entries, add each address again with the non-preferred
|
||||
- * transport, unless we are avoiding UDP. Flag these as deferred. */
|
||||
- if (retval == 0 && entry->transport == TCP_OR_UDP && strategy != NO_UDP) {
|
||||
+ * transport, if there is one. Flag these as deferred. */
|
||||
+ if (retval == 0 && entry->transport == TCP_OR_UDP &&
|
||||
+ (strategy == UDP_FIRST || strategy == UDP_LAST)) {
|
||||
transport = (strategy == UDP_FIRST) ? TCP : UDP;
|
||||
for (a = addrs; a != 0 && retval == 0; a = a->ai_next) {
|
||||
a->ai_socktype = socktype_for_transport(transport);
|
||||
--
|
||||
2.35.1
|
||||
|
186
SOURCES/Unify-kvno-option-documentation.patch
Normal file
186
SOURCES/Unify-kvno-option-documentation.patch
Normal file
@ -0,0 +1,186 @@
|
||||
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
|
||||
|
||||
Add missing kvno options to the kvno.rst synopsis and option
|
||||
descriptions, and to the kvno usage message. Remove mention of '-h'
|
||||
(help text), from kvno.rst as it is an implicit option. Note that the
|
||||
three new caching options were added in release 1.19.
|
||||
|
||||
Indicate the two exclusions (-u/-S and --u2u with the S4U2Self options)
|
||||
and dependency (-P on S4U2Self) where they are missing.
|
||||
|
||||
Switch xusage() to print only a single localized string, rather than
|
||||
running each line of output through localization separately.
|
||||
|
||||
Leave kvno -C undocumented for now, as the semantics of
|
||||
KRB5_GC_CANONICALIZE are minimally useful and likely to change.
|
||||
|
||||
[ghudson@mit.edu: edited documentation and commit message]
|
||||
|
||||
ticket: 7476
|
||||
tags: pullup
|
||||
target_version: 1.18-next
|
||||
|
||||
(cherry picked from commit becd1ad6830b526d08ddaf5b2b6f213154c6446c)
|
||||
(cherry picked from commit 52e3695cc5ef00766e12adfe8ed276c2885e71bb)
|
||||
---
|
||||
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 718313576..65c44e1c0 100644
|
||||
--- a/doc/user/user_commands/kvno.rst
|
||||
+++ b/doc/user/user_commands/kvno.rst
|
||||
@@ -10,13 +10,9 @@ SYNOPSIS
|
||||
[**-c** *ccache*]
|
||||
[**-e** *etype*]
|
||||
[**-q**]
|
||||
-[**-h**]
|
||||
+[**-u** | **-S** *sname*]
|
||||
[**-P**]
|
||||
-[**-S** *sname*]
|
||||
-[**-I** *for_user*]
|
||||
-[**-U** *for_user*]
|
||||
-[**-F** *cert_file*]
|
||||
-[**--u2u** *ccache*]
|
||||
+[[{**-F** *cert_file* | {**-I** | **-U**} *for_user*} [**-P**]] | **--u2u** *ccache*]
|
||||
*service1 service2* ...
|
||||
|
||||
|
||||
@@ -39,13 +35,18 @@ OPTIONS
|
||||
of all the services named on the command line. This is useful in
|
||||
certain backward compatibility situations.
|
||||
|
||||
+**-k** *keytab*
|
||||
+ Decrypt the acquired tickets using *keytab* to confirm their
|
||||
+ validity.
|
||||
+
|
||||
**-q**
|
||||
Suppress printing output when successful. If a service ticket
|
||||
cannot be obtained, an error message will still be printed and
|
||||
kvno will exit with nonzero status.
|
||||
|
||||
-**-h**
|
||||
- Prints a usage statement and exits.
|
||||
+**-u**
|
||||
+ Use the unknown name type in requested service principal names.
|
||||
+ This option Cannot be used with *-S*.
|
||||
|
||||
**-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 9d85864f6..c5f6bf700 100644
|
||||
--- a/src/clients/kvno/kvno.c
|
||||
+++ b/src/clients/kvno/kvno.c
|
||||
@@ -38,15 +38,18 @@
|
||||
static char *prog;
|
||||
static int quiet = 0;
|
||||
|
||||
+#define XUSAGE_BREAK "\n\t"
|
||||
+
|
||||
static void
|
||||
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[--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 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]]
|
||||
[\fB\-c\fP \fIccache\fP]
|
||||
[\fB\-e\fP \fIetype\fP]
|
||||
[\fB\-q\fP]
|
||||
-[\fB\-h\fP]
|
||||
+[\fB\-u\fP | \fB\-S\fP \fIsname\fP]
|
||||
[\fB\-P\fP]
|
||||
-[\fB\-S\fP \fIsname\fP]
|
||||
-[\fB\-I\fP \fIfor_user\fP]
|
||||
-[\fB\-U\fP \fIfor_user\fP]
|
||||
-[\fB\-F\fP \fIcert_file\fP]
|
||||
-[\fB\-\-u2u\fP \fIccache\fP]
|
||||
+[[{\fB\-F\fP \fIcert_file\fP | {\fB\-I\fP | \fB\-U\fP} \fIfor_user\fP} [\fB\-P\fP]] | \fB\-\-u2u\fP \fIccache\fP]
|
||||
\fIservice1 service2\fP ...
|
||||
.SH DESCRIPTION
|
||||
.sp
|
||||
@@ -60,13 +56,18 @@ Specifies the enctype which will be requested for the session key
|
||||
of all the services named on the command line. This is useful in
|
||||
certain backward compatibility situations.
|
||||
.TP
|
||||
+\fB\-k\fP \fIkeytab\fP
|
||||
+Decrypt the acquired tickets using \fIkeytab\fP to confirm their
|
||||
+validity.
|
||||
+.TP
|
||||
\fB\-q\fP
|
||||
Suppress printing output when successful. If a service ticket
|
||||
cannot be obtained, an error message will still be printed and
|
||||
kvno will exit with nonzero status.
|
||||
.TP
|
||||
-\fB\-h\fP
|
||||
-Prints a usage statement and exits.
|
||||
+\fB\-u\fP
|
||||
+Use the unknown name type in requested service principal names.
|
||||
+This option Cannot be used with \fI\-S\fP\&.
|
||||
.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
|
184
SOURCES/Use-14-instead-of-9-for-unkeyed-SHA-1-checksum.patch
Normal file
184
SOURCES/Use-14-instead-of-9-for-unkeyed-SHA-1-checksum.patch
Normal file
@ -0,0 +1,184 @@
|
||||
From b6ada496a285a7b350e28c97b53b6f659a9a94b9 Mon Sep 17 00:00:00 2001
|
||||
From: Greg Hudson <ghudson@mit.edu>
|
||||
Date: Sat, 11 Dec 2021 01:25:34 -0500
|
||||
Subject: [PATCH] Use 14 instead of 9 for unkeyed SHA-1 checksum
|
||||
|
||||
Although MIT krb5 had been using the value 9 for unkeyed SHA-1 since
|
||||
its 1.0 release in 1996, RFC 3961 instead assigned this value to
|
||||
rsa-md5-des3 (likely never used), and assigned the values 10 and 14 to
|
||||
SHA-1. Heimdal and Microsoft use the value 14. Unkeyed SHA-1 almost
|
||||
never appears on the wire, but has been seen in PKINIT asChecksum
|
||||
fields in replies from Windows KDCs (despite the field being specified
|
||||
as a keyed checksum).
|
||||
|
||||
Define a new symbol CKSUMTYPE_SHA1 with the value 14, and use it where
|
||||
we currently use CKSUMTYPE_NIST_SHA. Continue to allow the value 9
|
||||
for ABI compatibility. Remove the pkinit_clnt.c workaround as the
|
||||
value 14 will now work without adjustment.
|
||||
|
||||
ticket: 9040 (new)
|
||||
---
|
||||
doc/appdev/refs/macros/index.rst | 1 +
|
||||
src/include/krb5/krb5.hin | 6 ++++++
|
||||
src/lib/crypto/crypto_tests/t_cksums.c | 2 +-
|
||||
src/lib/crypto/krb/cksumtypes.c | 6 ++++++
|
||||
src/lib/gssapi/mechglue/g_saslname.c | 3 +--
|
||||
src/lib/krb5/os/trace.c | 2 +-
|
||||
src/plugins/kdb/test/kdb_test.c | 2 +-
|
||||
src/plugins/preauth/pkinit/pkinit_clnt.c | 11 ++---------
|
||||
src/plugins/preauth/pkinit/pkinit_srv.c | 4 ++--
|
||||
9 files changed, 21 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/doc/appdev/refs/macros/index.rst b/doc/appdev/refs/macros/index.rst
|
||||
index 788d094bff..001fb386a7 100644
|
||||
--- a/doc/appdev/refs/macros/index.rst
|
||||
+++ b/doc/appdev/refs/macros/index.rst
|
||||
@@ -42,6 +42,7 @@ Public
|
||||
CKSUMTYPE_RSA_MD4_DES.rst
|
||||
CKSUMTYPE_RSA_MD5.rst
|
||||
CKSUMTYPE_RSA_MD5_DES.rst
|
||||
+ CKSUMTYPE_SHA1.rst
|
||||
ENCTYPE_AES128_CTS_HMAC_SHA1_96.rst
|
||||
ENCTYPE_AES128_CTS_HMAC_SHA256_128.rst
|
||||
ENCTYPE_AES256_CTS_HMAC_SHA1_96.rst
|
||||
diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin
|
||||
index d2cf1eba2a..a7060aa733 100644
|
||||
--- a/src/include/krb5/krb5.hin
|
||||
+++ b/src/include/krb5/krb5.hin
|
||||
@@ -449,6 +449,11 @@ typedef struct _krb5_crypto_iov {
|
||||
#define ENCTYPE_CAMELLIA256_CTS_CMAC 0x001a /**< RFC 6803 */
|
||||
#define ENCTYPE_UNKNOWN 0x01ff
|
||||
|
||||
+/*
|
||||
+ * Historically we used the value 9 for unkeyed SHA-1. RFC 3961 assigns this
|
||||
+ * value to rsa-md5-des3, which fortunately is unused. For ABI compatibility
|
||||
+ * we allow either 9 or 14 for SHA-1.
|
||||
+ */
|
||||
#define CKSUMTYPE_CRC32 0x0001
|
||||
#define CKSUMTYPE_RSA_MD4 0x0002
|
||||
#define CKSUMTYPE_RSA_MD4_DES 0x0003
|
||||
@@ -459,6 +464,7 @@ typedef struct _krb5_crypto_iov {
|
||||
#define CKSUMTYPE_RSA_MD5_DES 0x0008
|
||||
#define CKSUMTYPE_NIST_SHA 0x0009
|
||||
#define CKSUMTYPE_HMAC_SHA1_DES3 0x000c /* @deprecated removed */
|
||||
+#define CKSUMTYPE_SHA1 0x000d /**< RFC 3962 */
|
||||
#define CKSUMTYPE_HMAC_SHA1_96_AES128 0x000f /**< RFC 3962. Used with
|
||||
ENCTYPE_AES128_CTS_HMAC_SHA1_96 */
|
||||
#define CKSUMTYPE_HMAC_SHA1_96_AES256 0x0010 /**< RFC 3962. Used with
|
||||
diff --git a/src/lib/crypto/crypto_tests/t_cksums.c b/src/lib/crypto/crypto_tests/t_cksums.c
|
||||
index 84408fb68a..de5ed3a22b 100644
|
||||
--- a/src/lib/crypto/crypto_tests/t_cksums.c
|
||||
+++ b/src/lib/crypto/crypto_tests/t_cksums.c
|
||||
@@ -54,7 +54,7 @@ struct test {
|
||||
},
|
||||
{
|
||||
{ KV5M_DATA, 0, "" },
|
||||
- CKSUMTYPE_NIST_SHA, 0, 0, { KV5M_DATA, 0, "" },
|
||||
+ CKSUMTYPE_SHA1, 0, 0, { KV5M_DATA, 0, "" },
|
||||
{ KV5M_DATA, 20,
|
||||
"\xDA\x39\xA3\xEE\x5E\x6B\x4B\x0D\x32\x55\xBF\xEF\x95\x60\x18\x90"
|
||||
"\xAF\xD8\x07\x09" }
|
||||
diff --git a/src/lib/crypto/krb/cksumtypes.c b/src/lib/crypto/krb/cksumtypes.c
|
||||
index f5fbe8a2a7..25a3ffd2d2 100644
|
||||
--- a/src/lib/crypto/krb/cksumtypes.c
|
||||
+++ b/src/lib/crypto/krb/cksumtypes.c
|
||||
@@ -46,6 +46,12 @@ const struct krb5_cksumtypes krb5int_cksumtypes_list[] = {
|
||||
krb5int_unkeyed_checksum, NULL,
|
||||
20, 20, CKSUM_UNKEYED },
|
||||
|
||||
+ { CKSUMTYPE_SHA1,
|
||||
+ "sha", { 0 }, "SHA-1",
|
||||
+ NULL, &krb5int_hash_sha1,
|
||||
+ krb5int_unkeyed_checksum, NULL,
|
||||
+ 20, 20, CKSUM_UNKEYED },
|
||||
+
|
||||
{ CKSUMTYPE_HMAC_MD5_ARCFOUR,
|
||||
"hmac-md5-rc4", { "hmac-md5-enc", "hmac-md5-earcfour" },
|
||||
"Microsoft HMAC MD5",
|
||||
diff --git a/src/lib/gssapi/mechglue/g_saslname.c b/src/lib/gssapi/mechglue/g_saslname.c
|
||||
index e25f9e0a53..2be0c8a69a 100644
|
||||
--- a/src/lib/gssapi/mechglue/g_saslname.c
|
||||
+++ b/src/lib/gssapi/mechglue/g_saslname.c
|
||||
@@ -58,8 +58,7 @@ oidToSaslName(OM_uint32 *minor, const gss_OID mech,
|
||||
iov[2].data.length = sizeof(cksumBuf);
|
||||
iov[2].data.data = (char *)cksumBuf;
|
||||
|
||||
- *minor = krb5_k_make_checksum_iov(NULL, CKSUMTYPE_NIST_SHA,
|
||||
- NULL, 0, iov, 3);
|
||||
+ *minor = krb5_k_make_checksum_iov(NULL, CKSUMTYPE_SHA1, NULL, 0, iov, 3);
|
||||
if (*minor != 0)
|
||||
return GSS_S_FAILURE;
|
||||
|
||||
diff --git a/src/lib/krb5/os/trace.c b/src/lib/krb5/os/trace.c
|
||||
index e9b99f4ca0..abb8a3f21b 100644
|
||||
--- a/src/lib/krb5/os/trace.c
|
||||
+++ b/src/lib/krb5/os/trace.c
|
||||
@@ -93,7 +93,7 @@ hash_bytes(krb5_context context, const void *ptr, size_t len)
|
||||
krb5_data d = make_data((void *) ptr, len);
|
||||
char *s = NULL;
|
||||
|
||||
- if (krb5_k_make_checksum(context, CKSUMTYPE_NIST_SHA, NULL, 0, &d,
|
||||
+ if (krb5_k_make_checksum(context, CKSUMTYPE_SHA1, NULL, 0, &d,
|
||||
&cksum) != 0)
|
||||
return NULL;
|
||||
if (cksum.length >= 2)
|
||||
diff --git a/src/plugins/kdb/test/kdb_test.c b/src/plugins/kdb/test/kdb_test.c
|
||||
index 95a6062e2a..38d371cb86 100644
|
||||
--- a/src/plugins/kdb/test/kdb_test.c
|
||||
+++ b/src/plugins/kdb/test/kdb_test.c
|
||||
@@ -205,7 +205,7 @@ make_keyblock(krb5_kvno kvno, krb5_enctype etype, int32_t salttype,
|
||||
(int)salttype, princstr, (int)realm->length, realm->data) < 0)
|
||||
abort();
|
||||
d = string2data(hashstr);
|
||||
- check(krb5_c_make_checksum(NULL, CKSUMTYPE_NIST_SHA, NULL, 0, &d, &cksum));
|
||||
+ check(krb5_c_make_checksum(NULL, CKSUMTYPE_SHA1, NULL, 0, &d, &cksum));
|
||||
|
||||
/* Make the appropriate number of input bytes from the hash result. */
|
||||
for (pos = 0; pos < keybytes; pos += n) {
|
||||
diff --git a/src/plugins/preauth/pkinit/pkinit_clnt.c b/src/plugins/preauth/pkinit/pkinit_clnt.c
|
||||
index 9b991ffe05..021e5f0723 100644
|
||||
--- a/src/plugins/preauth/pkinit/pkinit_clnt.c
|
||||
+++ b/src/plugins/preauth/pkinit/pkinit_clnt.c
|
||||
@@ -119,8 +119,8 @@ pa_pkinit_gen_req(krb5_context context,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
- retval = krb5_c_make_checksum(context, CKSUMTYPE_NIST_SHA, NULL, 0,
|
||||
- der_req, &cksum);
|
||||
+ retval = krb5_c_make_checksum(context, CKSUMTYPE_SHA1, NULL, 0, der_req,
|
||||
+ &cksum);
|
||||
if (retval)
|
||||
goto cleanup;
|
||||
TRACE_PKINIT_CLIENT_REQ_CHECKSUM(context, &cksum);
|
||||
@@ -701,13 +701,6 @@ pkinit_as_rep_parse(krb5_context context,
|
||||
pkiDebug("failed to decode reply_key_pack\n");
|
||||
goto cleanup;
|
||||
}
|
||||
- /*
|
||||
- * This is hack but Windows sends back SHA1 checksum
|
||||
- * with checksum type of 14. There is currently no
|
||||
- * checksum type of 14 defined.
|
||||
- */
|
||||
- if (key_pack->asChecksum.checksum_type == 14)
|
||||
- key_pack->asChecksum.checksum_type = CKSUMTYPE_NIST_SHA;
|
||||
retval = krb5_c_make_checksum(context,
|
||||
key_pack->asChecksum.checksum_type,
|
||||
&key_pack->replyKey,
|
||||
diff --git a/src/plugins/preauth/pkinit/pkinit_srv.c b/src/plugins/preauth/pkinit/pkinit_srv.c
|
||||
index 3ae56c0641..3bff456f8f 100644
|
||||
--- a/src/plugins/preauth/pkinit/pkinit_srv.c
|
||||
+++ b/src/plugins/preauth/pkinit/pkinit_srv.c
|
||||
@@ -546,8 +546,8 @@ pkinit_server_verify_padata(krb5_context context,
|
||||
goto cleanup;
|
||||
}
|
||||
der_req = cb->request_body(context, rock);
|
||||
- retval = krb5_c_make_checksum(context, CKSUMTYPE_NIST_SHA, NULL, 0,
|
||||
- der_req, &cksum);
|
||||
+ retval = krb5_c_make_checksum(context, CKSUMTYPE_SHA1, NULL, 0, der_req,
|
||||
+ &cksum);
|
||||
if (retval) {
|
||||
pkiDebug("unable to calculate AS REQ checksum\n");
|
||||
goto cleanup;
|
||||
--
|
||||
2.39.2
|
||||
|
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:')
|
||||
|
124
SOURCES/Use-SHA256-instead-of-SHA1-for-PKINIT-CMS-digest.patch
Normal file
124
SOURCES/Use-SHA256-instead-of-SHA1-for-PKINIT-CMS-digest.patch
Normal file
@ -0,0 +1,124 @@
|
||||
From baa2a485190d1b31f3dae06a18dc24d71dbe35bf Mon Sep 17 00:00:00 2001
|
||||
From: Julien Rische <jrische@redhat.com>
|
||||
Date: Fri, 11 Mar 2022 12:04:14 +0100
|
||||
Subject: [PATCH] Use SHA-256 instead of SHA-1 for PKINIT CMS digest
|
||||
|
||||
Various organizations including NIST have been strongly recommending to
|
||||
stop using SHA-1 for digital signatures for some years already. CMS
|
||||
digest is used to generate such signatures, hence it should be upgraded
|
||||
to use SHA-256.
|
||||
---
|
||||
.../preauth/pkinit/pkinit_crypto_openssl.c | 40 ++++++++++---------
|
||||
1 file changed, 22 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
|
||||
index dbb054378..32291e3ac 100644
|
||||
--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
|
||||
+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
|
||||
@@ -1234,7 +1234,7 @@ cms_signeddata_create(krb5_context context,
|
||||
/* will not fill-out EVP_PKEY because it's on the smartcard */
|
||||
|
||||
/* Set digest algs */
|
||||
- p7si->digest_alg->algorithm = OBJ_nid2obj(NID_sha1);
|
||||
+ p7si->digest_alg->algorithm = OBJ_nid2obj(NID_sha256);
|
||||
|
||||
if (p7si->digest_alg->parameter != NULL)
|
||||
ASN1_TYPE_free(p7si->digest_alg->parameter);
|
||||
@@ -1245,17 +1245,18 @@ cms_signeddata_create(krb5_context context,
|
||||
/* Set sig algs */
|
||||
if (p7si->digest_enc_alg->parameter != NULL)
|
||||
ASN1_TYPE_free(p7si->digest_enc_alg->parameter);
|
||||
- p7si->digest_enc_alg->algorithm = OBJ_nid2obj(NID_sha1WithRSAEncryption);
|
||||
+ p7si->digest_enc_alg->algorithm =
|
||||
+ OBJ_nid2obj(NID_sha256WithRSAEncryption);
|
||||
if (!(p7si->digest_enc_alg->parameter = ASN1_TYPE_new()))
|
||||
goto cleanup;
|
||||
p7si->digest_enc_alg->parameter->type = V_ASN1_NULL;
|
||||
|
||||
/* add signed attributes */
|
||||
- /* compute sha1 digest over the EncapsulatedContentInfo */
|
||||
+ /* compute sha256 digest over the EncapsulatedContentInfo */
|
||||
ctx = EVP_MD_CTX_new();
|
||||
if (ctx == NULL)
|
||||
goto cleanup;
|
||||
- EVP_DigestInit_ex(ctx, EVP_sha1(), NULL);
|
||||
+ EVP_DigestInit_ex(ctx, EVP_sha256(), NULL);
|
||||
EVP_DigestUpdate(ctx, data, data_len);
|
||||
md_tmp = EVP_MD_CTX_md(ctx);
|
||||
EVP_DigestFinal_ex(ctx, md_data, &md_len);
|
||||
@@ -1283,12 +1284,14 @@ cms_signeddata_create(krb5_context context,
|
||||
goto cleanup2;
|
||||
|
||||
#ifndef WITHOUT_PKCS11
|
||||
- /* Some tokens can only do RSAEncryption without sha1 hash */
|
||||
- /* to compute sha1WithRSAEncryption, encode the algorithm ID for the hash
|
||||
- * function and the hash value into an ASN.1 value of type DigestInfo
|
||||
- * DigestInfo::=SEQUENCE {
|
||||
- * digestAlgorithm AlgorithmIdentifier,
|
||||
- * digest OCTET STRING }
|
||||
+ /*
|
||||
+ * Some tokens can only do RSAEncryption without a hash. To compute
|
||||
+ * sha256WithRSAEncryption, encode the algorithm ID for the hash
|
||||
+ * function and the hash value into an ASN.1 value of type DigestInfo:
|
||||
+ * DigestInfo ::= SEQUENCE {
|
||||
+ * digestAlgorithm AlgorithmIdentifier,
|
||||
+ * digest OCTET STRING
|
||||
+ * }
|
||||
*/
|
||||
if (id_cryptoctx->pkcs11_method == 1 &&
|
||||
id_cryptoctx->mech == CKM_RSA_PKCS) {
|
||||
@@ -1304,7 +1307,7 @@ cms_signeddata_create(krb5_context context,
|
||||
alg = X509_ALGOR_new();
|
||||
if (alg == NULL)
|
||||
goto cleanup2;
|
||||
- X509_ALGOR_set0(alg, OBJ_nid2obj(NID_sha1), V_ASN1_NULL, NULL);
|
||||
+ X509_ALGOR_set0(alg, OBJ_nid2obj(NID_sha256), V_ASN1_NULL, NULL);
|
||||
alg_len = i2d_X509_ALGOR(alg, NULL);
|
||||
|
||||
digest = ASN1_OCTET_STRING_new();
|
||||
@@ -1333,7 +1336,7 @@ cms_signeddata_create(krb5_context context,
|
||||
#endif
|
||||
{
|
||||
pkiDebug("mech = %s\n",
|
||||
- id_cryptoctx->pkcs11_method == 1 ? "CKM_SHA1_RSA_PKCS" : "FS");
|
||||
+ id_cryptoctx->pkcs11_method == 1 ? "CKM_SHA256_RSA_PKCS" : "FS");
|
||||
retval = pkinit_sign_data(context, id_cryptoctx, abuf, alen,
|
||||
&sig, &sig_len);
|
||||
}
|
||||
@@ -4147,7 +4150,7 @@ create_signature(unsigned char **sig, unsigned int *sig_len,
|
||||
ctx = EVP_MD_CTX_new();
|
||||
if (ctx == NULL)
|
||||
return ENOMEM;
|
||||
- EVP_SignInit(ctx, EVP_sha1());
|
||||
+ EVP_SignInit(ctx, EVP_sha256());
|
||||
EVP_SignUpdate(ctx, data, data_len);
|
||||
*sig_len = EVP_PKEY_size(pkey);
|
||||
if ((*sig = malloc(*sig_len)) == NULL)
|
||||
@@ -4623,10 +4626,11 @@ pkinit_get_certs_pkcs11(krb5_context context,
|
||||
|
||||
#ifndef PKINIT_USE_MECH_LIST
|
||||
/*
|
||||
- * We'd like to use CKM_SHA1_RSA_PKCS for signing if it's available, but
|
||||
- * many cards seems to be confused about whether they are capable of
|
||||
- * this or not. The safe thing seems to be to ignore the mechanism list,
|
||||
- * always use CKM_RSA_PKCS and calculate the sha1 digest ourselves.
|
||||
+ * We'd like to use CKM_SHA256_RSA_PKCS for signing if it's available, but
|
||||
+ * historically many cards seem to be confused about whether they are
|
||||
+ * capable of mechanisms or not. The safe thing seems to be to ignore the
|
||||
+ * mechanism list, always use CKM_RSA_PKCS and calculate the sha256 digest
|
||||
+ * ourselves.
|
||||
*/
|
||||
|
||||
id_cryptoctx->mech = CKM_RSA_PKCS;
|
||||
@@ -4654,7 +4658,7 @@ pkinit_get_certs_pkcs11(krb5_context context,
|
||||
if (mechp[i] == CKM_RSA_PKCS) {
|
||||
/* This seems backwards... */
|
||||
id_cryptoctx->mech =
|
||||
- (info.flags & CKF_SIGN) ? CKM_SHA1_RSA_PKCS : CKM_RSA_PKCS;
|
||||
+ (info.flags & CKF_SIGN) ? CKM_SHA256_RSA_PKCS : CKM_RSA_PKCS;
|
||||
}
|
||||
}
|
||||
free(mechp);
|
||||
--
|
||||
2.35.1
|
||||
|
138
SOURCES/Wait-indefinitely-on-KDC-TCP-connections.patch
Normal file
138
SOURCES/Wait-indefinitely-on-KDC-TCP-connections.patch
Normal file
@ -0,0 +1,138 @@
|
||||
From 2e871df888d526a15e9e91807480c15ca4e40618 Mon Sep 17 00:00:00 2001
|
||||
From: Greg Hudson <ghudson@mit.edu>
|
||||
Date: Thu, 26 Oct 2023 16:26:42 -0400
|
||||
Subject: [PATCH] Wait indefinitely on KDC TCP connections
|
||||
|
||||
When making a KDC or password change request, wait indefinitely
|
||||
(limited only by request_timeout if set) once a KDC has accepted a TCP
|
||||
connection.
|
||||
|
||||
ticket: 9105 (new)
|
||||
(cherry picked from commit 6436a3808061da787a43c6810f5f0370cdfb6e36)
|
||||
---
|
||||
doc/admin/conf_files/krb5_conf.rst | 2 +-
|
||||
src/lib/krb5/os/sendto_kdc.c | 50 ++++++++++++++++--------------
|
||||
2 files changed, 27 insertions(+), 25 deletions(-)
|
||||
|
||||
diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst
|
||||
index 557094f6a2..98fe231813 100644
|
||||
--- a/doc/admin/conf_files/krb5_conf.rst
|
||||
+++ b/doc/admin/conf_files/krb5_conf.rst
|
||||
@@ -358,7 +358,7 @@ The libdefaults section may contain any of the following relations:
|
||||
for initial ticket requests. The default value is 0.
|
||||
|
||||
**request_timeout**
|
||||
- (:ref:`duration` string.) Sets the maximum total time for KDC or
|
||||
+ (:ref:`duration` string.) Sets the maximum total time for KDC and
|
||||
password change requests. This timeout does not affect the
|
||||
intervals between requests, so setting a low timeout may result in
|
||||
fewer requests being attempted and/or some servers not being
|
||||
diff --git a/src/lib/krb5/os/sendto_kdc.c b/src/lib/krb5/os/sendto_kdc.c
|
||||
index f57117126e..19b78aba24 100644
|
||||
--- a/src/lib/krb5/os/sendto_kdc.c
|
||||
+++ b/src/lib/krb5/os/sendto_kdc.c
|
||||
@@ -134,7 +134,6 @@ struct conn_state {
|
||||
krb5_data callback_buffer;
|
||||
size_t server_index;
|
||||
struct conn_state *next;
|
||||
- time_ms endtime;
|
||||
krb5_boolean defer;
|
||||
struct {
|
||||
const char *uri_path;
|
||||
@@ -344,15 +343,19 @@ cm_select_or_poll(const struct select_state *in, time_ms endtime,
|
||||
struct select_state *out, int *sret)
|
||||
{
|
||||
#ifndef USE_POLL
|
||||
- struct timeval tv;
|
||||
+ struct timeval tv, *tvp;
|
||||
#endif
|
||||
krb5_error_code retval;
|
||||
time_ms curtime, interval;
|
||||
|
||||
- retval = get_curtime_ms(&curtime);
|
||||
- if (retval != 0)
|
||||
- return retval;
|
||||
- interval = (curtime < endtime) ? endtime - curtime : 0;
|
||||
+ if (endtime != 0) {
|
||||
+ retval = get_curtime_ms(&curtime);
|
||||
+ if (retval != 0)
|
||||
+ return retval;
|
||||
+ interval = (curtime < endtime) ? endtime - curtime : 0;
|
||||
+ } else {
|
||||
+ interval = -1;
|
||||
+ }
|
||||
|
||||
/* We don't need a separate copy of the selstate for poll, but use one for
|
||||
* consistency with how we use select. */
|
||||
@@ -361,9 +364,14 @@ cm_select_or_poll(const struct select_state *in, time_ms endtime,
|
||||
#ifdef USE_POLL
|
||||
*sret = poll(out->fds, out->nfds, interval);
|
||||
#else
|
||||
- tv.tv_sec = interval / 1000;
|
||||
- tv.tv_usec = interval % 1000 * 1000;
|
||||
- *sret = select(out->max, &out->rfds, &out->wfds, &out->xfds, &tv);
|
||||
+ if (interval != -1) {
|
||||
+ tv.tv_sec = interval / 1000;
|
||||
+ tv.tv_usec = interval % 1000 * 1000;
|
||||
+ tvp = &tv;
|
||||
+ } else {
|
||||
+ tvp = NULL;
|
||||
+ }
|
||||
+ *sret = select(out->max, &out->rfds, &out->wfds, &out->xfds, tvp);
|
||||
#endif
|
||||
|
||||
return (*sret < 0) ? SOCKET_ERRNO : 0;
|
||||
@@ -1094,11 +1102,6 @@ service_tcp_connect(krb5_context context, const krb5_data *realm,
|
||||
}
|
||||
|
||||
conn->state = WRITING;
|
||||
-
|
||||
- /* Record this connection's timeout for service_fds. */
|
||||
- if (get_curtime_ms(&conn->endtime) == 0)
|
||||
- conn->endtime += 10000;
|
||||
-
|
||||
return conn->service_write(context, realm, conn, selstate);
|
||||
}
|
||||
|
||||
@@ -1373,19 +1376,18 @@ kill_conn:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
-/* Return the maximum of endtime and the endtime fields of all currently active
|
||||
- * TCP connections. */
|
||||
-static time_ms
|
||||
-get_endtime(time_ms endtime, struct conn_state *conns)
|
||||
+/* Return true if conns contains any states with connected TCP sockets. */
|
||||
+static krb5_boolean
|
||||
+any_tcp_connections(struct conn_state *conns)
|
||||
{
|
||||
struct conn_state *state;
|
||||
|
||||
for (state = conns; state != NULL; state = state->next) {
|
||||
- if ((state->state == READING || state->state == WRITING) &&
|
||||
- state->endtime > endtime)
|
||||
- endtime = state->endtime;
|
||||
+ if (state->addr.transport != UDP &&
|
||||
+ (state->state == READING || state->state == WRITING))
|
||||
+ return TRUE;
|
||||
}
|
||||
- return endtime;
|
||||
+ return FALSE;
|
||||
}
|
||||
|
||||
static krb5_boolean
|
||||
@@ -1408,9 +1410,9 @@ service_fds(krb5_context context, struct select_state *selstate,
|
||||
|
||||
e = 0;
|
||||
while (selstate->nfds > 0) {
|
||||
- endtime = get_endtime(interval_end, conns);
|
||||
+ endtime = any_tcp_connections(conns) ? 0 : interval_end;
|
||||
/* Don't wait longer than the whole request should last. */
|
||||
- if (timeout && endtime > timeout)
|
||||
+ if (timeout && (!endtime || endtime > timeout))
|
||||
endtime = timeout;
|
||||
e = cm_select_or_poll(selstate, endtime, seltemp, &selret);
|
||||
if (e == EINTR)
|
||||
--
|
||||
2.44.0
|
||||
|
126
SOURCES/downstream-Allow-to-make-AD-SIGNEDPATH-optional.patch
Normal file
126
SOURCES/downstream-Allow-to-make-AD-SIGNEDPATH-optional.patch
Normal file
@ -0,0 +1,126 @@
|
||||
From 274464a6faaee694c30ae4d1412a8ab516b1a982 Mon Sep 17 00:00:00 2001
|
||||
From: Julien Rische <jrische@redhat.com>
|
||||
Date: Wed, 20 Sep 2023 16:22:06 +0200
|
||||
Subject: [PATCH] [downstream] Allow to make AD-SIGNEDPATH optional
|
||||
|
||||
MIT krb5 1.20 and newer KDCs do generate a minimal PAC instead of
|
||||
AD-SIGNEDPATH. As a consequence, an evidence ticket generated by an
|
||||
older KDC would fail to be processed by a newer KDC for a constrained
|
||||
delegation request.
|
||||
|
||||
This commit modifies this behavior to check the AD-SIGNEDPATH whenever
|
||||
it is present in a TGS-REQ, but do not require it in case a PAC is
|
||||
provided AND the KDB plugin supports its verification. This is done
|
||||
regardless to the fact the constrained delegation request is from a
|
||||
local realm or a cross-realm.
|
||||
|
||||
To enable this mechanism, the KDB plugin must set the
|
||||
"optional_ab_signedpath" string attribute to "true" for the local TGS
|
||||
principal.
|
||||
---
|
||||
src/include/kdb.h | 1 +
|
||||
src/kdc/kdc_authdata.c | 65 +++++++++++++++++++++++++++++++++---------
|
||||
2 files changed, 52 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/src/include/kdb.h b/src/include/kdb.h
|
||||
index c56947ab81..95d07d0195 100644
|
||||
--- a/src/include/kdb.h
|
||||
+++ b/src/include/kdb.h
|
||||
@@ -136,6 +136,7 @@
|
||||
/* String attribute names recognized by krb5 */
|
||||
#define KRB5_KDB_SK_SESSION_ENCTYPES "session_enctypes"
|
||||
#define KRB5_KDB_SK_REQUIRE_AUTH "require_auth"
|
||||
+#define KRB5_KDB_SK_OPTIONAL_AD_SIGNEDPATH "optional_ad_signedpath"
|
||||
|
||||
#if !defined(_WIN32)
|
||||
|
||||
diff --git a/src/kdc/kdc_authdata.c b/src/kdc/kdc_authdata.c
|
||||
index 1ebe872467..c0fcccdf21 100644
|
||||
--- a/src/kdc/kdc_authdata.c
|
||||
+++ b/src/kdc/kdc_authdata.c
|
||||
@@ -668,6 +668,13 @@ has_pac(krb5_context context, krb5_authdata **authdata)
|
||||
return has_kdc_issued_authdata(context, authdata, KRB5_AUTHDATA_WIN2K_PAC);
|
||||
}
|
||||
|
||||
+/* Return true if the AD-SIGNEDPATH is present in authorization data. */
|
||||
+static krb5_boolean
|
||||
+has_ad_signedpath(krb5_context context, krb5_authdata **authdata)
|
||||
+{
|
||||
+ return has_kdc_issued_authdata(context, authdata, KRB5_AUTHDATA_SIGNTICKET);
|
||||
+}
|
||||
+
|
||||
/* Verify AD-SIGNTICKET authdata if we need to, and insert an AD-SIGNEDPATH
|
||||
* element if we should. */
|
||||
static krb5_error_code
|
||||
@@ -680,24 +687,54 @@ handle_signticket(krb5_context context, unsigned int flags,
|
||||
{
|
||||
krb5_error_code ret = 0;
|
||||
krb5_principal *deleg_path = NULL;
|
||||
- krb5_boolean signed_path = FALSE;
|
||||
- krb5_boolean s4u2proxy;
|
||||
+ krb5_boolean s4u2proxy, adsp_present, adsp_optional, adsp_valid = FALSE;
|
||||
+ char *str;
|
||||
|
||||
s4u2proxy = isflagset(flags, KRB5_KDB_FLAG_CONSTRAINED_DELEGATION);
|
||||
|
||||
- /* For cross-realm the Windows PAC must have been verified, and it
|
||||
- * fulfills the same role as the signed path. */
|
||||
- if (req->msg_type == KRB5_TGS_REQ &&
|
||||
- (!isflagset(flags, KRB5_KDB_FLAG_CROSS_REALM) ||
|
||||
- !has_pac(context, enc_tkt_req->authorization_data))) {
|
||||
- ret = verify_signedpath(context, local_tgt, local_tgt_key, enc_tkt_req,
|
||||
- &deleg_path, &signed_path);
|
||||
- if (ret)
|
||||
- goto cleanup;
|
||||
+ if (req->msg_type == KRB5_TGS_REQ) {
|
||||
+ adsp_present = has_ad_signedpath(context,
|
||||
+ enc_tkt_req->authorization_data);
|
||||
+
|
||||
+ /* In case of constained delegation, based on the value of the
|
||||
+ * "optional_ad_signedpath" string attribute of the local TGS principal:
|
||||
+ * - "true": in case AD-SIGNEDPATH is absent, the PAC must be present
|
||||
+ * - "false" or undefined: AD-SIGNEDPATH must be present
|
||||
+ */
|
||||
+ if (s4u2proxy && !adsp_present) {
|
||||
+ ret = krb5_dbe_get_string(context, local_tgt,
|
||||
+ KRB5_KDB_SK_OPTIONAL_AD_SIGNEDPATH,
|
||||
+ &str);
|
||||
+ /* TODO: should be using _krb5_conf_boolean(), but os-proto.h is not
|
||||
+ * available here.
|
||||
+ */
|
||||
+ adsp_optional = !ret && str && (strncasecmp(str, "true", 4) == 0
|
||||
+ || strncasecmp(str, "t", 1) == 0
|
||||
+ || strncasecmp(str, "yes", 3) == 0
|
||||
+ || strncasecmp(str, "y", 1) == 0
|
||||
+ || strncasecmp(str, "1", 1) == 0
|
||||
+ || strncasecmp(str, "on", 2) == 0);
|
||||
+
|
||||
+ if (!adsp_optional ||
|
||||
+ !has_pac(context, enc_tkt_req->authorization_data)) {
|
||||
+ ret = KRB5KDC_ERR_BADOPTION;
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
- if (s4u2proxy && signed_path == FALSE) {
|
||||
- ret = KRB5KDC_ERR_BADOPTION;
|
||||
- goto cleanup;
|
||||
+ /* If AD-SIGNEDPATH is present, verify it */
|
||||
+ if (adsp_present) {
|
||||
+ ret = verify_signedpath(context, local_tgt, local_tgt_key,
|
||||
+ enc_tkt_req, &deleg_path, &adsp_valid);
|
||||
+ if (ret)
|
||||
+ goto cleanup;
|
||||
+
|
||||
+ /* In case of contrained delegation, if AD-SIGNEDPATH is present, it
|
||||
+ * has to be valid */
|
||||
+ if (s4u2proxy && !adsp_valid) {
|
||||
+ ret = KRB5KDC_ERR_BADOPTION;
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.41.0
|
||||
|
@ -1,7 +1,7 @@
|
||||
From a3f9d8f66a7f2e01aa7b12ef4e2a289d867bb276 Mon Sep 17 00:00:00 2001
|
||||
From f87e8a6734726bdd166f33757232a8c7cf9a9058 Mon Sep 17 00:00:00 2001
|
||||
From: Robbie Harwood <rharwood@redhat.com>
|
||||
Date: Fri, 9 Nov 2018 15:12:21 -0500
|
||||
Subject: [PATCH] [downstream] FIPS with PRNG and RADIUS and MD4
|
||||
Subject: [PATCH] [downstream] FIPS with PRNG and RADIUS and MD4+5
|
||||
|
||||
NB: Use openssl's PRNG in FIPS mode and taint within krad.
|
||||
|
||||
@ -17,25 +17,45 @@ AES is fine. Shame about SPAKE though.
|
||||
|
||||
post6 restores MD4 (and therefore keygen-only RC4).
|
||||
|
||||
post7 restores MD5 and adds radius_md5_fips_override.
|
||||
|
||||
Last-updated: krb5-1.17
|
||||
(cherry picked from commit a721df13d09b5fdad32de15e6aa973b732727aa9)
|
||||
(cherry picked from commit bf8521bfaa4a4d54f6eb94f785c68942f4afa055)
|
||||
---
|
||||
doc/admin/conf_files/krb5_conf.rst | 6 +++
|
||||
src/lib/crypto/krb/prng.c | 11 ++++-
|
||||
.../crypto/openssl/enc_provider/camellia.c | 6 +++
|
||||
src/lib/crypto/openssl/enc_provider/rc4.c | 13 +++++-
|
||||
.../crypto/openssl/hash_provider/hash_evp.c | 12 +++++
|
||||
src/lib/crypto/openssl/hmac.c | 6 ++-
|
||||
src/lib/krad/attr.c | 45 ++++++++++++++-----
|
||||
src/lib/krad/attrset.c | 5 ++-
|
||||
src/lib/krad/internal.h | 13 +++++-
|
||||
src/lib/krad/packet.c | 22 ++++-----
|
||||
src/lib/krad/remote.c | 10 ++++-
|
||||
src/lib/krad/attr.c | 46 ++++++++++++++-----
|
||||
src/lib/krad/attrset.c | 5 +-
|
||||
src/lib/krad/internal.h | 28 ++++++++++-
|
||||
src/lib/krad/packet.c | 22 +++++----
|
||||
src/lib/krad/remote.c | 10 +++-
|
||||
src/lib/krad/t_attr.c | 3 +-
|
||||
src/lib/krad/t_attrset.c | 4 +-
|
||||
src/plugins/preauth/spake/spake_client.c | 6 +++
|
||||
src/plugins/preauth/spake/spake_kdc.c | 6 +++
|
||||
14 files changed, 129 insertions(+), 33 deletions(-)
|
||||
15 files changed, 151 insertions(+), 33 deletions(-)
|
||||
|
||||
diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst
|
||||
index 1d2aa7f68..3a8b9cf47 100644
|
||||
--- a/doc/admin/conf_files/krb5_conf.rst
|
||||
+++ b/doc/admin/conf_files/krb5_conf.rst
|
||||
@@ -331,6 +331,12 @@ The libdefaults section may contain any of the following relations:
|
||||
qualification of shortnames, set this relation to the empty string
|
||||
with ``qualify_shortname = ""``. (New in release 1.18.)
|
||||
|
||||
+**radius_md5_fips_override**
|
||||
+ Downstream-only option to enable use of MD5 in RADIUS
|
||||
+ communication (libkrad). This allows for local (or protected
|
||||
+ tunnel) communication with a RADIUS server that doesn't use krad
|
||||
+ (e.g., freeradius) while in FIPS mode.
|
||||
+
|
||||
**rdns**
|
||||
If this flag is true, reverse name lookup will be used in addition
|
||||
to forward name lookup to canonicalizing hostnames for use in
|
||||
diff --git a/src/lib/crypto/krb/prng.c b/src/lib/crypto/krb/prng.c
|
||||
index cb9ca9b98..f0e9984ca 100644
|
||||
--- a/src/lib/crypto/krb/prng.c
|
||||
@ -130,15 +150,15 @@ index a65d57b7a..6ccaca94a 100644
|
||||
* The cipher state here is a saved pointer to a struct arcfour_state
|
||||
* object, rather than a flat byte array as in most enc providers. The
|
||||
diff --git a/src/lib/crypto/openssl/hash_provider/hash_evp.c b/src/lib/crypto/openssl/hash_provider/hash_evp.c
|
||||
index 1e0fb8fc3..feb5eda99 100644
|
||||
index 1e0fb8fc3..2eb5139c0 100644
|
||||
--- a/src/lib/crypto/openssl/hash_provider/hash_evp.c
|
||||
+++ b/src/lib/crypto/openssl/hash_provider/hash_evp.c
|
||||
@@ -49,6 +49,11 @@ hash_evp(const EVP_MD *type, const krb5_crypto_iov *data, size_t num_data,
|
||||
if (ctx == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
+ if (type == EVP_md4()) {
|
||||
+ /* See comment below in hash_md4(). */
|
||||
+ if (type == EVP_md4() || type == EVP_md5()) {
|
||||
+ /* See comments below in hash_md4() and hash_md5(). */
|
||||
+ EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
|
||||
+ }
|
||||
+
|
||||
@ -160,8 +180,8 @@ index 1e0fb8fc3..feb5eda99 100644
|
||||
static krb5_error_code
|
||||
hash_md5(const krb5_crypto_iov *data, size_t num_data, krb5_data *output)
|
||||
{
|
||||
+ if (FIPS_mode())
|
||||
+ return KRB5_CRYPTO_INTERNAL;
|
||||
+ /* MD5 is needed in FIPS mode for communication with RADIUS servers. This
|
||||
+ * is gated in libkrad by libdefaults->radius_md5_fips_override. */
|
||||
return hash_evp(EVP_md5(), data, num_data, output);
|
||||
}
|
||||
|
||||
@ -183,18 +203,10 @@ index 7dc59dcc0..769a50c00 100644
|
||||
else if (!strncmp(hash->hash_name, "MD4", 3))
|
||||
return EVP_md4();
|
||||
diff --git a/src/lib/krad/attr.c b/src/lib/krad/attr.c
|
||||
index 9c13d9d75..275327e67 100644
|
||||
index 9c13d9d75..42d354a3b 100644
|
||||
--- a/src/lib/krad/attr.c
|
||||
+++ b/src/lib/krad/attr.c
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <k5-int.h>
|
||||
#include "internal.h"
|
||||
|
||||
+#include <openssl/crypto.h>
|
||||
#include <string.h>
|
||||
|
||||
/* RFC 2865 */
|
||||
@@ -38,7 +39,8 @@
|
||||
@@ -38,7 +38,8 @@
|
||||
typedef krb5_error_code
|
||||
(*attribute_transform_fn)(krb5_context ctx, const char *secret,
|
||||
const unsigned char *auth, const krb5_data *in,
|
||||
@ -204,7 +216,7 @@ index 9c13d9d75..275327e67 100644
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
@@ -51,12 +53,14 @@ typedef struct {
|
||||
@@ -51,12 +52,14 @@ typedef struct {
|
||||
static krb5_error_code
|
||||
user_password_encode(krb5_context ctx, const char *secret,
|
||||
const unsigned char *auth, const krb5_data *in,
|
||||
@ -221,7 +233,7 @@ index 9c13d9d75..275327e67 100644
|
||||
|
||||
static const attribute_record attributes[UCHAR_MAX] = {
|
||||
{"User-Name", 1, MAX_ATTRSIZE, NULL, NULL},
|
||||
@@ -128,7 +132,8 @@ static const attribute_record attributes[UCHAR_MAX] = {
|
||||
@@ -128,7 +131,8 @@ static const attribute_record attributes[UCHAR_MAX] = {
|
||||
static krb5_error_code
|
||||
user_password_encode(krb5_context ctx, const char *secret,
|
||||
const unsigned char *auth, const krb5_data *in,
|
||||
@ -231,20 +243,21 @@ index 9c13d9d75..275327e67 100644
|
||||
{
|
||||
const unsigned char *indx;
|
||||
krb5_error_code retval;
|
||||
@@ -154,8 +159,14 @@ user_password_encode(krb5_context ctx, const char *secret,
|
||||
@@ -154,8 +158,15 @@ user_password_encode(krb5_context ctx, const char *secret,
|
||||
for (blck = 0, indx = auth; blck * BLOCKSIZE < len; blck++) {
|
||||
memcpy(tmp.data + seclen, indx, BLOCKSIZE);
|
||||
|
||||
- retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0, &tmp,
|
||||
- &sum);
|
||||
+ if (FIPS_mode()) {
|
||||
+ if (kr_use_fips(ctx)) {
|
||||
+ /* Skip encryption here. Taint so that we won't pass it out of
|
||||
+ * the machine by accident. */
|
||||
+ *is_fips = TRUE;
|
||||
+ sum.contents = calloc(1, BLOCKSIZE);
|
||||
+ } else
|
||||
+ } else {
|
||||
+ retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0, &tmp,
|
||||
+ &sum);
|
||||
+ }
|
||||
if (retval != 0) {
|
||||
zap(tmp.data, tmp.length);
|
||||
zap(outbuf, len);
|
||||
@ -258,24 +271,25 @@ index 9c13d9d75..275327e67 100644
|
||||
{
|
||||
const unsigned char *indx;
|
||||
krb5_error_code retval;
|
||||
@@ -204,8 +216,14 @@ user_password_decode(krb5_context ctx, const char *secret,
|
||||
@@ -204,8 +216,15 @@ user_password_decode(krb5_context ctx, const char *secret,
|
||||
for (blck = 0, indx = auth; blck * BLOCKSIZE < in->length; blck++) {
|
||||
memcpy(tmp.data + seclen, indx, BLOCKSIZE);
|
||||
|
||||
- retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0,
|
||||
- &tmp, &sum);
|
||||
+ if (FIPS_mode()) {
|
||||
+ if (kr_use_fips(ctx)) {
|
||||
+ /* Skip encryption here. Taint so that we won't pass it out of
|
||||
+ * the machine by accident. */
|
||||
+ *is_fips = TRUE;
|
||||
+ sum.contents = calloc(1, BLOCKSIZE);
|
||||
+ } else
|
||||
+ } else {
|
||||
+ retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0,
|
||||
+ &tmp, &sum);
|
||||
+ }
|
||||
if (retval != 0) {
|
||||
zap(tmp.data, tmp.length);
|
||||
zap(outbuf, in->length);
|
||||
@@ -248,7 +266,7 @@ krb5_error_code
|
||||
@@ -248,7 +267,7 @@ krb5_error_code
|
||||
kr_attr_encode(krb5_context ctx, const char *secret,
|
||||
const unsigned char *auth, krad_attr type,
|
||||
const krb5_data *in, unsigned char outbuf[MAX_ATTRSIZE],
|
||||
@ -284,7 +298,7 @@ index 9c13d9d75..275327e67 100644
|
||||
{
|
||||
krb5_error_code retval;
|
||||
|
||||
@@ -265,7 +283,8 @@ kr_attr_encode(krb5_context ctx, const char *secret,
|
||||
@@ -265,7 +284,8 @@ kr_attr_encode(krb5_context ctx, const char *secret,
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -294,7 +308,7 @@ index 9c13d9d75..275327e67 100644
|
||||
}
|
||||
|
||||
krb5_error_code
|
||||
@@ -274,6 +293,7 @@ kr_attr_decode(krb5_context ctx, const char *secret, const unsigned char *auth,
|
||||
@@ -274,6 +294,7 @@ kr_attr_decode(krb5_context ctx, const char *secret, const unsigned char *auth,
|
||||
unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen)
|
||||
{
|
||||
krb5_error_code retval;
|
||||
@ -302,7 +316,7 @@ index 9c13d9d75..275327e67 100644
|
||||
|
||||
retval = kr_attr_valid(type, in);
|
||||
if (retval != 0)
|
||||
@@ -288,7 +308,8 @@ kr_attr_decode(krb5_context ctx, const char *secret, const unsigned char *auth,
|
||||
@@ -288,7 +309,8 @@ kr_attr_decode(krb5_context ctx, const char *secret, const unsigned char *auth,
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -336,10 +350,19 @@ index 03c613716..d89982a13 100644
|
||||
return retval;
|
||||
|
||||
diff --git a/src/lib/krad/internal.h b/src/lib/krad/internal.h
|
||||
index 996a89372..a53ce31ce 100644
|
||||
index 996a89372..312dc8258 100644
|
||||
--- a/src/lib/krad/internal.h
|
||||
+++ b/src/lib/krad/internal.h
|
||||
@@ -49,6 +49,13 @@
|
||||
@@ -39,6 +39,8 @@
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
|
||||
+#include <openssl/crypto.h>
|
||||
+
|
||||
#ifndef UCHAR_MAX
|
||||
#define UCHAR_MAX 255
|
||||
#endif
|
||||
@@ -49,6 +51,13 @@
|
||||
|
||||
typedef struct krad_remote_st krad_remote;
|
||||
|
||||
@ -353,7 +376,7 @@ index 996a89372..a53ce31ce 100644
|
||||
/* Validate constraints of an attribute. */
|
||||
krb5_error_code
|
||||
kr_attr_valid(krad_attr type, const krb5_data *data);
|
||||
@@ -57,7 +64,8 @@ kr_attr_valid(krad_attr type, const krb5_data *data);
|
||||
@@ -57,7 +66,8 @@ kr_attr_valid(krad_attr type, const krb5_data *data);
|
||||
krb5_error_code
|
||||
kr_attr_encode(krb5_context ctx, const char *secret, const unsigned char *auth,
|
||||
krad_attr type, const krb5_data *in,
|
||||
@ -363,7 +386,7 @@ index 996a89372..a53ce31ce 100644
|
||||
|
||||
/* Decode an attribute. */
|
||||
krb5_error_code
|
||||
@@ -69,7 +77,8 @@ kr_attr_decode(krb5_context ctx, const char *secret, const unsigned char *auth,
|
||||
@@ -69,7 +79,8 @@ kr_attr_decode(krb5_context ctx, const char *secret, const unsigned char *auth,
|
||||
krb5_error_code
|
||||
kr_attrset_encode(const krad_attrset *set, const char *secret,
|
||||
const unsigned char *auth,
|
||||
@ -373,19 +396,29 @@ index 996a89372..a53ce31ce 100644
|
||||
|
||||
/* Decode attributes from a buffer. */
|
||||
krb5_error_code
|
||||
@@ -152,4 +163,17 @@ gai_error_code(int err)
|
||||
}
|
||||
}
|
||||
|
||||
+static inline krb5_boolean
|
||||
+kr_use_fips(krb5_context ctx)
|
||||
+{
|
||||
+ int val = 0;
|
||||
+
|
||||
+ if (!FIPS_mode())
|
||||
+ return 0;
|
||||
+
|
||||
+ profile_get_boolean(ctx->profile, "libdefaults",
|
||||
+ "radius_md5_fips_override", NULL, 0, &val);
|
||||
+ return !val;
|
||||
+}
|
||||
+
|
||||
#endif /* INTERNAL_H_ */
|
||||
diff --git a/src/lib/krad/packet.c b/src/lib/krad/packet.c
|
||||
index c597174b6..794ac84c4 100644
|
||||
index c597174b6..fc2d24800 100644
|
||||
--- a/src/lib/krad/packet.c
|
||||
+++ b/src/lib/krad/packet.c
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
+#include <openssl/crypto.h>
|
||||
|
||||
typedef unsigned char uchar;
|
||||
|
||||
@@ -53,12 +54,6 @@ typedef unsigned char uchar;
|
||||
@@ -53,12 +53,6 @@ typedef unsigned char uchar;
|
||||
#define pkt_auth(p) ((uchar *)offset(&(p)->pkt, OFFSET_AUTH))
|
||||
#define pkt_attr(p) ((unsigned char *)offset(&(p)->pkt, OFFSET_ATTR))
|
||||
|
||||
@ -398,19 +431,20 @@ index c597174b6..794ac84c4 100644
|
||||
typedef struct {
|
||||
uchar x[(UCHAR_MAX + 1) / 8];
|
||||
} idmap;
|
||||
@@ -187,8 +182,13 @@ auth_generate_response(krb5_context ctx, const char *secret,
|
||||
@@ -187,8 +181,14 @@ auth_generate_response(krb5_context ctx, const char *secret,
|
||||
memcpy(data.data + response->pkt.length, secret, strlen(secret));
|
||||
|
||||
/* Hash it. */
|
||||
- retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0, &data,
|
||||
- &hash);
|
||||
+ if (FIPS_mode()) {
|
||||
+ if (kr_use_fips(ctx)) {
|
||||
+ /* This checksum does very little security-wise anyway, so don't
|
||||
+ * taint. */
|
||||
+ hash.contents = calloc(1, AUTH_FIELD_SIZE);
|
||||
+ } else
|
||||
+ } else {
|
||||
+ retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0, &data,
|
||||
+ &hash);
|
||||
+ }
|
||||
free(data.data);
|
||||
if (retval != 0)
|
||||
return retval;
|
@ -0,0 +1,156 @@
|
||||
From 10b32480395a01798b21818e884a593930b400d1 Mon Sep 17 00:00:00 2001
|
||||
From: Julien Rische <jrische@redhat.com>
|
||||
Date: Wed, 27 Apr 2022 15:29:08 +0200
|
||||
Subject: [PATCH] Fix dejagnu unit tests directory name for RPC lib
|
||||
|
||||
This commit renames RPC library's unit tests directory to match the
|
||||
newly enforced naming convention of dejagnu.
|
||||
|
||||
Resolves: rhbz#2070879
|
||||
|
||||
Signed-off-by: Julien Rische <jrische@redhat.com>
|
||||
---
|
||||
src/configure.ac | 2 +-
|
||||
src/lib/rpc/Makefile.in | 2 +-
|
||||
src/lib/rpc/{unit-test => testsuite}/Makefile.in | 10 +++++-----
|
||||
src/lib/rpc/{unit-test => testsuite}/client.c | 0
|
||||
src/lib/rpc/{unit-test => testsuite}/config/unix.exp | 0
|
||||
src/lib/rpc/{unit-test => testsuite}/deps | 0
|
||||
src/lib/rpc/{unit-test => testsuite}/lib/helpers.exp | 0
|
||||
.../rpc/{unit-test => testsuite}/rpc_test.0/expire.exp | 0
|
||||
.../{unit-test => testsuite}/rpc_test.0/fullrun.exp | 0
|
||||
.../rpc/{unit-test => testsuite}/rpc_test.0/gsserr.exp | 0
|
||||
src/lib/rpc/{unit-test => testsuite}/rpc_test.h | 0
|
||||
src/lib/rpc/{unit-test => testsuite}/rpc_test.x | 0
|
||||
src/lib/rpc/{unit-test => testsuite}/rpc_test_clnt.c | 0
|
||||
src/lib/rpc/{unit-test => testsuite}/rpc_test_svc.c | 0
|
||||
src/lib/rpc/{unit-test => testsuite}/server.c | 0
|
||||
15 files changed, 7 insertions(+), 7 deletions(-)
|
||||
rename src/lib/rpc/{unit-test => testsuite}/Makefile.in (93%)
|
||||
rename src/lib/rpc/{unit-test => testsuite}/client.c (100%)
|
||||
rename src/lib/rpc/{unit-test => testsuite}/config/unix.exp (100%)
|
||||
rename src/lib/rpc/{unit-test => testsuite}/deps (100%)
|
||||
rename src/lib/rpc/{unit-test => testsuite}/lib/helpers.exp (100%)
|
||||
rename src/lib/rpc/{unit-test => testsuite}/rpc_test.0/expire.exp (100%)
|
||||
rename src/lib/rpc/{unit-test => testsuite}/rpc_test.0/fullrun.exp (100%)
|
||||
rename src/lib/rpc/{unit-test => testsuite}/rpc_test.0/gsserr.exp (100%)
|
||||
rename src/lib/rpc/{unit-test => testsuite}/rpc_test.h (100%)
|
||||
rename src/lib/rpc/{unit-test => testsuite}/rpc_test.x (100%)
|
||||
rename src/lib/rpc/{unit-test => testsuite}/rpc_test_clnt.c (100%)
|
||||
rename src/lib/rpc/{unit-test => testsuite}/rpc_test_svc.c (100%)
|
||||
rename src/lib/rpc/{unit-test => testsuite}/server.c (100%)
|
||||
|
||||
diff --git a/src/configure.ac b/src/configure.ac
|
||||
index 37e36b76d..2a48aa83d 100644
|
||||
--- a/src/configure.ac
|
||||
+++ b/src/configure.ac
|
||||
@@ -1497,7 +1497,7 @@ V5_AC_OUTPUT_MAKEFILE(.
|
||||
lib/gssapi lib/gssapi/generic lib/gssapi/krb5 lib/gssapi/spnego
|
||||
lib/gssapi/mechglue
|
||||
|
||||
- lib/rpc lib/rpc/unit-test
|
||||
+ lib/rpc lib/rpc/testsuite
|
||||
|
||||
lib/kadm5 lib/kadm5/clnt lib/kadm5/srv lib/kadm5/testsuite
|
||||
lib/krad
|
||||
diff --git a/src/lib/rpc/Makefile.in b/src/lib/rpc/Makefile.in
|
||||
index 6b5f1e70a..78c7a1326 100644
|
||||
--- a/src/lib/rpc/Makefile.in
|
||||
+++ b/src/lib/rpc/Makefile.in
|
||||
@@ -2,7 +2,7 @@ mydir=lib$(S)rpc
|
||||
BUILDTOP=$(REL)..$(S)..
|
||||
DEFINES = -DGSSAPI_KRB5 -DDEBUG_GSSAPI=0 -DGSSRPC__IMPL
|
||||
|
||||
-SUBDIRS=unit-test
|
||||
+SUBDIRS=testsuite
|
||||
|
||||
##DOSBUILDTOP = ..\..
|
||||
##DOSLIBNAME=libgssrpc.lib
|
||||
diff --git a/src/lib/rpc/unit-test/Makefile.in b/src/lib/rpc/testsuite/Makefile.in
|
||||
similarity index 93%
|
||||
rename from src/lib/rpc/unit-test/Makefile.in
|
||||
rename to src/lib/rpc/testsuite/Makefile.in
|
||||
index 0b6e5203d..0fab26c10 100644
|
||||
--- a/src/lib/rpc/unit-test/Makefile.in
|
||||
+++ b/src/lib/rpc/testsuite/Makefile.in
|
||||
@@ -1,4 +1,4 @@
|
||||
-mydir=lib$(S)rpc$(S)unit-test
|
||||
+mydir=lib$(S)rpc$(S)testsuite
|
||||
BUILDTOP=$(REL)..$(S)..$(S)..
|
||||
|
||||
OBJS= client.o rpc_test_clnt.o rpc_test_svc.o server.o
|
||||
@@ -34,19 +34,19 @@ runenv.exp: Makefile
|
||||
# rm -f rpc_test.h rpc_test_clnt.c rpc_test_svc.c
|
||||
#
|
||||
|
||||
-check unit-test: unit-test-@DO_TEST@
|
||||
+check testsuite: testsuite-@DO_TEST@
|
||||
|
||||
-unit-test-:
|
||||
+testsuite-:
|
||||
@echo "+++"
|
||||
@echo "+++ WARNING: lib/rpc unit tests not run."
|
||||
@echo "+++ Either tcl, runtest, or Perl is unavailable."
|
||||
@echo "+++"
|
||||
@echo 'Skipped rpc tests: runtest or Perl not found' >> $(SKIPTESTS)
|
||||
|
||||
-unit-test-ok: unit-test-body
|
||||
+testsuite-ok: testsuite-body
|
||||
|
||||
PASS=@PASS@
|
||||
-unit-test-body: runenv.sh runenv.exp
|
||||
+testsuite-body: runenv.sh runenv.exp
|
||||
$(RM) krb5cc_rpc_test_*
|
||||
$(ENV_SETUP) $(VALGRIND) $(START_SERVERS)
|
||||
RPC_TEST_KEYTAB=/tmp/rpc_test_keytab.$$$$ ; export RPC_TEST_KEYTAB ; \
|
||||
diff --git a/src/lib/rpc/unit-test/client.c b/src/lib/rpc/testsuite/client.c
|
||||
similarity index 100%
|
||||
rename from src/lib/rpc/unit-test/client.c
|
||||
rename to src/lib/rpc/testsuite/client.c
|
||||
diff --git a/src/lib/rpc/unit-test/config/unix.exp b/src/lib/rpc/testsuite/config/unix.exp
|
||||
similarity index 100%
|
||||
rename from src/lib/rpc/unit-test/config/unix.exp
|
||||
rename to src/lib/rpc/testsuite/config/unix.exp
|
||||
diff --git a/src/lib/rpc/unit-test/deps b/src/lib/rpc/testsuite/deps
|
||||
similarity index 100%
|
||||
rename from src/lib/rpc/unit-test/deps
|
||||
rename to src/lib/rpc/testsuite/deps
|
||||
diff --git a/src/lib/rpc/unit-test/lib/helpers.exp b/src/lib/rpc/testsuite/lib/helpers.exp
|
||||
similarity index 100%
|
||||
rename from src/lib/rpc/unit-test/lib/helpers.exp
|
||||
rename to src/lib/rpc/testsuite/lib/helpers.exp
|
||||
diff --git a/src/lib/rpc/unit-test/rpc_test.0/expire.exp b/src/lib/rpc/testsuite/rpc_test.0/expire.exp
|
||||
similarity index 100%
|
||||
rename from src/lib/rpc/unit-test/rpc_test.0/expire.exp
|
||||
rename to src/lib/rpc/testsuite/rpc_test.0/expire.exp
|
||||
diff --git a/src/lib/rpc/unit-test/rpc_test.0/fullrun.exp b/src/lib/rpc/testsuite/rpc_test.0/fullrun.exp
|
||||
similarity index 100%
|
||||
rename from src/lib/rpc/unit-test/rpc_test.0/fullrun.exp
|
||||
rename to src/lib/rpc/testsuite/rpc_test.0/fullrun.exp
|
||||
diff --git a/src/lib/rpc/unit-test/rpc_test.0/gsserr.exp b/src/lib/rpc/testsuite/rpc_test.0/gsserr.exp
|
||||
similarity index 100%
|
||||
rename from src/lib/rpc/unit-test/rpc_test.0/gsserr.exp
|
||||
rename to src/lib/rpc/testsuite/rpc_test.0/gsserr.exp
|
||||
diff --git a/src/lib/rpc/unit-test/rpc_test.h b/src/lib/rpc/testsuite/rpc_test.h
|
||||
similarity index 100%
|
||||
rename from src/lib/rpc/unit-test/rpc_test.h
|
||||
rename to src/lib/rpc/testsuite/rpc_test.h
|
||||
diff --git a/src/lib/rpc/unit-test/rpc_test.x b/src/lib/rpc/testsuite/rpc_test.x
|
||||
similarity index 100%
|
||||
rename from src/lib/rpc/unit-test/rpc_test.x
|
||||
rename to src/lib/rpc/testsuite/rpc_test.x
|
||||
diff --git a/src/lib/rpc/unit-test/rpc_test_clnt.c b/src/lib/rpc/testsuite/rpc_test_clnt.c
|
||||
similarity index 100%
|
||||
rename from src/lib/rpc/unit-test/rpc_test_clnt.c
|
||||
rename to src/lib/rpc/testsuite/rpc_test_clnt.c
|
||||
diff --git a/src/lib/rpc/unit-test/rpc_test_svc.c b/src/lib/rpc/testsuite/rpc_test_svc.c
|
||||
similarity index 100%
|
||||
rename from src/lib/rpc/unit-test/rpc_test_svc.c
|
||||
rename to src/lib/rpc/testsuite/rpc_test_svc.c
|
||||
diff --git a/src/lib/rpc/unit-test/server.c b/src/lib/rpc/testsuite/server.c
|
||||
similarity index 100%
|
||||
rename from src/lib/rpc/unit-test/server.c
|
||||
rename to src/lib/rpc/testsuite/server.c
|
||||
--
|
||||
2.35.1
|
||||
|
@ -0,0 +1,140 @@
|
||||
From 8ded82fb279198f3fa20fb7c836e77290e7bc6f6 Mon Sep 17 00:00:00 2001
|
||||
From: Julien Rische <jrische@redhat.com>
|
||||
Date: Fri, 24 Mar 2023 16:22:06 +0100
|
||||
Subject: [PATCH] [downstream] Support PAC full checksum w/o ticket checksum
|
||||
|
||||
---
|
||||
doc/appdev/refs/api/index.rst | 1 +
|
||||
src/include/krb5/krb5.hin | 38 +++++++++++++++++++++++++++++++++++
|
||||
src/lib/krb5/krb/pac.c | 10 ++++++++-
|
||||
src/lib/krb5/krb/pac_sign.c | 17 ++++++++++++++++
|
||||
src/lib/krb5/libkrb5.exports | 1 +
|
||||
5 files changed, 66 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/doc/appdev/refs/api/index.rst b/doc/appdev/refs/api/index.rst
|
||||
index d12be47c3c..ff813108bb 100644
|
||||
--- a/doc/appdev/refs/api/index.rst
|
||||
+++ b/doc/appdev/refs/api/index.rst
|
||||
@@ -248,6 +248,7 @@ Rarely used public interfaces
|
||||
krb5_os_localaddr.rst
|
||||
krb5_pac_add_buffer.rst
|
||||
krb5_pac_free.rst
|
||||
+ krb5_pac_full_sign_compat.rst
|
||||
krb5_pac_get_buffer.rst
|
||||
krb5_pac_get_types.rst
|
||||
krb5_pac_init.rst
|
||||
diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin
|
||||
index 12a1d441b8..dbe87561c5 100644
|
||||
--- a/src/include/krb5/krb5.hin
|
||||
+++ b/src/include/krb5/krb5.hin
|
||||
@@ -8392,6 +8392,44 @@ krb5_pac_sign_ext(krb5_context context, krb5_pac pac, krb5_timestamp authtime,
|
||||
const krb5_keyblock *privsvr_key, krb5_boolean with_realm,
|
||||
krb5_data *data);
|
||||
|
||||
+/**
|
||||
+ * Compatibility function used by IPA if the 1.20 KDB diver API is not
|
||||
+ * available. It generates PAC signatures, including the extended KDC one when
|
||||
+ * relevant.
|
||||
+ *
|
||||
+ * It is similar to krb5_kdc_sign_ticket(), except it will not generate the
|
||||
+ * PAC ticket signature, and therefore does not expect encrypted ticket part as
|
||||
+ * parameter.
|
||||
+ *
|
||||
+ * @param [in] context Library context
|
||||
+ * @param [in] pac PAC handle
|
||||
+ * @param [in] authtime Expected timestamp
|
||||
+ * @param [in] client_princ Client principal name (or NULL)
|
||||
+ * @param [in] server_princ Server principal name
|
||||
+ * @param [in] server_key Key for server checksum
|
||||
+ * @param [in] privsvr_key Key for KDC checksum
|
||||
+ * @param [in] with_realm If true, include the realm of @a client_princ
|
||||
+ * @param [out] data Signed PAC encoding
|
||||
+ *
|
||||
+ * This function signs @a pac using the keys @a server_key and @a privsvr_key
|
||||
+ * and returns the signed encoding in @a data. @a pac is modified to include
|
||||
+ * the server and KDC checksum buffers. Use krb5_free_data_contents() to free
|
||||
+ * @a data when it is no longer needed.
|
||||
+ *
|
||||
+ * If @a with_realm is true, the PAC_CLIENT_INFO field of the signed PAC will
|
||||
+ * include the realm of @a client_princ as well as the name. This flag is
|
||||
+ * necessary to generate PACs for cross-realm S4U2Self referrals.
|
||||
+ */
|
||||
+krb5_error_code KRB5_CALLCONV
|
||||
+krb5_pac_full_sign_compat(krb5_context context, krb5_pac pac,
|
||||
+ krb5_timestamp authtime,
|
||||
+ krb5_const_principal client_princ,
|
||||
+ krb5_const_principal server_princ,
|
||||
+ const krb5_keyblock *server_key,
|
||||
+ const krb5_keyblock *privsvr_key,
|
||||
+ krb5_boolean with_realm,
|
||||
+ krb5_data *data);
|
||||
+
|
||||
/**
|
||||
* Sign a PAC, possibly including a ticket signature
|
||||
*
|
||||
diff --git a/src/lib/krb5/krb/pac.c b/src/lib/krb5/krb/pac.c
|
||||
index 9c00178a28..b7fa064100 100644
|
||||
--- a/src/lib/krb5/krb/pac.c
|
||||
+++ b/src/lib/krb5/krb/pac.c
|
||||
@@ -757,9 +757,17 @@ krb5_pac_verify_ext(krb5_context context,
|
||||
krb5_boolean with_realm)
|
||||
{
|
||||
krb5_error_code ret;
|
||||
+ krb5_boolean has_full_chksum;
|
||||
|
||||
if (server != NULL || privsvr != NULL) {
|
||||
- ret = verify_pac_checksums(context, pac, FALSE, server, privsvr);
|
||||
+ /* Fail only if full checksum is present and invalid.
|
||||
+ * Proceed if absent.
|
||||
+ */
|
||||
+ ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_FULL_CHECKSUM, NULL);
|
||||
+ has_full_chksum = ret != ENOENT;
|
||||
+
|
||||
+ ret = verify_pac_checksums(context, pac, has_full_chksum, server,
|
||||
+ privsvr);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
diff --git a/src/lib/krb5/krb/pac_sign.c b/src/lib/krb5/krb/pac_sign.c
|
||||
index 8ea61ac17b..7c3a86d8eb 100644
|
||||
--- a/src/lib/krb5/krb/pac_sign.c
|
||||
+++ b/src/lib/krb5/krb/pac_sign.c
|
||||
@@ -309,6 +309,23 @@ krb5_pac_sign_ext(krb5_context context, krb5_pac pac, krb5_timestamp authtime,
|
||||
with_realm, FALSE, data);
|
||||
}
|
||||
|
||||
+krb5_error_code KRB5_CALLCONV
|
||||
+krb5_pac_full_sign_compat(krb5_context context, krb5_pac pac,
|
||||
+ krb5_timestamp authtime,
|
||||
+ krb5_const_principal client_princ,
|
||||
+ krb5_const_principal server_princ,
|
||||
+ const krb5_keyblock *server_key,
|
||||
+ const krb5_keyblock *privsvr_key,
|
||||
+ krb5_boolean with_realm,
|
||||
+ krb5_data *data)
|
||||
+{
|
||||
+ krb5_boolean is_service_tkt;
|
||||
+
|
||||
+ is_service_tkt = k5_pac_should_have_ticket_signature(server_princ);
|
||||
+ return sign_pac(context, pac, authtime, client_princ, server_key,
|
||||
+ privsvr_key, with_realm, is_service_tkt, data);
|
||||
+}
|
||||
+
|
||||
/* Add a signature over der_enc_tkt in privsvr to pac. der_enc_tkt should be
|
||||
* encoded with a dummy PAC authdata element containing a single zero byte. */
|
||||
static krb5_error_code
|
||||
diff --git a/src/lib/krb5/libkrb5.exports b/src/lib/krb5/libkrb5.exports
|
||||
index 28784ec67c..ac94e0c236 100644
|
||||
--- a/src/lib/krb5/libkrb5.exports
|
||||
+++ b/src/lib/krb5/libkrb5.exports
|
||||
@@ -508,6 +508,7 @@ krb5_os_localaddr
|
||||
krb5_overridekeyname
|
||||
krb5_pac_add_buffer
|
||||
krb5_pac_free
|
||||
+krb5_pac_full_sign_compat
|
||||
krb5_pac_get_buffer
|
||||
krb5_pac_get_types
|
||||
krb5_pac_init
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,342 @@
|
||||
From cc1cd235a6a8c066531a17d5773f601455bedb52 Mon Sep 17 00:00:00 2001
|
||||
From: Julien Rische <jrische@redhat.com>
|
||||
Date: Thu, 31 Mar 2022 18:24:39 +0200
|
||||
Subject: [PATCH] Use newly enforced dejagnu path naming convention
|
||||
|
||||
Since version 1.6.3, dejagnu started to enforce a naming convention that
|
||||
was already in place, but not mandatory: dejagnu test directories have
|
||||
to be named "testsuite". If they don't implicit relative sub-paths
|
||||
resolution (e.g. "lib", "config") is not forking.
|
||||
|
||||
This commit renames kadm5 library's unit tests directory to match this
|
||||
requirement.
|
||||
|
||||
Resolves: rhbz#2070879
|
||||
|
||||
Signed-off-by: Julien Rische <jrische@redhat.com>
|
||||
---
|
||||
src/configure.ac | 2 +-
|
||||
src/lib/kadm5/Makefile.in | 2 +-
|
||||
.../{unit-test => testsuite}/Makefile.in | 28 +++++++++----------
|
||||
.../api.2/crte-policy.exp | 0
|
||||
.../api.2/get-policy.exp | 0
|
||||
.../api.2/mod-policy.exp | 0
|
||||
.../api.current/chpass-principal-v2.exp | 0
|
||||
.../api.current/chpass-principal.exp | 0
|
||||
.../api.current/crte-policy.exp | 0
|
||||
.../api.current/crte-principal.exp | 0
|
||||
.../api.current/destroy.exp | 0
|
||||
.../api.current/dlte-policy.exp | 0
|
||||
.../api.current/dlte-principal.exp | 0
|
||||
.../api.current/get-policy.exp | 0
|
||||
.../api.current/get-principal-v2.exp | 0
|
||||
.../api.current/get-principal.exp | 0
|
||||
.../api.current/init-v2.exp | 0
|
||||
.../api.current/init.exp | 0
|
||||
.../api.current/mod-policy.exp | 0
|
||||
.../api.current/mod-principal-v2.exp | 0
|
||||
.../api.current/mod-principal.exp | 0
|
||||
.../api.current/randkey-principal-v2.exp | 0
|
||||
.../api.current/randkey-principal.exp | 0
|
||||
.../{unit-test => testsuite}/config/unix.exp | 0
|
||||
src/lib/kadm5/{unit-test => testsuite}/deps | 0
|
||||
.../{unit-test => testsuite}/destroy-test.c | 0
|
||||
.../diff-files/destroy-1 | 0
|
||||
.../diff-files/no-diffs | 0
|
||||
.../{unit-test => testsuite}/handle-test.c | 0
|
||||
.../{unit-test => testsuite}/init-test.c | 0
|
||||
.../{unit-test => testsuite}/iter-test.c | 0
|
||||
.../kadm5/{unit-test => testsuite}/lib/lib.t | 2 +-
|
||||
.../{unit-test => testsuite}/lock-test.c | 0
|
||||
.../{unit-test => testsuite}/randkey-test.c | 0
|
||||
.../{unit-test => testsuite}/setkey-test.c | 0
|
||||
.../kadm5/{unit-test => testsuite}/site.exp | 0
|
||||
36 files changed, 17 insertions(+), 17 deletions(-)
|
||||
rename src/lib/kadm5/{unit-test => testsuite}/Makefile.in (86%)
|
||||
rename src/lib/kadm5/{unit-test => testsuite}/api.2/crte-policy.exp (100%)
|
||||
rename src/lib/kadm5/{unit-test => testsuite}/api.2/get-policy.exp (100%)
|
||||
rename src/lib/kadm5/{unit-test => testsuite}/api.2/mod-policy.exp (100%)
|
||||
rename src/lib/kadm5/{unit-test => testsuite}/api.current/chpass-principal-v2.exp (100%)
|
||||
rename src/lib/kadm5/{unit-test => testsuite}/api.current/chpass-principal.exp (100%)
|
||||
rename src/lib/kadm5/{unit-test => testsuite}/api.current/crte-policy.exp (100%)
|
||||
rename src/lib/kadm5/{unit-test => testsuite}/api.current/crte-principal.exp (100%)
|
||||
rename src/lib/kadm5/{unit-test => testsuite}/api.current/destroy.exp (100%)
|
||||
rename src/lib/kadm5/{unit-test => testsuite}/api.current/dlte-policy.exp (100%)
|
||||
rename src/lib/kadm5/{unit-test => testsuite}/api.current/dlte-principal.exp (100%)
|
||||
rename src/lib/kadm5/{unit-test => testsuite}/api.current/get-policy.exp (100%)
|
||||
rename src/lib/kadm5/{unit-test => testsuite}/api.current/get-principal-v2.exp (100%)
|
||||
rename src/lib/kadm5/{unit-test => testsuite}/api.current/get-principal.exp (100%)
|
||||
rename src/lib/kadm5/{unit-test => testsuite}/api.current/init-v2.exp (100%)
|
||||
rename src/lib/kadm5/{unit-test => testsuite}/api.current/init.exp (100%)
|
||||
rename src/lib/kadm5/{unit-test => testsuite}/api.current/mod-policy.exp (100%)
|
||||
rename src/lib/kadm5/{unit-test => testsuite}/api.current/mod-principal-v2.exp (100%)
|
||||
rename src/lib/kadm5/{unit-test => testsuite}/api.current/mod-principal.exp (100%)
|
||||
rename src/lib/kadm5/{unit-test => testsuite}/api.current/randkey-principal-v2.exp (100%)
|
||||
rename src/lib/kadm5/{unit-test => testsuite}/api.current/randkey-principal.exp (100%)
|
||||
rename src/lib/kadm5/{unit-test => testsuite}/config/unix.exp (100%)
|
||||
rename src/lib/kadm5/{unit-test => testsuite}/deps (100%)
|
||||
rename src/lib/kadm5/{unit-test => testsuite}/destroy-test.c (100%)
|
||||
rename src/lib/kadm5/{unit-test => testsuite}/diff-files/destroy-1 (100%)
|
||||
rename src/lib/kadm5/{unit-test => testsuite}/diff-files/no-diffs (100%)
|
||||
rename src/lib/kadm5/{unit-test => testsuite}/handle-test.c (100%)
|
||||
rename src/lib/kadm5/{unit-test => testsuite}/init-test.c (100%)
|
||||
rename src/lib/kadm5/{unit-test => testsuite}/iter-test.c (100%)
|
||||
rename src/lib/kadm5/{unit-test => testsuite}/lib/lib.t (99%)
|
||||
rename src/lib/kadm5/{unit-test => testsuite}/lock-test.c (100%)
|
||||
rename src/lib/kadm5/{unit-test => testsuite}/randkey-test.c (100%)
|
||||
rename src/lib/kadm5/{unit-test => testsuite}/setkey-test.c (100%)
|
||||
rename src/lib/kadm5/{unit-test => testsuite}/site.exp (100%)
|
||||
|
||||
diff --git a/src/configure.ac b/src/configure.ac
|
||||
index 29be532cb..37e36b76d 100644
|
||||
--- a/src/configure.ac
|
||||
+++ b/src/configure.ac
|
||||
@@ -1499,7 +1499,7 @@ V5_AC_OUTPUT_MAKEFILE(.
|
||||
|
||||
lib/rpc lib/rpc/unit-test
|
||||
|
||||
- lib/kadm5 lib/kadm5/clnt lib/kadm5/srv lib/kadm5/unit-test
|
||||
+ lib/kadm5 lib/kadm5/clnt lib/kadm5/srv lib/kadm5/testsuite
|
||||
lib/krad
|
||||
lib/apputils
|
||||
|
||||
diff --git a/src/lib/kadm5/Makefile.in b/src/lib/kadm5/Makefile.in
|
||||
index c4eaad38d..76fc4b548 100644
|
||||
--- a/src/lib/kadm5/Makefile.in
|
||||
+++ b/src/lib/kadm5/Makefile.in
|
||||
@@ -1,6 +1,6 @@
|
||||
mydir=lib$(S)kadm5
|
||||
BUILDTOP=$(REL)..$(S)..
|
||||
-SUBDIRS = clnt srv unit-test
|
||||
+SUBDIRS = clnt srv testsuite
|
||||
|
||||
##DOSBUILDTOP = ..\..
|
||||
|
||||
diff --git a/src/lib/kadm5/unit-test/Makefile.in b/src/lib/kadm5/testsuite/Makefile.in
|
||||
similarity index 86%
|
||||
rename from src/lib/kadm5/unit-test/Makefile.in
|
||||
rename to src/lib/kadm5/testsuite/Makefile.in
|
||||
index 68fa097ff..5a55b786b 100644
|
||||
--- a/src/lib/kadm5/unit-test/Makefile.in
|
||||
+++ b/src/lib/kadm5/testsuite/Makefile.in
|
||||
@@ -1,4 +1,4 @@
|
||||
-mydir=lib$(S)kadm5$(S)unit-test
|
||||
+mydir=lib$(S)kadm5$(S)testsuite
|
||||
BUILDTOP=$(REL)..$(S)..$(S)..
|
||||
KDB_DEP_LIB=$(DL_LIB) $(THREAD_LINKOPTS)
|
||||
|
||||
@@ -61,7 +61,7 @@ runenv.exp: Makefile
|
||||
eval echo "set env\($$i\) \$$$$i"; done > runenv.exp
|
||||
|
||||
#
|
||||
-# The unit-test targets
|
||||
+# The testsuite targets
|
||||
#
|
||||
|
||||
check: check-@DO_TEST@
|
||||
@@ -72,13 +72,13 @@ check-:
|
||||
@echo "+++ Either tcl, runtest, or Perl is unavailable."
|
||||
@echo "+++"
|
||||
|
||||
-check-ok unit-test: unit-test-client unit-test-server
|
||||
+check-ok testsuite: testsuite-client testsuite-server
|
||||
|
||||
-unit-test-client: unit-test-client-setup unit-test-client-body \
|
||||
- unit-test-client-cleanup
|
||||
+testsuite-client: testsuite-client-setup testsuite-client-body \
|
||||
+ testsuite-client-cleanup
|
||||
|
||||
-unit-test-server: unit-test-server-setup unit-test-server-body \
|
||||
- unit-test-server-cleanup
|
||||
+testsuite-server: testsuite-server-setup testsuite-server-body \
|
||||
+ testsuite-server-cleanup
|
||||
|
||||
test-randkey: randkey-test
|
||||
$(ENV_SETUP) $(VALGRIND) ./randkey-test
|
||||
@@ -98,19 +98,19 @@ test-destroy: destroy-test
|
||||
test-setkey-client: client-setkey-test
|
||||
$(ENV_SETUP) $(VALGRIND) ./client-setkey-test testkeys admin admin
|
||||
|
||||
-unit-test-client-setup: runenv.sh
|
||||
+testsuite-client-setup: runenv.sh
|
||||
$(ENV_SETUP) $(VALGRIND) $(START_SERVERS)
|
||||
|
||||
-unit-test-client-cleanup:
|
||||
+testsuite-client-cleanup:
|
||||
$(ENV_SETUP) $(STOP_SERVERS)
|
||||
|
||||
-unit-test-server-setup: runenv.sh
|
||||
+testsuite-server-setup: runenv.sh
|
||||
$(ENV_SETUP) $(VALGRIND) $(START_SERVERS_LOCAL)
|
||||
|
||||
-unit-test-server-cleanup:
|
||||
+testsuite-server-cleanup:
|
||||
$(ENV_SETUP) $(STOP_SERVERS_LOCAL)
|
||||
|
||||
-unit-test-client-body: site.exp test-noauth test-destroy test-handle-client \
|
||||
+testsuite-client-body: site.exp test-noauth test-destroy test-handle-client \
|
||||
test-setkey-client runenv.exp
|
||||
$(ENV_SETUP) $(RUNTEST) --tool api RPC=1 API=$(CLNTTCL) \
|
||||
KINIT=$(BUILDTOP)/clients/kinit/kinit \
|
||||
@@ -121,7 +121,7 @@ unit-test-client-body: site.exp test-noauth test-destroy test-handle-client \
|
||||
-mv api.log capi.log
|
||||
-mv api.sum capi.sum
|
||||
|
||||
-unit-test-server-body: site.exp test-handle-server lock-test
|
||||
+testsuite-server-body: site.exp test-handle-server lock-test
|
||||
$(ENV_SETUP) $(RUNTEST) --tool api RPC=0 API=$(SRVTCL) \
|
||||
LOCKTEST=./lock-test \
|
||||
KADMIN_LOCAL=$(BUILDTOP)/kadmin/cli/kadmin.local \
|
||||
@@ -140,4 +140,4 @@ clean:
|
||||
$(RM) lock-test lock-test.o
|
||||
$(RM) server-iter-test iter-test.o
|
||||
$(RM) server-setkey-test client-setkey-test setkey-test.o
|
||||
- $(RM) *.log *.plog *.sum *.psum unit-test-log.* runenv.exp
|
||||
+ $(RM) *.log *.plog *.sum *.psum testsuite-log.* runenv.exp
|
||||
diff --git a/src/lib/kadm5/unit-test/api.2/crte-policy.exp b/src/lib/kadm5/testsuite/api.2/crte-policy.exp
|
||||
similarity index 100%
|
||||
rename from src/lib/kadm5/unit-test/api.2/crte-policy.exp
|
||||
rename to src/lib/kadm5/testsuite/api.2/crte-policy.exp
|
||||
diff --git a/src/lib/kadm5/unit-test/api.2/get-policy.exp b/src/lib/kadm5/testsuite/api.2/get-policy.exp
|
||||
similarity index 100%
|
||||
rename from src/lib/kadm5/unit-test/api.2/get-policy.exp
|
||||
rename to src/lib/kadm5/testsuite/api.2/get-policy.exp
|
||||
diff --git a/src/lib/kadm5/unit-test/api.2/mod-policy.exp b/src/lib/kadm5/testsuite/api.2/mod-policy.exp
|
||||
similarity index 100%
|
||||
rename from src/lib/kadm5/unit-test/api.2/mod-policy.exp
|
||||
rename to src/lib/kadm5/testsuite/api.2/mod-policy.exp
|
||||
diff --git a/src/lib/kadm5/unit-test/api.current/chpass-principal-v2.exp b/src/lib/kadm5/testsuite/api.current/chpass-principal-v2.exp
|
||||
similarity index 100%
|
||||
rename from src/lib/kadm5/unit-test/api.current/chpass-principal-v2.exp
|
||||
rename to src/lib/kadm5/testsuite/api.current/chpass-principal-v2.exp
|
||||
diff --git a/src/lib/kadm5/unit-test/api.current/chpass-principal.exp b/src/lib/kadm5/testsuite/api.current/chpass-principal.exp
|
||||
similarity index 100%
|
||||
rename from src/lib/kadm5/unit-test/api.current/chpass-principal.exp
|
||||
rename to src/lib/kadm5/testsuite/api.current/chpass-principal.exp
|
||||
diff --git a/src/lib/kadm5/unit-test/api.current/crte-policy.exp b/src/lib/kadm5/testsuite/api.current/crte-policy.exp
|
||||
similarity index 100%
|
||||
rename from src/lib/kadm5/unit-test/api.current/crte-policy.exp
|
||||
rename to src/lib/kadm5/testsuite/api.current/crte-policy.exp
|
||||
diff --git a/src/lib/kadm5/unit-test/api.current/crte-principal.exp b/src/lib/kadm5/testsuite/api.current/crte-principal.exp
|
||||
similarity index 100%
|
||||
rename from src/lib/kadm5/unit-test/api.current/crte-principal.exp
|
||||
rename to src/lib/kadm5/testsuite/api.current/crte-principal.exp
|
||||
diff --git a/src/lib/kadm5/unit-test/api.current/destroy.exp b/src/lib/kadm5/testsuite/api.current/destroy.exp
|
||||
similarity index 100%
|
||||
rename from src/lib/kadm5/unit-test/api.current/destroy.exp
|
||||
rename to src/lib/kadm5/testsuite/api.current/destroy.exp
|
||||
diff --git a/src/lib/kadm5/unit-test/api.current/dlte-policy.exp b/src/lib/kadm5/testsuite/api.current/dlte-policy.exp
|
||||
similarity index 100%
|
||||
rename from src/lib/kadm5/unit-test/api.current/dlte-policy.exp
|
||||
rename to src/lib/kadm5/testsuite/api.current/dlte-policy.exp
|
||||
diff --git a/src/lib/kadm5/unit-test/api.current/dlte-principal.exp b/src/lib/kadm5/testsuite/api.current/dlte-principal.exp
|
||||
similarity index 100%
|
||||
rename from src/lib/kadm5/unit-test/api.current/dlte-principal.exp
|
||||
rename to src/lib/kadm5/testsuite/api.current/dlte-principal.exp
|
||||
diff --git a/src/lib/kadm5/unit-test/api.current/get-policy.exp b/src/lib/kadm5/testsuite/api.current/get-policy.exp
|
||||
similarity index 100%
|
||||
rename from src/lib/kadm5/unit-test/api.current/get-policy.exp
|
||||
rename to src/lib/kadm5/testsuite/api.current/get-policy.exp
|
||||
diff --git a/src/lib/kadm5/unit-test/api.current/get-principal-v2.exp b/src/lib/kadm5/testsuite/api.current/get-principal-v2.exp
|
||||
similarity index 100%
|
||||
rename from src/lib/kadm5/unit-test/api.current/get-principal-v2.exp
|
||||
rename to src/lib/kadm5/testsuite/api.current/get-principal-v2.exp
|
||||
diff --git a/src/lib/kadm5/unit-test/api.current/get-principal.exp b/src/lib/kadm5/testsuite/api.current/get-principal.exp
|
||||
similarity index 100%
|
||||
rename from src/lib/kadm5/unit-test/api.current/get-principal.exp
|
||||
rename to src/lib/kadm5/testsuite/api.current/get-principal.exp
|
||||
diff --git a/src/lib/kadm5/unit-test/api.current/init-v2.exp b/src/lib/kadm5/testsuite/api.current/init-v2.exp
|
||||
similarity index 100%
|
||||
rename from src/lib/kadm5/unit-test/api.current/init-v2.exp
|
||||
rename to src/lib/kadm5/testsuite/api.current/init-v2.exp
|
||||
diff --git a/src/lib/kadm5/unit-test/api.current/init.exp b/src/lib/kadm5/testsuite/api.current/init.exp
|
||||
similarity index 100%
|
||||
rename from src/lib/kadm5/unit-test/api.current/init.exp
|
||||
rename to src/lib/kadm5/testsuite/api.current/init.exp
|
||||
diff --git a/src/lib/kadm5/unit-test/api.current/mod-policy.exp b/src/lib/kadm5/testsuite/api.current/mod-policy.exp
|
||||
similarity index 100%
|
||||
rename from src/lib/kadm5/unit-test/api.current/mod-policy.exp
|
||||
rename to src/lib/kadm5/testsuite/api.current/mod-policy.exp
|
||||
diff --git a/src/lib/kadm5/unit-test/api.current/mod-principal-v2.exp b/src/lib/kadm5/testsuite/api.current/mod-principal-v2.exp
|
||||
similarity index 100%
|
||||
rename from src/lib/kadm5/unit-test/api.current/mod-principal-v2.exp
|
||||
rename to src/lib/kadm5/testsuite/api.current/mod-principal-v2.exp
|
||||
diff --git a/src/lib/kadm5/unit-test/api.current/mod-principal.exp b/src/lib/kadm5/testsuite/api.current/mod-principal.exp
|
||||
similarity index 100%
|
||||
rename from src/lib/kadm5/unit-test/api.current/mod-principal.exp
|
||||
rename to src/lib/kadm5/testsuite/api.current/mod-principal.exp
|
||||
diff --git a/src/lib/kadm5/unit-test/api.current/randkey-principal-v2.exp b/src/lib/kadm5/testsuite/api.current/randkey-principal-v2.exp
|
||||
similarity index 100%
|
||||
rename from src/lib/kadm5/unit-test/api.current/randkey-principal-v2.exp
|
||||
rename to src/lib/kadm5/testsuite/api.current/randkey-principal-v2.exp
|
||||
diff --git a/src/lib/kadm5/unit-test/api.current/randkey-principal.exp b/src/lib/kadm5/testsuite/api.current/randkey-principal.exp
|
||||
similarity index 100%
|
||||
rename from src/lib/kadm5/unit-test/api.current/randkey-principal.exp
|
||||
rename to src/lib/kadm5/testsuite/api.current/randkey-principal.exp
|
||||
diff --git a/src/lib/kadm5/unit-test/config/unix.exp b/src/lib/kadm5/testsuite/config/unix.exp
|
||||
similarity index 100%
|
||||
rename from src/lib/kadm5/unit-test/config/unix.exp
|
||||
rename to src/lib/kadm5/testsuite/config/unix.exp
|
||||
diff --git a/src/lib/kadm5/unit-test/deps b/src/lib/kadm5/testsuite/deps
|
||||
similarity index 100%
|
||||
rename from src/lib/kadm5/unit-test/deps
|
||||
rename to src/lib/kadm5/testsuite/deps
|
||||
diff --git a/src/lib/kadm5/unit-test/destroy-test.c b/src/lib/kadm5/testsuite/destroy-test.c
|
||||
similarity index 100%
|
||||
rename from src/lib/kadm5/unit-test/destroy-test.c
|
||||
rename to src/lib/kadm5/testsuite/destroy-test.c
|
||||
diff --git a/src/lib/kadm5/unit-test/diff-files/destroy-1 b/src/lib/kadm5/testsuite/diff-files/destroy-1
|
||||
similarity index 100%
|
||||
rename from src/lib/kadm5/unit-test/diff-files/destroy-1
|
||||
rename to src/lib/kadm5/testsuite/diff-files/destroy-1
|
||||
diff --git a/src/lib/kadm5/unit-test/diff-files/no-diffs b/src/lib/kadm5/testsuite/diff-files/no-diffs
|
||||
similarity index 100%
|
||||
rename from src/lib/kadm5/unit-test/diff-files/no-diffs
|
||||
rename to src/lib/kadm5/testsuite/diff-files/no-diffs
|
||||
diff --git a/src/lib/kadm5/unit-test/handle-test.c b/src/lib/kadm5/testsuite/handle-test.c
|
||||
similarity index 100%
|
||||
rename from src/lib/kadm5/unit-test/handle-test.c
|
||||
rename to src/lib/kadm5/testsuite/handle-test.c
|
||||
diff --git a/src/lib/kadm5/unit-test/init-test.c b/src/lib/kadm5/testsuite/init-test.c
|
||||
similarity index 100%
|
||||
rename from src/lib/kadm5/unit-test/init-test.c
|
||||
rename to src/lib/kadm5/testsuite/init-test.c
|
||||
diff --git a/src/lib/kadm5/unit-test/iter-test.c b/src/lib/kadm5/testsuite/iter-test.c
|
||||
similarity index 100%
|
||||
rename from src/lib/kadm5/unit-test/iter-test.c
|
||||
rename to src/lib/kadm5/testsuite/iter-test.c
|
||||
diff --git a/src/lib/kadm5/unit-test/lib/lib.t b/src/lib/kadm5/testsuite/lib/lib.t
|
||||
similarity index 99%
|
||||
rename from src/lib/kadm5/unit-test/lib/lib.t
|
||||
rename to src/lib/kadm5/testsuite/lib/lib.t
|
||||
index 3444775cf..327946849 100644
|
||||
--- a/src/lib/kadm5/unit-test/lib/lib.t
|
||||
+++ b/src/lib/kadm5/testsuite/lib/lib.t
|
||||
@@ -226,7 +226,7 @@ proc end_dump_compare {name} {
|
||||
global RPC
|
||||
|
||||
if { ! $RPC } {
|
||||
-# set file $TOP/admin/lib/unit-test/diff-files/$name
|
||||
+# set file $TOP/admin/lib/testsuite/diff-files/$name
|
||||
# exec $env(SIMPLE_DUMP) > /tmp/dump.after
|
||||
# exec $env(COMPARE_DUMP) /tmp/dump.before /tmp/dump.after $file
|
||||
}
|
||||
diff --git a/src/lib/kadm5/unit-test/lock-test.c b/src/lib/kadm5/testsuite/lock-test.c
|
||||
similarity index 100%
|
||||
rename from src/lib/kadm5/unit-test/lock-test.c
|
||||
rename to src/lib/kadm5/testsuite/lock-test.c
|
||||
diff --git a/src/lib/kadm5/unit-test/randkey-test.c b/src/lib/kadm5/testsuite/randkey-test.c
|
||||
similarity index 100%
|
||||
rename from src/lib/kadm5/unit-test/randkey-test.c
|
||||
rename to src/lib/kadm5/testsuite/randkey-test.c
|
||||
diff --git a/src/lib/kadm5/unit-test/setkey-test.c b/src/lib/kadm5/testsuite/setkey-test.c
|
||||
similarity index 100%
|
||||
rename from src/lib/kadm5/unit-test/setkey-test.c
|
||||
rename to src/lib/kadm5/testsuite/setkey-test.c
|
||||
diff --git a/src/lib/kadm5/unit-test/site.exp b/src/lib/kadm5/testsuite/site.exp
|
||||
similarity index 100%
|
||||
rename from src/lib/kadm5/unit-test/site.exp
|
||||
rename to src/lib/kadm5/testsuite/site.exp
|
||||
--
|
||||
2.35.1
|
||||
|
69
SOURCES/krb5-krad-larger-attrs.patch
Normal file
69
SOURCES/krb5-krad-larger-attrs.patch
Normal file
@ -0,0 +1,69 @@
|
||||
From b2b7729d71e7ab2cde9c73b40b8e972c82a875a2 Mon Sep 17 00:00:00 2001
|
||||
From: Sumit Bose <sbose@redhat.com>
|
||||
Date: Mon, 8 Nov 2021 17:48:50 +0100
|
||||
Subject: [PATCH] Support larger RADIUS attributes in libkrad
|
||||
|
||||
In kr_attrset_decode(), explicitly treat the length byte as unsigned.
|
||||
Otherwise attributes longer than 125 characters will be rejected with
|
||||
EBADMSG.
|
||||
|
||||
Add a 253-character-long NAS-Identifier attribute to the tests to make
|
||||
sure that attributes with the maximal number of characters are working
|
||||
as expected.
|
||||
|
||||
[ghudson@mit.edu: used uint8_t cast per current practices; edited
|
||||
commit message]
|
||||
|
||||
ticket: 9036 (new)
|
||||
---
|
||||
src/lib/krad/attrset.c | 2 +-
|
||||
src/lib/krad/t_packet.c | 13 +++++++++++++
|
||||
2 files changed, 14 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/lib/krad/attrset.c b/src/lib/krad/attrset.c
|
||||
index d89982a13..6ec031e32 100644
|
||||
--- a/src/lib/krad/attrset.c
|
||||
+++ b/src/lib/krad/attrset.c
|
||||
@@ -218,7 +218,7 @@ kr_attrset_decode(krb5_context ctx, const krb5_data *in, const char *secret,
|
||||
|
||||
for (i = 0; i + 2 < in->length; ) {
|
||||
type = in->data[i++];
|
||||
- tmp = make_data(&in->data[i + 1], in->data[i] - 2);
|
||||
+ tmp = make_data(&in->data[i + 1], (uint8_t)in->data[i] - 2);
|
||||
i += tmp.length + 1;
|
||||
|
||||
retval = (in->length < i) ? EBADMSG : 0;
|
||||
diff --git a/src/lib/krad/t_packet.c b/src/lib/krad/t_packet.c
|
||||
index 0a92e9cc2..c22489144 100644
|
||||
--- a/src/lib/krad/t_packet.c
|
||||
+++ b/src/lib/krad/t_packet.c
|
||||
@@ -57,6 +57,14 @@ make_packet(krb5_context ctx, const krb5_data *username,
|
||||
krb5_error_code retval;
|
||||
const krb5_data *data;
|
||||
int i = 0;
|
||||
+ krb5_data nas_id;
|
||||
+
|
||||
+ nas_id = string2data("12345678901234567890123456789012345678901234567890"
|
||||
+ "12345678901234567890123456789012345678901234567890"
|
||||
+ "12345678901234567890123456789012345678901234567890"
|
||||
+ "12345678901234567890123456789012345678901234567890"
|
||||
+ "12345678901234567890123456789012345678901234567890"
|
||||
+ "123");
|
||||
|
||||
retval = krad_attrset_new(ctx, &set);
|
||||
if (retval != 0)
|
||||
@@ -71,6 +79,11 @@ make_packet(krb5_context ctx, const krb5_data *username,
|
||||
if (retval != 0)
|
||||
goto out;
|
||||
|
||||
+ retval = krad_attrset_add(set, krad_attr_name2num("NAS-Identifier"),
|
||||
+ &nas_id);
|
||||
+ if (retval != 0)
|
||||
+ goto out;
|
||||
+
|
||||
retval = krad_packet_new_request(ctx, "foo",
|
||||
krad_code_name2num("Access-Request"),
|
||||
set, iterator, &i, &tmp);
|
||||
--
|
||||
2.35.3
|
||||
|
171
SOURCES/krb5-krad-remote.patch
Normal file
171
SOURCES/krb5-krad-remote.patch
Normal file
@ -0,0 +1,171 @@
|
||||
From da677b071dadda3700d12d037f5896b166d3546d Mon Sep 17 00:00:00 2001
|
||||
From: Greg Hudson <ghudson@mit.edu>
|
||||
Date: Tue, 9 Nov 2021 13:00:43 -0500
|
||||
Subject: [PATCH] Avoid use after free during libkrad cleanup
|
||||
|
||||
libkrad client requests contain a list of references to remotes, with
|
||||
no back-references or reference counts. To prevent accesses to
|
||||
dangling references during cleanup, cancel all requests on all remotes
|
||||
before freeing any remotes.
|
||||
|
||||
Remove the code for aging out unused servers. This code was fairly
|
||||
safe as all requests referencing a remote should have completed or
|
||||
timed out during an hour of disuse, but in the current design we have
|
||||
no way to guarantee or check that. The set of addresses we send
|
||||
RADIUS requests to will generally be small, so aging out servers is
|
||||
unnecessary.
|
||||
|
||||
ticket: 9035 (new)
|
||||
---
|
||||
src/lib/krad/client.c | 42 ++++++++++++++---------------------------
|
||||
src/lib/krad/internal.h | 4 ++++
|
||||
src/lib/krad/remote.c | 11 ++++++++---
|
||||
3 files changed, 26 insertions(+), 31 deletions(-)
|
||||
|
||||
diff --git a/src/lib/krad/client.c b/src/lib/krad/client.c
|
||||
index 6365dd1c6..810940afc 100644
|
||||
--- a/src/lib/krad/client.c
|
||||
+++ b/src/lib/krad/client.c
|
||||
@@ -64,7 +64,6 @@ struct request_st {
|
||||
|
||||
struct server_st {
|
||||
krad_remote *serv;
|
||||
- time_t last;
|
||||
K5_LIST_ENTRY(server_st) list;
|
||||
};
|
||||
|
||||
@@ -81,15 +80,10 @@ get_server(krad_client *rc, const struct addrinfo *ai, const char *secret,
|
||||
krad_remote **out)
|
||||
{
|
||||
krb5_error_code retval;
|
||||
- time_t currtime;
|
||||
server *srv;
|
||||
|
||||
- if (time(&currtime) == (time_t)-1)
|
||||
- return errno;
|
||||
-
|
||||
K5_LIST_FOREACH(srv, &rc->servers, list) {
|
||||
if (kr_remote_equals(srv->serv, ai, secret)) {
|
||||
- srv->last = currtime;
|
||||
*out = srv->serv;
|
||||
return 0;
|
||||
}
|
||||
@@ -98,7 +92,6 @@ get_server(krad_client *rc, const struct addrinfo *ai, const char *secret,
|
||||
srv = calloc(1, sizeof(server));
|
||||
if (srv == NULL)
|
||||
return ENOMEM;
|
||||
- srv->last = currtime;
|
||||
|
||||
retval = kr_remote_new(rc->kctx, rc->vctx, ai, secret, &srv->serv);
|
||||
if (retval != 0) {
|
||||
@@ -173,28 +166,12 @@ request_new(krad_client *rc, krad_code code, const krad_attrset *attrs,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-/* Close remotes that haven't been used in a while. */
|
||||
-static void
|
||||
-age(struct server_head *head, time_t currtime)
|
||||
-{
|
||||
- server *srv, *tmp;
|
||||
-
|
||||
- K5_LIST_FOREACH_SAFE(srv, head, list, tmp) {
|
||||
- if (currtime == (time_t)-1 || currtime - srv->last > 60 * 60) {
|
||||
- K5_LIST_REMOVE(srv, list);
|
||||
- kr_remote_free(srv->serv);
|
||||
- free(srv);
|
||||
- }
|
||||
- }
|
||||
-}
|
||||
-
|
||||
/* Handle a response from a server (or related errors). */
|
||||
static void
|
||||
on_response(krb5_error_code retval, const krad_packet *reqp,
|
||||
const krad_packet *rspp, void *data)
|
||||
{
|
||||
request *req = data;
|
||||
- time_t currtime;
|
||||
size_t i;
|
||||
|
||||
/* Do nothing if we are already completed. */
|
||||
@@ -221,10 +198,6 @@ on_response(krb5_error_code retval, const krad_packet *reqp,
|
||||
for (i = 0; req->remotes[i].remote != NULL; i++)
|
||||
kr_remote_cancel(req->remotes[i].remote, req->remotes[i].packet);
|
||||
|
||||
- /* Age out servers that haven't been used in a while. */
|
||||
- if (time(&currtime) != (time_t)-1)
|
||||
- age(&req->rc->servers, currtime);
|
||||
-
|
||||
request_free(req);
|
||||
}
|
||||
|
||||
@@ -247,10 +220,23 @@ krad_client_new(krb5_context kctx, verto_ctx *vctx, krad_client **out)
|
||||
void
|
||||
krad_client_free(krad_client *rc)
|
||||
{
|
||||
+ server *srv;
|
||||
+
|
||||
if (rc == NULL)
|
||||
return;
|
||||
|
||||
- age(&rc->servers, -1);
|
||||
+ /* Cancel all requests before freeing any remotes, since each request's
|
||||
+ * callback data may contain references to multiple remotes. */
|
||||
+ K5_LIST_FOREACH(srv, &rc->servers, list)
|
||||
+ kr_remote_cancel_all(srv->serv);
|
||||
+
|
||||
+ while (!K5_LIST_EMPTY(&rc->servers)) {
|
||||
+ srv = K5_LIST_FIRST(&rc->servers);
|
||||
+ K5_LIST_REMOVE(srv, list);
|
||||
+ kr_remote_free(srv->serv);
|
||||
+ free(srv);
|
||||
+ }
|
||||
+
|
||||
free(rc);
|
||||
}
|
||||
|
||||
diff --git a/src/lib/krad/internal.h b/src/lib/krad/internal.h
|
||||
index 312dc8258..b086598fb 100644
|
||||
--- a/src/lib/krad/internal.h
|
||||
+++ b/src/lib/krad/internal.h
|
||||
@@ -120,6 +120,10 @@ kr_remote_send(krad_remote *rr, krad_code code, krad_attrset *attrs,
|
||||
void
|
||||
kr_remote_cancel(krad_remote *rr, const krad_packet *pkt);
|
||||
|
||||
+/* Cancel all requests awaiting responses. */
|
||||
+void
|
||||
+kr_remote_cancel_all(krad_remote *rr);
|
||||
+
|
||||
/* Determine if this remote object refers to the remote resource identified
|
||||
* by the addrinfo struct and the secret. */
|
||||
krb5_boolean
|
||||
diff --git a/src/lib/krad/remote.c b/src/lib/krad/remote.c
|
||||
index 0f90443ce..b5dd8cd19 100644
|
||||
--- a/src/lib/krad/remote.c
|
||||
+++ b/src/lib/krad/remote.c
|
||||
@@ -421,15 +421,20 @@ error:
|
||||
return retval;
|
||||
}
|
||||
|
||||
+void
|
||||
+kr_remote_cancel_all(krad_remote *rr)
|
||||
+{
|
||||
+ while (!K5_TAILQ_EMPTY(&rr->list))
|
||||
+ request_finish(K5_TAILQ_FIRST(&rr->list), ECANCELED, NULL);
|
||||
+}
|
||||
+
|
||||
void
|
||||
kr_remote_free(krad_remote *rr)
|
||||
{
|
||||
if (rr == NULL)
|
||||
return;
|
||||
|
||||
- while (!K5_TAILQ_EMPTY(&rr->list))
|
||||
- request_finish(K5_TAILQ_FIRST(&rr->list), ECANCELED, NULL);
|
||||
-
|
||||
+ kr_remote_cancel_all(rr);
|
||||
free(rr->secret);
|
||||
if (rr->info != NULL)
|
||||
free(rr->info->ai_addr);
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1 +1 @@
|
||||
d /var/run/krb5kdc 0755 root root
|
||||
d /run/krb5kdc 0755 root root
|
||||
|
153
SPECS/krb5.spec
153
SPECS/krb5.spec
@ -18,12 +18,12 @@ 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: 5%{?dist}
|
||||
Release: 30%{?dist}
|
||||
|
||||
# lookaside-cached sources; two downloads and a build artifact
|
||||
Source0: https://web.mit.edu/kerberos/dist/krb5/1.17/krb5-%{version}%{prerelease}.tar.gz
|
||||
Source0: https://web.mit.edu/kerberos/dist/krb5/1.18/krb5-%{version}%{prerelease}.tar.gz
|
||||
# rharwood has trust path to signing key and verifies on check-in
|
||||
Source1: https://web.mit.edu/kerberos/dist/krb5/1.17/krb5-%{version}%{prerelease}.tar.gz.asc
|
||||
Source1: https://web.mit.edu/kerberos/dist/krb5/1.18/krb5-%{version}%{prerelease}.tar.gz.asc
|
||||
# This source is generated during the build because it is documentation.
|
||||
# To override this behavior (e.g., new upstream version), do:
|
||||
# tar cfT krb5-1.15.2-pdfs.tar /dev/null
|
||||
@ -53,7 +53,7 @@ Patch4: downstream-netlib-and-dns.patch
|
||||
Patch5: downstream-fix-debuginfo-with-y.tab.c.patch
|
||||
Patch6: downstream-Remove-3des-support.patch
|
||||
Patch7: rhel-Use-backported-version-of-OpenSSL-3-KDF-interfa.patch
|
||||
Patch108: downstream-FIPS-with-PRNG-and-RADIUS-and-MD4.patch
|
||||
Patch8: downstream-FIPS-with-PRNG-and-RADIUS-and-MD4-5.patch
|
||||
Patch110: Allow-certauth-modules-to-set-hw-authent-flag.patch
|
||||
Patch112: Refresh-manually-acquired-creds-from-client-keytab.patch
|
||||
Patch114: Add-finalization-safety-check-to-com_err.patch
|
||||
@ -71,8 +71,44 @@ 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
|
||||
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
|
||||
Patch144: Use-SHA256-instead-of-SHA1-for-PKINIT-CMS-digest.patch
|
||||
Patch145: downstream-Use-newly-enforced-dejagnu-path-naming-convention.patch
|
||||
Patch146: Make-kprop-work-for-dump-files-larger-than-4GB.patch
|
||||
Patch147: Try-harder-to-avoid-password-change-replay-errors.patch
|
||||
Patch148: downstream-Fix-dejagnu-unit-tests-directory-name-for-RPC-lib.patch
|
||||
Patch149: krb5-krad-larger-attrs.patch
|
||||
Patch150: krb5-krad-remote.patch
|
||||
Patch151: Fix-integer-overflows-in-PAC-parsing.patch
|
||||
Patch152: Use-14-instead-of-9-for-unkeyed-SHA-1-checksum.patch
|
||||
Patch153: Add-PAC-ticket-signature-APIs.patch
|
||||
Patch154: Factor-out-PAC-checksum-verification.patch
|
||||
Patch155: Add-PAC-full-checksums.patch
|
||||
Patch156: downstream-Support-PAC-full-checksum-w-o-ticket-chec.patch
|
||||
Patch157: downstream-Allow-to-make-AD-SIGNEDPATH-optional.patch
|
||||
Patch158: End-connection-on-KDC_ERR_SVC_UNAVAILABLE.patch
|
||||
Patch159: Add-request_timeout-configuration-parameter.patch
|
||||
Patch160: Wait-indefinitely-on-KDC-TCP-connections.patch
|
||||
Patch161: Fix-two-unlikely-memory-leaks.patch
|
||||
Patch162: Fix-defcred-leak-in-krb5-gss_inquire_cred.patch
|
||||
Patch163: Add-a-simple-DER-support-header.patch
|
||||
Patch164: Fix-vulnerabilities-in-GSS-message-token-handling.patch
|
||||
Patch165: Remove-PKINIT-RSA-support.patch
|
||||
Patch166: Generate-and-verify-message-MACs-in-libkrad.patch
|
||||
|
||||
License: MIT
|
||||
URL: http://web.mit.edu/kerberos/www/
|
||||
@ -278,7 +314,7 @@ popd
|
||||
# builds going on the same host don't step on each other.
|
||||
cfg="src/kadmin/testing/proto/kdc.conf.proto \
|
||||
src/kadmin/testing/proto/krb5.conf.proto \
|
||||
src/lib/kadm5/unit-test/api.current/init-v2.exp \
|
||||
src/lib/kadm5/testsuite/api.current/init-v2.exp \
|
||||
src/util/k5test.py"
|
||||
LONG_BIT=`getconf LONG_BIT`
|
||||
PORT=`expr 61000 + $LONG_BIT - 48`
|
||||
@ -683,6 +719,109 @@ exit 0
|
||||
%{_libdir}/libkadm5srv_mit.so.*
|
||||
|
||||
%changelog
|
||||
* Thu Oct 17 2024 Julien Rische <jrische@redhat.com> - 1.18.2-30
|
||||
- libkrad: implement support for Message-Authenticator (CVE-2024-3596)
|
||||
Resolves: RHEL-50253
|
||||
- Remove RSA protocol for PKINIT
|
||||
Resolves: RHEL-17616
|
||||
|
||||
* Mon Jul 01 2024 Julien Rische <jrische@redhat.com> - 1.18.2-29
|
||||
- CVE-2024-37370 CVE-2024-37371
|
||||
Fix vulnerabilities in GSS message token handling
|
||||
Resolves: RHEL-45398 RHEL-45386
|
||||
|
||||
* Tue Apr 09 2024 Julien Rische <jrische@redhat.com> - 1.18.2-28
|
||||
- Fix leak of default credentials in gss_inquire_cred()
|
||||
Resolves: RHEL-32258
|
||||
|
||||
* Thu Mar 21 2024 Julien Rische <jrische@redhat.com> - 1.18.2-27
|
||||
- Fix memory leak in GSSAPI interface
|
||||
Resolves: RHEL-27250
|
||||
- Fix memory leak in PMAP RPC interface
|
||||
Resolves: RHEL-27244
|
||||
- Make TCP waiting time configurable
|
||||
Resolves: RHEL-17131
|
||||
|
||||
* Wed Sep 27 2023 Julien Rische <jrische@redhat.com> - 1.18.2-26
|
||||
- Allow to make AD-SIGNEDPATH optional
|
||||
Resolves: RHEL-10514
|
||||
|
||||
* Thu Jul 06 2023 Julien Rische <jrische@redhat.com> - 1.18.2-25
|
||||
- Bump release number
|
||||
|
||||
* Wed Jul 05 2023 Julien Rische <jrische@redhat.com> - 1.18.2-24
|
||||
- Remove downloadable source signature file
|
||||
- Resolves: rhbz#2219654
|
||||
|
||||
* Wed May 31 2023 Julien Rische <jrische@redhat.com> - 1.18.2-23
|
||||
- Support PAC with KDC extended signature and without ticket signature
|
||||
- Resolves: rhbz#2169477
|
||||
|
||||
* Tue Nov 08 2022 Julien Rische <jrische@redhat.com> - 1.18.2-22
|
||||
- Fix integer overflows in PAC parsing (CVE-2022-42898)
|
||||
- Resolves: rhbz#2140968
|
||||
|
||||
* Fri Jul 01 2022 Julien Rische <jrische@redhat.com> - 1.18.2-21
|
||||
- Backport fix of memory use after free during libkrad cleanup
|
||||
- Backport support for larger RADIUS attributes in libkrad
|
||||
- Resolves: rhbz#2103125
|
||||
|
||||
* Wed Apr 27 2022 Julien Rische <jrische@redhat.com> - 1.18.2-19
|
||||
- Try harder to avoid password change replay errors
|
||||
- Resolves: #2077563
|
||||
|
||||
* Wed Apr 13 2022 Julien Rische <jrische@redhat.com> - 1.18.2-18
|
||||
- Fix kprop for propagating dump files larger than 4GB
|
||||
- Resolves: #2026462
|
||||
|
||||
* Mon Mar 21 2022 Julien Rische <jrische@redhat.com> - 1.18.2-15
|
||||
- Backport usage of SHA-256 instead of SHA-1 for PKINIT CMS digest
|
||||
- Resolves: #2066316
|
||||
|
||||
* 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
|
||||
|
||||
* Tue Nov 24 2020 Robbie Harwood <rharwood@redhat.com> - 1.18.2-7
|
||||
- Document -k option in kvno(1) synopsis
|
||||
- Resolves: #1869055
|
||||
|
||||
* Wed Oct 21 2020 Robbie Harwood <rharwood@redhat.com> - 1.18.2-6
|
||||
- Enable MD5 override for FIPS RADIUS
|
||||
- Resolves: #1872689
|
||||
|
||||
* Thu Oct 15 2020 Robbie Harwood <rharwood@redhat.com> - 1.18.2-5.2
|
||||
- Unify kvno option documentation
|
||||
- Resolves: #1869055
|
||||
|
||||
* Wed Oct 14 2020 Robbie Harwood <rharwood@redhat.com> - 1.18.2-5.1
|
||||
- Fix upstream URLs in spec file
|
||||
- Resolves: #1868039
|
||||
|
||||
* Tue Aug 04 2020 Robbie Harwood <rharwood@redhat.com> - 1.18.2-5
|
||||
- Fix leak in KERB_AP_OPTIONS_CBT server support
|
||||
- Resolves: #1860831
|
||||
|
Loading…
Reference in New Issue
Block a user