diff options
-rw-r--r-- | selftest/target/Samba4.pm | 3 | ||||
-rw-r--r-- | source4/scripting/python/samba/ntacls.py | 70 | ||||
-rw-r--r-- | source4/scripting/python/samba/provision/__init__.py | 74 |
3 files changed, 94 insertions, 53 deletions
diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm index 248a7259f7..7ac337425b 100644 --- a/selftest/target/Samba4.pm +++ b/selftest/target/Samba4.pm @@ -534,6 +534,7 @@ sub provision_raw_prepare($$$$$$$$$$) push (@provision_options, "--server-role=\"$ctx->{server_role}\""); push (@provision_options, "--function-level=\"$ctx->{functional_level}\""); push (@provision_options, "--dns-backend=BIND9_DLZ"); + if ($use_ntvfs) { push (@provision_options, "--use-ntvfs"); } @@ -1205,7 +1206,7 @@ sub provision_fl2000dc($$) "samba2000.example.com", "2000", "locDCpass5", - undef, "", 1); + undef, "", "", 1); unless($self->add_wins_config("$prefix/private")) { warn("Unable to add wins configuration"); diff --git a/source4/scripting/python/samba/ntacls.py b/source4/scripting/python/samba/ntacls.py index e3d24fa365..64dfd17d64 100644 --- a/source4/scripting/python/samba/ntacls.py +++ b/source4/scripting/python/samba/ntacls.py @@ -23,6 +23,7 @@ import os import samba.xattr_native, samba.xattr_tdb, samba.posix_eadb from samba.dcerpc import security, xattr from samba.ndr import ndr_pack, ndr_unpack +from samba.samba3 import smbd class XattrBackendError(Exception): """A generic xattr backend error.""" @@ -55,44 +56,51 @@ def checkset_backend(lp, backend, eadbfile): def getntacl(lp, file, backend=None, eadbfile=None): - (backend_obj, dbname) = checkset_backend(lp, backend, eadbfile) - if dbname is not None: - try: - attribute = backend_obj.wrap_getxattr(dbname, file, - xattr.XATTR_NTACL_NAME) - except Exception: - # FIXME: Don't catch all exceptions, just those related to opening - # xattrdb - print "Fail to open %s" % dbname + if use_ntvfs: + (backend_obj, dbname) = checkset_backend(lp, backend, eadbfile) + if dbname is not None: + try: + attribute = backend_obj.wrap_getxattr(dbname, file, + xattr.XATTR_NTACL_NAME) + except Exception: + # FIXME: Don't catch all exceptions, just those related to opening + # xattrdb + print "Fail to open %s" % dbname + attribute = samba.xattr_native.wrap_getxattr(file, + xattr.XATTR_NTACL_NAME) + else: attribute = samba.xattr_native.wrap_getxattr(file, - xattr.XATTR_NTACL_NAME) + xattr.XATTR_NTACL_NAME) + ntacl = ndr_unpack(xattr.NTACL, attribute) + return ntacl else: - attribute = samba.xattr_native.wrap_getxattr(file, - xattr.XATTR_NTACL_NAME) - ntacl = ndr_unpack(xattr.NTACL, attribute) - return ntacl + return smbd.get_nt_acl(file) -def setntacl(lp, file, sddl, domsid, backend=None, eadbfile=None): - (backend_obj, dbname) = checkset_backend(lp, backend, eadbfile) - ntacl = xattr.NTACL() - ntacl.version = 1 +def setntacl(lp, file, sddl, domsid, backend=None, eadbfile=None, use_ntvfs=True): sid = security.dom_sid(domsid) sd = security.descriptor.from_sddl(sddl, sid) - ntacl.info = sd - if dbname is not None: - try: - backend_obj.wrap_setxattr(dbname, - file, xattr.XATTR_NTACL_NAME, ndr_pack(ntacl)) - except Exception: - # FIXME: Don't catch all exceptions, just those related to opening - # xattrdb - print "Fail to open %s" % dbname - samba.xattr_native.wrap_setxattr(file, xattr.XATTR_NTACL_NAME, - ndr_pack(ntacl)) + + if use_ntvfs: + (backend_obj, dbname) = checkset_backend(lp, backend, eadbfile) + ntacl = xattr.NTACL() + ntacl.version = 1 + ntacl.info = sd + if dbname is not None: + try: + backend_obj.wrap_setxattr(dbname, + file, xattr.XATTR_NTACL_NAME, ndr_pack(ntacl)) + except Exception: + # FIXME: Don't catch all exceptions, just those related to opening + # xattrdb + print "Fail to open %s" % dbname + samba.xattr_native.wrap_setxattr(file, xattr.XATTR_NTACL_NAME, + ndr_pack(ntacl)) + else: + samba.xattr_native.wrap_setxattr(file, xattr.XATTR_NTACL_NAME, + ndr_pack(ntacl)) else: - samba.xattr_native.wrap_setxattr(file, xattr.XATTR_NTACL_NAME, - ndr_pack(ntacl)) + smbd.set_nt_acl(file, security.SECINFO_OWNER | security.SECINFO_GROUP | security.SECINFO_DACL, sd) def ldapmask2filemask(ldm): diff --git a/source4/scripting/python/samba/provision/__init__.py b/source4/scripting/python/samba/provision/__init__.py index 02ebf68310..fd71631ee7 100644 --- a/source4/scripting/python/samba/provision/__init__.py +++ b/source4/scripting/python/samba/provision/__init__.py @@ -44,7 +44,8 @@ import ldb from samba.auth import system_session, admin_session import samba -from samba.samba3 import smbd +from samba.samba3 import smbd, passdb +from samba.samba3 import param as s3param from samba.dsdb import DS_DOMAIN_FUNCTION_2000 from samba import ( Ldb, @@ -1359,16 +1360,16 @@ 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)" -def set_dir_acl(path, acl, lp, domsid): - setntacl(lp, path, acl, domsid) +def set_dir_acl(path, acl, lp, domsid, use_ntvfs): + setntacl(lp, path, acl, domsid, use_ntvfs=use_ntvfs) for root, dirs, files in os.walk(path, topdown=False): for name in files: - setntacl(lp, os.path.join(root, name), acl, domsid) + setntacl(lp, os.path.join(root, name), acl, domsid, use_ntvfs=use_ntvfs) for name in dirs: - setntacl(lp, os.path.join(root, name), acl, domsid) + setntacl(lp, os.path.join(root, name), acl, domsid, use_ntvfs=use_ntvfs) -def set_gpos_acl(sysvol, dnsdomain, domainsid, domaindn, samdb, lp): +def set_gpos_acl(sysvol, dnsdomain, domainsid, domaindn, samdb, lp, use_ntvfs): """Set ACL on the sysvol/<dnsname>/Policies folder and the policy folders beneath. @@ -1382,7 +1383,7 @@ def set_gpos_acl(sysvol, dnsdomain, domainsid, domaindn, samdb, lp): # Set ACL for GPO root folder root_policy_path = os.path.join(sysvol, dnsdomain, "Policies") - setntacl(lp, root_policy_path, POLICIES_ACL, str(domainsid)) + setntacl(lp, root_policy_path, POLICIES_ACL, str(domainsid), use_ntvfs=use_ntvfs) res = samdb.search(base="CN=Policies,CN=System,%s"%(domaindn), attrs=["cn", "nTSecurityDescriptor"], @@ -1393,11 +1394,11 @@ def set_gpos_acl(sysvol, dnsdomain, domainsid, domaindn, samdb, lp): str(policy["nTSecurityDescriptor"])).as_sddl() policy_path = getpolicypath(sysvol, dnsdomain, str(policy["cn"])) set_dir_acl(policy_path, dsacl2fsacl(acl, str(domainsid)), lp, - str(domainsid)) + str(domainsid), use_ntvfs) -def setsysvolacl(samdb, netlogon, sysvol, gid, domainsid, dnsdomain, domaindn, - lp): +def setsysvolacl(samdb, netlogon, sysvol, uid, gid, domainsid, dnsdomain, domaindn, + lp, use_ntvfs): """Set the ACL for the sysvol share and the subfolders :param samdb: An LDB object on the SAM db @@ -1409,27 +1410,49 @@ def setsysvolacl(samdb, netlogon, sysvol, gid, domainsid, dnsdomain, domaindn, :param domaindn: The DN of the domain (ie. DC=...) """ + if not use_ntvfs: + # 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())) + + try: - os.chown(sysvol, -1, gid) + if use_ntvfs: + os.chown(sysvol, -1, gid) except OSError: canchown = False else: canchown = True # Set the SYSVOL_ACL on the sysvol folder and subfolder (first level) - setntacl(lp,sysvol, SYSVOL_ACL, str(domainsid)) + setntacl(lp,sysvol, SYSVOL_ACL, str(domainsid), use_ntvfs=use_ntvfs) for root, dirs, files in os.walk(sysvol, topdown=False): for name in files: - if canchown: + 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)) + setntacl(lp, os.path.join(root, name), SYSVOL_ACL, str(domainsid), use_ntvfs=use_ntvfs) for name in dirs: - if canchown: + 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)) + setntacl(lp, os.path.join(root, name), SYSVOL_ACL, str(domainsid), use_ntvfs=use_ntvfs) # Set acls on Policy folder and policies folders - set_gpos_acl(sysvol, dnsdomain, domainsid, domaindn, samdb, lp) + set_gpos_acl(sysvol, dnsdomain, domainsid, domaindn, samdb, lp, use_ntvfs) def interface_ips_v4(lp): @@ -1460,7 +1483,7 @@ def provision_fill(samdb, secrets_ldb, logger, names, paths, invocationid=None, machinepass=None, ntdsguid=None, dns_backend=None, dnspass=None, serverrole=None, dom_for_fun_level=None, - am_rodc=False, lp=None): + am_rodc=False, lp=None, use_ntvfs=False): # create/adapt the group policy GUIDs # Default GUID for default policy are described at # "How Core Group Policy Works" @@ -1492,12 +1515,13 @@ def provision_fill(samdb, secrets_ldb, logger, names, paths, next_rid=next_rid, dc_rid=dc_rid) if serverrole == "active directory domain controller": + # Set up group policies (domain policy and domain controller # policy) create_default_gpo(paths.sysvol, names.dnsdomain, policyguid, policyguid_dc) - setsysvolacl(samdb, paths.netlogon, paths.sysvol, paths.wheel_gid, - domainsid, names.dnsdomain, names.domaindn, lp) + setsysvolacl(samdb, paths.netlogon, paths.sysvol, paths.root_uid, paths.wheel_gid, + domainsid, names.dnsdomain, names.domaindn, lp, use_ntvfs) secretsdb_self_join(secrets_ldb, domain=names.domain, realm=names.realm, dnsdomain=names.dnsdomain, @@ -1719,6 +1743,7 @@ def provision(logger, session_info, credentials, smbconf=None, paths = provision_paths_from_lp(lp, names.dnsdomain) paths.bind_gid = bind_gid + paths.root_uid = root_uid; paths.wheel_gid = wheel_gid if hostip is None: @@ -1761,6 +1786,9 @@ def provision(logger, session_info, credentials, smbconf=None, os.makedirs(paths.sysvol, 0775) if not use_ntvfs and serverrole == "active directory domain controller": + s3conf = s3param.get_context() + s3conf.load(lp.configfile) + if paths.sysvol is None: raise MissingShareError("sysvol", paths.smbconf) @@ -1776,6 +1804,10 @@ def provision(logger, session_info, credentials, smbconf=None, smbd.set_simple_acl(file.name, root_uid, wheel_gid) except Exception: raise ProvisioningError("Your filesystem or build does not support posix ACLs, which s3fs requires. Try the mounting the filesystem with the 'acl' option.") + try: + smbd.chown(file.name, root_uid, wheel_gid) + except Exception: + raise ProvisioningError("Unable to chown a file on your filesystem. You may not be running provision as root. ") finally: file.close() @@ -1871,7 +1903,7 @@ def provision(logger, session_info, credentials, smbconf=None, ntdsguid=ntdsguid, dns_backend=dns_backend, dnspass=dnspass, serverrole=serverrole, dom_for_fun_level=dom_for_fun_level, am_rodc=am_rodc, - lp=lp) + lp=lp, use_ntvfs=use_ntvfs) create_krb5_conf(paths.krb5conf, dnsdomain=names.dnsdomain, hostname=names.hostname, |