From c0c380a017eb465b41105d1ea84da92c8edfe8e3 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Fri, 29 Jan 2016 23:35:31 +0100
Subject: [PATCH 6/6] CVE-2018-14628: python:descriptor: let samba-tool dbcheck
 fix the nTSecurityDescriptor on CN=Deleted Objects containers

BUG: https://bugzilla.samba.org/show_bug.cgi?id=13595

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
(cherry picked from commit 97e4aab1a6e2feda7c6c6fdeaa7c3e1818c55566)

Conflict: context adapt for testprogs/blackbox/dbcheck-links.sh
remove source4/selftest/provisions/release-4-5-0-pre1/expected-dbcheck-link-output-missing-link-sid-corruption.txt
remove source4/selftest/provisions/release-4-5-0-pre1/expected-links-after-dbcheck.ldif
remove source4/selftest/provisions/release-4-5-0-pre1/rootdse-version.final.txt
Reference: https://attachments.samba.org/attachment.cgi?id=18168
[PATCH 6/6] CVE-2018-14628: python:descriptor: let samba-tool dbcheck
---
 python/samba/dbchecker.py           | 10 ++++++++--
 python/samba/descriptor.py          | 15 ++++++++++++++-
 testprogs/blackbox/dbcheck-links.sh | 12 ++++++++++++
 3 files changed, 34 insertions(+), 3 deletions(-)

diff --git a/python/samba/dbchecker.py b/python/samba/dbchecker.py
index 074e7d8..128aecf 100644
--- a/python/samba/dbchecker.py
+++ b/python/samba/dbchecker.py
@@ -2401,7 +2401,7 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base)))
                     error_count += 1
                     continue
 
-                if self.reset_well_known_acls:
+                if dn == deleted_objects_dn or self.reset_well_known_acls:
                     try:
                         well_known_sd = self.get_wellknown_sd(dn)
                     except KeyError:
@@ -2410,7 +2410,13 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base)))
                     current_sd = ndr_unpack(security.descriptor,
                                             obj[attrname][0])
 
-                    diff = get_diff_sds(well_known_sd, current_sd, security.dom_sid(self.samdb.get_domain_sid()))
+                    ignoreAdditionalACEs = False
+                    if not self.reset_well_known_acls:
+                        ignoreAdditionalACEs = True
+
+                    diff = get_diff_sds(well_known_sd, current_sd,
+                                        security.dom_sid(self.samdb.get_domain_sid()),
+                                        ignoreAdditionalACEs=ignoreAdditionalACEs)
                     if diff != "":
                         self.err_wrong_default_sd(dn, well_known_sd, current_sd, diff)
                         error_count += 1
diff --git a/python/samba/descriptor.py b/python/samba/descriptor.py
index ebdd920..0141f38 100644
--- a/python/samba/descriptor.py
+++ b/python/samba/descriptor.py
@@ -417,6 +417,7 @@ def get_wellknown_sds(samdb):
     # Then subcontainers
     subcontainers = [
         (ldb.Dn(samdb, "%s" % str(samdb.domain_dn())), get_domain_descriptor),
+        (ldb.Dn(samdb, "CN=Deleted Objects,%s" % str(samdb.domain_dn())), get_deletedobjects_descriptor),
         (ldb.Dn(samdb, "CN=LostAndFound,%s" % str(samdb.domain_dn())), get_domain_delete_protected2_descriptor),
         (ldb.Dn(samdb, "CN=System,%s" % str(samdb.domain_dn())), get_domain_delete_protected1_descriptor),
         (ldb.Dn(samdb, "CN=Infrastructure,%s" % str(samdb.domain_dn())), get_domain_infrastructure_descriptor),
@@ -427,6 +428,7 @@ def get_wellknown_sds(samdb):
         (ldb.Dn(samdb, "CN=MicrosoftDNS,CN=System,%s" % str(samdb.domain_dn())), get_dns_domain_microsoft_dns_descriptor),
 
         (ldb.Dn(samdb, "%s" % str(samdb.get_config_basedn())), get_config_descriptor),
+        (ldb.Dn(samdb, "CN=Deleted Objects,%s" % str(samdb.get_config_basedn())), get_deletedobjects_descriptor),
         (ldb.Dn(samdb, "CN=NTDS Quotas,%s" % str(samdb.get_config_basedn())), get_config_ntds_quotas_descriptor),
         (ldb.Dn(samdb, "CN=LostAndFoundConfig,%s" % str(samdb.get_config_basedn())), get_config_delete_protected1wd_descriptor),
         (ldb.Dn(samdb, "CN=Services,%s" % str(samdb.get_config_basedn())), get_config_delete_protected1_descriptor),
@@ -451,6 +453,9 @@ def get_wellknown_sds(samdb):
         if ldb.Dn(samdb, nc.decode('utf8')) == dnsforestdn:
             c = (ldb.Dn(samdb, "%s" % str(dnsforestdn)), get_dns_partition_descriptor)
             subcontainers.append(c)
+            c = (ldb.Dn(samdb, "CN=Deleted Objects,%s" % str(dnsforestdn)),
+                 get_deletedobjects_descriptor)
+            subcontainers.append(c)
             c = (ldb.Dn(samdb, "CN=Infrastructure,%s" % str(dnsforestdn)),
                  get_domain_delete_protected1_descriptor)
             subcontainers.append(c)
@@ -466,6 +471,9 @@ def get_wellknown_sds(samdb):
         if ldb.Dn(samdb, nc.decode('utf8')) == dnsdomaindn:
             c = (ldb.Dn(samdb, "%s" % str(dnsdomaindn)), get_dns_partition_descriptor)
             subcontainers.append(c)
+            c = (ldb.Dn(samdb, "CN=Deleted Objects,%s" % str(dnsdomaindn)),
+                 get_deletedobjects_descriptor)
+            subcontainers.append(c)
             c = (ldb.Dn(samdb, "CN=Infrastructure,%s" % str(dnsdomaindn)),
                  get_domain_delete_protected1_descriptor)
             subcontainers.append(c)
@@ -558,7 +566,8 @@ def get_clean_sd(sd):
     return sd_clean
 
 
-def get_diff_sds(refsd, cursd, domainsid, checkSacl=True):
+def get_diff_sds(refsd, cursd, domainsid, checkSacl=True,
+                 ignoreAdditionalACEs=False):
     """Get the difference between 2 sd
 
     This function split the textual representation of ACL into smaller
@@ -613,6 +622,10 @@ def get_diff_sds(refsd, cursd, domainsid, checkSacl=True):
                     h_ref.remove(k)
 
             if len(h_cur) + len(h_ref) > 0:
+                if txt == "" and len(h_ref) == 0:
+                    if ignoreAdditionalACEs:
+                        return ""
+
                 txt = "%s\tPart %s is different between reference" \
                       " and current here is the detail:\n" % (txt, part)
 
diff --git a/testprogs/blackbox/dbcheck-links.sh b/testprogs/blackbox/dbcheck-links.sh
index d9d80d4..a9f8e46 100755
--- a/testprogs/blackbox/dbcheck-links.sh
+++ b/testprogs/blackbox/dbcheck-links.sh
@@ -41,6 +41,16 @@ dbcheck() {
     fi
 }
 
+dbcheck_acl_reset()
+{
+       $PYTHON $BINDIR/samba-tool dbcheck -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb --cross-ncs --fix --yes --attrs=nTSecurityDescriptor
+}
+
+dbcheck_acl_clean()
+{
+       $PYTHON $BINDIR/samba-tool dbcheck -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb --cross-ncs --attrs=nTSecurityDescriptor
+}
+
 dbcheck_dangling() {
     dbcheck "" "1" "--selftest-check-expired-tombstones"
     return $?
@@ -734,6 +744,8 @@ dangling_multi_valued_check_equal_or_too_many() {
 
 if [ -d $release_dir ]; then
     testit $RELEASE undump
+    testit_expect_failure "dbcheck_acl_reset" dbcheck_acl_reset
+    testit "dbcheck_acl_clean" dbcheck_acl_clean
     testit "add_two_more_users" add_two_more_users
     testit "add_four_more_links" add_four_more_links
     testit "remove_one_link" remove_one_link
-- 
2.27.0

