provision: Fallback to assumption root-UID==zero
[metze/samba/wip.git] / python / samba / provision / __init__.py
index e5f0a02ca78d08a5423e20e63a712868f12a2cb5..14ab41be67005ce9e4e4a6fbd1b0cfce605c971a 100644 (file)
@@ -40,7 +40,6 @@ import logging
 import time
 import uuid
 import socket
-import string
 import tempfile
 import samba.dsdb
 
@@ -78,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,
@@ -220,8 +218,8 @@ def find_provision_key_parameters(samdb, secretsdb, idmapdb, paths, smbconf,
                                   "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)"
@@ -229,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:
@@ -307,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
 
@@ -366,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))
@@ -542,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.
 
@@ -616,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()
 
@@ -1193,11 +1203,16 @@ 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,
@@ -1412,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))
@@ -1751,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))
@@ -1760,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))
@@ -1849,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:
@@ -2139,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
@@ -2238,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,