summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
authorRalph Boehme <slow@samba.org>2018-01-25 14:48:55 +0100
committerKarolin Seeger <kseeger@samba.org>2018-02-09 09:30:22 +0100
commit367970e43e4c755f9122446b809cb7f0ec7b0541 (patch)
tree1b08c70bf861fc77128bba54e82c75a68bb0c299 /python
parent307ffdcb9c16c0cef166d4f2a86b3b97a6ca7480 (diff)
downloadsamba-367970e43e4c755f9122446b809cb7f0ec7b0541.tar.gz
dbcheck: add find_missing_forward_links_from_backlinks()
find_missing_forward_links_from_backlinks() finds and returns missing forward-links by searching all for all objects that link to the object in the backlink attribute. This will be used in the next commit to restore forward links in a corrupted forward link attribute by passing the missing backling objects to err_recover_forward_links(). BUG: https://bugzilla.samba.org/show_bug.cgi?id=13228 Pair-Programmed-With: Stefan Metzmacher <metze@samba.org> Signed-off-by: Ralph Boehme <slow@samba.org> Signed-off-by: Stefan Metzmacher <metze@samba.org> (cherry picked from commit d59f201388e8a16688adda145734dab8e27b785f)
Diffstat (limited to 'python')
-rw-r--r--python/samba/dbchecker.py96
1 files changed, 96 insertions, 0 deletions
diff --git a/python/samba/dbchecker.py b/python/samba/dbchecker.py
index 5b9c5515a06..8d8a193a7fa 100644
--- a/python/samba/dbchecker.py
+++ b/python/samba/dbchecker.py
@@ -987,6 +987,102 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base)))
return False
+ def find_missing_forward_links_from_backlinks(self, obj,
+ forward_attr,
+ forward_syntax,
+ backlink_attr,
+ forward_unique_dict):
+ '''Find all backlinks linking to obj_guid_str not already in forward_unique_dict'''
+ missing_forward_links = []
+ error_count = 0
+
+ if backlink_attr is None:
+ return (missing_forward_links, error_count)
+
+ if forward_syntax != ldb.SYNTAX_DN:
+ self.report("Not checking for missing forward links for syntax: %s",
+ forward_syntax)
+ return (missing_forward_links, error_count)
+
+ try:
+ obj_guid = obj['objectGUID'][0]
+ obj_guid_str = str(ndr_unpack(misc.GUID, obj_guid))
+ filter = "(%s=<GUID=%s>)" % (backlink_attr, obj_guid_str)
+
+ res = self.samdb.search(expression=filter,
+ scope=ldb.SCOPE_SUBTREE, attrs=["objectGUID"],
+ controls=["extended_dn:1:1",
+ "search_options:1:2",
+ "paged_results:1:1000"])
+ except ldb.LdbError, (enum, estr):
+ raise
+
+ for r in res:
+ target_dn = dsdb_Dn(self.samdb, r.dn.extended_str(), forward_syntax)
+
+ guid = target_dn.dn.get_extended_component("GUID")
+ guidstr = str(misc.GUID(guid))
+ if guidstr in forward_unique_dict:
+ continue
+
+ # A valid forward link looks like this:
+ #
+ # <GUID=9f92d30a-fc23-11e4-a5f6-30be15454808>;
+ # <RMD_ADDTIME=131607546230000000>;
+ # <RMD_CHANGETIME=131607546230000000>;
+ # <RMD_FLAGS=0>;
+ # <RMD_INVOCID=4e4496a3-7fb8-4f97-8a33-d238db8b5e2d>;
+ # <RMD_LOCAL_USN=3765>;
+ # <RMD_ORIGINATING_USN=3765>;
+ # <RMD_VERSION=1>;
+ # <SID=S-1-5-21-4177067393-1453636373-93818738-1124>;
+ # CN=unsorted-u8,CN=Users,DC=release-4-5-0-pre1,DC=samba,DC=corp
+ #
+ # Note that versions older than Samba 4.8 create
+ # links with RMD_VERSION=0.
+ #
+ # Try to get the local_usn and time from objectClass
+ # if possible and fallback to any other one.
+ repl = ndr_unpack(drsblobs.replPropertyMetaDataBlob,
+ obj['replPropertyMetadata'][0])
+ for o in repl.ctr.array:
+ local_usn = o.local_usn
+ t = o.originating_change_time
+ if o.attid == drsuapi.DRSUAPI_ATTID_objectClass:
+ break
+
+ # We use a magic invocationID for restoring missing
+ # forward links to recover from bug #13228.
+ # This should allow some more future magic to fix the
+ # problem.
+ #
+ # It also means it looses the conflict resolution
+ # against almost every real invocation, if the
+ # version is also 0.
+ originating_invocid = misc.GUID("ffffffff-4700-4700-4700-000000b13228")
+ originating_usn = 1
+
+ rmd_addtime = t
+ rmd_changetime = t
+ rmd_flags = 0
+ rmd_invocid = originating_invocid
+ rmd_originating_usn = originating_usn
+ rmd_local_usn = local_usn
+ rmd_version = 0
+
+ target_dn.dn.set_extended_component("RMD_ADDTIME", str(rmd_addtime))
+ target_dn.dn.set_extended_component("RMD_CHANGETIME", str(rmd_changetime))
+ target_dn.dn.set_extended_component("RMD_FLAGS", str(rmd_flags))
+ target_dn.dn.set_extended_component("RMD_INVOCID", ndr_pack(rmd_invocid))
+ target_dn.dn.set_extended_component("RMD_ORIGINATING_USN", str(rmd_originating_usn))
+ target_dn.dn.set_extended_component("RMD_LOCAL_USN", str(rmd_local_usn))
+ target_dn.dn.set_extended_component("RMD_VERSION", str(rmd_version))
+
+ error_count += 1
+ missing_forward_links.append(target_dn)
+
+ return (missing_forward_links, error_count)
+
def check_dn(self, obj, attrname, syntax_oid):
'''check a DN attribute for correctness'''
error_count = 0