1a0d7a
From 7d93bda31ce0b4e0e22c6e464c9138800dcf8b1c Mon Sep 17 00:00:00 2001
1a0d7a
From: Alexander Bokovoy <abokovoy@redhat.com>
1a0d7a
Date: Fri, 26 Nov 2021 11:13:51 +0200
1a0d7a
Subject: [PATCH] ipa-kdb: fix requester SID check according to MS-KILE and
1a0d7a
 MS-SFU updates
1a0d7a
1a0d7a
New versions of MS-KILE and MS-SFU after Windows Server November 2021
1a0d7a
security updates add PAC_REQUESTER_SID buffer check behavior:
1a0d7a
1a0d7a
 - PAC_REQUESTER_SID should only be added for TGT requests
1a0d7a
1a0d7a
 - if PAC_REQUESTER_SID is present, KDC must verify that the cname on
1a0d7a
   the ticket resolves to the account with the same SID as the
1a0d7a
   PAC_REQUESTER_SID. If it doesn't KDC must respond with
1a0d7a
   KDC_ERR_TKT_REVOKED
1a0d7a
1a0d7a
Change requester SID check to skip exact check for non-local
1a0d7a
PAC_REQUESTER_SID but harden to ensure it comes from the trusted domains
1a0d7a
we know about.
1a0d7a
1a0d7a
If requester SID is the same as in PAC, we already do cname vs PAC SID
1a0d7a
verification.
1a0d7a
1a0d7a
With these changes FreeIPA works against Windows Server 2019 with
1a0d7a
November 2021 security fixes in cross-realm S4U2Self operations.
1a0d7a
1a0d7a
Fixes: https://pagure.io/freeipa/issue/9031
1a0d7a
1a0d7a
Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com>
1a0d7a
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
1a0d7a
---
1a0d7a
 daemons/ipa-kdb/ipa_kdb_mspac.c | 47 ++++++++++++++++++++++++---------
1a0d7a
 1 file changed, 34 insertions(+), 13 deletions(-)
1a0d7a
1a0d7a
diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c
1a0d7a
index 538cfbba9..1b972c167 100644
1a0d7a
--- a/daemons/ipa-kdb/ipa_kdb_mspac.c
1a0d7a
+++ b/daemons/ipa-kdb/ipa_kdb_mspac.c
1a0d7a
@@ -1697,7 +1697,7 @@ static krb5_error_code check_logon_info_consistent(krb5_context context,
1a0d7a
                                       "local [%s], PAC [%s]",
1a0d7a
                                       dom ? dom : "<failed to display>",
1a0d7a
                                       sid ? sid : "<failed to display>");
1a0d7a
-            return KRB5KDC_ERR_POLICY;
1a0d7a
+            return KRB5KDC_ERR_TGT_REVOKED;
1a0d7a
         }
1a0d7a
     }
1a0d7a
 
1a0d7a
@@ -1709,7 +1709,7 @@ static krb5_error_code check_logon_info_consistent(krb5_context context,
1a0d7a
     kerr = ipadb_get_principal(context, client_princ, flags, &client_actual);
1a0d7a
     if (kerr != 0) {
1a0d7a
         krb5_klog_syslog(LOG_ERR, "PAC issue: ipadb_get_principal failed.");
1a0d7a
-        return KRB5KDC_ERR_POLICY;
1a0d7a
+        return KRB5KDC_ERR_TGT_REVOKED;
1a0d7a
     }
1a0d7a
 
1a0d7a
     ied = (struct ipadb_e_data *)client_actual->e_data;
1a0d7a
@@ -1743,7 +1743,7 @@ static krb5_error_code check_logon_info_consistent(krb5_context context,
1a0d7a
                                   "local [%s] vs PAC [%s]",
1a0d7a
                                   local_sid ? local_sid : "<failed to display>",
1a0d7a
                                   pac_sid ? pac_sid : "<failed to display>");
1a0d7a
-        kerr = KRB5KDC_ERR_POLICY;
1a0d7a
+        kerr = KRB5KDC_ERR_TGT_REVOKED;
1a0d7a
         goto done;
1a0d7a
     }
1a0d7a
 
1a0d7a
@@ -2005,22 +2005,43 @@ static krb5_error_code ipadb_check_logon_info(krb5_context context,
1a0d7a
     /* Check that requester SID is the same as in the PAC entry */
1a0d7a
     if (requester_sid != NULL) {
1a0d7a
         struct dom_sid client_sid;
1a0d7a
+        bool is_from_trusted_domain = false;
1a0d7a
         kerr = ipadb_get_sid_from_pac(tmpctx, info.info, &client_sid);
1a0d7a
         if (kerr) {
1a0d7a
             goto done;
1a0d7a
         }
1a0d7a
         result = dom_sid_check(&client_sid, requester_sid, true);
1a0d7a
         if (!result) {
1a0d7a
-            /* memctx is freed by the caller */
1a0d7a
-            char *pac_sid = dom_sid_string(tmpctx, &client_sid);
1a0d7a
-            char *req_sid = dom_sid_string(tmpctx, requester_sid);
1a0d7a
-            krb5_klog_syslog(LOG_ERR, "PAC issue: PAC has a SID "
1a0d7a
-                                      "different from what PAC requester claims. "
1a0d7a
-                                      "PAC [%s] vs PAC requester [%s]",
1a0d7a
-                                      pac_sid ? pac_sid : "<failed to display>",
1a0d7a
-                                      req_sid ? req_sid : "<failed to display>");
1a0d7a
-            kerr = KRB5KDC_ERR_POLICY;
1a0d7a
-            goto done;
1a0d7a
+            struct ipadb_context *ipactx = ipadb_get_context(context);
1a0d7a
+            if (!ipactx || !ipactx->mspac) {
1a0d7a
+                return KRB5_KDB_DBNOTINITED;
1a0d7a
+            }
1a0d7a
+            /* In S4U case we might be dealing with the PAC issued by the trusted domain */
1a0d7a
+            if (is_s4u && (ipactx->mspac->trusts != NULL)) {
1a0d7a
+                /* Iterate through list of trusts and check if this SID belongs to
1a0d7a
+                * one of the domains we trust */
1a0d7a
+                for(int i = 0 ; i < ipactx->mspac->num_trusts ; i++) {
1a0d7a
+                    result = dom_sid_check(&ipactx->mspac->trusts[i].domsid,
1a0d7a
+                                           requester_sid, false);
1a0d7a
+                    if (result) {
1a0d7a
+                        is_from_trusted_domain = true;
1a0d7a
+                        break;
1a0d7a
+                    }
1a0d7a
+                }
1a0d7a
+            }
1a0d7a
+
1a0d7a
+            if (!is_from_trusted_domain) {
1a0d7a
+                /* memctx is freed by the caller */
1a0d7a
+                char *pac_sid = dom_sid_string(tmpctx, &client_sid);
1a0d7a
+                char *req_sid = dom_sid_string(tmpctx, requester_sid);
1a0d7a
+                krb5_klog_syslog(LOG_ERR, "PAC issue: PAC has a SID "
1a0d7a
+                                        "different from what PAC requester claims. "
1a0d7a
+                                        "PAC [%s] vs PAC requester [%s]",
1a0d7a
+                                        pac_sid ? pac_sid : "<failed to display>",
1a0d7a
+                                        req_sid ? req_sid : "<failed to display>");
1a0d7a
+                kerr = KRB5KDC_ERR_TGT_REVOKED;
1a0d7a
+                goto done;
1a0d7a
+            }
1a0d7a
         }
1a0d7a
     }
1a0d7a
 
1a0d7a
-- 
1a0d7a
2.31.1
1a0d7a