Revert "TODO... s4:scripting/python: add support for utf-8 passwords from the command...
[metze/samba/wip.git] / python / samba / provision / __init__.py
index 151444d156e825842d95c967f5638296641b0ee9..b36a7d2a7c9cd525cae2551f4c273426d52104a0 100644 (file)
@@ -164,6 +164,9 @@ class ProvisionNames(object):
         self.hostname = None
         self.sitename = None
         self.smbconf = None
+        self.domainsid = None
+        self.forestsid = None
+        self.domainguid = None
         self.name_map = {}
 
 
@@ -240,8 +243,11 @@ def find_provision_key_parameters(samdb, secretsdb, idmapdb, paths, smbconf,
 
     # dns hostname and server dn
     res4 = samdb.search(expression="(CN=%s)" % names.netbiosname,
-                            base="OU=Domain Controllers,%s" % basedn,
-                            scope=ldb.SCOPE_ONELEVEL, attrs=["dNSHostName"])
+                        base="OU=Domain Controllers,%s" % basedn,
+                        scope=ldb.SCOPE_ONELEVEL, attrs=["dNSHostName"])
+    if len(res4) == 0:
+        raise ProvisioningError("Unable to find DC called CN=%s under OU=Domain Controllers,%s" % (names.netbiosname, basedn))
+
     names.hostname = str(res4[0]["dNSHostName"]).replace("." + names.dnsdomain, "")
 
     server_res = samdb.search(expression="serverReference=%s" % res4[0].dn,
@@ -262,6 +268,7 @@ def find_provision_key_parameters(samdb, secretsdb, idmapdb, paths, smbconf,
                 "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])
     if res6[0].get("msDS-Behavior-Version") is None or \
         int(res6[0]["msDS-Behavior-Version"][0]) < DS_DOMAIN_FUNCTION_2000:
         names.domainlevel = DS_DOMAIN_FUNCTION_2000
@@ -269,16 +276,15 @@ def find_provision_key_parameters(samdb, secretsdb, idmapdb, paths, smbconf,
         names.domainlevel = int(res6[0]["msDS-Behavior-Version"][0])
 
     # policy guid
-    res7 = samdb.search(expression="(displayName=Default Domain Policy)",
+    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("}","")
     # dc policy guid
-    res8 = samdb.search(expression="(displayName=Default Domain Controllers"
-                                   " Policy)",
-                            base="CN=Policies,CN=System," + basedn,
-                            scope=ldb.SCOPE_ONELEVEL,
-                            attrs=["cn","displayName"])
+    res8 = samdb.search(expression="(name={%s})" % DEFAULT_DC_POLICY_GUID,
+                        base="CN=Policies,CN=System," + basedn,
+                        scope=ldb.SCOPE_ONELEVEL,
+                        attrs=["cn","displayName"])
     if len(res8) == 1:
         names.policyid_dc = str(res8[0]["cn"]).replace("{","").replace("}","")
     else:
@@ -1203,7 +1209,13 @@ def setup_samdb(path, session_info, provision_backend, lp, names,
 
     # And now we can connect to the DB - the schema won't be loaded from the
     # DB
-    samdb.connect(path)
+    try:
+        samdb.connect(path)
+    except ldb.LdbError, (num, string_error):
+        if (num == ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS):
+            raise ProvisioningError("Permission denied connecting to %s, are you running as root?" % path)
+        else:
+            raise
 
     # But we have to give it one more kick to have it use the schema
     # during provision - it needs, now that it is connected, to write
@@ -1213,7 +1225,7 @@ def setup_samdb(path, session_info, provision_backend, lp, names,
     return samdb
 
 
-def fill_samdb(samdb, lp, names, logger, domainsid, domainguid, policyguid,
+def fill_samdb(samdb, lp, names, logger, policyguid,
         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):
@@ -1235,7 +1247,7 @@ def fill_samdb(samdb, lp, names, logger, domainsid, domainguid, policyguid,
     domainControllerFunctionality = DS_DOMAIN_FUNCTION_2008_R2
 
     if dom_for_fun_level is None:
-        dom_for_fun_level = DS_DOMAIN_FUNCTION_2003
+        dom_for_fun_level = DS_DOMAIN_FUNCTION_2008_R2
 
     if dom_for_fun_level > domainControllerFunctionality:
         raise ProvisioningError("You want to run SAMBA 4 on a domain and forest function level which itself is higher than its actual DC function level (2008_R2). This won't work!")
@@ -1260,23 +1272,23 @@ def fill_samdb(samdb, lp, names, logger, domainsid, domainguid, policyguid,
         samdb.set_opaque_integer("domainControllerFunctionality",
             domainControllerFunctionality)
 
-        samdb.set_domain_sid(str(domainsid))
+        samdb.set_domain_sid(str(names.domainsid))
         samdb.set_invocation_id(invocationid)
 
         logger.info("Adding DomainDN: %s" % names.domaindn)
 
         # impersonate domain admin
-        admin_session_info = admin_session(lp, str(domainsid))
+        admin_session_info = admin_session(lp, str(names.domainsid))
         samdb.set_session_info(admin_session_info)
-        if domainguid is not None:
-            domainguid_line = "objectGUID: %s\n-" % domainguid
+        if names.domainguid is not None:
+            domainguid_line = "objectGUID: %s\n-" % names.domainguid
         else:
             domainguid_line = ""
 
-        descr = b64encode(get_domain_descriptor(domainsid))
+        descr = b64encode(get_domain_descriptor(names.domainsid))
         setup_add_ldif(samdb, setup_path("provision_basedn.ldif"), {
                 "DOMAINDN": names.domaindn,
-                "DOMAINSID": str(domainsid),
+                "DOMAINSID": str(names.domainsid),
                 "DESCRIPTOR": descr,
                 "DOMAINGUID": domainguid_line
                 })
@@ -1295,7 +1307,7 @@ 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("Adding configuration container")
-            descr = b64encode(get_config_descriptor(domainsid))
+            descr = b64encode(get_config_descriptor(names.domainsid))
             setup_add_ldif(samdb, setup_path("provision_configuration_basedn.ldif"), {
                     "CONFIGDN": names.configdn,
                     "DESCRIPTOR": descr,
@@ -1329,12 +1341,12 @@ def fill_samdb(samdb, lp, names, logger, domainsid, domainguid, policyguid,
         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))
+            partitions_descr = b64encode(get_config_partitions_descriptor(names.domainsid))
+            sites_descr = b64encode(get_config_sites_descriptor(names.domainsid))
+            ntdsquotas_descr = b64encode(get_config_ntds_quotas_descriptor(names.domainsid))
+            protected1_descr = b64encode(get_config_delete_protected1_descriptor(names.domainsid))
+            protected1wd_descr = b64encode(get_config_delete_protected1wd_descriptor(names.domainsid))
+            protected2_descr = b64encode(get_config_delete_protected2_descriptor(names.domainsid))
 
             setup_add_ldif(samdb, setup_path("provision_configuration.ldif"), {
                     "CONFIGDN": names.configdn,
@@ -1373,7 +1385,7 @@ def fill_samdb(samdb, lp, names, logger, domainsid, domainguid, policyguid,
                 })
 
         logger.info("Adding users container")
-        users_desc = b64encode(get_domain_users_descriptor(domainsid))
+        users_desc = b64encode(get_domain_users_descriptor(names.domainsid))
         setup_add_ldif(samdb, setup_path("provision_users_add.ldif"), {
                 "DOMAINDN": names.domaindn,
                 "USERS_DESCRIPTOR": users_desc
@@ -1382,7 +1394,7 @@ def fill_samdb(samdb, lp, names, logger, domainsid, domainguid, policyguid,
         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))
+        computers_desc = b64encode(get_domain_computers_descriptor(names.domainsid))
         setup_add_ldif(samdb, setup_path("provision_computers_add.ldif"), {
                 "DOMAINDN": names.domaindn,
                 "COMPUTERS_DESCRIPTOR": computers_desc
@@ -1392,11 +1404,11 @@ def fill_samdb(samdb, lp, names, logger, domainsid, domainguid, policyguid,
             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))
+        infrastructure_desc = b64encode(get_domain_infrastructure_descriptor(names.domainsid))
+        lostandfound_desc = b64encode(get_domain_delete_protected2_descriptor(names.domainsid))
+        system_desc = b64encode(get_domain_delete_protected1_descriptor(names.domainsid))
+        builtin_desc = b64encode(get_domain_builtin_descriptor(names.domainsid))
+        controllers_desc = b64encode(get_domain_controllers_descriptor(names.domainsid))
         setup_add_ldif(samdb, setup_path("provision.ldif"), {
             "CREATTIME": str(samba.unix2nttime(int(time.time()))),
             "DOMAINDN": names.domaindn,
@@ -1421,7 +1433,7 @@ 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))
+            protected1wd_descr = b64encode(get_config_delete_protected1wd_descriptor(names.domainsid))
             setup_add_ldif(samdb, setup_path("provision_well_known_sec_princ.ldif"), {
                 "CONFIGDN": names.configdn,
                 "WELLKNOWNPRINCIPALS_DESCRIPTOR": protected1wd_descr,
@@ -1435,7 +1447,7 @@ def fill_samdb(samdb, lp, names, logger, domainsid, domainguid, policyguid,
             logger.info("Setting up sam.ldb users and groups")
             setup_add_ldif(samdb, setup_path("provision_users.ldif"), {
                 "DOMAINDN": names.domaindn,
-                "DOMAINSID": str(domainsid),
+                "DOMAINSID": str(names.domainsid),
                 "ADMINPASS_B64": b64encode(adminpass.encode('utf-16-le')),
                 "KRBTGTPASS_B64": b64encode(krbtgtpass.encode('utf-16-le'))
                 })
@@ -1446,7 +1458,7 @@ def fill_samdb(samdb, lp, names, logger, domainsid, domainguid, policyguid,
                 dns_backend=dns_backend,
                 dnspass=dnspass,
                 machinepass=machinepass,
-                domainsid=domainsid,
+                domainsid=names.domainsid,
                 next_rid=next_rid,
                 dc_rid=dc_rid,
                 policyguid=policyguid,
@@ -1527,6 +1539,31 @@ def setsysvolacl(samdb, netlogon, sysvol, uid, gid, domainsid, dnsdomain,
     s4_passdb = None
 
     if not use_ntvfs:
+        s3conf = s3param.get_context()
+        s3conf.load(lp.configfile)
+
+        file = tempfile.NamedTemporaryFile(dir=os.path.abspath(sysvol))
+        try:
+            try:
+                smbd.set_simple_acl(file.name, 0755, gid)
+            except OSError:
+                if not smbd.have_posix_acls():
+                    # This clue is only strictly correct for RPM and
+                    # Debian-like Linux systems, but hopefully other users
+                    # will get enough clue from it.
+                    raise ProvisioningError("Samba was compiled without the posix ACL support that s3fs requires.  "
+                                            "Try installing libacl1-dev or libacl-devel, then re-run configure and make.")
+
+                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, uid, gid)
+            except OSError:
+                raise ProvisioningError("Unable to chown a file on your filesystem.  "
+                                        "You may not be running provision as root.")
+        finally:
+            file.close()
+
         # This will ensure that the smbd code we are running when setting ACLs
         # is initialised with the smb.conf
         s3conf = s3param.get_context()
@@ -1716,7 +1753,7 @@ def interface_ips_v6(lp):
 
 
 def provision_fill(samdb, secrets_ldb, logger, names, paths,
-                   domainsid, schema=None,
+                   schema=None,
                    targetdir=None, samdb_fill=FILL_FULL,
                    hostip=None, hostip6=None,
                    next_rid=1000, dc_rid=None, adminpass=None, krbtgtpass=None,
@@ -1747,7 +1784,7 @@ def provision_fill(samdb, secrets_ldb, logger, names, paths,
         dnspass = samba.generate_random_password(128, 255)
 
     samdb = fill_samdb(samdb, lp, names, logger=logger,
-                   domainsid=domainsid, schema=schema, domainguid=domainguid,
+                   schema=schema,
                    policyguid=policyguid, policyguid_dc=policyguid_dc,
                    fill=samdb_fill, adminpass=adminpass, krbtgtpass=krbtgtpass,
                    invocationid=invocationid, machinepass=machinepass,
@@ -1764,14 +1801,14 @@ 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.root_gid, domainsid, names.dnsdomain,
+                         paths.root_gid, names.domainsid, names.dnsdomain,
                          names.domaindn, lp, use_ntvfs)
         else:
             logger.info("Setting acl on sysvol skipped")
 
         secretsdb_self_join(secrets_ldb, domain=names.domain,
                 realm=names.realm, dnsdomain=names.dnsdomain,
-                netbiosname=names.netbiosname, domainsid=domainsid,
+                netbiosname=names.netbiosname, domainsid=names.domainsid,
                 machinepass=machinepass, secure_channel_type=SEC_CHAN_BDC)
 
         # Now set up the right msDS-SupportedEncryptionTypes into the DB
@@ -1792,10 +1829,10 @@ def provision_fill(samdb, secrets_ldb, logger, names, paths,
                 # It might be that this attribute does not exist in this schema
                 raise
 
-        setup_ad_dns(samdb, secrets_ldb, domainsid, names, paths, lp, logger,
+        setup_ad_dns(samdb, secrets_ldb, names, paths, lp, logger,
                      hostip=hostip, hostip6=hostip6, dns_backend=dns_backend,
                      dnspass=dnspass, os_level=dom_for_fun_level,
-                     targetdir=targetdir, site=DEFAULTSITE, fill_level=samdb_fill)
+                     targetdir=targetdir, fill_level=samdb_fill)
 
         domainguid = samdb.searchone(basedn=samdb.get_default_basedn(),
                                      attribute="objectGUID")
@@ -1921,8 +1958,6 @@ def provision(logger, session_info, smbconf=None,
 
     if domainsid is None:
         domainsid = security.random_sid()
-    else:
-        domainsid = security.dom_sid(domainsid)
 
     root_uid = findnss_uid([root or "root"])
     nobody_uid = findnss_uid([nobody or "nobody"])
@@ -2018,6 +2053,9 @@ def provision(logger, session_info, smbconf=None,
 
     names.hostip = hostip
     names.hostip6 = hostip6
+    names.domainguid = domainguid
+    names.domainsid = domainsid
+    names.forestsid = domainsid
 
     if serverrole is None:
         serverrole = lp.get("server role")
@@ -2032,32 +2070,6 @@ def provision(logger, session_info, smbconf=None,
     if paths.sysvol and not os.path.exists(paths.sysvol):
         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)
-
-        file = tempfile.NamedTemporaryFile(dir=os.path.abspath(paths.sysvol))
-        try:
-            try:
-                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
-                    # Debian-like Linux systems, but hopefully other users
-                    # will get enough clue from it.
-                    raise ProvisioningError("Samba was compiled without the posix ACL support that s3fs requires.  Try installing libacl1-dev or libacl-devel, then re-run configure and make.")
-
-                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, root_gid)
-            except Exception:
-                raise ProvisioningError("Unable to chown a file on your filesystem.  You may not be running provision as root.")
-        finally:
-            file.close()
-
     ldapi_url = "ldapi://%s" % urllib.quote(paths.s4_ldapi_path, safe="")
 
     schema = Schema(domainsid, invocationid=invocationid,
@@ -2147,9 +2159,9 @@ def provision(logger, session_info, smbconf=None,
         if samdb_fill == FILL_FULL:
             provision_fill(samdb, secrets_ldb, logger, names, paths,
                     schema=schema, targetdir=targetdir, samdb_fill=samdb_fill,
-                    hostip=hostip, hostip6=hostip6, domainsid=domainsid,
+                    hostip=hostip, hostip6=hostip6,
                     next_rid=next_rid, dc_rid=dc_rid, adminpass=adminpass,
-                    krbtgtpass=krbtgtpass, domainguid=domainguid,
+                    krbtgtpass=krbtgtpass,
                     policyguid=policyguid, policyguid_dc=policyguid_dc,
                     invocationid=invocationid, machinepass=machinepass,
                     ntdsguid=ntdsguid, dns_backend=dns_backend,