Blame SOURCES/0029-GPO-fix-link-order-in-a-SOM.patch

836b22
From 7cf6b86408e53c5c2c5f6da89aef3dec68223c59 Mon Sep 17 00:00:00 2001
836b22
From: Sumit Bose <sbose@redhat.com>
836b22
Date: Thu, 27 Feb 2020 06:54:21 +0100
836b22
Subject: [PATCH] GPO: fix link order in a SOM
836b22
836b22
GPOs of the same OU were applied in the wrong order. Details about how
836b22
GPOs should be processed can be found e.g. at
836b22
https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-r2-and-2012/dn581922(v%3Dws.11)
836b22
836b22
Resolves: https://github.com/SSSD/sssd/issues/5103
836b22
836b22
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
836b22
(cherry picked from commit dce025b882db7247571b135e928afb47f069a60f)
836b22
---
836b22
 src/providers/ad/ad_gpo.c | 59 +++++++++++++++++++++++++++++----------
836b22
 1 file changed, 45 insertions(+), 14 deletions(-)
836b22
836b22
diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c
836b22
index 5f85910a9..4b991783b 100644
836b22
--- a/src/providers/ad/ad_gpo.c
836b22
+++ b/src/providers/ad/ad_gpo.c
836b22
@@ -3183,14 +3183,19 @@ ad_gpo_process_som_recv(struct tevent_req *req,
836b22
  * - GPOs linked to an OU will be applied after GPOs linked to a Domain,
836b22
  *   which will be applied after GPOs linked to a Site.
836b22
  * - multiple GPOs linked to a single SOM are applied in their link order
836b22
- *   (i.e. 1st GPO linked to SOM is applied after 2nd GPO linked to SOM, etc).
836b22
+ *   (i.e. 1st GPO linked to SOM is applied before 2nd GPO linked to SOM, etc).
836b22
  * - enforced GPOs are applied after unenforced GPOs.
836b22
  *
836b22
  * As such, the _candidate_gpos output's dn fields looks like (in link order):
836b22
- * [unenforced {Site, Domain, OU}; enforced {Site, Domain, OU}]
836b22
+ * [unenforced {Site, Domain, OU}; enforced {OU, Domain, Site}]
836b22
  *
836b22
  * Note that in the case of conflicting policy settings, GPOs appearing later
836b22
- * in the list will trump GPOs appearing earlier in the list.
836b22
+ * in the list will trump GPOs appearing earlier in the list. Therefore the
836b22
+ * enforced GPOs are applied in revers order after the unenforced GPOs to
836b22
+ * make sure the enforced setting form the highest level will be applied.
836b22
+ *
836b22
+ * GPO processing details can be found e.g. at
836b22
+ * https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-r2-and-2012/dn581922(v%3Dws.11)
836b22
  */
836b22
 static errno_t
836b22
 ad_gpo_populate_candidate_gpos(TALLOC_CTX *mem_ctx,
836b22
@@ -3214,6 +3219,7 @@ ad_gpo_populate_candidate_gpos(TALLOC_CTX *mem_ctx,
836b22
     int i = 0;
836b22
     int j = 0;
836b22
     int ret;
836b22
+    size_t som_count = 0;
836b22
 
836b22
     tmp_ctx = talloc_new(NULL);
836b22
     if (tmp_ctx == NULL) {
836b22
@@ -3240,6 +3246,7 @@ ad_gpo_populate_candidate_gpos(TALLOC_CTX *mem_ctx,
836b22
         }
836b22
         i++;
836b22
     }
836b22
+    som_count = i;
836b22
 
836b22
     num_candidate_gpos = num_enforced + num_unenforced;
836b22
 
836b22
@@ -3262,9 +3269,43 @@ ad_gpo_populate_candidate_gpos(TALLOC_CTX *mem_ctx,
836b22
         goto done;
836b22
     }
836b22
 
836b22
+    i = som_count -1 ;
836b22
+    while (i >= 0) {
836b22
+        gp_som = som_list[i];
836b22
+
836b22
+        /* For unenforced_gpo_dns the most specific GPOs with the highest
836b22
+         * priority should be the last. We start with the top-level SOM and go
836b22
+         * down to the most specific one and add the unenforced following the
836b22
+         * gplink_list where the GPO with the highest priority comes last. */
836b22
+        j = 0;
836b22
+        while (gp_som && gp_som->gplink_list && gp_som->gplink_list[j]) {
836b22
+                gp_gplink = gp_som->gplink_list[j];
836b22
+
836b22
+                if (!gp_gplink->enforced) {
836b22
+                    unenforced_gpo_dns[unenforced_idx] =
836b22
+                        talloc_steal(unenforced_gpo_dns, gp_gplink->gpo_dn);
836b22
+
836b22
+                    if (unenforced_gpo_dns[unenforced_idx] == NULL) {
836b22
+                        ret = ENOMEM;
836b22
+                        goto done;
836b22
+                    }
836b22
+                    unenforced_idx++;
836b22
+                }
836b22
+                j++;
836b22
+        }
836b22
+        i--;
836b22
+    }
836b22
+
836b22
     i = 0;
836b22
     while (som_list[i]) {
836b22
         gp_som = som_list[i];
836b22
+
836b22
+        /* For enforced GPOs we start processing with the most specific SOM to
836b22
+         * make sur enforced GPOs from higher levels override to lower level
836b22
+         * ones. According to the 'Group Policy Inheritance' tab in the
836b22
+         * Windows 'Goup Policy Management' utility in the same SOM the link
836b22
+         * order is still observed and an enforced GPO with a lower link order
836b22
+         * value still overrides an enforced GPO with a higher link order. */
836b22
         j = 0;
836b22
         while (gp_som && gp_som->gplink_list && gp_som->gplink_list[j]) {
836b22
             gp_gplink = gp_som->gplink_list[j];
836b22
@@ -3282,16 +3323,6 @@ ad_gpo_populate_candidate_gpos(TALLOC_CTX *mem_ctx,
836b22
                     goto done;
836b22
                 }
836b22
                 enforced_idx++;
836b22
-            } else {
836b22
-
836b22
-                unenforced_gpo_dns[unenforced_idx] =
836b22
-                    talloc_steal(unenforced_gpo_dns, gp_gplink->gpo_dn);
836b22
-
836b22
-                if (unenforced_gpo_dns[unenforced_idx] == NULL) {
836b22
-                    ret = ENOMEM;
836b22
-                    goto done;
836b22
-                }
836b22
-                unenforced_idx++;
836b22
             }
836b22
             j++;
836b22
         }
836b22
@@ -3310,7 +3341,7 @@ ad_gpo_populate_candidate_gpos(TALLOC_CTX *mem_ctx,
836b22
     }
836b22
 
836b22
     gpo_dn_idx = 0;
836b22
-    for (i = num_unenforced - 1; i >= 0; i--) {
836b22
+    for (i = 0; i < num_unenforced; i++) {
836b22
         candidate_gpos[gpo_dn_idx] = talloc_zero(candidate_gpos, struct gp_gpo);
836b22
         if (candidate_gpos[gpo_dn_idx] == NULL) {
836b22
             ret = ENOMEM;
836b22
-- 
836b22
2.21.1
836b22