Hello, A couple of month back we discussed on samba mailing-list an issue in heimdal with S4U2Self when the user is not in the same domain as the impersonating service.
The problem is that we cannot just start by sending S4U2Self request to local KDC in the service realm and hope to be referred. Instead we first need to obtain a TGT to TGS in that user's realm. Only then we can send S4U2Self request to a KDC in the user's realm and follow back referrals to our own realm. See MS-SFU sections [3.1.5.1.1.1] and [4.2] for details, as well as MIT implementation where it works ok. I would like to propose the attached patch which I have tested against windows lab env, both direct forest trust and transitive forest trust with two child domains thru parent (passes make-check). Example test: kgetcred --debug --out-cache=out --impersonate=a...@child-one.acme.com -H HTTP/tomcat.child-two.acme....@child-two.acme.com A couple of follow-ups items I am thinking on: - Try to see if it can be tested by heimdal. - Do we need to fix get_cred_kdc_capath() too or just fail it early (we currently issue a failed sfu request before falling back to referrals). - When the impersonated user is given as UPN (enterprise?) then according to MS-SFU [3.1.5.1.1.1] the first step is to locate user's realm (since the same UPN suffix can be used in different realms). This is done by sending AS request to the local KDC of the service with the UPN follow referrals till we get pre-auth required. This is implemented in MIT in s4u_identify_user() and I'm considering porting it. - The fix currently only works when the service name is given as SPN, that is a shared global namespace and can be referred by KDC in other realms. The way MIT work around this, is by converting the user principal to enterprise name (user@domain) which is a global namespace as well (convert_to_enterprise()). I wonder if it is worth porting since the caller could determine the situation and convert by himself. Thank you, Isaac B.
From 61529e9226ff3e9d8147111484dcfe52df520c9f Mon Sep 17 00:00:00 2001 From: Isaac Boukris <ibouk...@gmail.com> Date: Sat, 14 Jul 2018 02:47:36 +0300 Subject: [PATCH] S4U2Self: fix impersonate with multiple realms using referrals When impersonating a user from another realm, we first need to obtain a TGT to TGS in that user's realm. Only then we can ask for a ticket for self and follow back referrals to our own realm. See MS-SFU sections 3.1.5.1.1.1 and 4.2 Signed-off-by: Isaac Boukris <ibouk...@gmail.com> --- lib/krb5/get_cred.c | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/lib/krb5/get_cred.c b/lib/krb5/get_cred.c index 45da8a374..748a4249a 100644 --- a/lib/krb5/get_cred.c +++ b/lib/krb5/get_cred.c @@ -990,7 +990,41 @@ get_cred_kdc_referral(krb5_context context, if (start_realm == NULL) return krb5_enomem(context); - /* find tgt for the clients base realm */ + /* + * find tgt for the clients base realm, if we are impersonating a user + * from another realm, then we actually need a referral tgt to that realm. + */ + if (impersonate_principal != NULL && + !krb5_realm_compare(context, impersonate_principal, in_creds->client)) + { + krb5_creds *impersonate_tgt; + referral = *in_creds; + + ret = krb5_make_principal(context, &referral.server, + start_realm, KRB5_TGS_NAME, + impersonate_principal->realm, NULL); + free(start_realm); + if (ret) { + return ret; + } + + ret = get_cred_kdc_referral(context, flags, ccache, &referral, + NULL, NULL, &impersonate_tgt); + krb5_free_principal(context, referral.server); + if (ret) { + return ret; + } + + tgt = *impersonate_tgt; + free(impersonate_tgt); + + start_realm = strdup(impersonate_principal->realm); + if (start_realm == NULL) { + krb5_free_cred_contents(context, &tgt); + return krb5_enomem(context); + } + } + else { krb5_principal tgtname; -- 2.14.3