diff options
-rw-r--r-- | source4/auth/credentials/config.mk | 2 | ||||
-rw-r--r-- | source4/auth/credentials/credentials.i | 3 | ||||
-rw-r--r-- | source4/auth/credentials/credentials.py | 1 | ||||
-rw-r--r-- | source4/auth/credentials/credentials_wrap.c | 30 | ||||
-rw-r--r-- | source4/auth/credentials/tests/bindings.py | 3 | ||||
-rw-r--r-- | source4/scripting/python/misc.i | 11 | ||||
-rw-r--r-- | source4/scripting/python/misc.py | 1 | ||||
-rw-r--r-- | source4/scripting/python/misc_wrap.c | 51 | ||||
-rw-r--r-- | source4/scripting/python/samba/__init__.py | 19 | ||||
-rw-r--r-- | source4/scripting/python/samba/getopt.py | 6 | ||||
-rw-r--r-- | source4/scripting/python/samba/provision.py | 506 | ||||
-rw-r--r-- | source4/scripting/python/samba/samdb.py | 11 | ||||
-rw-r--r-- | source4/scripting/python/samba/tests/__init__.py | 6 | ||||
-rw-r--r-- | source4/scripting/python/samba/upgrade.py | 5 | ||||
-rwxr-xr-x | source4/setup/provision.py | 83 |
15 files changed, 487 insertions, 251 deletions
diff --git a/source4/auth/credentials/config.mk b/source4/auth/credentials/config.mk index 8d33bdbd55..fee9519ae5 100644 --- a/source4/auth/credentials/config.mk +++ b/source4/auth/credentials/config.mk @@ -14,5 +14,5 @@ PRIVATE_DEPENDENCIES = \ SECRETS [PYTHON::swig_credentials] -PUBLIC_DEPENDENCIES = CREDENTIALS +PUBLIC_DEPENDENCIES = CREDENTIALS LIBCMDLINE_CREDENTIALS SWIG_FILE = credentials.i diff --git a/source4/auth/credentials/credentials.i b/source4/auth/credentials/credentials.i index fedb8bd1d7..41ec67580e 100644 --- a/source4/auth/credentials/credentials.i +++ b/source4/auth/credentials/credentials.i @@ -27,6 +27,7 @@ #include "includes.h" #include "auth/credentials/credentials.h" #include "param/param.h" +#include "lib/cmdline/credentials.h" typedef struct cli_credentials cli_credentials; %} @@ -93,6 +94,8 @@ typedef struct cli_credentials { bool authentication_requested(void); bool wrong_password(void); + + bool set_cmdline_callbacks(); } } cli_credentials; diff --git a/source4/auth/credentials/credentials.py b/source4/auth/credentials/credentials.py index 0d91526b8f..14526af910 100644 --- a/source4/auth/credentials/credentials.py +++ b/source4/auth/credentials/credentials.py @@ -82,6 +82,7 @@ Credentials.is_anonymous = new_instancemethod(_credentials.Credentials_is_anonym Credentials.get_nt_hash = new_instancemethod(_credentials.Credentials_get_nt_hash,None,Credentials) Credentials.authentication_requested = new_instancemethod(_credentials.Credentials_authentication_requested,None,Credentials) Credentials.wrong_password = new_instancemethod(_credentials.Credentials_wrong_password,None,Credentials) +Credentials.set_cmdline_callbacks = new_instancemethod(_credentials.Credentials_set_cmdline_callbacks,None,Credentials) Credentials_swigregister = _credentials.Credentials_swigregister Credentials_swigregister(Credentials) diff --git a/source4/auth/credentials/credentials_wrap.c b/source4/auth/credentials/credentials_wrap.c index 849b28ebff..b1b904c8a3 100644 --- a/source4/auth/credentials/credentials_wrap.c +++ b/source4/auth/credentials/credentials_wrap.c @@ -2521,6 +2521,7 @@ static swig_module_info swig_module = {swig_types, 16, 0, 0, 0, 0}; #include "includes.h" #include "auth/credentials/credentials.h" #include "param/param.h" +#include "lib/cmdline/credentials.h" typedef struct cli_credentials cli_credentials; @@ -3486,6 +3487,34 @@ fail: } +SWIGINTERN PyObject *_wrap_Credentials_set_cmdline_callbacks(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) { + PyObject *resultobj = 0; + cli_credentials *arg1 = (cli_credentials *) 0 ; + bool result; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject * obj0 = 0 ; + char * kwnames[] = { + (char *) "self", NULL + }; + + arg1 = NULL; + if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"|O:Credentials_set_cmdline_callbacks",kwnames,&obj0)) SWIG_fail; + if (obj0) { + res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_cli_credentials, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Credentials_set_cmdline_callbacks" "', argument " "1"" of type '" "cli_credentials *""'"); + } + arg1 = (cli_credentials *)(argp1); + } + result = (bool)cli_credentials_set_cmdline_callbacks(arg1); + resultobj = SWIG_From_bool((bool)(result)); + return resultobj; +fail: + return NULL; +} + + SWIGINTERN PyObject *_wrap_delete_Credentials(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) { PyObject *resultobj = 0; cli_credentials *arg1 = (cli_credentials *) 0 ; @@ -3545,6 +3574,7 @@ static PyMethodDef SwigMethods[] = { { (char *)"Credentials_get_nt_hash", (PyCFunction) _wrap_Credentials_get_nt_hash, METH_VARARGS | METH_KEYWORDS, NULL}, { (char *)"Credentials_authentication_requested", (PyCFunction) _wrap_Credentials_authentication_requested, METH_VARARGS | METH_KEYWORDS, NULL}, { (char *)"Credentials_wrong_password", (PyCFunction) _wrap_Credentials_wrong_password, METH_VARARGS | METH_KEYWORDS, NULL}, + { (char *)"Credentials_set_cmdline_callbacks", (PyCFunction) _wrap_Credentials_set_cmdline_callbacks, METH_VARARGS | METH_KEYWORDS, NULL}, { (char *)"delete_Credentials", (PyCFunction) _wrap_delete_Credentials, METH_VARARGS | METH_KEYWORDS, NULL}, { (char *)"Credentials_swigregister", Credentials_swigregister, METH_VARARGS, NULL}, { (char *)"Credentials_swiginit", Credentials_swiginit, METH_VARARGS, NULL}, diff --git a/source4/auth/credentials/tests/bindings.py b/source4/auth/credentials/tests/bindings.py index 8312e77e9e..d2ca68d115 100644 --- a/source4/auth/credentials/tests/bindings.py +++ b/source4/auth/credentials/tests/bindings.py @@ -83,6 +83,9 @@ class CredentialsTests(unittest.TestCase): # Just check the method is there and doesn't raise an exception self.creds.guess() + def test_set_cmdline_callbacks(self): + self.creds.set_cmdline_callbacks() + def test_authentication_requested(self): self.creds.set_username("") self.assertFalse(self.creds.authentication_requested()) diff --git a/source4/scripting/python/misc.i b/source4/scripting/python/misc.i index 2f41840670..a11b2fb825 100644 --- a/source4/scripting/python/misc.i +++ b/source4/scripting/python/misc.i @@ -66,3 +66,14 @@ WERROR dsdb_attach_schema_from_ldif_file(struct ldb_context *ldb, const char *pf const char *samba_version_string(void); int dsdb_set_global_schema(struct ldb_context *ldb); int ldb_register_samba_handlers(struct ldb_context *ldb); + +%inline %{ +bool dsdb_set_ntds_invocation_id(struct ldb_context *ldb, const char *guid) +{ + struct GUID invocation_id_in; + if (NT_STATUS_IS_ERR(GUID_from_string(guid, &invocation_id_in))) { + return false; + } + return samdb_set_ntds_invocation_id(ldb, &invocation_id_in); +} +%} diff --git a/source4/scripting/python/misc.py b/source4/scripting/python/misc.py index ae900a1f62..2fc7fe37e7 100644 --- a/source4/scripting/python/misc.py +++ b/source4/scripting/python/misc.py @@ -70,5 +70,6 @@ dsdb_attach_schema_from_ldif_file = _misc.dsdb_attach_schema_from_ldif_file version = _misc.version dsdb_set_global_schema = _misc.dsdb_set_global_schema ldb_register_samba_handlers = _misc.ldb_register_samba_handlers +dsdb_set_ntds_invocation_id = _misc.dsdb_set_ntds_invocation_id diff --git a/source4/scripting/python/misc_wrap.c b/source4/scripting/python/misc_wrap.c index a7493550cc..f467f851bd 100644 --- a/source4/scripting/python/misc_wrap.c +++ b/source4/scripting/python/misc_wrap.c @@ -2794,6 +2794,16 @@ SWIG_From_int (int value) return SWIG_From_long (value); } + +bool dsdb_set_ntds_invocation_id(struct ldb_context *ldb, const char *guid) +{ + struct GUID invocation_id_in; + if (NT_STATUS_IS_ERR(GUID_from_string(guid, &invocation_id_in))) { + return false; + } + return samdb_set_ntds_invocation_id(ldb, &invocation_id_in); +} + #ifdef __cplusplus extern "C" { #endif @@ -3102,6 +3112,46 @@ fail: } +SWIGINTERN PyObject *_wrap_dsdb_set_ntds_invocation_id(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) { + PyObject *resultobj = 0; + struct ldb_context *arg1 = (struct ldb_context *) 0 ; + char *arg2 = (char *) 0 ; + bool result; + void *argp1 = 0 ; + int res1 = 0 ; + int res2 ; + char *buf2 = 0 ; + int alloc2 = 0 ; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + char * kwnames[] = { + (char *) "ldb",(char *) "guid", NULL + }; + + if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OO:dsdb_set_ntds_invocation_id",kwnames,&obj0,&obj1)) SWIG_fail; + res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ldb_context, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "dsdb_set_ntds_invocation_id" "', argument " "1"" of type '" "struct ldb_context *""'"); + } + arg1 = (struct ldb_context *)(argp1); + res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "dsdb_set_ntds_invocation_id" "', argument " "2"" of type '" "char const *""'"); + } + arg2 = (char *)(buf2); + if (arg1 == NULL) + SWIG_exception(SWIG_ValueError, + "ldb context must be non-NULL"); + result = (bool)dsdb_set_ntds_invocation_id(arg1,(char const *)arg2); + resultobj = SWIG_From_bool((bool)(result)); + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + return resultobj; +fail: + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + return NULL; +} + + static PyMethodDef SwigMethods[] = { { (char *)"random_password", (PyCFunction) _wrap_random_password, METH_VARARGS | METH_KEYWORDS, NULL}, { (char *)"ldb_set_credentials", (PyCFunction) _wrap_ldb_set_credentials, METH_VARARGS | METH_KEYWORDS, NULL}, @@ -3112,6 +3162,7 @@ static PyMethodDef SwigMethods[] = { { (char *)"version", (PyCFunction)_wrap_version, METH_NOARGS, NULL}, { (char *)"dsdb_set_global_schema", (PyCFunction) _wrap_dsdb_set_global_schema, METH_VARARGS | METH_KEYWORDS, NULL}, { (char *)"ldb_register_samba_handlers", (PyCFunction) _wrap_ldb_register_samba_handlers, METH_VARARGS | METH_KEYWORDS, NULL}, + { (char *)"dsdb_set_ntds_invocation_id", (PyCFunction) _wrap_dsdb_set_ntds_invocation_id, METH_VARARGS | METH_KEYWORDS, NULL}, { NULL, NULL, 0, NULL } }; diff --git a/source4/scripting/python/samba/__init__.py b/source4/scripting/python/samba/__init__.py index 483929661d..5c14edd357 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 @@ -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 dfcf2c457e..088a5acf6f 100644 --- a/source4/scripting/python/samba/getopt.py +++ b/source4/scripting/python/samba/getopt.py @@ -50,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, @@ -62,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): @@ -77,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 d59cea121e..918d983782 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 @@ -53,7 +69,7 @@ class ProvisionPaths: 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,12 +77,11 @@ 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): @@ -112,7 +127,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,7 +143,7 @@ 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) @@ -159,19 +174,20 @@ 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) -def provision_paths_from_lp(lp, dnsdomain): +def provision_paths_from_lp(lp, dnsdomain, private_dir=None): """Set the default paths for provisioning. :param lp: Loadparm context. :param dnsdomain: DNS Domain name """ paths = ProvisionPaths() - private_dir = lp.get("private dir") + if private_dir is None: + private_dir = lp.get("private dir") 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") @@ -235,63 +251,160 @@ 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. + :param + + :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 + schema_ldb = "schema.ldb" + if ldap_backend is not None: + schema_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"] + + 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,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), + }) - samdb = SamDB(paths.samdb, session_info=session_info, + 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.load_ldif_file_add(setup_path("secrets.ldif")) @@ -299,13 +412,29 @@ def setup_secretsdb(path, setup_path, session_info, credentials, lp): 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 +446,12 @@ 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 +464,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 +500,39 @@ 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. + + """ - 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 +542,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 +551,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 +581,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 +631,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 +643,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 +662,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, ldapbackend, 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 +682,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: @@ -628,29 +711,25 @@ def provision(lp, setup_dir, message, blank, paths, session_info, aci = "# no aci for local ldb" if serverrole is None: serverrole = lp.get("server role") + 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) + + 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")) + 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].lower() @@ -662,13 +741,30 @@ def provision(lp, setup_dir, message, blank, paths, session_info, raise InvalidNetbiosName(netbiosname) dnsdomain = realm.lower() - domaindn = "DC=" + dnsdomain.replace(".", ",DC=") - rootdn = domaindn + if serverrole == "domain controller": + domaindn = "DC=" + dnsdomain.replace(".", ",DC=") + if domain is None: + domain = lp.get("workgroup") + + if lp.get("workgroup").upper() != domain.upper(): + raise Error("workgroup '%s' in smb.conf must match chosen domain '%s'", + lp.get("workgroup"), domain) + + assert domain is not None + domain = domain.upper() + if not valid_netbios_name(domain): + raise InvalidNetbiosName(domain) + + else: + domaindn = "CN=" + netbiosname + domain = netbiosname + + if rootdn is None: + rootdn = domaindn + configdn = "CN=Configuration," + rootdn schemadn = "CN=Schema," + configdn - rdn_dc = domaindn.split(",")[0][len("DC="):] - message("set DOMAIN SID: %s" % str(domainsid)) message("Provisioning for %s in realm %s" % (domain, realm)) message("Using administrator password: %s" % adminpass) @@ -684,7 +780,8 @@ def provision(lp, setup_dir, message, blank, paths, session_info, smbconfsuffix = "member" else: assert "Invalid server role setting: %s" % serverrole - setup_file(setup_path("provision.smb.conf.%s" % smbconfsuffix), paths.smbconf, { + setup_file(setup_path("provision.smb.conf.%s" % smbconfsuffix), + paths.smbconf, { "HOSTNAME": hostname, "DOMAIN_CONF": domain, "REALM_CONF": realm, @@ -701,6 +798,7 @@ def provision(lp, setup_dir, message, blank, paths, session_info, credentials=credentials, lp=lp) share_ldb.load_ldif_file_add(setup_path("share.ldif")) + message("Setting up secrets.ldb") secrets_ldb = setup_secretsdb(paths.secrets, setup_path, session_info=session_info, @@ -714,44 +812,47 @@ def provision(lp, setup_dir, message, blank, paths, session_info, setup_templatesdb(paths.templates, setup_path, session_info=session_info, credentials=credentials, lp=lp) - samdb = setup_samdb(paths.samdb, setup_path, session_info=session_info, credentials=credentials, - lp=lp, schemadn=schemadn, configdn=configdn, domaindn=domaindn, - dnsdomain=dnsdomain, netbiosname=netbiosname, realm=realm, message=message, - hostname=hostname, rootdn=rootdn, erase=erase, domainsid=domainsid, aci=aci, - rdn_dc=rdn_dc, domainguid=domainguid, policyguid=policyguid, - domainname=domain, blank=blank, adminpass=adminpass, krbtgtpass=krbtgtpass, - hostguid=hostguid, invocationid=invocationid, machinepass=machinepass, - dnspass=dnspass) + samdb = setup_samdb(paths.samdb, setup_path, session_info=session_info, + credentials=credentials, lp=lp, schemadn=schemadn, + configdn=configdn, domaindn=domaindn, + dnsdomain=dnsdomain, netbiosname=netbiosname, + realm=realm, message=message, hostname=hostname, + rootdn=rootdn, erase=erase, domainsid=domainsid, + aci=aci, domainguid=domainguid, policyguid=policyguid, + domainname=domain, fill=samdb_fill, + adminpass=adminpass, krbtgtpass=krbtgtpass, + hostguid=hostguid, invocationid=invocationid, + machinepass=machinepass, dnspass=dnspass, + serverrole=serverrole, ldap_backend=ldap_backend, + ldap_backend_type=ldap_backend_type) if lp.get("server role") == "domain controller": - os.makedirs(os.path.join(paths.sysvol, dnsdomain, "Policies", "{" + policyguid + "}"), 0755) - os.makedirs(os.path.join(paths.sysvol, dnsdomain, "Policies", "{" + policyguid + "}", "Machine"), 0755) - os.makedirs(os.path.join(paths.sysvol, dnsdomain, "Policies", "{" + policyguid + "}", "User"), 0755) - if not os.path.isdir(paths.netlogon): + policy_path = os.path.join(paths.sysvol, dnsdomain, "Policies", + "{" + policyguid + "}") + os.makedirs(policy_path, 0755) + os.makedirs(os.path.join(policy_path, "Machine"), 0755) + os.makedirs(os.path.join(policy_path, "User"), 0755) + if not os.path.isdir(paths.netlogon): os.makedirs(paths.netlogon, 0755) - secrets_ldb = Ldb(paths.secrets, session_info=session_info, credentials=credentials, lp=lp) - setup_ldb(secrets_ldb, setup_path("secrets_dc.ldif"), { - "MACHINEPASS_B64": b64encode(machinepass), - "DOMAIN": domain, - "REALM": realm, - "LDAPTIME": timestring(int(time.time())), - "DNSDOMAIN": dnsdomain, - "DOMAINSID": str(domainsid), - "SECRETS_KEYTAB": paths.keytab, - "NETBIOSNAME": netbiosname, - "SAM_LDB": paths.samdb, - "DNS_KEYTAB": paths.dns_keytab, - "DNSPASS_B64": b64encode(dnspass), - }) - - if not blank: - setup_name_mappings(samdb, str(domainsid), - domaindn, root=root, nobody=nobody, - nogroup=nogroup, wheel=wheel, users=users, - backup=backup) + secrets_ldb = Ldb(paths.secrets, session_info=session_info, + credentials=credentials, lp=lp) + secretsdb_become_dc(secrets_ldb, setup_path, domain=domain, realm=realm, + netbiosname=netbiosname, domainsid=domainsid, + keytab_path=paths.keytab, samdb_url=paths.samdb, + dns_keytab_path=paths.dns_keytab, dnspass=dnspass, + machinepass=machinepass, dnsdomain=dnsdomain) + + if samdb_fill == FILL_FULL: + setup_name_mappings(samdb, str(domainsid), domaindn, root=root, + nobody=nobody, nogroup=nogroup, wheel=wheel, + users=users, backup=backup) + + message("Setting up sam.ldb rootDSE marking as synchronized") + setup_modify_ldif(samdb, setup_path("provision_rootdse_modify.ldif")) message("Setting up phpLDAPadmin configuration") - create_phplpapdadmin_config(paths.phpldapadminconfig, setup_path, paths.s4_ldapi_path) + create_phpldapadmin_config(paths.phpldapadminconfig, setup_path, + ldapi_url) message("Please install the phpLDAPadmin configuration located at %s into /etc/phpldapadmin/config.php" % paths.phpldapadminconfig) @@ -775,15 +876,15 @@ def provision(lp, setup_dir, message, blank, paths, session_info, return domaindn -def create_phplpapdadmin_config(path, setup_path, s4_ldapi_path): + +def create_phpldapadmin_config(path, setup_path, ldap_backend): """Create a PHP LDAP admin configuration file. :param path: Path to write the configuration to. :param setup_path: Function to generate setup paths. - :param s4_ldapi_path: Path to Samba 4 LDAPI socket. """ - setup_file(setup_path("phpldapadmin-config.php"), - path, {"S4_LDAPI_URI": "ldapi://%s" % s4_ldapi_path.replace("/", "%2F")}) + setup_file(setup_path("phpldapadmin-config.php"), path, + {"S4_LDAPI_URI": ldap_backend}) def create_zone_file(path, setup_path, samdb, dnsdomain, domaindn, @@ -833,6 +934,7 @@ def load_schema(setup_path, samdb, schemadn, netbiosname, configdn): "SCHEMADN": schemadn, "NETBIOSNAME": netbiosname, "CONFIGDN": configdn, - "DEFAULTSITE": DEFAULTSITE}) + "DEFAULTSITE": DEFAULTSITE + }) samdb.attach_schema_from_ldif(head_data, schema_data) diff --git a/source4/scripting/python/samba/samdb.py b/source4/scripting/python/samba/samdb.py index 353eaee198..b757330ecb 100644 --- a/source4/scripting/python/samba/samdb.py +++ b/source4/scripting/python/samba/samdb.py @@ -1,10 +1,10 @@ #!/usr/bin/python # Unix SMB/CIFS implementation. -# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007 +# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007-2008 # # Based on the original in EJS: -# Copyright (C) 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 @@ -145,3 +145,10 @@ member: %s def attach_schema_from_ldif(self, pf, df): misc.dsdb_attach_schema_from_ldif_file(self, pf, df) + + def set_invocation_id(self, invocation_id): + """Set the invocation id for this SamDB handle. + + :param invocation_id: GUID of the invocation id. + """ + misc.dsdb_set_ntds_invocation_id(self, invocation_id) diff --git a/source4/scripting/python/samba/tests/__init__.py b/source4/scripting/python/samba/tests/__init__.py index ad8a2524b5..9839811470 100644 --- a/source4/scripting/python/samba/tests/__init__.py +++ b/source4/scripting/python/samba/tests/__init__.py @@ -1,7 +1,7 @@ #!/usr/bin/python # Unix SMB/CIFS implementation. -# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007 +# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007-2008 # # 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 @@ -67,6 +67,10 @@ class SubstituteVarTestCase(unittest.TestCase): def test_unknown_var(self): self.assertEquals("foo ${bla} gsff", samba.substitute_var("foo ${bla} gsff", {"bar": "bla"})) + + def test_check_all_substituted(self): + check_all_substituted("nothing to see here") + self.assertRaises(Exception, check_all_substituted, "Not subsituted: ${FOOBAR}") class LdbExtensionTests(TestCaseInTempDir): diff --git a/source4/scripting/python/samba/upgrade.py b/source4/scripting/python/samba/upgrade.py index abf1127c36..a118af2526 100644 --- a/source4/scripting/python/samba/upgrade.py +++ b/source4/scripting/python/samba/upgrade.py @@ -7,7 +7,7 @@ """Support code for upgrading from Samba 3 to Samba 4.""" -from provision import findnss, provision +from provision import findnss, provision, FILL_DRS import grp import ldb import pwd @@ -245,7 +245,8 @@ def upgrade_provision(samba3, setup_dir, message, credentials, session_info, lp, else: machinepass = None - domaindn = provision(lp=lp, setup_dir=setup_dir, message=message, blank=True, ldapbackend=None, + domaindn = provision(lp=lp, setup_dir=setup_dir, message=message, + samdb_fill=FILL_DRS, ldapbackend=None, paths=paths, session_info=session_info, credentials=credentials, realm=realm, domain=domainname, domainsid=domainsid, domainguid=domainguid, machinepass=machinepass, serverrole=serverrole) diff --git a/source4/setup/provision.py b/source4/setup/provision.py index b9a11bdd78..743a94700d 100755 --- a/source4/setup/provision.py +++ b/source4/setup/provision.py @@ -33,8 +33,10 @@ import samba from auth import system_session import samba.getopt as options import param -from samba.provision import (provision, - provision_paths_from_lp) +from samba.provision import (provision, + provision_paths_from_lp, + FILL_FULL, FILL_NT4SYNC, + FILL_DRS) parser = optparse.OptionParser("provision [options]") sambaopts = options.SambaOptions(parser) @@ -84,8 +86,9 @@ parser.add_option("--blank", action="store_true", help="do not add users or groups, just the structure") parser.add_option("--ldap-backend", type="string", metavar="LDAPSERVER", help="LDAP server to use for this provision") -parser.add_option("--ldap-module=", type="string", metavar="MODULE", - help="LDB mapping module to use for the LDAP backend") +parser.add_option("--ldap-backend-type", type="choice", metavar="LDAP-BACKEND-TYPE", + help="LDB mapping module to use for the LDAP backend", + choices=["fedora-ds", "openldap"]) parser.add_option("--aci", type="string", metavar="ACI", help="An arbitary LDIF fragment, particularly useful to loading a backend ACI value into a target LDAP server. You must provide at least a realm and domain") parser.add_option("--server-role", type="choice", metavar="ROLE", @@ -122,51 +125,47 @@ lp.set("realm", opts.realm) lp.set("workgroup", opts.domain) lp.set("server role", opts.server_role or "domain controller") + if opts.aci is not None: print "set ACI: %s" % opts.aci -paths = provision_paths_from_lp(lp, opts.realm.lower()) +private_dir = None +if opts.targetdir is not None: + private_dir = os.path.join(opts.targetdir, "private") +paths = provision_paths_from_lp(lp, opts.realm.lower(), private_dir) paths.smbconf = sambaopts.get_loadparm_path() -if opts.ldap_backend: - if opts.ldap_backend == "ldapi": - subobj.ldap_backend = subobj.ldapi_uri - - if not opts.ldap_module: - subobj.ldapmodule = "entryuuid" - - subobj.domaindn_ldb = subobj.ldap_backend - subobj.domaindn_mod2 = ",%s,paged_searches" % subobj.ldapmodule - subobj.configdn_ldb = subobj.ldap_backend - subobj.configdn_mod2 = ",%s,paged_searches" % subobj.ldapmodule - subobj.schemadn_ldb = subobj.ldap_backend - subobj.schemadn_mod2 = ",%s,paged_searches" % subobj.ldapmodule - message("LDAP module: %s on backend: %s" % (subobj.ldapmodule, subobj.ldap_backend)) - creds = credopts.get_credentials() setup_dir = opts.setupdir if setup_dir is None: setup_dir = "setup" -if opts.partitions_only: - provision_become_dc(setup_dir, message, False, - paths, lp, system_session(), creds) -else: - provision(lp, setup_dir, message, opts.blank, paths, - system_session(), creds, opts.ldap_backend, realm=opts.realm, - domainguid=opts.domain_guid, domainsid=opts.domain_sid, - policyguid=opts.policy_guid, hostname=opts.host_name, - hostip=opts.host_ip, hostguid=opts.host_guid, - invocationid=opts.invocationid, adminpass=opts.adminpass, - krbtgtpass=opts.krbtgtpass, machinepass=opts.machinepass, - dnspass=opts.dnspass, root=opts.root, nobody=opts.nobody, - nogroup=opts.nogroup, wheel=opts.wheel, users=opts.users, - aci=opts.aci, serverrole=opts.server_role) - message("To reproduce this provision, run with:") - def shell_escape(arg): - if " " in arg: - return '"%s"' % arg - return arg - message(" ".join([shell_escape(arg) for arg in sys.argv])) - -message("All OK") + +samdb_fill = FILL_FULL +if opts.blank: + samdb_fill = FILL_NT4SYNC +elif opts.partitions_only: + samdb_fill = FILL_DRS + +provision(lp, setup_dir, message, paths, + system_session(), creds, opts.ldap_backend, + samdb_fill=samdb_fill, realm=opts.realm, + domainguid=opts.domain_guid, domainsid=opts.domain_sid, + policyguid=opts.policy_guid, hostname=opts.host_name, + hostip=opts.host_ip, hostguid=opts.host_guid, + invocationid=opts.invocationid, adminpass=opts.adminpass, + krbtgtpass=opts.krbtgtpass, machinepass=opts.machinepass, + dnspass=opts.dnspass, root=opts.root, nobody=opts.nobody, + nogroup=opts.nogroup, wheel=opts.wheel, users=opts.users, + aci=opts.aci, serverrole=opts.server_role, + ldap_backend=opts.ldap_backend, + ldap_backend_type=opts.ldap_backend_type) + +message("To reproduce this provision, run with:") +def shell_escape(arg): + if " " in arg: + return '"%s"' % arg + return arg +message(" ".join([shell_escape(arg) for arg in sys.argv])) + +message("All OK")
\ No newline at end of file |