The branch, master has been updated via 815658d samba_tool/fsmo: Allocate RID Set when seizing RID manager via 2a49c74 python-libnet: Use new NTSTATUSError, WERRORError and DsExtendedError exceptions via e51256c python: Add DsExtendedError Exception via e737171 pyerrors: Add PyErr_Set{WERROR,HRESULT,NTSTATUS}_and_string() via c8505c5 python: create NTSTATUSError, HRESULTError and WERRORError via f72da5b dsdb: Catch errors in extended operations (like allocating a RID Set) via 46fefb2 dsdb: Rework DSDB code to use WERROR via fe90dad dsdb: Create RID Set as SYSTEM via 09537a6 dbcheck: Correctly initialise keep_transaction in missing_parent test via 7fd5be5 dbcheck: confirm RID Set presence and consistency via 035df7a dsdb: Add python hooks to allocate a RID set and allocate a RID pool via 1b40bb6 tests/ridalloc_exop: Add a new suite of tests for RID allocation from 9c6f0dc ctdb-scripts: Fix calculation of CTDB_BASE
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 815658d2db46e4accdd35f5925585ec1f1c3d74f Author: Garming Sam <garm...@catalyst.net.nz> Date: Tue Nov 1 16:29:53 2016 +1300 samba_tool/fsmo: Allocate RID Set when seizing RID manager Seizing the role without allocating a RID set for itself is likely prone to cause issues. Pair-programmed-with: Clive Ferreira <cliveferre...@catalyst.net.nz> Signed-off-by: Clive Ferreira <cliveferre...@catalyst.net.nz> Signed-off-by: Garming Sam <garm...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> BUG: https://bugzilla.samba.org/show_bug.cgi?id=9954 Autobuild-User(master): Garming Sam <garm...@samba.org> Autobuild-Date(master): Fri Nov 4 08:37:05 CET 2016 on sn-devel-144 commit 2a49c7451949d42e5a4d6fce3ce607f05f9e7b71 Author: Andrew Bartlett <abart...@samba.org> Date: Tue Nov 1 12:38:48 2016 +1300 python-libnet: Use new NTSTATUSError, WERRORError and DsExtendedError exceptions This will allow callers to catch specific errors rather than RuntimeException As this slightly changes the exception, the timecmd test must be updated. Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Garming Sam <garm...@catalyst.net.nz> BUG: https://bugzilla.samba.org/show_bug.cgi?id=12398 commit e51256c7d58040eeee02fc189b55afbc58379f81 Author: Andrew Bartlett <abart...@samba.org> Date: Tue Nov 1 16:09:20 2016 +1300 python: Add DsExtendedError Exception This will be used for checking errors during a GetNCChanges EXOP like RID Set allocation. Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Garming Sam <garm...@catalyst.net.nz> BUG: https://bugzilla.samba.org/show_bug.cgi?id=12398 commit e737171f6ef172de559b41d54989eca0d7663b4e Author: Andrew Bartlett <abart...@samba.org> Date: Tue Nov 1 16:03:09 2016 +1300 pyerrors: Add PyErr_Set{WERROR,HRESULT,NTSTATUS}_and_string() This varient allows control of the text explaination string Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Garming Sam <garm...@catalyst.net.nz> BUG: https://bugzilla.samba.org/show_bug.cgi?id=12398 commit c8505c53da3e21f31454f121efd5961d95349a38 Author: Andrew Bartlett <abart...@samba.org> Date: Tue Nov 1 15:23:58 2016 +1300 python: create NTSTATUSError, HRESULTError and WERRORError The advantage of these over the previous use of just RuntimeError is that we can catch just the errors we want, without having to catch all possible RuntimeError cases and assume they decode to a tuple Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Garming Sam <garm...@catalyst.net.nz> BUG: https://bugzilla.samba.org/show_bug.cgi?id=12398 commit f72da5ba51ae8bf9f3f54bed36b4572cd1b57adb Author: Andrew Bartlett <abart...@samba.org> Date: Mon Oct 31 16:25:51 2016 +1300 dsdb: Catch errors in extended operations (like allocating a RID Set) There are cases where allocating a RID Set can reasonably fail. Catch those nicely. Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Garming Sam <garm...@catalyst.net.nz> BUG: https://bugzilla.samba.org/show_bug.cgi?id=12398 commit 46fefb251f61b274cb687f6d1cb0a0a97fb36b44 Author: Andrew Bartlett <abart...@samba.org> Date: Mon Oct 31 16:19:37 2016 +1300 dsdb: Rework DSDB code to use WERROR The WERROR codes are more descriptive for DSDB issues, and almost all the code was converting from WERROR to NTSTATUS. This will allow us to better catch specific errors like WERR_DS_DRA_MISSING_PARENT Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Garming Sam <garm...@catalyst.net.nz> BUG: https://bugzilla.samba.org/show_bug.cgi?id=12398 commit fe90dadd2cd13c20484c06318724c592e5cf298e Author: Andrew Bartlett <abart...@samba.org> Date: Mon Oct 31 10:41:39 2016 +1300 dsdb: Create RID Set as SYSTEM We do not want random users with add-user rights to own the new RID Set for this server, and the ridSet class is thankfully system-only. BUG: https://bugzilla.samba.org/show_bug.cgi?id=9954 Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Garming Sam <garm...@catalyst.net.nz> commit 09537a67b0e761c834fb7c14d7e8d55e07fc5156 Author: Andrew Bartlett <abart...@samba.org> Date: Thu Nov 3 13:30:56 2016 +1300 dbcheck: Correctly initialise keep_transaction in missing_parent test Otherwise there is no point to this variable, we are trying to work out if the subsequent modify succeded Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Garming Sam <garm...@catalyst.net.nz> BUG: https://bugzilla.samba.org/show_bug.cgi?id=9954 commit 7fd5be535ade5ed119d869c8f215aa605aba2125 Author: Clive Ferreira <cliveferre...@catalyst.net.nz> Date: Thu Oct 27 17:28:01 2016 +1300 dbcheck: confirm RID Set presence and consistency Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Garming Sam <garm...@catalyst.net.nz> BUG: https://bugzilla.samba.org/show_bug.cgi?id=9954 commit 035df7adbe9cc119324275275c2605433f6c4292 Author: Andrew Bartlett <abart...@samba.org> Date: Fri Oct 28 16:08:57 2016 +1300 dsdb: Add python hooks to allocate a RID set and allocate a RID pool This will help us to correct errors during dbcheck Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Garming Sam <garm...@catalyst.net.nz> BUG: https://bugzilla.samba.org/show_bug.cgi?id=9954 commit 1b40bb69d101b767ee453c96234cc6d573142ab3 Author: Garming Sam <garm...@catalyst.net.nz> Date: Mon Oct 31 15:24:49 2016 +1300 tests/ridalloc_exop: Add a new suite of tests for RID allocation This moves some tests from getnc_exop.py regarding RID sets as well as adding new tests for actions on join. BUG: https://bugzilla.samba.org/show_bug.cgi?id=9954 Pair-programmed-with: Clive Ferreira <cliveferre...@catalyst.net.nz> Signed-off-by: Andrew Bartlett <abart...@samaba.org> Signed-off-by: Garming Sam <garm...@catalyst.net.nz> Signed-off-by: Clive Ferreira <cliveferre...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> ----------------------------------------------------------------------- Summary of changes: python/pyglue.c | 28 ++ python/samba/__init__.py | 5 + python/samba/dbchecker.py | 134 +++++- python/samba/netcmd/fsmo.py | 29 +- python/samba/samdb.py | 8 + python/samba/tests/samba_tool/timecmd.py | 2 +- selftest/knownfail | 4 + source4/dsdb/pydsdb.c | 74 +++ source4/dsdb/samdb/ldb_modules/ridalloc.c | 20 +- source4/dsdb/samdb/ldb_modules/samldb.c | 51 ++ source4/dsdb/samdb/samdb.h | 10 + source4/libcli/util/pyerrors.h | 30 +- source4/libnet/libnet_become_dc.c | 8 +- source4/libnet/libnet_become_dc.h | 16 +- source4/libnet/libnet_vampire.c | 125 ++--- source4/libnet/py_net.c | 143 +++++- source4/selftest/tests.py | 11 +- source4/setup/schema_samba4.ldif | 2 + source4/torture/drs/python/getnc_exop.py | 161 ------- source4/torture/drs/python/ridalloc_exop.py | 714 ++++++++++++++++++++++++++++ 20 files changed, 1316 insertions(+), 259 deletions(-) create mode 100644 source4/torture/drs/python/ridalloc_exop.py Changeset truncated at 500 lines: diff --git a/python/pyglue.c b/python/pyglue.c index 81244a2..dbe7eb4 100644 --- a/python/pyglue.c +++ b/python/pyglue.c @@ -24,6 +24,10 @@ #include "lib/socket/netif.h" void init_glue(void); +static PyObject *PyExc_NTSTATUSError; +static PyObject *PyExc_WERRORError; +static PyObject *PyExc_HRESULTError; +static PyObject *PyExc_DsExtendedError; static PyObject *py_generate_random_str(PyObject *self, PyObject *args) { @@ -294,5 +298,29 @@ void init_glue(void) PyModule_AddObject(m, "version", PyString_FromString(SAMBA_VERSION_STRING)); + PyExc_NTSTATUSError = PyErr_NewException(discard_const_p(char, "samba.NTSTATUSError"), PyExc_RuntimeError, NULL); + if (PyExc_NTSTATUSError != NULL) { + Py_INCREF(PyExc_NTSTATUSError); + PyModule_AddObject(m, "NTSTATUSError", PyExc_NTSTATUSError); + } + + PyExc_WERRORError = PyErr_NewException(discard_const_p(char, "samba.WERRORError"), PyExc_RuntimeError, NULL); + if (PyExc_WERRORError != NULL) { + Py_INCREF(PyExc_WERRORError); + PyModule_AddObject(m, "WERRORError", PyExc_WERRORError); + } + + PyExc_HRESULTError = PyErr_NewException(discard_const_p(char, "samba.HRESULTError"), PyExc_RuntimeError, NULL); + if (PyExc_HRESULTError != NULL) { + Py_INCREF(PyExc_HRESULTError); + PyModule_AddObject(m, "HRESULTError", PyExc_HRESULTError); + } + + PyExc_DsExtendedError = PyErr_NewException(discard_const_p(char, "samba.DsExtendedError"), PyExc_RuntimeError, NULL); + if (PyExc_DsExtendedError != NULL) { + Py_INCREF(PyExc_DsExtendedError); + PyModule_AddObject(m, "DsExtendedError", PyExc_DsExtendedError); + } + } diff --git a/python/samba/__init__.py b/python/samba/__init__.py index 7cfbc4c..5f91531 100644 --- a/python/samba/__init__.py +++ b/python/samba/__init__.py @@ -399,3 +399,8 @@ generate_random_password = _glue.generate_random_password strcasecmp_m = _glue.strcasecmp_m strstr_m = _glue.strstr_m is_ntvfs_fileserver_built = _glue.is_ntvfs_fileserver_built + +NTSTATUSError = _glue.NTSTATUSError +HRESULTError = _glue.HRESULTError +WERRORError = _glue.WERRORError +DsExtendedError = _glue.DsExtendedError diff --git a/python/samba/dbchecker.py b/python/samba/dbchecker.py index 9b0784b..294c320 100644 --- a/python/samba/dbchecker.py +++ b/python/samba/dbchecker.py @@ -32,6 +32,7 @@ from samba.dcerpc import security from samba.descriptor import get_wellknown_sds, get_diff_sds from samba.auth import system_session, admin_session from samba.netcmd import CommandError +from samba.netcmd.fsmo import get_fsmo_roleowner class dbcheck(object): @@ -79,6 +80,7 @@ class dbcheck(object): self.fix_base64_userparameters = False self.fix_utf8_userparameters = False self.fix_doubled_userparameters = False + self.fix_sid_rid_set_conflict = False self.reset_well_known_acls = reset_well_known_acls self.reset_all_well_known_acls = False self.in_transaction = in_transaction @@ -92,6 +94,7 @@ class dbcheck(object): self.fix_all_missing_objectclass = False self.fix_missing_deleted_objects = False self.fix_replica_locations = False + self.fix_missing_rid_set_master = False self.dn_set = set() self.link_id_cache = {} @@ -157,6 +160,27 @@ class dbcheck(object): if len(forest) == 1: self.dns_partitions.append((ldb.Dn(self.samdb, domaindns_zone), forest[0])) + fsmo_dn = ldb.Dn(self.samdb, "CN=RID Manager$,CN=System," + self.samdb.domain_dn()) + rid_master = get_fsmo_roleowner(self.samdb, fsmo_dn, "rid") + if ldb.Dn(self.samdb, self.samdb.get_dsServiceName()) == rid_master: + self.is_rid_master = True + else: + self.is_rid_master = False + + # To get your rid set + # 1. Get server name + res = self.samdb.search(base=ldb.Dn(self.samdb, self.samdb.get_serverName()), + scope=ldb.SCOPE_BASE, attrs=["serverReference"]) + # 2. Get server reference + self.server_ref_dn = ldb.Dn(self.samdb, res[0]['serverReference'][0]) + + # 3. Get RID Set + res = self.samdb.search(base=self.server_ref_dn, + scope=ldb.SCOPE_BASE, attrs=['rIDSetReferences']) + if "rIDSetReferences" in res[0]: + self.rid_set_dn = ldb.Dn(self.samdb, res[0]['rIDSetReferences'][0]) + else: + self.rid_set_dn = None def check_database(self, DN=None, scope=ldb.SCOPE_SUBTREE, controls=[], attrs=['*']): '''perform a database check, returning the number of errors found''' @@ -658,7 +682,7 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base))) self.report('Not moving object %s into LostAndFound' % (obj.dn)) return - keep_transaction = True + keep_transaction = False self.samdb.transaction_start() try: nc_root = self.samdb.get_nc_root(obj.dn); @@ -1847,6 +1871,114 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base))) self.err_replica_locations(obj, msg.dn, location) error_count += 1 + if dn == self.server_ref_dn: + # Check we have a valid RID Set + if "*" in attrs or "rIDSetReferences" in attrs: + if "rIDSetReferences" not in obj: + # NO RID SET reference + # We are RID master, allocate it. + error_count += 1 + + if self.is_rid_master: + # Allocate a RID Set + if self.confirm_all('Allocate the missing RID set for RID master?', + 'fix_missing_rid_set_master'): + + # We don't have auto-transaction logic on + # extended operations, so we have to do it + # here. + + self.samdb.transaction_start() + + try: + self.samdb.create_own_rid_set() + + except: + self.samdb.transaction_cancel() + raise + + self.samdb.transaction_commit() + + + elif not self.samdb.am_rodc(): + self.report("No RID Set found for this server: %s, and we are not the RID Master (so can not self-allocate)" % dn) + + + # Check some details of our own RID Set + if dn == self.rid_set_dn: + res = self.samdb.search(base=self.rid_set_dn, scope=ldb.SCOPE_BASE, + attrs=["rIDAllocationPool", + "rIDPreviousAllocationPool", + "rIDUsedPool", + "rIDNextRID"]) + if "rIDAllocationPool" not in res[0]: + self.report("No rIDAllocationPool found in %s" % dn) + error_count += 1 + else: + next_pool = int(res[0]["rIDAllocationPool"][0]) + + high = (0xFFFFFFFF00000000 & next_pool) >> 32 + low = 0x00000000FFFFFFFF & next_pool + + if high <= low: + self.report("Invalid RID set %d-%s, %d > %d!" % (low, high, low, high)) + error_count += 1 + + if "rIDNextRID" in res[0]: + next_free_rid = int(res[0]["rIDNextRID"][0]) + else: + next_free_rid = 0 + + if next_free_rid == 0: + next_free_rid = low + else: + next_free_rid += 1 + + # Check the remainder of this pool for conflicts. If + # ridalloc_allocate_rid() moves to a new pool, this + # will be above high, so we will stop. + while next_free_rid <= high: + sid = "%s-%d" % (self.samdb.get_domain_sid(), next_free_rid) + try: + res = self.samdb.search(base="<SID=%s>" % sid, scope=ldb.SCOPE_BASE, + attrs=[]) + except ldb.LdbError, (enum, estr): + if enum != ldb.ERR_NO_SUCH_OBJECT: + raise + res = None + if res is not None: + self.report("SID %s for %s conflicts with our current RID set in %s" % (sid, res[0].dn, dn)) + error_count += 1 + + if self.confirm_all('Fix conflict between SID %s and RID pool in %s by allocating a new RID?' + % (sid, dn), + 'fix_sid_rid_set_conflict'): + self.samdb.transaction_start() + + # This will burn RIDs, which will move + # past the conflict. We then check again + # to see if the new RID conflicts, until + # the end of the current pool. We don't + # look at the next pool to avoid burning + # all RIDs in one go in some strange + # failure case. + try: + while True: + allocated_rid = self.samdb.allocate_rid() + if allocated_rid >= next_free_rid: + next_free_rid = allocated_rid + 1 + break + except: + self.samdb.transaction_cancel() + raise + + self.samdb.transaction_commit() + else: + break + else: + next_free_rid += 1 + + return error_count ################################################################ diff --git a/python/samba/netcmd/fsmo.py b/python/samba/netcmd/fsmo.py index 1351654..62b3e43 100644 --- a/python/samba/netcmd/fsmo.py +++ b/python/samba/netcmd/fsmo.py @@ -295,12 +295,37 @@ You must provide an Admin user and password."""), m["fSMORoleOwner"]= ldb.MessageElement( serviceName, ldb.FLAG_MOD_REPLACE, "fSMORoleOwner") + + samdb.transaction_start() try: samdb.modify(m) + if role == "rid": + # We may need to allocate the initial RID Set + samdb.create_own_rid_set() + except LdbError, (num, msg): - raise CommandError("Failed to seize '%s' role: %s" % - (role, msg)) + if role == "rid" and num == ldb.ERR_ENTRY_ALREADY_EXISTS: + + # Try again without the RID Set allocation + # (normal). We have to manage the transaction as + # we do not have nested transactions and creating + # a RID set touches multiple objects. :-( + samdb.transaction_cancel() + samdb.transaction_start() + try: + samdb.modify(m) + except LdbError, (num, msg): + samdb.transaction_cancel() + raise CommandError("Failed to seize '%s' role: %s" % + (role, msg)) + + else: + samdb.transaction_cancel() + raise CommandError("Failed to seize '%s' role: %s" % + (role, msg)) + samdb.transaction_commit() self.outf.write("FSMO seize of '%s' role successful\n" % role) + return True def seize_dns_role(self, role, samdb, credopts, sambaopts, diff --git a/python/samba/samdb.py b/python/samba/samdb.py index 3d7ea3e..eabe363 100644 --- a/python/samba/samdb.py +++ b/python/samba/samdb.py @@ -963,3 +963,11 @@ accountExpires: %u return dsdb._dsdb_garbage_collect_tombstones(self, dn, current_time, tombstone_lifetime) + + def create_own_rid_set(self): + '''create a RID set for this DSA''' + return dsdb._dsdb_create_own_rid_set(self) + + def allocate_rid(self): + '''return a new RID from the RID Pool on this DSA''' + return dsdb._dsdb_allocate_rid(self) diff --git a/python/samba/tests/samba_tool/timecmd.py b/python/samba/tests/samba_tool/timecmd.py index 310f861..68dcb06 100644 --- a/python/samba/tests/samba_tool/timecmd.py +++ b/python/samba/tests/samba_tool/timecmd.py @@ -39,5 +39,5 @@ class TimeCmdTestCase(SambaToolCmdTest): """Run time against a non-existent server, and make sure it fails""" (result, out, err) = self.runcmd("time", "notaserver") self.assertEquals(result, -1, "check for result code") - self.assertTrue(err.strip().endswith("NT_STATUS_OBJECT_NAME_NOT_FOUND"), "ensure right error string") + self.assertNotEqual(err.strip().find("NT_STATUS_OBJECT_NAME_NOT_FOUND"), -1, "ensure right error string") self.assertEquals(out, "", "ensure no output returned") diff --git a/selftest/knownfail b/selftest/knownfail index 38b5f51..ddfe0ad 100644 --- a/selftest/knownfail +++ b/selftest/knownfail @@ -306,3 +306,7 @@ ^samba4.rpc.echo.*on.*with.object.echo.sinkdata.*nt4_dc ^samba4.rpc.echo.*on.*with.object.echo.addone.*nt4_dc ^samba4.rpc.echo.*on.*ncacn_ip_tcp.*with.object.*nt4_dc +^samba4.drs.ridalloc_exop.python.*ridalloc_exop.DrsReplicaSyncTestCase.test_offline_ridalloc +^samba4.drs.ridalloc_exop.python.*ridalloc_exop.DrsReplicaSyncTestCase.test_join_time_ridalloc +^samba4.drs.ridalloc_exop.python.*ridalloc_exop.DrsReplicaSyncTestCase.test_rid_set_dbcheck_after_seize +^samba4.drs.ridalloc_exop.python.*ridalloc_exop.DrsReplicaSyncTestCase.test_rid_set_dbcheck \ No newline at end of file diff --git a/source4/dsdb/pydsdb.c b/source4/dsdb/pydsdb.c index e53a245..ab1d0d2 100644 --- a/source4/dsdb/pydsdb.c +++ b/source4/dsdb/pydsdb.c @@ -1078,6 +1078,74 @@ static PyObject *py_dsdb_am_pdc(PyObject *self, PyObject *args) return PyBool_FromLong(am_pdc); } +/* + call DSDB_EXTENDED_CREATE_OWN_RID_SET to get a new RID set for this server + */ +static PyObject *py_dsdb_create_own_rid_set(PyObject *self, PyObject *args) +{ + PyObject *py_ldb; + struct ldb_context *ldb; + int ret; + struct ldb_result *ext_res; + + if (!PyArg_ParseTuple(args, "O", &py_ldb)) + return NULL; + + PyErr_LDB_OR_RAISE(py_ldb, ldb); + + /* + * Run DSDB_EXTENDED_CREATE_OWN_RID_SET to get a RID set + */ + + ret = ldb_extended(ldb, DSDB_EXTENDED_CREATE_OWN_RID_SET, NULL, &ext_res); + + PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb); + + TALLOC_FREE(ext_res); + + Py_RETURN_NONE; +} + +/* + call DSDB_EXTENDED_ALLOCATE_RID to get a new RID set for this server + */ +static PyObject *py_dsdb_allocate_rid(PyObject *self, PyObject *args) +{ + PyObject *py_ldb; + struct ldb_context *ldb; + int ret; + uint32_t rid; + struct ldb_result *ext_res = NULL; + struct dsdb_extended_allocate_rid *rid_return = NULL; + if (!PyArg_ParseTuple(args, "O", &py_ldb)) { + return NULL; + } + + PyErr_LDB_OR_RAISE(py_ldb, ldb); + + rid_return = talloc_zero(ldb, struct dsdb_extended_allocate_rid); + if (rid_return == NULL) { + return PyErr_NoMemory(); + } + + /* + * Run DSDB_EXTENDED_ALLOCATE_RID to get a new RID + */ + + ret = ldb_extended(ldb, DSDB_EXTENDED_ALLOCATE_RID, rid_return, &ext_res); + if (ret != LDB_SUCCESS) { + TALLOC_FREE(rid_return); + TALLOC_FREE(ext_res); + PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb); + } + + rid = rid_return->rid; + TALLOC_FREE(rid_return); + TALLOC_FREE(ext_res); + + return PyInt_FromLong(rid); +} + static PyObject *py_dsdb_garbage_collect_tombstones(PyObject *self, PyObject *args) { PyObject *py_ldb, *py_list_dn; @@ -1245,6 +1313,12 @@ static PyMethodDef py_dsdb_methods[] = { { "_dsdb_garbage_collect_tombstones", (PyCFunction)py_dsdb_garbage_collect_tombstones, METH_VARARGS, "_dsdb_kcc_check_deleted(samdb, [dn], current_time, tombstone_lifetime)" " -> (num_objects_expunged, num_links_expunged)" }, + { "_dsdb_create_own_rid_set", (PyCFunction)py_dsdb_create_own_rid_set, METH_VARARGS, + "_dsdb_create_own_rid_set(samdb)" + " -> None" }, + { "_dsdb_allocate_rid", (PyCFunction)py_dsdb_allocate_rid, METH_VARARGS, + "_dsdb_allocate_rid(samdb)" + " -> RID" }, { NULL } }; diff --git a/source4/dsdb/samdb/ldb_modules/ridalloc.c b/source4/dsdb/samdb/ldb_modules/ridalloc.c index 4c619b7..d3463e6 100644 --- a/source4/dsdb/samdb/ldb_modules/ridalloc.c +++ b/source4/dsdb/samdb/ldb_modules/ridalloc.c @@ -347,8 +347,12 @@ static int ridalloc_create_rid_set_ntds(struct ldb_module *module, TALLOC_CTX *m /* we need this to go all the way to the top of the module * stack, as we need all the extra attributes added (including - * complex ones like ntsecuritydescriptor) */ - ret = dsdb_module_add(module, msg, DSDB_FLAG_TOP_MODULE | DSDB_MODIFY_RELAX, parent); + * complex ones like ntsecuritydescriptor). We must do this + * as system, otherwise a user might end up owning the RID + * set, and that would be bad... */ + ret = dsdb_module_add(module, msg, + DSDB_FLAG_TOP_MODULE | DSDB_FLAG_AS_SYSTEM + | DSDB_MODIFY_RELAX, parent); if (ret != LDB_SUCCESS) { ldb_asprintf_errstring(ldb, "Failed to add RID Set %s - %s", ldb_dn_get_linearized(msg->dn), @@ -401,8 +405,8 @@ static int ridalloc_create_rid_set_ntds(struct ldb_module *module, TALLOC_CTX *m /* create a RID Set object for this DC */ -static int ridalloc_create_own_rid_set(struct ldb_module *module, TALLOC_CTX *mem_ctx, - struct ldb_dn **dn, struct ldb_request *parent) +int ridalloc_create_own_rid_set(struct ldb_module *module, TALLOC_CTX *mem_ctx, + struct ldb_dn **dn, struct ldb_request *parent) { TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); struct ldb_dn *rid_manager_dn, *fsmo_role_dn; @@ -466,7 +470,8 @@ static int ridalloc_create_own_rid_set(struct ldb_module *module, TALLOC_CTX *me get a new RID pool for ourselves also returns the first rid for the new pool */ -static int ridalloc_new_own_pool(struct ldb_module *module, uint64_t *new_pool, struct ldb_request *parent) + +int ridalloc_new_own_pool(struct ldb_module *module, uint64_t *new_pool, struct ldb_request *parent) { TALLOC_CTX *tmp_ctx = talloc_new(module); struct ldb_dn *rid_manager_dn, *fsmo_role_dn; @@ -685,6 +690,11 @@ int ridalloc_allocate_rid(struct ldb_module *module, uint32_t *rid, struct ldb_r /* called by DSDB_EXTENDED_ALLOCATE_RID_POOL extended operation in samldb + + This is for the DRS server to allocate a RID Pool for another server. + + Called by another server over DRS (which calls this extended + operation), it runs on the RID Manager only. */ int ridalloc_allocate_rid_pool_fsmo(struct ldb_module *module, struct dsdb_fsmo_extended_op *exop, struct ldb_request *parent) diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index cc101a6..b33cf24 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -3869,12 +3869,63 @@ static int samldb_extended_allocate_rid_pool(struct ldb_module *module, struct l return ldb_module_done(req, NULL, NULL, LDB_SUCCESS); } +static int samldb_extended_allocate_rid(struct ldb_module *module, struct ldb_request *req) +{ + struct ldb_context *ldb = ldb_module_get_ctx(module); + struct dsdb_extended_allocate_rid *exop; + int ret; + + exop = talloc_get_type(req->op.extended.data, + struct dsdb_extended_allocate_rid); + if (!exop) { + ldb_set_errstring(ldb, + "samldb_extended_allocate_rid: invalid extended data"); + return LDB_ERR_PROTOCOL_ERROR; + } + + ret = ridalloc_allocate_rid(module, &exop->rid, req); + if (ret != LDB_SUCCESS) { + return ret; + } + + return ldb_module_done(req, NULL, NULL, LDB_SUCCESS); +} + +static int samldb_extended_create_own_rid_set(struct ldb_module *module, struct ldb_request *req) +{ + struct ldb_context *ldb = ldb_module_get_ctx(module); + int ret; -- Samba Shared Repository