diff options
| author | Jelmer Vernooij <jelmer@samba.org> | 2008-02-09 20:06:54 +0100 |
|---|---|---|
| committer | Jelmer Vernooij <jelmer@samba.org> | 2008-02-09 20:06:54 +0100 |
| commit | ec106a14216ee034b7e04c177c89703e63dfd107 (patch) | |
| tree | 59c56cd663ee3dc03d0ce63bf4405ee87c14834a /source4/scripting/python/samba | |
| parent | 4075a2ba982ea56ff925e0a33839f0760fd71911 (diff) | |
| parent | 1a2544a24c064e9eecb973439ccd0e7126e06e77 (diff) | |
| download | samba-ec106a14216ee034b7e04c177c89703e63dfd107.tar.gz samba-ec106a14216ee034b7e04c177c89703e63dfd107.tar.bz2 samba-ec106a14216ee034b7e04c177c89703e63dfd107.zip | |
Merge branch 'v4-0-trivial' into v4-0-python
(This used to be commit b874f07175ae38a041f53f0e4ac6a4050dcefeae)
Diffstat (limited to 'source4/scripting/python/samba')
| -rw-r--r-- | source4/scripting/python/samba/__init__.py | 23 | ||||
| -rw-r--r-- | source4/scripting/python/samba/getopt.py | 26 | ||||
| -rw-r--r-- | source4/scripting/python/samba/provision.py | 577 | ||||
| -rw-r--r-- | source4/scripting/python/samba/samdb.py | 13 | ||||
| -rw-r--r-- | source4/scripting/python/samba/tests/__init__.py | 8 | ||||
| -rw-r--r-- | source4/scripting/python/samba/tests/provision.py | 58 | ||||
| -rw-r--r-- | source4/scripting/python/samba/upgrade.py | 9 |
7 files changed, 472 insertions, 242 deletions
diff --git a/source4/scripting/python/samba/__init__.py b/source4/scripting/python/samba/__init__.py index 483929661da..b041165800f 100644 --- a/source4/scripting/python/samba/__init__.py +++ b/source4/scripting/python/samba/__init__.py @@ -1,8 +1,10 @@ #!/usr/bin/python # Unix SMB/CIFS implementation. +# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007-2008 +# +# Based on the original in EJS: # Copyright (C) Andrew Tridgell <tridge@samba.org> 2005 -# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007 # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -89,7 +91,7 @@ class Ldb(ldb.Ldb): set_session_info = misc.ldb_set_session_info set_loadparm = misc.ldb_set_loadparm - def searchone(self, basedn, attribute, expression=None, + def searchone(self, attribute, basedn=None, expression=None, scope=ldb.SCOPE_BASE): """Search for one attribute as a string. @@ -104,7 +106,7 @@ class Ldb(ldb.Ldb): return None values = set(res[0][attribute]) assert len(values) == 1 - return values.pop() + return self.schema_format_value(attribute, values.pop()) def erase(self): """Erase this ldb, removing all records.""" @@ -192,6 +194,21 @@ def substitute_var(text, values): return text +def check_all_substituted(text): + """Make sure that all substitution variables in a string have been replaced. + If not, raise an exception. + + :param text: The text to search for substitution variables + """ + if not "${" in text: + return + + var_start = text.find("${") + var_end = text.find("}", var_start) + + raise Exception("Not all variables substituted: %s" % text[var_start:var_end+1]) + + def valid_netbios_name(name): """Check whether a name is valid as a NetBIOS name. """ # FIXME: There are probably more constraints here. diff --git a/source4/scripting/python/samba/getopt.py b/source4/scripting/python/samba/getopt.py index a087974a698..088a5acf6fc 100644 --- a/source4/scripting/python/samba/getopt.py +++ b/source4/scripting/python/samba/getopt.py @@ -23,9 +23,25 @@ from credentials import Credentials class SambaOptions(optparse.OptionGroup): def __init__(self, parser): optparse.OptionGroup.__init__(self, parser, "Samba Common Options") - self.add_option("-s", "--configfile", type="string", metavar="FILE", - help="Configuration file") + self.add_option("-s", "--configfile", action="callback", + type=str, metavar="FILE", help="Configuration file", + callback=self._load_configfile) + self._configfile = None + def get_loadparm_path(self): + return self._configfile + + def _load_configfile(self, option, opt_str, arg, parser): + self._configfile = arg + + def get_loadparm(self): + import param + lp = param.LoadParm() + if self._configfile is None: + lp.load_default() + else: + lp.load(self._configfile) + return lp class VersionOptions(optparse.OptionGroup): def __init__(self, parser): @@ -34,6 +50,7 @@ class VersionOptions(optparse.OptionGroup): class CredentialsOptions(optparse.OptionGroup): def __init__(self, parser): + self.no_pass = False optparse.OptionGroup.__init__(self, parser, "Credentials Options") self.add_option("--simple-bind-dn", metavar="DN", action="callback", callback=self._set_simple_bind_dn, type=str, @@ -46,6 +63,8 @@ class CredentialsOptions(optparse.OptionGroup): self.add_option("-W", "--workgroup", metavar="WORKGROUP", action="callback", type=str, help="Workgroup", callback=self._parse_workgroup) + self.add_option("-N", "--no-pass", action="store_true", + help="Don't ask for a password") self.creds = Credentials() def _parse_username(self, option, opt_str, arg, parser): @@ -61,4 +80,7 @@ class CredentialsOptions(optparse.OptionGroup): self.creds.set_bind_dn(arg) def get_credentials(self): + self.creds.guess() + if not self.no_pass: + self.creds.set_cmdline_callbacks() return self.creds diff --git a/source4/scripting/python/samba/provision.py b/source4/scripting/python/samba/provision.py index d59cea121e8..4f52d36167b 100644 --- a/source4/scripting/python/samba/provision.py +++ b/source4/scripting/python/samba/provision.py @@ -1,10 +1,25 @@ # -# backend code for provisioning a Samba4 server -# Released under the GNU GPL v3 or later -# Copyright Jelmer Vernooij 2007 +# Unix SMB/CIFS implementation. +# backend code for provisioning a Samba4 server + +# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007-2008 +# Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008 # # Based on the original in EJS: -# Copyright Andrew Tridgell 2005 +# Copyright (C) Andrew Tridgell <tridge@samba.org> 2005 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. # from base64 import b64encode @@ -17,9 +32,10 @@ from socket import gethostname, gethostbyname import param import registry import samba -from samba import Ldb, substitute_var, valid_netbios_name +from samba import Ldb, substitute_var, valid_netbios_name, check_all_substituted from samba.samdb import SamDB import security +import urllib from ldb import SCOPE_SUBTREE, SCOPE_ONELEVEL, SCOPE_BASE, LdbError, \ LDB_ERR_NO_SUCH_OBJECT, timestring, CHANGETYPE_MODIFY, CHANGETYPE_NONE @@ -48,12 +64,9 @@ class ProvisionPaths: self.dns_keytab = None self.dns = None self.winsdb = None - self.ldap_basedn_ldif = None - self.ldap_config_basedn_ldif = None - self.ldap_schema_basedn_ldif = None -def install_ok(lp, session_info, credentials): +def check_install(lp, session_info, credentials): """Check whether the current install seems ok. :param lp: Loadparm context @@ -61,22 +74,26 @@ def install_ok(lp, session_info, credentials): :param credentials: Credentials """ if lp.get("realm") == "": - return False + raise Error("Realm empty") ldb = Ldb(lp.get("sam database"), session_info=session_info, credentials=credentials, lp=lp) if len(ldb.search("(cn=Administrator)")) != 1: - return False - return True + raise "No administrator account found" -def findnss(nssfn, *names): - """Find a user or group from a list of possibilities.""" +def findnss(nssfn, names): + """Find a user or group from a list of possibilities. + + :param nssfn: NSS Function to try (should raise KeyError if not found) + :param names: Names to check. + :return: Value return by first names list. + """ for name in names: try: return nssfn(name) except KeyError: pass - raise Exception("Unable to find user/group for %s" % arguments[1]) + raise KeyError("Unable to find user/group %r" % names) def open_ldb(session_info, credentials, lp, dbname): @@ -112,7 +129,7 @@ def setup_add_ldif(ldb, ldif_path, subst_vars=None): if subst_vars is not None: data = substitute_var(data, subst_vars) - assert "${" not in data + check_all_substituted(data) ldb.add_ldif(data) @@ -128,12 +145,20 @@ def setup_modify_ldif(ldb, ldif_path, substvars=None): if substvars is not None: data = substitute_var(data, substvars) - assert "${" not in data + check_all_substituted(data) ldb.modify_ldif(data) def setup_ldb(ldb, ldif_path, subst_vars): + """Import a LDIF a file into a LDB handle, optionally substituting variables. + + :note: Either all LDIF data will be added or none (using transactions). + + :param ldb: LDB file to import into. + :param ldif_path: Path to the LDIF file. + :param subst_vars: Dictionary with substitution variables. + """ assert ldb is not None ldb.transaction_start() try: @@ -159,7 +184,7 @@ def setup_file(template, fname, substvars): data = open(template, 'r').read() if substvars: data = substitute_var(data, substvars) - assert not "${" in data + check_all_substituted(data) open(f, 'w').write(data) @@ -172,18 +197,26 @@ def provision_paths_from_lp(lp, dnsdomain): """ paths = ProvisionPaths() private_dir = lp.get("private dir") + paths.keytab = "secrets.keytab" + paths.dns_keytab = "dns.keytab" + paths.shareconf = os.path.join(private_dir, "share.ldb") paths.samdb = os.path.join(private_dir, lp.get("sam database") or "samdb.ldb") paths.secrets = os.path.join(private_dir, lp.get("secrets database") or "secrets.ldb") paths.templates = os.path.join(private_dir, "templates.ldb") - paths.keytab = os.path.join(private_dir, "secrets.keytab") - paths.dns_keytab = os.path.join(private_dir, "dns.keytab") paths.dns = os.path.join(private_dir, dnsdomain + ".zone") paths.winsdb = os.path.join(private_dir, "wins.ldb") paths.s4_ldapi_path = os.path.join(private_dir, "ldapi") + paths.smbconf = os.path.join(private_dir, "smb.conf") paths.phpldapadminconfig = os.path.join(private_dir, "phpldapadmin-config.php") - paths.hklm = os.path.join(private_dir, "hklm.ldb") + paths.hklm = "hklm.ldb" + paths.hkcr = "hkcr.ldb" + paths.hkcu = "hkcu.ldb" + paths.hku = "hku.ldb" + paths.hkpd = "hkpd.ldb" + paths.hkpt = "hkpt.ldb" + paths.sysvol = lp.get("sysvol", "path") if paths.sysvol is None: paths.sysvol = os.path.join(lp.get("lock dir"), "sysvol") @@ -235,77 +268,201 @@ def setup_name_mappings(ldb, sid, domaindn, root, nobody, nogroup, users, ldb.setup_name_mapping(domaindn, sid + "-520", wheel) -def provision_become_dc(setup_dir, message, paths, lp, session_info, - credentials): +def setup_samdb_partitions(samdb_path, setup_path, message, lp, session_info, + credentials, configdn, schemadn, domaindn, + hostname, netbiosname, dnsdomain, realm, + rootdn, serverrole, ldap_backend=None, + ldap_backend_type=None, erase=False): + """Setup the partitions for the SAM database. + + Alternatively, provision() may call this, and then populate the database. + + :param erase: Remove the existing data present in the database. + + :note: This will wipe the Sam Database! + + :note: This function always removes the local SAM LDB file. The erase + parameter controls whether to erase the existing data, which + may not be stored locally but in LDAP. + """ assert session_info is not None - erase = False - - def setup_path(file): - return os.path.join(setup_dir, file) - os.path.unlink(paths.samdb) - message("Setting up templates db") - setup_templatesdb(paths.templates, setup_path, session_info=session_info, - credentials=credentials, lp=lp) + if os.path.exists(samdb_path): + os.unlink(samdb_path) # Also wipes the database - message("Setting up sam.ldb") - samdb = SamDB(paths.samdb, session_info=session_info, + samdb = SamDB(samdb_path, session_info=session_info, credentials=credentials, lp=lp) - message("Setting up sam.ldb partitions") - setup_samdb_partitions(samdb, setup_path, schemadn, configdn, domaindn) + #Add modules to the list to activate them by default + #beware often order is important + # + # Some Known ordering constraints: + # - rootdse must be first, as it makes redirects from "" -> cn=rootdse + # - objectclass must be before password_hash, because password_hash checks + # that the objectclass is of type person (filled in by objectclass + # module when expanding the objectclass list) + # - partition must be last + # - each partition has its own module list then + modules_list = ["rootdse", + "paged_results", + "ranged_results", + "anr", + "server_sort", + "extended_dn", + "asq", + "samldb", + "rdn_name", + "objectclass", + "kludge_acl", + "operational"] + tdb_modules_list = [ + "subtree_rename", + "subtree_delete", + "linked_attributes"] + modules_list2 = ["show_deleted", + "partition"] + + domaindn_ldb = "users.ldb" + if ldap_backend is not None: + domaindn_ldb = ldap_backend + configdn_ldb = "configuration.ldb" + if ldap_backend is not None: + configdn_ldb = ldap_backend + schemadn_ldb = "schema.ldb" + if ldap_backend is not None: + schema_ldb = ldap_backend + + schemadn_ldb = ldap_backend + + if ldap_backend_type == "fedora-ds": + backend_modules = ["nsuniqueid","paged_searches"] + elif ldap_backend_type == "openldap": + backend_modules = ["normalise","entryuuid","paged_searches"] + elif serverrole == "domain controller": + backend_modules = ["repl_meta_data"] + else: + backend_modules = ["objectguid"] + + samdb.transaction_start() + try: + setup_add_ldif(samdb, setup_path("provision_partitions.ldif"), { + "SCHEMADN": schemadn, + "SCHEMADN_LDB": schemadn_ldb, + "SCHEMADN_MOD2": ",objectguid", + "CONFIGDN": configdn, + "CONFIGDN_LDB": configdn_ldb, + "DOMAINDN": domaindn, + "DOMAINDN_LDB": domaindn_ldb, + "SCHEMADN_MOD": "schema_fsmo,instancetype", + "CONFIGDN_MOD": "naming_fsmo,instancetype", + "DOMAINDN_MOD": "pdc_fsmo,password_hash,instancetype", + "MODULES_LIST": ",".join(modules_list), + "TDB_MODULES_LIST": ","+",".join(tdb_modules_list), + "MODULES_LIST2": ",".join(modules_list2), + "BACKEND_MOD": ",".join(backend_modules), + }) + + except: + samdb.transaction_cancel() + raise - samdb = SamDB(paths.samdb, session_info=session_info, + samdb.transaction_commit() + + samdb = SamDB(samdb_path, session_info=session_info, credentials=credentials, lp=lp) - ldb.transaction_start() + samdb.transaction_start() try: message("Setting up sam.ldb attributes") samdb.load_ldif_file_add(setup_path("provision_init.ldif")) message("Setting up sam.ldb rootDSE") - setup_samdb_rootdse(samdb, setup_path, schemadn, domaindn, - hostname, dnsdomain, realm, rootdn, configdn, - netbiosname) + setup_samdb_rootdse(samdb, setup_path, schemadn, domaindn, hostname, + dnsdomain, realm, rootdn, configdn, netbiosname) if erase: message("Erasing data from partitions") samdb.erase_partitions() - message("Setting up sam.ldb indexes") - samdb.load_ldif_file_add(setup_path("provision_index.ldif")) except: samdb.transaction_cancel() raise samdb.transaction_commit() + + return samdb + - message("Setting up %s" % paths.secrets) - secrets_ldb = setup_secretsdb(paths.secrets, setup_path, session_info, - credentials, lp) - setup_ldb(secrets_ldb, setup_path("secrets_dc.ldif"), - { "MACHINEPASS_B64": b64encode(machinepass) }) +def secretsdb_become_dc(secretsdb, setup_path, domain, realm, dnsdomain, + netbiosname, domainsid, keytab_path, samdb_url, + dns_keytab_path, dnspass, machinepass): + """Add DC-specific bits to a secrets database. + + :param secretsdb: Ldb Handle to the secrets database + :param setup_path: Setup path function + :param machinepass: Machine password + """ + setup_ldb(secretsdb, setup_path("secrets_dc.ldif"), { + "MACHINEPASS_B64": b64encode(machinepass), + "DOMAIN": domain, + "REALM": realm, + "DNSDOMAIN": dnsdomain, + "DOMAINSID": str(domainsid), + "SECRETS_KEYTAB": keytab_path, + "NETBIOSNAME": netbiosname, + "SAM_LDB": samdb_url, + "DNS_KEYTAB": dns_keytab_path, + "DNSPASS_B64": b64encode(dnspass), + }) def setup_secretsdb(path, setup_path, session_info, credentials, lp): + """Setup the secrets database. + + :param path: Path to the secrets database. + :param setup_path: Get the path to a setup file. + :param session_info: Session info. + :param credentials: Credentials + :param lp: Loadparm context + :return: LDB handle for the created secrets database + """ if os.path.exists(path): os.unlink(path) - secrets_ldb = Ldb(path, session_info=session_info, credentials=credentials, lp=lp) + secrets_ldb = Ldb(path, session_info=session_info, credentials=credentials, + lp=lp) secrets_ldb.erase() secrets_ldb.load_ldif_file_add(setup_path("secrets_init.ldif")) + secrets_ldb = Ldb(path, session_info=session_info, credentials=credentials, + lp=lp) secrets_ldb.load_ldif_file_add(setup_path("secrets.ldif")) return secrets_ldb def setup_templatesdb(path, setup_path, session_info, credentials, lp): + """Setup the templates database. + + :param path: Path to the database. + :param setup_path: Function for obtaining the path to setup files. + :param session_info: Session info + :param credentials: Credentials + :param lp: Loadparm context + """ templates_ldb = SamDB(path, session_info=session_info, - credentials=credentials, lp=lp) + credentials=credentials, lp=lp) templates_ldb.erase() templates_ldb.load_ldif_file_add(setup_path("provision_templates.ldif")) def setup_registry(path, setup_path, session_info, credentials, lp): + """Setup the registry. + + :param path: Path to the registry database + :param setup_path: Function that returns the path to a setup. + :param session_info: Session information + :param credentials: Credentials + :param lp: Loadparm context + """ reg = registry.Registry() hive = registry.open_ldb(path, session_info=session_info, credentials=credentials, lp_ctx=lp) @@ -317,6 +474,11 @@ def setup_registry(path, setup_path, session_info, credentials, lp): def setup_samdb_rootdse(samdb, setup_path, schemadn, domaindn, hostname, dnsdomain, realm, rootdn, configdn, netbiosname): + """Setup the SamDB rootdse. + + :param samdb: Sam Database handle + :param setup_path: Obtain setup path + """ setup_add_ldif(samdb, setup_path("provision_rootdse_add.ldif"), { "SCHEMADN": schemadn, "NETBIOSNAME": netbiosname, @@ -329,61 +491,13 @@ def setup_samdb_rootdse(samdb, setup_path, schemadn, domaindn, hostname, "CONFIGDN": configdn, "VERSION": samba.version(), }) - - -def setup_samdb_partitions(samdb, setup_path, schemadn, configdn, domaindn): - #Add modules to the list to activate them by default - #beware often order is important - # - # Some Known ordering constraints: - # - rootdse must be first, as it makes redirects from "" -> cn=rootdse - # - objectclass must be before password_hash, because password_hash checks - # that the objectclass is of type person (filled in by objectclass - # module when expanding the objectclass list) - # - partition must be last - # - each partition has its own module list then - modules_list = ["rootdse", - "paged_results", - "ranged_results", - "anr", - "server_sort", - "extended_dn", - "asq", - "samldb", - "rdn_name", - "objectclass", - "kludge_acl", - "operational"] - tdb_modules_list = [ - "subtree_rename", - "subtree_delete", - "linked_attributes"] - modules_list2 = ["show_deleted", - "partition"] - - setup_add_ldif(samdb, setup_path("provision_partitions.ldif"), { - "SCHEMADN": schemadn, - "SCHEMADN_LDB": "schema.ldb", - "SCHEMADN_MOD2": ",objectguid", - "CONFIGDN": configdn, - "CONFIGDN_LDB": "configuration.ldb", - "DOMAINDN": domaindn, - "DOMAINDN_LDB": "users.ldb", - "SCHEMADN_MOD": "schema_fsmo", - "CONFIGDN_MOD": "naming_fsmo", - "CONFIGDN_MOD2": ",objectguid", - "DOMAINDN_MOD": "pdc_fsmo,password_hash", - "DOMAINDN_MOD2": ",objectguid", - "MODULES_LIST": ",".join(modules_list), - "TDB_MODULES_LIST": ","+",".join(tdb_modules_list), - "MODULES_LIST2": ",".join(modules_list2), - }) - + def setup_self_join(samdb, configdn, schemadn, domaindn, netbiosname, hostname, dnsdomain, machinepass, dnspass, realm, domainname, domainsid, invocationid, setup_path, policyguid, hostguid=None): + """Join a host to its own domain.""" if hostguid is not None: hostguid_add = "objectGUID: %s" % hostguid else: @@ -413,43 +527,40 @@ def setup_self_join(samdb, configdn, schemadn, domaindn, def setup_samdb(path, setup_path, session_info, credentials, lp, schemadn, configdn, domaindn, dnsdomain, realm, netbiosname, message, hostname, rootdn, erase, - domainsid, aci, rdn_dc, domainguid, policyguid, - domainname, blank, adminpass, krbtgtpass, - machinepass, hostguid, invocationid, dnspass): - # Also wipes the database - message("Setting up sam.ldb") - samdb = SamDB(path, session_info=session_info, - credentials=credentials, lp=lp) + domainsid, aci, domainguid, policyguid, + domainname, fill, adminpass, krbtgtpass, + machinepass, hostguid, invocationid, dnspass, + serverrole, ldap_backend=None, ldap_backend_type=None): + """Setup a complete SAM Database. + + :note: This will wipe the main SAM database file! + """ - message("Setting up sam.ldb partitions") - setup_samdb_partitions(samdb, setup_path, schemadn, configdn, domaindn) + # Also wipes the database + setup_samdb_partitions(path, setup_path, schemadn=schemadn, configdn=configdn, + domaindn=domaindn, message=message, lp=lp, + credentials=credentials, session_info=session_info, + hostname=hostname, netbiosname=netbiosname, + dnsdomain=dnsdomain, realm=realm, rootdn=rootdn, + ldap_backend=ldap_backend, serverrole=serverrole, + ldap_backend_type=ldap_backend_type, erase=erase) samdb = SamDB(path, session_info=session_info, credentials=credentials, lp=lp) - samdb.transaction_start() - try: - message("Setting up sam.ldb attributes") - samdb.load_ldif_file_add(setup_path("provision_init.ldif")) - - message("Setting up sam.ldb rootDSE") - setup_samdb_rootdse(samdb, setup_path, schemadn, domaindn, - hostname, dnsdomain, realm, rootdn, configdn, - netbiosname) - - if erase: - message("Erasing data from partitions") - samdb.erase_partitions() - except: - samdb.transaction_cancel() - raise - - samdb.transaction_commit() + if fill == FILL_DRS: + # We want to finish here, but setup the index before we do so + message("Setting up sam.ldb index") + samdb.load_ldif_file_add(setup_path("provision_index.ldif")) + return samdb message("Pre-loading the Samba 4 and AD schema") samdb = SamDB(path, session_info=session_info, credentials=credentials, lp=lp) samdb.set_domain_sid(domainsid) + if lp.get("server role") == "domain controller": + samdb.set_invocation_id(invocationid) + load_schema(setup_path, samdb, schemadn, netbiosname, configdn) samdb.transaction_start() @@ -459,7 +570,6 @@ def setup_samdb(path, setup_path, session_info, credentials, lp, setup_add_ldif(samdb, setup_path("provision_basedn.ldif"), { "DOMAINDN": domaindn, "ACI": aci, - "RDN_DC": rdn_dc, }) message("Modifying DomainDN: " + domaindn + "") @@ -469,7 +579,6 @@ def setup_samdb(path, setup_path, session_info, credentials, lp, domainguid_mod = "" setup_modify_ldif(samdb, setup_path("provision_basedn_modify.ldif"), { - "RDN_DC": rdn_dc, "LDAPTIME": timestring(int(time.time())), "DOMAINSID": str(domainsid), "SCHEMADN": schemadn, @@ -500,7 +609,8 @@ def setup_samdb(path, setup_path, session_info, credentials, lp, "EXTENSIBLEOBJECT": "# no objectClass: extensibleObject for local ldb" }) message("Modifying schema container") - setup_modify_ldif(samdb, setup_path("provision_schema_basedn_modify.ldif"), { + setup_modify_ldif(samdb, + setup_path("provision_schema_basedn_modify.ldif"), { "SCHEMADN": schemadn, "NETBIOSNAME": netbiosname, "DEFAULTSITE": DEFAULTSITE, @@ -549,7 +659,7 @@ def setup_samdb(path, setup_path, session_info, credentials, lp, "CONFIGDN": configdn, }) - if not blank: + if fill == FILL_FULL: message("Setting up sam.ldb users and groups") setup_add_ldif(samdb, setup_path("provision_users.ldif"), { "DOMAINDN": domaindn, @@ -561,17 +671,18 @@ def setup_samdb(path, setup_path, session_info, credentials, lp, if lp.get("server role") == "domain controller": message("Setting up self join") - setup_self_join(samdb, configdn=configdn, schemadn=schemadn, domaindn=domaindn, - invocationid=invocationid, dnspass=dnspass, netbiosname=netbiosname, - dnsdomain=dnsdomain, realm=realm, machinepass=machinepass, - domainname=domainname, domainsid=domainsid, policyguid=policyguid, - hostname=hostname, hostguid=hostguid, setup_path=setup_path) - + setup_self_join(samdb, configdn=configdn, schemadn=schemadn, + domaindn=domaindn, invocationid=invocationid, + dnspass=dnspass, netbiosname=netbiosname, + dnsdomain=dnsdomain, realm=realm, + machinepass=machinepass, domainname=domainname, + domainsid=domainsid, policyguid=policyguid, + hostname=hostname, hostguid=hostguid, + setup_path=setup_path) + + #We want to setup the index last, as adds are faster unindexed message("Setting up sam.ldb index") samdb.load_ldif_file_add(setup_path("provision_index.ldif")) - - message("Setting up sam.ldb rootDSE marking as synchronized") - setup_modify_ldif(samdb, setup_path("provision_rootdse_modify.ldif")) except: samdb.transaction_cancel() raise @@ -579,14 +690,18 @@ def setup_samdb(path, setup_path, session_info, credentials, lp, samdb.transaction_commit() return samdb - -def provision(lp, setup_dir, message, blank, paths, session_info, - credentials, ldapbackend, realm=None, domain=None, hostname=None, - hostip=None, domainsid=None, hostguid=None, adminpass=None, - krbtgtpass=None, domainguid=None, policyguid=None, - invocationid=None, machinepass=None, dnspass=None, root=None, - nobody=None, nogroup=None, users=None, wheel=None, backup=None, - aci=None, serverrole=None): +FILL_FULL = "FULL" +FILL_NT4SYNC = "NT4SYNC" +FILL_DRS = "DRS" + +def provision(lp, setup_dir, message, paths, session_info, + credentials, samdb_fill=FILL_FULL, realm=None, rootdn=None, + domain=None, hostname=None, hostip=None, domainsid=None, + hostguid=None, adminpass=None, krbtgtpass=None, domainguid=None, + policyguid=None, invocationid=None, machinepass=None, + dnspass=None, root=None, nobody=None, nogroup=None, users=None, + wheel=None, backup=None, aci=None, serverrole=None, erase=False, + ldap_backend=None, ldap_backend_type=None): """Provision samba4 :note: caution, this wipes all existing data! @@ -595,14 +710,10 @@ def provision(lp, setup_dir, message, blank, paths, session_info, def setup_path(file): return os.path.join(setup_dir, file) - erase = False - if domainsid is None: domainsid = security.random_sid() if policyguid is None: policyguid = uuid.random() - if invocationid is None: - invocationid = uuid.random() if adminpass is None: adminpass = misc.random_password(12) if krbtgtpass is None: @@ -612,45 +723,42 @@ def provision(lp, setup_dir, message, blank, paths, session_info, if dnspass is None: dnspass = misc.random_password(12) if root is None: - root = findnss(pwd.getpwnam, "root")[4] + root = findnss(pwd.getpwnam, ["root"])[0] if nobody is None: - nobody = findnss(pwd.getpwnam, "nobody")[4] + nobody = findnss(pwd.getpwnam, ["nobody"])[0] if nogroup is None: - nogroup = findnss(grp.getgrnam, "nogroup", "nobody")[2] + nogroup = findnss(grp.getgrnam, ["nogroup", "nobody"])[0] if users is None: - users = findnss(grp.getgrnam, "users", "guest", "other", "unknown", - "usr")[2] + users = findnss(grp.getgrnam, ["users", "guest", "other", "unknown", + "usr"])[0] if wheel is None: - wheel = findnss(grp.getgrnam, "wheel", "root", "staff", "adm")[2] + wheel = findnss(grp.getgrnam, ["wheel", "root", "staff", "adm"])[0] if backup is None: - backup = findnss(grp.getgrnam, "backup", "wheel", "root", "staff")[2] + backup = findnss(grp.getgrnam, ["backup", "wheel", "root", "staff"])[0] if aci is None: aci = "# no aci for local ldb" if serverrole is None: serverrole = lp.get("server role") + assert serverrole in ("domain controller", "member server") + if invocationid is None and serverrole == "domain controller": + invocationid = uuid.random() if realm is None: realm = lp.get("realm") - else: - if lp.get("realm").upper() != realm.upper(): - raise Exception("realm '%s' in smb.conf must match chosen realm '%s'\n" % + + if lp.get("realm").upper() != realm.upper(): + raise Exception("realm '%s' in smb.conf must match chosen realm '%s'" % (lp.get("realm"), realm)) + ldapi_url = "ldapi://%s" % urllib.quote(paths.s4_ldapi_path, safe="") + + if ldap_backend == "ldapi": + # provision-backend will set this path suggested slapd command line / fedorads.inf + ldap_backend = "ldapi://" % urllib.quote(os.path.join(lp.get("private dir"), "ldap", "ldapi"), safe="") + assert realm is not None realm = realm.upper() - if domain is None: - domain = lp.get("workgroup") - else: - if lp.get("workgroup").upper() != domain.upper(): - raise Error("workgroup '%s' in smb.conf must match chosen domain '%s'\n", - lp.get("workgroup"), domain) - - assert domain is not None - domain = domain.upper() - if not valid_netbios_name(domain): - raise InvalidNetbiosName(domain) - if hostname is None: hostname = gethostname().split(".")[0] |
