Compare commits
No commits in common. "c8" and "c8-beta" have entirely different histories.
@ -1,673 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,840 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,619 +0,0 @@
|
|||||||
From 7b5dad42e9d5103b763f3c79b82fc619bd3d2d32 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Julien Rische <jrische@redhat.com>
|
|
||||||
Date: Thu, 3 Apr 2025 16:29:07 +0200
|
|
||||||
Subject: [PATCH] Add PKINIT paChecksum2 from MS-PKCA v20230920
|
|
||||||
|
|
||||||
(This commit was rewrote for CentOS 8 Stream)
|
|
||||||
|
|
||||||
In 2023, Microsoft updated MS-PKCA to add the optional paChecksum2
|
|
||||||
element in the PKAuthenticator sequence. This checksum accepts SHA-1,
|
|
||||||
SHA-256, SHA-384, and SHA-512 digests.
|
|
||||||
|
|
||||||
In Windows Server 2025, this checksum becomes mandatory when using
|
|
||||||
PKINIT with FFDH (but strangely not with ECDH if SHA-1 is configured as
|
|
||||||
allowed).
|
|
||||||
|
|
||||||
[ghudson@mit.edu: refactored crypto interfaces to reduce complexity of
|
|
||||||
calling code]
|
|
||||||
|
|
||||||
ticket: 9166 (new)
|
|
||||||
---
|
|
||||||
src/include/k5-int-pkinit.h | 25 ++--
|
|
||||||
src/lib/krb5/asn.1/asn1_k_encode.c | 18 ++-
|
|
||||||
src/plugins/preauth/pkinit/pkinit.h | 1 +
|
|
||||||
src/plugins/preauth/pkinit/pkinit_clnt.c | 41 +++----
|
|
||||||
src/plugins/preauth/pkinit/pkinit_crypto.h | 18 +++
|
|
||||||
.../preauth/pkinit/pkinit_crypto_openssl.c | 110 ++++++++++++++++++
|
|
||||||
.../preauth/pkinit/pkinit_kdf_constants.c | 24 ++++
|
|
||||||
src/plugins/preauth/pkinit/pkinit_lib.c | 16 ++-
|
|
||||||
src/plugins/preauth/pkinit/pkinit_srv.c | 39 ++-----
|
|
||||||
src/plugins/preauth/pkinit/pkinit_trace.h | 5 +-
|
|
||||||
src/tests/asn.1/krb5_decode_test.c | 2 +-
|
|
||||||
src/tests/asn.1/ktest.c | 7 +-
|
|
||||||
src/tests/asn.1/ktest_equal.c | 2 +-
|
|
||||||
src/tests/asn.1/pkinit_encode.out | 2 +-
|
|
||||||
src/tests/asn.1/pkinit_trval.out | 2 +-
|
|
||||||
15 files changed, 233 insertions(+), 79 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/include/k5-int-pkinit.h b/src/include/k5-int-pkinit.h
|
|
||||||
index c23cfd3043..096f4e6145 100644
|
|
||||||
--- a/src/include/k5-int-pkinit.h
|
|
||||||
+++ b/src/include/k5-int-pkinit.h
|
|
||||||
@@ -36,15 +36,6 @@
|
|
||||||
* pkinit structures
|
|
||||||
*/
|
|
||||||
|
|
||||||
-/* PKAuthenticator */
|
|
||||||
-typedef struct _krb5_pk_authenticator {
|
|
||||||
- krb5_int32 cusec; /* (0..999999) */
|
|
||||||
- krb5_timestamp ctime;
|
|
||||||
- krb5_int32 nonce; /* (0..4294967295) */
|
|
||||||
- krb5_checksum paChecksum;
|
|
||||||
- krb5_data *freshnessToken;
|
|
||||||
-} krb5_pk_authenticator;
|
|
||||||
-
|
|
||||||
/* AlgorithmIdentifier */
|
|
||||||
typedef struct _krb5_algorithm_identifier {
|
|
||||||
krb5_data algorithm; /* OID */
|
|
||||||
@@ -57,6 +48,22 @@ typedef struct _krb5_subject_pk_info {
|
|
||||||
krb5_data subjectPublicKey; /* BIT STRING */
|
|
||||||
} krb5_subject_pk_info;
|
|
||||||
|
|
||||||
+/* PAChecksum2 */
|
|
||||||
+typedef struct _krb5_pachecksum2 {
|
|
||||||
+ krb5_data checksum;
|
|
||||||
+ krb5_algorithm_identifier algorithmIdentifier;
|
|
||||||
+} krb5_pachecksum2;
|
|
||||||
+
|
|
||||||
+/* PKAuthenticator */
|
|
||||||
+typedef struct _krb5_pk_authenticator {
|
|
||||||
+ krb5_int32 cusec; /* (0..999999) */
|
|
||||||
+ krb5_timestamp ctime;
|
|
||||||
+ krb5_int32 nonce; /* (0..4294967295) */
|
|
||||||
+ krb5_data paChecksum;
|
|
||||||
+ krb5_data *freshnessToken; /* Optional */
|
|
||||||
+ krb5_pachecksum2 *paChecksum2; /* Optional */
|
|
||||||
+} krb5_pk_authenticator;
|
|
||||||
+
|
|
||||||
/** AuthPack from RFC 4556*/
|
|
||||||
typedef struct _krb5_auth_pack {
|
|
||||||
krb5_pk_authenticator pkAuthenticator;
|
|
||||||
diff --git a/src/lib/krb5/asn.1/asn1_k_encode.c b/src/lib/krb5/asn.1/asn1_k_encode.c
|
|
||||||
index 39fa8e3bbb..79c845b5d6 100644
|
|
||||||
--- a/src/lib/krb5/asn.1/asn1_k_encode.c
|
|
||||||
+++ b/src/lib/krb5/asn.1/asn1_k_encode.c
|
|
||||||
@@ -1429,20 +1429,30 @@ DEFSEQTYPE(pkinit_supp_pub_info, krb5_pkinit_supp_pub_info,
|
|
||||||
MAKE_ENCODER(encode_krb5_pkinit_supp_pub_info, pkinit_supp_pub_info);
|
|
||||||
MAKE_ENCODER(encode_krb5_sp80056a_other_info, sp80056a_other_info);
|
|
||||||
|
|
||||||
-/* A krb5_checksum encoded as an OCTET STRING, for PKAuthenticator. */
|
|
||||||
-DEFCOUNTEDTYPE(ostring_checksum, krb5_checksum, contents, length, octetstring);
|
|
||||||
+DEFFIELD(pachecksum2_0, krb5_pachecksum2, checksum, 0, ostring_data);
|
|
||||||
+DEFFIELD(pachecksum2_1, krb5_pachecksum2, algorithmIdentifier, 1,
|
|
||||||
+ algorithm_identifier);
|
|
||||||
+static const struct atype_info *pachecksum2_fields[] = {
|
|
||||||
+ &k5_atype_pachecksum2_0, &k5_atype_pachecksum2_1
|
|
||||||
+};
|
|
||||||
+DEFSEQTYPE(pachecksum2, krb5_pachecksum2, pachecksum2_fields);
|
|
||||||
+
|
|
||||||
+DEFPTRTYPE(pachecksum2_ptr, pachecksum2);
|
|
||||||
+DEFOPTIONALZEROTYPE(opt_pachecksum2_ptr, pachecksum2_ptr);
|
|
||||||
|
|
||||||
DEFFIELD(pk_authenticator_0, krb5_pk_authenticator, cusec, 0, int32);
|
|
||||||
DEFFIELD(pk_authenticator_1, krb5_pk_authenticator, ctime, 1, kerberos_time);
|
|
||||||
DEFFIELD(pk_authenticator_2, krb5_pk_authenticator, nonce, 2, int32);
|
|
||||||
DEFFIELD(pk_authenticator_3, krb5_pk_authenticator, paChecksum, 3,
|
|
||||||
- ostring_checksum);
|
|
||||||
+ ostring_data);
|
|
||||||
DEFFIELD(pk_authenticator_4, krb5_pk_authenticator, freshnessToken, 4,
|
|
||||||
opt_ostring_data_ptr);
|
|
||||||
+DEFFIELD(pk_authenticator_5, krb5_pk_authenticator, paChecksum2, 5,
|
|
||||||
+ opt_pachecksum2_ptr);
|
|
||||||
static const struct atype_info *pk_authenticator_fields[] = {
|
|
||||||
&k5_atype_pk_authenticator_0, &k5_atype_pk_authenticator_1,
|
|
||||||
&k5_atype_pk_authenticator_2, &k5_atype_pk_authenticator_3,
|
|
||||||
- &k5_atype_pk_authenticator_4
|
|
||||||
+ &k5_atype_pk_authenticator_4, &k5_atype_pk_authenticator_5
|
|
||||||
};
|
|
||||||
DEFSEQTYPE(pk_authenticator, krb5_pk_authenticator, pk_authenticator_fields);
|
|
||||||
|
|
||||||
diff --git a/src/plugins/preauth/pkinit/pkinit.h b/src/plugins/preauth/pkinit/pkinit.h
|
|
||||||
index ab132d78a9..b4120f3c61 100644
|
|
||||||
--- a/src/plugins/preauth/pkinit/pkinit.h
|
|
||||||
+++ b/src/plugins/preauth/pkinit/pkinit.h
|
|
||||||
@@ -339,6 +339,7 @@ void free_krb5_algorithm_identifiers(krb5_algorithm_identifier ***in);
|
|
||||||
void free_krb5_algorithm_identifier(krb5_algorithm_identifier *in);
|
|
||||||
void free_krb5_kdc_dh_key_info(krb5_kdc_dh_key_info **in);
|
|
||||||
void free_krb5_subject_pk_info(krb5_subject_pk_info **in);
|
|
||||||
+void free_pachecksum2(krb5_context context, krb5_pachecksum2 **in);
|
|
||||||
krb5_error_code pkinit_copy_krb5_data(krb5_data *dst, const krb5_data *src);
|
|
||||||
|
|
||||||
|
|
||||||
diff --git a/src/plugins/preauth/pkinit/pkinit_clnt.c b/src/plugins/preauth/pkinit/pkinit_clnt.c
|
|
||||||
index ca0162897b..e07c05518c 100644
|
|
||||||
--- a/src/plugins/preauth/pkinit/pkinit_clnt.c
|
|
||||||
+++ b/src/plugins/preauth/pkinit/pkinit_clnt.c
|
|
||||||
@@ -57,10 +57,9 @@ use_content_info(krb5_context context, pkinit_req_context req,
|
|
||||||
static krb5_error_code
|
|
||||||
pkinit_as_req_create(krb5_context context, pkinit_context plgctx,
|
|
||||||
pkinit_req_context reqctx, krb5_timestamp ctsec,
|
|
||||||
- krb5_int32 cusec, krb5_ui_4 nonce,
|
|
||||||
- const krb5_checksum *cksum,
|
|
||||||
- krb5_principal client, krb5_principal server,
|
|
||||||
- krb5_data **as_req);
|
|
||||||
+ krb5_int32 cusec, krb5_ui_4 nonce, const krb5_data *cksum,
|
|
||||||
+ const krb5_pachecksum2 *cksum2, krb5_principal client,
|
|
||||||
+ krb5_principal server, krb5_data **as_req);
|
|
||||||
|
|
||||||
static krb5_error_code
|
|
||||||
pkinit_as_rep_parse(krb5_context context, pkinit_context plgctx,
|
|
||||||
@@ -90,7 +89,8 @@ pa_pkinit_gen_req(krb5_context context,
|
|
||||||
krb5_timestamp ctsec = 0;
|
|
||||||
krb5_int32 cusec = 0;
|
|
||||||
krb5_ui_4 nonce = 0;
|
|
||||||
- krb5_checksum cksum;
|
|
||||||
+ krb5_data cksum = empty_data();
|
|
||||||
+ krb5_pachecksum2 *cksum2 = NULL;
|
|
||||||
krb5_data *der_req = NULL;
|
|
||||||
krb5_pa_data **return_pa_data = NULL;
|
|
||||||
|
|
||||||
@@ -119,15 +119,10 @@ pa_pkinit_gen_req(krb5_context context,
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
- retval = krb5_c_make_checksum(context, CKSUMTYPE_SHA1, NULL, 0, der_req,
|
|
||||||
- &cksum);
|
|
||||||
+ retval = crypto_generate_checksums(context, der_req, &cksum, &cksum2);
|
|
||||||
if (retval)
|
|
||||||
goto cleanup;
|
|
||||||
- TRACE_PKINIT_CLIENT_REQ_CHECKSUM(context, &cksum);
|
|
||||||
-#ifdef DEBUG_CKSUM
|
|
||||||
- pkiDebug("calculating checksum on buf size (%d)\n", der_req->length);
|
|
||||||
- print_buffer(der_req->data, der_req->length);
|
|
||||||
-#endif
|
|
||||||
+ TRACE_PKINIT_CLIENT_REQ_CHECKSUMS(context, &cksum, cksum2);
|
|
||||||
|
|
||||||
retval = cb->get_preauth_time(context, rock, TRUE, &ctsec, &cusec);
|
|
||||||
if (retval)
|
|
||||||
@@ -141,7 +136,8 @@ pa_pkinit_gen_req(krb5_context context,
|
|
||||||
nonce = request->nonce;
|
|
||||||
|
|
||||||
retval = pkinit_as_req_create(context, plgctx, reqctx, ctsec, cusec,
|
|
||||||
- nonce, &cksum, request->client, request->server, &out_data);
|
|
||||||
+ nonce, &cksum, cksum2, request->client,
|
|
||||||
+ request->server, &out_data);
|
|
||||||
if (retval) {
|
|
||||||
pkiDebug("error %d on pkinit_as_req_create; aborting PKINIT\n",
|
|
||||||
(int) retval);
|
|
||||||
@@ -169,23 +165,19 @@ pa_pkinit_gen_req(krb5_context context,
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
krb5_free_data(context, der_req);
|
|
||||||
- krb5_free_checksum_contents(context, &cksum);
|
|
||||||
+ krb5_free_data_contents(context, &cksum);
|
|
||||||
+ free_pachecksum2(context, &cksum2);
|
|
||||||
krb5_free_data(context, out_data);
|
|
||||||
krb5_free_pa_data(context, return_pa_data);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
static krb5_error_code
|
|
||||||
-pkinit_as_req_create(krb5_context context,
|
|
||||||
- pkinit_context plgctx,
|
|
||||||
- pkinit_req_context reqctx,
|
|
||||||
- krb5_timestamp ctsec,
|
|
||||||
- krb5_int32 cusec,
|
|
||||||
- krb5_ui_4 nonce,
|
|
||||||
- const krb5_checksum * cksum,
|
|
||||||
- krb5_principal client,
|
|
||||||
- krb5_principal server,
|
|
||||||
- krb5_data ** as_req)
|
|
||||||
+pkinit_as_req_create(krb5_context context, pkinit_context plgctx,
|
|
||||||
+ pkinit_req_context reqctx, krb5_timestamp ctsec,
|
|
||||||
+ krb5_int32 cusec, krb5_ui_4 nonce, const krb5_data *cksum,
|
|
||||||
+ const krb5_pachecksum2 *cksum2, krb5_principal client,
|
|
||||||
+ krb5_principal server, krb5_data **as_req)
|
|
||||||
{
|
|
||||||
krb5_error_code retval = ENOMEM;
|
|
||||||
krb5_subject_pk_info info;
|
|
||||||
@@ -207,6 +199,7 @@ pkinit_as_req_create(krb5_context context,
|
|
||||||
auth_pack.pkAuthenticator.paChecksum = *cksum;
|
|
||||||
if (!reqctx->opts->disable_freshness)
|
|
||||||
auth_pack.pkAuthenticator.freshnessToken = reqctx->freshness_token;
|
|
||||||
+ auth_pack.pkAuthenticator.paChecksum2 = (krb5_pachecksum2 *)cksum2;
|
|
||||||
auth_pack.clientDHNonce.length = 0;
|
|
||||||
auth_pack.clientPublicValue = &info;
|
|
||||||
auth_pack.supportedKDFs = (krb5_data **)supported_kdf_alg_ids;
|
|
||||||
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto.h b/src/plugins/preauth/pkinit/pkinit_crypto.h
|
|
||||||
index f251e41064..d576cd6cef 100644
|
|
||||||
--- a/src/plugins/preauth/pkinit/pkinit_crypto.h
|
|
||||||
+++ b/src/plugins/preauth/pkinit/pkinit_crypto.h
|
|
||||||
@@ -568,6 +568,10 @@ extern const krb5_octet krb5_pkinit_sha256_oid[];
|
|
||||||
extern const size_t krb5_pkinit_sha256_oid_len;
|
|
||||||
extern const krb5_octet krb5_pkinit_sha512_oid[];
|
|
||||||
extern const size_t krb5_pkinit_sha512_oid_len;
|
|
||||||
+extern const krb5_data cms_sha1_id;
|
|
||||||
+extern const krb5_data cms_sha256_id;
|
|
||||||
+extern const krb5_data cms_sha384_id;
|
|
||||||
+extern const krb5_data cms_sha512_id;
|
|
||||||
/**
|
|
||||||
* An ordered set of OIDs, stored as krb5_data, of KDF algorithms
|
|
||||||
* supported by this implementation. The order of this array controls
|
|
||||||
@@ -585,4 +589,18 @@ crypto_req_cert_matching_data(krb5_context context,
|
|
||||||
pkinit_req_crypto_context reqctx,
|
|
||||||
pkinit_cert_matching_data **md_out);
|
|
||||||
|
|
||||||
+/* Generate a SHA-1 checksum over body in *cksum1_out and a SHA-256 checksum
|
|
||||||
+ * over body in *cksum2_out with appropriate metadata. */
|
|
||||||
+krb5_error_code
|
|
||||||
+crypto_generate_checksums(krb5_context context, const krb5_data *body,
|
|
||||||
+ krb5_data *cksum1_out,
|
|
||||||
+ krb5_pachecksum2 **cksum2_out);
|
|
||||||
+
|
|
||||||
+/* Verify the SHA-1 checksum in cksum1 and the tagged checksum in cksum2.
|
|
||||||
+ * cksum2 may be NULL, in which case only cksum1 is verified. */
|
|
||||||
+krb5_error_code
|
|
||||||
+crypto_verify_checksums(krb5_context context, krb5_data *body,
|
|
||||||
+ const krb5_data *cksum1,
|
|
||||||
+ const krb5_pachecksum2 *cksum2);
|
|
||||||
+
|
|
||||||
#endif /* _PKINIT_CRYPTO_H */
|
|
||||||
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
|
|
||||||
index 76ad7526bb..638971fe83 100644
|
|
||||||
--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
|
|
||||||
+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
|
|
||||||
@@ -5413,3 +5413,113 @@ crypto_req_cert_matching_data(krb5_context context,
|
|
||||||
return get_matching_data(context, plgctx, reqctx, reqctx->received_cert,
|
|
||||||
md_out);
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+/* Return the OpenSSL message digest type matching the given CMS OID, or NULL
|
|
||||||
+ * if it doesn't match any of the CMS OIDs we know about. */
|
|
||||||
+static const EVP_MD *
|
|
||||||
+md_from_cms_oid(const krb5_data *alg_id)
|
|
||||||
+{
|
|
||||||
+ if (data_eq(*alg_id, cms_sha1_id))
|
|
||||||
+ return EVP_sha1();
|
|
||||||
+ if (data_eq(*alg_id, cms_sha256_id))
|
|
||||||
+ return EVP_sha256();
|
|
||||||
+ if (data_eq(*alg_id, cms_sha384_id))
|
|
||||||
+ return EVP_sha384();
|
|
||||||
+ if (data_eq(*alg_id, cms_sha512_id))
|
|
||||||
+ return EVP_sha512();
|
|
||||||
+ return NULL;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/* Compute a message digest of the given type over body, placing the result in
|
|
||||||
+ * *digest_out in allocated storage. Return true on success. */
|
|
||||||
+static krb5_boolean
|
|
||||||
+make_digest(const krb5_data *body, const EVP_MD *md, krb5_data *digest_out)
|
|
||||||
+{
|
|
||||||
+ krb5_error_code ret;
|
|
||||||
+ krb5_data d;
|
|
||||||
+
|
|
||||||
+ if (md == NULL)
|
|
||||||
+ return FALSE;
|
|
||||||
+ ret = alloc_data(&d, EVP_MD_size(md));
|
|
||||||
+ if (ret)
|
|
||||||
+ return FALSE;
|
|
||||||
+ if (!EVP_Digest(body->data, body->length, (uint8_t *)d.data, &d.length, md,
|
|
||||||
+ NULL)) {
|
|
||||||
+ free(d.data);
|
|
||||||
+ return FALSE;
|
|
||||||
+ }
|
|
||||||
+ *digest_out = d;
|
|
||||||
+ return TRUE;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/* Return true if digest verifies for the given body and message digest
|
|
||||||
+ * type. */
|
|
||||||
+static krb5_boolean
|
|
||||||
+check_digest(const krb5_data *body, const EVP_MD *md, const krb5_data *digest)
|
|
||||||
+{
|
|
||||||
+ unsigned int digest_len;
|
|
||||||
+ uint8_t buf[EVP_MAX_MD_SIZE];
|
|
||||||
+
|
|
||||||
+ if (md == NULL)
|
|
||||||
+ return FALSE;
|
|
||||||
+ if (!EVP_Digest(body->data, body->length, buf, &digest_len, md, NULL))
|
|
||||||
+ return FALSE;
|
|
||||||
+ return (digest->length == digest_len &&
|
|
||||||
+ CRYPTO_memcmp(digest->data, buf, digest_len) == 0);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+krb5_error_code
|
|
||||||
+crypto_generate_checksums(krb5_context context, const krb5_data *body,
|
|
||||||
+ krb5_data *cksum1_out, krb5_pachecksum2 **cksum2_out)
|
|
||||||
+{
|
|
||||||
+ krb5_data cksum1 = empty_data();
|
|
||||||
+ krb5_pachecksum2 *cksum2 = NULL;
|
|
||||||
+ krb5_error_code ret;
|
|
||||||
+
|
|
||||||
+ if (!make_digest(body, EVP_sha1(), &cksum1))
|
|
||||||
+ goto fail;
|
|
||||||
+
|
|
||||||
+ cksum2 = k5alloc(sizeof(*cksum2), &ret);
|
|
||||||
+ if (cksum2 == NULL)
|
|
||||||
+ goto fail;
|
|
||||||
+
|
|
||||||
+ if (!make_digest(body, EVP_sha256(), &cksum2->checksum))
|
|
||||||
+ goto fail;
|
|
||||||
+
|
|
||||||
+ if (krb5int_copy_data_contents(context, &cms_sha256_id,
|
|
||||||
+ &cksum2->algorithmIdentifier.algorithm))
|
|
||||||
+ goto fail;
|
|
||||||
+
|
|
||||||
+ cksum2->algorithmIdentifier.parameters = empty_data();
|
|
||||||
+
|
|
||||||
+ *cksum1_out = cksum1;
|
|
||||||
+ *cksum2_out = cksum2;
|
|
||||||
+ return 0;
|
|
||||||
+
|
|
||||||
+fail:
|
|
||||||
+ krb5_free_data_contents(context, &cksum1);
|
|
||||||
+ free_pachecksum2(context, &cksum2);
|
|
||||||
+ return KRB5_CRYPTO_INTERNAL;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+krb5_error_code
|
|
||||||
+crypto_verify_checksums(krb5_context context, krb5_data *body,
|
|
||||||
+ const krb5_data *cksum1,
|
|
||||||
+ const krb5_pachecksum2 *cksum2)
|
|
||||||
+{
|
|
||||||
+ const EVP_MD *md;
|
|
||||||
+
|
|
||||||
+ /* RFC 4556 doesn't say what error to return if the checksum doesn't match.
|
|
||||||
+ * Windows returns this one. */
|
|
||||||
+ if (!check_digest(body, EVP_sha1(), cksum1))
|
|
||||||
+ return KRB5KRB_AP_ERR_MODIFIED;
|
|
||||||
+
|
|
||||||
+ if (cksum2 == NULL)
|
|
||||||
+ return 0;
|
|
||||||
+
|
|
||||||
+ md = md_from_cms_oid(&cksum2->algorithmIdentifier.algorithm);
|
|
||||||
+ if (!check_digest(body, md, &cksum2->checksum))
|
|
||||||
+ return KRB5KRB_AP_ERR_MODIFIED;
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
diff --git a/src/plugins/preauth/pkinit/pkinit_kdf_constants.c b/src/plugins/preauth/pkinit/pkinit_kdf_constants.c
|
|
||||||
index 1604f1670a..315fc36866 100644
|
|
||||||
--- a/src/plugins/preauth/pkinit/pkinit_kdf_constants.c
|
|
||||||
+++ b/src/plugins/preauth/pkinit/pkinit_kdf_constants.c
|
|
||||||
@@ -57,3 +57,27 @@ krb5_data const * const supported_kdf_alg_ids[] = {
|
|
||||||
&sha512_id,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
+
|
|
||||||
+/* RFC 3370 sha-1: iso(1) identified-organization(3) oiw(14) secsig(3)
|
|
||||||
+ * algorithm(2) 26 */
|
|
||||||
+static char cms_sha1[] = { 0x2b, 0x0e, 0x03, 0x02, 0x1a };
|
|
||||||
+/* RFC 5754 id-sha256: joint-iso-itu-t(2) country(16) us(840) organization(1)
|
|
||||||
+ * gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1 */
|
|
||||||
+static char cms_sha256[] = {
|
|
||||||
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01
|
|
||||||
+};
|
|
||||||
+/* RFC 5754 id-sha384: joint-iso-itu-t(2) country(16) us(840) organization(1)
|
|
||||||
+ * gov(101) csor(3) nistalgorithm(4) hashalgs(2) 2 */
|
|
||||||
+static char cms_sha384[] = {
|
|
||||||
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02
|
|
||||||
+};
|
|
||||||
+/* RFC 5754 id-sha512: joint-iso-itu-t(2) country(16) us(840) organization(1)
|
|
||||||
+ * gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 */
|
|
||||||
+static char cms_sha512[] = {
|
|
||||||
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+const krb5_data cms_sha1_id = { KV5M_DATA, sizeof(cms_sha1), cms_sha1 };
|
|
||||||
+const krb5_data cms_sha256_id = { KV5M_DATA, sizeof(cms_sha256), cms_sha256 };
|
|
||||||
+const krb5_data cms_sha384_id = { KV5M_DATA, sizeof(cms_sha384), cms_sha384 };
|
|
||||||
+const krb5_data cms_sha512_id = { KV5M_DATA, sizeof(cms_sha512), cms_sha512 };
|
|
||||||
diff --git a/src/plugins/preauth/pkinit/pkinit_lib.c b/src/plugins/preauth/pkinit/pkinit_lib.c
|
|
||||||
index 7af880bf5c..47972bb5eb 100644
|
|
||||||
--- a/src/plugins/preauth/pkinit/pkinit_lib.c
|
|
||||||
+++ b/src/plugins/preauth/pkinit/pkinit_lib.c
|
|
||||||
@@ -29,6 +29,7 @@
|
|
||||||
* SUCH DAMAGES.
|
|
||||||
*/
|
|
||||||
|
|
||||||
+#include "k5-int.h"
|
|
||||||
#include "pkinit.h"
|
|
||||||
|
|
||||||
#define FAKECERT
|
|
||||||
@@ -127,8 +128,9 @@ free_krb5_auth_pack(krb5_auth_pack **in)
|
|
||||||
free((*in)->clientPublicValue->subjectPublicKey.data);
|
|
||||||
free((*in)->clientPublicValue);
|
|
||||||
}
|
|
||||||
- free((*in)->pkAuthenticator.paChecksum.contents);
|
|
||||||
+ free((*in)->pkAuthenticator.paChecksum.data);
|
|
||||||
krb5_free_data(NULL, (*in)->pkAuthenticator.freshnessToken);
|
|
||||||
+ free_pachecksum2(NULL, &(*in)->pkAuthenticator.paChecksum2);
|
|
||||||
if ((*in)->supportedCMSTypes != NULL)
|
|
||||||
free_krb5_algorithm_identifiers(&((*in)->supportedCMSTypes));
|
|
||||||
if ((*in)->supportedKDFs) {
|
|
||||||
@@ -213,6 +215,18 @@ free_krb5_kdc_dh_key_info(krb5_kdc_dh_key_info **in)
|
|
||||||
free(*in);
|
|
||||||
}
|
|
||||||
|
|
||||||
+void
|
|
||||||
+free_pachecksum2(krb5_context context, krb5_pachecksum2 **in)
|
|
||||||
+{
|
|
||||||
+ if (*in == NULL)
|
|
||||||
+ return;
|
|
||||||
+ krb5_free_data_contents(context, &(*in)->checksum);
|
|
||||||
+ krb5_free_data_contents(context, &(*in)->algorithmIdentifier.algorithm);
|
|
||||||
+ krb5_free_data_contents(context, &(*in)->algorithmIdentifier.parameters);
|
|
||||||
+ free(*in);
|
|
||||||
+ *in = NULL;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
void
|
|
||||||
init_krb5_pa_pk_as_req(krb5_pa_pk_as_req **in)
|
|
||||||
{
|
|
||||||
diff --git a/src/plugins/preauth/pkinit/pkinit_srv.c b/src/plugins/preauth/pkinit/pkinit_srv.c
|
|
||||||
index 4eab5a2761..f5b3d98ef8 100644
|
|
||||||
--- a/src/plugins/preauth/pkinit/pkinit_srv.c
|
|
||||||
+++ b/src/plugins/preauth/pkinit/pkinit_srv.c
|
|
||||||
@@ -426,11 +426,12 @@ pkinit_server_verify_padata(krb5_context context,
|
|
||||||
krb5_data authp_data = {0, 0, NULL}, krb5_authz = {0, 0, NULL};
|
|
||||||
krb5_pa_pk_as_req *reqp = NULL;
|
|
||||||
krb5_auth_pack *auth_pack = NULL;
|
|
||||||
+ krb5_pk_authenticator *pka;
|
|
||||||
pkinit_kdc_context plgctx = NULL;
|
|
||||||
pkinit_kdc_req_context reqctx = NULL;
|
|
||||||
krb5_checksum cksum = {0, 0, 0, NULL};
|
|
||||||
krb5_data *der_req = NULL;
|
|
||||||
- krb5_data k5data, *ftoken;
|
|
||||||
+ krb5_data k5data;
|
|
||||||
int is_signed = 1;
|
|
||||||
krb5_pa_data **e_data = NULL;
|
|
||||||
krb5_kdcpreauth_modreq modreq = NULL;
|
|
||||||
@@ -522,8 +523,9 @@ pkinit_server_verify_padata(krb5_context context,
|
|
||||||
pkiDebug("failed to decode krb5_auth_pack\n");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
+ pka = &auth_pack->pkAuthenticator;
|
|
||||||
|
|
||||||
- retval = krb5_check_clockskew(context, auth_pack->pkAuthenticator.ctime);
|
|
||||||
+ retval = krb5_check_clockskew(context, pka->ctime);
|
|
||||||
if (retval)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
@@ -546,36 +548,13 @@ pkinit_server_verify_padata(krb5_context context,
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
der_req = cb->request_body(context, rock);
|
|
||||||
- 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;
|
|
||||||
- }
|
|
||||||
- if (cksum.length != auth_pack->pkAuthenticator.paChecksum.length ||
|
|
||||||
- k5_bcmp(cksum.contents, auth_pack->pkAuthenticator.paChecksum.contents,
|
|
||||||
- cksum.length) != 0) {
|
|
||||||
- pkiDebug("failed to match the checksum\n");
|
|
||||||
-#ifdef DEBUG_CKSUM
|
|
||||||
- pkiDebug("calculating checksum on buf size (%d)\n", req_pkt->length);
|
|
||||||
- print_buffer(req_pkt->data, req_pkt->length);
|
|
||||||
- pkiDebug("received checksum type=%d size=%d ",
|
|
||||||
- auth_pack->pkAuthenticator.paChecksum.checksum_type,
|
|
||||||
- auth_pack->pkAuthenticator.paChecksum.length);
|
|
||||||
- print_buffer(auth_pack->pkAuthenticator.paChecksum.contents,
|
|
||||||
- auth_pack->pkAuthenticator.paChecksum.length);
|
|
||||||
- pkiDebug("expected checksum type=%d size=%d ",
|
|
||||||
- cksum.checksum_type, cksum.length);
|
|
||||||
- print_buffer(cksum.contents, cksum.length);
|
|
||||||
-#endif
|
|
||||||
-
|
|
||||||
- retval = KRB5KDC_ERR_PA_CHECKSUM_MUST_BE_INCLUDED;
|
|
||||||
+ retval = crypto_verify_checksums(context, der_req, &pka->paChecksum,
|
|
||||||
+ pka->paChecksum2);
|
|
||||||
+ if (retval)
|
|
||||||
goto cleanup;
|
|
||||||
- }
|
|
||||||
|
|
||||||
- ftoken = auth_pack->pkAuthenticator.freshnessToken;
|
|
||||||
- if (ftoken != NULL) {
|
|
||||||
- retval = cb->check_freshness_token(context, rock, ftoken);
|
|
||||||
+ if (pka->freshnessToken != NULL) {
|
|
||||||
+ retval = cb->check_freshness_token(context, rock, pka->freshnessToken);
|
|
||||||
if (retval)
|
|
||||||
goto cleanup;
|
|
||||||
valid_freshness_token = TRUE;
|
|
||||||
diff --git a/src/plugins/preauth/pkinit/pkinit_trace.h b/src/plugins/preauth/pkinit/pkinit_trace.h
|
|
||||||
index 4f80e0b9b6..3017f9e059 100644
|
|
||||||
--- a/src/plugins/preauth/pkinit/pkinit_trace.h
|
|
||||||
+++ b/src/plugins/preauth/pkinit/pkinit_trace.h
|
|
||||||
@@ -58,8 +58,9 @@
|
|
||||||
TRACE(c, "PKINIT client verified DH reply")
|
|
||||||
#define TRACE_PKINIT_CLIENT_REP_DH_FAIL(c) \
|
|
||||||
TRACE(c, "PKINIT client could not verify DH reply")
|
|
||||||
-#define TRACE_PKINIT_CLIENT_REQ_CHECKSUM(c, cksum) \
|
|
||||||
- TRACE(c, "PKINIT client computed kdc-req-body checksum {cksum}", cksum)
|
|
||||||
+#define TRACE_PKINIT_CLIENT_REQ_CHECKSUMS(c, ck1, ck2) \
|
|
||||||
+ TRACE(c, "PKINIT client computed checksums: {hexdata} {hexdata}", \
|
|
||||||
+ ck1, &(ck2)->checksum)
|
|
||||||
#define TRACE_PKINIT_CLIENT_REQ_DH(c) \
|
|
||||||
TRACE(c, "PKINIT client making DH request")
|
|
||||||
#define TRACE_PKINIT_CLIENT_SAN_CONFIG_DNSNAME(c, host) \
|
|
||||||
diff --git a/src/tests/asn.1/krb5_decode_test.c b/src/tests/asn.1/krb5_decode_test.c
|
|
||||||
index 7a116b40d9..9946ebd3a5 100644
|
|
||||||
--- a/src/tests/asn.1/krb5_decode_test.c
|
|
||||||
+++ b/src/tests/asn.1/krb5_decode_test.c
|
|
||||||
@@ -1173,7 +1173,7 @@ int main(argc, argv)
|
|
||||||
/* decode_krb5_auth_pack */
|
|
||||||
{
|
|
||||||
setup(krb5_auth_pack,ktest_make_sample_auth_pack);
|
|
||||||
- decode_run("krb5_auth_pack","","30 81 93 A0 29 30 27 A0 05 02 03 01 E2 40 A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A2 03 02 01 2A A3 06 04 04 31 32 33 34 A1 22 30 20 30 13 06 09 2A 86 48 86 F7 12 01 02 02 04 06 70 61 72 61 6D 73 03 09 00 6B 72 62 35 64 61 74 61 A2 24 30 22 30 13 06 09 2A 86 48 86 F7 12 01 02 02 04 06 70 61 72 61 6D 73 30 0B 06 09 2A 86 48 86 F7 12 01 02 02 A3 0A 04 08 6B 72 62 35 64 61 74 61 A4 10 30 0E 30 0C A0 0A 06 08 6B 72 62 35 64 61 74 61",
|
|
||||||
+ decode_run("krb5_auth_pack","","30 81 97 A0 2D 30 2B A0 05 02 03 01 E2 40 A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A2 03 02 01 2A A3 0A 04 08 6B 72 62 35 64 61 74 61 A1 22 30 20 30 13 06 09 2A 86 48 86 F7 12 01 02 02 04 06 70 61 72 61 6D 73 03 09 00 6B 72 62 35 64 61 74 61 A2 24 30 22 30 13 06 09 2A 86 48 86 F7 12 01 02 02 04 06 70 61 72 61 6D 73 30 0B 06 09 2A 86 48 86 F7 12 01 02 02 A3 0A 04 08 6B 72 62 35 64 61 74 61 A4 10 30 0E 30 0C A0 0A 06 08 6B 72 62 35 64 61 74 61",
|
|
||||||
acc.decode_krb5_auth_pack,
|
|
||||||
ktest_equal_auth_pack,ktest_free_auth_pack);
|
|
||||||
ktest_empty_auth_pack(&ref);
|
|
||||||
diff --git a/src/tests/asn.1/ktest.c b/src/tests/asn.1/ktest.c
|
|
||||||
index 7bb698732b..fc953ac9b7 100644
|
|
||||||
--- a/src/tests/asn.1/ktest.c
|
|
||||||
+++ b/src/tests/asn.1/ktest.c
|
|
||||||
@@ -722,9 +722,7 @@ ktest_make_sample_pk_authenticator(krb5_pk_authenticator *p)
|
|
||||||
p->cusec = SAMPLE_USEC;
|
|
||||||
p->ctime = SAMPLE_TIME;
|
|
||||||
p->nonce = SAMPLE_NONCE;
|
|
||||||
- ktest_make_sample_checksum(&p->paChecksum);
|
|
||||||
- /* We don't encode the checksum type, only the contents. */
|
|
||||||
- p->paChecksum.checksum_type = 0;
|
|
||||||
+ ktest_make_sample_data(&p->paChecksum);
|
|
||||||
p->freshnessToken = ealloc(sizeof(krb5_data));
|
|
||||||
ktest_make_sample_data(p->freshnessToken);
|
|
||||||
}
|
|
||||||
@@ -1666,8 +1664,7 @@ ktest_empty_pa_otp_req(krb5_pa_otp_req *p)
|
|
||||||
static void
|
|
||||||
ktest_empty_pk_authenticator(krb5_pk_authenticator *p)
|
|
||||||
{
|
|
||||||
- ktest_empty_checksum(&p->paChecksum);
|
|
||||||
- p->paChecksum.contents = NULL;
|
|
||||||
+ ktest_empty_data(&p->paChecksum);
|
|
||||||
krb5_free_data(NULL, p->freshnessToken);
|
|
||||||
p->freshnessToken = NULL;
|
|
||||||
}
|
|
||||||
diff --git a/src/tests/asn.1/ktest_equal.c b/src/tests/asn.1/ktest_equal.c
|
|
||||||
index eed6872f9f..eec7a71601 100644
|
|
||||||
--- a/src/tests/asn.1/ktest_equal.c
|
|
||||||
+++ b/src/tests/asn.1/ktest_equal.c
|
|
||||||
@@ -872,7 +872,7 @@ ktest_equal_pk_authenticator(krb5_pk_authenticator *ref,
|
|
||||||
p = p && scalar_equal(cusec);
|
|
||||||
p = p && scalar_equal(ctime);
|
|
||||||
p = p && scalar_equal(nonce);
|
|
||||||
- p = p && struct_equal(paChecksum, ktest_equal_checksum);
|
|
||||||
+ p = p && data_eq(ref->paChecksum, var->paChecksum);
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
diff --git a/src/tests/asn.1/pkinit_encode.out b/src/tests/asn.1/pkinit_encode.out
|
|
||||||
index 9bd08e159f..cab27cfb68 100644
|
|
||||||
--- a/src/tests/asn.1/pkinit_encode.out
|
|
||||||
+++ b/src/tests/asn.1/pkinit_encode.out
|
|
||||||
@@ -1,7 +1,7 @@
|
|
||||||
encode_krb5_pa_pk_as_req: 30 38 80 08 6B 72 62 35 64 61 74 61 A1 22 30 20 30 1E 80 08 6B 72 62 35 64 61 74 61 81 08 6B 72 62 35 64 61 74 61 82 08 6B 72 62 35 64 61 74 61 82 08 6B 72 62 35 64 61 74 61
|
|
||||||
encode_krb5_pa_pk_as_rep(dhInfo): A0 28 30 26 80 08 6B 72 62 35 64 61 74 61 A1 0A 04 08 6B 72 62 35 64 61 74 61 A2 0E 30 0C A0 0A 06 08 6B 72 62 35 64 61 74 61
|
|
||||||
encode_krb5_pa_pk_as_rep(encKeyPack): 81 08 6B 72 62 35 64 61 74 61
|
|
||||||
-encode_krb5_auth_pack: 30 81 9F A0 35 30 33 A0 05 02 03 01 E2 40 A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A2 03 02 01 2A A3 06 04 04 31 32 33 34 A4 0A 04 08 6B 72 62 35 64 61 74 61 A1 22 30 20 30 13 06 09 2A 86 48 86 F7 12 01 02 02 04 06 70 61 72 61 6D 73 03 09 00 6B 72 62 35 64 61 74 61 A2 24 30 22 30 13 06 09 2A 86 48 86 F7 12 01 02 02 04 06 70 61 72 61 6D 73 30 0B 06 09 2A 86 48 86 F7 12 01 02 02 A3 0A 04 08 6B 72 62 35 64 61 74 61 A4 10 30 0E 30 0C A0 0A 06 08 6B 72 62 35 64 61 74 61
|
|
||||||
+encode_krb5_auth_pack: 30 81 A3 A0 39 30 37 A0 05 02 03 01 E2 40 A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A2 03 02 01 2A A3 0A 04 08 6B 72 62 35 64 61 74 61 A4 0A 04 08 6B 72 62 35 64 61 74 61 A1 22 30 20 30 13 06 09 2A 86 48 86 F7 12 01 02 02 04 06 70 61 72 61 6D 73 03 09 00 6B 72 62 35 64 61 74 61 A2 24 30 22 30 13 06 09 2A 86 48 86 F7 12 01 02 02 04 06 70 61 72 61 6D 73 30 0B 06 09 2A 86 48 86 F7 12 01 02 02 A3 0A 04 08 6B 72 62 35 64 61 74 61 A4 10 30 0E 30 0C A0 0A 06 08 6B 72 62 35 64 61 74 61
|
|
||||||
encode_krb5_kdc_dh_key_info: 30 25 A0 0B 03 09 00 6B 72 62 35 64 61 74 61 A1 03 02 01 2A A2 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A
|
|
||||||
encode_krb5_reply_key_pack: 30 26 A0 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A1 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34
|
|
||||||
encode_krb5_sp80056a_other_info: 30 81 81 30 0B 06 09 2A 86 48 86 F7 12 01 02 02 A0 32 04 30 30 2E A0 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A1 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A1 32 04 30 30 2E A0 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A1 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A2 0A 04 08 6B 72 62 35 64 61 74 61
|
|
||||||
diff --git a/src/tests/asn.1/pkinit_trval.out b/src/tests/asn.1/pkinit_trval.out
|
|
||||||
index 3675fba386..047dec842e 100644
|
|
||||||
--- a/src/tests/asn.1/pkinit_trval.out
|
|
||||||
+++ b/src/tests/asn.1/pkinit_trval.out
|
|
||||||
@@ -38,7 +38,7 @@ encode_krb5_auth_pack:
|
|
||||||
. . [0] [Integer] 123456
|
|
||||||
. . [1] [Generalized Time] "19940610060317Z"
|
|
||||||
. . [2] [Integer] 42
|
|
||||||
-. . [3] [Octet String] "1234"
|
|
||||||
+. . [3] [Octet String] "krb5data"
|
|
||||||
. . [4] [Octet String] "krb5data"
|
|
||||||
. [1] [Sequence/Sequence Of]
|
|
||||||
. . [Sequence/Sequence Of]
|
|
||||||
--
|
|
||||||
2.49.0
|
|
||||||
|
|
@ -1,169 +0,0 @@
|
|||||||
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,226 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,374 +0,0 @@
|
|||||||
From bf57cb193ef7180bb01c8e307258ee6ac93d9b8f Mon Sep 17 00:00:00 2001
|
|
||||||
From: Greg Hudson <ghudson@mit.edu>
|
|
||||||
Date: Fri, 16 Dec 2022 18:31:07 -0500
|
|
||||||
Subject: [PATCH] Don't issue session keys with deprecated enctypes
|
|
||||||
|
|
||||||
A paper by Tom Tervoort noted that rc4-hmac pre-hashes the input for
|
|
||||||
its checksum and GSS operations before applying HMAC, and is therefore
|
|
||||||
potentially vulnerable to hash collision attacks if a protocol
|
|
||||||
contains a restricted signing oracle.
|
|
||||||
|
|
||||||
In light of these potential attacks, begin the functional deprecation
|
|
||||||
of DES3 and RC4 by disallowing their use as session key enctypes by
|
|
||||||
default. Add the variables allow_des3 and allow_rc4 in case
|
|
||||||
negotiability of these enctypes for session keys needs to be turned
|
|
||||||
back on, with the expectation that in future releases the enctypes
|
|
||||||
will be more comprehensively deprecated.
|
|
||||||
|
|
||||||
ticket: 9081
|
|
||||||
(cherry picked from commit 1b57a4d134bbd0e7c52d5885a92eccc815726463)
|
|
||||||
---
|
|
||||||
doc/admin/conf_files/krb5_conf.rst | 12 +++++
|
|
||||||
doc/admin/enctypes.rst | 23 ++++++--
|
|
||||||
src/include/k5-int.h | 4 ++
|
|
||||||
src/kdc/kdc_util.c | 10 ++++
|
|
||||||
src/lib/krb5/krb/get_in_tkt.c | 85 ++++++++++++++++++++++++++++++
|
|
||||||
src/lib/krb5/krb/init_ctx.c | 10 ++++
|
|
||||||
src/tests/gssapi/t_enctypes.py | 5 +-
|
|
||||||
src/tests/t_etype_info.py | 4 +-
|
|
||||||
src/tests/t_sesskeynego.py | 28 +++++++++-
|
|
||||||
src/util/k5test.py | 9 +++-
|
|
||||||
10 files changed, 180 insertions(+), 10 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst
|
|
||||||
index 98fe231813..c77a9fd46d 100644
|
|
||||||
--- a/doc/admin/conf_files/krb5_conf.rst
|
|
||||||
+++ b/doc/admin/conf_files/krb5_conf.rst
|
|
||||||
@@ -95,6 +95,18 @@ Additionally, krb5.conf may include any of the relations described in
|
|
||||||
|
|
||||||
The libdefaults section may contain any of the following relations:
|
|
||||||
|
|
||||||
+**allow_des3**
|
|
||||||
+ Permit the KDC to issue tickets with des3-cbc-sha1 session keys.
|
|
||||||
+ In future releases, this flag will allow des3-cbc-sha1 to be used
|
|
||||||
+ at all. The default value for this tag is false. (Added in
|
|
||||||
+ release 1.21.)
|
|
||||||
+
|
|
||||||
+**allow_rc4**
|
|
||||||
+ Permit the KDC to issue tickets with arcfour-hmac session keys.
|
|
||||||
+ In future releases, this flag will allow arcfour-hmac to be used
|
|
||||||
+ at all. The default value for this tag is false. (Added in
|
|
||||||
+ release 1.21.)
|
|
||||||
+
|
|
||||||
**allow_weak_crypto**
|
|
||||||
If this flag is set to false, then weak encryption types (as noted
|
|
||||||
in :ref:`Encryption_types` in :ref:`kdc.conf(5)`) will be filtered
|
|
||||||
diff --git a/doc/admin/enctypes.rst b/doc/admin/enctypes.rst
|
|
||||||
index 65b55cdb9d..76ef2a2133 100644
|
|
||||||
--- a/doc/admin/enctypes.rst
|
|
||||||
+++ b/doc/admin/enctypes.rst
|
|
||||||
@@ -48,12 +48,15 @@ Session key selection
|
|
||||||
The KDC chooses the session key enctype by taking the intersection of
|
|
||||||
its **permitted_enctypes** list, the list of long-term keys for the
|
|
||||||
most recent kvno of the service, and the client's requested list of
|
|
||||||
-enctypes.
|
|
||||||
+enctypes. Starting in krb5-1.21, all services are assumed to support
|
|
||||||
+aes256-cts-hmac-sha1-96; also, des3-cbc-sha1 and arcfour-hmac session
|
|
||||||
+keys will not be issued by default.
|
|
||||||
|
|
||||||
Starting in krb5-1.11, it is possible to set a string attribute on a
|
|
||||||
service principal to control what session key enctypes the KDC may
|
|
||||||
-issue for service tickets for that principal. See :ref:`set_string`
|
|
||||||
-in :ref:`kadmin(1)` for details.
|
|
||||||
+issue for service tickets for that principal, overriding the service's
|
|
||||||
+long-term keys and the assumption of aes256-cts-hmac-sha1-96 support.
|
|
||||||
+See :ref:`set_string` in :ref:`kadmin(1)` for details.
|
|
||||||
|
|
||||||
|
|
||||||
Choosing enctypes for a service
|
|
||||||
@@ -87,6 +90,20 @@ affect how enctypes are chosen.
|
|
||||||
acceptable risk for your environment and the weak enctypes are
|
|
||||||
required for backward compatibility.
|
|
||||||
|
|
||||||
+**allow_des3**
|
|
||||||
+ was added in release 1.21 and defaults to *false*. Unless this
|
|
||||||
+ flag is set to *true*, the KDC will not issue tickets with
|
|
||||||
+ des3-cbc-sha1 session keys. In a future release, this flag will
|
|
||||||
+ control whether des3-cbc-sha1 is permitted in similar fashion to
|
|
||||||
+ weak enctypes.
|
|
||||||
+
|
|
||||||
+**allow_rc4**
|
|
||||||
+ was added in release 1.21 and defaults to *false*. Unless this
|
|
||||||
+ flag is set to *true*, the KDC will not issue tickets with
|
|
||||||
+ arcfour-hmac session keys. In a future release, this flag will
|
|
||||||
+ control whether arcfour-hmac is permitted in similar fashion to
|
|
||||||
+ weak enctypes.
|
|
||||||
+
|
|
||||||
**permitted_enctypes**
|
|
||||||
controls the set of enctypes that a service will permit for
|
|
||||||
session keys and for ticket and authenticator encryption. The KDC
|
|
||||||
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
|
|
||||||
index d062617268..c3d081fd30 100644
|
|
||||||
--- a/src/include/k5-int.h
|
|
||||||
+++ b/src/include/k5-int.h
|
|
||||||
@@ -181,6 +181,8 @@ typedef unsigned char u_char;
|
|
||||||
* matches the variable name. Keep these alphabetized. */
|
|
||||||
#define KRB5_CONF_ACL_FILE "acl_file"
|
|
||||||
#define KRB5_CONF_ADMIN_SERVER "admin_server"
|
|
||||||
+#define KRB5_CONF_ALLOW_DES3 "allow_des3"
|
|
||||||
+#define KRB5_CONF_ALLOW_RC4 "allow_rc4"
|
|
||||||
#define KRB5_CONF_ALLOW_WEAK_CRYPTO "allow_weak_crypto"
|
|
||||||
#define KRB5_CONF_AUTH_TO_LOCAL "auth_to_local"
|
|
||||||
#define KRB5_CONF_AUTH_TO_LOCAL_NAMES "auth_to_local_names"
|
|
||||||
@@ -1259,6 +1261,8 @@ struct _krb5_context {
|
|
||||||
struct _kdb_log_context *kdblog_context;
|
|
||||||
|
|
||||||
krb5_boolean allow_weak_crypto;
|
|
||||||
+ krb5_boolean allow_des3;
|
|
||||||
+ krb5_boolean allow_rc4;
|
|
||||||
krb5_boolean ignore_acceptor_hostname;
|
|
||||||
krb5_boolean enforce_ok_as_delegate;
|
|
||||||
enum dns_canonhost dns_canonicalize_hostname;
|
|
||||||
diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
|
|
||||||
index 23aadb88e9..b081d8e439 100644
|
|
||||||
--- a/src/kdc/kdc_util.c
|
|
||||||
+++ b/src/kdc/kdc_util.c
|
|
||||||
@@ -1041,6 +1041,16 @@ select_session_keytype(kdc_realm_t *kdc_active_realm, krb5_db_entry *server,
|
|
||||||
if (!krb5_is_permitted_enctype(kdc_context, ktype[i]))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
+ /*
|
|
||||||
+ * Prevent these deprecated enctypes from being used as session keys
|
|
||||||
+ * unless they are explicitly allowed. In the future they will be more
|
|
||||||
+ * comprehensively disabled and eventually removed.
|
|
||||||
+ */
|
|
||||||
+ if (ktype[i] == ENCTYPE_DES3_CBC_SHA1 && !kdc_context->allow_des3)
|
|
||||||
+ continue;
|
|
||||||
+ if (ktype[i] == ENCTYPE_ARCFOUR_HMAC && !kdc_context->allow_rc4)
|
|
||||||
+ continue;
|
|
||||||
+
|
|
||||||
if (dbentry_supports_enctype(kdc_active_realm, server, ktype[i]))
|
|
||||||
return ktype[i];
|
|
||||||
}
|
|
||||||
diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c
|
|
||||||
index f5dd7518b0..322fc94892 100644
|
|
||||||
--- a/src/lib/krb5/krb/get_in_tkt.c
|
|
||||||
+++ b/src/lib/krb5/krb/get_in_tkt.c
|
|
||||||
@@ -1592,6 +1592,90 @@ warn_pw_expiry(krb5_context context, krb5_get_init_creds_opt *options,
|
|
||||||
(*prompter)(context, data, 0, banner, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
+/* Display a warning via the prompter if a deprecated enctype was used for
|
|
||||||
+ * either the reply key or the session key. */
|
|
||||||
+static void
|
|
||||||
+warn_deprecated(krb5_context context, krb5_init_creds_context ctx,
|
|
||||||
+ krb5_enctype as_key_enctype)
|
|
||||||
+{
|
|
||||||
+ krb5_enctype etype;
|
|
||||||
+ char encbuf[128], banner[256];
|
|
||||||
+
|
|
||||||
+ if (ctx->prompter == NULL)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ if (krb5int_c_deprecated_enctype(as_key_enctype))
|
|
||||||
+ etype = as_key_enctype;
|
|
||||||
+ else if (krb5int_c_deprecated_enctype(ctx->cred.keyblock.enctype))
|
|
||||||
+ etype = ctx->cred.keyblock.enctype;
|
|
||||||
+ else
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ if (krb5_enctype_to_name(etype, FALSE, encbuf, sizeof(encbuf)) != 0)
|
|
||||||
+ return;
|
|
||||||
+ snprintf(banner, sizeof(banner),
|
|
||||||
+ _("Warning: encryption type %s used for authentication is "
|
|
||||||
+ "deprecated and will be disabled"), encbuf);
|
|
||||||
+
|
|
||||||
+ /* PROMPTER_INVOCATION */
|
|
||||||
+ (*ctx->prompter)(context, ctx->prompter_data, NULL, banner, 0, NULL);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+ * If ctx specifies an output ccache, create or refresh it (atomically, if
|
|
||||||
+ * possible) with the obtained credential and any appropriate ccache
|
|
||||||
+ * configuration.
|
|
||||||
+ */
|
|
||||||
+static krb5_error_code
|
|
||||||
+write_out_ccache(krb5_context context, krb5_init_creds_context ctx,
|
|
||||||
+ krb5_boolean fast_avail)
|
|
||||||
+{
|
|
||||||
+ krb5_error_code ret;
|
|
||||||
+ krb5_ccache out_ccache = k5_gic_opt_get_out_ccache(ctx->opt);
|
|
||||||
+ krb5_ccache mcc = NULL;
|
|
||||||
+ krb5_data yes = string2data("yes");
|
|
||||||
+
|
|
||||||
+ if (out_ccache == NULL)
|
|
||||||
+ return 0;
|
|
||||||
+
|
|
||||||
+ ret = krb5_cc_new_unique(context, "MEMORY", NULL, &mcc);
|
|
||||||
+ if (ret)
|
|
||||||
+ goto cleanup;
|
|
||||||
+
|
|
||||||
+ ret = krb5_cc_initialize(context, mcc, ctx->cred.client);
|
|
||||||
+ if (ret)
|
|
||||||
+ goto cleanup;
|
|
||||||
+
|
|
||||||
+ if (fast_avail) {
|
|
||||||
+ ret = krb5_cc_set_config(context, mcc, ctx->cred.server,
|
|
||||||
+ KRB5_CC_CONF_FAST_AVAIL, &yes);
|
|
||||||
+ if (ret)
|
|
||||||
+ goto cleanup;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ ret = save_selected_preauth_type(context, mcc, ctx);
|
|
||||||
+ if (ret)
|
|
||||||
+ goto cleanup;
|
|
||||||
+
|
|
||||||
+ ret = save_cc_config_out_data(context, mcc, ctx);
|
|
||||||
+ if (ret)
|
|
||||||
+ goto cleanup;
|
|
||||||
+
|
|
||||||
+ ret = k5_cc_store_primary_cred(context, mcc, &ctx->cred);
|
|
||||||
+ if (ret)
|
|
||||||
+ goto cleanup;
|
|
||||||
+
|
|
||||||
+ ret = krb5_cc_move(context, mcc, out_ccache);
|
|
||||||
+ if (ret)
|
|
||||||
+ goto cleanup;
|
|
||||||
+ mcc = NULL;
|
|
||||||
+
|
|
||||||
+cleanup:
|
|
||||||
+ if (mcc != NULL)
|
|
||||||
+ krb5_cc_destroy(context, mcc);
|
|
||||||
+ return ret;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static krb5_error_code
|
|
||||||
init_creds_step_reply(krb5_context context,
|
|
||||||
krb5_init_creds_context ctx,
|
|
||||||
@@ -1805,6 +1889,7 @@ init_creds_step_reply(krb5_context context,
|
|
||||||
ctx->complete = TRUE;
|
|
||||||
warn_pw_expiry(context, ctx->opt, ctx->prompter, ctx->prompter_data,
|
|
||||||
ctx->in_tkt_service, ctx->reply);
|
|
||||||
+ warn_deprecated(context, ctx, encrypting_key.enctype);
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
krb5_free_pa_data(context, kdc_padata);
|
|
||||||
diff --git a/src/lib/krb5/krb/init_ctx.c b/src/lib/krb5/krb/init_ctx.c
|
|
||||||
index 1a6e0bf672..4b23738817 100644
|
|
||||||
--- a/src/lib/krb5/krb/init_ctx.c
|
|
||||||
+++ b/src/lib/krb5/krb/init_ctx.c
|
|
||||||
@@ -226,6 +226,16 @@ krb5_init_context_profile(profile_t profile, krb5_flags flags,
|
|
||||||
goto cleanup;
|
|
||||||
ctx->allow_weak_crypto = tmp;
|
|
||||||
|
|
||||||
+ retval = get_boolean(ctx, KRB5_CONF_ALLOW_DES3, 0, &tmp);
|
|
||||||
+ if (retval)
|
|
||||||
+ goto cleanup;
|
|
||||||
+ ctx->allow_des3 = tmp;
|
|
||||||
+
|
|
||||||
+ retval = get_boolean(ctx, KRB5_CONF_ALLOW_RC4, 0, &tmp);
|
|
||||||
+ if (retval)
|
|
||||||
+ goto cleanup;
|
|
||||||
+ ctx->allow_rc4 = tmp;
|
|
||||||
+
|
|
||||||
retval = get_boolean(ctx, KRB5_CONF_IGNORE_ACCEPTOR_HOSTNAME, 0, &tmp);
|
|
||||||
if (retval)
|
|
||||||
goto cleanup;
|
|
||||||
diff --git a/src/tests/gssapi/t_enctypes.py b/src/tests/gssapi/t_enctypes.py
|
|
||||||
index 2f95d89967..e6bde47afc 100755
|
|
||||||
--- a/src/tests/gssapi/t_enctypes.py
|
|
||||||
+++ b/src/tests/gssapi/t_enctypes.py
|
|
||||||
@@ -10,8 +10,9 @@ d_rc4 = 'DEPRECATED:arcfour-hmac'
|
|
||||||
|
|
||||||
# These tests make assumptions about the default enctype lists, so set
|
|
||||||
# them explicitly rather than relying on the library defaults.
|
|
||||||
-supp='aes256-cts:normal aes128-cts:normal rc4-hmac:normal'
|
|
||||||
-conf = {'libdefaults': {'permitted_enctypes': 'aes rc4'},
|
|
||||||
+supp='aes256-cts:normal aes128-cts:normal des3-cbc-sha1:normal rc4-hmac:normal'
|
|
||||||
+conf = {'libdefaults': {'permitted_enctypes': 'aes des3 rc4',
|
|
||||||
+ 'allow_des3': 'true', 'allow_rc4': 'true'},
|
|
||||||
'realms': {'$realm': {'supported_enctypes': supp}}}
|
|
||||||
realm = K5Realm(krb5_conf=conf)
|
|
||||||
shutil.copyfile(realm.ccache, os.path.join(realm.testdir, 'save'))
|
|
||||||
diff --git a/src/tests/t_etype_info.py b/src/tests/t_etype_info.py
|
|
||||||
index ace0edc3c4..9ea5ca6228 100644
|
|
||||||
--- a/src/tests/t_etype_info.py
|
|
||||||
+++ b/src/tests/t_etype_info.py
|
|
||||||
@@ -1,7 +1,7 @@
|
|
||||||
from k5test import *
|
|
||||||
|
|
||||||
-supported_enctypes = 'aes128-cts rc4-hmac'
|
|
||||||
-conf = {'libdefaults': {'allow_weak_crypto': 'true'},
|
|
||||||
+supported_enctypes = 'aes128-cts des3-cbc-sha1 rc4-hmac'
|
|
||||||
+conf = {'libdefaults': {'allow_des3': 'true', 'allow_rc4': 'true'},
|
|
||||||
'realms': {'$realm': {'supported_enctypes': supported_enctypes}}}
|
|
||||||
realm = K5Realm(create_host=False, get_creds=False, krb5_conf=conf)
|
|
||||||
|
|
||||||
diff --git a/src/tests/t_sesskeynego.py b/src/tests/t_sesskeynego.py
|
|
||||||
index 73a55366c4..f30d0bc16c 100755
|
|
||||||
--- a/src/tests/t_sesskeynego.py
|
|
||||||
+++ b/src/tests/t_sesskeynego.py
|
|
||||||
@@ -25,6 +25,8 @@ conf3 = {'libdefaults': {
|
|
||||||
'default_tkt_enctypes': 'aes128-cts',
|
|
||||||
'default_tgs_enctypes': 'rc4-hmac,aes128-cts'}}
|
|
||||||
conf4 = {'libdefaults': {'permitted_enctypes': 'aes256-cts'}}
|
|
||||||
+conf5 = {'libdefaults': {'allow_rc4': 'true'}}
|
|
||||||
+conf6 = {'libdefaults': {'allow_des3': 'true'}}
|
|
||||||
# Test with client request and session_enctypes preferring aes128, but
|
|
||||||
# aes256 long-term key.
|
|
||||||
realm = K5Realm(krb5_conf=conf1, create_host=False, get_creds=False)
|
|
||||||
@@ -54,10 +56,12 @@ realm.run([kadminl, 'setstr', 'server', 'session_enctypes',
|
|
||||||
'aes128-cts,aes256-cts'])
|
|
||||||
test_kvno(realm, 'aes128-cts-hmac-sha1-96', 'aes256-cts-hmac-sha1-96')
|
|
||||||
|
|
||||||
-# 3b: Negotiate rc4-hmac session key when principal only has aes256 long-term.
|
|
||||||
+# 3b: Skip RC4 (as the KDC does not allow it for session keys by
|
|
||||||
+# default) and negotiate aes128-cts session key, with only an aes256
|
|
||||||
+# long-term service key.
|
|
||||||
realm.run([kadminl, 'setstr', 'server', 'session_enctypes',
|
|
||||||
'rc4-hmac,aes128-cts,aes256-cts'])
|
|
||||||
-test_kvno(realm, 'DEPRECATED:arcfour-hmac', 'aes256-cts-hmac-sha1-96')
|
|
||||||
+test_kvno(realm, 'aes128-cts-hmac-sha1-96', 'aes256-cts-hmac-sha1-96')
|
|
||||||
realm.stop()
|
|
||||||
|
|
||||||
# 4: Check that permitted_enctypes is a default for session key enctypes.
|
|
||||||
@@ -67,4 +71,24 @@ realm.run([kvno, 'user'],
|
|
||||||
expected_trace=('etypes requested in TGS request: aes256-cts',))
|
|
||||||
realm.stop()
|
|
||||||
|
|
||||||
+# 5: allow_rc4 permits negotiation of rc4-hmac session key.
|
|
||||||
+realm = K5Realm(krb5_conf=conf5, create_host=False, get_creds=False)
|
|
||||||
+realm.run([kadminl, 'addprinc', '-randkey', '-e', 'aes256-cts', 'server'])
|
|
||||||
+realm.run([kadminl, 'setstr', 'server', 'session_enctypes', 'rc4-hmac'])
|
|
||||||
+test_kvno(realm, 'DEPRECATED:arcfour-hmac', 'aes256-cts-hmac-sha1-96')
|
|
||||||
+realm.stop()
|
|
||||||
+
|
|
||||||
+# 6: allow_des3 permits negotiation of des3-cbc-sha1 session key.
|
|
||||||
+realm = K5Realm(krb5_conf=conf6, create_host=False, get_creds=False)
|
|
||||||
+realm.run([kadminl, 'addprinc', '-randkey', '-e', 'aes256-cts', 'server'])
|
|
||||||
+realm.run([kadminl, 'setstr', 'server', 'session_enctypes', 'des3-cbc-sha1'])
|
|
||||||
+test_kvno(realm, 'DEPRECATED:des3-cbc-sha1', 'aes256-cts-hmac-sha1-96')
|
|
||||||
+realm.stop()
|
|
||||||
+
|
|
||||||
+# 7: default config negotiates aes256-sha1 session key for RC4-only service.
|
|
||||||
+realm = K5Realm(create_host=False, get_creds=False)
|
|
||||||
+realm.run([kadminl, 'addprinc', '-randkey', '-e', 'rc4-hmac', 'server'])
|
|
||||||
+test_kvno(realm, 'aes256-cts-hmac-sha1-96', 'DEPRECATED:arcfour-hmac')
|
|
||||||
+realm.stop()
|
|
||||||
+
|
|
||||||
success('sesskeynego')
|
|
||||||
diff --git a/src/util/k5test.py b/src/util/k5test.py
|
|
||||||
index eea92275d7..96474cc5aa 100644
|
|
||||||
--- a/src/util/k5test.py
|
|
||||||
+++ b/src/util/k5test.py
|
|
||||||
@@ -1299,9 +1299,16 @@ _passes = [
|
|
||||||
# No special settings; exercises AES256.
|
|
||||||
('default', None, None, None),
|
|
||||||
|
|
||||||
+ # Exercise the DES3 enctype.
|
|
||||||
+ ('des3', None,
|
|
||||||
+ {'libdefaults': {'permitted_enctypes': 'des3 aes256-sha1'}},
|
|
||||||
+ {'realms': {'$realm': {
|
|
||||||
+ 'supported_enctypes': 'des3-cbc-sha1:normal',
|
|
||||||
+ 'master_key_type': 'des3-cbc-sha1'}}}),
|
|
||||||
+
|
|
||||||
# Exercise the arcfour enctype.
|
|
||||||
('arcfour', None,
|
|
||||||
- {'libdefaults': {'permitted_enctypes': 'rc4'}},
|
|
||||||
+ {'libdefaults': {'permitted_enctypes': 'rc4 aes256-sha1'}},
|
|
||||||
{'realms': {'$realm': {
|
|
||||||
'supported_enctypes': 'arcfour-hmac:normal',
|
|
||||||
'master_key_type': 'arcfour-hmac'}}}),
|
|
||||||
--
|
|
||||||
2.49.0
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,258 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,205 +0,0 @@
|
|||||||
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,535 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,629 +0,0 @@
|
|||||||
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,51 +0,0 @@
|
|||||||
From 5b67abf41026a420974f2d938c3e42d7f072abe5 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Greg Hudson <ghudson@mit.edu>
|
|
||||||
Date: Wed, 14 Dec 2022 13:20:46 -0500
|
|
||||||
Subject: [PATCH] In KDC, assume all services support aes256-sha1
|
|
||||||
|
|
||||||
To facilitate negotiating session keys with acceptable security,
|
|
||||||
assume that services support aes256-cts-hmac-sha1 unless a
|
|
||||||
session_enctypes string attribute says otherwise.
|
|
||||||
|
|
||||||
ticket: 9075
|
|
||||||
(cherry picked from commit 2cbd847e0e92bc4e219b65c770ae33f851b22afc)
|
|
||||||
---
|
|
||||||
src/kdc/kdc_util.c | 4 ++++
|
|
||||||
src/tests/t_keyrollover.py | 6 +++---
|
|
||||||
2 files changed, 7 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
|
|
||||||
index e3352f9cc6..23aadb88e9 100644
|
|
||||||
--- a/src/kdc/kdc_util.c
|
|
||||||
+++ b/src/kdc/kdc_util.c
|
|
||||||
@@ -1015,6 +1015,10 @@ dbentry_supports_enctype(kdc_realm_t *kdc_active_realm, krb5_db_entry *server,
|
|
||||||
free(etypes_str);
|
|
||||||
free(etypes);
|
|
||||||
|
|
||||||
+ /* Assume every server without a session_enctypes attribute supports
|
|
||||||
+ * aes256-cts-hmac-sha1-96. */
|
|
||||||
+ if (enctype == ENCTYPE_AES256_CTS_HMAC_SHA1_96)
|
|
||||||
+ return TRUE;
|
|
||||||
/* Assume the server supports any enctype it has a long-term key for. */
|
|
||||||
return !krb5_dbe_find_enctype(kdc_context, server, enctype, -1, 0, &datap);
|
|
||||||
}
|
|
||||||
diff --git a/src/tests/t_keyrollover.py b/src/tests/t_keyrollover.py
|
|
||||||
index f29e0d5500..583c2fa27e 100755
|
|
||||||
--- a/src/tests/t_keyrollover.py
|
|
||||||
+++ b/src/tests/t_keyrollover.py
|
|
||||||
@@ -22,9 +22,9 @@ realm.run([kvno, princ1])
|
|
||||||
realm.run([kadminl, 'purgekeys', realm.krbtgt_princ])
|
|
||||||
# Make sure an old TGT fails after purging old TGS key.
|
|
||||||
realm.run([kvno, princ2], expected_code=1)
|
|
||||||
-et = "aes128-cts-hmac-sha256-128"
|
|
||||||
-msg = 'krbtgt/%s@%s\n\tEtype (skey, tkt): %s, %s' % \
|
|
||||||
- (realm.realm, realm.realm, et, et)
|
|
||||||
+msg = 'krbtgt/%s@%s\n\tEtype (skey, tkt): ' \
|
|
||||||
+ 'aes256-cts-hmac-sha1-96, aes128-cts-hmac-sha256-128' % \
|
|
||||||
+ (realm.realm, realm.realm)
|
|
||||||
realm.run([klist, '-e'], expected_msg=msg)
|
|
||||||
|
|
||||||
# Check that new key actually works.
|
|
||||||
--
|
|
||||||
2.49.0
|
|
||||||
|
|
@ -1,64 +0,0 @@
|
|||||||
From 105ba83436476f5a08759b8e97bfb0c5a69596b9 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Zoltan Borbely <Zoltan.Borbely@morganstanley.com>
|
|
||||||
Date: Tue, 28 Jan 2025 16:39:25 -0500
|
|
||||||
Subject: [PATCH] Prevent overflow when calculating ulog block size
|
|
||||||
|
|
||||||
In kdb_log.c:resize(), log an error and fail if the update size is
|
|
||||||
larger than the largest possible block size (2^16-1).
|
|
||||||
|
|
||||||
CVE-2025-24528:
|
|
||||||
|
|
||||||
In MIT krb5 release 1.7 and later with incremental propagation
|
|
||||||
enabled, an authenticated attacker can cause kadmind to write beyond
|
|
||||||
the end of the mapped region for the iprop log file, likely causing a
|
|
||||||
process crash.
|
|
||||||
|
|
||||||
[ghudson@mit.edu: edited commit message and added CVE description]
|
|
||||||
|
|
||||||
ticket: 9159 (new)
|
|
||||||
tags: pullup
|
|
||||||
target_version: 1.21-next
|
|
||||||
|
|
||||||
(cherry picked from commit 78ceba024b64d49612375be4a12d1c066b0bfbd0)
|
|
||||||
---
|
|
||||||
src/lib/kdb/kdb_log.c | 10 ++++++++--
|
|
||||||
1 file changed, 8 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/lib/kdb/kdb_log.c b/src/lib/kdb/kdb_log.c
|
|
||||||
index e9b95fce59..c805ebd988 100644
|
|
||||||
--- a/src/lib/kdb/kdb_log.c
|
|
||||||
+++ b/src/lib/kdb/kdb_log.c
|
|
||||||
@@ -183,7 +183,7 @@ extend_file_to(int fd, unsigned int new_size)
|
|
||||||
*/
|
|
||||||
static krb5_error_code
|
|
||||||
resize(kdb_hlog_t *ulog, uint32_t ulogentries, int ulogfd,
|
|
||||||
- unsigned int recsize)
|
|
||||||
+ unsigned int recsize, const kdb_incr_update_t *upd)
|
|
||||||
{
|
|
||||||
unsigned int new_block, new_size;
|
|
||||||
|
|
||||||
@@ -195,6 +195,12 @@ resize(kdb_hlog_t *ulog, uint32_t ulogentries, int ulogfd,
|
|
||||||
new_block *= ULOG_BLOCK;
|
|
||||||
new_size += ulogentries * new_block;
|
|
||||||
|
|
||||||
+ if (new_block > UINT16_MAX) {
|
|
||||||
+ syslog(LOG_ERR, _("ulog overflow caused by principal %.*s"),
|
|
||||||
+ upd->kdb_princ_name.utf8str_t_len,
|
|
||||||
+ upd->kdb_princ_name.utf8str_t_val);
|
|
||||||
+ return KRB5_LOG_ERROR;
|
|
||||||
+ }
|
|
||||||
if (new_size > MAXLOGLEN)
|
|
||||||
return KRB5_LOG_ERROR;
|
|
||||||
|
|
||||||
@@ -291,7 +297,7 @@ store_update(kdb_log_context *log_ctx, kdb_incr_update_t *upd)
|
|
||||||
recsize = sizeof(kdb_ent_header_t) + upd_size;
|
|
||||||
|
|
||||||
if (recsize > ulog->kdb_block) {
|
|
||||||
- retval = resize(ulog, ulogentries, log_ctx->ulogfd, recsize);
|
|
||||||
+ retval = resize(ulog, ulogentries, log_ctx->ulogfd, recsize, upd);
|
|
||||||
if (retval)
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
--
|
|
||||||
2.48.1
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -1,61 +0,0 @@
|
|||||||
From 8c2dbb9260e8beab6ae7d169e9791d8756eb40a2 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Julien Rische <jrische@redhat.com>
|
|
||||||
Date: Thu, 1 Aug 2024 10:56:07 +0200
|
|
||||||
Subject: [PATCH] Set missing mask flags for kdb5_util operations
|
|
||||||
|
|
||||||
Set KADM5_TL_DATA for the use_mkey and update_princ_encryption
|
|
||||||
commands. (Commit c877f13c8985d820583b0d7ac1bb4c5dc36e677e did this
|
|
||||||
for the add_new_mkey and purge_mkeys commands.) Set appropriate flags
|
|
||||||
for the add_random_key command.
|
|
||||||
|
|
||||||
[ghudson@mit.edu: combined two commits; pruned out proposed mask flag
|
|
||||||
additions for values represented within key data or tl-data (like
|
|
||||||
KADM5_MKVNO), as those flags are currently only used in the kadm5
|
|
||||||
protocol, not to communicate with the KDB module]
|
|
||||||
|
|
||||||
ticket: 9158 (new)
|
|
||||||
(cherry picked from commit 4ed7da378940198cf4415f86d4eb013de6ac6455)
|
|
||||||
---
|
|
||||||
src/kadmin/dbutil/kdb5_mkey.c | 4 +++-
|
|
||||||
src/kadmin/dbutil/kdb5_util.c | 3 +++
|
|
||||||
2 files changed, 6 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/src/kadmin/dbutil/kdb5_mkey.c b/src/kadmin/dbutil/kdb5_mkey.c
|
|
||||||
index aceb0a9b80..ac5c51d05e 100644
|
|
||||||
--- a/src/kadmin/dbutil/kdb5_mkey.c
|
|
||||||
+++ b/src/kadmin/dbutil/kdb5_mkey.c
|
|
||||||
@@ -525,6 +525,8 @@ kdb5_use_mkey(int argc, char *argv[])
|
|
||||||
goto cleanup_return;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ master_entry->mask |= KADM5_TL_DATA;
|
|
||||||
+
|
|
||||||
if ((retval = krb5_db_put_principal(util_context, master_entry))) {
|
|
||||||
com_err(progname, retval,
|
|
||||||
_("while adding master key entry to the database"));
|
|
||||||
@@ -814,7 +816,7 @@ update_princ_encryption_1(void *cb, krb5_db_entry *ent)
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
- ent->mask |= KADM5_KEY_DATA;
|
|
||||||
+ ent->mask |= KADM5_KEY_DATA | KADM5_TL_DATA;
|
|
||||||
|
|
||||||
if ((retval = krb5_db_put_principal(util_context, ent))) {
|
|
||||||
com_err(progname, retval, _("while updating principal '%s' key data "
|
|
||||||
diff --git a/src/kadmin/dbutil/kdb5_util.c b/src/kadmin/dbutil/kdb5_util.c
|
|
||||||
index a720eecf0b..0bb4244681 100644
|
|
||||||
--- a/src/kadmin/dbutil/kdb5_util.c
|
|
||||||
+++ b/src/kadmin/dbutil/kdb5_util.c
|
|
||||||
@@ -600,6 +600,9 @@ add_random_key(argc, argv)
|
|
||||||
exit_status++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+ dbent->mask |= KADM5_ATTRIBUTES | KADM5_KEY_DATA | KADM5_TL_DATA;
|
|
||||||
+
|
|
||||||
ret = krb5_db_put_principal(util_context, dbent);
|
|
||||||
krb5_db_free_principal(util_context, dbent);
|
|
||||||
if (ret) {
|
|
||||||
--
|
|
||||||
2.48.1
|
|
||||||
|
|
@ -1,184 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,138 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,126 +0,0 @@
|
|||||||
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,157 +0,0 @@
|
|||||||
From 400c8d5253a81c2bc220dc158a4f60ab7dbc5951 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Julien Rische <jrische@redhat.com>
|
|
||||||
Date: Thu, 24 Apr 2025 15:56:32 +0200
|
|
||||||
Subject: [PATCH] [downstream] Do not block HMAC-MD4/5 in FIPS mode
|
|
||||||
|
|
||||||
To ensure RC4 HMAC-MD5 was not used in FIPS mode, access to HMAC-MD4/5
|
|
||||||
was not allowed in this mode. However, since we provide the
|
|
||||||
"radius_md5_fips_override" configuration parameter to allow using RADIUS
|
|
||||||
regardless to the FIPS restrictions, we should allow HMAC-MD5 to be used
|
|
||||||
too in this case, because it is required for the newly supported
|
|
||||||
Message-Authenticator attribute.
|
|
||||||
|
|
||||||
A FIPS mode check is added in calculate_mac() which will fail if
|
|
||||||
"radius_md5_fips_override" is not true. It will not affect interactions
|
|
||||||
between krb5kdc and ipa-otpd, because the Message-Authenticator
|
|
||||||
attribute is not generated in this case.
|
|
||||||
|
|
||||||
This C8S patch does not include the code for loading the OpenSSL default
|
|
||||||
and legacy providers in a library context. A flag is enough to unblock
|
|
||||||
MD5 and HMAC-MD5 in FIPS mode on C8S, contrary to C9S and C10S.
|
|
||||||
---
|
|
||||||
src/lib/crypto/openssl/hmac.c | 19 +++++++++++--------
|
|
||||||
src/lib/krad/packet.c | 19 ++++++++++++-------
|
|
||||||
2 files changed, 23 insertions(+), 15 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/lib/crypto/openssl/hmac.c b/src/lib/crypto/openssl/hmac.c
|
|
||||||
index 769a50c007..5814328e3c 100644
|
|
||||||
--- a/src/lib/crypto/openssl/hmac.c
|
|
||||||
+++ b/src/lib/crypto/openssl/hmac.c
|
|
||||||
@@ -103,11 +103,7 @@ map_digest(const struct krb5_hash_provider *hash)
|
|
||||||
return EVP_sha256();
|
|
||||||
else if (!strncmp(hash->hash_name, "SHA-384",7))
|
|
||||||
return EVP_sha384();
|
|
||||||
-
|
|
||||||
- if (FIPS_mode())
|
|
||||||
- return NULL;
|
|
||||||
-
|
|
||||||
- if (!strncmp(hash->hash_name, "MD5", 3))
|
|
||||||
+ else if (!strncmp(hash->hash_name, "MD5", 3))
|
|
||||||
return EVP_md5();
|
|
||||||
else if (!strncmp(hash->hash_name, "MD4", 3))
|
|
||||||
return EVP_md4();
|
|
||||||
@@ -125,6 +121,7 @@ krb5int_hmac_keyblock(const struct krb5_hash_provider *hash,
|
|
||||||
unsigned char md[EVP_MAX_MD_SIZE];
|
|
||||||
HMAC_CTX *ctx;
|
|
||||||
size_t hashsize, blocksize;
|
|
||||||
+ const EVP_MD *md_alg;
|
|
||||||
|
|
||||||
hashsize = hash->hashsize;
|
|
||||||
blocksize = hash->blocksize;
|
|
||||||
@@ -134,15 +131,21 @@ krb5int_hmac_keyblock(const struct krb5_hash_provider *hash,
|
|
||||||
if (output->length < hashsize)
|
|
||||||
return(KRB5_BAD_MSIZE);
|
|
||||||
|
|
||||||
- if (!map_digest(hash))
|
|
||||||
+ md_alg = map_digest(hash);
|
|
||||||
+ if (!md_alg)
|
|
||||||
return(KRB5_CRYPTO_INTERNAL); // unsupported alg
|
|
||||||
|
|
||||||
ctx = HMAC_CTX_new();
|
|
||||||
if (ctx == NULL)
|
|
||||||
return ENOMEM;
|
|
||||||
|
|
||||||
- ok = HMAC_Init_ex(ctx, keyblock->contents, keyblock->length,
|
|
||||||
- map_digest(hash), NULL);
|
|
||||||
+ if (md_alg == EVP_md4() || md_alg == EVP_md5()) {
|
|
||||||
+ /* HMAC-MD5 and HMAC-MD4 are blocked by default in FIPS mode,
|
|
||||||
+ * but needed to support RADIUS Message-Authenticator. */
|
|
||||||
+ HMAC_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ ok = HMAC_Init_ex(ctx, keyblock->contents, keyblock->length, md_alg, NULL);
|
|
||||||
for (i = 0; ok && i < num_data; i++) {
|
|
||||||
const krb5_crypto_iov *iov = &data[i];
|
|
||||||
|
|
||||||
diff --git a/src/lib/krad/packet.c b/src/lib/krad/packet.c
|
|
||||||
index 257bbc6345..b1a31d78cc 100644
|
|
||||||
--- a/src/lib/krad/packet.c
|
|
||||||
+++ b/src/lib/krad/packet.c
|
|
||||||
@@ -278,7 +278,7 @@ lookup_msgauth_addr(const krad_packet *pkt)
|
|
||||||
* auth, which may be from pkt or from a corresponding request.
|
|
||||||
*/
|
|
||||||
static krb5_error_code
|
|
||||||
-calculate_mac(const char *secret, const krad_packet *pkt,
|
|
||||||
+calculate_mac(krb5_context ctx, const char *secret, const krad_packet *pkt,
|
|
||||||
const uint8_t auth[AUTH_FIELD_SIZE],
|
|
||||||
uint8_t mac_out[MD5_DIGEST_SIZE])
|
|
||||||
{
|
|
||||||
@@ -288,6 +288,10 @@ calculate_mac(const char *secret, const krad_packet *pkt,
|
|
||||||
krb5_crypto_iov input[5];
|
|
||||||
krb5_data ksecr, mac;
|
|
||||||
|
|
||||||
+ /* Do not use HMAC-MD5 if not explicitly allowed */
|
|
||||||
+ if (kr_use_fips(ctx))
|
|
||||||
+ return KRB5_CRYPTO_INTERNAL;
|
|
||||||
+
|
|
||||||
msgauth_attr = lookup_msgauth_addr(pkt);
|
|
||||||
if (msgauth_attr == NULL)
|
|
||||||
return EINVAL;
|
|
||||||
@@ -393,7 +397,8 @@ krad_packet_new_request(krb5_context ctx, const char *secret, krad_code code,
|
|
||||||
|
|
||||||
if (msgauth_required) {
|
|
||||||
/* Calculate and set the Message-Authenticator MAC. */
|
|
||||||
- retval = calculate_mac(secret, pkt, pkt_auth(pkt), pkt_attr(pkt) + 2);
|
|
||||||
+ retval = calculate_mac(ctx, secret, pkt, pkt_auth(pkt),
|
|
||||||
+ pkt_attr(pkt) + 2);
|
|
||||||
if (retval != 0)
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
@@ -454,7 +459,7 @@ krad_packet_new_response(krb5_context ctx, const char *secret, krad_code code,
|
|
||||||
* section 5.14, use the authenticator from the request, not from the
|
|
||||||
* response.
|
|
||||||
*/
|
|
||||||
- retval = calculate_mac(secret, pkt, pkt_auth(request),
|
|
||||||
+ retval = calculate_mac(ctx, secret, pkt, pkt_auth(request),
|
|
||||||
pkt_attr(pkt) + 2);
|
|
||||||
if (retval != 0)
|
|
||||||
goto error;
|
|
||||||
@@ -476,7 +481,7 @@ error:
|
|
||||||
/* 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,
|
|
||||||
+verify_msgauth(krb5_context ctx, const char *secret, const krad_packet *pkt,
|
|
||||||
const uint8_t auth[AUTH_FIELD_SIZE])
|
|
||||||
{
|
|
||||||
uint8_t mac[MD5_DIGEST_SIZE];
|
|
||||||
@@ -488,7 +493,7 @@ verify_msgauth(const char *secret, const krad_packet *pkt,
|
|
||||||
if (msgauth == NULL)
|
|
||||||
return ENODATA;
|
|
||||||
|
|
||||||
- retval = calculate_mac(secret, pkt, auth, mac);
|
|
||||||
+ retval = calculate_mac(ctx, secret, pkt, auth, mac);
|
|
||||||
if (retval)
|
|
||||||
return retval;
|
|
||||||
|
|
||||||
@@ -561,7 +566,7 @@ krad_packet_decode_request(krb5_context ctx, const char *secret,
|
|
||||||
|
|
||||||
/* Verify Message-Authenticator if present. */
|
|
||||||
if (has_pkt_msgauth(req)) {
|
|
||||||
- retval = verify_msgauth(secret, req, pkt_auth(req));
|
|
||||||
+ retval = verify_msgauth(ctx, secret, req, pkt_auth(req));
|
|
||||||
if (retval) {
|
|
||||||
krad_packet_free(req);
|
|
||||||
return retval;
|
|
||||||
@@ -613,7 +618,7 @@ krad_packet_decode_response(krb5_context ctx, const char *secret,
|
|
||||||
|
|
||||||
/* Verify Message-Authenticator if present. */
|
|
||||||
if (has_pkt_msgauth(*rsppkt)) {
|
|
||||||
- if (verify_msgauth(secret, *rsppkt, pkt_auth(tmp)) != 0)
|
|
||||||
+ if (verify_msgauth(ctx, secret, *rsppkt, pkt_auth(tmp)) != 0)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
2.49.0
|
|
||||||
|
|
@ -1,239 +0,0 @@
|
|||||||
From dea76c0b677ae02f59f6e5a796b0cf8c5d2e02f2 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Julien Rische <jrische@redhat.com>
|
|
||||||
Date: Fri, 4 Apr 2025 15:08:36 +0200
|
|
||||||
Subject: [PATCH] [downstream] Remove 3des support (cumulative 1)
|
|
||||||
|
|
||||||
Remove mentions for the triple-DES encryption type which were added
|
|
||||||
since the previous downstream patch.
|
|
||||||
---
|
|
||||||
README | 3 +++
|
|
||||||
doc/admin/conf_files/krb5_conf.rst | 6 ------
|
|
||||||
doc/admin/enctypes.rst | 11 ++---------
|
|
||||||
doc/mitK5features.rst | 3 +++
|
|
||||||
src/include/k5-int.h | 2 --
|
|
||||||
src/kdc/kdc_util.c | 2 --
|
|
||||||
src/lib/krb5/krb/init_ctx.c | 5 -----
|
|
||||||
src/man/krb5.conf.man | 6 ++++++
|
|
||||||
src/tests/gssapi/t_enctypes.py | 5 ++---
|
|
||||||
src/tests/t_etype_info.py | 4 ++--
|
|
||||||
src/tests/t_sesskeynego.py | 8 --------
|
|
||||||
src/util/k5test.py | 7 -------
|
|
||||||
12 files changed, 18 insertions(+), 44 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/README b/README
|
|
||||||
index 0f39ac2443..b863ef84a3 100644
|
|
||||||
--- a/README
|
|
||||||
+++ b/README
|
|
||||||
@@ -168,6 +168,9 @@ Developer experience:
|
|
||||||
|
|
||||||
Protocol evolution:
|
|
||||||
|
|
||||||
+* The KDC will no longer issue tickets with RC4 session keys unless
|
|
||||||
+ explicitly configured with the new allow_rc4 variable.
|
|
||||||
+
|
|
||||||
* Add KDC support for S4U2Self requests where the user is identified
|
|
||||||
by X.509 certificate. (Requires support for certificate lookup from
|
|
||||||
a third-party KDB module.)
|
|
||||||
diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst
|
|
||||||
index c77a9fd46d..54e4780327 100644
|
|
||||||
--- a/doc/admin/conf_files/krb5_conf.rst
|
|
||||||
+++ b/doc/admin/conf_files/krb5_conf.rst
|
|
||||||
@@ -95,12 +95,6 @@ Additionally, krb5.conf may include any of the relations described in
|
|
||||||
|
|
||||||
The libdefaults section may contain any of the following relations:
|
|
||||||
|
|
||||||
-**allow_des3**
|
|
||||||
- Permit the KDC to issue tickets with des3-cbc-sha1 session keys.
|
|
||||||
- In future releases, this flag will allow des3-cbc-sha1 to be used
|
|
||||||
- at all. The default value for this tag is false. (Added in
|
|
||||||
- release 1.21.)
|
|
||||||
-
|
|
||||||
**allow_rc4**
|
|
||||||
Permit the KDC to issue tickets with arcfour-hmac session keys.
|
|
||||||
In future releases, this flag will allow arcfour-hmac to be used
|
|
||||||
diff --git a/doc/admin/enctypes.rst b/doc/admin/enctypes.rst
|
|
||||||
index 76ef2a2133..90e85309fa 100644
|
|
||||||
--- a/doc/admin/enctypes.rst
|
|
||||||
+++ b/doc/admin/enctypes.rst
|
|
||||||
@@ -49,8 +49,8 @@ The KDC chooses the session key enctype by taking the intersection of
|
|
||||||
its **permitted_enctypes** list, the list of long-term keys for the
|
|
||||||
most recent kvno of the service, and the client's requested list of
|
|
||||||
enctypes. Starting in krb5-1.21, all services are assumed to support
|
|
||||||
-aes256-cts-hmac-sha1-96; also, des3-cbc-sha1 and arcfour-hmac session
|
|
||||||
-keys will not be issued by default.
|
|
||||||
+aes256-cts-hmac-sha1-96; also, arcfour-hmac session keys will not be
|
|
||||||
+issued by default.
|
|
||||||
|
|
||||||
Starting in krb5-1.11, it is possible to set a string attribute on a
|
|
||||||
service principal to control what session key enctypes the KDC may
|
|
||||||
@@ -90,13 +90,6 @@ affect how enctypes are chosen.
|
|
||||||
acceptable risk for your environment and the weak enctypes are
|
|
||||||
required for backward compatibility.
|
|
||||||
|
|
||||||
-**allow_des3**
|
|
||||||
- was added in release 1.21 and defaults to *false*. Unless this
|
|
||||||
- flag is set to *true*, the KDC will not issue tickets with
|
|
||||||
- des3-cbc-sha1 session keys. In a future release, this flag will
|
|
||||||
- control whether des3-cbc-sha1 is permitted in similar fashion to
|
|
||||||
- weak enctypes.
|
|
||||||
-
|
|
||||||
**allow_rc4**
|
|
||||||
was added in release 1.21 and defaults to *false*. Unless this
|
|
||||||
flag is set to *true*, the KDC will not issue tickets with
|
|
||||||
diff --git a/doc/mitK5features.rst b/doc/mitK5features.rst
|
|
||||||
index f4594ed137..d7e516861f 100644
|
|
||||||
--- a/doc/mitK5features.rst
|
|
||||||
+++ b/doc/mitK5features.rst
|
|
||||||
@@ -501,6 +501,9 @@ Release 1.18
|
|
||||||
|
|
||||||
* Protocol evolution:
|
|
||||||
|
|
||||||
+ - The KDC will no longer issue tickets with RC4 session keys unless
|
|
||||||
+ explicitly configured with the new allow_rc4 variable.
|
|
||||||
+
|
|
||||||
- Add KDC support for S4U2Self requests where the user is identified
|
|
||||||
by X.509 certificate. (Requires support for certificate lookup
|
|
||||||
from a third-party KDB module.)
|
|
||||||
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
|
|
||||||
index c3d081fd30..3c74934f25 100644
|
|
||||||
--- a/src/include/k5-int.h
|
|
||||||
+++ b/src/include/k5-int.h
|
|
||||||
@@ -181,7 +181,6 @@ typedef unsigned char u_char;
|
|
||||||
* matches the variable name. Keep these alphabetized. */
|
|
||||||
#define KRB5_CONF_ACL_FILE "acl_file"
|
|
||||||
#define KRB5_CONF_ADMIN_SERVER "admin_server"
|
|
||||||
-#define KRB5_CONF_ALLOW_DES3 "allow_des3"
|
|
||||||
#define KRB5_CONF_ALLOW_RC4 "allow_rc4"
|
|
||||||
#define KRB5_CONF_ALLOW_WEAK_CRYPTO "allow_weak_crypto"
|
|
||||||
#define KRB5_CONF_AUTH_TO_LOCAL "auth_to_local"
|
|
||||||
@@ -1261,7 +1260,6 @@ struct _krb5_context {
|
|
||||||
struct _kdb_log_context *kdblog_context;
|
|
||||||
|
|
||||||
krb5_boolean allow_weak_crypto;
|
|
||||||
- krb5_boolean allow_des3;
|
|
||||||
krb5_boolean allow_rc4;
|
|
||||||
krb5_boolean ignore_acceptor_hostname;
|
|
||||||
krb5_boolean enforce_ok_as_delegate;
|
|
||||||
diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
|
|
||||||
index b081d8e439..5a2589b0c0 100644
|
|
||||||
--- a/src/kdc/kdc_util.c
|
|
||||||
+++ b/src/kdc/kdc_util.c
|
|
||||||
@@ -1046,8 +1046,6 @@ select_session_keytype(kdc_realm_t *kdc_active_realm, krb5_db_entry *server,
|
|
||||||
* unless they are explicitly allowed. In the future they will be more
|
|
||||||
* comprehensively disabled and eventually removed.
|
|
||||||
*/
|
|
||||||
- if (ktype[i] == ENCTYPE_DES3_CBC_SHA1 && !kdc_context->allow_des3)
|
|
||||||
- continue;
|
|
||||||
if (ktype[i] == ENCTYPE_ARCFOUR_HMAC && !kdc_context->allow_rc4)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
diff --git a/src/lib/krb5/krb/init_ctx.c b/src/lib/krb5/krb/init_ctx.c
|
|
||||||
index 4b23738817..980cc0893b 100644
|
|
||||||
--- a/src/lib/krb5/krb/init_ctx.c
|
|
||||||
+++ b/src/lib/krb5/krb/init_ctx.c
|
|
||||||
@@ -226,11 +226,6 @@ krb5_init_context_profile(profile_t profile, krb5_flags flags,
|
|
||||||
goto cleanup;
|
|
||||||
ctx->allow_weak_crypto = tmp;
|
|
||||||
|
|
||||||
- retval = get_boolean(ctx, KRB5_CONF_ALLOW_DES3, 0, &tmp);
|
|
||||||
- if (retval)
|
|
||||||
- goto cleanup;
|
|
||||||
- ctx->allow_des3 = tmp;
|
|
||||||
-
|
|
||||||
retval = get_boolean(ctx, KRB5_CONF_ALLOW_RC4, 0, &tmp);
|
|
||||||
if (retval)
|
|
||||||
goto cleanup;
|
|
||||||
diff --git a/src/man/krb5.conf.man b/src/man/krb5.conf.man
|
|
||||||
index 067a9cbfe8..1a1c13b1a1 100644
|
|
||||||
--- a/src/man/krb5.conf.man
|
|
||||||
+++ b/src/man/krb5.conf.man
|
|
||||||
@@ -178,6 +178,12 @@ kdc.conf(5), but it is not a recommended practice.
|
|
||||||
The libdefaults section may contain any of the following relations:
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
|
||||||
+\fBallow_rc4\fP
|
|
||||||
+Permit the KDC to issue tickets with arcfour\-hmac session keys.
|
|
||||||
+In future releases, this flag will allow arcfour\-hmac to be used
|
|
||||||
+at all. The default value for this tag is false. (Added in
|
|
||||||
+release 1.21.)
|
|
||||||
+.TP
|
|
||||||
\fBallow_weak_crypto\fP
|
|
||||||
If this flag is set to false, then weak encryption types (as noted
|
|
||||||
in Encryption_types in kdc.conf(5)) will be filtered
|
|
||||||
diff --git a/src/tests/gssapi/t_enctypes.py b/src/tests/gssapi/t_enctypes.py
|
|
||||||
index e6bde47afc..1bb8c40b6b 100755
|
|
||||||
--- a/src/tests/gssapi/t_enctypes.py
|
|
||||||
+++ b/src/tests/gssapi/t_enctypes.py
|
|
||||||
@@ -10,9 +10,8 @@ d_rc4 = 'DEPRECATED:arcfour-hmac'
|
|
||||||
|
|
||||||
# These tests make assumptions about the default enctype lists, so set
|
|
||||||
# them explicitly rather than relying on the library defaults.
|
|
||||||
-supp='aes256-cts:normal aes128-cts:normal des3-cbc-sha1:normal rc4-hmac:normal'
|
|
||||||
-conf = {'libdefaults': {'permitted_enctypes': 'aes des3 rc4',
|
|
||||||
- 'allow_des3': 'true', 'allow_rc4': 'true'},
|
|
||||||
+supp='aes256-cts:normal aes128-cts:normal rc4-hmac:normal'
|
|
||||||
+conf = {'libdefaults': {'permitted_enctypes': 'aes rc4', 'allow_rc4': 'true'},
|
|
||||||
'realms': {'$realm': {'supported_enctypes': supp}}}
|
|
||||||
realm = K5Realm(krb5_conf=conf)
|
|
||||||
shutil.copyfile(realm.ccache, os.path.join(realm.testdir, 'save'))
|
|
||||||
diff --git a/src/tests/t_etype_info.py b/src/tests/t_etype_info.py
|
|
||||||
index 9ea5ca6228..cfdd6ab83c 100644
|
|
||||||
--- a/src/tests/t_etype_info.py
|
|
||||||
+++ b/src/tests/t_etype_info.py
|
|
||||||
@@ -1,7 +1,7 @@
|
|
||||||
from k5test import *
|
|
||||||
|
|
||||||
-supported_enctypes = 'aes128-cts des3-cbc-sha1 rc4-hmac'
|
|
||||||
-conf = {'libdefaults': {'allow_des3': 'true', 'allow_rc4': 'true'},
|
|
||||||
+supported_enctypes = 'aes128-cts rc4-hmac'
|
|
||||||
+conf = {'libdefaults': {'allow_rc4': 'true'},
|
|
||||||
'realms': {'$realm': {'supported_enctypes': supported_enctypes}}}
|
|
||||||
realm = K5Realm(create_host=False, get_creds=False, krb5_conf=conf)
|
|
||||||
|
|
||||||
diff --git a/src/tests/t_sesskeynego.py b/src/tests/t_sesskeynego.py
|
|
||||||
index f30d0bc16c..43bdcd5d7e 100755
|
|
||||||
--- a/src/tests/t_sesskeynego.py
|
|
||||||
+++ b/src/tests/t_sesskeynego.py
|
|
||||||
@@ -26,7 +26,6 @@ conf3 = {'libdefaults': {
|
|
||||||
'default_tgs_enctypes': 'rc4-hmac,aes128-cts'}}
|
|
||||||
conf4 = {'libdefaults': {'permitted_enctypes': 'aes256-cts'}}
|
|
||||||
conf5 = {'libdefaults': {'allow_rc4': 'true'}}
|
|
||||||
-conf6 = {'libdefaults': {'allow_des3': 'true'}}
|
|
||||||
# Test with client request and session_enctypes preferring aes128, but
|
|
||||||
# aes256 long-term key.
|
|
||||||
realm = K5Realm(krb5_conf=conf1, create_host=False, get_creds=False)
|
|
||||||
@@ -78,13 +77,6 @@ realm.run([kadminl, 'setstr', 'server', 'session_enctypes', 'rc4-hmac'])
|
|
||||||
test_kvno(realm, 'DEPRECATED:arcfour-hmac', 'aes256-cts-hmac-sha1-96')
|
|
||||||
realm.stop()
|
|
||||||
|
|
||||||
-# 6: allow_des3 permits negotiation of des3-cbc-sha1 session key.
|
|
||||||
-realm = K5Realm(krb5_conf=conf6, create_host=False, get_creds=False)
|
|
||||||
-realm.run([kadminl, 'addprinc', '-randkey', '-e', 'aes256-cts', 'server'])
|
|
||||||
-realm.run([kadminl, 'setstr', 'server', 'session_enctypes', 'des3-cbc-sha1'])
|
|
||||||
-test_kvno(realm, 'DEPRECATED:des3-cbc-sha1', 'aes256-cts-hmac-sha1-96')
|
|
||||||
-realm.stop()
|
|
||||||
-
|
|
||||||
# 7: default config negotiates aes256-sha1 session key for RC4-only service.
|
|
||||||
realm = K5Realm(create_host=False, get_creds=False)
|
|
||||||
realm.run([kadminl, 'addprinc', '-randkey', '-e', 'rc4-hmac', 'server'])
|
|
||||||
diff --git a/src/util/k5test.py b/src/util/k5test.py
|
|
||||||
index 96474cc5aa..c3ab63f8e8 100644
|
|
||||||
--- a/src/util/k5test.py
|
|
||||||
+++ b/src/util/k5test.py
|
|
||||||
@@ -1299,13 +1299,6 @@ _passes = [
|
|
||||||
# No special settings; exercises AES256.
|
|
||||||
('default', None, None, None),
|
|
||||||
|
|
||||||
- # Exercise the DES3 enctype.
|
|
||||||
- ('des3', None,
|
|
||||||
- {'libdefaults': {'permitted_enctypes': 'des3 aes256-sha1'}},
|
|
||||||
- {'realms': {'$realm': {
|
|
||||||
- 'supported_enctypes': 'des3-cbc-sha1:normal',
|
|
||||||
- 'master_key_type': 'des3-cbc-sha1'}}}),
|
|
||||||
-
|
|
||||||
# Exercise the arcfour enctype.
|
|
||||||
('arcfour', None,
|
|
||||||
{'libdefaults': {'permitted_enctypes': 'rc4 aes256-sha1'}},
|
|
||||||
--
|
|
||||||
2.49.0
|
|
||||||
|
|
@ -1,140 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,7 +1,3 @@
|
|||||||
[libdefaults]
|
|
||||||
# Allow RC4 HMAC-MD5 for session keys (see CVE-2022-37966)
|
|
||||||
#allow_rc4 = true
|
|
||||||
|
|
||||||
[kdcdefaults]
|
[kdcdefaults]
|
||||||
kdc_ports = 88
|
kdc_ports = 88
|
||||||
kdc_tcp_ports = 88
|
kdc_tcp_ports = 88
|
||||||
|
@ -18,7 +18,7 @@ Summary: The Kerberos network authentication system
|
|||||||
Name: krb5
|
Name: krb5
|
||||||
Version: 1.18.2
|
Version: 1.18.2
|
||||||
# for prerelease, should be e.g., 0.% {prerelease}.1% { ?dist } (without spaces)
|
# for prerelease, should be e.g., 0.% {prerelease}.1% { ?dist } (without spaces)
|
||||||
Release: 32%{?dist}
|
Release: 22%{?dist}
|
||||||
|
|
||||||
# lookaside-cached sources; two downloads and a build artifact
|
# lookaside-cached sources; two downloads and a build artifact
|
||||||
Source0: https://web.mit.edu/kerberos/dist/krb5/1.18/krb5-%{version}%{prerelease}.tar.gz
|
Source0: https://web.mit.edu/kerberos/dist/krb5/1.18/krb5-%{version}%{prerelease}.tar.gz
|
||||||
@ -94,28 +94,6 @@ Patch148: downstream-Fix-dejagnu-unit-tests-directory-name-for-RPC-lib.patch
|
|||||||
Patch149: krb5-krad-larger-attrs.patch
|
Patch149: krb5-krad-larger-attrs.patch
|
||||||
Patch150: krb5-krad-remote.patch
|
Patch150: krb5-krad-remote.patch
|
||||||
Patch151: Fix-integer-overflows-in-PAC-parsing.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
|
|
||||||
Patch167: Set-missing-mask-flags-for-kdb5_util-operations.patch
|
|
||||||
Patch168: Prevent-overflow-when-calculating-ulog-block-size.patch
|
|
||||||
Patch169: In-KDC-assume-all-services-support-aes256-sha1.patch
|
|
||||||
Patch170: Don-t-issue-session-keys-with-deprecated-enctypes.patch
|
|
||||||
Patch171: downstream-Remove-3des-support-cumulative-1.patch
|
|
||||||
Patch172: Add-PKINIT-paChecksum2-from-MS-PKCA-v20230920.patch
|
|
||||||
Patch173: downstream-Do-not-block-HMAC-MD4-5-in-FIPS-mode.patch
|
|
||||||
|
|
||||||
License: MIT
|
License: MIT
|
||||||
URL: http://web.mit.edu/kerberos/www/
|
URL: http://web.mit.edu/kerberos/www/
|
||||||
@ -726,58 +704,6 @@ exit 0
|
|||||||
%{_libdir}/libkadm5srv_mit.so.*
|
%{_libdir}/libkadm5srv_mit.so.*
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
* Thu Apr 24 2025 Julien Rische <jrische@redhat.com> - 1.18.2-32
|
|
||||||
- Do not block HMAC-MD4/5 in FIPS mode
|
|
||||||
Resolves: RHEL-86786
|
|
||||||
- Don't issue RC4 session keys by default (CVE-2025-3576)
|
|
||||||
Resolves: RHEL-88049
|
|
||||||
- Add PKINIT paChecksum2 from MS-PKCA v20230920
|
|
||||||
Resolves: RHEL-82648
|
|
||||||
|
|
||||||
* Tue Feb 11 2025 Julien Rische <jrische@redhat.com> - 1.18.2-31
|
|
||||||
- Prevent overflow when calculating ulog block size (CVE-2025-24528)
|
|
||||||
Resolves: RHEL-78248
|
|
||||||
- kdb5_util: fix DB entry flags on modification
|
|
||||||
Resolves: RHEL-56060
|
|
||||||
|
|
||||||
* 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
|
* Tue Nov 08 2022 Julien Rische <jrische@redhat.com> - 1.18.2-22
|
||||||
- Fix integer overflows in PAC parsing (CVE-2022-42898)
|
- Fix integer overflows in PAC parsing (CVE-2022-42898)
|
||||||
- Resolves: rhbz#2140968
|
- Resolves: rhbz#2140968
|
||||||
|
Loading…
Reference in New Issue
Block a user