aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreg Hudson <ghudson@mit.edu>2021-06-07 13:27:29 -0400
committerGreg Hudson <ghudson@mit.edu>2021-06-08 20:53:06 -0400
commitc077d0c6430c4ac163443aacc03d14d206a4cbb8 (patch)
treed7e701e8ad04d7323f232c65d141e42c84acb447
parent4e186b2789b3613362845b126bf386fa89c26709 (diff)
downloadkrb5-c077d0c6430c4ac163443aacc03d14d206a4cbb8.zip
krb5-c077d0c6430c4ac163443aacc03d14d206a4cbb8.tar.gz
krb5-c077d0c6430c4ac163443aacc03d14d206a4cbb8.tar.bz2
Fix some principal realm canonicalization cases
The no_hostrealm and subst_defrealm flags in struct canonprinc were only applied when dns_canonicalize_hostname=fallback; in the other cases, the initial krb5_sname_to_principal() result is treated as canonical. For no_hostrealm this limitation doesn't currently matter, because all uses pass a principal with no realm as input. However, subst_defrealm is used to convert the referral realm to the default realm in krb5_get_init_creds_keytab(), krb5_cc_cache_match(), and gss_acquire_cred() when it needs to check the desired name against a specified ccache. In k5_canonprinc(), if the input principal is a krb5_sname_to_principal() result and fallback isn't in effect, apply subst_defrealm. Document in os-proto.h that no_hostrealm doesn't remove an existing realm and that krb5_sname_to_principal() may already have looked one up. ticket: 9011 (new)
-rw-r--r--src/lib/krb5/os/os-proto.h13
-rw-r--r--src/lib/krb5/os/sn2princ.c24
2 files changed, 30 insertions, 7 deletions
diff --git a/src/lib/krb5/os/os-proto.h b/src/lib/krb5/os/os-proto.h
index 7d5e797..a985f2a 100644
--- a/src/lib/krb5/os/os-proto.h
+++ b/src/lib/krb5/os/os-proto.h
@@ -85,10 +85,15 @@ struct sendto_callback_info {
/*
* Initialize with all zeros except for princ. Set no_hostrealm to disable
- * host-to-realm lookup, which ordinarily happens after canonicalizing the host
- * part. Set subst_defrealm to substitute the default realm for the referral
- * realm after realm lookup (this has no effect if no_hostrealm is set). Free
- * with free_canonprinc() when done.
+ * host-to-realm lookup, which ordinarily happens during fallback processing
+ * after canonicalizing the host part. Set subst_defrealm to substitute the
+ * default realm for the referral realm after realm lookup. Do not set both
+ * flags. Free with free_canonprinc() when done.
+ *
+ * no_hostrealm only applies if fallback processing is in use
+ * (dns_canonicalize_hostname = fallback). It will not remove the realm if
+ * krb5_sname_to_principal() already canonicalized the hostname and looked up a
+ * realm. subst_defrealm applies whether or not fallback processing is in use.
*/
struct canonprinc {
krb5_const_principal princ;
diff --git a/src/lib/krb5/os/sn2princ.c b/src/lib/krb5/os/sn2princ.c
index c99b7da..93c1559 100644
--- a/src/lib/krb5/os/sn2princ.c
+++ b/src/lib/krb5/os/sn2princ.c
@@ -271,18 +271,36 @@ krb5_error_code
k5_canonprinc(krb5_context context, struct canonprinc *iter,
krb5_const_principal *princ_out)
{
+ krb5_error_code ret;
int step = ++iter->step;
*princ_out = NULL;
- /* If we're not doing fallback, the input principal is canonical. */
- if (context->dns_canonicalize_hostname != CANONHOST_FALLBACK ||
- iter->princ->type != KRB5_NT_SRV_HST || iter->princ->length != 2 ||
+ /* If the hostname isn't from krb5_sname_to_principal(), the input
+ * principal is canonical. */
+ if (iter->princ->type != KRB5_NT_SRV_HST || iter->princ->length != 2 ||
iter->princ->data[1].length == 0) {
*princ_out = (step == 1) ? iter->princ : NULL;
return 0;
}
+ /* If we're not doing fallback, the hostname is canonical, but we may need
+ * to substitute the default realm. */
+ if (context->dns_canonicalize_hostname != CANONHOST_FALLBACK) {
+ if (step > 1)
+ return 0;
+ iter->copy = *iter->princ;
+ if (iter->subst_defrealm && iter->copy.realm.length == 0) {
+ ret = krb5_get_default_realm(context, &iter->realm);
+ if (ret)
+ return ret;
+ iter->copy = *iter->princ;
+ iter->copy.realm = string2data(iter->realm);
+ }
+ *princ_out = &iter->copy;
+ return 0;
+ }
+
/* Canonicalize without DNS at step 1, with DNS at step 2. */
if (step > 2)
return 0;