Blame SOURCES/0006-ipa-kdb-PAC-consistency-checker-needs-to-handle-child-domains-as-well_rhbz#2166324.patch

2fe7e5
From 2a0868fccbc9f4dfc540a7d3bb5dfa22c0bdce4e Mon Sep 17 00:00:00 2001
2fe7e5
From: Alexander Bokovoy <abokovoy@redhat.com>
2fe7e5
Date: Mon, 30 Jan 2023 14:22:30 +0200
2fe7e5
Subject: [PATCH 1/2] ipa-kdb: PAC consistency checker needs to handle child
2fe7e5
 domains as well
2fe7e5
2fe7e5
When PAC check is performed, we might get a signing TGT instead of the
2fe7e5
client DB entry. This means it is a principal from a trusted domain but
2fe7e5
we don't know which one exactly because we only have a krbtgt for the
2fe7e5
forest root. This happens in MIT Kerberos 1.20 or later where KDB's
2fe7e5
issue_pac() callback never gets the original client principal directly.
2fe7e5
2fe7e5
Look into known child domains as well and make pass the check if both
2fe7e5
NetBIOS name and SID correspond to one of the trusted domains under this
2fe7e5
forest root. Move check for the SID before NetBIOS name check because we
2fe7e5
can use SID of the domain in PAC to find out the right child domain in
2fe7e5
our trusted domains' topology list.
2fe7e5
2fe7e5
Fixes: https://pagure.io/freeipa/issue/9316
2fe7e5
2fe7e5
Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com>
2fe7e5
---
2fe7e5
 daemons/ipa-kdb/ipa_kdb_mspac.c | 51 +++++++++++++++++++++------------
2fe7e5
 1 file changed, 32 insertions(+), 19 deletions(-)
2fe7e5
2fe7e5
diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c
2fe7e5
index a15050e2166..476d1cb558a 100644
2fe7e5
--- a/daemons/ipa-kdb/ipa_kdb_mspac.c
2fe7e5
+++ b/daemons/ipa-kdb/ipa_kdb_mspac.c
2fe7e5
@@ -1827,11 +1827,43 @@ krb5_error_code filter_logon_info(krb5_context context,
2fe7e5
     bool result;
2fe7e5
     char *domstr = NULL;
2fe7e5
 
2fe7e5
+    ipactx = ipadb_get_context(context);
2fe7e5
+    if (!ipactx || !ipactx->mspac) {
2fe7e5
+        return KRB5_KDB_DBNOTINITED;
2fe7e5
+    }
2fe7e5
+
2fe7e5
     domain = get_domain_from_realm_update(context, realm);
2fe7e5
     if (!domain) {
2fe7e5
         return EINVAL;
2fe7e5
     }
2fe7e5
 
2fe7e5
+    /* check exact sid */
2fe7e5
+    result = dom_sid_check(&domain->domsid, info->info->info3.base.domain_sid, true);
2fe7e5
+    if (!result) {
2fe7e5
+        struct ipadb_mspac *mspac_ctx = ipactx->mspac;
2fe7e5
+        result = FALSE;
2fe7e5
+        /* Didn't match but perhaps the original PAC was issued by a child domain's DC? */
2fe7e5
+        for (k = 0; k < mspac_ctx->num_trusts; k++) {
2fe7e5
+            result = dom_sid_check(&mspac_ctx->trusts[k].domsid,
2fe7e5
+                             info->info->info3.base.domain_sid, true);
2fe7e5
+            if (result) {
2fe7e5
+                domain = &mspac_ctx->trusts[k];
2fe7e5
+                break;
2fe7e5
+            }
2fe7e5
+        }
2fe7e5
+        if (!result) {
2fe7e5
+            domstr = dom_sid_string(NULL, info->info->info3.base.domain_sid);
2fe7e5
+            krb5_klog_syslog(LOG_ERR, "PAC Info mismatch: domain = %s, "
2fe7e5
+                                      "expected domain SID = %s, "
2fe7e5
+                                      "found domain SID = %s",
2fe7e5
+                                      domain->domain_name, domain->domain_sid,
2fe7e5
+                                      domstr ? domstr : "<failed to display>");
2fe7e5
+            talloc_free(domstr);
2fe7e5
+            return EINVAL;
2fe7e5
+        }
2fe7e5
+    }
2fe7e5
+
2fe7e5
+    /* At this point we may have changed the domain we look at, */
2fe7e5
     /* check netbios/flat name */
2fe7e5
     if (strcasecmp(info->info->info3.base.logon_domain.string,
2fe7e5
                    domain->flat_name) != 0) {
2fe7e5
@@ -1843,21 +1875,6 @@ krb5_error_code filter_logon_info(krb5_context context,
2fe7e5
         return EINVAL;
2fe7e5
     }
2fe7e5
 
2fe7e5
-    /* check exact sid */
2fe7e5
-    result = dom_sid_check(&domain->domsid, info->info->info3.base.domain_sid, true);
2fe7e5
-    if (!result) {
2fe7e5
-        domstr = dom_sid_string(NULL, info->info->info3.base.domain_sid);
2fe7e5
-        if (!domstr) {
2fe7e5
-            return EINVAL;
2fe7e5
-        }
2fe7e5
-        krb5_klog_syslog(LOG_ERR, "PAC Info mismatch: domain = %s, "
2fe7e5
-                                  "expected domain SID = %s, "
2fe7e5
-                                  "found domain SID = %s",
2fe7e5
-                                  domain->domain_name, domain->domain_sid, domstr);
2fe7e5
-        talloc_free(domstr);
2fe7e5
-        return EINVAL;
2fe7e5
-    }
2fe7e5
-
2fe7e5
     /* Check if this domain has been filtered out by the trust itself*/
2fe7e5
     if (domain->parent != NULL) {
2fe7e5
         for(k = 0; k < domain->parent->len_sid_blocklist_incoming; k++) {
2fe7e5
@@ -1944,10 +1961,6 @@ krb5_error_code filter_logon_info(krb5_context context,
2fe7e5
      * should include different possibilities into account
2fe7e5
      * */
2fe7e5
     if (info->info->info3.sidcount != 0) {
2fe7e5
-        ipactx = ipadb_get_context(context);
2fe7e5
-        if (!ipactx || !ipactx->mspac) {
2fe7e5
-            return KRB5_KDB_DBNOTINITED;
2fe7e5
-        }
2fe7e5
         count = info->info->info3.sidcount;
2fe7e5
         i = 0;
2fe7e5
         j = 0;
2fe7e5
2fe7e5
From 1a4f2597253c750696f6cd34613b375dc30fe456 Mon Sep 17 00:00:00 2001
2fe7e5
From: Anuja More <amore@redhat.com>
2fe7e5
Date: Mon, 30 Jan 2023 19:27:49 +0530
2fe7e5
Subject: [PATCH 2/2] Add test for SSH with GSSAPI auth.
2fe7e5
2fe7e5
Added test for aduser with GSSAPI authentication.
2fe7e5
2fe7e5
Related : https://pagure.io/freeipa/issue/9316
2fe7e5
2fe7e5
Signed-off-by: Anuja More <amore@redhat.com>
2fe7e5
---
2fe7e5
 ipatests/test_integration/test_trust.py | 46 +++++++++++++++++++++++++
2fe7e5
 1 file changed, 46 insertions(+)
2fe7e5
2fe7e5
diff --git a/ipatests/test_integration/test_trust.py b/ipatests/test_integration/test_trust.py
2fe7e5
index 21c814ff1a9..a1ed906c6ae 100644
2fe7e5
--- a/ipatests/test_integration/test_trust.py
2fe7e5
+++ b/ipatests/test_integration/test_trust.py
2fe7e5
@@ -527,6 +527,35 @@ def test_subordinate_suffix(self):
2fe7e5
                    .format(self.ad_domain, subordinate_suffix))
2fe7e5
             self.ad.run_command(['powershell', '-c', cmd])
2fe7e5
 
2fe7e5
+    def test_ssh_aduser(self):
2fe7e5
+        """Test ssh with GSSAPI is working with aduser
2fe7e5
+
2fe7e5
+        When kerberos ticket is obtained for child domain user
2fe7e5
+        and ssh with this ticket should be successful
2fe7e5
+        with no password prompt.
2fe7e5
+
2fe7e5
+        Related : https://pagure.io/freeipa/issue/9316
2fe7e5
+        """
2fe7e5
+        testuser = 'testuser@{0}'.format(self.ad_domain)
2fe7e5
+        testusersub = 'subdomaintestuser@{0}'.format(self.ad_subdomain)
2fe7e5
+
2fe7e5
+        def sshuser(host, user):
2fe7e5
+            tasks.kdestroy_all(host)
2fe7e5
+            try:
2fe7e5
+                tasks.kinit_as_user(host, user,
2fe7e5
+                                    host.config.ad_admin_password
2fe7e5
+                                    )
2fe7e5
+                ssh_cmd = "ssh -q -K -l {user} {host} hostname"
2fe7e5
+                valid_ssh = host.run_command(
2fe7e5
+                    ssh_cmd.format(user=user, host=host.hostname)
2fe7e5
+                )
2fe7e5
+                assert host.hostname in valid_ssh.stdout_text
2fe7e5
+            finally:
2fe7e5
+                tasks.kdestroy_all(host)
2fe7e5
+
2fe7e5
+        sshuser(self.master, testuser)
2fe7e5
+        sshuser(self.master, testusersub)
2fe7e5
+
2fe7e5
     def test_remove_nonposix_trust(self):
2fe7e5
         self.remove_trust(self.ad)
2fe7e5
         tasks.unconfigure_dns_for_trust(self.master, self.ad)
2fe7e5
@@ -784,6 +813,23 @@ def test_user_gid_uid_resolution_in_external_treedomain_trust(self):
2fe7e5
         assert re.search(
2fe7e5
             testuser_regex, result.stdout_text), result.stdout_text
2fe7e5
 
2fe7e5
+    def test_ssh_adtreeuser(self):
2fe7e5
+        testuser = 'treetestuser@{0}'.format(self.ad_treedomain)
2fe7e5
+        self.master.run_command(["id", testuser])
2fe7e5
+        tasks.clear_sssd_cache(self.master)
2fe7e5
+        tasks.kdestroy_all(self.master)
2fe7e5
+        try:
2fe7e5
+            tasks.kinit_as_user(self.master, testuser,
2fe7e5
+                                password="Secret123456"
2fe7e5
+                                )
2fe7e5
+            ssh_cmd = "ssh -q -K -l {user} {host} hostname"
2fe7e5
+            valid_ssh = self.master.run_command(
2fe7e5
+                ssh_cmd.format(user=testuser, host=self.master.hostname)
2fe7e5
+            )
2fe7e5
+            assert self.master.hostname in valid_ssh.stdout_text
2fe7e5
+        finally:
2fe7e5
+            tasks.kdestroy_all(self.master)
2fe7e5
+
2fe7e5
     def test_remove_external_treedomain_trust(self):
2fe7e5
         self.remove_trust(self.tree_ad)
2fe7e5
         tasks.unconfigure_dns_for_trust(self.master, self.ad, self.tree_ad)