--- a/python/samba/provision/__init__.py.orig 2019-01-23 20:05:28.800000000 +0100 +++ b/python/samba/provision/__init__.py 2019-01-23 20:30:12.172000000 +0100 @@ -1686,21 +1686,45 @@ return else: raise - """changed acl in if-statements to acl_sddl""" + + ## Sanitize "domainsid" to be a string and "sid" to be the security.dom_sid if isinstance(domainsid, str): sid = security.dom_sid(domainsid) elif isinstance(domainsid, security.dom_sid): sid = domainsid domainsid = str(sid) + ## Mask AI and P in DACL flags for comparison + fsacl_type_tmp = fsacl.type + fsacl_owner_sid_tmp = fsacl.owner_sid + fsacl.type &= ~ (security.SEC_DESC_DACL_AUTO_INHERITED | security.SEC_DESC_DACL_PROTECTED) + ## If DA in filesystem then treat it as LA for comparison (workaround for sysvolcheck, GPMC against Samba 4.7 seems to write this?) + if fsacl.owner_sid == security.dom_sid("%s-%d" % (domainsid, security.DOMAIN_RID_ADMINS)): + fsacl.owner_sid = security.dom_sid("%s-%d" % (domainsid, security.DOMAIN_RID_ADMINISTRATOR)) + fsacl_sddl_filtered = fsacl.as_sddl(sid) + fsacl.type = fsacl_type_tmp + fsacl.owner_sid = fsacl_owner_sid_tmp + sd = security.descriptor.from_sddl(acl, sid) + acl_sddl = sd.as_sddl(sid) + ## Mask AI and P in DACL flags for comparison + sd.type &= ~ (security.SEC_DESC_DACL_AUTO_INHERITED | security.SEC_DESC_DACL_PROTECTED) + ## If DA in DSACL then treat it as LA for comparison (this seems to be what sysvolreset does) if sd.owner_sid == security.dom_sid("%s-%d" % (domainsid, security.DOMAIN_RID_ADMINS)): sd.owner_sid = security.dom_sid("%s-%d" % (domainsid, security.DOMAIN_RID_ADMINISTRATOR)) - acl_sddl = sd.as_sddl(sid) + acl_sddl_filtered = sd.as_sddl(sid) - if fsacl_sddl != acl_sddl: + if fsacl_sddl_filtered != acl_sddl_filtered: raise ProvisioningError('%s NTACL of GPO directory %s %s does not match value %s expected from GPO object' % (acl_type(direct_db_access), path, fsacl_sddl, acl_sddl)) + ## similar to dsacl2fsacl: Mask the OI CI and ID in ACE flags for comparison + aces = sd.dacl.aces + for i in range(0, len(aces)): + ace = aces[i] + if not ace.type & security.SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT and str(ace.trustee) != security.SID_BUILTIN_PREW2K: + ace.flags &= ~ (security.SEC_ACE_FLAG_OBJECT_INHERIT | security.SEC_ACE_FLAG_CONTAINER_INHERIT | security.SEC_ACE_FLAG_INHERITED_ACE) + acl_sddl_filtered = sd.as_sddl(sid) + for root, dirs, files in os.walk(path, topdown=False): for name in files: fsacl = getntacl(lp, os.path.join(root, name), @@ -1708,8 +1732,16 @@ if fsacl is None: raise ProvisioningError('%s ACL on GPO file %s %s not found!' % (acl_type(direct_db_access), os.path.join(root, name))) fsacl_sddl = fsacl.as_sddl(sid) - - if fsacl_sddl != acl_sddl: + ## Mask AI and P in DACL flags for comparison + fsacl.type &= ~ (security.SEC_DESC_DACL_AUTO_INHERITED | security.SEC_DESC_DACL_PROTECTED) + ## similar to dsacl2fsacl: Mask the OI CI and ID in ACE flags for comparison + aces = fsacl.dacl.aces + for i in range(0, len(aces)): + ace = aces[i] + if not ace.type & security.SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT and str(ace.trustee) != security.SID_BUILTIN_PREW2K: + ace.flags &= ~ (security.SEC_ACE_FLAG_OBJECT_INHERIT | security.SEC_ACE_FLAG_CONTAINER_INHERIT | security.SEC_ACE_FLAG_INHERITED_ACE) + fsacl_sddl_filtered = fsacl.as_sddl(sid) + if fsacl_sddl_filtered != acl_sddl_filtered: raise ProvisioningError('%s NTACL of GPO file %s %s does not match value %s expected from GPO object' % (acl_type(direct_db_access), os.path.join(root, name), fsacl_sddl, acl_sddl)) for name in dirs: @@ -1718,8 +1750,17 @@ if fsacl is None: raise ProvisioningError('%s ACL on GPO directory %s %s not found!' % (acl_type(direct_db_access), os.path.join(root, name))) fsacl_sddl = fsacl.as_sddl(sid) + ## Mask AI and P in DACL flags for comparison + fsacl.type &= ~ (security.SEC_DESC_DACL_AUTO_INHERITED | security.SEC_DESC_DACL_PROTECTED) + ## similar to dsacl2fsacl: Mask the OI CI and ID in ACE flags for comparison + aces = fsacl.dacl.aces + for i in range(0, len(aces)): + ace = aces[i] + if not ace.type & security.SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT and str(ace.trustee) != security.SID_BUILTIN_PREW2K: + ace.flags &= ~ (security.SEC_ACE_FLAG_OBJECT_INHERIT | security.SEC_ACE_FLAG_CONTAINER_INHERIT | security.SEC_ACE_FLAG_INHERITED_ACE) + fsacl_sddl_filtered = fsacl.as_sddl(sid) - if fsacl_sddl != acl_sddl: + if fsacl_sddl_filtered != acl_sddl_filtered: raise ProvisioningError('%s NTACL of GPO directory %s %s does not match value %s expected from GPO object' % (acl_type(direct_db_access), os.path.join(root, name), fsacl_sddl, acl_sddl)) def check_gpos_acl(sysvol, dnsdomain, domainsid, domaindn, samdb, lp,