provision: Fallback to assumption root-UID==zero
[metze/samba/wip.git] / python / samba / provision / __init__.py
index 4dc6a5a75d98c1319d4a893190e026ef1f03fae4..14ab41be67005ce9e4e4a6fbd1b0cfce605c971a 100644 (file)
@@ -27,6 +27,8 @@
 __docformat__ = "restructuredText"
 
 from samba.compat import urllib_quote
+from samba.compat import string_types
+from samba.compat import binary_type
 from base64 import b64encode
 import errno
 import os
@@ -38,7 +40,6 @@ import logging
 import time
 import uuid
 import socket
-import string
 import tempfile
 import samba.dsdb
 
@@ -76,7 +77,6 @@ from samba.ms_display_specifiers import read_ms_ldif
 from samba.ntacls import setntacl, getntacl, dsacl2fsacl
 from samba.ndr import ndr_pack, ndr_unpack
 from samba.provision.backend import (
-    ExistingBackend,
     FDSBackend,
     LDBBackend,
     OpenLDAPBackend,
@@ -204,9 +204,9 @@ def find_provision_key_parameters(samdb, secretsdb, idmapdb, paths, smbconf,
     # netbiosname
     # Get the netbiosname first (could be obtained from smb.conf in theory)
     res = secretsdb.search(expression="(flatname=%s)" %
-                           names.domain,base="CN=Primary Domains",
+                           names.domain, base="CN=Primary Domains",
                            scope=ldb.SCOPE_SUBTREE, attrs=["sAMAccountName"])
-    names.netbiosname = str(res[0]["sAMAccountName"]).replace("$","")
+    names.netbiosname = str(res[0]["sAMAccountName"]).replace("$", "")
 
     names.smbconf = smbconf
 
@@ -215,11 +215,11 @@ 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"][0]
-    names.schemadn = current[0]["schemaNamingContext"][0]
+    names.configdn = str(current[0]["configurationNamingContext"][0])
+    names.schemadn = str(current[0]["schemaNamingContext"][0])
     if not (ldb.Dn(samdb, basedn) == (ldb.Dn(samdb,
                                              current[0]["defaultNamingContext"][0].decode('utf8')))):
         raise ProvisioningError(("basedn in %s (%s) and from %s (%s)"
@@ -227,14 +227,14 @@ def find_provision_key_parameters(samdb, secretsdb, idmapdb, paths, smbconf,
                                                           str(current[0]["defaultNamingContext"][0].decode('utf8')),
                                                           paths.smbconf, basedn)))
 
-    names.domaindn = current[0]["defaultNamingContext"][0]
-    names.rootdn = current[0]["rootDomainNamingContext"][0]
+    names.domaindn = str(current[0]["defaultNamingContext"][0])
+    names.rootdn = str(current[0]["rootDomainNamingContext"][0])
     names.ncs = current[0]["namingContexts"]
     names.dnsforestdn = None
     names.dnsdomaindn = None
 
     for i in range(0, len(names.ncs)):
-        nc = names.ncs[i]
+        nc = str(names.ncs[i])
 
         dnsforestdn = "DC=ForestDnsZones,%s" % (str(names.rootdn))
         if nc == dnsforestdn:
@@ -248,7 +248,7 @@ def find_provision_key_parameters(samdb, secretsdb, idmapdb, paths, smbconf,
 
     # default site name
     res3 = samdb.search(expression="(objectClass=site)",
-                        base="CN=Sites," + names.configdn, scope=ldb.SCOPE_ONELEVEL, attrs=["cn"])
+                        base="CN=Sites," + str(names.configdn), scope=ldb.SCOPE_ONELEVEL, attrs=["cn"])
     names.sitename = str(res3[0]["cn"])
 
     # dns hostname and server dn
@@ -275,7 +275,7 @@ def find_provision_key_parameters(samdb, secretsdb, idmapdb, paths, smbconf,
     # domain guid/sid
     res6 = samdb.search(expression="(objectClass=*)", base=basedn,
                         scope=ldb.SCOPE_BASE, attrs=["objectGUID",
-                                                     "objectSid","msDS-Behavior-Version"])
+                                                     "objectSid", "msDS-Behavior-Version"])
     names.domainguid = str(ndr_unpack(misc.GUID, res6[0]["objectGUID"][0]))
     names.domainsid = ndr_unpack(security.dom_sid, res6[0]["objectSid"][0])
     names.forestsid = ndr_unpack(security.dom_sid, res6[0]["objectSid"][0])
@@ -288,15 +288,15 @@ def find_provision_key_parameters(samdb, secretsdb, idmapdb, paths, smbconf,
     # policy guid
     res7 = samdb.search(expression="(name={%s})" % DEFAULT_POLICY_GUID,
                         base="CN=Policies,CN=System," + basedn,
-                        scope=ldb.SCOPE_ONELEVEL, attrs=["cn","displayName"])
-    names.policyid = str(res7[0]["cn"]).replace("{","").replace("}","")
+                        scope=ldb.SCOPE_ONELEVEL, attrs=["cn", "displayName"])
+    names.policyid = str(res7[0]["cn"]).replace("{", "").replace("}", "")
     # dc policy guid
     res8 = samdb.search(expression="(name={%s})" % DEFAULT_DC_POLICY_GUID,
                         base="CN=Policies,CN=System," + basedn,
                         scope=ldb.SCOPE_ONELEVEL,
-                        attrs=["cn","displayName"])
+                        attrs=["cn", "displayName"])
     if len(res8) == 1:
-        names.policyid_dc = str(res8[0]["cn"]).replace("{","").replace("}","")
+        names.policyid_dc = str(res8[0]["cn"]).replace("{", "").replace("}", "")
     else:
         names.policyid_dc = None
 
@@ -305,8 +305,8 @@ def find_provision_key_parameters(samdb, secretsdb, idmapdb, paths, smbconf,
                           attrs=["xidNumber", "type"])
     if len(res9) != 1:
         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]
+    if str(res9[0]["type"][0]) == "ID_TYPE_BOTH":
+        names.root_gid = int(res9[0]["xidNumber"][0])
     else:
         names.root_gid = pwd.getpwuid(int(res9[0]["xidNumber"][0])).pw_gid
 
@@ -364,8 +364,8 @@ def update_provision_usn(samdb, low, high, id, replace=False):
                              scope=ldb.SCOPE_BASE,
                              attrs=[LAST_PROVISION_USN_ATTRIBUTE, "dn"])
         for e in entry[0][LAST_PROVISION_USN_ATTRIBUTE]:
-            if not re.search(';', e):
-                e = "%s;%s" % (e, id)
+            if not re.search(';', str(e)):
+                e = "%s;%s" % (str(e), id)
             tab.append(str(e))
 
     tab.append("%s-%s;%s" % (low, high, id))
@@ -407,7 +407,7 @@ def set_provision_usn(samdb, low, high, id):
     samdb.add(delta)
 
 
-def get_max_usn(samdb,basedn):
+def get_max_usn(samdb, basedn):
     """ This function return the biggest USN present in the provision
 
     :param samdb: A LDB object pointing to the sam.ldb
@@ -415,8 +415,8 @@ def get_max_usn(samdb,basedn):
                     (ie. DC=foo, DC=bar)
     :return: The biggest USN in the provision"""
 
-    res = samdb.search(expression="objectClass=*",base=basedn,
-                       scope=ldb.SCOPE_SUBTREE,attrs=["uSNChanged"],
+    res = samdb.search(expression="objectClass=*", base=basedn,
+                       scope=ldb.SCOPE_SUBTREE, attrs=["uSNChanged"],
                        controls=["search_options:1:2",
                                  "server_sort:1:1:uSNChanged",
                                  "paged_results:1:1"])
@@ -540,6 +540,16 @@ def findnss_gid(names):
     return findnss(grp.getgrnam, names)[2]
 
 
+def get_root_uid(root, logger):
+    try:
+        root_uid = findnss_uid(root)
+    except KeyError as e:
+        logger.info(e)
+        logger.info("Assuming root user has UID zero")
+        root_uid = 0
+    return root_uid
+
+
 def provision_paths_from_lp(lp, dnsdomain):
     """Set the default paths for provisioning.
 
@@ -614,7 +624,9 @@ def guess_names(lp=None, hostname=None, domain=None, dnsdomain=None,
     if dnsdomain is None:
         dnsdomain = lp.get("realm")
         if dnsdomain is None or dnsdomain == "":
-            raise ProvisioningError("guess_names: 'realm' not specified in supplied %s!", lp.configfile)
+            raise ProvisioningError(
+                "guess_names: 'realm' not specified in supplied %s!" %
+                lp.configfile)
 
     dnsdomain = dnsdomain.lower()
 
@@ -709,6 +721,7 @@ def guess_names(lp=None, hostname=None, domain=None, dnsdomain=None,
 
     return names
 
+
 def make_smbconf(smbconf, hostname, domain, realm, targetdir,
                  serverrole=None, eadb=False, use_ntvfs=False, lp=None,
                  global_param=None):
@@ -739,7 +752,7 @@ def make_smbconf(smbconf, hostname, domain, realm, targetdir,
 
     if lp is None:
         lp = samba.param.LoadParm()
-    #Load non-existent file
+    # Load non-existent file
     if os.path.exists(smbconf):
         lp.load(smbconf)
 
@@ -756,7 +769,7 @@ def make_smbconf(smbconf, hostname, domain, realm, targetdir,
         global_settings["binddns dir"] = os.path.abspath(os.path.join(targetdir, "bind-dns"))
 
         lp.set("lock dir", os.path.abspath(targetdir))
-        lp.set("state directory",  global_settings["state directory"])
+        lp.set("state directory", global_settings["state directory"])
         lp.set("cache directory", global_settings["cache directory"])
         lp.set("binddns dir", global_settings["binddns dir"])
 
@@ -882,7 +895,6 @@ def setup_samdb_partitions(samdb_path, logger, lp, session_info,
                 "BACKEND_STORE": backend_store_line
         })
 
-
         setup_add_ldif(samdb, setup_path("provision_init.ldif"), {
                 "BACKEND_TYPE": provision_backend.type,
                 "SERVER_ROLE": serverrole,
@@ -1030,16 +1042,16 @@ def setup_secretsdb(paths, session_info, backend_credentials, lp):
             if backend_credentials.get_bind_dn() is not None:
                 setup_add_ldif(secrets_ldb,
                                setup_path("secrets_simple_ldap.ldif"), {
-                        "LDAPMANAGERDN": backend_credentials.get_bind_dn(),
-                        "LDAPMANAGERPASS_B64": b64encode(backend_credentials.get_password()).decode('utf8')
-                    })
+                                   "LDAPMANAGERDN": backend_credentials.get_bind_dn(),
+                                   "LDAPMANAGERPASS_B64": b64encode(backend_credentials.get_password()).decode('utf8')
+                               })
             else:
                 setup_add_ldif(secrets_ldb,
                                setup_path("secrets_sasl_ldap.ldif"), {
-                        "LDAPADMINUSER": backend_credentials.get_username(),
-                        "LDAPADMINREALM": backend_credentials.get_realm(),
-                        "LDAPADMINPASS_B64": b64encode(backend_credentials.get_password()).decode('utf8')
-                    })
+                                   "LDAPADMINUSER": backend_credentials.get_username(),
+                                   "LDAPADMINREALM": backend_credentials.get_realm(),
+                                   "LDAPADMINPASS_B64": b64encode(backend_credentials.get_password()).decode('utf8')
+                               })
     except:
         secrets_ldb.transaction_cancel()
         raise
@@ -1061,6 +1073,7 @@ def setup_privileges(path, session_info, lp):
     privilege_ldb.erase()
     privilege_ldb.load_ldif_file_add(setup_path("provision_privilege.ldif"))
 
+
 def setup_encrypted_secrets_key(path):
     """Setup the encrypted secrets key file.
 
@@ -1081,7 +1094,7 @@ def setup_encrypted_secrets_key(path):
     finally:
         os.umask(umask_original)
 
-    with os.fdopen(fd, 'w') as f:
+    with os.fdopen(fd, 'wb') as f:
         key = samba.generate_random_bytes(16)
         f.write(key)
 
@@ -1140,7 +1153,7 @@ def setup_self_join(samdb, admin_session_info, names, fill, machinepass,
     """Join a host to its own domain."""
     assert isinstance(invocationid, str)
     if ntdsguid is not None:
-        ntdsguid_line = "objectGUID: %s\n"%ntdsguid
+        ntdsguid_line = "objectGUID: %s\n" % ntdsguid
     else:
         ntdsguid_line = ""
 
@@ -1190,15 +1203,20 @@ def setup_self_join(samdb, admin_session_info, names, fill, machinepass,
                 "DOMAIN_CONTROLLER_FUNCTIONALITY": str(
                     domainControllerFunctionality)})
 
-    # Setup fSMORoleOwner entries to point at the newly created DC entry
+        # Setup fSMORoleOwner entries to point at the newly created DC entry
+        setup_modify_ldif(samdb,
+                          setup_path("provision_self_join_modify_schema.ldif"), {
+                              "SCHEMADN": names.schemadn,
+                              "SERVERDN": names.serverdn,
+                          },
+                          controls=["provision:0", "relax:0"])
         setup_modify_ldif(samdb,
                           setup_path("provision_self_join_modify_config.ldif"), {
-                "CONFIGDN": names.configdn,
-                "SCHEMADN": names.schemadn,
-                "DEFAULTSITE": names.sitename,
-                "NETBIOSNAME": names.netbiosname,
-                "SERVERDN": names.serverdn,
-            })
+                              "CONFIGDN": names.configdn,
+                              "DEFAULTSITE": names.sitename,
+                              "NETBIOSNAME": names.netbiosname,
+                              "SERVERDN": names.serverdn,
+                          })
 
     system_session_info = system_session()
     samdb.set_session_info(system_session_info)
@@ -1264,10 +1282,10 @@ def create_default_gpo(sysvolpath, dnsdomain, policyguid, policyguid_dc):
     :param policyguid: GUID of the default domain policy
     :param policyguid_dc: GUID of the default domain controler policy
     """
-    policy_path = getpolicypath(sysvolpath,dnsdomain,policyguid)
+    policy_path = getpolicypath(sysvolpath, dnsdomain, policyguid)
     create_gpo_struct(policy_path)
 
-    policy_path = getpolicypath(sysvolpath,dnsdomain,policyguid_dc)
+    policy_path = getpolicypath(sysvolpath, dnsdomain, policyguid_dc)
     create_gpo_struct(policy_path)
 
 
@@ -1409,16 +1427,20 @@ def fill_samdb(samdb, lp, names, logger, policyguid,
 
         # The LDIF here was created when the Schema object was constructed
         ignore_checks_oid = "local_oid:%s:0" % samba.dsdb.DSDB_CONTROL_SKIP_DUPLICATES_CHECK_OID
+        schema_controls = [
+            "provision:0",
+            "relax:0",
+            ignore_checks_oid
+        ]
+
         logger.info("Setting up sam.ldb schema")
-        samdb.add_ldif(schema.schema_dn_add,
-                       controls=["relax:0", ignore_checks_oid])
-        samdb.modify_ldif(schema.schema_dn_modify,
-                          controls=[ignore_checks_oid])
+        samdb.add_ldif(schema.schema_dn_add, controls=schema_controls)
+        samdb.modify_ldif(schema.schema_dn_modify, controls=schema_controls)
         samdb.write_prefixes_from_schema()
-        samdb.add_ldif(schema.schema_data, controls=["relax:0", ignore_checks_oid])
+        samdb.add_ldif(schema.schema_data, controls=schema_controls)
         setup_add_ldif(samdb, setup_path("aggregate_schema.ldif"),
                        {"SCHEMADN": names.schemadn},
-                       controls=["relax:0", ignore_checks_oid])
+                       controls=schema_controls)
 
     # Now register this container in the root of the forest
     msg = ldb.Message(ldb.Dn(samdb, names.domaindn))
@@ -1467,7 +1489,7 @@ def fill_samdb(samdb, lp, names, logger, policyguid,
 
         setup_add_ldif(samdb, setup_path("extended-rights.ldif"), {
                 "CONFIGDN": names.configdn,
-                "INC2012" : incl_2012,
+                "INC2012": incl_2012,
                 })
 
         logger.info("Setting up display specifiers")
@@ -1481,9 +1503,9 @@ def fill_samdb(samdb, lp, names, logger, policyguid,
         logger.info("Modifying display specifiers and extended rights")
         setup_modify_ldif(samdb,
                           setup_path("provision_configuration_modify.ldif"), {
-                "CONFIGDN": names.configdn,
-                "DISPLAYSPECIFIERS_DESCRIPTOR": protected2_descr
-            })
+                              "CONFIGDN": names.configdn,
+                              "DISPLAYSPECIFIERS_DESCRIPTOR": protected2_descr
+                          })
 
     logger.info("Adding users container")
     users_desc = b64encode(get_domain_users_descriptor(names.domainsid)).decode('utf8')
@@ -1503,7 +1525,7 @@ def fill_samdb(samdb, lp, names, logger, policyguid,
     logger.info("Modifying computers container")
     setup_modify_ldif(samdb,
                       setup_path("provision_computers_modify.ldif"), {
-            "DOMAINDN": names.domaindn})
+                          "DOMAINDN": names.domaindn})
     logger.info("Setting up sam.ldb data")
     infrastructure_desc = b64encode(get_domain_infrastructure_descriptor(names.domainsid)).decode('utf8')
     lostandfound_desc = b64encode(get_domain_delete_protected2_descriptor(names.domainsid)).decode('utf8')
@@ -1572,8 +1594,8 @@ def fill_samdb(samdb, lp, names, logger, policyguid,
 
         ntds_dn = "CN=NTDS Settings,%s" % names.serverdn
         names.ntdsguid = samdb.searchone(basedn=ntds_dn,
-                                         attribute="objectGUID", expression="", scope=ldb.SCOPE_BASE)
-        assert isinstance(names.ntdsguid, str)
+                                         attribute="objectGUID", expression="", scope=ldb.SCOPE_BASE).decode('utf8')
+        assert isinstance(names.ntdsguid, string_types)
 
     return samdb
 
@@ -1582,6 +1604,7 @@ 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_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):
@@ -1610,13 +1633,13 @@ def set_gpos_acl(sysvol, dnsdomain, domainsid, domaindn, samdb, lp, use_ntvfs, p
     setntacl(lp, root_policy_path, POLICIES_ACL, str(domainsid),
              use_ntvfs=use_ntvfs, skip_invalid_chown=True, passdb=passdb, service=SYSVOL_SERVICE)
 
-    res = samdb.search(base="CN=Policies,CN=System,%s"%(domaindn),
+    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["nTSecurityDescriptor"][0]).as_sddl()
         policy_path = getpolicypath(sysvol, dnsdomain, str(policy["cn"]))
         set_dir_acl(policy_path, dsacl2fsacl(acl, domainsid), lp,
                     str(domainsid), use_ntvfs,
@@ -1687,7 +1710,6 @@ def setsysvolacl(samdb, netlogon, sysvol, uid, gid, domainsid, dnsdomain,
         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()))
 
-
     try:
         if use_ntvfs:
             os.chown(sysvol, -1, gid)
@@ -1729,12 +1751,14 @@ def setsysvolacl(samdb, netlogon, sysvol, uid, gid, domainsid, dnsdomain,
     # Set acls on Policy folder and policies folders
     set_gpos_acl(sysvol, dnsdomain, domainsid, domaindn, samdb, lp, use_ntvfs, passdb=s4_passdb)
 
+
 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, service=SYSVOL_SERVICE)
     fsacl_sddl = fsacl.as_sddl(domainsid)
@@ -1746,7 +1770,9 @@ def check_dir_acl(path, acl, lp, domainsid, 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)))
+                raise ProvisioningError('%s ACL on GPO file %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))
@@ -1755,7 +1781,9 @@ def check_dir_acl(path, acl, lp, domainsid, 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 directory %s %s not found!' % (acl_type(direct_db_access), os.path.join(root, name)))
+                raise ProvisioningError('%s ACL on GPO directory %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_sddl, acl))
@@ -1783,13 +1811,13 @@ def check_gpos_acl(sysvol, dnsdomain, domainsid, domaindn, samdb, lp,
     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), root_policy_path, fsacl_sddl, fsacl))
-    res = samdb.search(base="CN=Policies,CN=System,%s"%(domaindn),
+    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["nTSecurityDescriptor"][0]).as_sddl()
         policy_path = getpolicypath(sysvol, dnsdomain, str(policy["cn"]))
         check_dir_acl(policy_path, dsacl2fsacl(acl, domainsid), lp,
                       domainsid, direct_db_access)
@@ -1844,9 +1872,9 @@ def checksysvolacl(samdb, netlogon, sysvol, domainsid, dnsdomain, domaindn,
                        direct_db_access)
 
 
-def interface_ips_v4(lp):
+def interface_ips_v4(lp, all_interfaces=False):
     """return only IPv4 IPs"""
-    ips = samba.interface_ips(lp, False)
+    ips = samba.interface_ips(lp, all_interfaces)
     ret = []
     for i in ips:
         if i.find(':') == -1:
@@ -1961,8 +1989,8 @@ def provision_fill(samdb, secrets_ldb, logger, names, paths,
                      backend_store=backend_store)
 
         domainguid = samdb.searchone(basedn=samdb.get_default_basedn(),
-                                     attribute="objectGUID")
-        assert isinstance(domainguid, str)
+                                     attribute="objectGUID").decode('utf8')
+        assert isinstance(domainguid, string_types)
 
     lastProvisionUSNs = get_last_provision_usn(samdb)
     maxUSN = get_max_usn(samdb, str(names.rootdn))
@@ -2053,6 +2081,7 @@ def provision_fake_ypserver(logger, samdb, domaindn, netbiosname, nisdomain,
     else:
         samdb.transaction_commit()
 
+
 def directory_create_or_exists(path, mode=0o755):
     if not os.path.exists(path):
         try:
@@ -2063,6 +2092,7 @@ def directory_create_or_exists(path, mode=0o755):
             else:
                 raise ProvisioningError("Failed to create directory %s: %s" % (path, e.strerror))
 
+
 def determine_host_ip(logger, lp, hostip=None):
     if hostip is None:
         logger.info("Looking up IPv4 addresses")
@@ -2079,6 +2109,7 @@ def determine_host_ip(logger, lp, hostip=None):
 
     return hostip
 
+
 def determine_host_ip6(logger, lp, hostip6=None):
     if hostip6 is None:
         logger.info("Looking up IPv6 addresses")
@@ -2092,6 +2123,7 @@ def determine_host_ip6(logger, lp, hostip6=None):
 
     return hostip6
 
+
 def provision(logger, session_info, smbconf=None,
               targetdir=None, samdb_fill=FILL_FULL, realm=None, rootdn=None,
               domaindn=None, schemadn=None, configdn=None, serverdn=None,
@@ -2130,7 +2162,7 @@ def provision(logger, session_info, smbconf=None,
     if domainsid is None:
         domainsid = security.random_sid()
 
-    root_uid = findnss_uid([root or "root"])
+    root_uid = get_root_uid([root or "root"], logger)
     nobody_uid = findnss_uid([nobody or "nobody"])
     users_gid = findnss_gid([users or "users", 'users', 'other', 'staff'])
     root_gid = pwd.getpwuid(root_uid).pw_gid
@@ -2196,7 +2228,7 @@ def provision(logger, session_info, smbconf=None,
     paths = provision_paths_from_lp(lp, names.dnsdomain)
 
     paths.bind_gid = bind_gid
-    paths.root_uid = root_uid;
+    paths.root_uid = root_uid
     paths.root_gid = root_gid
 
     hostip = determine_host_ip(logger, lp, hostip)
@@ -2229,13 +2261,6 @@ def provision(logger, session_info, smbconf=None,
         provision_backend = LDBBackend(backend_type, paths=paths,
                                        lp=lp,
                                        names=names, logger=logger)
-    elif backend_type == "existing":
-        # If support for this is ever added back, then the URI will need to be
-        # specified again
-        provision_backend = ExistingBackend(backend_type, paths=paths,
-                                            lp=lp,
-                                            names=names, logger=logger,
-                                            ldap_backend_forced_uri=ldap_backend_forced_uri)
     elif backend_type == "fedora-ds":
         provision_backend = FDSBackend(backend_type, paths=paths,
                                        lp=lp,
@@ -2305,7 +2330,8 @@ def provision(logger, session_info, smbconf=None,
             adminpass = samba.generate_random_password(12, 32)
             adminpass_generated = True
         else:
-            adminpass = unicode(adminpass, 'utf-8')
+            if isinstance(adminpass, binary_type):
+                adminpass = adminpass.decode('utf-8')
             adminpass_generated = False
 
         if samdb_fill == FILL_FULL: