summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2012-08-23 10:37:46 +1000
committerAndrew Bartlett <abartlet@samba.org>2012-08-23 15:02:26 +0200
commitebcdc4a36be9b79325b11ec0c44a43db93e29519 (patch)
tree6973d52f33386d3d55f4cd812e2985e3994e7e5f
parent0aed29105e9d8ddcd27a70d7af820da8813ca47b (diff)
downloadsamba-ebcdc4a36be9b79325b11ec0c44a43db93e29519.tar.gz
samba-ebcdc4a36be9b79325b11ec0c44a43db93e29519.tar.bz2
samba-ebcdc4a36be9b79325b11ec0c44a43db93e29519.zip
s4-samba-tool: Add samba-tool ntacl sysvolcheck command
This command verifies that the current on-disk ACLs match the directory and the defaults from provision. Unlike sysvolreset, this does not change any of the permissions. Andrew Bartlett
-rw-r--r--source4/scripting/python/samba/netcmd/ntacl.py34
-rw-r--r--source4/scripting/python/samba/provision/__init__.py110
2 files changed, 143 insertions, 1 deletions
diff --git a/source4/scripting/python/samba/netcmd/ntacl.py b/source4/scripting/python/samba/netcmd/ntacl.py
index 81217b76d6..4a0c91c289 100644
--- a/source4/scripting/python/samba/netcmd/ntacl.py
+++ b/source4/scripting/python/samba/netcmd/ntacl.py
@@ -179,6 +179,39 @@ class cmd_ntacl_sysvolreset(Command):
lp.get("realm").lower(), samdb.domain_dn(),
lp, use_ntvfs=use_ntvfs)
+class cmd_ntacl_sysvolcheck(Command):
+ """Check sysvol ACLs match defaults (including correct ACLs on GPOs)"""
+ synopsis = "%prog <file> [options]"
+
+ takes_optiongroups = {
+ "sambaopts": options.SambaOptions,
+ "credopts": options.CredentialsOptions,
+ "versionopts": options.VersionOptions,
+ }
+
+ def run(self,
+ credopts=None, sambaopts=None, versionopts=None):
+ lp = sambaopts.get_loadparm()
+ path = lp.private_path("secrets.ldb")
+ creds = credopts.get_credentials(lp)
+ creds.set_kerberos_state(DONT_USE_KERBEROS)
+ logger = self.get_logger()
+
+ netlogon = lp.get("path", "netlogon")
+ sysvol = lp.get("path", "sysvol")
+ try:
+ samdb = SamDB(session_info=system_session(),
+ lp=lp)
+ except Exception, e:
+ raise CommandError("Unable to open samdb:", e)
+
+ domain_sid = security.dom_sid(samdb.domain_sid)
+
+ provision.checksysvolacl(samdb, netlogon, sysvol,
+ domain_sid,
+ lp.get("realm").lower(), samdb.domain_dn(),
+ lp)
+
class cmd_ntacl(SuperCommand):
"""NT ACLs manipulation"""
@@ -187,4 +220,5 @@ class cmd_ntacl(SuperCommand):
subcommands["set"] = cmd_ntacl_set()
subcommands["get"] = cmd_ntacl_get()
subcommands["sysvolreset"] = cmd_ntacl_sysvolreset()
+ subcommands["sysvolcheck"] = cmd_ntacl_sysvolcheck()
diff --git a/source4/scripting/python/samba/provision/__init__.py b/source4/scripting/python/samba/provision/__init__.py
index 4762e5b162..ed46b4040d 100644
--- a/source4/scripting/python/samba/provision/__init__.py
+++ b/source4/scripting/python/samba/provision/__init__.py
@@ -69,7 +69,7 @@ from samba.dsdb import (
)
from samba.idmap import IDmapDB
from samba.ms_display_specifiers import read_ms_ldif
-from samba.ntacls import setntacl, dsacl2fsacl
+from samba.ntacls import setntacl, getntacl, dsacl2fsacl
from samba.ndr import ndr_pack, ndr_unpack
from samba.provision.backend import (
ExistingBackend,
@@ -1455,6 +1455,114 @@ def setsysvolacl(samdb, netlogon, sysvol, uid, gid, domainsid, dnsdomain, domain
# Set acls on Policy folder and policies folders
set_gpos_acl(sysvol, dnsdomain, domainsid, domaindn, samdb, lp, use_ntvfs)
+def acl_type(direct_db_access):
+ if direct_db_access:
+ return "DB"
+ else:
+ return "VFS"
+
+def check_dir_acl(path, acl, lp, domainsid, direct_db_access):
+ fsacl = getntacl(lp, path, direct_db_access=direct_db_access)
+ fsacl_sddl = fsacl.as_sddl(domainsid)
+ if fsacl_sddl != acl:
+ raise ProvisioningError('%s ACL on GPO directory %s %s does not match expected value %s from GPO object' % (acl_type(direct_db_access), path, fsacl_sddl, acl))
+
+ for root, dirs, files in os.walk(path, topdown=False):
+ for name in files:
+ fsacl = getntacl(lp, os.path.join(root, name), direct_db_access=direct_db_access)
+ 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(domainsid)
+ if fsacl_sddl != acl:
+ raise ProvisioningError('%s ACL on GPO file %s %s does not match expected value %s from GPO object' % (acl_type(direct_db_access), os.path.join(root, name), fsacl, acl))
+
+ for name in files:
+ fsacl = getntacl(lp, os.path.join(root, name), direct_db_access=direct_db_access)
+ 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(domainsid)
+ if fsacl_sddl != acl:
+ raise ProvisioningError('%s ACL on GPO directory %s %s does not match expected value %s from GPO object' % (acl_type(direct_db_access), os.path.join(root, name), fsacl, acl))
+
+
+def check_gpos_acl(sysvol, dnsdomain, domainsid, domaindn, samdb, lp, direct_db_access):
+ """Set ACL on the sysvol/<dnsname>/Policies folder and the policy
+ folders beneath.
+
+ :param sysvol: Physical path for the sysvol folder
+ :param dnsdomain: The DNS name of the domain
+ :param domainsid: The SID of the domain
+ :param domaindn: The DN of the domain (ie. DC=...)
+ :param samdb: An LDB object on the SAM db
+ :param lp: an LP object
+ """
+
+ # Set ACL for GPO root folder
+ root_policy_path = os.path.join(sysvol, dnsdomain, "Policies")
+ fsacl = getntacl(lp, root_policy_path, direct_db_access=direct_db_access)
+ if fsacl is None:
+ raise ProvisioningError('DB ACL on policy root %s %s not found!' % (acl_type(direct_db_access), root_policy_path))
+ fsacl_sddl = fsacl.as_sddl(domainsid)
+ if fsacl_sddl != POLICIES_ACL:
+ raise ProvisioningError('%s ACL on policy root %s %s does not match expected value %s from provision' % (acl_type(direct_db_access), policy_root, fsacl_sddl, acl))
+ res = samdb.search(base="CN=Policies,CN=System,%s"%(domaindn),
+ attrs=["cn", "nTSecurityDescriptor"],
+ expression="", scope=ldb.SCOPE_ONELEVEL)
+
+ for policy in res:
+ acl = ndr_unpack(security.descriptor,
+ str(policy["nTSecurityDescriptor"])).as_sddl()
+ policy_path = getpolicypath(sysvol, dnsdomain, str(policy["cn"]))
+ check_dir_acl(policy_path, dsacl2fsacl(acl, str(domainsid)), lp,
+ domainsid, direct_db_access)
+
+
+def checksysvolacl(samdb, netlogon, sysvol, domainsid, dnsdomain, domaindn,
+ lp):
+ """Set the ACL for the sysvol share and the subfolders
+
+ :param samdb: An LDB object on the SAM db
+ :param netlogon: Physical path for the netlogon folder
+ :param sysvol: Physical path for the sysvol folder
+ :param uid: The UID of the "Administrator" user
+ :param gid: The GID of the "Domain adminstrators" group
+ :param domainsid: The SID of the domain
+ :param dnsdomain: The DNS name of the domain
+ :param domaindn: The DN of the domain (ie. DC=...)
+ """
+
+ # This will ensure that the smbd code we are running when setting ACLs is initialised with the smb.conf
+ s3conf = s3param.get_context()
+ s3conf.load(lp.configfile)
+ # ensure we are using the right samba4 passdb backend, no matter what
+ s3conf.set("passdb backend", "samba4:%s" % samdb.url)
+ # ensure that we init the samba4 backend, so the domain sid is marked in secrets.tdb
+ s4_passdb = passdb.PDB(s3conf.get("passdb backend"))
+
+ # now ensure everything matches correctly, to avoid wierd issues
+ if passdb.get_global_sam_sid() != domainsid:
+ raise ProvisioningError('SID as seen by smbd [%s] does not match SID as seen by the provision script [%s]!' % (passdb.get_global_sam_sid(), domainsid))
+
+ domain_info = s4_passdb.domain_info()
+ if domain_info["dom_sid"] != domainsid:
+ raise ProvisioningError('SID as seen by pdb_samba4 [%s] does not match SID as seen by the provision script [%s]!' % (domain_info["dom_sid"], domainsid))
+
+ if domain_info["dns_domain"].upper() != dnsdomain.upper():
+ raise ProvisioningError('Realm as seen by pdb_samba4 [%s] does not match Realm as seen by the provision script [%s]!' % (domain_info["dns_domain"].upper(), dnsdomain.upper()))
+
+ # Set the SYSVOL_ACL on the sysvol folder and subfolder (first level)
+ for direct_db_access in [True, False]:
+ for dir_path in [os.path.join(sysvol, dnsdomain), netlogon]:
+ fsacl = getntacl(lp, dir_path, direct_db_access=direct_db_access)
+ if fsacl is None:
+ raise ProvisioningError('%s ACL on sysvol directory %s not found!' % (acl_type(direct_db_access), dir_path))
+ fsacl_sddl = fsacl.as_sddl(domainsid)
+ if fsacl_sddl != SYSVOL_ACL:
+ raise ProvisioningError('%s ACL on sysvol directory %s %s does not match expected value %s from provision' % (acl_type(direct_db_access), dir_path, fsacl_sddl, SYSVOL_ACL))
+
+ # Check acls on Policy folder and policies folders
+ check_gpos_acl(sysvol, dnsdomain, domainsid, domaindn, samdb, lp, direct_db_access)
+
def interface_ips_v4(lp):
'''return only IPv4 IPs'''