From f33d5338b982ab6c79213b015d74f3d7cee05b72 Mon Sep 17 00:00:00 2001 From: Lukas Oyen Date: Wed, 13 Sep 2017 13:25:38 +0200 Subject: [PATCH 1/5] pysmb: improve debugging in `set_nt_acl_conn()` --- source3/smbd/pysmbd.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source3/smbd/pysmbd.c b/source3/smbd/pysmbd.c index fca8f10..239cac5 100644 --- a/source3/smbd/pysmbd.c +++ b/source3/smbd/pysmbd.c @@ -147,7 +147,7 @@ static NTSTATUS set_nt_acl_conn(const char *fname, fsp->fh->fd = SMB_VFS_OPEN(conn, smb_fname, fsp, flags, 00400); } if (fsp->fh->fd == -1) { - printf("open: error=%d (%s)\n", errno, strerror(errno)); + DBG_WARNING("open: error=%d (%s)\n", errno, strerror(errno)); TALLOC_FREE(frame); umask(saved_umask); return NT_STATUS_UNSUCCESSFUL; @@ -156,10 +156,9 @@ static NTSTATUS set_nt_acl_conn(const char *fname, ret = SMB_VFS_FSTAT(fsp, &smb_fname->st); if (ret == -1) { /* If we have an fd, this stat should succeed. */ - DEBUG(0,("Error doing fstat on open file %s " - "(%s)\n", + DBG_WARNING("Error doing fstat on open file %s (%s)\n", smb_fname_str_dbg(smb_fname), - strerror(errno) )); + strerror(errno)); TALLOC_FREE(frame); umask(saved_umask); return map_nt_error_from_unix(errno); @@ -178,7 +177,8 @@ static NTSTATUS set_nt_acl_conn(const char *fname, status = SMB_VFS_FSET_NT_ACL( fsp, security_info_sent, sd); if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("set_nt_acl_no_snum: fset_nt_acl returned %s.\n", nt_errstr(status))); + DBG_WARNING("set_nt_acl_no_snum: fset_nt_acl returned %s.\n", + nt_errstr(status)); } SMB_VFS_CLOSE(fsp); -- 2.7.4 From 4699655e7ee2af6644a76b496cf2c5819ffe67b8 Mon Sep 17 00:00:00 2001 From: Lukas Oyen Date: Tue, 12 Sep 2017 13:35:54 +0200 Subject: [PATCH 2/5] pysmb: map_nt_error_from_unix() in set_nt_acl_conn() --- source3/smbd/pysmbd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/smbd/pysmbd.c b/source3/smbd/pysmbd.c index 239cac5..5889a1c 100644 --- a/source3/smbd/pysmbd.c +++ b/source3/smbd/pysmbd.c @@ -150,7 +150,7 @@ static NTSTATUS set_nt_acl_conn(const char *fname, DBG_WARNING("open: error=%d (%s)\n", errno, strerror(errno)); TALLOC_FREE(frame); umask(saved_umask); - return NT_STATUS_UNSUCCESSFUL; + return map_nt_error_from_unix(errno); } ret = SMB_VFS_FSTAT(fsp, &smb_fname->st); -- 2.7.4 From 3ba7ddb6068d4ce834ad06002e710535e723bbfa Mon Sep 17 00:00:00 2001 From: Lukas Oyen Date: Thu, 14 Sep 2017 14:31:12 +0200 Subject: [PATCH 3/5] python/provision: add `set_nt_acl_wrapper()` --- python/samba/provision/__init__.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/python/samba/provision/__init__.py b/python/samba/provision/__init__.py index 48fc937..7a56b7e 100644 --- a/python/samba/provision/__init__.py +++ b/python/samba/provision/__init__.py @@ -27,6 +27,7 @@ __docformat__ = "restructuredText" from base64 import b64encode +import ctypes import os import re import pwd @@ -50,6 +51,7 @@ from samba.dsdb import DS_DOMAIN_FUNCTION_2000 from samba import ( Ldb, MAX_NETBIOS_NAME_LEN, + NTSTATUSError, check_all_substituted, is_valid_netbios_char, setup_file, @@ -125,6 +127,8 @@ DEFAULT_DC_POLICY_GUID = "6AC1786C-016F-11D2-945F-00C04FB984F9" DEFAULTSITE = "Default-First-Site-Name" LAST_PROVISION_USN_ATTRIBUTE = "lastProvisionUSN" +NT_STATUS_OBJECT_NAME_NOT_FOUND = 0xc0000034 + class ProvisionPaths(object): @@ -1473,6 +1477,25 @@ SYSVOL_ACL = "O:LAG:BAD:P(A;OICI;0x001f01ff;;;BA)(A;OICI;0x001200a9;;;SO)(A;OICI POLICIES_ACL = "O:LAG:BAD:P(A;OICI;0x001f01ff;;;BA)(A;OICI;0x001200a9;;;SO)(A;OICI;0x001f01ff;;;SY)(A;OICI;0x001200a9;;;AU)(A;OICI;0x001301bf;;;PA)" SYSVOL_SERVICE="sysvol" +def set_nt_acl_wrapper(lp, file, sddl, domsid, backend=None, eadbfile=None, + use_ntvfs=True, skip_invalid_chown=False, passdb=None, service=None, + logger=None, resume_on_error=False): + """A wrapper around setntacl() that catches NTSTATUSError and only logs + them if a logger is given and resume_on_error is True. + """ + try: + setntacl(lp, file, sddl, domsid, backend=backend, eadbfile=eadbfile, + use_ntvfs=use_ntvfs, skip_invalid_chown=skip_invalid_chown, + passdb=passdb, service=service) + except NTSTATUSError as error: + err_value = ctypes.c_uint32(error[0]).value + only_log = err_value == NT_STATUS_OBJECT_NAME_NOT_FOUND + if resume_on_error and logger and only_log: + logger.warning('Unable to set ACL %s on %s' % (sddl, file)) + else: + raise + + def set_dir_acl(path, acl, lp, domsid, use_ntvfs, passdb, service=SYSVOL_SERVICE): setntacl(lp, path, acl, domsid, use_ntvfs=use_ntvfs, skip_invalid_chown=True, passdb=passdb, service=service) for root, dirs, files in os.walk(path, topdown=False): -- 2.7.4 From 7db9181de3d1646c7ad7647bc2aaf3f34e3356df Mon Sep 17 00:00:00 2001 From: Lukas Oyen Date: Thu, 14 Sep 2017 14:34:52 +0200 Subject: [PATCH 4/5] python/provision: use `set_nt_acl_wrapper()` instead of `setntacl()` --- python/samba/netcmd/ntacl.py | 8 ++--- python/samba/provision/__init__.py | 73 +++++++++++++++++++++++++------------- python/samba/upgrade.py | 9 ++--- 3 files changed, 57 insertions(+), 33 deletions(-) diff --git a/python/samba/netcmd/ntacl.py b/python/samba/netcmd/ntacl.py index eaea0e7..7a89f51 100644 --- a/python/samba/netcmd/ntacl.py +++ b/python/samba/netcmd/ntacl.py @@ -233,10 +233,10 @@ class cmd_ntacl_sysvolreset(Command): if use_ntvfs: logger.warning("Please note that POSIX permissions have NOT been changed, only the stored NT ACL") - provision.setsysvolacl(samdb, netlogon, sysvol, - LA_uid, BA_gid, domain_sid, - lp.get("realm").lower(), samdb.domain_dn(), - lp, use_ntvfs=use_ntvfs) + provision.setsysvolacl(samdb, logger, netlogon, sysvol, LA_uid, BA_gid, + domain_sid, lp.get("realm").lower(), + samdb.domain_dn(), lp, use_ntvfs=use_ntvfs, + resume_on_error=False) class cmd_ntacl_sysvolcheck(Command): """Check sysvol ACLs match defaults (including correct ACLs on GPOs).""" diff --git a/python/samba/provision/__init__.py b/python/samba/provision/__init__.py index 7a56b7e..2436421 100644 --- a/python/samba/provision/__init__.py +++ b/python/samba/provision/__init__.py @@ -1496,33 +1496,45 @@ def set_nt_acl_wrapper(lp, file, sddl, domsid, backend=None, eadbfile=None, raise -def set_dir_acl(path, acl, lp, domsid, use_ntvfs, passdb, service=SYSVOL_SERVICE): - setntacl(lp, path, acl, domsid, use_ntvfs=use_ntvfs, skip_invalid_chown=True, passdb=passdb, service=service) +def set_dir_acl(path, acl, lp, domsid, use_ntvfs, passdb, service=SYSVOL_SERVICE, logger=None, resume_on_error=False): + set_nt_acl_wrapper(lp, path, acl, domsid, use_ntvfs=use_ntvfs, + skip_invalid_chown=True, passdb=passdb, service=service, + logger=logger, resume_on_error=resume_on_error) for root, dirs, files in os.walk(path, topdown=False): for name in files: - setntacl(lp, os.path.join(root, name), acl, domsid, - use_ntvfs=use_ntvfs, skip_invalid_chown=True, passdb=passdb, service=service) + set_nt_acl_wrapper(lp, os.path.join(root, name), acl, domsid, + use_ntvfs=use_ntvfs, skip_invalid_chown=True, + passdb=passdb, service=service, logger=logger, + resume_on_error=resume_on_error) for name in dirs: - setntacl(lp, os.path.join(root, name), acl, domsid, - use_ntvfs=use_ntvfs, skip_invalid_chown=True, passdb=passdb, service=service) + set_nt_acl_wrapper(lp, os.path.join(root, name), acl, domsid, + use_ntvfs=use_ntvfs, skip_invalid_chown=True, + passdb=passdb, service=service, logger=logger, + resume_on_error=resume_on_error) -def set_gpos_acl(sysvol, dnsdomain, domainsid, domaindn, samdb, lp, use_ntvfs, passdb): +def set_gpos_acl(sysvol, logger, dnsdomain, domainsid, domaindn, samdb, lp, + use_ntvfs, passdb, resume_on_error): """Set ACL on the sysvol//Policies folder and the policy folders beneath. :param sysvol: Physical path for the sysvol folder + :param logger: Logger object :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 + :param resume_on_error: A boolean that indicates if the function should + only log a NTSTATUSError and continue. """ # Set ACL for GPO root folder root_policy_path = os.path.join(sysvol, dnsdomain, "Policies") - setntacl(lp, root_policy_path, POLICIES_ACL, str(domainsid), - use_ntvfs=use_ntvfs, skip_invalid_chown=True, passdb=passdb, service=SYSVOL_SERVICE) + set_nt_acl_wrapper(lp, root_policy_path, POLICIES_ACL, str(domainsid), + use_ntvfs=use_ntvfs, skip_invalid_chown=True, + passdb=passdb, service=SYSVOL_SERVICE, logger=logger, + resume_on_error=resume_on_error) res = samdb.search(base="CN=Policies,CN=System,%s"%(domaindn), attrs=["cn", "nTSecurityDescriptor"], @@ -1534,14 +1546,16 @@ def set_gpos_acl(sysvol, dnsdomain, domainsid, domaindn, samdb, lp, use_ntvfs, p policy_path = getpolicypath(sysvol, dnsdomain, str(policy["cn"])) set_dir_acl(policy_path, dsacl2fsacl(acl, domainsid), lp, str(domainsid), use_ntvfs, - passdb=passdb) + passdb=passdb, logger=logger, + resume_on_error=resume_on_error) -def setsysvolacl(samdb, netlogon, sysvol, uid, gid, domainsid, dnsdomain, - domaindn, lp, use_ntvfs): +def setsysvolacl(samdb, logger, netlogon, sysvol, uid, gid, domainsid, + dnsdomain, domaindn, lp, use_ntvfs, resume_on_error): """Set the ACL for the sysvol share and the subfolders :param samdb: An LDB object on the SAM db + :param logger: Logger object :param netlogon: Physical path for the netlogon folder :param sysvol: Physical path for the sysvol folder :param uid: The UID of the "Administrator" user @@ -1549,6 +1563,8 @@ def setsysvolacl(samdb, netlogon, sysvol, uid, gid, domainsid, dnsdomain, :param domainsid: The SID of the domain :param dnsdomain: The DNS name of the domain :param domaindn: The DN of the domain (ie. DC=...) + :param resume_on_error: A boolean that indicates if the function should + only log a NTSTATUSError and continue. """ s4_passdb = None @@ -1611,25 +1627,31 @@ def setsysvolacl(samdb, netlogon, sysvol, uid, gid, domainsid, dnsdomain, canchown = True # Set the SYSVOL_ACL on the sysvol folder and subfolder (first level) - setntacl(lp,sysvol, SYSVOL_ACL, str(domainsid), use_ntvfs=use_ntvfs, - skip_invalid_chown=True, passdb=s4_passdb, - service=SYSVOL_SERVICE) + set_nt_acl_wrapper(lp, sysvol, SYSVOL_ACL, str(domainsid), + use_ntvfs=use_ntvfs, skip_invalid_chown=True, + passdb=s4_passdb, service=SYSVOL_SERVICE, logger=logger, + resume_on_error=resume_on_error) for root, dirs, files in os.walk(sysvol, topdown=False): for name in files: if use_ntvfs and canchown: os.chown(os.path.join(root, name), -1, gid) - setntacl(lp, os.path.join(root, name), SYSVOL_ACL, str(domainsid), - use_ntvfs=use_ntvfs, skip_invalid_chown=True, - passdb=s4_passdb, service=SYSVOL_SERVICE) + set_nt_acl_wrapper(lp, os.path.join(root, name), SYSVOL_ACL, + str(domainsid), use_ntvfs=use_ntvfs, + skip_invalid_chown=True, passdb=s4_passdb, + service=SYSVOL_SERVICE, logger=logger, + resume_on_error=resume_on_error) for name in dirs: if use_ntvfs and canchown: os.chown(os.path.join(root, name), -1, gid) - setntacl(lp, os.path.join(root, name), SYSVOL_ACL, str(domainsid), - use_ntvfs=use_ntvfs, skip_invalid_chown=True, - passdb=s4_passdb, service=SYSVOL_SERVICE) + set_nt_acl_wrapper(lp, os.path.join(root, name), SYSVOL_ACL, + str(domainsid), use_ntvfs=use_ntvfs, + skip_invalid_chown=True, passdb=s4_passdb, + service=SYSVOL_SERVICE, logger=logger, + resume_on_error=resume_on_error) # Set acls on Policy folder and policies folders - set_gpos_acl(sysvol, dnsdomain, domainsid, domaindn, samdb, lp, use_ntvfs, passdb=s4_passdb) + set_gpos_acl(sysvol, logger, dnsdomain, domainsid, domaindn, samdb, lp, + use_ntvfs, passdb=s4_passdb, resume_on_error=resume_on_error) def acl_type(direct_db_access): if direct_db_access: @@ -1824,9 +1846,10 @@ def provision_fill(samdb, secrets_ldb, logger, names, paths, # Continue setting up sysvol for GPO. This appears to require being # outside a transaction. if not skip_sysvolacl: - setsysvolacl(samdb, paths.netlogon, paths.sysvol, paths.root_uid, - paths.root_gid, names.domainsid, names.dnsdomain, - names.domaindn, lp, use_ntvfs) + setsysvolacl(samdb, logger, paths.netlogon, paths.sysvol, + paths.root_uid, paths.root_gid, names.domainsid, + names.dnsdomain, names.domaindn, lp, use_ntvfs, + resume_on_error=False) else: logger.info("Setting acl on sysvol skipped") diff --git a/python/samba/upgrade.py b/python/samba/upgrade.py index 3856323..b4bff8d 100644 --- a/python/samba/upgrade.py +++ b/python/samba/upgrade.py @@ -847,10 +847,11 @@ Please fix this account before attempting to upgrade again logger.info("Administrator password has been set to password of user '%s'", admin_user) if result.server_role == "active directory domain controller": - setsysvolacl(result.samdb, result.paths.netlogon, result.paths.sysvol, - result.paths.root_uid, result.paths.root_gid, - security.dom_sid(result.domainsid), result.names.dnsdomain, - result.names.domaindn, result.lp, use_ntvfs) + setsysvolacl(result.samdb, logger, result.paths.netlogon, + result.paths.sysvol, result.paths.root_uid, + result.paths.root_gid, security.dom_sid(result.domainsid), + result.names.dnsdomain, result.names.domaindn, result.lp, + use_ntvfs, resume_on_error=False) # FIXME: import_registry(registry.Registry(), samba3.get_registry()) # FIXME: shares -- 2.7.4 From 091050b890666468b2fc5127b072dc631e2556dd Mon Sep 17 00:00:00 2001 From: Lukas Oyen Date: Thu, 14 Sep 2017 14:35:39 +0200 Subject: [PATCH 5/5] netcmd/ntacl: add option `--resume-on-error` to sysvolreset --- python/samba/netcmd/ntacl.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/python/samba/netcmd/ntacl.py b/python/samba/netcmd/ntacl.py index 7a89f51..1158e69 100644 --- a/python/samba/netcmd/ntacl.py +++ b/python/samba/netcmd/ntacl.py @@ -183,10 +183,11 @@ class cmd_ntacl_sysvolreset(Command): takes_options = [ Option("--use-ntvfs", help="Set the ACLs for use with the ntvfs file server", action="store_true"), - Option("--use-s3fs", help="Set the ACLs for use with the default s3fs file server", action="store_true") + Option("--use-s3fs", help="Set the ACLs for use with the default s3fs file server", action="store_true"), + Option("--resume-on-error", help="Only log unsuccessful ACL operation and resume", action="store_true"), ] - def run(self, use_ntvfs=False, use_s3fs=False, + def run(self, use_ntvfs=False, use_s3fs=False, resume_on_error=False, credopts=None, sambaopts=None, versionopts=None): lp = sambaopts.get_loadparm() path = lp.private_path("secrets.ldb") @@ -236,7 +237,7 @@ class cmd_ntacl_sysvolreset(Command): provision.setsysvolacl(samdb, logger, netlogon, sysvol, LA_uid, BA_gid, domain_sid, lp.get("realm").lower(), samdb.domain_dn(), lp, use_ntvfs=use_ntvfs, - resume_on_error=False) + resume_on_error=resume_on_error) class cmd_ntacl_sysvolcheck(Command): """Check sysvol ACLs match defaults (including correct ACLs on GPOs).""" -- 2.7.4