127 lines
5.1 KiB
Diff
127 lines
5.1 KiB
Diff
|
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
|
||
|
|