summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/auth/credentials/config.mk2
-rw-r--r--source4/auth/credentials/credentials.i3
-rw-r--r--source4/auth/credentials/credentials.py1
-rw-r--r--source4/auth/credentials/credentials_wrap.c30
-rw-r--r--source4/auth/credentials/tests/bindings.py3
-rw-r--r--source4/scripting/python/misc.i11
-rw-r--r--source4/scripting/python/misc.py1
-rw-r--r--source4/scripting/python/misc_wrap.c51
-rw-r--r--source4/scripting/python/samba/__init__.py19
-rw-r--r--source4/scripting/python/samba/getopt.py6
-rw-r--r--source4/scripting/python/samba/provision.py506
-rw-r--r--source4/scripting/python/samba/samdb.py11
-rw-r--r--source4/scripting/python/samba/tests/__init__.py6
-rw-r--r--source4/scripting/python/samba/upgrade.py5
-rwxr-xr-xsource4/setup/provision.py83
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