Blame SOURCES/Fix-some-principal-realm-canonicalization-cases.patch

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