Allow to set PAC ticket signature as optional
Resolves: rhbz#2178298 Signed-off-by: Julien Rische <jrische@redhat.com>
This commit is contained in:
parent
a135c3ec8a
commit
a599b39ea9
|
@ -0,0 +1,276 @@
|
||||||
|
From 5ace3ea56c0d507ca3d976d06c0e68aa63c52f26 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Julien Rische <jrische@redhat.com>
|
||||||
|
Date: Wed, 15 Mar 2023 15:56:34 +0100
|
||||||
|
Subject: [PATCH] [downstream] Allow to set PAC ticket signature as optional
|
||||||
|
|
||||||
|
MS-PAC states that "The ticket signature SHOULD be included in tickets
|
||||||
|
that are not encrypted to the krbtgt account". However, the
|
||||||
|
implementation of krb5_kdc_verify_ticket() will require the ticket
|
||||||
|
signature to be present in case the target of the request is a service
|
||||||
|
principal.
|
||||||
|
|
||||||
|
In gradual upgrade environments, it results in S4U2Proxy requests
|
||||||
|
against a 1.20 KDC using a service ticket generated by an older version
|
||||||
|
KDC to fail.
|
||||||
|
|
||||||
|
This commit adds a krb5_kdc_verify_ticket_ext() function with an extra
|
||||||
|
switch parameter to tolerate the absence of ticket signature in this
|
||||||
|
scenario. If the ticket signature is present, it has to be valid,
|
||||||
|
regardless of this parameter.
|
||||||
|
|
||||||
|
This parameter is set based on the "optional_pac_tkt_chksum" string
|
||||||
|
attribute of the TGT KDB entry.
|
||||||
|
---
|
||||||
|
doc/admin/admin_commands/kadmin_local.rst | 6 ++++
|
||||||
|
doc/appdev/refs/api/index.rst | 1 +
|
||||||
|
src/include/kdb.h | 1 +
|
||||||
|
src/include/krb5/krb5.hin | 40 +++++++++++++++++++++++
|
||||||
|
src/kdc/kdc_util.c | 26 ++++++++++++---
|
||||||
|
src/lib/krb5/krb/pac.c | 31 +++++++++++++++---
|
||||||
|
src/lib/krb5/libkrb5.exports | 1 +
|
||||||
|
src/lib/krb5_32.def | 1 +
|
||||||
|
src/man/kadmin.man | 6 ++++
|
||||||
|
9 files changed, 105 insertions(+), 8 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/doc/admin/admin_commands/kadmin_local.rst b/doc/admin/admin_commands/kadmin_local.rst
|
||||||
|
index cf75e61584..45cce8bb57 100644
|
||||||
|
--- a/doc/admin/admin_commands/kadmin_local.rst
|
||||||
|
+++ b/doc/admin/admin_commands/kadmin_local.rst
|
||||||
|
@@ -671,6 +671,12 @@ KDC:
|
||||||
|
is in the same format as those used by the **pkinit_cert_match**
|
||||||
|
option in :ref:`krb5.conf(5)`. (New in release 1.16.)
|
||||||
|
|
||||||
|
+**optional_pac_tkt_chksum**
|
||||||
|
+ Boolean value defining the behavior of the KDC in case an expected
|
||||||
|
+ ticket checksum signed with one of this principal keys is not
|
||||||
|
+ present in the PAC. This is typically the case for TGS or
|
||||||
|
+ cross-realm TGS principals when processing S4U2Proxy requests.
|
||||||
|
+
|
||||||
|
This command requires the **modify** privilege.
|
||||||
|
|
||||||
|
Alias: **setstr**
|
||||||
|
diff --git a/doc/appdev/refs/api/index.rst b/doc/appdev/refs/api/index.rst
|
||||||
|
index d12be47c3c..9b95ebd0f9 100644
|
||||||
|
--- a/doc/appdev/refs/api/index.rst
|
||||||
|
+++ b/doc/appdev/refs/api/index.rst
|
||||||
|
@@ -225,6 +225,7 @@ Rarely used public interfaces
|
||||||
|
krb5_is_referral_realm.rst
|
||||||
|
krb5_kdc_sign_ticket.rst
|
||||||
|
krb5_kdc_verify_ticket.rst
|
||||||
|
+ krb5_kdc_verify_ticket_ext.rst
|
||||||
|
krb5_kt_add_entry.rst
|
||||||
|
krb5_kt_end_seq_get.rst
|
||||||
|
krb5_kt_get_entry.rst
|
||||||
|
diff --git a/src/include/kdb.h b/src/include/kdb.h
|
||||||
|
index 21bddcfb88..b65c300d8a 100644
|
||||||
|
--- a/src/include/kdb.h
|
||||||
|
+++ b/src/include/kdb.h
|
||||||
|
@@ -134,6 +134,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_PAC_TKT_CHKSUM "optional_pac_tkt_chksum"
|
||||||
|
|
||||||
|
#if !defined(_WIN32)
|
||||||
|
|
||||||
|
diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin
|
||||||
|
index 2ba4010514..404719a3a4 100644
|
||||||
|
--- a/src/include/krb5/krb5.hin
|
||||||
|
+++ b/src/include/krb5/krb5.hin
|
||||||
|
@@ -8355,6 +8355,46 @@ krb5_kdc_verify_ticket(krb5_context context, const krb5_enc_tkt_part *enc_tkt,
|
||||||
|
const krb5_keyblock *server,
|
||||||
|
const krb5_keyblock *privsvr, krb5_pac *pac_out);
|
||||||
|
|
||||||
|
+/**
|
||||||
|
+ * Verify a PAC, possibly including ticket signature
|
||||||
|
+ *
|
||||||
|
+ * @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)
|
||||||
|
+ * @paran [in] optional_tkt_chksum Whether to require a ticket checksum
|
||||||
|
+ * @param [out] pac_out Verified PAC (NULL if no PAC included)
|
||||||
|
+ *
|
||||||
|
+ * This function is an extension of krb5_kdc_verify_ticket(), adding the @a
|
||||||
|
+ * optional_tkt_chksum parameter allowing to tolerate the absence of the PAC
|
||||||
|
+ * ticket signature.
|
||||||
|
+ *
|
||||||
|
+ * 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 and
|
||||||
|
+ * @a optional_tkt_chksum is FALSE, 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.
|
||||||
|
+ *
|
||||||
|
+ * 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
|
||||||
|
+ */
|
||||||
|
+krb5_error_code KRB5_CALLCONV
|
||||||
|
+krb5_kdc_verify_ticket_ext(krb5_context context,
|
||||||
|
+ const krb5_enc_tkt_part *enc_tkt,
|
||||||
|
+ krb5_const_principal server_princ,
|
||||||
|
+ const krb5_keyblock *server,
|
||||||
|
+ const krb5_keyblock *privsvr,
|
||||||
|
+ krb5_boolean optional_tkt_chksum,
|
||||||
|
+ 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,
|
||||||
|
diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
|
||||||
|
index b7a9aa4992..bdf1bf2dc8 100644
|
||||||
|
--- a/src/kdc/kdc_util.c
|
||||||
|
+++ b/src/kdc/kdc_util.c
|
||||||
|
@@ -535,6 +535,8 @@ get_verified_pac(krb5_context context, const krb5_enc_tkt_part *enc_tkt,
|
||||||
|
krb5_key_data *kd;
|
||||||
|
krb5_keyblock old_key;
|
||||||
|
krb5_kvno kvno;
|
||||||
|
+ krb5_boolean optional_tkt_chksum;
|
||||||
|
+ char *str = NULL;
|
||||||
|
int tries;
|
||||||
|
|
||||||
|
*pac_out = NULL;
|
||||||
|
@@ -545,8 +547,23 @@ get_verified_pac(krb5_context context, const krb5_enc_tkt_part *enc_tkt,
|
||||||
|
NULL, pac_out);
|
||||||
|
}
|
||||||
|
|
||||||
|
- ret = krb5_kdc_verify_ticket(context, enc_tkt, sprinc, server_key,
|
||||||
|
- tgt_key, pac_out);
|
||||||
|
+ /* Check if the absence of ticket signature is tolerated for this realm */
|
||||||
|
+ ret = krb5_dbe_get_string(context, tgt,
|
||||||
|
+ KRB5_KDB_SK_OPTIONAL_PAC_TKT_CHKSUM, &str);
|
||||||
|
+ /* TODO: should be using _krb5_conf_boolean(), but os-proto.h is not
|
||||||
|
+ * available here.
|
||||||
|
+ */
|
||||||
|
+ optional_tkt_chksum = !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);
|
||||||
|
+
|
||||||
|
+ krb5_dbe_free_string(context, str);
|
||||||
|
+
|
||||||
|
+ ret = krb5_kdc_verify_ticket_ext(context, enc_tkt, sprinc, server_key,
|
||||||
|
+ tgt_key, optional_tkt_chksum, pac_out);
|
||||||
|
if (ret != KRB5KRB_AP_ERR_MODIFIED && ret != KRB5_BAD_ENCTYPE)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
@@ -559,8 +576,9 @@ get_verified_pac(krb5_context context, const krb5_enc_tkt_part *enc_tkt,
|
||||||
|
ret = krb5_dbe_decrypt_key_data(context, NULL, kd, &old_key, NULL);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
- ret = krb5_kdc_verify_ticket(context, enc_tkt, sprinc, server_key,
|
||||||
|
- &old_key, pac_out);
|
||||||
|
+ ret = krb5_kdc_verify_ticket_ext(context, enc_tkt, sprinc, server_key,
|
||||||
|
+ &old_key, optional_tkt_chksum,
|
||||||
|
+ pac_out);
|
||||||
|
krb5_free_keyblock_contents(context, &old_key);
|
||||||
|
if (!ret)
|
||||||
|
return 0;
|
||||||
|
diff --git a/src/lib/krb5/krb/pac.c b/src/lib/krb5/krb/pac.c
|
||||||
|
index 954482e0c7..738887b388 100644
|
||||||
|
--- a/src/lib/krb5/krb/pac.c
|
||||||
|
+++ b/src/lib/krb5/krb/pac.c
|
||||||
|
@@ -636,6 +636,19 @@ 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)
|
||||||
|
+{
|
||||||
|
+ return krb5_kdc_verify_ticket_ext(context, enc_tkt, server_princ, server,
|
||||||
|
+ privsvr, FALSE, pac_out);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+krb5_error_code KRB5_CALLCONV
|
||||||
|
+krb5_kdc_verify_ticket_ext(krb5_context context,
|
||||||
|
+ const krb5_enc_tkt_part *enc_tkt,
|
||||||
|
+ krb5_const_principal server_princ,
|
||||||
|
+ const krb5_keyblock *server,
|
||||||
|
+ const krb5_keyblock *privsvr,
|
||||||
|
+ krb5_boolean optional_tkt_chksum,
|
||||||
|
+ krb5_pac *pac_out)
|
||||||
|
{
|
||||||
|
krb5_error_code ret;
|
||||||
|
krb5_pac pac = NULL;
|
||||||
|
@@ -643,7 +656,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;
|
||||||
|
+ krb5_boolean is_service_tkt, has_tkt_chksum = FALSE;
|
||||||
|
size_t i, j;
|
||||||
|
|
||||||
|
*pac_out = NULL;
|
||||||
|
@@ -706,11 +719,21 @@ krb5_kdc_verify_ticket(krb5_context context, const krb5_enc_tkt_part *enc_tkt,
|
||||||
|
|
||||||
|
ret = verify_checksum(context, pac, KRB5_PAC_TICKET_CHECKSUM, privsvr,
|
||||||
|
KRB5_KEYUSAGE_APP_DATA_CKSUM, recoded_tkt);
|
||||||
|
- if (ret)
|
||||||
|
- goto cleanup;
|
||||||
|
+ if (ret) {
|
||||||
|
+ if (!optional_tkt_chksum)
|
||||||
|
+ goto cleanup;
|
||||||
|
+ else if (ret != ENOENT)
|
||||||
|
+ goto cleanup;
|
||||||
|
+ /* Otherwise ticket signature is absent but optional. Proceed... */
|
||||||
|
+ } else {
|
||||||
|
+ has_tkt_chksum = TRUE;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
+ /* Else, we make the assumption the ticket signature is absent in case this
|
||||||
|
+ * is not a service ticket.
|
||||||
|
+ */
|
||||||
|
|
||||||
|
- ret = verify_pac_checksums(context, pac, is_service_tkt, server, privsvr);
|
||||||
|
+ ret = verify_pac_checksums(context, pac, has_tkt_chksum, server, privsvr);
|
||||||
|
if (ret)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
diff --git a/src/lib/krb5/libkrb5.exports b/src/lib/krb5/libkrb5.exports
|
||||||
|
index 4c50e935a2..d4b0455c8c 100644
|
||||||
|
--- a/src/lib/krb5/libkrb5.exports
|
||||||
|
+++ b/src/lib/krb5/libkrb5.exports
|
||||||
|
@@ -463,6 +463,7 @@ krb5_is_thread_safe
|
||||||
|
krb5_kdc_rep_decrypt_proc
|
||||||
|
krb5_kdc_sign_ticket
|
||||||
|
krb5_kdc_verify_ticket
|
||||||
|
+krb5_kdc_verify_ticket_ext
|
||||||
|
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 b1610974b1..6ecd92c1ec 100644
|
||||||
|
--- a/src/lib/krb5_32.def
|
||||||
|
+++ b/src/lib/krb5_32.def
|
||||||
|
@@ -510,3 +510,4 @@ EXPORTS
|
||||||
|
k5_sname_compare @474 ; PRIVATE GSSAPI
|
||||||
|
krb5_kdc_sign_ticket @475 ;
|
||||||
|
krb5_kdc_verify_ticket @476 ;
|
||||||
|
+ krb5_kdc_verify_ticket_ext @477 ;
|
||||||
|
diff --git a/src/man/kadmin.man b/src/man/kadmin.man
|
||||||
|
index 73e1b03cdb..54efd4ebc9 100644
|
||||||
|
--- a/src/man/kadmin.man
|
||||||
|
+++ b/src/man/kadmin.man
|
||||||
|
@@ -715,6 +715,12 @@ attributes required for the client certificate used by the
|
||||||
|
principal during PKINIT authentication. The matching expression
|
||||||
|
is in the same format as those used by the \fBpkinit_cert_match\fP
|
||||||
|
option in krb5.conf(5)\&. (New in release 1.16.)
|
||||||
|
+.TP
|
||||||
|
+\fBoptional_pac_tkt_chksum\fP
|
||||||
|
+Boolean value defining the behavior of the KDC in case an expected ticket
|
||||||
|
+checksum signed with one of this principal keys is not present in the PAC. This
|
||||||
|
+is typically the case for TGS or cross-realm TGS principals when processing
|
||||||
|
+S4U2Proxy requests.
|
||||||
|
.UNINDENT
|
||||||
|
.sp
|
||||||
|
This command requires the \fBmodify\fP privilege.
|
||||||
|
--
|
||||||
|
2.40.1
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
#
|
#
|
||||||
# baserelease is what we have standardized across Fedora and what
|
# baserelease is what we have standardized across Fedora and what
|
||||||
# rpmdev-bumpspec knows how to handle.
|
# rpmdev-bumpspec knows how to handle.
|
||||||
%global baserelease 8
|
%global baserelease 8.1
|
||||||
|
|
||||||
# This should be e.g. beta1 or %%nil
|
# This should be e.g. beta1 or %%nil
|
||||||
%global pre_release %nil
|
%global pre_release %nil
|
||||||
|
@ -101,6 +101,7 @@ Patch15: 0015-downstream-Allow-KRB5KDF-MD5-and-MD4-in-FIPS-mode.patch
|
||||||
Patch16: 0016-Add-PAC-full-checksums.patch
|
Patch16: 0016-Add-PAC-full-checksums.patch
|
||||||
Patch17: 0017-Fix-possible-double-free-during-KDB-creation.patch
|
Patch17: 0017-Fix-possible-double-free-during-KDB-creation.patch
|
||||||
Patch18: 0018-Fix-meridian-type-in-kadmin-datetime-parser.patch
|
Patch18: 0018-Fix-meridian-type-in-kadmin-datetime-parser.patch
|
||||||
|
Patch19: 0019-downstream-Allow-to-set-PAC-ticket-signature-as-opti.patch
|
||||||
|
|
||||||
License: MIT
|
License: MIT
|
||||||
URL: https://web.mit.edu/kerberos/www/
|
URL: https://web.mit.edu/kerberos/www/
|
||||||
|
@ -665,6 +666,10 @@ exit 0
|
||||||
%{_libdir}/libkadm5srv_mit.so.*
|
%{_libdir}/libkadm5srv_mit.so.*
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Thu Jun 08 2023 Julien Rische <jrische@redhat.com> - 1.20.1-8.1
|
||||||
|
- Allow to set PAC ticket signature as optional
|
||||||
|
- Resolves: rhbz#2178298
|
||||||
|
|
||||||
* Wed Feb 22 2023 Julien Rische <jrische@redhat.com> - 1.20.1-8
|
* Wed Feb 22 2023 Julien Rische <jrische@redhat.com> - 1.20.1-8
|
||||||
- Fix datetime parsing in kadmin on s390x
|
- Fix datetime parsing in kadmin on s390x
|
||||||
- Resolves: rhbz#2169985
|
- Resolves: rhbz#2169985
|
||||||
|
|
Loading…
Reference in New Issue