From ba58edd0bc2d77c6ed1b6a76f33787da9031db5b Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 14 Jul 2009 08:00:09 +1000 Subject: Add a way to set an opaque integer onto a samdb This will allow us to set some more flags into ldb during the provision. --- source4/scripting/python/pyglue.c | 59 +++++++++++++++++++++++++++++++++ source4/scripting/python/samba/samdb.py | 8 +++++ 2 files changed, 67 insertions(+) (limited to 'source4/scripting/python') diff --git a/source4/scripting/python/pyglue.c b/source4/scripting/python/pyglue.c index 5816d9637d..abd018f6fc 100644 --- a/source4/scripting/python/pyglue.c +++ b/source4/scripting/python/pyglue.c @@ -204,6 +204,63 @@ static PyObject *py_dsdb_set_ntds_invocation_id(PyObject *self, PyObject *args) Py_RETURN_NONE; } +static PyObject *py_dsdb_set_opaque_integer(PyObject *self, PyObject *args) +{ + PyObject *py_ldb; + int value; + int *old_val, *new_val; + char *py_opaque_name, *opaque_name_talloc; + struct ldb_context *ldb; + TALLOC_CTX *tmp_ctx; + + if (!PyArg_ParseTuple(args, "Osi", &py_ldb, &py_opaque_name, &value)) + return NULL; + + PyErr_LDB_OR_RAISE(py_ldb, ldb); + + /* see if we have a cached copy */ + old_val = (int *)ldb_get_opaque(ldb, + py_opaque_name); + + if (old_val) { + *old_val = value; + Py_RETURN_NONE; + } + + tmp_ctx = talloc_new(ldb); + if (tmp_ctx == NULL) { + goto failed; + } + + new_val = talloc(tmp_ctx, int); + if (!new_val) { + goto failed; + } + + opaque_name_talloc = talloc_strdup(tmp_ctx, py_opaque_name); + if (!opaque_name_talloc) { + goto failed; + } + + *new_val = value; + + /* cache the domain_sid in the ldb */ + if (ldb_set_opaque(ldb, opaque_name_talloc, new_val) != LDB_SUCCESS) { + goto failed; + } + + talloc_steal(ldb, new_val); + talloc_steal(ldb, opaque_name_talloc); + talloc_free(tmp_ctx); + + Py_RETURN_NONE; + +failed: + talloc_free(tmp_ctx); + PyErr_SetString(PyExc_RuntimeError, "Failed to set opaque integer into the ldb!\n"); + return NULL; +} + static PyObject *py_dsdb_set_global_schema(PyObject *self, PyObject *args) { PyObject *py_ldb; @@ -284,6 +341,8 @@ static PyMethodDef py_misc_methods[] = { "Register Samba-specific LDB modules and schemas." }, { "dsdb_set_ntds_invocation_id", (PyCFunction)py_dsdb_set_ntds_invocation_id, METH_VARARGS, NULL }, + { "dsdb_set_opaque_integer", (PyCFunction)py_dsdb_set_opaque_integer, METH_VARARGS, + NULL }, { "dsdb_set_global_schema", (PyCFunction)py_dsdb_set_global_schema, METH_VARARGS, NULL }, { "dsdb_attach_schema_from_ldif", (PyCFunction)py_dsdb_attach_schema_from_ldif, METH_VARARGS, diff --git a/source4/scripting/python/samba/samdb.py b/source4/scripting/python/samba/samdb.py index bc76cd3c5f..6cb2469846 100644 --- a/source4/scripting/python/samba/samdb.py +++ b/source4/scripting/python/samba/samdb.py @@ -231,6 +231,14 @@ userPassword:: %s """ glue.dsdb_set_ntds_invocation_id(self, invocation_id) + def set_opaque_integer(self, name, value): + """Set an integer as an opaque (a flag or other value) value on the database + + :param name: The name for the opaque value + :param value: The integer value + """ + glue.dsdb_set_opaque_integer(self, name, value) + def setexpiry(self, user, expiry_seconds, noexpiry): """Set the account expiry for a user -- cgit From 271b5af92e9aada36adc648a6dd43a13c5aed340 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 14 Jul 2009 08:15:50 +1000 Subject: s4:dsdb Handle dc/domain/forest functional levels properly Rather than have the functional levels scattered in 4 different, unconnected locations, the provision script now sets it, and the rootdse module maintains it's copy only as a cached view onto the original values. We also use the functional level to determine if we should store AES Kerberos keys. Andrew Bartlett --- source4/scripting/python/pyglue.c | 6 ++++++ source4/scripting/python/samba/__init__.py | 5 +++++ source4/scripting/python/samba/provision.py | 24 +++++++++++++++++++----- 3 files changed, 30 insertions(+), 5 deletions(-) (limited to 'source4/scripting/python') diff --git a/source4/scripting/python/pyglue.c b/source4/scripting/python/pyglue.c index abd018f6fc..c6b731ce8b 100644 --- a/source4/scripting/python/pyglue.c +++ b/source4/scripting/python/pyglue.c @@ -362,5 +362,11 @@ void initglue(void) return; PyModule_AddObject(m, "version", PyString_FromString(SAMBA_VERSION_STRING)); + + PyModule_AddObject(m, "DS_BEHAVIOR_WIN2000", PyInt_FromLong(DS_BEHAVIOR_WIN2000)); + PyModule_AddObject(m, "DS_BEHAVIOR_WIN2003_INTERIM", PyInt_FromLong(DS_BEHAVIOR_WIN2003_INTERIM)); + PyModule_AddObject(m, "DS_BEHAVIOR_WIN2003", PyInt_FromLong(DS_BEHAVIOR_WIN2003)); + PyModule_AddObject(m, "DS_BEHAVIOR_WIN2008", PyInt_FromLong(DS_BEHAVIOR_WIN2008)); + } diff --git a/source4/scripting/python/samba/__init__.py b/source4/scripting/python/samba/__init__.py index 60a7919136..e3ebc4a637 100644 --- a/source4/scripting/python/samba/__init__.py +++ b/source4/scripting/python/samba/__init__.py @@ -242,3 +242,8 @@ def valid_netbios_name(name): return True version = glue.version + +DS_BEHAVIOR_WIN2000 = glue.DS_BEHAVIOR_WIN2000 +DS_BEHAVIOR_WIN2003_INTERIM = glue.DS_BEHAVIOR_WIN2003_INTERIM +DS_BEHAVIOR_WIN2003 = glue.DS_BEHAVIOR_WIN2003 +DS_BEHAVIOR_WIN2008 = glue.DS_BEHAVIOR_WIN2008 diff --git a/source4/scripting/python/samba/provision.py b/source4/scripting/python/samba/provision.py index 189c93a1fc..8f57105224 100644 --- a/source4/scripting/python/samba/provision.py +++ b/source4/scripting/python/samba/provision.py @@ -37,7 +37,8 @@ import param import registry import samba from auth import system_session -from samba import Ldb, substitute_var, valid_netbios_name, check_all_substituted +from samba import version, Ldb, substitute_var, valid_netbios_name, check_all_substituted, \ + DS_BEHAVIOR_WIN2000, DS_BEHAVIOR_WIN2003_INTERIM, DS_BEHAVIOR_WIN2003, DS_BEHAVIOR_WIN2008 from samba.samdb import SamDB from samba.idmap import IDmapDB from samba.dcerpc import security @@ -729,7 +730,7 @@ def setup_samdb_rootdse(samdb, setup_path, names): def setup_self_join(samdb, names, machinepass, dnspass, domainsid, invocationid, setup_path, - policyguid): + policyguid, domainControllerFunctionality): """Join a host to its own domain.""" assert isinstance(invocationid, str) setup_add_ldif(samdb, setup_path("provision_self_join.ldif"), { @@ -745,7 +746,9 @@ def setup_self_join(samdb, names, "DNSPASS_B64": b64encode(dnspass), "REALM": names.realm, "DOMAIN": names.domain, - "DNSDOMAIN": names.dnsdomain}) + "DNSDOMAIN": names.dnsdomain, + "SAMBA_VERSION_STRING": version, + "DOMAIN_CONTROLLER_FUNCTIONALITY": str(domainControllerFunctionality)}) setup_add_ldif(samdb, setup_path("provision_group_policy.ldif"), { "POLICYGUID": policyguid, "DNSDOMAIN": names.dnsdomain, @@ -765,6 +768,10 @@ def setup_samdb(path, setup_path, session_info, credentials, lp, :note: This will wipe the main SAM database file! """ + domainFunctionality = DS_BEHAVIOR_WIN2008 + forestFunctionality = DS_BEHAVIOR_WIN2008 + domainControllerFunctionality = DS_BEHAVIOR_WIN2008 + erase = (fill != FILL_DRS) # Also wipes the database @@ -780,6 +787,11 @@ def setup_samdb(path, setup_path, session_info, credentials, lp, return samdb message("Pre-loading the Samba 4 and AD schema") + + samdb.set_opaque_integer("domainFunctionality", domainFunctionality) + samdb.set_opaque_integer("forestFunctionality", forestFunctionality) + samdb.set_opaque_integer("domainControllerFunctionality", domainControllerFunctionality) + samdb.set_domain_sid(str(domainsid)) if serverrole == "domain controller": samdb.set_invocation_id(invocationid) @@ -818,6 +830,7 @@ def setup_samdb(path, setup_path, session_info, credentials, lp, "POLICYGUID": policyguid, "DOMAINDN": names.domaindn, "DOMAINGUID_MOD": domainguid_mod, + "DOMAIN_FUNCTIONALITY": str(domainFunctionality) }) message("Adding configuration container (permitted to fail)") @@ -864,7 +877,8 @@ def setup_samdb(path, setup_path, session_info, credentials, lp, "DOMAIN": names.domain, "SCHEMADN": names.schemadn, "DOMAINDN": names.domaindn, - "SERVERDN": names.serverdn + "SERVERDN": names.serverdn, + "FOREST_FUNCTIONALALITY": str(forestFunctionality) }) message("Setting up display specifiers") @@ -908,7 +922,7 @@ def setup_samdb(path, setup_path, session_info, credentials, lp, dnspass=dnspass, machinepass=machinepass, domainsid=domainsid, policyguid=policyguid, - setup_path=setup_path) + setup_path=setup_path, domainControllerFunctionality=domainControllerFunctionality) except: samdb.transaction_cancel() -- cgit From d356669492912ad97d031694123b628a9307c3bd Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 18 Jul 2009 16:11:21 +0200 Subject: Remove pyldb_util and simply duplicate the 5-line function it contains, rather than creating a separate shared library for it. --- source4/scripting/python/pyglue.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'source4/scripting/python') diff --git a/source4/scripting/python/pyglue.c b/source4/scripting/python/pyglue.c index c6b731ce8b..0869d2feac 100644 --- a/source4/scripting/python/pyglue.c +++ b/source4/scripting/python/pyglue.c @@ -46,6 +46,15 @@ } */\ ldb = PyLdb_AsLdbContext(py_ldb); +static void PyErr_SetLdbError(PyObject *error, int ret, struct ldb_context *ldb_ctx) +{ + if (ret == LDB_ERR_PYTHON_EXCEPTION) + return; /* Python exception should already be set, just keep that */ + + PyErr_SetObject(error, + Py_BuildValue(discard_const_p(char, "(i,s)"), ret, + ldb_ctx == NULL?ldb_strerror(ret):ldb_errstring(ldb_ctx))); +} static PyObject *py_ldb_get_exception(void) { -- cgit From 7883897b8d4e5993e636d3cde8bad509ee272fcb Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 18 Jul 2009 18:39:20 +0200 Subject: python: Set right ldb modules directory when using system ldb. --- source4/scripting/python/samba/__init__.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source4/scripting/python') diff --git a/source4/scripting/python/samba/__init__.py b/source4/scripting/python/samba/__init__.py index e3ebc4a637..131d1a3ac6 100644 --- a/source4/scripting/python/samba/__init__.py +++ b/source4/scripting/python/samba/__init__.py @@ -73,6 +73,8 @@ class Ldb(ldb.Ldb): self.set_modules_dir(modules_dir) elif default_ldb_modules_dir is not None: self.set_modules_dir(default_ldb_modules_dir) + elif lp is not None: + self.set_modules_dir(os.path.join(lp.get("modules dir"), "ldb")) if credentials is not None: self.set_credentials(credentials) -- cgit From 478446f96dae1f42312b72fda4210f1300023e57 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 19 Jul 2009 18:51:15 +0200 Subject: Remove unnecessary imports. --- source4/scripting/python/samba/__init__.py | 1 - source4/scripting/python/samba/getopt.py | 2 +- source4/scripting/python/samba/idmap.py | 2 -- source4/scripting/python/samba/provision.py | 5 ++--- source4/scripting/python/samba/samba3.py | 4 ++-- source4/scripting/python/samba/upgrade.py | 9 ++++----- 6 files changed, 9 insertions(+), 14 deletions(-) (limited to 'source4/scripting/python') diff --git a/source4/scripting/python/samba/__init__.py b/source4/scripting/python/samba/__init__.py index 131d1a3ac6..164803bb65 100644 --- a/source4/scripting/python/samba/__init__.py +++ b/source4/scripting/python/samba/__init__.py @@ -42,7 +42,6 @@ else: import ldb -import credentials import glue class Ldb(ldb.Ldb): diff --git a/source4/scripting/python/samba/getopt.py b/source4/scripting/python/samba/getopt.py index c12245f6c5..8b756b2d6f 100644 --- a/source4/scripting/python/samba/getopt.py +++ b/source4/scripting/python/samba/getopt.py @@ -20,7 +20,7 @@ """Support for parsing Samba-related command-line options.""" import optparse -from credentials import Credentials, AUTO_USE_KERBEROS, DONT_USE_KERBEROS, MUST_USE_KERBEROS +from credentials import Credentials, DONT_USE_KERBEROS, MUST_USE_KERBEROS from hostconfig import Hostconfig __docformat__ = "restructuredText" diff --git a/source4/scripting/python/samba/idmap.py b/source4/scripting/python/samba/idmap.py index f8eeb18925..ee79be1af9 100644 --- a/source4/scripting/python/samba/idmap.py +++ b/source4/scripting/python/samba/idmap.py @@ -23,8 +23,6 @@ __docformat__ = "restructuredText" import samba -import glue -import ldb class IDmapDB(samba.Ldb): """The IDmap database.""" diff --git a/source4/scripting/python/samba/provision.py b/source4/scripting/python/samba/provision.py index 8f57105224..8a7ed6a86e 100644 --- a/source4/scripting/python/samba/provision.py +++ b/source4/scripting/python/samba/provision.py @@ -38,13 +38,12 @@ import registry import samba from auth import system_session from samba import version, Ldb, substitute_var, valid_netbios_name, check_all_substituted, \ - DS_BEHAVIOR_WIN2000, DS_BEHAVIOR_WIN2003_INTERIM, DS_BEHAVIOR_WIN2003, DS_BEHAVIOR_WIN2008 + DS_BEHAVIOR_WIN2008 from samba.samdb import SamDB from samba.idmap import IDmapDB from samba.dcerpc import security import urllib -from ldb import SCOPE_SUBTREE, SCOPE_ONELEVEL, SCOPE_BASE, LdbError, \ - timestring, CHANGETYPE_MODIFY, CHANGETYPE_NONE +from ldb import SCOPE_SUBTREE, LdbError, timestring from ms_schema import read_ms_schema __docformat__ = "restructuredText" diff --git a/source4/scripting/python/samba/samba3.py b/source4/scripting/python/samba/samba3.py index c8ddbc8864..179efa2700 100644 --- a/source4/scripting/python/samba/samba3.py +++ b/source4/scripting/python/samba/samba3.py @@ -502,7 +502,7 @@ TDBSAM_USER_PREFIX = "USER_" class LdapSam(object): """Samba 3 LDAP passdb backend reader.""" def __init__(self, url): - self.ldap_url = ldap_url + self.ldap_url = url class TdbSam(TdbDatabase): @@ -692,7 +692,7 @@ class ParamFile(object): (k, v) = l.split("=", 1) self._sections[section][self._sanitize_name(k)] = v else: - raise Error("Unable to parser line %d: %r" % (i+1,l)) + raise Exception("Unable to parser line %d: %r" % (i+1,l)) def get(self, param, section=None): """Return the value of a parameter. diff --git a/source4/scripting/python/samba/upgrade.py b/source4/scripting/python/samba/upgrade.py index 0c83604e82..81945525e6 100644 --- a/source4/scripting/python/samba/upgrade.py +++ b/source4/scripting/python/samba/upgrade.py @@ -9,17 +9,16 @@ __docformat__ = "restructuredText" -from provision import findnss, provision, FILL_DRS +from provision import provision, FILL_DRS import grp import ldb import time import pwd -import uuid import registry from samba import Ldb -from samba.samdb import SamDB +from samba.param import LoadParm -def import_sam_policy(samldb, samba3_policy, domaindn): +def import_sam_policy(samldb, policy, dn): """Import a Samba 3 policy database.""" samldb.modify_ldif(""" dn: %s @@ -394,7 +393,7 @@ def upgrade_smbconf(oldconf,mark): kept in the new configuration as "samba3:" """ data = oldconf.data() - newconf = param_init() + newconf = LoadParm() for s in data: for p in data[s]: -- cgit From c80783eafd28bb3d749761cbbed80423c908d247 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 20 Jul 2009 10:25:25 +0200 Subject: Re-add accidently removed shares test. --- source4/scripting/python/samba/tests/shares.py | 74 ++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 source4/scripting/python/samba/tests/shares.py (limited to 'source4/scripting/python') diff --git a/source4/scripting/python/samba/tests/shares.py b/source4/scripting/python/samba/tests/shares.py new file mode 100644 index 0000000000..9130c36780 --- /dev/null +++ b/source4/scripting/python/samba/tests/shares.py @@ -0,0 +1,74 @@ +#!/usr/bin/python + +# Unix SMB/CIFS implementation. Tests for shares +# Copyright (C) Jelmer Vernooij 2009 +# +# 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 . +# +from samba.shares import SharesContainer +from unittest import TestCase + + +class MockService(object): + + def __init__(self, data): + self.data = data + + def __getitem__(self, name): + return self.data[name] + + +class MockLoadParm(object): + + def __init__(self, data): + self.data = data + + def __getitem__(self, name): + return MockService(self.data[name]) + + def __contains__(self, name): + return name in self.data + + def __len__(self): + return len(self.data) + + def services(self): + return self.data.keys() + + +class ShareTests(TestCase): + + def _get_shares(self, conf): + return SharesContainer(MockLoadParm(conf)) + + def test_len_no_global(self): + shares = self._get_shares({}) + self.assertEquals(0, len(shares)) + + def test_iter(self): + self.assertEquals([], list(self._get_shares({}))) + self.assertEquals([], list(self._get_shares({"global":{}}))) + self.assertEquals(["bla"], list(self._get_shares({"global":{}, "bla":{}}))) + + def test_len(self): + shares = self._get_shares({"global": {}}) + self.assertEquals(0, len(shares)) + + def test_getitem_nonexistant(self): + shares = self._get_shares({"global": {}}) + self.assertRaises(KeyError, shares.__getitem__, "bla") + + def test_getitem_global(self): + shares = self._get_shares({"global": {}}) + self.assertRaises(KeyError, shares.__getitem__, "global") -- cgit From 1887ad0a26cca026c3503f0ef4e40f8eff42a121 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 22 Jul 2009 18:04:58 +1000 Subject: s4:provision Fix provision on FreeBSD We were missing the 'cn' attribute, which we then prepare a sorted list based on. On Linux, strcmp(NULL, NULL) does not segfault, where it does on FreeBSD. Reported by Timur I. Bakeyev Andrew Bartlett --- source4/scripting/python/samba/ms_schema.py | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/scripting/python') diff --git a/source4/scripting/python/samba/ms_schema.py b/source4/scripting/python/samba/ms_schema.py index 2e8050e503..a0abc337ce 100644 --- a/source4/scripting/python/samba/ms_schema.py +++ b/source4/scripting/python/samba/ms_schema.py @@ -226,6 +226,7 @@ def __transform_entry(entry, objectClass): assert(cn) entry.insert(0, ["dn", "CN=%s,${SCHEMADN}" % cn]) entry.insert(1, ["objectClass", ["top", objectClass]]) + entry.insert(2, ["cn", cn]) for l in entry: key = l[0].lower() -- cgit