[SCM] Samba Shared Repository - branch master updated
Andrew Bartlett
abartlet at samba.org
Tue Mar 14 07:17:02 UTC 2023
The branch, master has been updated
via b4a6c054ec6 selftest: Use setUpClass() to reduce "make test TESTS=large_ldap" time
via cad96f59a08 lib/ldb: Avoid allocation and memcpy() for every wildcard match candidate
via 4fa0242b9d3 python:netcmd: Decode return value of find_netbios() from bytes into string
via bfc33b47bb4 dsdb: Avoid ERROR(ldb): uncaught exception - Deleted target CN=NTDS Settings... in join
via 2d41bcce83a selftest/drs: Demonstrate ERROR(ldb): uncaught exception - Deleted target CN=NTDS Settings... in join
via 5a7a28cc458 tsocket: Increase tcp_user_timeout max_loops
from 7ee725f2860 idmap_hash: remember new domain sids in idmap_hash_sid_to_id()
https://git.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit b4a6c054ec6acefacd22cb7230a783d20cb07c05
Author: Andrew Bartlett <abartlet at samba.org>
Date: Mon Mar 13 17:20:00 2023 +1300
selftest: Use setUpClass() to reduce "make test TESTS=large_ldap" time
This reduces the elapsed time to 6m from 20m on my laptop.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15332
Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Joseph Sutton <josephsutton at catalyst.net.nz>
Autobuild-User(master): Andrew Bartlett <abartlet at samba.org>
Autobuild-Date(master): Tue Mar 14 07:16:04 UTC 2023 on atb-devel-224
commit cad96f59a08192df927fb1df4e9787c7f70991a2
Author: Andrew Bartlett <abartlet at samba.org>
Date: Mon Mar 13 14:25:56 2023 +1300
lib/ldb: Avoid allocation and memcpy() for every wildcard match candidate
The value can be quite large, the allocation will take much
longer than the actual match and is repeated per candidate
record.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15331
Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Joseph Sutton <josephsutton at catalyst.net.nz>
commit 4fa0242b9d34decd8dbd813be40655a593df3db9
Author: Andreas Schneider <asn at samba.org>
Date: Fri Mar 10 09:08:48 2023 +0100
python:netcmd: Decode return value of find_netbios() from bytes into string
ERROR(<class 'TypeError'>): uncaught exception - replace() argument 1 must be
str, not bytes
File "bin/python/samba/netcmd/__init__.py", line 230, in _run
return self.run(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "bin/python/samba/netcmd/ldapcmp.py", line 966, in run
if b1.diff(b2):
^^^^^^^^^^^
File "bin/python/samba/netcmd/ldapcmp.py", line 790, in diff
if object1 == object2:
^^^^^^^^^^^^^^^^^^
File "bin/python/samba/netcmd/ldapcmp.py", line 557, in __eq__
return self.cmp_attrs(other)
^^^^^^^^^^^^^^^^^^^^^
File "bin/python/samba/netcmd/ldapcmp.py", line 656, in cmp_attrs
p = [self.fix_domain_netbios(j) for j in m]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "bin/python/samba/netcmd/ldapcmp.py", line 656, in <listcomp>
p = [self.fix_domain_netbios(j) for j in m]
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "bin/python/samba/netcmd/ldapcmp.py", line 542, in fix_domain_netbios
res = res.replace(self.con.domain_netbios.lower(), self.con.domain_netbios.upper())
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
BUGS: https://bugzilla.samba.org/show_bug.cgi?id=15330
Signed-off-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
commit bfc33b47bb428233e100f75e7a725ac52179f823
Author: Andrew Bartlett <abartlet at samba.org>
Date: Thu Mar 9 20:25:06 2023 +1300
dsdb: Avoid ERROR(ldb): uncaught exception - Deleted target CN=NTDS Settings... in join
"samba-tool domain join" uses the replication API in a strange way, perhaps no longer
required, except that we often still have folks upgrading from very old Samba versions.
When deferring the writing out to the DB of link replication to the very end, there
is a greater opportunity for the deletion of an object to have been sent with the
other objects, and have the link applied later.
This tells the repl_meta_data code to behave as if GET_TGT had been sent at the
time the link was returned, allowing a link to a deleted object to be silently
discarded.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15329
Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Joseph Sutton <josephsutton at catalyst.net.nz>
commit 2d41bcce83a976b85636c92d6fc38c63fdde5431
Author: Andrew Bartlett <abartlet at samba.org>
Date: Thu Mar 9 17:02:35 2023 +1300
selftest/drs: Demonstrate ERROR(ldb): uncaught exception - Deleted target CN=NTDS Settings... in join
"samba-tool domain join" uses the replication API in a strange way, perhaps no longer
required, except that we often still have folks upgrading from very old Samba versions.
By deferring the writing out to the DB of link replication to the very end, we have a
better chance that all the objects required are present, however the situation may
have changed during the cycle, and a link could still be sent, pointing to a deleted
object.
We currently fail in this situation.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15329
Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Joseph Sutton <josephsutton at catalyst.net.nz>
commit 5a7a28cc45870949fc11d30586a06c309aa517dc
Author: Andrew Bartlett <abartlet at samba.org>
Date: Thu Mar 9 10:06:26 2023 +1300
tsocket: Increase tcp_user_timeout max_loops
Often, on rackspace GitLab CI runners, we get:
UNEXPECTED(failure): samba.unittests.tsocket_tstream.test_tstream_more_tcp_user_timeout_spin(none)
REASON: Exception: Exception: 0xf == 0xf
../../lib/tsocket/tests/test_tstream.c:405: error: Failure!
This allows us more spins before we fail the test.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15328
Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Joseph Sutton <josephsutton at catalyst.net.nz>
-----------------------------------------------------------------------
Summary of changes:
lib/ldb/common/ldb_match.c | 60 +++++++++--
lib/tsocket/tests/test_tstream.c | 2 +-
python/samba/join.py | 19 ++++
python/samba/netcmd/ldapcmp.py | 2 +-
source4/dsdb/pydsdb.c | 2 +
source4/dsdb/samdb/ldb_modules/repl_meta_data.c | 13 ++-
source4/dsdb/samdb/samdb.h | 2 +
source4/dsdb/tests/python/large_ldap.py | 69 ++++++------
source4/torture/drs/python/ridalloc_exop.py | 135 ++++++++++++++++++++++++
9 files changed, 258 insertions(+), 46 deletions(-)
Changeset truncated at 500 lines:
diff --git a/lib/ldb/common/ldb_match.c b/lib/ldb/common/ldb_match.c
index 2f4d41f3441..51376871b4c 100644
--- a/lib/ldb/common/ldb_match.c
+++ b/lib/ldb/common/ldb_match.c
@@ -34,6 +34,7 @@
#include "ldb_private.h"
#include "dlinklist.h"
+#include "ldb_handlers.h"
/*
check if the scope matches in a search result
@@ -259,20 +260,42 @@ static int ldb_wildcard_compare(struct ldb_context *ldb,
return LDB_SUCCESS;
}
- if (a->syntax->canonicalise_fn(ldb, ldb, &value, &val) != 0) {
- return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
+ /* No need to just copy this value for a binary match */
+ if (a->syntax->canonicalise_fn != ldb_handler_copy) {
+ if (a->syntax->canonicalise_fn(ldb, ldb, &value, &val) != 0) {
+ return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
+ }
+
+ /*
+ * Only set save_p if we allocate (call
+ * a->syntax->canonicalise_fn()), as we
+ * talloc_free(save_p) below to clean up
+ */
+ save_p = val.data;
+ } else {
+ val = value;
}
- save_p = val.data;
cnk.data = NULL;
if ( ! tree->u.substring.start_with_wildcard ) {
+ uint8_t *cnk_to_free = NULL;
chunk = tree->u.substring.chunks[c];
- if (a->syntax->canonicalise_fn(ldb, ldb, chunk, &cnk) != 0) goto mismatch;
+ /* No need to just copy this value for a binary match */
+ if (a->syntax->canonicalise_fn != ldb_handler_copy) {
+ if (a->syntax->canonicalise_fn(ldb, ldb, chunk, &cnk) != 0) {
+ goto mismatch;
+ }
+
+ cnk_to_free = cnk.data;
+ } else {
+ cnk = *chunk;
+ }
/* This deals with wildcard prefix searches on binary attributes (eg objectGUID) */
if (cnk.length > val.length) {
+ TALLOC_FREE(cnk_to_free);
goto mismatch;
}
/*
@@ -280,32 +303,47 @@ static int ldb_wildcard_compare(struct ldb_context *ldb,
* we can cope with this.
*/
if (cnk.length == 0) {
+ TALLOC_FREE(cnk_to_free);
+ goto mismatch;
+ }
+
+ if (memcmp((char *)val.data, (char *)cnk.data, cnk.length) != 0) {
+ TALLOC_FREE(cnk_to_free);
goto mismatch;
}
- if (memcmp((char *)val.data, (char *)cnk.data, cnk.length) != 0) goto mismatch;
val.length -= cnk.length;
val.data += cnk.length;
c++;
- talloc_free(cnk.data);
+ TALLOC_FREE(cnk_to_free);
cnk.data = NULL;
}
while (tree->u.substring.chunks[c]) {
uint8_t *p;
+ uint8_t *cnk_to_free = NULL;
chunk = tree->u.substring.chunks[c];
- if(a->syntax->canonicalise_fn(ldb, ldb, chunk, &cnk) != 0) {
- goto mismatch;
+ /* No need to just copy this value for a binary match */
+ if (a->syntax->canonicalise_fn != ldb_handler_copy) {
+ if (a->syntax->canonicalise_fn(ldb, ldb, chunk, &cnk) != 0) {
+ goto mismatch;
+ }
+
+ cnk_to_free = cnk.data;
+ } else {
+ cnk = *chunk;
}
/*
* Empty strings are returned as length 0. Ensure
* we can cope with this.
*/
if (cnk.length == 0) {
+ TALLOC_FREE(cnk_to_free);
goto mismatch;
}
if (cnk.length > val.length) {
+ TALLOC_FREE(cnk_to_free);
goto mismatch;
}
@@ -320,6 +358,8 @@ static int ldb_wildcard_compare(struct ldb_context *ldb,
cmp = memcmp(p,
cnk.data,
cnk.length);
+ TALLOC_FREE(cnk_to_free);
+
if (cmp != 0) {
goto mismatch;
}
@@ -331,15 +371,16 @@ static int ldb_wildcard_compare(struct ldb_context *ldb,
p = memmem((const void *)val.data, val.length,
(const void *)cnk.data, cnk.length);
if (p == NULL) {
+ TALLOC_FREE(cnk_to_free);
goto mismatch;
}
/* move val to the end of the match */
p += cnk.length;
val.length -= (p - val.data);
val.data = p;
+ TALLOC_FREE(cnk_to_free);
}
c++;
- TALLOC_FREE(cnk.data);
}
talloc_free(save_p);
@@ -349,7 +390,6 @@ static int ldb_wildcard_compare(struct ldb_context *ldb,
mismatch:
*matched = false;
talloc_free(save_p);
- talloc_free(cnk.data);
return LDB_SUCCESS;
}
diff --git a/lib/tsocket/tests/test_tstream.c b/lib/tsocket/tests/test_tstream.c
index a920e671cda..47008bb8bf8 100644
--- a/lib/tsocket/tests/test_tstream.c
+++ b/lib/tsocket/tests/test_tstream.c
@@ -322,7 +322,7 @@ static void test_tstream_server_spin_client_tcp_user_timeout(struct socket_pair
rc = write(sp->socket_client, TEST_STRING, sizeof(TEST_STRING));
assert_return_code(rc, errno);
sp->expected_errno = ETIMEDOUT;
- sp->max_loops = 15;
+ sp->max_loops = 30;
}
static void test_tstream_server_spin_client_both_timer(struct tevent_context *ev,
diff --git a/python/samba/join.py b/python/samba/join.py
index 70b3c9729b0..6c1ab3be7b4 100644
--- a/python/samba/join.py
+++ b/python/samba/join.py
@@ -50,6 +50,7 @@ import tempfile
from collections import OrderedDict
from samba.common import get_string
from samba.netcmd import CommandError
+from samba import dsdb
class DCJoinException(Exception):
@@ -937,6 +938,10 @@ class DCJoinContext(object):
"""Replicate the SAM."""
ctx.logger.info("Starting replication")
+
+ # A global transaction is started so that linked attributes
+ # are applied at the very end, once all partitions are
+ # replicated. This helps get all cross-partition links.
ctx.local_samdb.transaction_start()
try:
source_dsa_invocation_id = misc.GUID(ctx.samdb.get_invocation_id())
@@ -1057,7 +1062,21 @@ class DCJoinContext(object):
ctx.local_samdb.transaction_cancel()
raise
else:
+
+ # This is a special case, we have completed a full
+ # replication so if a link comes to us that points to a
+ # deleted object, and we asked for all objects already, we
+ # just have to ignore it, the chance to re-try the
+ # replication with GET_TGT has long gone. This can happen
+ # if the object is deleted and sent to us after the link
+ # was sent, as we are processing all links in the
+ # transaction_commit().
+ if not ctx.domain_replica_flags & drsuapi.DRSUAPI_DRS_CRITICAL_ONLY:
+ ctx.local_samdb.set_opaque_integer(dsdb.DSDB_FULL_JOIN_REPLICATION_COMPLETED_OPAQUE_NAME,
+ 1)
ctx.local_samdb.transaction_commit()
+ ctx.local_samdb.set_opaque_integer(dsdb.DSDB_FULL_JOIN_REPLICATION_COMPLETED_OPAQUE_NAME,
+ 0)
ctx.logger.info("Committed SAM database")
# A large replication may have caused our LDB connection to the
diff --git a/python/samba/netcmd/ldapcmp.py b/python/samba/netcmd/ldapcmp.py
index fb49cbe1ae5..ff26e96332d 100644
--- a/python/samba/netcmd/ldapcmp.py
+++ b/python/samba/netcmd/ldapcmp.py
@@ -121,7 +121,7 @@ class LDAPBase(object):
for x in res:
if "nETBIOSName" in x:
- return x["nETBIOSName"][0]
+ return x["nETBIOSName"][0].decode()
def object_exists(self, object_dn):
res = None
diff --git a/source4/dsdb/pydsdb.c b/source4/dsdb/pydsdb.c
index 804007e9e86..fd7cda21a43 100644
--- a/source4/dsdb/pydsdb.c
+++ b/source4/dsdb/pydsdb.c
@@ -1768,5 +1768,7 @@ MODULE_INIT_FUNC(dsdb)
ADD_DSDB_STRING(DS_GUID_SCHEMA_CLASS_MANAGED_SERVICE_ACCOUNT);
ADD_DSDB_STRING(DS_GUID_SCHEMA_CLASS_USER);
+ ADD_DSDB_STRING(DSDB_FULL_JOIN_REPLICATION_COMPLETED_OPAQUE_NAME);
+
return m;
}
diff --git a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
index c1ea5ad90f8..175a02d3ba7 100644
--- a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
+++ b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
@@ -7533,6 +7533,16 @@ static int replmd_allow_missing_target(struct ldb_module *module,
source_dn,
target_dn);
if (is_in_same_nc) {
+ /*
+ * We allow the join.py code to point out that all
+ * replication is completed, so failing now would just
+ * trigger errors, rather than trigger a GET_TGT
+ */
+ int *finished_full_join_ptr =
+ talloc_get_type(ldb_get_opaque(ldb,
+ DSDB_FULL_JOIN_REPLICATION_COMPLETED_OPAQUE_NAME),
+ int);
+ bool finished_full_join = finished_full_join_ptr && *finished_full_join_ptr;
/*
* if the target is already be up-to-date there's no point in
@@ -7540,7 +7550,8 @@ static int replmd_allow_missing_target(struct ldb_module *module,
* on a one-way link was deleted. We ignore the link rather
* than failing the replication cycle completely
*/
- if (dsdb_repl_flags & DSDB_REPL_FLAG_TARGETS_UPTODATE) {
+ if (finished_full_join
+ || dsdb_repl_flags & DSDB_REPL_FLAG_TARGETS_UPTODATE) {
*ignore_link = true;
DBG_WARNING("%s is %s "
"but up to date. Ignoring link from %s\n",
diff --git a/source4/dsdb/samdb/samdb.h b/source4/dsdb/samdb/samdb.h
index d76cbeba841..cbbb766ea22 100644
--- a/source4/dsdb/samdb/samdb.h
+++ b/source4/dsdb/samdb/samdb.h
@@ -371,6 +371,8 @@ struct dsdb_extended_dn_store_format {
#define DSDB_OPAQUE_PARTITION_MODULE_MSG_OPAQUE_NAME "DSDB_OPAQUE_PARTITION_MODULE_MSG"
+#define DSDB_FULL_JOIN_REPLICATION_COMPLETED_OPAQUE_NAME "DSDB_FULL_JOIN_REPLICATION_COMPLETED"
+
#define DSDB_ACL_CHECKS_DIRSYNC_FLAG 0x1
#define DSDB_SAMDB_MINIMUM_ALLOWED_RID 1000
diff --git a/source4/dsdb/tests/python/large_ldap.py b/source4/dsdb/tests/python/large_ldap.py
index 0805119a700..13729052e65 100644
--- a/source4/dsdb/tests/python/large_ldap.py
+++ b/source4/dsdb/tests/python/large_ldap.py
@@ -66,30 +66,32 @@ creds = credopts.get_credentials(lp)
class ManyLDAPTest(samba.tests.TestCase):
- def setUp(self):
- super(ManyLDAPTest, self).setUp()
- self.ldb = SamDB(url, credentials=creds, session_info=system_session(lp), lp=lp)
- self.base_dn = self.ldb.domain_dn()
- self.OU_NAME_MANY="many_ou" + format(random.randint(0, 99999), "05")
- self.ou_dn = ldb.Dn(self.ldb, "ou=" + self.OU_NAME_MANY + "," + str(self.base_dn))
-
- samba.tests.delete_force(self.ldb, self.ou_dn,
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass()
+ cls.ldb = SamDB(url, credentials=creds, session_info=system_session(lp), lp=lp)
+ cls.base_dn = self.ldb.domain_dn()
+ cls.OU_NAME_MANY="many_ou" + format(random.randint(0, 99999), "05")
+ cls.ou_dn = ldb.Dn(self.ldb, "ou=" + self.OU_NAME_MANY + "," + str(self.base_dn))
+
+ samba.tests.delete_force(cls.ldb, cls.ou_dn,
controls=['tree_delete:1'])
- self.ldb.add({
- "dn": self.ou_dn,
+ cls.ldb.add({
+ "dn": cls.ou_dn,
"objectclass": "organizationalUnit",
- "ou": self.OU_NAME_MANY})
+ "ou": cls.OU_NAME_MANY})
for x in range(2000):
- ou_name = self.OU_NAME_MANY + str(x)
- self.ldb.add({
- "dn": "ou=" + ou_name + "," + str(self.ou_dn),
+ ou_name = cls.OU_NAME_MANY + str(x)
+ cls.ldb.add({
+ "dn": "ou=" + ou_name + "," + str(cls.ou_dn),
"objectclass": "organizationalUnit",
"ou": ou_name})
- def tearDown(self):
- samba.tests.delete_force(self.ldb, self.ou_dn,
+ @classmethod
+ def tearDownClass(cls):
+ samba.tests.delete_force(cls.ldb, self.ou_dn,
controls=['tree_delete:1'])
def test_unindexed_iterator_search(self):
@@ -117,34 +119,35 @@ class ManyLDAPTest(samba.tests.TestCase):
class LargeLDAPTest(samba.tests.TestCase):
- def setUp(self):
- super(LargeLDAPTest, self).setUp()
- self.ldb = SamDB(url, credentials=creds, session_info=system_session(lp), lp=lp)
- self.base_dn = self.ldb.domain_dn()
- self.USER_NAME = "large_user" + format(random.randint(0, 99999), "05") + "-"
- self.OU_NAME="large_user_ou" + format(random.randint(0, 99999), "05")
- self.ou_dn = ldb.Dn(self.ldb, "ou=" + self.OU_NAME + "," + str(self.base_dn))
+ @classmethod
+ def setUpClass(cls):
+ cls.ldb = SamDB(url, credentials=creds, session_info=system_session(lp), lp=lp)
+ cls.base_dn = cls.ldb.domain_dn()
+ cls.USER_NAME = "large_user" + format(random.randint(0, 99999), "05") + "-"
+ cls.OU_NAME="large_user_ou" + format(random.randint(0, 99999), "05")
+ cls.ou_dn = ldb.Dn(cls.ldb, "ou=" + cls.OU_NAME + "," + str(cls.base_dn))
- samba.tests.delete_force(self.ldb, self.ou_dn,
+ samba.tests.delete_force(cls.ldb, cls.ou_dn,
controls=['tree_delete:1'])
- self.ldb.add({
- "dn": self.ou_dn,
+ cls.ldb.add({
+ "dn": cls.ou_dn,
"objectclass": "organizationalUnit",
- "ou": self.OU_NAME})
+ "ou": cls.OU_NAME})
for x in range(200):
- user_name = self.USER_NAME + format(x, "03")
- self.ldb.add({
- "dn": "cn=" + user_name + "," + str(self.ou_dn),
+ user_name = cls.USER_NAME + format(x, "03")
+ cls.ldb.add({
+ "dn": "cn=" + user_name + "," + str(cls.ou_dn),
"objectclass": "user",
"sAMAccountName": user_name,
"jpegPhoto": b'a' * (2 * 1024 * 1024)})
- def tearDown(self):
+ @classmethod
+ def tearDownClass(cls):
# Remake the connection for tear-down (old Samba drops the socket)
- self.ldb = SamDB(url, credentials=creds, session_info=system_session(lp), lp=lp)
- samba.tests.delete_force(self.ldb, self.ou_dn,
+ cls.ldb = SamDB(url, credentials=creds, session_info=system_session(lp), lp=lp)
+ samba.tests.delete_force(cls.ldb, cls.ou_dn,
controls=['tree_delete:1'])
def test_unindexed_iterator_search(self):
diff --git a/source4/torture/drs/python/ridalloc_exop.py b/source4/torture/drs/python/ridalloc_exop.py
index 76b36854adf..d6d0082eccd 100644
--- a/source4/torture/drs/python/ridalloc_exop.py
+++ b/source4/torture/drs/python/ridalloc_exop.py
@@ -43,6 +43,7 @@ from samba.auth import system_session, admin_session
from samba.dbchecker import dbcheck
from samba.ndr import ndr_pack
from samba.dcerpc import security
+from samba import drs_utils, dsdb
class DrsReplicaSyncTestCase(drs_base.DrsBaseTestCase):
@@ -665,3 +666,137 @@ class DrsReplicaSyncTestCase(drs_base.DrsBaseTestCase):
finally:
self._test_force_demote(fsmo_owner['dns_name'], "RIDALLOCTEST7")
shutil.rmtree(targetdir, ignore_errors=True)
+
+ def test_replicate_against_deleted_objects_transaction(self):
+ """Not related to RID allocation, but uses the infrastructure here.
+ Do a join, create a link between two objects remotely, but
+ remove the target locally. Show that we need to set a magic
+ opaque if there is an outer transaction.
+
+ """
+ fsmo_dn = ldb.Dn(self.ldb_dc1, "CN=RID Manager$,CN=System," + self.ldb_dc1.domain_dn())
+ (fsmo_owner, fsmo_not_owner) = self._determine_fSMORoleOwner(fsmo_dn)
+
+ test_user4 = "ridalloctestuser4"
+ test_group = "ridalloctestgroup1"
+
+ self.ldb_dc1.newuser(test_user4, "P at ssword!")
+
+ self.addCleanup(self.ldb_dc1.deleteuser, test_user4)
+
+ self.ldb_dc1.newgroup(test_group)
+ self.addCleanup(self.ldb_dc1.deletegroup, test_group)
+
+ targetdir = self._test_join(self.dnsname_dc1, "RIDALLOCTEST8")
+ try:
+ # Connect to the database
+ ldb_url = "tdb://%s" % os.path.join(targetdir, "private/sam.ldb")
+ lp = self.get_loadparm()
+
+ new_ldb = SamDB(ldb_url,
+ session_info=system_session(lp), lp=lp)
+
+ destination_dsa_guid = misc.GUID(new_ldb.get_ntds_GUID())
+
+ repl = drs_utils.drs_Replicate(f'ncacn_ip_tcp:{self.dnsname_dc1}[seal]',
+ lp,
+ self.get_credentials(),
+ new_ldb,
+ destination_dsa_guid)
+
+ source_dsa_invocation_id = misc.GUID(self.ldb_dc1.invocation_id)
+
+ # Add the link on the remote DC
+ self.ldb_dc1.add_remove_group_members(test_group, [test_user4])
+
+ # Starting a transaction overrides, currently the logic
+ # inside repl.replicatate to retry with GET_TGT which in
+ # turn tells the repl_meta_data module that the most up to
+ # date info is already available
+ new_ldb.transaction_start()
+ repl.replicate(self.ldb_dc1.domain_dn(),
+ source_dsa_invocation_id,
+ destination_dsa_guid)
+
+ # Delete the user locally, before applying the links.
+ # This simulates getting the delete in the replciation
+ # stream.
+ new_ldb.deleteuser(test_user4)
+
+ # This fails as the user has been deleted locally but a remote link is sent
+ self.assertRaises(ldb.LdbError, new_ldb.transaction_commit)
+
+ new_ldb.transaction_start()
+ repl.replicate(self.ldb_dc1.domain_dn(),
+ source_dsa_invocation_id,
+ destination_dsa_guid)
+
+ # Delete the user locally (the previous transaction
+ # doesn't apply), before applying the links. This
+ # simulates getting the delete in the replciation stream.
+ new_ldb.deleteuser(test_user4)
+
+ new_ldb.set_opaque_integer(dsdb.DSDB_FULL_JOIN_REPLICATION_COMPLETED_OPAQUE_NAME,
+ 1)
+
+ # This should now work
+ try:
+ new_ldb.transaction_commit()
+ except ldb.LdbError as e:
+ self.fail(f"Failed to replicate despite setting opaque with {e.args[1]}")
+
+ finally:
+ self._test_force_demote(self.dnsname_dc1, "RIDALLOCTEST8")
+ shutil.rmtree(targetdir, ignore_errors=True)
+
+ def test_replicate_against_deleted_objects_normal(self):
+ """Not related to RID allocation, but uses the infrastructure here.
+ Do a join, create a link between two objects remotely, but
+ remove the target locally. .
+
+ """
+ fsmo_dn = ldb.Dn(self.ldb_dc1, "CN=RID Manager$,CN=System," + self.ldb_dc1.domain_dn())
+ (fsmo_owner, fsmo_not_owner) = self._determine_fSMORoleOwner(fsmo_dn)
+
+ test_user5 = "ridalloctestuser5"
+ test_group2 = "ridalloctestgroup2"
+
+ self.ldb_dc1.newuser(test_user5, "P at ssword!")
+ self.addCleanup(self.ldb_dc1.deleteuser, test_user5)
+
+ self.ldb_dc1.newgroup(test_group2)
+ self.addCleanup(self.ldb_dc1.deletegroup, test_group2)
+
+ targetdir = self._test_join(self.dnsname_dc1, "RIDALLOCTEST9")
+ try:
+ # Connect to the database
+ ldb_url = "tdb://%s" % os.path.join(targetdir, "private/sam.ldb")
--
Samba Shared Repository
More information about the samba-cvs
mailing list