|
0 |
-- a/python/samba/netcmd/ntacl.py |
0 |
++ b/python/samba/netcmd/ntacl.py |
Lines 293-299
class cmd_ntacl_sysvolcheck(Command):
|
Link Here
|
---|
|
293 |
"versionopts": options.VersionOptions, |
293 |
"versionopts": options.VersionOptions, |
294 |
} |
294 |
} |
295 |
|
295 |
|
296 |
def run(self, credopts=None, sambaopts=None, versionopts=None): |
296 |
takes_options = [ |
|
|
297 |
Option("--mask-msad-differences", help="Ignore standard differences to MS AD ACLs", action="store_true"), |
298 |
] |
299 |
def run(self, mask_msad_differences=False, credopts=None, sambaopts=None, versionopts=None): |
297 |
lp = sambaopts.get_loadparm() |
300 |
lp = sambaopts.get_loadparm() |
298 |
creds = credopts.get_credentials(lp) |
301 |
creds = credopts.get_credentials(lp) |
299 |
creds.set_kerberos_state(DONT_USE_KERBEROS) |
302 |
creds.set_kerberos_state(DONT_USE_KERBEROS) |
Lines 311-317
class cmd_ntacl_sysvolcheck(Command):
|
Link Here
|
---|
|
311 |
provision.checksysvolacl(samdb, netlogon, sysvol, |
359 |
provision.checksysvolacl(samdb, netlogon, sysvol, |
312 |
domain_sid, |
360 |
domain_sid, |
313 |
lp.get("realm").lower(), samdb.domain_dn(), |
361 |
lp.get("realm").lower(), samdb.domain_dn(), |
314 |
lp) |
362 |
lp, mask_msad_differences) |
315 |
|
363 |
|
316 |
|
364 |
|
317 |
class cmd_ntacl(SuperCommand): |
365 |
class cmd_ntacl(SuperCommand): |
318 |
-- a/python/samba/provision/__init__.py |
366 |
++ b/python/samba/provision/__init__.py |
Lines 1728-1735
def check_dir_acl(path, acl, lp, domains
|
Link Here
|
---|
|
1728 |
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_mapped, acl)) |
1729 |
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_mapped, acl)) |
1729 |
|
1730 |
|
1730 |
|
1731 |
|
|
|
1732 |
def check_dir_acl_masked(path, acl_expected_for_gpo, lp, domainsid, direct_db_access): |
1733 |
try: |
1734 |
fsacl = getntacl(lp, path, direct_db_access=direct_db_access, service=SYSVOL_SERVICE) |
1735 |
fsacl_sddl = fsacl.as_sddl(domainsid) |
1736 |
except TypeError as error: |
1737 |
return |
1738 |
except NTSTATUSError as error: |
1739 |
if check_runtime_error(error, ntstatus.NT_STATUS_OBJECT_NAME_NOT_FOUND): |
1740 |
print "ERROR: File not found", path |
1741 |
return |
1742 |
else: |
1743 |
raise |
1744 |
|
1745 |
## Sanitize "domainsid" to be a security.dom_sid |
1746 |
if isinstance(domainsid, str): |
1747 |
domainsid = security.dom_sid(domainsid) |
1748 |
|
1749 |
LA = security.dom_sid("%s-%d" % (domainsid, security.DOMAIN_RID_ADMINISTRATOR)) |
1750 |
DA = security.dom_sid("%s-%d" % (domainsid, security.DOMAIN_RID_ADMINS)) |
1751 |
CO = security.dom_sid(security.SID_CREATOR_OWNER) |
1752 |
|
1753 |
## If LA in filesystem then treat it as DA for comparison (reversing what samba.ntacls.setntacl did) |
1754 |
if fsacl.owner_sid == LA: |
1755 |
fsacl.owner_sid = DA |
1756 |
|
1757 |
""" |
1758 |
MS doc about SE_DACL_AUTO_INHERITED of SECURITY_DESCRIPTOR_CONTROL: |
1759 |
For Windows 2000 ACLs that support auto-inheritance, this bit is always set. |
1760 |
""" |
1761 |
## The default {31B2F340-016D-11D2-945F-00C04FB984F9} and {6AC1786C-016F-11D2-945F-00C04FB984F9} don't have this in Samba |
1762 |
## so mask this difference here to avoid false positives |
1763 |
if os.path.split(path)[-1] in ("{31B2F340-016D-11D2-945F-00C04FB984F9}", "{6AC1786C-016F-11D2-945F-00C04FB984F9}"): |
1764 |
fsacl.type |= security.SEC_DESC_DACL_AUTO_INHERITED |
1765 |
fix_P_to_AI = True ## also below in the subdir and file checks |
1766 |
else: |
1767 |
fix_P_to_AI = False |
1768 |
|
1769 |
fsacl_sddl_mapped = fsacl.as_sddl(domainsid) |
1770 |
|
1771 |
## at least in UCS, all base GPO directories have AI set, so expect that |
1772 |
sd = security.descriptor.from_sddl(acl_expected_for_gpo, domainsid) |
1773 |
sd.type |= security.SEC_DESC_DACL_AUTO_INHERITED |
1774 |
acl_expected_for_gpo = sd.as_sddl(domainsid) |
1775 |
|
1776 |
if fsacl_sddl_mapped != acl_expected_for_gpo: |
1777 |
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)) |
1778 |
|
1779 |
### After the base GPO directory has passed, now fix the FSACLs calculated by dsacl2fsacl to work for the subdirs and files |
1780 |
## copy the security descriptor structure, we have to filter out a few ACEs |
1781 |
sd_masked = security.descriptor() |
1782 |
sd_masked.owner_sid = sd.owner_sid |
1783 |
sd_masked.group_sid = sd.group_sid |
1784 |
sd_masked.type = sd.type |
1785 |
sd_masked.revision = sd.revision |
1786 |
|
1787 |
## the subdirs and files are AI and not P |
1788 |
sd_masked.type |= security.SEC_DESC_DACL_AUTO_INHERITED |
1789 |
sd_masked.type &= ~security.SEC_DESC_DACL_PROTECTED |
1790 |
|
1791 |
skip_other_da_aces = False |
1792 |
for i in range(0, len(sd.dacl.aces)): |
1793 |
if skip_other_da_aces and sd.dacl.aces[i].trustee in (DA, LA): |
1794 |
## filter out additional ACEs for DA and LA, there is some duplication and ordering issue |
1795 |
continue |
1796 |
elif sd.dacl.aces[i].trustee == DA: |
1797 |
## flag first occurrence of DA |
1798 |
skip_other_da_aces = True |
1799 |
if sd.dacl.aces[i].flags & security.SEC_ACE_FLAG_CONTAINER_INHERIT: |
1800 |
## If GPO says CI then the subobjects must show the inherited flag |
1801 |
## Note: dsacl2fsacl currently always fakes security.SEC_ACE_FLAG_CONTAINER_INHERIT |
1802 |
sd.dacl.aces[i].flags |= security.SEC_ACE_FLAG_INHERITED_ACE |
1803 |
|
1804 |
sd_masked.dacl_add(sd.dacl.aces[i]) |
1805 |
acl_expected_for_subdir = sd_masked.as_sddl(domainsid) |
1806 |
|
1807 |
## Additionally for files MS AD and GPMC don't set the CI and OI flags |
1808 |
for i in range(0, len(sd_masked.dacl.aces)): |
1809 |
sd_masked.dacl.aces[i].flags &= ~ (security.SEC_ACE_FLAG_OBJECT_INHERIT | security.SEC_ACE_FLAG_CONTAINER_INHERIT) |
1810 |
try: |
1811 |
## also filter out ACE for CO, not present for GPT.INI of new GPOs created via GPMC |
1812 |
sd_masked.dacl_del(CO) |
1813 |
except: |
1814 |
pass |
1815 |
acl_expected_for_file = sd_masked.as_sddl(domainsid) |
1816 |
|
1817 |
#print "ACL GPO: %s" % acl_expected_for_gpo |
1818 |
#print "ACL DIR: %s" % acl_expected_for_subdir |
1819 |
#print "ACL FILE: %s" % acl_expected_for_file |
1820 |
|
1821 |
for root, dirs, files in os.walk(path, topdown=False): |
1822 |
for name in files: |
1823 |
fsacl = getntacl(lp, os.path.join(root, name), |
1824 |
direct_db_access=direct_db_access, service=SYSVOL_SERVICE) |
1825 |
if fsacl is None: |
1826 |
raise ProvisioningError('%s ACL on GPO file %s %s not found!' % (acl_type(direct_db_access), os.path.join(root, name))) |
1827 |
|
1828 |
## If LA in filesystem then treat it as DA for comparison (reversing what samba.ntacls.setntacl did) |
1829 |
if fsacl.owner_sid == LA: |
1830 |
fsacl.owner_sid = DA |
1831 |
|
1832 |
## Mask current differences between Samba and MS AD & GPMC |
1833 |
fsacl_masked = security.descriptor() |
1834 |
fsacl_masked.owner_sid = fsacl.owner_sid |
1835 |
fsacl_masked.group_sid = fsacl.group_sid |
1836 |
fsacl_masked.type = fsacl.type |
1837 |
fsacl_masked.revision = fsacl.revision |
1838 |
|
1839 |
if fix_P_to_AI: |
1840 |
fsacl_masked.type &= ~security.SEC_DESC_DACL_PROTECTED |
1841 |
fsacl_masked.type |= security.SEC_DESC_DACL_AUTO_INHERITED |
1842 |
|
1843 |
skip_other_da_aces = False |
1844 |
for i in range(0, len(fsacl.dacl.aces)): |
1845 |
if skip_other_da_aces and fsacl.dacl.aces[i].trustee in (DA, LA): |
1846 |
## filter out additional ACEs for DA and LA, there is some duplication and ordering issue |
1847 |
continue |
1848 |
elif fsacl.dacl.aces[i].trustee == DA: |
1849 |
## flag first occurrence of DA |
1850 |
skip_other_da_aces = True |
1851 |
if str(fsacl.dacl.aces[i].trustee) == security.SID_CREATOR_OWNER: |
1852 |
## filter out ACE for CO, not present for GPT.INI of new GPOs created via GPMC |
1853 |
continue |
1854 |
if fix_P_to_AI: |
1855 |
fsacl.dacl.aces[i].flags |= security.SEC_ACE_FLAG_INHERITED_ACE |
1856 |
## The OI and CI flags don't make sense for files and are neither set by MS AD nor MS GPMC |
1857 |
fsacl.dacl.aces[i].flags &= ~ (security.SEC_ACE_FLAG_OBJECT_INHERIT | security.SEC_ACE_FLAG_CONTAINER_INHERIT) |
1858 |
fsacl_masked.dacl_add(fsacl.dacl.aces[i]) |
1859 |
|
1860 |
fsacl_sddl_mapped = fsacl_masked.as_sddl(domainsid) |
1861 |
|
1862 |
if fsacl_sddl_mapped != acl_expected_for_file: |
1863 |
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)) |
1864 |
|
1865 |
for name in dirs: |
1866 |
fsacl = getntacl(lp, os.path.join(root, name), |
1867 |
direct_db_access=direct_db_access, service=SYSVOL_SERVICE) |
1868 |
if fsacl is None: |
1869 |
raise ProvisioningError('%s ACL on GPO directory %s %s not found!' % (acl_type(direct_db_access), os.path.join(root, name))) |
1870 |
|
1871 |
## If LA in filesystem then treat it as DA for comparison (reversing what samba.ntacls.setntacl did) |
1872 |
if fsacl.owner_sid == LA: |
1873 |
fsacl.owner_sid = DA |
1874 |
|
1875 |
## Mask current differences between Samba and MS AD & GPMC |
1876 |
fsacl_masked = security.descriptor() |
1877 |
fsacl_masked.owner_sid = fsacl.owner_sid |
1878 |
fsacl_masked.group_sid = fsacl.group_sid |
1879 |
fsacl_masked.type = fsacl.type |
1880 |
fsacl_masked.revision = fsacl.revision |
1881 |
|
1882 |
if fix_P_to_AI: |
1883 |
fsacl_masked.type &= ~security.SEC_DESC_DACL_PROTECTED |
1884 |
fsacl_masked.type |= security.SEC_DESC_DACL_AUTO_INHERITED |
1885 |
|
1886 |
skip_other_da_aces = False |
1887 |
for i in range(0, len(fsacl.dacl.aces)): |
1888 |
if skip_other_da_aces and fsacl.dacl.aces[i].trustee in (DA, LA): |
1889 |
## filter out additional ACEs for DA and LA, there is some duplication and ordering issue |
1890 |
continue |
1891 |
elif fsacl.dacl.aces[i].trustee == DA: |
1892 |
## flag first occurrence of DA |
1893 |
skip_other_da_aces = True |
1894 |
if fix_P_to_AI: |
1895 |
fsacl.dacl.aces[i].flags |= security.SEC_ACE_FLAG_INHERITED_ACE |
1896 |
fsacl_masked.dacl_add(fsacl.dacl.aces[i]) |
1897 |
|
1898 |
fsacl_sddl_mapped = fsacl_masked.as_sddl(domainsid) |
1899 |
|
1900 |
if fsacl_sddl_mapped != acl_expected_for_subdir: |
1901 |
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)) |
1902 |
|
1903 |
|
1731 |
def check_gpos_acl(sysvol, dnsdomain, domainsid, domaindn, samdb, lp, |
1904 |
def check_gpos_acl(sysvol, dnsdomain, domainsid, domaindn, samdb, lp, |
1732 |
direct_db_access): |
1905 |
direct_db_access, mask_msad_differences=False): |
1733 |
"""Set ACL on the sysvol/<dnsname>/Policies folder and the policy |
1906 |
"""Set ACL on the sysvol/<dnsname>/Policies folder and the policy |
1734 |
folders beneath. |
1907 |
folders beneath. |
1735 |
|
1908 |
|
Lines 1759-1773
def check_gpos_acl(sysvol, dnsdomain, do
|
Link Here
|
---|
|
1759 |
policy["nTSecurityDescriptor"][0]).as_sddl() |
1932 |
policy["nTSecurityDescriptor"][0]).as_sddl() |
1760 |
policy_path = getpolicypath(sysvol, dnsdomain, str(policy["cn"])) |
1933 |
policy_path = getpolicypath(sysvol, dnsdomain, str(policy["cn"])) |
1761 |
try: |
1934 |
try: |
1762 |
check_dir_acl(policy_path, dsacl2fsacl(acl, domainsid), lp, |
1935 |
if mask_msad_differences: |
1763 |
domainsid, direct_db_access) |
1936 |
check_dir_acl_masked(policy_path, dsacl2fsacl(acl, domainsid), lp, |
|
|
1937 |
domainsid, direct_db_access) |
1938 |
else: |
1939 |
check_dir_acl(policy_path, dsacl2fsacl(acl, domainsid), lp, |
1940 |
domainsid, direct_db_access) |
1764 |
except Exception as e: |
1941 |
except Exception as e: |
1765 |
print(e) |
1942 |
print(e) |
1766 |
continue |
1943 |
continue |
1767 |
|
1944 |
|
1768 |
|
1945 |
|
1769 |
def checksysvolacl(samdb, netlogon, sysvol, domainsid, dnsdomain, domaindn, |
1946 |
def checksysvolacl(samdb, netlogon, sysvol, domainsid, dnsdomain, domaindn, |
1770 |
lp): |
1947 |
lp, mask_msad_differences=False): |
1771 |
"""Set the ACL for the sysvol share and the subfolders |
1948 |
"""Set the ACL for the sysvol share and the subfolders |
1772 |
|
1949 |
|
1773 |
:param samdb: An LDB object on the SAM db |
1950 |
:param samdb: An LDB object on the SAM db |
Lines 1812-1818
def checksysvolacl(samdb, netlogon, sysv
|
Link Here
|
---|
|
1812 |
|
1989 |
|
1813 |
# Check acls on Policy folder and policies folders |
1990 |
# Check acls on Policy folder and policies folders |
1814 |
check_gpos_acl(sysvol, dnsdomain, domainsid, domaindn, samdb, lp, |
1991 |
check_gpos_acl(sysvol, dnsdomain, domainsid, domaindn, samdb, lp, |
1815 |
direct_db_access) |
1992 |
direct_db_access, mask_msad_differences) |
1816 |
|
1993 |
|
1817 |
|
1994 |
|
1818 |
def interface_ips_v4(lp): |
1995 |
def interface_ips_v4(lp): |