125 lines
4.8 KiB
Diff
125 lines
4.8 KiB
Diff
From d80afa1396c3a6605338e4eaaf5bc44f8ad3eacc Mon Sep 17 00:00:00 2001
|
|
From: Isaac Boukris <iboukris@gmail.com>
|
|
Date: Fri, 4 Sep 2020 14:05:50 +0300
|
|
Subject: [PATCH] Improve KDC alias checking for S4U requests
|
|
|
|
When processing an S4U2Self request, check for DB aliases when
|
|
matching the TGT client against the request server. When processing
|
|
an S4U2Proxy request, check for DB aliases when matching the TGT
|
|
client against the evidence ticket server.
|
|
|
|
[ghudson@mit.edu: minor edits; rewrote commit message]
|
|
|
|
ticket: 8946 (new)
|
|
(cherry picked from commit 05deeebfc096970b5d9aa67a48b14106cf1b9b56)
|
|
---
|
|
src/kdc/kdc_util.c | 74 ++++++++++++++++------------------------------
|
|
1 file changed, 25 insertions(+), 49 deletions(-)
|
|
|
|
diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
|
|
index e3352f9cc..dcb2df8dc 100644
|
|
--- a/src/kdc/kdc_util.c
|
|
+++ b/src/kdc/kdc_util.c
|
|
@@ -1463,6 +1463,25 @@ cleanup:
|
|
return code;
|
|
}
|
|
|
|
+/* Return true if princ canonicalizes to the same principal as canon. */
|
|
+static krb5_boolean
|
|
+is_client_alias(krb5_context context, krb5_const_principal canon,
|
|
+ krb5_const_principal princ)
|
|
+{
|
|
+ krb5_error_code ret;
|
|
+ krb5_db_entry *self;
|
|
+ krb5_boolean is_self = FALSE;
|
|
+
|
|
+ ret = krb5_db_get_principal(context, princ,
|
|
+ KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY, &self);
|
|
+ if (!ret) {
|
|
+ is_self = krb5_principal_compare(context, canon, self->princ);
|
|
+ krb5_db_free_principal(context, self);
|
|
+ }
|
|
+
|
|
+ return is_self;
|
|
+}
|
|
+
|
|
/*
|
|
* Protocol transition (S4U2Self)
|
|
*/
|
|
@@ -1481,7 +1500,6 @@ kdc_process_s4u2self_req(kdc_realm_t *kdc_active_realm,
|
|
{
|
|
krb5_error_code code;
|
|
krb5_pa_data *pa_data;
|
|
- int flags;
|
|
krb5_db_entry *princ;
|
|
krb5_s4u_userid *id;
|
|
|
|
@@ -1515,51 +1533,11 @@ kdc_process_s4u2self_req(kdc_realm_t *kdc_active_realm,
|
|
}
|
|
id = &(*s4u_x509_user)->user_id;
|
|
|
|
- /*
|
|
- * We need to compare the client name in the TGT with the requested
|
|
- * server name. Supporting server name aliases without assuming a
|
|
- * global name service makes this difficult to do.
|
|
- *
|
|
- * The comparison below handles the following cases (note that the
|
|
- * term "principal name" below excludes the realm).
|
|
- *
|
|
- * (1) The requested service is a host-based service with two name
|
|
- * components, in which case we assume the principal name to
|
|
- * contain sufficient qualifying information. The realm is
|
|
- * ignored for the purpose of comparison.
|
|
- *
|
|
- * (2) The requested service name is an enterprise principal name:
|
|
- * the service principal name is compared with the unparsed
|
|
- * form of the client name (including its realm).
|
|
- *
|
|
- * (3) The requested service is some other name type: an exact
|
|
- * match is required.
|
|
- *
|
|
- * An alternative would be to look up the server once again with
|
|
- * FLAG_CANONICALIZE | FLAG_CLIENT_REFERRALS_ONLY set, do an exact
|
|
- * match between the returned name and client_princ. However, this
|
|
- * assumes that the client set FLAG_CANONICALIZE when requesting
|
|
- * the TGT and that we have a global name service.
|
|
- */
|
|
- flags = 0;
|
|
- switch (krb5_princ_type(kdc_context, request->server)) {
|
|
- case KRB5_NT_SRV_HST: /* (1) */
|
|
- if (krb5_princ_size(kdc_context, request->server) == 2)
|
|
- flags |= KRB5_PRINCIPAL_COMPARE_IGNORE_REALM;
|
|
- break;
|
|
- case KRB5_NT_ENTERPRISE_PRINCIPAL: /* (2) */
|
|
- flags |= KRB5_PRINCIPAL_COMPARE_ENTERPRISE;
|
|
- break;
|
|
- default: /* (3) */
|
|
- break;
|
|
- }
|
|
-
|
|
- if (!krb5_principal_compare_flags(kdc_context,
|
|
- request->server,
|
|
- client_princ,
|
|
- flags)) {
|
|
- *status = "INVALID_S4U2SELF_REQUEST";
|
|
- return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; /* match Windows error code */
|
|
+ /* If the server is local, check that the request is for self. */
|
|
+ if (!isflagset(c_flags, KRB5_KDB_FLAG_ISSUING_REFERRAL) &&
|
|
+ !is_client_alias(kdc_context, server->princ, client_princ)) {
|
|
+ *status = "INVALID_S4U2SELF_REQUEST_SERVER_MISMATCH";
|
|
+ return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; /* match Windows error */
|
|
}
|
|
|
|
/*
|
|
@@ -1750,9 +1728,7 @@ kdc_process_s4u2proxy_req(kdc_realm_t *kdc_active_realm, unsigned int flags,
|
|
}
|
|
|
|
client_princ = *stkt_authdata_client;
|
|
- } else if (!krb5_principal_compare(kdc_context,
|
|
- server->princ, /* after canon */
|
|
- server_princ)) {
|
|
+ } else if (!is_client_alias(kdc_context, server->princ, server_princ)) {
|
|
*status = "EVIDENCE_TICKET_MISMATCH";
|
|
return KRB5KDC_ERR_SERVER_NOMATCH;
|
|
}
|