|
Lines 1672-1678
Link Here
|
| 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) |