provision: setup names.dns_backend
[nivanova/samba-autobuild/.git] / source4 / scripting / python / samba / provision / __init__.py
index d9ba90cab560137a71a4d2bcd201ba8d326230b4..507582bad590f492cc332a0a6166015d33a2cc63 100644 (file)
@@ -77,8 +77,25 @@ from samba.provision.backend import (
     OpenLDAPBackend,
     )
 from samba.provision.descriptor import (
+    get_empty_descriptor,
     get_config_descriptor,
-    get_domain_descriptor
+    get_config_partitions_descriptor,
+    get_config_sites_descriptor,
+    get_config_ntds_quotas_descriptor,
+    get_config_delete_protected1_descriptor,
+    get_config_delete_protected1wd_descriptor,
+    get_config_delete_protected2_descriptor,
+    get_domain_descriptor,
+    get_domain_infrastructure_descriptor,
+    get_domain_builtin_descriptor,
+    get_domain_computers_descriptor,
+    get_domain_users_descriptor,
+    get_domain_controllers_descriptor,
+    get_domain_delete_protected1_descriptor,
+    get_domain_delete_protected2_descriptor,
+    get_dns_partition_descriptor,
+    get_dns_forest_microsoft_dns_descriptor,
+    get_dns_domain_microsoft_dns_descriptor,
     )
 from samba.provision.common import (
     setup_path,
@@ -86,6 +103,7 @@ from samba.provision.common import (
     setup_modify_ldif,
     )
 from samba.provision.sambadns import (
+    get_dnsadmins_sid,
     setup_ad_dns,
     create_dns_update_list
     )
@@ -122,16 +140,18 @@ class ProvisionPaths(object):
         self.winsdb = None
         self.private_dir = None
         self.state_dir = None
-        self.phpldapadminconfig = None
 
 
 class ProvisionNames(object):
 
     def __init__(self):
+        self.ncs = None
         self.rootdn = None
         self.domaindn = None
         self.configdn = None
         self.schemadn = None
+        self.dnsforestdn = None
+        self.dnsdomaindn = None
         self.ldapmanagerdn = None
         self.dnsdomain = None
         self.realm = None
@@ -140,6 +160,7 @@ class ProvisionNames(object):
         self.hostname = None
         self.sitename = None
         self.smbconf = None
+        self.name_map = {}
 
 
 def find_provision_key_parameters(samdb, secretsdb, idmapdb, paths, smbconf,
@@ -177,7 +198,8 @@ def find_provision_key_parameters(samdb, secretsdb, idmapdb, paths, smbconf,
     current = samdb.search(expression="(objectClass=*)",
         base="", scope=ldb.SCOPE_BASE,
         attrs=["defaultNamingContext", "schemaNamingContext",
-               "configurationNamingContext","rootDomainNamingContext"])
+               "configurationNamingContext","rootDomainNamingContext",
+               "namingContexts"])
 
     names.configdn = current[0]["configurationNamingContext"]
     configdn = str(names.configdn)
@@ -191,6 +213,23 @@ def find_provision_key_parameters(samdb, secretsdb, idmapdb, paths, smbconf,
 
     names.domaindn=current[0]["defaultNamingContext"]
     names.rootdn=current[0]["rootDomainNamingContext"]
+    names.ncs=current[0]["namingContexts"]
+    names.dnsforestdn = None
+    names.dnsdomaindn = None
+
+    for i in range(0, len(names.ncs)):
+        nc = names.ncs[i]
+
+        dnsforestdn = "DC=ForestDnsZones,%s" % (str(names.rootdn))
+        if nc == dnsforestdn:
+            names.dnsforestdn = dnsforestdn
+            continue
+
+        dnsdomaindn = "DC=DomainDnsZones,%s" % (str(names.domaindn))
+        if nc == dnsdomaindn:
+            names.dnsdomaindn = dnsdomaindn
+            continue
+
     # default site name
     res3 = samdb.search(expression="(objectClass=site)",
         base="CN=Sites," + configdn, scope=ldb.SCOPE_ONELEVEL, attrs=["cn"])
@@ -241,12 +280,46 @@ def find_provision_key_parameters(samdb, secretsdb, idmapdb, paths, smbconf,
         names.policyid_dc = str(res8[0]["cn"]).replace("{","").replace("}","")
     else:
         names.policyid_dc = None
-    res9 = idmapdb.search(expression="(cn=%s)" %
-                            (security.SID_BUILTIN_ADMINISTRATORS),
-                            attrs=["xidNumber"])
+
+    res9 = idmapdb.search(expression="(cn=%s-%s)" %
+                          (str(names.domainsid), security.DOMAIN_RID_ADMINISTRATOR),
+                          attrs=["xidNumber", "type"])
     if len(res9) != 1:
-        raise ProvisioningError("Unable to find uid/gid for Domain Admins rid")
-    names.wheel_gid = res9[0]["xidNumber"]
+        raise ProvisioningError("Unable to find uid/gid for Domain Admins rid (%s-%s" % (str(names.domainsid), security.DOMAIN_RID_ADMINISTRATOR))
+    if res9[0]["type"][0] == "ID_TYPE_BOTH":
+        names.root_gid = res9[0]["xidNumber"][0]
+    else:
+        names.root_gid = pwd.getpwuid(int(res9[0]["xidNumber"][0])).pw_gid
+
+    res10 = samdb.search(expression="(samaccountname=dns)",
+                         scope=ldb.SCOPE_SUBTREE, attrs=["dn"],
+                         controls=["search_options:1:2"])
+    if (len(res10) > 0):
+        has_legacy_dns_account = True
+    else:
+        has_legacy_dns_account = False
+
+    res11 = samdb.search(expression="(samaccountname=dns-%s)" % names.netbiosname,
+                         scope=ldb.SCOPE_SUBTREE, attrs=["dn"],
+                         controls=["search_options:1:2"])
+    if (len(res11) > 0):
+        has_dns_account = True
+    else:
+        has_dns_account = False
+
+    if names.dnsdomaindn is not None:
+        if has_dns_account:
+            names.dns_backend = 'BIND9_DLZ'
+        else:
+            names.dns_backend = 'SAMBA_INTERNAL'
+    elif has_dns_account or has_legacy_dns_account:
+        names.dns_backend = 'BIND9_FLATFILE'
+    else:
+        names.dns_backend = 'NONE'
+
+    dns_admins_sid = get_dnsadmins_sid(samdb, names.domaindn)
+    names.name_map['DnsAdmins'] = str(dns_admins_sid)
+
     return names
 
 
@@ -401,12 +474,6 @@ class ProvisionResult(object):
         logger.info("DNS Domain:            %s", self.names.dnsdomain)
         logger.info("DOMAIN SID:            %s", self.domainsid)
 
-        if self.paths.phpldapadminconfig is not None:
-            logger.info(
-                "A phpLDAPadmin configuration file suitable for administering "
-                "the Samba 4 LDAP server has been created in %s.",
-                self.paths.phpldapadminconfig)
-
         if self.backend_result:
             self.backend_result.report_logger(logger)
 
@@ -474,8 +541,6 @@ def provision_paths_from_lp(lp, dnsdomain):
     paths.krb5conf = os.path.join(paths.private_dir, "krb5.conf")
     paths.winsdb = os.path.join(paths.private_dir, "wins.ldb")
     paths.s4_ldapi_path = os.path.join(paths.private_dir, "ldapi")
-    paths.phpldapadminconfig = os.path.join(paths.private_dir,
-                                            "phpldapadmin-config.php")
     paths.hklm = "hklm.ldb"
     paths.hkcr = "hkcr.ldb"
     paths.hkcu = "hkcu.ldb"
@@ -692,7 +757,7 @@ def make_smbconf(smbconf, hostname, domain, realm, targetdir,
 
 
 def setup_name_mappings(idmap, sid, root_uid, nobody_uid,
-                        users_gid, wheel_gid):
+                        users_gid, root_gid):
     """setup reasonable name mappings for sam names to unix names.
 
     :param samdb: SamDB object.
@@ -702,10 +767,9 @@ def setup_name_mappings(idmap, sid, root_uid, nobody_uid,
     :param root_uid: uid of the UNIX root user.
     :param nobody_uid: uid of the UNIX nobody user.
     :param users_gid: gid of the UNIX users group.
-    :param wheel_gid: gid of the UNIX wheel group.
+    :param root_gid: gid of the UNIX root group.
     """
     idmap.setup_name_mapping("S-1-5-7", idmap.TYPE_UID, nobody_uid)
-    idmap.setup_name_mapping("S-1-5-32-544", idmap.TYPE_GID, wheel_gid)
 
     idmap.setup_name_mapping(sid + "-500", idmap.TYPE_UID, root_uid)
     idmap.setup_name_mapping(sid + "-513", idmap.TYPE_GID, users_gid)
@@ -969,7 +1033,7 @@ def setup_samdb_rootdse(samdb, names):
 
 
 def setup_self_join(samdb, admin_session_info, names, fill, machinepass,
-        dnspass, domainsid, next_rid, invocationid,
+        dns_backend, dnspass, domainsid, next_rid, invocationid,
         policyguid, policyguid_dc,
         domainControllerFunctionality, ntdsguid=None, dc_rid=None):
     """Join a host to its own domain."""
@@ -1048,14 +1112,17 @@ def setup_self_join(samdb, admin_session_info, names, fill, machinepass,
 
     samdb.set_session_info(admin_session_info)
 
-    setup_add_ldif(samdb, setup_path("provision_dns_add_samba.ldif"), {
-          "DNSDOMAIN": names.dnsdomain,
-          "DOMAINDN": names.domaindn,
-          "DNSPASS_B64": b64encode(dnspass.encode('utf-16-le')),
-          "HOSTNAME" : names.hostname,
-          "DNSNAME" : '%s.%s' % (
-              names.netbiosname.lower(), names.dnsdomain.lower())
-          })
+    if dns_backend != "SAMBA_INTERNAL":
+        # This is Samba4 specific and should be replaced by the correct
+        # DNS AD-style setup
+        setup_add_ldif(samdb, setup_path("provision_dns_add_samba.ldif"), {
+              "DNSDOMAIN": names.dnsdomain,
+              "DOMAINDN": names.domaindn,
+              "DNSPASS_B64": b64encode(dnspass.encode('utf-16-le')),
+              "HOSTNAME" : names.hostname,
+              "DNSNAME" : '%s.%s' % (
+                  names.netbiosname.lower(), names.dnsdomain.lower())
+              })
 
 
 def getpolicypath(sysvolpath, dnsdomain, guid):
@@ -1143,7 +1210,7 @@ def setup_samdb(path, session_info, provision_backend, lp, names,
 
 
 def fill_samdb(samdb, lp, names, logger, domainsid, domainguid, policyguid,
-        policyguid_dc, fill, adminpass, krbtgtpass, machinepass,
+        policyguid_dc, fill, adminpass, krbtgtpass, machinepass, dns_backend,
         dnspass, invocationid, ntdsguid, serverrole, am_rodc=False,
         dom_for_fun_level=None, schema=None, next_rid=None, dc_rid=None):
 
@@ -1257,6 +1324,14 @@ def fill_samdb(samdb, lp, names, logger, domainsid, domainguid, policyguid,
         # If we are setting up a subdomain, then this has been replicated in, so we don't need to add it
         if fill == FILL_FULL:
             logger.info("Setting up sam.ldb configuration data")
+
+            partitions_descr = b64encode(get_config_partitions_descriptor(domainsid))
+            sites_descr = b64encode(get_config_sites_descriptor(domainsid))
+            ntdsquotas_descr = b64encode(get_config_ntds_quotas_descriptor(domainsid))
+            protected1_descr = b64encode(get_config_delete_protected1_descriptor(domainsid))
+            protected1wd_descr = b64encode(get_config_delete_protected1wd_descriptor(domainsid))
+            protected2_descr = b64encode(get_config_delete_protected2_descriptor(domainsid))
+
             setup_add_ldif(samdb, setup_path("provision_configuration.ldif"), {
                     "CONFIGDN": names.configdn,
                     "NETBIOSNAME": names.netbiosname,
@@ -1268,6 +1343,14 @@ def fill_samdb(samdb, lp, names, logger, domainsid, domainguid, policyguid,
                     "SERVERDN": names.serverdn,
                     "FOREST_FUNCTIONALITY": str(forestFunctionality),
                     "DOMAIN_FUNCTIONALITY": str(domainFunctionality),
+                    "NTDSQUOTAS_DESCRIPTOR": ntdsquotas_descr,
+                    "LOSTANDFOUND_DESCRIPTOR": protected1wd_descr,
+                    "SERVICES_DESCRIPTOR": protected1_descr,
+                    "PHYSICALLOCATIONS_DESCRIPTOR": protected1wd_descr,
+                    "FORESTUPDATES_DESCRIPTOR": protected1wd_descr,
+                    "EXTENDEDRIGHTS_DESCRIPTOR": protected2_descr,
+                    "PARTITIONS_DESCRIPTOR": partitions_descr,
+                    "SITES_DESCRIPTOR": sites_descr,
                     })
 
             logger.info("Setting up display specifiers")
@@ -1278,20 +1361,38 @@ def fill_samdb(samdb, lp, names, logger, domainsid, domainguid, policyguid,
             check_all_substituted(display_specifiers_ldif)
             samdb.add_ldif(display_specifiers_ldif)
 
+            logger.info("Modifying display specifiers")
+            setup_modify_ldif(samdb,
+                setup_path("provision_configuration_modify.ldif"), {
+                "CONFIGDN": names.configdn,
+                "DISPLAYSPECIFIERS_DESCRIPTOR": protected2_descr
+                })
+
         logger.info("Adding users container")
+        users_desc = b64encode(get_domain_users_descriptor(domainsid))
         setup_add_ldif(samdb, setup_path("provision_users_add.ldif"), {
-                "DOMAINDN": names.domaindn})
+                "DOMAINDN": names.domaindn,
+                "USERS_DESCRIPTOR": users_desc
+                })
         logger.info("Modifying users container")
         setup_modify_ldif(samdb, setup_path("provision_users_modify.ldif"), {
                 "DOMAINDN": names.domaindn})
         logger.info("Adding computers container")
+        computers_desc = b64encode(get_domain_computers_descriptor(domainsid))
         setup_add_ldif(samdb, setup_path("provision_computers_add.ldif"), {
-                "DOMAINDN": names.domaindn})
+                "DOMAINDN": names.domaindn,
+                "COMPUTERS_DESCRIPTOR": computers_desc
+                })
         logger.info("Modifying computers container")
         setup_modify_ldif(samdb,
             setup_path("provision_computers_modify.ldif"), {
                 "DOMAINDN": names.domaindn})
         logger.info("Setting up sam.ldb data")
+        infrastructure_desc = b64encode(get_domain_infrastructure_descriptor(domainsid))
+        lostandfound_desc = b64encode(get_domain_delete_protected2_descriptor(domainsid))
+        system_desc = b64encode(get_domain_delete_protected1_descriptor(domainsid))
+        builtin_desc = b64encode(get_domain_builtin_descriptor(domainsid))
+        controllers_desc = b64encode(get_domain_controllers_descriptor(domainsid))
         setup_add_ldif(samdb, setup_path("provision.ldif"), {
             "CREATTIME": str(samba.unix2nttime(int(time.time()))),
             "DOMAINDN": names.domaindn,
@@ -1300,7 +1401,12 @@ def fill_samdb(samdb, lp, names, logger, domainsid, domainguid, policyguid,
             "CONFIGDN": names.configdn,
             "SERVERDN": names.serverdn,
             "RIDAVAILABLESTART": str(next_rid + 600),
-            "POLICYGUID_DC": policyguid_dc
+            "POLICYGUID_DC": policyguid_dc,
+            "INFRASTRUCTURE_DESCRIPTOR": infrastructure_desc,
+            "LOSTANDFOUND_DESCRIPTOR": lostandfound_desc,
+            "SYSTEM_DESCRIPTOR": system_desc,
+            "BUILTIN_DESCRIPTOR": builtin_desc,
+            "DOMAIN_CONTROLLERS_DESCRIPTOR": controllers_desc,
             })
 
         # If we are setting up a subdomain, then this has been replicated in, so we don't need to add it
@@ -1311,8 +1417,10 @@ def fill_samdb(samdb, lp, names, logger, domainsid, domainguid, policyguid,
                     "SCHEMADN": names.schemadn})
 
             logger.info("Setting up well known security principals")
+            protected1wd_descr = b64encode(get_config_delete_protected1wd_descriptor(domainsid))
             setup_add_ldif(samdb, setup_path("provision_well_known_sec_princ.ldif"), {
                 "CONFIGDN": names.configdn,
+                "WELLKNOWNPRINCIPALS_DESCRIPTOR": protected1wd_descr,
                 })
 
         if fill == FILL_FULL or fill == FILL_SUBDOMAIN:
@@ -1331,6 +1439,7 @@ def fill_samdb(samdb, lp, names, logger, domainsid, domainguid, policyguid,
             logger.info("Setting up self join")
             setup_self_join(samdb, admin_session_info, names=names, fill=fill,
                 invocationid=invocationid,
+                dns_backend=dns_backend,
                 dnspass=dnspass,
                 machinepass=machinepass,
                 domainsid=domainsid,
@@ -1359,17 +1468,17 @@ FILL_NT4SYNC = "NT4SYNC"
 FILL_DRS = "DRS"
 SYSVOL_ACL = "O:LAG:BAD:P(A;OICI;0x001f01ff;;;BA)(A;OICI;0x001200a9;;;SO)(A;OICI;0x001f01ff;;;SY)(A;OICI;0x001200a9;;;AU)"
 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_dir_acl(path, acl, lp, domsid, use_ntvfs, passdb):
-    setntacl(lp, path, acl, domsid, use_ntvfs=use_ntvfs, skip_invalid_chown=True, passdb=passdb)
+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):
         for name in files:
             setntacl(lp, os.path.join(root, name), acl, domsid,
-                    use_ntvfs=use_ntvfs, skip_invalid_chown=True, passdb=passdb)
+                    use_ntvfs=use_ntvfs, skip_invalid_chown=True, passdb=passdb, service=service)
         for name in dirs:
             setntacl(lp, os.path.join(root, name), acl, domsid,
-                    use_ntvfs=use_ntvfs, skip_invalid_chown=True, passdb=passdb)
+                    use_ntvfs=use_ntvfs, skip_invalid_chown=True, passdb=passdb, service=service)
 
 
 def set_gpos_acl(sysvol, dnsdomain, domainsid, domaindn, samdb, lp, use_ntvfs, passdb):
@@ -1387,7 +1496,7 @@ def set_gpos_acl(sysvol, dnsdomain, domainsid, domaindn, samdb, lp, use_ntvfs, p
     # 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)
+            use_ntvfs=use_ntvfs, skip_invalid_chown=True, passdb=passdb, service=SYSVOL_SERVICE)
 
     res = samdb.search(base="CN=Policies,CN=System,%s"%(domaindn),
                         attrs=["cn", "nTSecurityDescriptor"],
@@ -1397,7 +1506,7 @@ def set_gpos_acl(sysvol, dnsdomain, domainsid, domaindn, samdb, lp, use_ntvfs, p
         acl = ndr_unpack(security.descriptor,
                          str(policy["nTSecurityDescriptor"])).as_sddl()
         policy_path = getpolicypath(sysvol, dnsdomain, str(policy["cn"]))
-        set_dir_acl(policy_path, dsacl2fsacl(acl, str(domainsid)), lp,
+        set_dir_acl(policy_path, dsacl2fsacl(acl, domainsid), lp,
                     str(domainsid), use_ntvfs,
                     passdb=passdb)
 
@@ -1451,16 +1560,22 @@ 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)
+    setntacl(lp,sysvol, SYSVOL_ACL, str(domainsid), use_ntvfs=use_ntvfs,
+             skip_invalid_chown=True, passdb=s4_passdb,
+             service=SYSVOL_SERVICE)
     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)
+            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)
         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)
+            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 acls on Policy folder and policies folders
     set_gpos_acl(sysvol, dnsdomain, domainsid, domaindn, samdb, lp, use_ntvfs, passdb=s4_passdb)
@@ -1472,22 +1587,24 @@ def acl_type(direct_db_access):
         return "VFS"
 
 def check_dir_acl(path, acl, lp, domainsid, direct_db_access):
-    fsacl = getntacl(lp, path, direct_db_access=direct_db_access)
+    fsacl = getntacl(lp, path, direct_db_access=direct_db_access, service=SYSVOL_SERVICE)
     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)
+            fsacl = getntacl(lp, os.path.join(root, name),
+                             direct_db_access=direct_db_access, service=SYSVOL_SERVICE)
             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_sddl, acl))
 
-        for name in files:
-            fsacl = getntacl(lp, os.path.join(root, name), direct_db_access=direct_db_access)
+        for name in dirs:
+            fsacl = getntacl(lp, os.path.join(root, name),
+                             direct_db_access=direct_db_access, service=SYSVOL_SERVICE)
             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)
@@ -1510,7 +1627,8 @@ def check_gpos_acl(sysvol, dnsdomain, domainsid, domaindn, samdb, lp,
 
     # 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)
+    fsacl = getntacl(lp, root_policy_path,
+                     direct_db_access=direct_db_access, service=SYSVOL_SERVICE)
     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)
@@ -1524,7 +1642,7 @@ def check_gpos_acl(sysvol, dnsdomain, domainsid, domaindn, samdb, lp,
         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,
+        check_dir_acl(policy_path, dsacl2fsacl(acl, domainsid), lp,
                       domainsid, direct_db_access)
 
 
@@ -1561,10 +1679,11 @@ def checksysvolacl(samdb, netlogon, sysvol, domainsid, dnsdomain, domaindn,
     if domain_info["dns_domain"].upper() != dnsdomain.upper():
         raise ProvisioningError('Realm as seen by pdb_samba_dsdb [%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)
+    # Ensure we can read this directly, and via the smbd VFS
     for direct_db_access in [True, False]:
+        # Check the SYSVOL_ACL on the sysvol folder and subfolder (first level)
         for dir_path in [os.path.join(sysvol, dnsdomain), netlogon]:
-            fsacl = getntacl(lp, dir_path, direct_db_access=direct_db_access)
+            fsacl = getntacl(lp, dir_path, direct_db_access=direct_db_access, service=SYSVOL_SERVICE)
             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)
@@ -1603,8 +1722,8 @@ def provision_fill(samdb, secrets_ldb, logger, names, paths,
                    next_rid=1000, dc_rid=None, adminpass=None, krbtgtpass=None,
                    domainguid=None, policyguid=None, policyguid_dc=None,
                    invocationid=None, machinepass=None, ntdsguid=None,
-                   dns_backend=None,
-                   dnspass=None, serverrole=None, dom_for_fun_level=None,
+                   dns_backend=None, dnspass=None,
+                   serverrole=None, dom_for_fun_level=None,
                    am_rodc=False, lp=None, use_ntvfs=False, skip_sysvolacl=False):
     # create/adapt the group policy GUIDs
     # Default GUID for default policy are described at
@@ -1632,7 +1751,8 @@ def provision_fill(samdb, secrets_ldb, logger, names, paths,
                    policyguid=policyguid, policyguid_dc=policyguid_dc,
                    fill=samdb_fill, adminpass=adminpass, krbtgtpass=krbtgtpass,
                    invocationid=invocationid, machinepass=machinepass,
-                   dnspass=dnspass, ntdsguid=ntdsguid, serverrole=serverrole,
+                   dns_backend=dns_backend, dnspass=dnspass,
+                   ntdsguid=ntdsguid, serverrole=serverrole,
                    dom_for_fun_level=dom_for_fun_level, am_rodc=am_rodc,
                    next_rid=next_rid, dc_rid=dc_rid)
 
@@ -1644,7 +1764,7 @@ def provision_fill(samdb, secrets_ldb, logger, names, paths,
                            policyguid_dc)
         if not skip_sysvolacl:
             setsysvolacl(samdb, paths.netlogon, paths.sysvol, paths.root_uid,
-                         paths.wheel_gid, domainsid, names.dnsdomain,
+                         paths.root_gid, domainsid, names.dnsdomain,
                          names.domaindn, lp, use_ntvfs)
         else:
             logger.info("Setting acl on sysvol skipped")
@@ -1776,7 +1896,7 @@ def provision(logger, session_info, credentials, smbconf=None,
         krbtgtpass=None, domainguid=None, policyguid=None, policyguid_dc=None,
         dns_backend=None, dns_forwarder=None, dnspass=None,
         invocationid=None, machinepass=None, ntdsguid=None,
-        root=None, nobody=None, users=None, wheel=None, backup=None, aci=None,
+        root=None, nobody=None, users=None, backup=None, aci=None,
         serverrole=None, dom_for_fun_level=None, backend_type=None,
         sitename=None, ol_mmr_urls=None, ol_olc=None, slapd_path="/bin/false",
         useeadb=False, am_rodc=False, lp=None, use_ntvfs=False,
@@ -1806,10 +1926,8 @@ def provision(logger, session_info, credentials, smbconf=None,
     root_uid = findnss_uid([root or "root"])
     nobody_uid = findnss_uid([nobody or "nobody"])
     users_gid = findnss_gid([users or "users", 'users', 'other', 'staff'])
-    if wheel is None:
-        wheel_gid = findnss_gid(["wheel", "adm"])
-    else:
-        wheel_gid = findnss_gid([wheel])
+    root_gid = pwd.getpwuid(root_uid).pw_gid
+
     try:
         bind_gid = findnss_gid(["bind", "named"])
     except KeyError:
@@ -1872,7 +1990,7 @@ def provision(logger, session_info, credentials, smbconf=None,
 
     paths.bind_gid = bind_gid
     paths.root_uid = root_uid;
-    paths.wheel_gid = wheel_gid
+    paths.root_gid = root_gid
 
     if hostip is None:
         logger.info("Looking up IPv4 addresses")
@@ -1923,7 +2041,7 @@ def provision(logger, session_info, credentials, smbconf=None,
         file = tempfile.NamedTemporaryFile(dir=os.path.abspath(paths.sysvol))
         try:
             try:
-                smbd.set_simple_acl(file.name, 0755, wheel_gid)
+                smbd.set_simple_acl(file.name, 0755, root_gid)
             except Exception:
                 if not smbd.have_posix_acls():
                     # This clue is only strictly correct for RPM and
@@ -1933,7 +2051,7 @@ def provision(logger, session_info, credentials, smbconf=None,
 
                 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)
+                smbd.chown(file.name, root_uid, root_gid)
             except Exception:
                 raise ProvisioningError("Unable to chown a file on your filesystem.  You may not be running provision as root.")
         finally:
@@ -1997,7 +2115,7 @@ def provision(logger, session_info, credentials, smbconf=None,
 
         setup_name_mappings(idmap, sid=str(domainsid),
                             root_uid=root_uid, nobody_uid=nobody_uid,
-                            users_gid=users_gid, wheel_gid=wheel_gid)
+                            users_gid=users_gid, root_gid=root_gid)
 
         logger.info("Setting up SAM db")
         samdb = setup_samdb(paths.samdb, session_info,
@@ -2047,8 +2165,6 @@ def provision(logger, session_info, credentials, smbconf=None,
         backend_result = provision_backend.post_setup()
         provision_backend.shutdown()
 
-        create_phpldapadmin_config(paths.phpldapadminconfig,
-                                   ldapi_url)
     except:
         secrets_ldb.transaction_cancel()
         raise
@@ -2099,7 +2215,7 @@ def provision_become_dc(smbconf=None, targetdir=None,
         serverdn=None, domain=None, hostname=None, domainsid=None,
         adminpass=None, krbtgtpass=None, domainguid=None, policyguid=None,
         policyguid_dc=None, invocationid=None, machinepass=None, dnspass=None,
-        dns_backend=None, root=None, nobody=None, users=None, wheel=None,
+        dns_backend=None, root=None, nobody=None, users=None,
         backup=None, serverrole=None, ldap_backend=None,
         ldap_backend_type=None, sitename=None, debuglevel=1, use_ntvfs=False):
 
@@ -2119,15 +2235,6 @@ def provision_become_dc(smbconf=None, targetdir=None,
     return res
 
 
-def create_phpldapadmin_config(path, ldapi_uri):
-    """Create a PHP LDAP admin configuration file.
-
-    :param path: Path to write the configuration to.
-    """
-    setup_file(setup_path("phpldapadmin-config.php"), path,
-            {"S4_LDAPI_URI": ldapi_uri})
-
-
 def create_krb5_conf(path, dnsdomain, hostname, realm):
     """Write out a file containing zone statements suitable for inclusion in a
     named.conf file (including GSS-TSIG configuration).