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