|
1672 |
return True |
1672 |
return True |
1673 |
return False |
1673 |
return False |
1674 |
|
1674 |
|
1675 |
def check_dir_acl(path, acl, lp, domainsid, direct_db_access): |
1675 |
def check_dir_acl(path, acl_expected_for_gpo, lp, domainsid, direct_db_access): |
|
|
1676 |
try: |
1677 |
fsacl = getntacl(lp, path, direct_db_access=direct_db_access, service=SYSVOL_SERVICE) |
1678 |
fsacl_sddl = fsacl.as_sddl(domainsid) |
1679 |
except TypeError as error: |
1680 |
return |
1681 |
except NTSTATUSError as error: |
1682 |
if check_runtime_error(error, ntstatus.NT_STATUS_OBJECT_NAME_NOT_FOUND): |
1683 |
print "ERROR: File not found", path |
1684 |
return |
1685 |
else: |
1686 |
raise |
1687 |
|
1688 |
## Sanitize "domainsid" to be a security.dom_sid |
1689 |
if isinstance(domainsid, str): |
1690 |
domainsid = security.dom_sid(domainsid) |
1691 |
|
1692 |
LA = security.dom_sid("%s-%d" % (domainsid, security.DOMAIN_RID_ADMINISTRATOR)) |
1693 |
DA = security.dom_sid("%s-%d" % (domainsid, security.DOMAIN_RID_ADMINS)) |
1694 |
CO = security.dom_sid(security.SID_CREATOR_OWNER) |
1695 |
|
1696 |
## If LA in filesystem then treat it as DA for comparison (reversing what samba.ntacls.setntacl did) |
1697 |
if fsacl.owner_sid == LA: |
1698 |
fsacl.owner_sid = DA |
1699 |
|
1700 |
""" |
1701 |
MS doc about SE_DACL_AUTO_INHERITED of SECURITY_DESCRIPTOR_CONTROL: |
1702 |
For Windows 2000 ACLs that support auto-inheritance, this bit is always set. |
1703 |
""" |
1704 |
## The default {31B2F340-016D-11D2-945F-00C04FB984F9} and {6AC1786C-016F-11D2-945F-00C04FB984F9} don't have this in Samba |
1705 |
## so mask this difference here to avoid false positives |
1706 |
## |
1707 |
## sysvolreset removes the AI as well, so we always mask this: |
1708 |
fsacl.type |= security.SEC_DESC_DACL_AUTO_INHERITED |
1709 |
fix_P_to_AI = True ## also below in the subdir and file checks |
1710 |
|
1711 |
fsacl_sddl_mapped = fsacl.as_sddl(domainsid) |
1712 |
|
1713 |
## at least in UCS, all base GPO directories have AI set, so expect that |
1714 |
sd = security.descriptor.from_sddl(acl_expected_for_gpo, domainsid) |
1715 |
sd.type |= security.SEC_DESC_DACL_AUTO_INHERITED |
1716 |
acl_expected_for_gpo = sd.as_sddl(domainsid) |
1717 |
|
1718 |
if fsacl_sddl_mapped != acl_expected_for_gpo: |
1719 |
raise ProvisioningError('%s NTACL of GPO directory %s does not match value expected from GPO object\nFSACL: %s\nDSACL: %s' % (acl_type(direct_db_access), path, fsacl_sddl_mapped, acl_expected_for_gpo)) |
1720 |
|
1721 |
### After the base GPO directory has passed, now fix the FSACLs calculated by dsacl2fsacl to work for the subdirs and files |
1722 |
## copy the security descriptor structure, we have to filter out a few ACEs |
1723 |
sd_masked = security.descriptor() |
1724 |
sd_masked.owner_sid = sd.owner_sid |
1725 |
sd_masked.group_sid = sd.group_sid |
1726 |
sd_masked.type = sd.type |
1727 |
sd_masked.revision = sd.revision |
1728 |
|
1729 |
## the subdirs and files are AI and not P |
1730 |
sd_masked.type |= security.SEC_DESC_DACL_AUTO_INHERITED |
1731 |
sd_masked.type &= ~security.SEC_DESC_DACL_PROTECTED |
1732 |
|
1733 |
skip_other_da_aces = False |
1734 |
for i in range(0, len(sd.dacl.aces)): |
1735 |
if skip_other_da_aces and sd.dacl.aces[i].trustee in (DA, LA): |
1736 |
## filter out additional ACEs for DA and LA, there is some duplication and ordering issue |
1737 |
continue |
1738 |
elif sd.dacl.aces[i].trustee in (DA, LA): |
1739 |
## flag first occurrence of DA |
1740 |
skip_other_da_aces = True |
1741 |
if sd.dacl.aces[i].flags & security.SEC_ACE_FLAG_CONTAINER_INHERIT: |
1742 |
## If GPO says CI then the subobjects must show the inherited flag |
1743 |
## Note: dsacl2fsacl currently always fakes security.SEC_ACE_FLAG_CONTAINER_INHERIT |
1744 |
sd.dacl.aces[i].flags |= security.SEC_ACE_FLAG_INHERITED_ACE |
1745 |
|
1746 |
sd_masked.dacl_add(sd.dacl.aces[i]) |
1747 |
acl_expected_for_subdir = sd_masked.as_sddl(domainsid) |
1748 |
|
1749 |
## Additionally for files MS AD and GPMC don't set the CI and OI flags |
1750 |
for i in range(0, len(sd_masked.dacl.aces)): |
1751 |
sd_masked.dacl.aces[i].flags &= ~ (security.SEC_ACE_FLAG_OBJECT_INHERIT | security.SEC_ACE_FLAG_CONTAINER_INHERIT) |
1752 |
try: |
1753 |
## also filter out ACE for CO, not present for GPT.INI of new GPOs created via GPMC |
1754 |
sd_masked.dacl_del(CO) |
1755 |
except: |
1756 |
pass |
1757 |
acl_expected_for_file = sd_masked.as_sddl(domainsid) |
1758 |
sd_masked.type &= ~security.SEC_DESC_DACL_AUTO_INHERIT_REQ |
1759 |
acl_expected_for_registry_pol = sd_masked.as_sddl(domainsid) |
1760 |
|
1761 |
#print "ACL GPO: %s" % acl_expected_for_gpo |
1762 |
#print "ACL DIR: %s" % acl_expected_for_subdir |
1763 |
#print "ACL FILE: %s" % acl_expected_for_file |
1764 |
|
1765 |
for root, dirs, files in os.walk(path, topdown=False): |
1766 |
for name in files: |
1767 |
fsacl = getntacl(lp, os.path.join(root, name), |
1768 |
direct_db_access=direct_db_access, service=SYSVOL_SERVICE) |
1769 |
if fsacl is None: |
1770 |
raise ProvisioningError('%s ACL on GPO file %s %s not found!' % (acl_type(direct_db_access), os.path.join(root, name))) |
1771 |
|
1772 |
## If LA in filesystem then treat it as DA for comparison (reversing what samba.ntacls.setntacl did) |
1773 |
if fsacl.owner_sid == LA: |
1774 |
fsacl.owner_sid = DA |
1775 |
|
1776 |
## Mask current differences between Samba and MS AD & GPMC |
1777 |
fsacl_masked = security.descriptor() |
1778 |
fsacl_masked.owner_sid = fsacl.owner_sid |
1779 |
fsacl_masked.group_sid = fsacl.group_sid |
1780 |
fsacl_masked.type = fsacl.type |
1781 |
fsacl_masked.revision = fsacl.revision |
1782 |
|
1783 |
if fix_P_to_AI: |
1784 |
fsacl_masked.type &= ~security.SEC_DESC_DACL_PROTECTED |
1785 |
fsacl_masked.type |= security.SEC_DESC_DACL_AUTO_INHERITED |
1786 |
|
1787 |
skip_other_da_aces = False |
1788 |
for i in range(0, len(fsacl.dacl.aces)): |
1789 |
if skip_other_da_aces and fsacl.dacl.aces[i].trustee in (DA, LA): |
1790 |
## filter out additional ACEs for DA and LA, there is some duplication and ordering issue |
1791 |
continue |
1792 |
elif fsacl.dacl.aces[i].trustee in (DA, LA): |
1793 |
## flag first occurrence of DA |
1794 |
skip_other_da_aces = True |
1795 |
if str(fsacl.dacl.aces[i].trustee) == security.SID_CREATOR_OWNER: |
1796 |
## filter out ACE for CO, not present for GPT.INI of new GPOs created via GPMC |
1797 |
continue |
1798 |
if fix_P_to_AI: |
1799 |
fsacl.dacl.aces[i].flags |= security.SEC_ACE_FLAG_INHERITED_ACE |
1800 |
## The OI and CI flags don't make sense for files and are neither set by MS AD nor MS GPMC |
1801 |
fsacl.dacl.aces[i].flags &= ~ (security.SEC_ACE_FLAG_OBJECT_INHERIT | security.SEC_ACE_FLAG_CONTAINER_INHERIT) |
1802 |
fsacl_masked.dacl_add(fsacl.dacl.aces[i]) |
1803 |
|
1804 |
fsacl_sddl_mapped = fsacl_masked.as_sddl(domainsid) |
1805 |
|
1806 |
if name in ("GPT.INI", "GptTmpl.inf", "comment.cmtx"): |
1807 |
if fsacl_sddl_mapped != acl_expected_for_file: |
1808 |
raise ProvisioningError('%s NTACL of GPO file %s does not match value expected from GPO object\nFSACL: %s\nDSACL: %s' % (acl_type(direct_db_access), os.path.join(root, name), fsacl_sddl_mapped, acl_expected_for_file)) |
1809 |
else: |
1810 |
if fsacl_sddl_mapped != acl_expected_for_registry_pol: |
1811 |
raise ProvisioningError('%s NTACL of GPO file %s does not match value expected from GPO object\nFSACL: %s\nDSACL: %s' % (acl_type(direct_db_access), os.path.join(root, name), fsacl_sddl_mapped, acl_expected_for_registry_pol)) |
1812 |
|
1813 |
for name in dirs: |
1814 |
fsacl = getntacl(lp, os.path.join(root, name), |
1815 |
direct_db_access=direct_db_access, service=SYSVOL_SERVICE) |
1816 |
if fsacl is None: |
1817 |
raise ProvisioningError('%s ACL on GPO directory %s %s not found!' % (acl_type(direct_db_access), os.path.join(root, name))) |
1818 |
|
1819 |
## If LA in filesystem then treat it as DA for comparison (reversing what samba.ntacls.setntacl did) |
1820 |
if fsacl.owner_sid == LA: |
1821 |
fsacl.owner_sid = DA |
1822 |
|
1823 |
## Mask current differences between Samba and MS AD & GPMC |
1824 |
fsacl_masked = security.descriptor() |
1825 |
fsacl_masked.owner_sid = fsacl.owner_sid |
1826 |
fsacl_masked.group_sid = fsacl.group_sid |
1827 |
fsacl_masked.type = fsacl.type |
1828 |
fsacl_masked.revision = fsacl.revision |
1829 |
|
1830 |
if fix_P_to_AI: |
1831 |
fsacl_masked.type &= ~security.SEC_DESC_DACL_PROTECTED |
1832 |
fsacl_masked.type |= security.SEC_DESC_DACL_AUTO_INHERITED |
1833 |
|
1834 |
skip_other_da_aces = False |
1835 |
for i in range(0, len(fsacl.dacl.aces)): |
1836 |
if skip_other_da_aces and fsacl.dacl.aces[i].trustee in (DA, LA): |
1837 |
## filter out additional ACEs for DA and LA, there is some duplication and ordering issue |
1838 |
continue |
1839 |
elif fsacl.dacl.aces[i].trustee == DA: |
1840 |
## flag first occurrence of DA |
1841 |
skip_other_da_aces = True |
1842 |
if fix_P_to_AI: |
1843 |
fsacl.dacl.aces[i].flags |= security.SEC_ACE_FLAG_INHERITED_ACE |
1844 |
fsacl_masked.dacl_add(fsacl.dacl.aces[i]) |
1845 |
|
1846 |
fsacl_sddl_mapped = fsacl_masked.as_sddl(domainsid) |
1847 |
|
1848 |
if fsacl_sddl_mapped != acl_expected_for_subdir: |
1849 |
raise ProvisioningError('%s NTACL of GPO subdirectory %s does not match value expected from GPO object\nFSACL: %s\nDSACL: %s' % (acl_type(direct_db_access), os.path.join(root, name), fsacl_sddl_mapped, acl_expected_for_subdir)) |
1850 |
|
1851 |
|
1852 |
def check_dir_acl_orig(path, acl, lp, domainsid, direct_db_access): |
1676 |
try: |
1853 |
try: |
1677 |
fsacl = getntacl(lp, path, direct_db_access=direct_db_access, service=SYSVOL_SERVICE) |
1854 |
fsacl = getntacl(lp, path, direct_db_access=direct_db_access, service=SYSVOL_SERVICE) |
1678 |
fsacl_sddl = fsacl.as_sddl(domainsid) |
1855 |
fsacl_sddl = fsacl.as_sddl(domainsid) |