bbecb6
From 0206369eec8530e96c66986c4ca501d8962193ce Mon Sep 17 00:00:00 2001
bbecb6
From: Alexander Bokovoy <abokovoy@redhat.com>
bbecb6
Date: Mon, 30 Jan 2023 14:22:30 +0200
bbecb6
Subject: [PATCH] ipa-kdb: PAC consistency checker needs to handle child
bbecb6
 domains as well
bbecb6
bbecb6
When PAC check is performed, we might get a signing TGT instead of the
bbecb6
client DB entry. This means it is a principal from a trusted domain but
bbecb6
we don't know which one exactly because we only have a krbtgt for the
bbecb6
forest root. This happens in MIT Kerberos 1.20 or later where KDB's
bbecb6
issue_pac() callback never gets the original client principal directly.
bbecb6
bbecb6
Look into known child domains as well and make pass the check if both
bbecb6
NetBIOS name and SID correspond to one of the trusted domains under this
bbecb6
forest root. Move check for the SID before NetBIOS name check because we
bbecb6
can use SID of the domain in PAC to find out the right child domain in
bbecb6
our trusted domains' topology list.
bbecb6
bbecb6
Fixes: https://pagure.io/freeipa/issue/9316
bbecb6
bbecb6
Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com>
bbecb6
Reviewed-By: Rafael Guterres Jeffman <rjeffman@redhat.com>
bbecb6
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
bbecb6
---
bbecb6
 daemons/ipa-kdb/ipa_kdb_mspac.c | 51 +++++++++++++++++++++------------
bbecb6
 1 file changed, 32 insertions(+), 19 deletions(-)
bbecb6
bbecb6
diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c
bbecb6
index a15050e2166f95c227d2e3c7d238e1ea2fe01235..476d1cb558a53420821ccfb1b794cb6bedce7794 100644
bbecb6
--- a/daemons/ipa-kdb/ipa_kdb_mspac.c
bbecb6
+++ b/daemons/ipa-kdb/ipa_kdb_mspac.c
bbecb6
@@ -1827,11 +1827,43 @@ krb5_error_code filter_logon_info(krb5_context context,
bbecb6
     bool result;
bbecb6
     char *domstr = NULL;
bbecb6
 
bbecb6
+    ipactx = ipadb_get_context(context);
bbecb6
+    if (!ipactx || !ipactx->mspac) {
bbecb6
+        return KRB5_KDB_DBNOTINITED;
bbecb6
+    }
bbecb6
+
bbecb6
     domain = get_domain_from_realm_update(context, realm);
bbecb6
     if (!domain) {
bbecb6
         return EINVAL;
bbecb6
     }
bbecb6
 
bbecb6
+    /* check exact sid */
bbecb6
+    result = dom_sid_check(&domain->domsid, info->info->info3.base.domain_sid, true);
bbecb6
+    if (!result) {
bbecb6
+        struct ipadb_mspac *mspac_ctx = ipactx->mspac;
bbecb6
+        result = FALSE;
bbecb6
+        /* Didn't match but perhaps the original PAC was issued by a child domain's DC? */
bbecb6
+        for (k = 0; k < mspac_ctx->num_trusts; k++) {
bbecb6
+            result = dom_sid_check(&mspac_ctx->trusts[k].domsid,
bbecb6
+                             info->info->info3.base.domain_sid, true);
bbecb6
+            if (result) {
bbecb6
+                domain = &mspac_ctx->trusts[k];
bbecb6
+                break;
bbecb6
+            }
bbecb6
+        }
bbecb6
+        if (!result) {
bbecb6
+            domstr = dom_sid_string(NULL, info->info->info3.base.domain_sid);
bbecb6
+            krb5_klog_syslog(LOG_ERR, "PAC Info mismatch: domain = %s, "
bbecb6
+                                      "expected domain SID = %s, "
bbecb6
+                                      "found domain SID = %s",
bbecb6
+                                      domain->domain_name, domain->domain_sid,
bbecb6
+                                      domstr ? domstr : "<failed to display>");
bbecb6
+            talloc_free(domstr);
bbecb6
+            return EINVAL;
bbecb6
+        }
bbecb6
+    }
bbecb6
+
bbecb6
+    /* At this point we may have changed the domain we look at, */
bbecb6
     /* check netbios/flat name */
bbecb6
     if (strcasecmp(info->info->info3.base.logon_domain.string,
bbecb6
                    domain->flat_name) != 0) {
bbecb6
@@ -1843,21 +1875,6 @@ krb5_error_code filter_logon_info(krb5_context context,
bbecb6
         return EINVAL;
bbecb6
     }
bbecb6
 
bbecb6
-    /* check exact sid */
bbecb6
-    result = dom_sid_check(&domain->domsid, info->info->info3.base.domain_sid, true);
bbecb6
-    if (!result) {
bbecb6
-        domstr = dom_sid_string(NULL, info->info->info3.base.domain_sid);
bbecb6
-        if (!domstr) {
bbecb6
-            return EINVAL;
bbecb6
-        }
bbecb6
-        krb5_klog_syslog(LOG_ERR, "PAC Info mismatch: domain = %s, "
bbecb6
-                                  "expected domain SID = %s, "
bbecb6
-                                  "found domain SID = %s",
bbecb6
-                                  domain->domain_name, domain->domain_sid, domstr);
bbecb6
-        talloc_free(domstr);
bbecb6
-        return EINVAL;
bbecb6
-    }
bbecb6
-
bbecb6
     /* Check if this domain has been filtered out by the trust itself*/
bbecb6
     if (domain->parent != NULL) {
bbecb6
         for(k = 0; k < domain->parent->len_sid_blocklist_incoming; k++) {
bbecb6
@@ -1944,10 +1961,6 @@ krb5_error_code filter_logon_info(krb5_context context,
bbecb6
      * should include different possibilities into account
bbecb6
      * */
bbecb6
     if (info->info->info3.sidcount != 0) {
bbecb6
-        ipactx = ipadb_get_context(context);
bbecb6
-        if (!ipactx || !ipactx->mspac) {
bbecb6
-            return KRB5_KDB_DBNOTINITED;
bbecb6
-        }
bbecb6
         count = info->info->info3.sidcount;
bbecb6
         i = 0;
bbecb6
         j = 0;
bbecb6
-- 
bbecb6
2.39.1
bbecb6