[SCM] Samba Shared Repository - branch master updated

Stefan Metzmacher metze at samba.org
Mon Mar 25 06:26:02 MDT 2013


The branch, master has been updated
       via  30adf0c scripting: Fill the ProvisionNames hash with strings, not ldb.MessageElement or Dn
       via  5d42260 samba-tool ldapcmp: Remove the GUID -> name mappings
       via  1589e46 selftest: Add tests for samba-tool dbcheck --reset-well-known-acls
       via  874a93b scripting: Modify samba.descriptor.get_diff_sds() to cope with a missing reference owner
       via  4789a30 samba-tool dbcheck: Allow dbcheck to correct an nTSecurityDescriptor without an owner or group
       via  810f8b4 samba-tool dbcheck: Add --reset-well-known-acls
       via  9040e26 scripting: Move get_diff_sds from samba.upgradehelpers to samba.descriptor
       via  a113ddb scripting: Modify samba.descriptor.get_wellknown_sds() use samdb calls only
       via  352aff8 scripting: Move samba.provision.descriptor to samba.descriptor
       via  e81a97d scripting: Make samba.provision.descriptor.get_wellknown_sds() return ldb.Dn objects
       via  6df17fe scripting: Fix documentation comment on upgradehelpers.py:get_clean_sd
       via  3da89b0 scripting: Move the list of well known SDs to samba.provision.descriptor
       via  afe9343 build: Do not pass CPP="" to pidl, skip the env variable entirely
       via  7dc6dfd build: Remove the forced use of only the first part of the compiler string
      from  d27f00c vfs-btrfs: Fix build on 32 bit platforms by using long long types

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 30adf0cdbae6d9aaf2e72513d9c33267248f20c0
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Fri Mar 22 21:58:25 2013 +1100

    scripting: Fill the ProvisionNames hash with strings, not ldb.MessageElement or Dn
    
    This avoids the need to fix it up again in samba_upgradedns.
    
    Andrew Bartlett
    
    Reviewed-by: Stefan Metzmacher <metze at samba.org>
    
    Autobuild-User(master): Stefan Metzmacher <metze at samba.org>
    Autobuild-Date(master): Mon Mar 25 13:25:30 CET 2013 on sn-devel-104

commit 5d42260eecfd4f26cc82637ce1bc989083c9eb9d
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Fri Mar 22 21:36:49 2013 +1100

    samba-tool ldapcmp: Remove the GUID -> name mappings
    
    These mappings are very convenient, however because they are not
    one-to-one, they lead to differences being reported when none exist,
    dependent only on the order the schema searches return results in.
    
    Sadly the time saved by the names is offset by the time wasted chasing
    the 'differences' that don't exist.
    
    This in turn fixes some tests that were previously knownfail
    
    Andrew Bartlett
    
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit 1589e46d11f29551f3598876b62e29fcbad06580
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Fri Mar 22 17:12:43 2013 +1100

    selftest: Add tests for samba-tool dbcheck --reset-well-known-acls
    
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit 874a93bc1c437543474a6c574b0065b7b953ad38
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Fri Mar 22 22:16:03 2013 +1100

    scripting: Modify samba.descriptor.get_diff_sds() to cope with a missing reference owner
    
    This allows the reference SD not to have an owner specified, and still
    have the comparison with a database SD that does have an owner pass.
    (And the same for owning group).
    
    Andrew Bartlett
    
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit 4789a3072a4241841c096115dbdb0c3259968e68
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Mon Feb 11 14:49:01 2013 +1100

    samba-tool dbcheck: Allow dbcheck to correct an nTSecurityDescriptor without an owner or group
    
    This is done by making a modification to the SD, which triggers it to be
    filled in if we have the correct session_info established on the DB.
    
    However, we normally want dbcheck running as system, so we wrap
    the session_info set around this operation only.
    
    Andrew Bartlett
    
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit 810f8b48d925ea15f3439c4b228741d8fddaccd8
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Mon Feb 11 14:49:01 2013 +1100

    samba-tool dbcheck: Add --reset-well-known-acls
    
    This will allow an upgrade from Samba 4.0.0 without needing to run
    samba_upgradeprovision, which for now is not the preferred upgrade
    tool.
    
    Andrew Bartlett
    
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit 9040e2684161ce75738e9da0fee191aa34858607
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Fri Mar 22 16:19:27 2013 +1100

    scripting: Move get_diff_sds from samba.upgradehelpers to samba.descriptor
    
    This helps avoid a dependency loop when we use get_diff_sds in dbcheck.
    
    Andrew Bartlett
    
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit a113ddbf881c5905bbf7072638c7ba8843eeb85e
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Fri Mar 22 11:15:38 2013 +1100

    scripting: Modify samba.descriptor.get_wellknown_sds() use samdb calls only
    
    We need this routine not to use the names context as this is tied to
    provision, and we end up in a circular dependency if we use that in
    dbcheck.
    
    Andrew Bartlett

commit 352aff8ed7e06c14b7a00a56b31c79ffddf71dd4
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Thu Mar 21 13:34:26 2013 +1100

    scripting: Move samba.provision.descriptor to samba.descriptor
    
    This will allow dbcheck to import it, without a cirucular dependency via
    samba.provision importing dbcheck.
    
    Andrew Bartlett
    
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit e81a97dd6fc2da701f2cbf42513311a7a44adad3
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Thu Mar 21 12:49:46 2013 +1100

    scripting: Make samba.provision.descriptor.get_wellknown_sds() return ldb.Dn objects
    
    As we look to use this function in more places, it does not make sense to constantly create
    Dn objects from the strings.
    
    Andrew Bartlett
    
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit 6df17fe799968ca7e2f92ce9e294e3962ac8cbaf
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Wed Mar 20 14:50:55 2013 +1100

    scripting: Fix documentation comment on upgradehelpers.py:get_clean_sd
    
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit 3da89b01faebba669434b07db344c203a4521ca2
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Wed Mar 20 14:12:26 2013 +1100

    scripting: Move the list of well known SDs to samba.provision.descriptor
    
    This will allow us to call this from dbcheck.
    
    Andrew Bartlett
    
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit afe9343880ee27cf9fe937c6379c469435ef20d6
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Fri Mar 22 13:47:46 2013 +1100

    build: Do not pass CPP="" to pidl, skip the env variable entirely
    
    This will cause pidl to use $CC -E instead.
    
    Andrew Bartlett
    
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit 7dc6dfd90c5182ed85042b22d4864d3e9b007531
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Fri Mar 22 13:06:43 2013 +1100

    build: Remove the forced use of only the first part of the compiler string
    
    This corrects parts of 378295c3fe813c70815a14c7de608e4a859bd6cc and
    301d59caf2ee6f49e108b748b0e38221dec9bb96.  This is seen if CC="ccache
    gcc" and CPP isn't used for some reason.
    
    Andrew Bartlett
    
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 buildtools/wafsamba/samba_pidl.py                 |    6 +-
 python/samba/dbchecker.py                         |  107 ++++++++++-
 python/samba/{provision => }/descriptor.py        |  222 +++++++++++++++++++++
 python/samba/netcmd/dbcheck.py                    |    7 +-
 python/samba/netcmd/ldapcmp.py                    |   47 +----
 python/samba/provision/__init__.py                |   17 +-
 python/samba/provision/sambadns.py                |    2 +-
 python/samba/tests/upgradeprovision.py            |    4 +-
 python/samba/upgradehelpers.py                    |  158 ---------------
 selftest/knownfail                                |    7 +-
 source4/scripting/bin/samba_upgradedns            |   16 +--
 source4/scripting/bin/samba_upgradeprovision      |   80 +-------
 testprogs/blackbox/dbcheck-oldrelease.sh          |   64 ++++++-
 testprogs/blackbox/dbcheck.sh                     |    6 +
 testprogs/blackbox/upgradeprovision-oldrelease.sh |   10 +
 15 files changed, 437 insertions(+), 316 deletions(-)
 rename python/samba/{provision => }/descriptor.py (67%)


Changeset truncated at 500 lines:

diff --git a/buildtools/wafsamba/samba_pidl.py b/buildtools/wafsamba/samba_pidl.py
index 4056359..2393c72 100644
--- a/buildtools/wafsamba/samba_pidl.py
+++ b/buildtools/wafsamba/samba_pidl.py
@@ -59,9 +59,9 @@ def SAMBA_PIDL(bld, pname, source,
     # the cd .. is needed because pidl currently is sensitive to the directory it is run in
     cpp = ""
     cc = ""
-    if bld.CONFIG_SET("CPP"):
+    if bld.CONFIG_SET("CPP") and bld.CONFIG_GET("CPP") != "":
         if isinstance(bld.CONFIG_GET("CPP"), list):
-            cpp = 'CPP="%s"' % bld.CONFIG_GET("CPP")[0]
+            cpp = 'CPP="%s"' % " ".join(bld.CONFIG_GET("CPP"))
         else:
             cpp = 'CPP="%s"' % bld.CONFIG_GET("CPP")
 
@@ -71,7 +71,7 @@ def SAMBA_PIDL(bld, pname, source,
 
     if bld.CONFIG_SET("CC"):
         if isinstance(bld.CONFIG_GET("CC"), list):
-            cc = 'CC="%s"' % bld.CONFIG_GET("CC")[0]
+            cc = 'CC="%s"' % " ".join(bld.CONFIG_GET("CC"))
         else:
             cc = 'CC="%s"' % bld.CONFIG_GET("CC")
 
diff --git a/python/samba/dbchecker.py b/python/samba/dbchecker.py
index fd42a78..d0d0ab3 100644
--- a/python/samba/dbchecker.py
+++ b/python/samba/dbchecker.py
@@ -25,13 +25,16 @@ from samba.ndr import ndr_unpack, ndr_pack
 from samba.dcerpc import drsblobs
 from samba.common import dsdb_Dn
 from samba.dcerpc import security
+from samba.descriptor import get_wellknown_sds, get_diff_sds
+from samba.auth import system_session, admin_session
 
 
 class dbcheck(object):
     """check a SAM database for errors"""
 
     def __init__(self, samdb, samdb_schema=None, verbose=False, fix=False,
-                 yes=False, quiet=False, in_transaction=False):
+                 yes=False, quiet=False, in_transaction=False,
+                 reset_well_known_acls=False):
         self.samdb = samdb
         self.dict_oid_name = None
         self.samdb_schema = (samdb_schema or samdb)
@@ -52,9 +55,12 @@ class dbcheck(object):
         self.fix_all_orphaned_backlinks = False
         self.fix_rmd_flags = False
         self.fix_ntsecuritydescriptor = False
+        self.fix_ntsecuritydescriptor_owner_group = False
         self.seize_fsmo_role = False
         self.move_to_lost_and_found = False
         self.fix_instancetype = False
+        self.reset_well_known_acls = reset_well_known_acls
+        self.reset_all_well_known_acls = False
         self.in_transaction = in_transaction
         self.infrastructure_dn = ldb.Dn(samdb, "CN=Infrastructure," + samdb.domain_dn())
         self.naming_dn = ldb.Dn(samdb, "CN=Partitions,%s" % samdb.get_config_basedn())
@@ -62,6 +68,21 @@ class dbcheck(object):
         self.rid_dn = ldb.Dn(samdb, "CN=RID Manager$,CN=System," + samdb.domain_dn())
         self.ntds_dsa = ldb.Dn(samdb, samdb.get_dsServiceName())
         self.class_schemaIDGUID = {}
+        self.wellknown_sds = get_wellknown_sds(self.samdb)
+
+        self.name_map = {}
+        try:
+            res = samdb.search(base="CN=DnsAdmins,CN=Users,%s" % samdb.domain_dn(), scope=ldb.SCOPE_BASE,
+                           attrs=["objectSid"])
+            dnsadmins_sid = ndr_unpack(security.dom_sid, res[0]["objectSid"][0])
+            self.name_map['DnsAdmins'] = str(dnsadmins_sid)
+        except ldb.LdbError, (enum, estr):
+            if enum != ldb.ERR_NO_SUCH_OBJECT:
+                raise
+            pass
+
+        self.system_session_info = system_session()
+        self.admin_session_info = admin_session(None, samdb.get_domain_sid())
 
         res = self.samdb.search(base=self.ntds_dsa, scope=ldb.SCOPE_BASE, attrs=['msDS-hasMasterNCs', 'hasMasterNCs'])
         if "msDS-hasMasterNCs" in res[0]:
@@ -739,8 +760,61 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base)))
         nmsg.dn = dn
         nmsg[sd_attr] = ldb.MessageElement(sd_val, ldb.FLAG_MOD_REPLACE, sd_attr)
         if self.do_modify(nmsg, ["sd_flags:1:%d" % sd_flags],
+                          "Failed to fix attribute %s" % sd_attr):
+            self.report("Fixed attribute '%s' of '%s'\n" % (sd_attr, dn))
+
+    def err_wrong_default_sd(self, dn, sd, sd_old, diff):
+        '''re-write the SD due to not matching the default (optional mode for fixing an incorrect provision)'''
+        sd_attr = "nTSecurityDescriptor"
+        sd_val = ndr_pack(sd)
+        sd_old_val = ndr_pack(sd_old)
+        sd_flags = security.SECINFO_DACL | security.SECINFO_SACL
+        if sd.owner_sid is not None:
+            sd_flags |= security.SECINFO_OWNER
+        if sd.group_sid is not None:
+            sd_flags |= security.SECINFO_GROUP
+
+        if not self.confirm_all('Reset %s on %s back to provision default?\n%s' % (sd_attr, dn, diff), 'reset_all_well_known_acls'):
+            self.report('Not resetting %s on %s\n' % (sd_attr, dn))
+            return
+
+        m = ldb.Message()
+        m.dn = dn
+        m[sd_attr] = ldb.MessageElement(sd_val, ldb.FLAG_MOD_REPLACE, sd_attr)
+        if self.do_modify(m, ["sd_flags:1:%d" % sd_flags],
+                          "Failed to reset attribute %s" % sd_attr):
+            self.report("Fixed attribute '%s' of '%s'\n" % (sd_attr, dn))
+
+    def err_missing_sd_owner(self, dn, sd):
+        '''re-write the SD due to a missing owner or group'''
+        sd_attr = "nTSecurityDescriptor"
+        sd_val = ndr_pack(sd)
+        sd_flags = security.SECINFO_OWNER | security.SECINFO_GROUP
+
+        if not self.confirm_all('Fix missing owner or group in %s on %s?' % (sd_attr, dn), 'fix_ntsecuritydescriptor_owner_group'):
+            self.report('Not fixing missing owner or group %s on %s\n' % (sd_attr, dn))
+            return
+
+        nmsg = ldb.Message()
+        nmsg.dn = dn
+        nmsg[sd_attr] = ldb.MessageElement(sd_val, ldb.FLAG_MOD_REPLACE, sd_attr)
+
+        # By setting the session_info to admin_session_info and
+        # setting the security.SECINFO_OWNER | security.SECINFO_GROUP
+        # flags we cause the descriptor module to set the correct
+        # owner and group on the SD, replacing the None/NULL values
+        # for owner_sid and group_sid currently present.
+        #
+        # The admin_session_info matches that used in provision, and
+        # is the best guess we can make for an existing object that
+        # hasn't had something specifically set.
+        #
+        # This is important for the dns related naming contexts.
+        self.samdb.set_session_info(self.admin_session_info)
+        if self.do_modify(nmsg, ["sd_flags:1:%d" % sd_flags],
                           "Failed to fix metadata for attribute %s" % sd_attr):
             self.report("Fixed attribute '%s' of '%s'\n" % (sd_attr, dn))
+        self.samdb.set_session_info(self.system_session_info)
 
     def is_fsmo_role(self, dn):
         if dn == self.samdb.domain_dn:
@@ -774,6 +848,16 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base)))
 
         return instancetype
 
+    def get_wellknown_sd(self, dn):
+        for [sd_dn, descriptor_fn] in self.wellknown_sds:
+            if dn == sd_dn:
+                domain_sid = security.dom_sid(self.samdb.get_domain_sid())
+                return ndr_unpack(security.descriptor,
+                                  descriptor_fn(domain_sid,
+                                                name_map=self.name_map))
+
+        raise KeyError
+
     def check_object(self, dn, attrs=['*']):
         '''check one object'''
         if self.verbose:
@@ -826,6 +910,27 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base)))
                 if sd_broken is not None:
                     self.err_wrong_sd(dn, sd, sd_broken)
                     error_count += 1
+                    continue
+
+                if sd.owner_sid is None or sd.group_sid is None:
+                    self.err_missing_sd_owner(dn, sd)
+                    error_count += 1
+                    continue
+
+                if self.reset_well_known_acls:
+                    try:
+                        well_known_sd = self.get_wellknown_sd(dn)
+                    except KeyError:
+                        continue
+
+                    current_sd = ndr_unpack(security.descriptor,
+                                            str(obj[attrname][0]))
+
+                    diff = get_diff_sds(well_known_sd, current_sd, security.dom_sid(self.samdb.get_domain_sid()))
+                    if diff != "":
+                        self.err_wrong_default_sd(dn, well_known_sd, current_sd, diff)
+                        error_count += 1
+                        continue
                 continue
 
             if str(attrname).lower() == 'objectclass':
diff --git a/python/samba/provision/descriptor.py b/python/samba/descriptor.py
similarity index 67%
rename from python/samba/provision/descriptor.py
rename to python/samba/descriptor.py
index 32e91ed..164b0bf 100644
--- a/python/samba/provision/descriptor.py
+++ b/python/samba/descriptor.py
@@ -28,6 +28,9 @@
 
 from samba.dcerpc import security
 from samba.ndr import ndr_pack
+from samba.schema import get_schema_descriptor
+import ldb
+import re
 
 # Descriptors of naming contexts and other important objects
 
@@ -357,3 +360,222 @@ def get_dns_domain_microsoft_dns_descriptor(domain_sid, name_map={}):
     "(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)" \
     "(A;CI;RPWPCRCCDCLCRCWOWDSDDTSW;;;ED)"
     return sddl2binary(sddl, domain_sid, name_map)
+
+def get_wellknown_sds(samdb):
+
+    # Then subcontainers
+    subcontainers = [
+        (ldb.Dn(samdb, "%s" % str(samdb.domain_dn())), get_domain_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),
+        (ldb.Dn(samdb, "CN=Builtin,%s" % str(samdb.domain_dn())), get_domain_builtin_descriptor),
+        (ldb.Dn(samdb, "CN=Computers,%s" % str(samdb.domain_dn())), get_domain_computers_descriptor),
+        (ldb.Dn(samdb, "CN=Users,%s" % str(samdb.domain_dn())), get_domain_users_descriptor),
+        (ldb.Dn(samdb, "OU=Domain Controllers,%s" % str(samdb.domain_dn())), get_domain_controllers_descriptor),
+        (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=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),
+        (ldb.Dn(samdb, "CN=Physical Locations,%s" % str(samdb.get_config_basedn())), get_config_delete_protected1wd_descriptor),
+        (ldb.Dn(samdb, "CN=WellKnown Security Principals,%s" % str(samdb.get_config_basedn())), get_config_delete_protected1wd_descriptor),
+        (ldb.Dn(samdb, "CN=ForestUpdates,%s" % str(samdb.get_config_basedn())), get_config_delete_protected1wd_descriptor),
+        (ldb.Dn(samdb, "CN=DisplaySpecifiers,%s" % str(samdb.get_config_basedn())), get_config_delete_protected2_descriptor),
+        (ldb.Dn(samdb, "CN=Extended-Rights,%s" % str(samdb.get_config_basedn())), get_config_delete_protected2_descriptor),
+        (ldb.Dn(samdb, "CN=Partitions,%s" % str(samdb.get_config_basedn())), get_config_partitions_descriptor),
+        (ldb.Dn(samdb, "CN=Sites,%s" % str(samdb.get_config_basedn())), get_config_sites_descriptor),
+
+        (ldb.Dn(samdb, "%s" % str(samdb.get_schema_basedn())), get_schema_descriptor),
+    ]
+
+    current = samdb.search(expression="(objectClass=*)",
+                           base="", scope=ldb.SCOPE_BASE,
+                           attrs=["namingContexts"])
+
+    for nc in current[0]["namingContexts"]:
+
+        dnsforestdn = ldb.Dn(samdb, "DC=ForestDnsZones,%s" % (str(samdb.get_root_basedn())))
+        if ldb.Dn(samdb, nc) == dnsforestdn:
+            c = (ldb.Dn(samdb, "%s" % str(dnsforestdn)), get_dns_partition_descriptor)
+            subcontainers.append(c)
+            c = (ldb.Dn(samdb, "CN=Infrastructure,%s" % str(dnsforestdn)),
+                 get_domain_delete_protected1_descriptor)
+            subcontainers.append(c)
+            c = (ldb.Dn(samdb, "CN=LostAndFound,%s" % str(dnsforestdn)),
+                 get_domain_delete_protected2_descriptor)
+            subcontainers.append(c)
+            c = (ldb.Dn(samdb, "CN=MicrosoftDNS,%s" % str(dnsforestdn)),
+                 get_dns_forest_microsoft_dns_descriptor)
+            subcontainers.append(c)
+            continue
+
+        dnsdomaindn = ldb.Dn(samdb, "DC=DomainDnsZones,%s" % (str(samdb.domain_dn())))
+        if ldb.Dn(samdb, nc) == dnsdomaindn:
+            c = (ldb.Dn(samdb, "%s" % str(dnsdomaindn)), get_dns_partition_descriptor)
+            subcontainers.append(c)
+            c = (ldb.Dn(samdb, "CN=Infrastructure,%s" % str(dnsdomaindn)),
+                 get_domain_delete_protected1_descriptor)
+            subcontainers.append(c)
+            c = (ldb.Dn(samdb, "CN=LostAndFound,%s" % str(dnsdomaindn)),
+                 get_domain_delete_protected2_descriptor)
+            subcontainers.append(c)
+            c = (ldb.Dn(samdb, "CN=MicrosoftDNS,%s" % str(dnsdomaindn)),
+                 get_dns_domain_microsoft_dns_descriptor)
+            subcontainers.append(c)
+
+    return subcontainers
+
+
+def chunck_acl(acl):
+    """Return separate ACE of an ACL
+
+    :param acl: A string representing the ACL
+    :return: A hash with different parts
+    """
+
+    p = re.compile(r'(\w+)?(\(.*?\))')
+    tab = p.findall(acl)
+
+    hash = {}
+    hash["aces"] = []
+    for e in tab:
+        if len(e[0]) > 0:
+            hash["flags"] = e[0]
+        hash["aces"].append(e[1])
+
+    return hash
+
+
+def chunck_sddl(sddl):
+    """ Return separate parts of the SDDL (owner, group, ...)
+
+    :param sddl: An string containing the SDDL to chunk
+    :return: A hash with the different chunk
+    """
+
+    p = re.compile(r'([OGDS]:)(.*?)(?=(?:[GDS]:|$))')
+    tab = p.findall(sddl)
+
+    hash = {}
+    for e in tab:
+        if e[0] == "O:":
+            hash["owner"] = e[1]
+        if e[0] == "G:":
+            hash["group"] = e[1]
+        if e[0] == "D:":
+            hash["dacl"] = e[1]
+        if e[0] == "S:":
+            hash["sacl"] = e[1]
+
+    return hash
+
+
+def get_clean_sd(sd):
+    """Get the SD without any inherited ACEs
+
+    :param sd: SD to strip
+    :return: An SD with inherited ACEs stripped
+    """
+
+    sd_clean = security.descriptor()
+    sd_clean.owner_sid = sd.owner_sid
+    sd_clean.group_sid = sd.group_sid
+    sd_clean.type = sd.type
+    sd_clean.revision = sd.revision
+
+    aces = []
+    if sd.sacl is not None:
+        aces = sd.sacl.aces
+    for i in range(0, len(aces)):
+        ace = aces[i]
+
+        if not ace.flags & security.SEC_ACE_FLAG_INHERITED_ACE:
+            sd_clean.sacl_add(ace)
+            continue
+
+    aces = []
+    if sd.dacl is not None:
+        aces = sd.dacl.aces
+    for i in range(0, len(aces)):
+        ace = aces[i]
+
+        if not ace.flags & security.SEC_ACE_FLAG_INHERITED_ACE:
+            sd_clean.dacl_add(ace)
+            continue
+    return sd_clean
+
+
+def get_diff_sds(refsd, cursd, domainsid, checkSacl = True):
+    """Get the difference between 2 sd
+
+    This function split the textual representation of ACL into smaller
+    chunck in order to not to report a simple permutation as a difference
+
+    :param refsddl: First sddl to compare
+    :param cursddl: Second sddl to compare
+    :param checkSacl: If false we skip the sacl checks
+    :return: A string that explain difference between sddls
+    """
+
+    cursddl = get_clean_sd(cursd).as_sddl(domainsid)
+    refsddl = get_clean_sd(refsd).as_sddl(domainsid)
+
+    txt = ""
+    hash_cur = chunck_sddl(cursddl)
+    hash_ref = chunck_sddl(refsddl)
+
+    if not hash_cur.has_key("owner"):
+        txt = "\tNo owner in current SD"
+    elif hash_ref.has_key("owner") and hash_cur["owner"] != hash_ref["owner"]:
+        txt = "\tOwner mismatch: %s (in ref) %s" \
+              "(in current)\n" % (hash_ref["owner"], hash_cur["owner"])
+
+    if not hash_cur.has_key("group"):
+        txt = "%s\tNo group in current SD" % txt
+    elif hash_ref.has_key("group") and hash_cur["group"] != hash_ref["group"]:
+        txt = "%s\tGroup mismatch: %s (in ref) %s" \
+              "(in current)\n" % (txt, hash_ref["group"], hash_cur["group"])
+
+    parts = [ "dacl" ]
+    if checkSacl:
+        parts.append("sacl")
+    for part in parts:
+        if hash_cur.has_key(part) and hash_ref.has_key(part):
+
+            # both are present, check if they contain the same ACE
+            h_cur = set()
+            h_ref = set()
+            c_cur = chunck_acl(hash_cur[part])
+            c_ref = chunck_acl(hash_ref[part])
+
+            for elem in c_cur["aces"]:
+                h_cur.add(elem)
+
+            for elem in c_ref["aces"]:
+                h_ref.add(elem)
+
+            for k in set(h_ref):
+                if k in h_cur:
+                    h_cur.remove(k)
+                    h_ref.remove(k)
+
+            if len(h_cur) + len(h_ref) > 0:
+                txt = "%s\tPart %s is different between reference" \
+                      " and current here is the detail:\n" % (txt, part)
+
+                for item in h_cur:
+                    txt = "%s\t\t%s ACE is not present in the" \
+                          " reference\n" % (txt, item)
+
+                for item in h_ref:
+                    txt = "%s\t\t%s ACE is not present in the" \
+                          " current\n" % (txt, item)
+
+        elif hash_cur.has_key(part) and not hash_ref.has_key(part):
+            txt = "%s\tReference ACL hasn't a %s part\n" % (txt, part)
+        elif not hash_cur.has_key(part) and hash_ref.has_key(part):
+            txt = "%s\tCurrent ACL hasn't a %s part\n" % (txt, part)
+
+    return txt
diff --git a/python/samba/netcmd/dbcheck.py b/python/samba/netcmd/dbcheck.py
index 889b0ff..4cc0631 100644
--- a/python/samba/netcmd/dbcheck.py
+++ b/python/samba/netcmd/dbcheck.py
@@ -56,6 +56,7 @@ class cmd_dbcheck(Command):
         Option("--attrs", dest="attrs", default=None, help="list of attributes to check (space separated)"),
         Option("--reindex", dest="reindex", default=False, action="store_true", help="force database re-index"),
         Option("--force-modules", dest="force_modules", default=False, action="store_true", help="force loading of Samba modules and ignore the @MODULES record (for very old databases)"),
+        Option("--reset-well-known-acls", dest="reset_well_known_acls", default=False, action="store_true", help="reset ACLs on objects with well known default ACL values to the default"),
         Option("-H", "--URL", help="LDB URL for database or target server (defaults to local SAM database)",
                type=str, metavar="URL", dest="H"),
         ]
@@ -63,7 +64,8 @@ class cmd_dbcheck(Command):
     def run(self, DN=None, H=None, verbose=False, fix=False, yes=False,
             cross_ncs=False, quiet=False,
             scope="SUB", credopts=None, sambaopts=None, versionopts=None,
-            attrs=None, reindex=False, force_modules=False):
+            attrs=None, reindex=False, force_modules=False,
+            reset_well_known_acls=False):
 
         lp = sambaopts.get_loadparm()
 
@@ -114,7 +116,8 @@ class cmd_dbcheck(Command):
             started_transaction = True
         try:
             chk = dbcheck(samdb, samdb_schema=samdb_schema, verbose=verbose,
-                          fix=fix, yes=yes, quiet=quiet, in_transaction=started_transaction)
+                          fix=fix, yes=yes, quiet=quiet, in_transaction=started_transaction,
+                          reset_well_known_acls=reset_well_known_acls)
 
             if reindex:
                 self.outf.write("Re-indexing...\n")
diff --git a/python/samba/netcmd/ldapcmp.py b/python/samba/netcmd/ldapcmp.py
index 6e025a2..7bd118e 100644
--- a/python/samba/netcmd/ldapcmp.py
+++ b/python/samba/netcmd/ldapcmp.py
@@ -80,7 +80,6 @@ class LDAPBase(object):
         self.server_names = self.find_servers()
         self.domain_name = re.sub("[Dd][Cc]=", "", self.base_dn).replace(",", ".")
         self.domain_sid = self.find_domain_sid()
-        self.get_guid_map()
         self.get_sid_map()
         #
         # Log some domain controller specific place-holers that are being used
@@ -250,20 +249,6 @@ class LDAPBase(object):
         assert index == len(blob)
         return res.strip().replace(" ", "-")
 
-    def get_guid_map(self):
-        """ Build dictionary that maps GUID to 'name' attribute found in Schema or Extended-Rights.
-        """
-        self.guid_map = {}
-        res = self.ldb.search(base=self.schema_dn,
-                              expression="(schemaIdGuid=*)", scope=SCOPE_SUBTREE, attrs=["schemaIdGuid", "name"])
-        for item in res:
-            self.guid_map[self.guid_as_string(item["schemaIdGuid"]).lower()] = item["name"][0]
-        #
-        res = self.ldb.search(base="cn=extended-rights,%s" % self.config_dn,
-                              expression="(rightsGuid=*)", scope=SCOPE_SUBTREE, attrs=["rightsGuid", "name"])
-        for item in res:
-            self.guid_map[str(item["rightsGuid"]).lower()] = item["name"][0]
-
     def get_sid_map(self):
         """ Build dictionary that maps GUID to 'name' attribute found in Schema or Extended-Rights.
         """
@@ -299,22 +284,6 @@ class Descriptor(object):
             return []
         return re.findall("(\(.*?\))", res)
 
-    def fix_guid(self, ace):
-        res = "%s" % ace


-- 
Samba Shared Repository


More information about the samba-cvs mailing list