krb5 commit: Fix some principal realm canonicalization cases

Greg Hudson <[email protected]>
Newsgroups gmane.comp.encryption.kerberos.cvs
Message-ID <[email protected]>
https://github.com/krb5/krb5/commit/c077d0c6430c4ac163443aacc03d14d206a4cbb8
commit c077d0c6430c4ac163443aacc03d14d206a4cbb8
Author: Greg Hudson <[email protected]>
Date:   Mon Jun 7 13:27:29 2021 -0400

    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)

 src/lib/krb5/os/os-proto.h |   13 +++++++++----
 src/lib/krb5/os/sn2princ.c |   24 +++++++++++++++++++++---
 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;
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.