diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c index 255628612..6e8fa20dc 100644 --- a/daemons/ipa-kdb/ipa_kdb_mspac.c +++ b/daemons/ipa-kdb/ipa_kdb_mspac.c @@ -1840,8 +1840,12 @@ static krb5_error_code ipadb_verify_pac(krb5_context context, priv_key = krbtgt_key; } - kerr = krb5_pac_verify(context, old_pac, authtime, - client_princ, srv_key, priv_key); + /* only pass with_realm TRUE when it is cross-realm ticket and S4U + * extension (S4U2Self or S4U2Proxy (RBCD)) was requested */ + kerr = krb5_pac_verify_ext(context, old_pac, authtime, + client_princ, srv_key, priv_key, + (is_cross_realm && + (flags & KRB5_KDB_FLAG_PROTOCOL_TRANSITION))); if (kerr) { goto done; } @@ -1875,7 +1879,8 @@ static krb5_error_code ipadb_verify_pac(krb5_context context, for (i = 0; i < num_buffers; i++) { if (types[i] == KRB5_PAC_SERVER_CHECKSUM || - types[i] == KRB5_PAC_PRIVSVR_CHECKSUM) { + types[i] == KRB5_PAC_PRIVSVR_CHECKSUM || + types[i] == KRB5_PAC_CLIENT_INFO) { continue; } @@ -1933,6 +1938,7 @@ done: } static krb5_error_code ipadb_sign_pac(krb5_context context, + unsigned int flags, krb5_const_principal client_princ, krb5_db_entry *server, krb5_db_entry *krbtgt, @@ -1948,6 +1954,7 @@ static krb5_error_code ipadb_sign_pac(krb5_context context, krb5_principal krbtgt_princ = NULL; krb5_error_code kerr; char *princ = NULL; + bool is_issuing_referral = false; int ret; /* for cross realm trusts cases we need to sign with the right key. @@ -2006,8 +2013,17 @@ static krb5_error_code ipadb_sign_pac(krb5_context context, right_krbtgt_signing_key = krbtgt_key; } - kerr = krb5_pac_sign(context, pac, authtime, client_princ, - server_key, right_krbtgt_signing_key, pac_data); +#ifdef KRB5_KDB_FLAG_ISSUING_REFERRAL + is_issuing_referral = (flags & KRB5_KDB_FLAG_ISSUING_REFERRAL) != 0; +#endif + + /* only pass with_realm TRUE when it is cross-realm ticket and S4U2Self + * was requested */ + kerr = krb5_pac_sign_ext(context, pac, authtime, client_princ, server_key, + right_krbtgt_signing_key, + (is_issuing_referral && + (flags & KRB5_KDB_FLAG_PROTOCOL_TRANSITION)), + pac_data); done: free(princ); @@ -2224,9 +2240,10 @@ krb5_error_code ipadb_sign_authdata(krb5_context context, } /* we need to create a PAC if we are requested one and this is an AS REQ, - * or we are doing protocol transition (s4u2self) */ + * or we are doing protocol transition (S4USelf) but not over cross-realm + */ if ((is_as_req && (flags & KRB5_KDB_FLAG_INCLUDE_PAC)) || - (flags & KRB5_KDB_FLAG_PROTOCOL_TRANSITION)) { + ((flags & KRB5_KDB_FLAG_PROTOCOL_TRANSITION) && (client != NULL))) { make_ad = true; } @@ -2296,7 +2313,7 @@ krb5_error_code ipadb_sign_authdata(krb5_context context, goto done; } - kerr = ipadb_sign_pac(context, ks_client_princ, server, krbtgt, + kerr = ipadb_sign_pac(context, flags, ks_client_princ, server, krbtgt, server_key, krbtgt_key, authtime, pac, &pac_data); if (kerr != 0) { goto done; diff --git a/daemons/ipa-kdb/ipa_kdb_principals.c b/daemons/ipa-kdb/ipa_kdb_principals.c index a647b9661..57f8d01b7 100644 --- a/daemons/ipa-kdb/ipa_kdb_principals.c +++ b/daemons/ipa-kdb/ipa_kdb_principals.c @@ -1361,7 +1361,12 @@ krb5_error_code ipadb_get_principal(krb5_context kcontext, upn->length - (realm - upn->data), &trusted_realm); } - if (kerr == 0) { + + if (kerr != 0) { + goto done; + } + + if (flags & KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY) { kentry = calloc(1, sizeof(krb5_db_entry)); if (!kentry) { kerr = ENOMEM; @@ -1378,8 +1383,47 @@ krb5_error_code ipadb_get_principal(krb5_context kcontext, goto done; } *entry = kentry; + + goto done; + } else if (flags & KRB5_KDB_FLAG_INCLUDE_PAC) { + kerr = KRB5_KDB_NOENTRY; + goto done; + } else { + /* server referrals: lookup krbtgt/next_realm@our_realm */ + krb5_principal tgtp; + + kerr = krb5_build_principal_ext(kcontext, &tgtp, + strlen(ipactx->realm), + ipactx->realm, + KRB5_TGS_NAME_SIZE, + KRB5_TGS_NAME, + strlen(trusted_realm), + trusted_realm, 0); + if (kerr != 0) { + goto done; + } + + krb5_free_unparsed_name(kcontext, principal); + principal = NULL; + kerr = krb5_unparse_name(kcontext, tgtp, &principal); + krb5_free_principal(kcontext, tgtp); + if (kerr != 0) { + goto done; + } + + ldap_msgfree(res); + res = NULL; + kerr = ipadb_fetch_principals(ipactx, flags, principal, &res); + if (kerr != 0) { + goto done; + } + + kerr = ipadb_find_principal(kcontext, flags, res, &principal, + &lentry); + if (kerr != 0) { + goto done; + } } - goto done; } } else { goto done;